├── .gitignore
├── README.md
├── assembler
├── README.md
├── asm
│ ├── add
│ │ └── Add.asm
│ ├── max
│ │ ├── Max.asm
│ │ └── MaxL.asm
│ ├── pong
│ │ ├── Pong.asm
│ │ └── PongL.asm
│ └── rect
│ │ ├── Rect.asm
│ │ └── RectL.asm
├── ast
│ ├── ast.go
│ └── ast_test.go
├── code
│ ├── code.go
│ └── code_test.go
├── go.mod
├── main.go
├── main_test.go
├── parser
│ ├── parser.go
│ └── parser_test.go
├── symboltable
│ ├── symboltable.go
│ └── symboltable_test.go
└── value
│ └── value.go
├── hardware
├── README.md
├── alu
│ ├── ALU-nostat.cmp
│ ├── ALU-nostat.tst
│ ├── ALU.cmp
│ ├── ALU.hdl
│ ├── ALU.out
│ ├── ALU.tst
│ ├── Add16.cmp
│ ├── Add16.hdl
│ ├── Add16.out
│ ├── Add16.tst
│ ├── FullAdder.cmp
│ ├── FullAdder.hdl
│ ├── FullAdder.out
│ ├── FullAdder.tst
│ ├── HalfAdder.cmp
│ ├── HalfAdder.hdl
│ ├── HalfAdder.out
│ ├── HalfAdder.tst
│ ├── Inc16.cmp
│ ├── Inc16.hdl
│ ├── Inc16.out
│ ├── Inc16.tst
│ ├── IsNegative16.hdl
│ └── Or16Way.hdl
├── bool_gate
│ ├── And.cmp
│ ├── And.hdl
│ ├── And.out
│ ├── And.tst
│ ├── And16.cmp
│ ├── And16.hdl
│ ├── And16.out
│ ├── And16.tst
│ ├── DMux.cmp
│ ├── DMux.hdl
│ ├── DMux.out
│ ├── DMux.tst
│ ├── DMux4Way.cmp
│ ├── DMux4Way.hdl
│ ├── DMux4Way.tst
│ ├── DMux8Way.cmp
│ ├── DMux8Way.hdl
│ ├── DMux8Way.tst
│ ├── Mux.cmp
│ ├── Mux.hdl
│ ├── Mux.out
│ ├── Mux.tst
│ ├── Mux16.cmp
│ ├── Mux16.hdl
│ ├── Mux16.out
│ ├── Mux16.tst
│ ├── Mux4Way16.cmp
│ ├── Mux4Way16.hdl
│ ├── Mux4Way16.out
│ ├── Mux4Way16.tst
│ ├── Mux8Way16.cmp
│ ├── Mux8Way16.hdl
│ ├── Mux8Way16.tst
│ ├── Not.cmp
│ ├── Not.hdl
│ ├── Not.tst
│ ├── Not16.cmp
│ ├── Not16.hdl
│ ├── Not16.out
│ ├── Not16.tst
│ ├── Or.cmp
│ ├── Or.hdl
│ ├── Or.out
│ ├── Or.tst
│ ├── Or16.cmp
│ ├── Or16.hdl
│ ├── Or16.out
│ ├── Or16.tst
│ ├── Or8Way.cmp
│ ├── Or8Way.hdl
│ ├── Or8Way.out
│ ├── Or8Way.tst
│ ├── Xor.cmp
│ ├── Xor.hdl
│ ├── Xor.out
│ └── Xor.tst
├── computer
│ ├── AReg.hdl
│ ├── Add.hack
│ ├── CPU-external.cmp
│ ├── CPU-external.tst
│ ├── CPU.cmp
│ ├── CPU.hdl
│ ├── CPU.out
│ ├── CPU.tst
│ ├── Computer.hdl
│ ├── ComputerAdd-external.cmp
│ ├── ComputerAdd-external.tst
│ ├── ComputerAdd.cmp
│ ├── ComputerAdd.out
│ ├── ComputerAdd.tst
│ ├── ComputerMax-external.cmp
│ ├── ComputerMax-external.tst
│ ├── ComputerMax.cmp
│ ├── ComputerMax.tst
│ ├── ComputerRect-external.cmp
│ ├── ComputerRect-external.tst
│ ├── ComputerRect.cmp
│ ├── ComputerRect.tst
│ ├── Max.hack
│ ├── Memory.cmp
│ ├── Memory.hdl
│ ├── Memory.out
│ ├── Memory.tst
│ └── Rect.hack
└── sequential_circuit
│ ├── Bit.cmp
│ ├── Bit.hdl
│ ├── Bit.out
│ ├── Bit.tst
│ ├── DFF16.hdl
│ ├── PC.cmp
│ ├── PC.hdl
│ ├── PC.out
│ ├── PC.tst
│ ├── RAM16K.cmp
│ ├── RAM16K.hdl
│ ├── RAM16K.out
│ ├── RAM16K.tst
│ ├── RAM4K.cmp
│ ├── RAM4K.hdl
│ ├── RAM4K.out
│ ├── RAM4K.tst
│ ├── RAM512.cmp
│ ├── RAM512.hdl
│ ├── RAM512.out
│ ├── RAM512.tst
│ ├── RAM64.cmp
│ ├── RAM64.hdl
│ ├── RAM64.out
│ ├── RAM64.tst
│ ├── RAM8.cmp
│ ├── RAM8.hdl
│ ├── RAM8.out
│ ├── RAM8.tst
│ ├── Register.cmp
│ ├── Register.hdl
│ ├── Register.out
│ └── Register.tst
├── jackcompiler
├── README.md
├── ast
│ └── ast.go
├── compilationengine
│ ├── compilationengine.go
│ └── compilationengine_test.go
├── go.mod
├── jack
│ ├── Add
│ │ └── Main.jack
│ ├── Average
│ │ └── Main.jack
│ ├── ComplexArrays
│ │ └── Main.jack
│ ├── ConsumptionTaxCalculator
│ │ ├── ConsumptionTaxCalculator.jack
│ │ ├── ConsumptionTaxTwo.jack
│ │ └── Main.jack
│ ├── ConvertToBin
│ │ └── Main.jack
│ ├── HelloWorld
│ │ └── Main.jack
│ ├── Pong
│ │ ├── Ball.jack
│ │ ├── Bat.jack
│ │ ├── Main.jack
│ │ └── PongGame.jack
│ ├── Seven
│ │ └── Main.jack
│ ├── SimpleArray
│ │ └── Main.jack
│ ├── SimpleIf
│ │ └── Main.jack
│ ├── SimpleWhile
│ │ └── Main.jack
│ ├── Square
│ │ ├── Main.jack
│ │ ├── Square.jack
│ │ └── SquareGame.jack
│ └── StaticTest
│ │ ├── Main.jack
│ │ └── StaticTest.jack
├── main.go
├── parser
│ ├── parser.go
│ └── parser_test.go
├── symboltable
│ ├── symboltable.go
│ └── symboltable_test.go
├── token
│ └── token.go
├── tokenizer
│ ├── tokenizer.go
│ └── tokenizer_test.go
├── value
│ └── value.go
├── vm
│ ├── Array.vm
│ ├── Keyboard.vm
│ ├── Math.vm
│ ├── Memory.vm
│ ├── Output.vm
│ ├── Screen.vm
│ ├── String.vm
│ ├── Sys.vm
│ └── program
│ │ ├── Main.vm
│ │ ├── Square.vm
│ │ └── SquareGame.vm
└── vmwriter
│ ├── vmwriter.go
│ └── vmwriter_test.go
└── vmtranslator
├── README.md
├── ast
├── ast.go
└── ast_test.go
├── codewriter
├── codewriter.go
└── codewriter_test.go
├── go.mod
├── main.go
├── main_test.go
├── parser
├── parser.go
└── parser_test.go
├── value
└── value.go
└── vm
├── BasicLoop
├── BasicLoop.cmp
├── BasicLoop.out
├── BasicLoop.tst
├── BasicLoop.vm
└── BasicLoopVME.tst
├── FibonacciElement
├── FibonacciElement.cmp
├── FibonacciElement.out
├── FibonacciElement.tst
├── FibonacciElementVME.tst
├── Main.vm
└── Sys.vm
├── FibonacciSeries
├── FibonacciSeries.cmp
├── FibonacciSeries.out
├── FibonacciSeries.tst
├── FibonacciSeries.vm
└── FibonacciSeriesVME.tst
├── NestedCall
├── NestedCall.cmp
├── NestedCall.html
├── NestedCall.out
├── NestedCall.tst
├── NestedCallStack.html
├── NestedCallVME.tst
└── Sys.vm
├── SimpleFunction
├── SimpleFunction.cmp
├── SimpleFunction.out
├── SimpleFunction.tst
├── SimpleFunction.vm
└── SimpleFunctionVME.tst
└── StaticsTest
├── Class1.vm
├── Class2.vm
├── StaticsTest.cmp
├── StaticsTest.out
├── StaticsTest.tst
├── StaticsTestVME.tst
└── Sys.vm
/.gitignore:
--------------------------------------------------------------------------------
1 | tools
2 | .DS_Store
3 | start-kit.sh
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
)
4 |
5 |
6 | # Nand2Tetris :smiley_cat:
7 |
8 | Implmentation of Nand2Tetris :smiley_cat:
9 |
10 | ## What is Nand2tetris?
11 |
12 | - Implement a computer and programming language that allows Tetris to operate from the smallest element, the Nand gate.
13 |
14 | - Through their implementation, we will understand the mechanisms and theories that support modern computers, such as hardware, compilers, and assembly.
15 |
16 | ## Directories
17 |
18 | - **hardware/** ... Hardware (chapter 1 ~ 5)
19 | - **assembler/** ... Assembler which translate assembly to machine language by Golang ʕ◔ϖ◔ʔ(chapter 6)
20 | - **vmtranslator/** ... VMtranslator which translate intermediate code to assembly by Golang ʕ◔ϖ◔ʔ(chapter 7/8)
21 | - **jackcompiler/** ... Jack Compiler which compiles **Jack(Object oriented language like Java,C#)** to intermediate language code by Golang ʕ◔ϖ◔ʔ(chapter 10/11)
22 |
23 |
24 | ## Reference
25 |
26 | - [「Nand2Tetris Official Site」](https://www.nand2tetris.org/)
27 |
28 | - [「コンピュータシステムの理論と実装」](https://www.amazon.co.jp/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E2%80%95%E3%83%A2%E3%83%80%E3%83%B3%E3%81%AA%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-Noam-Nisan/dp/4873117127)
29 |
30 | - [「The Elements of Computing Systems: Building a Modern Computer from First Principles」](https://www.amazon.co.jp/Elements-Computing-Systems-Building-Principles/dp/0262640686)
31 |
32 | - [「Go 言語でつくるインタプリタ」](https://www.amazon.co.jp/Go%E8%A8%80%E8%AA%9E%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%97%E3%83%AA%E3%82%BF-Thorsten-Ball/dp/4873118220)
33 |
34 | - [「Writing An Interpreter In Go 」](https://www.amazon.co.jp/Writing-Interpreter-Go-Thorsten-Ball/dp/3982016118/ref=pd_bxgy_img_1/358-0651022-5160614?pd_rd_w=NJ0lb&pf_rd_p=d8f6e0ab-48ef-4eca-99d5-60d97e927468&pf_rd_r=H5DDRH744DZQWEC8887N&pd_rd_r=92fb3969-78f9-42fe-9c0b-f605fd3b7bc8&pd_rd_wg=B98nq&pd_rd_i=3982016118&psc=1)
35 |
--------------------------------------------------------------------------------
/assembler/README.md:
--------------------------------------------------------------------------------
1 | # Nand2tetris Assembler by Golang 😺
2 |
3 | ## Overview
4 |
5 | - Assembler implementation by Golang ʕ◔ϖ◔ʔ.
6 | - Assembler translates assembly to machine language.
7 | - This package corresponds to chapter 6 of 「Building a Modern Computer from First Principles」
8 |
9 | ## Requirements
10 |
11 | - Go==1.16
12 |
13 | ## Assembly and Machine Language.
14 |
15 | ### Assembly
16 |
17 | Assembly is a format in which machine language are represented by symbols for easy human understanding. There is one machine language instruction corresponding to one assembly command.
18 |
19 | Code below is assembly program [Add.asm](https://github.com/YadaYuki/nand2tetris/blob/main/assembler/asm/add/Add.asm) which stores the result of 2 + 3 to 0th register(R0)
20 |
21 | ```
22 | @2
23 | D=A
24 | @3
25 | D=D+A
26 | @0
27 | M=D
28 | ```
29 |
30 | ### Machine Language
31 |
32 | Machine language is a format of instructions that can be directly understood by the CPU.
33 |
34 | Code below is machine language program which translate [Add.asm](https://github.com/YadaYuki/nand2tetris/blob/main/assembler/asm/add/Add.asm) to machine language .
35 |
36 | ```
37 | 0000000000000010
38 | 1110110000010000
39 | 0000000000000011
40 | 1110000010010000
41 | 0000000000000000
42 | 1110001100001000
43 | ```
44 |
45 | ## How to work
46 |
47 | ### Generate machine language from assembly
48 |
49 | You can generate machine language from assembly by running:
50 |
51 | ```
52 | $ go run main.go {path to asm file}
53 | ```
54 |
55 | Executing this command, machine language program (.hack) will be generated in same dir as assembly file(.asm)
56 |
57 | For example, to translate `asm/add/Add.asm` program which stores the result of 2 + 3 to 0th register(R0) to machine language, execute below:
58 |
59 | ```
60 | $ go run main.go asm/add/Add.asm
61 | ```
62 |
63 | Executing this command, you can confirm that machine language program file(`Add.hack`) is generated in same dir of `Add.asm`(`asm/add/`)
64 |
65 | ### Run machine language program on CPU Emulator
66 |
67 | You can emulate machine language program by CPU Emulator provided by [nand2tetris official site](https://www.nand2tetris.org/software)
68 |
69 | The gif animation below is pong/Pong.asm converted to machine language by this assembler and executed by CPU Emulator.
70 |
71 | 
72 |
73 |
74 | ## Reference
75 |
76 | - [「Nand2Tetris Official Site」](https://www.nand2tetris.org/)
77 |
78 | - [「コンピュータシステムの理論と実装」](https://www.amazon.co.jp/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E2%80%95%E3%83%A2%E3%83%80%E3%83%B3%E3%81%AA%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-Noam-Nisan/dp/4873117127)
79 |
80 | - [「The Elements of Computing Systems: Building a Modern Computer from First Principles」](https://www.amazon.co.jp/Elements-Computing-Systems-Building-Principles/dp/0262640686)
81 |
82 | - [「Go 言語でつくるインタプリタ」](https://www.amazon.co.jp/Go%E8%A8%80%E8%AA%9E%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%97%E3%83%AA%E3%82%BF-Thorsten-Ball/dp/4873118220)
83 |
84 | - [「Writing An Interpreter In Go 」](https://www.amazon.co.jp/Writing-Interpreter-Go-Thorsten-Ball/dp/3982016118/ref=pd_bxgy_img_1/358-0651022-5160614?pd_rd_w=NJ0lb&pf_rd_p=d8f6e0ab-48ef-4eca-99d5-60d97e927468&pf_rd_r=H5DDRH744DZQWEC8887N&pd_rd_r=92fb3969-78f9-42fe-9c0b-f605fd3b7bc8&pd_rd_wg=B98nq&pd_rd_i=3982016118&psc=1)
85 |
--------------------------------------------------------------------------------
/assembler/asm/add/Add.asm:
--------------------------------------------------------------------------------
1 | @2
2 | D=A
3 | @3
4 | D=D+A
5 | @0
6 | M=D
--------------------------------------------------------------------------------
/assembler/asm/max/Max.asm:
--------------------------------------------------------------------------------
1 | @R0
2 | D=M // D = first number
3 | @R1
4 | D=D-M // D = first number - second number
5 | @OUTPUT_FIRST
6 | D;JGT // if D>0 (first is greater) goto output_first
7 | @R1
8 | D=M // D = second number
9 | @OUTPUT_D
10 | 0;JMP // goto output_d
11 | (OUTPUT_FIRST)
12 | @R0
13 | D=M // D = first number
14 | (OUTPUT_D)
15 | @R2
16 | M=D // M[2] = D (greatest number)
17 | (INFINITE_LOOP)
18 | @INFINITE_LOOP
19 | 0;JMP // infinite loop
--------------------------------------------------------------------------------
/assembler/asm/max/MaxL.asm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/06/max/MaxL.asm
5 |
6 | // Symbol-less version of the Max.asm program.
7 |
8 | @0
9 | D=M
10 | @1
11 | D=D-M
12 | @10
13 | D;JGT
14 | @1
15 | D=M
16 | @12
17 | 0;JMP
18 | @0
19 | D=M
20 | @2
21 | M=D
22 | @14
23 | 0;JMP
24 |
--------------------------------------------------------------------------------
/assembler/asm/rect/Rect.asm:
--------------------------------------------------------------------------------
1 | @0
2 | D=M
3 | @INFINITE_LOOP
4 | D;JLE
5 | @counter
6 | M=D
7 | @SCREEN
8 | D=A
9 | @address
10 | M=D
11 | (LOOP)
12 | @address
13 | A=M
14 | M=-1
15 | @address
16 | D=M
17 | @32
18 | D=D+A
19 | @address
20 | M=D
21 | @counter
22 | MD=M-1
23 | @LOOP
24 | D;JGT
25 | (INFINITE_LOOP)
26 | @INFINITE_LOOP
27 | 0;JMP
28 |
--------------------------------------------------------------------------------
/assembler/asm/rect/RectL.asm:
--------------------------------------------------------------------------------
1 | @0
2 | D=M
3 | @23
4 | D;JLE
5 | @16
6 | M=D
7 | @16384
8 | D=A
9 | @17
10 | M=D
11 | @17
12 | A=M
13 | M=-1
14 | @17
15 | D=M
16 | @32
17 | D=D+A
18 | @17
19 | M=D
20 | @16
21 | MD=M-1
22 | @10
23 | D;JGT
24 | @23
25 | 0;JMP
--------------------------------------------------------------------------------
/assembler/ast/ast.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import (
4 | "assembler/value"
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | type CommandType string
10 |
11 | const (
12 | A_COMMAND CommandType = "A_COMMAND"
13 | C_COMMAND CommandType = "C_COMMAND"
14 | L_COMMAND CommandType = "L_COMMAND"
15 | )
16 |
17 | type Command interface {
18 | String() string
19 | }
20 |
21 | type ACommand struct {
22 | Value int
23 | ValueStr string
24 | }
25 |
26 | func (aCommand *ACommand) String() string {
27 | return fmt.Sprintf("@%s", aCommand.ValueStr) + value.NEW_LINE
28 | }
29 |
30 | type CCommand struct {
31 | Comp string
32 | Dest string
33 | Jump string
34 | }
35 |
36 | func (cCommand *CCommand) String() string {
37 | commandStr := fmt.Sprintf("%s=%s;%s", cCommand.Dest, cCommand.Comp, cCommand.Jump) + value.NEW_LINE
38 | if cCommand.Jump == "" {
39 | commandStr = strings.Replace(commandStr, ";", "", 1)
40 | } else if cCommand.Dest == "" {
41 | commandStr = strings.Replace(commandStr, "=", "", 1)
42 | }
43 | return commandStr
44 | }
45 |
46 | type LCommand struct {
47 | Symbol string
48 | }
49 |
50 | func (lCommand *LCommand) String() string {
51 | return fmt.Sprintf("(%s)", lCommand.Symbol)
52 | }
53 |
--------------------------------------------------------------------------------
/assembler/ast/ast_test.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import (
4 | "assembler/value"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | func TestACommand(t *testing.T) {
10 | val := 10000
11 | aCommand := ACommand{Value: val, ValueStr: fmt.Sprintf("%d", val)}
12 | if aCommand.String() != "@10000"+value.NEW_LINE {
13 | t.Fatalf("aCommand.String() should be %s, got %s ", "@10000"+value.NEW_LINE, aCommand.String())
14 | }
15 | }
16 |
17 | func TestCCommand(t *testing.T) {
18 | testCases := []struct {
19 | command CCommand
20 | commandStr string
21 | }{
22 | {CCommand{Comp: "-1", Dest: "M"}, "M=-1" + value.NEW_LINE},
23 | {CCommand{Comp: "D", Jump: "JMP"}, "D;JMP" + value.NEW_LINE},
24 | {CCommand{Comp: "D|A", Dest: "AM", Jump: "JMP"}, "AM=D|A;JMP" + value.NEW_LINE},
25 | }
26 | for _, tt := range testCases {
27 | if tt.commandStr != tt.command.String() {
28 | t.Fatalf("cCommand.String() should be %s, got %s ", tt.commandStr, tt.command.String())
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/assembler/code/code.go:
--------------------------------------------------------------------------------
1 | package code
2 |
3 | import (
4 | "assembler/ast"
5 | "fmt"
6 | )
7 |
8 | func Binary(command ast.Command) string {
9 | switch c := command.(type) {
10 | case *ast.ACommand:
11 | return fmt.Sprintf("%016b", c.Value)
12 | case *ast.CCommand:
13 | cCommandBinaryPrefix := "111"
14 | return cCommandBinaryPrefix + Comp(c.Comp) + Dest(c.Dest) + Jump(c.Jump)
15 | }
16 | return ""
17 | }
18 |
19 | // GetDestBinary return Binary Code Correspond to dest label
20 | func Dest(dest string) string {
21 | if dest == "" {
22 | return "000"
23 | }
24 | destBinaryMap := map[string]string{"M": "001", "D": "010", "MD": "011", "A": "100", "AM": "101", "AD": "110", "AMD": "111"}
25 | destBinary := destBinaryMap[dest]
26 | return destBinary
27 | }
28 |
29 | // GetJumpBinary return Binary Code Correspond to dest label
30 | func Jump(jump string) string {
31 | if jump == "" {
32 | return "000"
33 | }
34 | jumpBinaryMap := map[string]string{"JGT": "001", "JEQ": "010", "JGE": "011", "JLT": "100", "JNE": "101", "JLE": "110", "JMP": "111"}
35 | jumpBinary := jumpBinaryMap[jump]
36 | return jumpBinary
37 | }
38 |
39 | func Comp(comp string) string {
40 | compBinaryMap := map[string]string{
41 | // a = 0
42 | "0": "0101010",
43 | "1": "0111111",
44 | "-1": "0111010",
45 | "D": "0001100",
46 | "A": "0110000",
47 | "!D": "0001101",
48 | "!A": "0110001",
49 | "-D": "0001111",
50 | "-A": "0110011",
51 | "D+1": "0011111",
52 | "A+1": "0110111",
53 | "D-1": "0001110",
54 | "A-1": "0110010",
55 | "D+A": "0000010",
56 | "D-A": "0010011",
57 | "A-D": "0000111",
58 | "D&A": "0000000",
59 | "D|A": "0010101",
60 | // a = 1
61 | "M": "1110000",
62 | "!M": "1110001",
63 | "-M": "1110011",
64 | "M+1": "1110111",
65 | "M-1": "1110010",
66 | "D+M": "1000010",
67 | "D-M": "1010011",
68 | "M-D": "1000111",
69 | "D&M": "1000000",
70 | "D|M": "1010101",
71 | }
72 | return compBinaryMap[comp]
73 | }
74 |
--------------------------------------------------------------------------------
/assembler/code/code_test.go:
--------------------------------------------------------------------------------
1 | package code
2 |
3 | import (
4 | "assembler/ast"
5 | // "assembler/value"
6 | "testing"
7 | )
8 |
9 | func TestBinary(t *testing.T) {
10 | testCases := []struct {
11 | command ast.Command
12 | binaryStr string
13 | }{
14 | {&ast.ACommand{Value: 100}, "0000000001100100"},
15 | {&ast.CCommand{Comp: "A", Dest: "D"}, "1110110000010000"},
16 | {&ast.CCommand{Comp: "M", Dest: "D"}, "1110001100001000"},
17 | {&ast.CCommand{Comp: "D|A", Dest: "AM", Jump: "JMP"}, "1110010101101111"},
18 | }
19 | for _, tt := range testCases {
20 | binaryStr := Binary(tt.command)
21 | if tt.binaryStr != binaryStr {
22 | t.Fatalf("binaryStr should be %s, got %s ", tt.binaryStr, binaryStr)
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/assembler/go.mod:
--------------------------------------------------------------------------------
1 | module assembler
2 |
3 | go 1.16
4 |
--------------------------------------------------------------------------------
/assembler/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "assembler/ast"
5 | "assembler/code"
6 | "assembler/parser"
7 | "assembler/symboltable"
8 | "assembler/value"
9 | "flag"
10 | "fmt"
11 | "io/ioutil"
12 | "os"
13 | "path"
14 | "path/filepath"
15 | "strconv"
16 | "strings"
17 | )
18 |
19 | func Assemble(input string) (binaryArr []string, err error) {
20 | st := symboltable.New()
21 | p := parser.New(input, st)
22 | // first path
23 | currentBinaryCount := 0
24 | for p.HasMoreCommand() {
25 | switch p.CommandType() {
26 | case ast.A_COMMAND, ast.C_COMMAND:
27 | currentBinaryCount++
28 | case ast.L_COMMAND:
29 | symbol, _ := p.Symbol()
30 | p.AddEntry(symbol, currentBinaryCount)
31 | }
32 | p.Advance()
33 | }
34 | p.ResetParseIdx()
35 |
36 | customVariableCount := 0
37 | INTIAL_VARIABLE_COUNT := 16
38 | for p.HasMoreCommand() {
39 | if p.CommandType() == ast.A_COMMAND {
40 | symbol, _ := p.Symbol()
41 | _, err := strconv.Atoi(symbol)
42 | if !p.Contains(symbol) && err != nil {
43 | p.AddEntry(symbol, INTIAL_VARIABLE_COUNT+customVariableCount)
44 | customVariableCount++
45 | }
46 | }
47 | p.Advance()
48 | }
49 | p.ResetParseIdx()
50 | // second path
51 | for p.HasMoreCommand() {
52 | command, _ := p.ParseCommand()
53 | if p.CommandType() == ast.A_COMMAND || p.CommandType() == ast.C_COMMAND {
54 | binaryArr = append(binaryArr, code.Binary(command))
55 | }
56 | p.Advance()
57 | }
58 | return binaryArr, nil
59 | }
60 |
61 | func AssembleAsmFile(asmFilename string, hackFilename string) error {
62 | asm, _ := ioutil.ReadFile(asmFilename)
63 | input := string(asm)
64 | binaryArr, _ := Assemble(input)
65 | ioutil.WriteFile(hackFilename, []byte(strings.Join(binaryArr, value.NEW_LINE)), os.ModePerm)
66 | return nil
67 | }
68 |
69 | func removeExt(filename string) string {
70 | return strings.Trim(filename, filepath.Ext(filename))
71 | }
72 |
73 | func main() {
74 | flag.Parse()
75 | pathToAsm := flag.Args()[0]
76 | asmDirName, asmFilename := path.Dir(pathToAsm), path.Base(pathToAsm)
77 | hackFilename := fmt.Sprintf("%s.hack", removeExt(asmFilename))
78 | pathToHack := path.Join(asmDirName, hackFilename)
79 | AssembleAsmFile(pathToAsm, pathToHack)
80 | }
81 |
--------------------------------------------------------------------------------
/assembler/main_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "assembler/value"
5 | "io/ioutil"
6 | "strings"
7 | "testing"
8 | )
9 |
10 | func TestAssemble(t *testing.T) {
11 | testCases := []struct {
12 | asmFilename string
13 | hackFilename string
14 | }{
15 | {"add/Add.asm", "add/Add.hack"},
16 | {"rect/Rect.asm", "rect/Rect.hack"},
17 | {"max/Max.asm", "max/Max.hack"},
18 | {"pong/Pong.asm", "pong/Pong.hack"},
19 | }
20 | for _, tt := range testCases {
21 | asm, _ := ioutil.ReadFile(tt.asmFilename)
22 | input := string(asm)
23 | hack, _ := ioutil.ReadFile(tt.hackFilename)
24 | binaryArrInFile := strings.Split(string(hack), value.LF)
25 | binaryArr, _ := Assemble(input)
26 | for i := range binaryArr {
27 | if binaryArrInFile[i] != binaryArr[i] {
28 | t.Logf("binary should be %s got,%s", binaryArrInFile[i], binaryArr[i])
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/assembler/symboltable/symboltable.go:
--------------------------------------------------------------------------------
1 | package symboltable
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type SymbolTable struct {
8 | SymbolTableDict map[string]int
9 | }
10 |
11 | func getInitialSymbolTable() map[string]int {
12 | initialSymbolTable := map[string]int{"SP": 0, "LCL": 1, "ARG": 2, "THIS": 3, "THAT": 4, "SCREEN": 16384, "KBD": 24576}
13 | // initialize Register Address
14 | for i := 0; i < 16; i++ {
15 | initialSymbolTable[fmt.Sprintf("R%d", i)] = i
16 | }
17 | return initialSymbolTable
18 | }
19 |
20 | func New() *SymbolTable {
21 | initialSymbolTable := getInitialSymbolTable()
22 | return &SymbolTable{SymbolTableDict: initialSymbolTable}
23 | }
24 |
25 | func (st *SymbolTable) Contains(symbol string) bool {
26 | _, ok := st.SymbolTableDict[symbol]
27 | return ok
28 | }
29 |
30 | func (st *SymbolTable) GetAddress(symbol string) (int, error) {
31 | contains := st.Contains(symbol)
32 | if !contains {
33 | return -1, fmt.Errorf("%s is not Contained in symbolTable", symbol)
34 | }
35 | return st.SymbolTableDict[symbol], nil
36 | }
37 |
38 | func (st *SymbolTable) AddEntry(symbol string, address int) error {
39 | st.SymbolTableDict[symbol] = address
40 | return nil
41 | }
42 |
--------------------------------------------------------------------------------
/assembler/symboltable/symboltable_test.go:
--------------------------------------------------------------------------------
1 | package symboltable
2 |
3 | import "testing"
4 |
5 | func TestContains(t *testing.T) {
6 | symbolTable := New()
7 | testCases := []struct {
8 | symbol string
9 | contains bool
10 | }{
11 | {"R1", true}, {"SP", true}, {"HOGE", false},
12 | }
13 | for _, tt := range testCases {
14 | contains := symbolTable.Contains(tt.symbol)
15 | if contains != tt.contains {
16 | t.Fatalf("Contains(%s) should return %t ,got %t", tt.symbol, tt.contains, contains)
17 | }
18 | }
19 | }
20 |
21 | func TestGetAddress(t *testing.T) {
22 | symbolTable := New()
23 | testCases := []struct {
24 | symbol string
25 | address int
26 | }{
27 | {"R1", 1}, {"SP", 0}, {"HOGE", -1},
28 | }
29 | for _, tt := range testCases {
30 | address, _ := symbolTable.GetAddress(tt.symbol)
31 | if address != tt.address {
32 | t.Fatalf("%s's address should be %d, got %d", tt.symbol, tt.address, address)
33 | }
34 | }
35 | }
36 | func TestAddEntry(t *testing.T) {
37 | symbolTable := New()
38 | testCases := []struct {
39 | symbol string
40 | address int
41 | }{
42 | {"SMAP", 16}, {"KINGNOO", 17}, {"ARASHI", 18},
43 | }
44 | for _, tt := range testCases {
45 | symbolTable.AddEntry(tt.symbol, tt.address)
46 | address, _ := symbolTable.GetAddress(tt.symbol)
47 | if address != tt.address {
48 | t.Fatalf("%s's address should be %d, got %d", tt.symbol, tt.address, address)
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/assembler/value/value.go:
--------------------------------------------------------------------------------
1 | package value
2 |
3 | var LF = "\n"
4 | var CR = "\r"
5 | var NEW_LINE = CR + LF
6 | var SPACE = byte(' ')
7 |
8 | var TAB = byte('\t')
9 |
10 | // var
11 |
--------------------------------------------------------------------------------
/hardware/README.md:
--------------------------------------------------------------------------------
1 | # Nand2tetris Hardware 😺
2 |
3 | ## Overview
4 |
5 | - Hardware implementation (CPU,ALU,Memory...etc)
6 | - This package corresponds to chapter 1 ~ 5 of 「Building a Modern Computer from First Principles」
7 |
8 | ## Directories
9 |
10 | What is implemented in each directory is as follows:
11 |
12 | - **bool_gate/** ... Implementation of several bool gates (Or-gate,And-gate,Not-gate,Multiplexer ...etc) from Nand Gate. (chapter 1)
13 |
14 | - **alu/** ... Implementation of ALU and the circuits that make it up (chapter 2)
15 |
16 | - **sequential_circuit/** ... Implementation of several sequantial circuits (Register, Program Counter ...etc) from D Flip-Flop. (chapter 3)
17 |
18 | - **computer/** ... Implementation of computer and the circuits(CPU,Memory ...etc) that make it up (chapter 5)
19 |
20 | ## How to work
21 |
22 | ### Emulate hardware on Hardware simulator
23 |
24 | You can emulate these hardware by Hardware simulator provided by [nand2tetris official site](https://www.nand2tetris.org/software)
25 |
26 | The gif animation below shows the execution of computer/ComputerRect-external.tst on the Hardware Simulator.
27 |
28 | 
29 |
30 |
31 |
32 | ## Reference
33 |
34 | - [「Nand2Tetris Official Site」](https://www.nand2tetris.org/)
35 |
36 | - [「コンピュータシステムの理論と実装」](https://www.amazon.co.jp/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E2%80%95%E3%83%A2%E3%83%80%E3%83%B3%E3%81%AA%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-Noam-Nisan/dp/4873117127)
37 |
38 |
39 |
--------------------------------------------------------------------------------
/hardware/alu/ALU-nostat.cmp:
--------------------------------------------------------------------------------
1 | | x | y |zx |nx |zy |ny | f |no | out |
2 | | 0000000000000000 | 1111111111111111 | 1 | 0 | 1 | 0 | 1 | 0 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 |
4 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 1 | 0 | 1 | 0 | 1111111111111111 |
5 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 0 | 0 | 0000000000000000 |
6 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 0 | 0 | 1111111111111111 |
7 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 0 | 1 | 1111111111111111 |
8 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 0 | 1 | 0000000000000000 |
9 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 1 | 1 | 0000000000000000 |
10 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 1 | 1 | 0000000000000001 |
11 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 |
12 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 1 | 1 | 1 | 0000000000000000 |
13 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 1 | 0 | 1111111111111111 |
14 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 1 | 0 | 1111111111111110 |
15 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 0 | 1 | 0 | 1111111111111111 |
16 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 0 | 0 | 1 | 1 | 0000000000000001 |
17 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 1 | 1 | 1 | 1111111111111111 |
18 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 0 | 0 | 0 | 0000000000000000 |
19 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 0 | 1 | 0 | 1 | 1111111111111111 |
20 | | 0101101110100000 | 0001111011010010 | 1 | 0 | 1 | 0 | 1 | 0 | 0000000000000000 |
21 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 |
22 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 1 | 0 | 1 | 0 | 1111111111111111 |
23 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 1 | 1 | 0 | 0 | 0101101110100000 |
24 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 0 | 0 | 0 | 0 | 0001111011010010 |
25 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 1 | 1 | 0 | 1 | 1010010001011111 |
26 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 0 | 0 | 0 | 1 | 1110000100101101 |
27 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 1 | 1 | 1 | 1 | 1010010001100000 |
28 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 0 | 0 | 1 | 1 | 1110000100101110 |
29 | | 0101101110100000 | 0001111011010010 | 0 | 1 | 1 | 1 | 1 | 1 | 0101101110100001 |
30 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 0 | 1 | 1 | 1 | 0001111011010011 |
31 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 1 | 1 | 1 | 0 | 0101101110011111 |
32 | | 0101101110100000 | 0001111011010010 | 1 | 1 | 0 | 0 | 1 | 0 | 0001111011010001 |
33 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 0 | 0 | 1 | 0 | 0111101001110010 |
34 | | 0101101110100000 | 0001111011010010 | 0 | 1 | 0 | 0 | 1 | 1 | 0011110011001110 |
35 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 0 | 1 | 1 | 1 | 1100001100110010 |
36 | | 0101101110100000 | 0001111011010010 | 0 | 0 | 0 | 0 | 0 | 0 | 0001101010000000 |
37 | | 0101101110100000 | 0001111011010010 | 0 | 1 | 0 | 1 | 0 | 1 | 0101111111110010 |
38 |
--------------------------------------------------------------------------------
/hardware/alu/ALU.cmp:
--------------------------------------------------------------------------------
1 | | x | y |zx |nx |zy |ny | f |no | out |zr |ng |
2 | | 0000000000000000 | 1111111111111111 | 1 | 0 | 1 | 0 | 1 | 0 | 0000000000000000 | 1 | 0 |
3 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 | 0 | 0 |
4 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 1 | 0 | 1 | 0 | 1111111111111111 | 0 | 1 |
5 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 0 | 0 | 0000000000000000 | 1 | 0 |
6 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 0 | 0 | 1111111111111111 | 0 | 1 |
7 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 0 | 1 | 1111111111111111 | 0 | 1 |
8 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 0 | 1 | 0000000000000000 | 1 | 0 |
9 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 1 | 1 | 0000000000000000 | 1 | 0 |
10 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 1 | 1 | 0000000000000001 | 0 | 0 |
11 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 | 0 | 0 |
12 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 1 | 1 | 1 | 0000000000000000 | 1 | 0 |
13 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 1 | 0 | 1111111111111111 | 0 | 1 |
14 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 1 | 0 | 1111111111111110 | 0 | 1 |
15 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 0 | 1 | 0 | 1111111111111111 | 0 | 1 |
16 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 0 | 0 | 1 | 1 | 0000000000000001 | 0 | 0 |
17 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 1 | 1 | 1 | 1111111111111111 | 0 | 1 |
18 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 0 | 0 | 0 | 0000000000000000 | 1 | 0 |
19 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 0 | 1 | 0 | 1 | 1111111111111111 | 0 | 1 |
20 | | 0000000000010001 | 0000000000000011 | 1 | 0 | 1 | 0 | 1 | 0 | 0000000000000000 | 1 | 0 |
21 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 | 0 | 0 |
22 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 1 | 0 | 1 | 0 | 1111111111111111 | 0 | 1 |
23 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 0 | 0 | 0000000000010001 | 0 | 0 |
24 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 0 | 0 | 0000000000000011 | 0 | 0 |
25 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 0 | 1 | 1111111111101110 | 0 | 1 |
26 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 0 | 1 | 1111111111111100 | 0 | 1 |
27 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 1 | 1 | 1111111111101111 | 0 | 1 |
28 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 1 | 1 | 1111111111111101 | 0 | 1 |
29 | | 0000000000010001 | 0000000000000011 | 0 | 1 | 1 | 1 | 1 | 1 | 0000000000010010 | 0 | 0 |
30 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 1 | 1 | 1 | 0000000000000100 | 0 | 0 |
31 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 1 | 0 | 0000000000010000 | 0 | 0 |
32 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 1 | 0 | 0000000000000010 | 0 | 0 |
33 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 0 | 0 | 1 | 0 | 0000000000010100 | 0 | 0 |
34 | | 0000000000010001 | 0000000000000011 | 0 | 1 | 0 | 0 | 1 | 1 | 0000000000001110 | 0 | 0 |
35 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 0 | 1 | 1 | 1 | 1111111111110010 | 0 | 1 |
36 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 0 | 0 | 0 | 0 | 0000000000000001 | 0 | 0 |
37 | | 0000000000010001 | 0000000000000011 | 0 | 1 | 0 | 1 | 0 | 1 | 0000000000010011 | 0 | 0 |
38 |
--------------------------------------------------------------------------------
/hardware/alu/ALU.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/ALU.hdl
5 |
6 | /**
7 | * The ALU (Arithmetic Logic Unit).
8 | * Computes one of the following functions:
9 | * x+y, x-y, y-x, 0, 1, -1, x, y, -x, -y, !x, !y,
10 | * x+1, y+1, x-1, y-1, x&y, x|y on two 16-bit inputs,
11 | * according to 6 input bits denoted zx,nx,zy,ny,f,no.
12 | * In addition, the ALU computes two 1-bit outputs:
13 | * if the ALU output == 0, zr is set to 1; otherwise zr is set to 0;
14 | * if the ALU output < 0, ng is set to 1; otherwise ng is set to 0.
15 | */
16 |
17 | // Implementation: the ALU logic manipulates the x and y inputs
18 | // and operates on the resulting values, as follows:
19 | // if (zx == 1) set x = 0 // 16-bit constant
20 | // if (nx == 1) set x = !x // bitwise not
21 | // if (zy == 1) set y = 0 // 16-bit constant
22 | // if (ny == 1) set y = !y // bitwise not
23 | // if (f == 1) set out = x + y // integer 2's complement addition
24 | // if (f == 0) set out = x & y // bitwise and
25 | // if (no == 1) set out = !out // bitwise not
26 | // if (out == 0) set zr = 1
27 | // if (out < 0) set ng = 1
28 |
29 | CHIP ALU {
30 | IN
31 | x[16], y[16], // 16-bit inputs
32 | zx, // zero the x input?
33 | nx, // negate the x input?
34 | zy, // zero the y input?
35 | ny, // negate the y input?
36 | f, // compute out = x + y (if 1) or x & y (if 0)
37 | no; // negate the out output?
38 |
39 | OUT
40 | out[16], // 16-bit output
41 | zr, // 1 if (out == 0), 0 otherwise
42 | ng; // 1 if (out < 0), 0 otherwise
43 |
44 | PARTS:
45 |
46 | // out x
47 | Mux16(a=x,b=false,sel=zx,out=outzx);
48 | Not16(in=outzx,out=notoutzx);
49 | Mux16(a=outzx,b=notoutzx,sel=nx,out=outx);
50 | // out y
51 | Mux16(a=y,b=false,sel=zy,out=outzy);
52 | Not16(in=outzy,out=notoutzy);
53 | Mux16(a=outzy,b=notoutzy,sel=ny,out=outy);
54 |
55 | // out fx
56 | Add16(a=outx,b=outy,out=addoutxy);
57 | And16(a=outx,b=outy,out=andoutxy);
58 | Mux16(a=andoutxy,b=addoutxy,sel=f,out=outfx);
59 |
60 | // out no
61 | Not16(in=outfx,out=notoutfx);
62 | Mux16(a=outfx,b=notoutfx,sel=no,out=outval);
63 | And16(a=outval,b=true,out=out);
64 | // ng
65 | IsNegative16(in=outval,out=ng);
66 | // zr
67 | Or16Way(in=outval,out=notzr);
68 | Not(in=notzr,out=zr);
69 | }
--------------------------------------------------------------------------------
/hardware/alu/ALU.out:
--------------------------------------------------------------------------------
1 | | x | y |zx |nx |zy |ny | f |no | out |zr |ng |
2 | | 0000000000000000 | 1111111111111111 | 1 | 0 | 1 | 0 | 1 | 0 | 0000000000000000 | 1 | 0 |
3 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 | 0 | 0 |
4 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 1 | 0 | 1 | 0 | 1111111111111111 | 0 | 1 |
5 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 0 | 0 | 0000000000000000 | 1 | 0 |
6 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 0 | 0 | 1111111111111111 | 0 | 1 |
7 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 0 | 1 | 1111111111111111 | 0 | 1 |
8 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 0 | 1 | 0000000000000000 | 1 | 0 |
9 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 1 | 1 | 0000000000000000 | 1 | 0 |
10 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 1 | 1 | 0000000000000001 | 0 | 0 |
11 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 | 0 | 0 |
12 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 1 | 1 | 1 | 0000000000000000 | 1 | 0 |
13 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 1 | 1 | 1 | 0 | 1111111111111111 | 0 | 1 |
14 | | 0000000000000000 | 1111111111111111 | 1 | 1 | 0 | 0 | 1 | 0 | 1111111111111110 | 0 | 1 |
15 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 0 | 1 | 0 | 1111111111111111 | 0 | 1 |
16 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 0 | 0 | 1 | 1 | 0000000000000001 | 0 | 0 |
17 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 1 | 1 | 1 | 1111111111111111 | 0 | 1 |
18 | | 0000000000000000 | 1111111111111111 | 0 | 0 | 0 | 0 | 0 | 0 | 0000000000000000 | 1 | 0 |
19 | | 0000000000000000 | 1111111111111111 | 0 | 1 | 0 | 1 | 0 | 1 | 1111111111111111 | 0 | 1 |
20 | | 0000000000010001 | 0000000000000011 | 1 | 0 | 1 | 0 | 1 | 0 | 0000000000000000 | 1 | 0 |
21 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 1 | 1 | 1 | 1 | 0000000000000001 | 0 | 0 |
22 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 1 | 0 | 1 | 0 | 1111111111111111 | 0 | 1 |
23 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 0 | 0 | 0000000000010001 | 0 | 0 |
24 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 0 | 0 | 0000000000000011 | 0 | 0 |
25 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 0 | 1 | 1111111111101110 | 0 | 1 |
26 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 0 | 1 | 1111111111111100 | 0 | 1 |
27 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 1 | 1 | 1111111111101111 | 0 | 1 |
28 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 1 | 1 | 1111111111111101 | 0 | 1 |
29 | | 0000000000010001 | 0000000000000011 | 0 | 1 | 1 | 1 | 1 | 1 | 0000000000010010 | 0 | 0 |
30 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 1 | 1 | 1 | 0000000000000100 | 0 | 0 |
31 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 1 | 1 | 1 | 0 | 0000000000010000 | 0 | 0 |
32 | | 0000000000010001 | 0000000000000011 | 1 | 1 | 0 | 0 | 1 | 0 | 0000000000000010 | 0 | 0 |
33 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 0 | 0 | 1 | 0 | 0000000000010100 | 0 | 0 |
34 | | 0000000000010001 | 0000000000000011 | 0 | 1 | 0 | 0 | 1 | 1 | 0000000000001110 | 0 | 0 |
35 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 0 | 1 | 1 | 1 | 1111111111110010 | 0 | 1 |
36 | | 0000000000010001 | 0000000000000011 | 0 | 0 | 0 | 0 | 0 | 0 | 0000000000000001 | 0 | 0 |
37 | | 0000000000010001 | 0000000000000011 | 0 | 1 | 0 | 1 | 0 | 1 | 0000000000010011 | 0 | 0 |
38 |
--------------------------------------------------------------------------------
/hardware/alu/Add16.cmp:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 1111111111111111 |
4 | | 1111111111111111 | 1111111111111111 | 1111111111111110 |
5 | | 1010101010101010 | 0101010101010101 | 1111111111111111 |
6 | | 0011110011000011 | 0000111111110000 | 0100110010110011 |
7 | | 0001001000110100 | 1001100001110110 | 1010101010101010 |
8 |
--------------------------------------------------------------------------------
/hardware/alu/Add16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/Adder16.hdl
5 |
6 | /**
7 | * Adds two 16-bit values.
8 | * The most significant carry bit is ignored.
9 | */
10 |
11 | CHIP Add16 {
12 | IN a[16], b[16];
13 | OUT out[16];
14 |
15 | PARTS:
16 | FullAdder(a=a[0],b=b[0],c=false,sum=out[0],carry=carry0);
17 | FullAdder(a=a[1],b=b[1],c=carry0,sum=out[1],carry=carry1);
18 | FullAdder(a=a[2],b=b[2],c=carry1,sum=out[2],carry=carry2);
19 | FullAdder(a=a[3],b=b[3],c=carry2,sum=out[3],carry=carry3);
20 | FullAdder(a=a[4],b=b[4],c=carry3,sum=out[4],carry=carry4);
21 | FullAdder(a=a[5],b=b[5],c=carry4,sum=out[5],carry=carry5);
22 | FullAdder(a=a[6],b=b[6],c=carry5,sum=out[6],carry=carry6);
23 | FullAdder(a=a[7],b=b[7],c=carry6,sum=out[7],carry=carry7);
24 | FullAdder(a=a[8],b=b[8],c=carry7,sum=out[8],carry=carry8);
25 | FullAdder(a=a[9],b=b[9],c=carry8,sum=out[9],carry=carry9);
26 | FullAdder(a=a[10],b=b[10],c=carry9,sum=out[10],carry=carry10);
27 | FullAdder(a=a[11],b=b[11],c=carry10,sum=out[11],carry=carry11);
28 | FullAdder(a=a[12],b=b[12],c=carry11,sum=out[12],carry=carry12);
29 | FullAdder(a=a[13],b=b[13],c=carry12,sum=out[13],carry=carry13);
30 | FullAdder(a=a[14],b=b[14],c=carry13,sum=out[14],carry=carry14);
31 | FullAdder(a=a[15],b=b[15],c=carry14,sum=out[15],carry=carry15);
32 | }
--------------------------------------------------------------------------------
/hardware/alu/Add16.out:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 1111111111111111 |
4 | | 1111111111111111 | 1111111111111111 | 1111111111111110 |
5 | | 1010101010101010 | 0101010101010101 | 1111111111111111 |
6 | | 0011110011000011 | 0000111111110000 | 0100110010110011 |
7 | | 0001001000110100 | 1001100001110110 | 1010101010101010 |
8 |
--------------------------------------------------------------------------------
/hardware/alu/Add16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/Add16.tst
5 |
6 | load Add16.hdl,
7 | output-file Add16.out,
8 | compare-to Add16.cmp,
9 | output-list a%B1.16.1 b%B1.16.1 out%B1.16.1;
10 |
11 | set a %B0000000000000000,
12 | set b %B0000000000000000,
13 | eval,
14 | output;
15 |
16 | set a %B0000000000000000,
17 | set b %B1111111111111111,
18 | eval,
19 | output;
20 |
21 | set a %B1111111111111111,
22 | set b %B1111111111111111,
23 | eval,
24 | output;
25 |
26 | set a %B1010101010101010,
27 | set b %B0101010101010101,
28 | eval,
29 | output;
30 |
31 | set a %B0011110011000011,
32 | set b %B0000111111110000,
33 | eval,
34 | output;
35 |
36 | set a %B0001001000110100,
37 | set b %B1001100001110110,
38 | eval,
39 | output;
40 |
--------------------------------------------------------------------------------
/hardware/alu/FullAdder.cmp:
--------------------------------------------------------------------------------
1 | | a | b | c | sum | carry |
2 | | 0 | 0 | 0 | 0 | 0 |
3 | | 0 | 0 | 1 | 1 | 0 |
4 | | 0 | 1 | 0 | 1 | 0 |
5 | | 0 | 1 | 1 | 0 | 1 |
6 | | 1 | 0 | 0 | 1 | 0 |
7 | | 1 | 0 | 1 | 0 | 1 |
8 | | 1 | 1 | 0 | 0 | 1 |
9 | | 1 | 1 | 1 | 1 | 1 |
10 |
--------------------------------------------------------------------------------
/hardware/alu/FullAdder.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/FullAdder.hdl
5 |
6 | /**
7 | * Computes the sum of three bits.
8 | */
9 |
10 | CHIP FullAdder {
11 | IN a, b, c; // 1-bit inputs
12 | OUT sum, // Right bit of a + b + c
13 | carry; // Left bit of a + b + c
14 |
15 | PARTS:
16 | And(a=a,b=b,out=ab);
17 | And(a=a,b=c,out=ac);
18 | And(a=b,b=c,out=bc);
19 | Or(a=ab,b=ac,out=o1);
20 | Or(a=o1,b=bc,out=carry);
21 |
22 | Not(in=a,out=nota);
23 | Not(in=b,out=notb);
24 | Not(in=c,out=notc);
25 |
26 | Xor(a=b,b=c,out=xorbc);
27 | And(a=nota,b=xorbc,out=o2);
28 |
29 | And(a=notb,b=notc,out=notbc);
30 | Or(a=notbc,b=bc,out=notbcbc);
31 | And(a=a,b=notbcbc,out=o3);
32 |
33 | Or(a=o2,b=o3,out=sum);
34 | }
--------------------------------------------------------------------------------
/hardware/alu/FullAdder.out:
--------------------------------------------------------------------------------
1 | | a | b | c | sum | carry |
2 | | 0 | 0 | 0 | 0 | 0 |
3 | | 0 | 0 | 1 | 1 | 0 |
4 | | 0 | 1 | 0 | 1 | 0 |
5 | | 0 | 1 | 1 | 0 | 1 |
6 | | 1 | 0 | 0 | 1 | 0 |
7 | | 1 | 0 | 1 | 0 | 1 |
8 | | 1 | 1 | 0 | 0 | 1 |
9 | | 1 | 1 | 1 | 1 | 1 |
10 |
--------------------------------------------------------------------------------
/hardware/alu/FullAdder.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/FullAdder.tst
5 |
6 | load FullAdder.hdl,
7 | output-file FullAdder.out,
8 | compare-to FullAdder.cmp,
9 | output-list a%B3.1.3 b%B3.1.3 c%B3.1.3 sum%B3.1.3 carry%B3.1.3;
10 |
11 | set a 0,
12 | set b 0,
13 | set c 0,
14 | eval,
15 | output;
16 |
17 | set c 1,
18 | eval,
19 | output;
20 |
21 | set b 1,
22 | set c 0,
23 | eval,
24 | output;
25 |
26 | set c 1,
27 | eval,
28 | output;
29 |
30 | set a 1,
31 | set b 0,
32 | set c 0,
33 | eval,
34 | output;
35 |
36 | set c 1,
37 | eval,
38 | output;
39 |
40 | set b 1,
41 | set c 0,
42 | eval,
43 | output;
44 |
45 | set c 1,
46 | eval,
47 | output;
48 |
--------------------------------------------------------------------------------
/hardware/alu/HalfAdder.cmp:
--------------------------------------------------------------------------------
1 | | a | b | sum | carry |
2 | | 0 | 0 | 0 | 0 |
3 | | 0 | 1 | 1 | 0 |
4 | | 1 | 0 | 1 | 0 |
5 | | 1 | 1 | 0 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/alu/HalfAdder.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/HalfAdder.hdl
5 |
6 | /**
7 | * Computes the sum of two bits.
8 | */
9 |
10 | CHIP HalfAdder {
11 | IN a, b; // 1-bit inputs
12 | OUT sum, // Right bit of a + b
13 | carry; // Left bit of a + b
14 |
15 | PARTS:
16 | Xor(a=a,b=b,out=sum);
17 | And(a=a,b=b,out=carry);
18 | }
19 |
--------------------------------------------------------------------------------
/hardware/alu/HalfAdder.out:
--------------------------------------------------------------------------------
1 | | a | b | sum | carry |
2 | | 0 | 0 | 0 | 0 |
3 | | 0 | 1 | 1 | 0 |
4 | | 1 | 0 | 1 | 0 |
5 | | 1 | 1 | 0 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/alu/HalfAdder.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/HalfAdder.tst
5 |
6 | load HalfAdder.hdl,
7 | output-file HalfAdder.out,
8 | compare-to HalfAdder.cmp,
9 | output-list a%B3.1.3 b%B3.1.3 sum%B3.1.3 carry%B3.1.3;
10 |
11 | set a 0,
12 | set b 0,
13 | eval,
14 | output;
15 |
16 | set a 0,
17 | set b 1,
18 | eval,
19 | output;
20 |
21 | set a 1,
22 | set b 0,
23 | eval,
24 | output;
25 |
26 | set a 1,
27 | set b 1,
28 | eval,
29 | output;
30 |
--------------------------------------------------------------------------------
/hardware/alu/Inc16.cmp:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 0000000000000000 | 0000000000000001 |
3 | | 1111111111111111 | 0000000000000000 |
4 | | 0000000000000101 | 0000000000000110 |
5 | | 1111111111111011 | 1111111111111100 |
6 |
--------------------------------------------------------------------------------
/hardware/alu/Inc16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/Inc16.hdl
5 |
6 | /**
7 | * 16-bit incrementer:
8 | * out = in + 1 (arithmetic addition)
9 | */
10 |
11 | CHIP Inc16 {
12 | IN in[16];
13 | OUT out[16];
14 |
15 | PARTS:
16 | Add16(a=in,b[0]=true, b[1..15]=false,out=out);
17 | }
--------------------------------------------------------------------------------
/hardware/alu/Inc16.out:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 0000000000000000 | 0000000000000001 |
3 | | 1111111111111111 | 0000000000000000 |
4 | | 0000000000000101 | 0000000000000110 |
5 | | 1111111111111011 | 1111111111111100 |
6 |
--------------------------------------------------------------------------------
/hardware/alu/Inc16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/02/Inc16.tst
5 |
6 | load Inc16.hdl,
7 | output-file Inc16.out,
8 | compare-to Inc16.cmp,
9 | output-list in%B1.16.1 out%B1.16.1;
10 |
11 | set in %B0000000000000000, // in = 0
12 | eval,
13 | output;
14 |
15 | set in %B1111111111111111, // in = -1
16 | eval,
17 | output;
18 |
19 | set in %B0000000000000101, // in = 5
20 | eval,
21 | output;
22 |
23 | set in %B1111111111111011, // in = -5
24 | eval,
25 | output;
26 |
--------------------------------------------------------------------------------
/hardware/alu/IsNegative16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or16.hdl
5 |
6 |
7 | CHIP IsNegative16 {
8 | IN in[16];
9 | OUT out;
10 | PARTS:
11 | And(a=in[15],b=true,out=out);
12 | }
--------------------------------------------------------------------------------
/hardware/alu/Or16Way.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or8Way.hdl
5 |
6 |
7 | CHIP Or16Way {
8 | IN in[16];
9 | OUT out;
10 |
11 | PARTS:
12 | Or8Way(in=in[0..7],out=a);
13 | Or8Way(in=in[8..15],out=b);
14 | Or(a=a,b=b,out=out);
15 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/And.cmp:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0 | 0 | 0 |
3 | | 0 | 1 | 0 |
4 | | 1 | 0 | 0 |
5 | | 1 | 1 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/And.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/And.hdl
5 |
6 | /**
7 | * And gate:
8 | * out = 1 if (a == 1 and b == 1)
9 | * 0 otherwise
10 | */
11 |
12 | CHIP And {
13 | IN a, b;
14 | OUT out;
15 |
16 | PARTS:
17 | Nand (a=a,b=b,out=out1);
18 | Not(in=out1,out=out);
19 | }
20 |
--------------------------------------------------------------------------------
/hardware/bool_gate/And.out:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0 | 0 | 0 |
3 | | 0 | 1 | 0 |
4 | | 1 | 0 | 0 |
5 | | 1 | 1 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/And.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/And.tst
5 |
6 | load And.hdl,
7 | output-file And.out,
8 | compare-to And.cmp,
9 | output-list a%B3.1.3 b%B3.1.3 out%B3.1.3;
10 |
11 | set a 0,
12 | set b 0,
13 | eval,
14 | output;
15 |
16 | set a 0,
17 | set b 1,
18 | eval,
19 | output;
20 |
21 | set a 1,
22 | set b 0,
23 | eval,
24 | output;
25 |
26 | set a 1,
27 | set b 1,
28 | eval,
29 | output;
30 |
--------------------------------------------------------------------------------
/hardware/bool_gate/And16.cmp:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 0000000000000000 |
4 | | 1111111111111111 | 1111111111111111 | 1111111111111111 |
5 | | 1010101010101010 | 0101010101010101 | 0000000000000000 |
6 | | 0011110011000011 | 0000111111110000 | 0000110011000000 |
7 | | 0001001000110100 | 1001100001110110 | 0001000000110100 |
8 |
--------------------------------------------------------------------------------
/hardware/bool_gate/And16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/And16.hdl
5 |
6 | /**
7 | * 16-bit bitwise And:
8 | * for i = 0..15: out[i] = (a[i] and b[i])
9 | */
10 |
11 |
12 | CHIP And16 {
13 | IN a[16], b[16];
14 | OUT out[16];
15 | PARTS:
16 |
17 | And(a=a[0],b=b[0],out=out[0]);
18 | And(a=a[1],b=b[1],out=out[1]);
19 | And(a=a[2],b=b[2],out=out[2]);
20 | And(a=a[3],b=b[3],out=out[3]);
21 | And(a=a[4],b=b[4],out=out[4]);
22 | And(a=a[5],b=b[5],out=out[5]);
23 | And(a=a[6],b=b[6],out=out[6]);
24 | And(a=a[7],b=b[7],out=out[7]);
25 | And(a=a[8],b=b[8],out=out[8]);
26 | And(a=a[9],b=b[9],out=out[9]);
27 | And(a=a[10],b=b[10],out=out[10]);
28 | And(a=a[11],b=b[11],out=out[11]);
29 | And(a=a[12],b=b[12],out=out[12]);
30 | And(a=a[13],b=b[13],out=out[13]);
31 | And(a=a[14],b=b[14],out=out[14]);
32 | And(a=a[15],b=b[15],out=out[15]);
33 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/And16.out:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 0000000000000000 |
4 | | 1111111111111111 | 1111111111111111 | 1111111111111111 |
5 | | 1010101010101010 | 0101010101010101 | 0000000000000000 |
6 | | 0011110011000011 | 0000111111110000 | 0000110011000000 |
7 | | 0001001000110100 | 1001100001110110 | 0001000000110100 |
8 |
--------------------------------------------------------------------------------
/hardware/bool_gate/And16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/And16.tst
5 |
6 | load And16.hdl,
7 | output-file And16.out,
8 | compare-to And16.cmp,
9 | output-list a%B1.16.1 b%B1.16.1 out%B1.16.1;
10 |
11 | set a %B0000000000000000,
12 | set b %B0000000000000000,
13 | eval,
14 | output;
15 |
16 | set a %B0000000000000000,
17 | set b %B1111111111111111,
18 | eval,
19 | output;
20 |
21 | set a %B1111111111111111,
22 | set b %B1111111111111111,
23 | eval,
24 | output;
25 |
26 | set a %B1010101010101010,
27 | set b %B0101010101010101,
28 | eval,
29 | output;
30 |
31 | set a %B0011110011000011,
32 | set b %B0000111111110000,
33 | eval,
34 | output;
35 |
36 | set a %B0001001000110100,
37 | set b %B1001100001110110,
38 | eval,
39 | output;
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux.cmp:
--------------------------------------------------------------------------------
1 | | in | sel | a | b |
2 | | 0 | 0 | 0 | 0 |
3 | | 0 | 1 | 0 | 0 |
4 | | 1 | 0 | 1 | 0 |
5 | | 1 | 1 | 0 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/DMux.hdl
5 |
6 | /**
7 | * Demultiplexor:
8 | * {a, b} = {in, 0} if sel == 0
9 | * {0, in} if sel == 1
10 | */
11 |
12 | CHIP DMux {
13 | IN in, sel;
14 | OUT a, b;
15 |
16 | PARTS:
17 | Not(in=sel,out=notsel);
18 | And(a=notsel,b=in,out=a);
19 | And(a=sel,b=in,out=b);
20 | }
21 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux.out:
--------------------------------------------------------------------------------
1 | | in | sel | a | b |
2 | | 0 | 0 | 0 | 0 |
3 | | 0 | 1 | 0 | 0 |
4 | | 1 | 0 | 1 | 0 |
5 | | 1 | 1 | 0 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/DMux.tst
5 |
6 | load DMux.hdl,
7 | output-file DMux.out,
8 | compare-to DMux.cmp,
9 | output-list in%B3.1.3 sel%B3.1.3 a%B3.1.3 b%B3.1.3;
10 |
11 | set in 0,
12 | set sel 0,
13 | eval,
14 | output;
15 |
16 | set sel 1,
17 | eval,
18 | output;
19 |
20 | set in 1,
21 | set sel 0,
22 | eval,
23 | output;
24 |
25 | set sel 1,
26 | eval,
27 | output;
28 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux4Way.cmp:
--------------------------------------------------------------------------------
1 | | in | sel | a | b | c | d |
2 | | 0 | 00 | 0 | 0 | 0 | 0 |
3 | | 0 | 01 | 0 | 0 | 0 | 0 |
4 | | 0 | 10 | 0 | 0 | 0 | 0 |
5 | | 0 | 11 | 0 | 0 | 0 | 0 |
6 | | 1 | 00 | 1 | 0 | 0 | 0 |
7 | | 1 | 01 | 0 | 1 | 0 | 0 |
8 | | 1 | 10 | 0 | 0 | 1 | 0 |
9 | | 1 | 11 | 0 | 0 | 0 | 1 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux4Way.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/DMux4Way.hdl
5 |
6 | /**
7 | * 4-way demultiplexor:
8 | * {a, b, c, d} = {in, 0, 0, 0} if sel == 00
9 | * {0, in, 0, 0} if sel == 01
10 | * {0, 0, in, 0} if sel == 10
11 | * {0, 0, 0, in} if sel == 11
12 | */
13 |
14 | CHIP DMux4Way {
15 | IN in, sel[2];
16 | OUT a, b, c, d;
17 |
18 | PARTS:
19 | // Put your code here:
20 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux4Way.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/DMux4Way.tst
5 |
6 | load DMux4Way.hdl,
7 | output-file DMux4Way.out,
8 | compare-to DMux4Way.cmp,
9 | output-list in%B2.1.2 sel%B2.2.2 a%B2.1.2 b%B2.1.2 c%B2.1.2 d%B2.1.2;
10 |
11 | set in 0,
12 | set sel %B00,
13 | eval,
14 | output;
15 |
16 | set sel %B01,
17 | eval,
18 | output;
19 |
20 | set sel %B10,
21 | eval,
22 | output;
23 |
24 | set sel %B11,
25 | eval,
26 | output;
27 |
28 | set in 1,
29 | set sel %B00,
30 | eval,
31 | output;
32 |
33 | set sel %B01,
34 | eval,
35 | output;
36 |
37 | set sel %B10,
38 | eval,
39 | output;
40 |
41 | set sel %B11,
42 | eval,
43 | output;
44 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux8Way.cmp:
--------------------------------------------------------------------------------
1 | | in | sel | a | b | c | d | e | f | g | h |
2 | | 0 | 000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | | 0 | 001 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | | 0 | 010 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | | 0 | 011 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | | 0 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | | 0 | 101 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | | 0 | 110 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | | 0 | 111 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | | 1 | 000 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
11 | | 1 | 001 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
12 | | 1 | 010 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
13 | | 1 | 011 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
14 | | 1 | 100 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
15 | | 1 | 101 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
16 | | 1 | 110 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
17 | | 1 | 111 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
18 |
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux8Way.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/DMux8Way.hdl
5 |
6 | /**
7 | * 8-way demultiplexor:
8 | * {a, b, c, d, e, f, g, h} = {in, 0, 0, 0, 0, 0, 0, 0} if sel == 000
9 | * {0, in, 0, 0, 0, 0, 0, 0} if sel == 001
10 | * etc.
11 | * {0, 0, 0, 0, 0, 0, 0, in} if sel == 111
12 | */
13 |
14 | CHIP DMux8Way {
15 | IN in, sel[3];
16 | OUT a, b, c, d, e, f, g, h;
17 |
18 | PARTS:
19 | // Put your code here:
20 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/DMux8Way.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/DMux8Way.tst
5 |
6 | load DMux8Way.hdl,
7 | output-file DMux8Way.out,
8 | compare-to DMux8Way.cmp,
9 | output-list in%B2.1.2 sel%B2.3.2 a%B2.1.2 b%B2.1.2 c%B2.1.2 d%B2.1.2 e%B2.1.2 f%B2.1.2 g%B2.1.2 h%B2.1.2;
10 |
11 | set in 0,
12 | set sel %B000,
13 | eval,
14 | output;
15 |
16 | set sel %B001,
17 | eval,
18 | output;
19 |
20 | set sel %B010,
21 | eval,
22 | output;
23 |
24 | set sel %B011,
25 | eval,
26 | output;
27 |
28 | set sel %B100,
29 | eval,
30 | output;
31 |
32 | set sel %B101,
33 | eval,
34 | output;
35 |
36 | set sel %B110,
37 | eval,
38 | output;
39 |
40 | set sel %B111,
41 | eval,
42 | output;
43 |
44 | set in 1,
45 | set sel %B000,
46 | eval,
47 | output;
48 |
49 | set sel %B001,
50 | eval,
51 | output;
52 |
53 | set sel %B010,
54 | eval,
55 | output;
56 |
57 | set sel %B011,
58 | eval,
59 | output;
60 |
61 | set sel %B100,
62 | eval,
63 | output;
64 |
65 | set sel %B101,
66 | eval,
67 | output;
68 |
69 | set sel %B110,
70 | eval,
71 | output;
72 |
73 | set sel %B111,
74 | eval,
75 | output;
76 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux.cmp:
--------------------------------------------------------------------------------
1 | | a | b | sel | out |
2 | | 0 | 0 | 0 | 0 |
3 | | 0 | 0 | 1 | 0 |
4 | | 0 | 1 | 0 | 0 |
5 | | 0 | 1 | 1 | 1 |
6 | | 1 | 0 | 0 | 1 |
7 | | 1 | 0 | 1 | 0 |
8 | | 1 | 1 | 0 | 1 |
9 | | 1 | 1 | 1 | 1 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux.hdl
5 |
6 | /**
7 | * Multiplexor:
8 | * out = a if sel == 0
9 | * b otherwise
10 | */
11 |
12 | CHIP Mux {
13 | IN a, b, sel;
14 | OUT out;
15 |
16 | PARTS:
17 | // Put your code here:
18 | Not (in=sel,out=notsel);
19 | And (a=a,b=notsel,out=out1);
20 | And (a=b,b=sel,out=out2);
21 | Or (a=out1,b=out2,out=out);
22 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux.out:
--------------------------------------------------------------------------------
1 | | a | b | sel | out |
2 | | 0 | 0 | 0 | 0 |
3 | | 0 | 0 | 1 | 0 |
4 | | 0 | 1 | 0 | 0 |
5 | | 0 | 1 | 1 | 1 |
6 | | 1 | 0 | 0 | 1 |
7 | | 1 | 0 | 1 | 0 |
8 | | 1 | 1 | 0 | 1 |
9 | | 1 | 1 | 1 | 1 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux.tst
5 |
6 | load Mux.hdl,
7 | output-file Mux.out,
8 | compare-to Mux.cmp,
9 | output-list a%B3.1.3 b%B3.1.3 sel%B3.1.3 out%B3.1.3;
10 |
11 | set a 0,
12 | set b 0,
13 | set sel 0,
14 | eval,
15 | output;
16 |
17 | set sel 1,
18 | eval,
19 | output;
20 |
21 | set a 0,
22 | set b 1,
23 | set sel 0,
24 | eval,
25 | output;
26 |
27 | set sel 1,
28 | eval,
29 | output;
30 |
31 | set a 1,
32 | set b 0,
33 | set sel 0,
34 | eval,
35 | output;
36 |
37 | set sel 1,
38 | eval,
39 | output;
40 |
41 | set a 1,
42 | set b 1,
43 | set sel 0,
44 | eval,
45 | output;
46 |
47 | set sel 1,
48 | eval,
49 | output;
50 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux16.cmp:
--------------------------------------------------------------------------------
1 | | a | b | sel | out |
2 | | 0000000000000000 | 0000000000000000 | 0 | 0000000000000000 |
3 | | 0000000000000000 | 0000000000000000 | 1 | 0000000000000000 |
4 | | 0000000000000000 | 0001001000110100 | 0 | 0000000000000000 |
5 | | 0000000000000000 | 0001001000110100 | 1 | 0001001000110100 |
6 | | 1001100001110110 | 0000000000000000 | 0 | 1001100001110110 |
7 | | 1001100001110110 | 0000000000000000 | 1 | 0000000000000000 |
8 | | 1010101010101010 | 0101010101010101 | 0 | 1010101010101010 |
9 | | 1010101010101010 | 0101010101010101 | 1 | 0101010101010101 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux16.hdl
5 |
6 | /**
7 | * 16-bit multiplexor:
8 | * for i = 0..15 out[i] = a[i] if sel == 0
9 | * b[i] if sel == 1
10 | */
11 |
12 | CHIP Mux16 {
13 | IN a[16], b[16], sel;
14 | OUT out[16];
15 |
16 | PARTS:
17 | Not (in=sel,out=notsel);
18 |
19 | And (a=a[0],b=notsel,out=out11);
20 | And (a=b[0],b=sel,out=out12);
21 | Or (a=out11,b=out12,out=out[0]);
22 |
23 | And (a=a[1],b=notsel,out=out21);
24 | And (a=b[1],b=sel,out=out22);
25 | Or (a=out21,b=out22,out=out[1]);
26 |
27 | And (a=a[2],b=notsel,out=out31);
28 | And (a=b[2],b=sel,out=out32);
29 | Or (a=out31,b=out32,out=out[2]);
30 |
31 | And (a=a[3],b=notsel,out=out41);
32 | And (a=b[3],b=sel,out=out42);
33 | Or (a=out41,b=out42,out=out[3]);
34 |
35 | And (a=a[4],b=notsel,out=out51);
36 | And (a=b[4],b=sel,out=out52);
37 | Or (a=out51,b=out52,out=out[4]);
38 |
39 | And (a=a[5],b=notsel,out=out61);
40 | And (a=b[5],b=sel,out=out62);
41 | Or (a=out61,b=out62,out=out[5]);
42 |
43 | And (a=a[6],b=notsel,out=out71);
44 | And (a=b[6],b=sel,out=out72);
45 | Or (a=out71,b=out72,out=out[6]);
46 |
47 | And (a=a[7],b=notsel,out=out81);
48 | And (a=b[7],b=sel,out=out82);
49 | Or (a=out81,b=out82,out=out[7]);
50 |
51 | And (a=a[8],b=notsel,out=out91);
52 | And (a=b[8],b=sel,out=out92);
53 | Or (a=out91,b=out92,out=out[8]);
54 |
55 | And (a=a[9],b=notsel,out=out101);
56 | And (a=b[9],b=sel,out=out102);
57 | Or (a=out101,b=out102,out=out[9]);
58 |
59 | And (a=a[10],b=notsel,out=out111);
60 | And (a=b[10],b=sel,out=out112);
61 | Or (a=out111,b=out112,out=out[10]);
62 |
63 | And (a=a[11],b=notsel,out=out121);
64 | And (a=b[11],b=sel,out=out122);
65 | Or (a=out121,b=out122,out=out[11]);
66 |
67 | And (a=a[12],b=notsel,out=out131);
68 | And (a=b[12],b=sel,out=out132);
69 | Or (a=out131,b=out132,out=out[12]);
70 |
71 | And (a=a[13],b=notsel,out=out141);
72 | And (a=b[13],b=sel,out=out142);
73 | Or (a=out141,b=out142,out=out[13]);
74 |
75 | And (a=a[14],b=notsel,out=out151);
76 | And (a=b[14],b=sel,out=out152);
77 | Or (a=out151,b=out152,out=out[14]);
78 |
79 | And (a=a[15],b=notsel,out=outaaa);
80 | And (a=b[15],b=sel,out=out162);
81 | Or (a=outaaa,b=out162,out=out[15]);
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux16.out:
--------------------------------------------------------------------------------
1 | | a | b | sel | out |
2 | | 0000000000000000 | 0000000000000000 | 0 | 0000000000000000 |
3 | | 0000000000000000 | 0000000000000000 | 1 | 0000000000000000 |
4 | | 0000000000000000 | 0001001000110100 | 0 | 0000000000000000 |
5 | | 0000000000000000 | 0001001000110100 | 1 | 0001001000110100 |
6 | | 1001100001110110 | 0000000000000000 | 0 | 1001100001110110 |
7 | | 1001100001110110 | 0000000000000000 | 1 | 0000000000000000 |
8 | | 1010101010101010 | 0101010101010101 | 0 | 1010101010101010 |
9 | | 1010101010101010 | 0101010101010101 | 1 | 0101010101010101 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux16.tst
5 |
6 | load Mux16.hdl,
7 | output-file Mux16.out,
8 | compare-to Mux16.cmp,
9 | output-list a%B1.16.1 b%B1.16.1 sel%D2.1.2 out%B1.16.1;
10 |
11 | set a 0,
12 | set b 0,
13 | set sel 0,
14 | eval,
15 | output;
16 |
17 | set sel 1,
18 | eval,
19 | output;
20 |
21 | set a %B0000000000000000,
22 | set b %B0001001000110100,
23 | set sel 0,
24 | eval,
25 | output;
26 |
27 | set sel 1,
28 | eval,
29 | output;
30 |
31 | set a %B1001100001110110,
32 | set b %B0000000000000000,
33 | set sel 0,
34 | eval,
35 | output;
36 |
37 | set sel 1,
38 | eval,
39 | output;
40 |
41 | set a %B1010101010101010,
42 | set b %B0101010101010101,
43 | set sel 0,
44 | eval,
45 | output;
46 |
47 | set sel 1,
48 | eval,
49 | output;
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux4Way16.cmp:
--------------------------------------------------------------------------------
1 | | a | b | c | d | sel | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 00 | 0000000000000000 |
3 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 01 | 0000000000000000 |
4 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 10 | 0000000000000000 |
5 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 11 | 0000000000000000 |
6 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 00 | 0001001000110100 |
7 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 01 | 1001100001110110 |
8 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 10 | 1010101010101010 |
9 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 11 | 0101010101010101 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux4Way16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux4Way16.hdl
5 |
6 | /**
7 | * 4-way 16-bit multiplexor:
8 | * out = a if sel == 00
9 | * b if sel == 01
10 | * c if sel == 10
11 | * d if sel == 11
12 | */
13 |
14 | CHIP Mux4Way16 {
15 | IN a[16], b[16], c[16], d[16], sel[2];
16 | OUT out[16];
17 |
18 | PARTS:
19 | Mux16(a=a,b=b,sel=sel[0],out=o1);
20 | Mux16(a=c,b=d,sel=sel[0],out=o2);
21 | Mux16(a=o1,b=o2,sel=sel[1],out=out);
22 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux4Way16.out:
--------------------------------------------------------------------------------
1 | | a | b | c | d | sel | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 00 | 0000000000000000 |
3 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 01 | 0000000000000000 |
4 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 10 | 0000000000000000 |
5 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 11 | 0000000000000000 |
6 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 00 | 0001001000110100 |
7 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 01 | 1001100001110110 |
8 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 10 | 1010101010101010 |
9 | | 0001001000110100 | 1001100001110110 | 1010101010101010 | 0101010101010101 | 11 | 0101010101010101 |
10 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux4Way16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux4Way16.tst
5 |
6 | load Mux4Way16.hdl,
7 | output-file Mux4Way16.out,
8 | compare-to Mux4Way16.cmp,
9 | output-list a%B1.16.1 b%B1.16.1 c%B1.16.1 d%B1.16.1 sel%B2.2.2 out%B1.16.1;
10 |
11 | set a 0,
12 | set b 0,
13 | set c 0,
14 | set d 0,
15 | set sel 0,
16 | eval,
17 | output;
18 |
19 | set sel 1,
20 | eval,
21 | output;
22 |
23 | set sel 2,
24 | eval,
25 | output;
26 |
27 | set sel 3,
28 | eval,
29 | output;
30 |
31 | set a %B0001001000110100,
32 | set b %B1001100001110110,
33 | set c %B1010101010101010,
34 | set d %B0101010101010101,
35 | set sel 0,
36 | eval,
37 | output;
38 |
39 | set sel 1,
40 | eval,
41 | output;
42 |
43 | set sel 2,
44 | eval,
45 | output;
46 |
47 | set sel 3,
48 | eval,
49 | output;
50 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux8Way16.cmp:
--------------------------------------------------------------------------------
1 | | a | b | c | d | e | f | g | h | sel | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 000 | 0000000000000000 |
3 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 001 | 0000000000000000 |
4 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 010 | 0000000000000000 |
5 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 011 | 0000000000000000 |
6 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 100 | 0000000000000000 |
7 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 101 | 0000000000000000 |
8 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 110 | 0000000000000000 |
9 | | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 0000000000000000 | 111 | 0000000000000000 |
10 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 000 | 0001001000110100 |
11 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 001 | 0010001101000101 |
12 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 010 | 0011010001010110 |
13 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 011 | 0100010101100111 |
14 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 100 | 0101011001111000 |
15 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 101 | 0110011110001001 |
16 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 110 | 0111100010011010 |
17 | | 0001001000110100 | 0010001101000101 | 0011010001010110 | 0100010101100111 | 0101011001111000 | 0110011110001001 | 0111100010011010 | 1000100110101011 | 111 | 1000100110101011 |
18 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux8Way16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux8Way16.hdl
5 |
6 | /**
7 | * 8-way 16-bit multiplexor:
8 | * out = a if sel == 000
9 | * b if sel == 001
10 | * etc.
11 | * h if sel == 111
12 | */
13 |
14 | CHIP Mux8Way16 {
15 | IN a[16], b[16], c[16], d[16],
16 | e[16], f[16], g[16], h[16],
17 | sel[3];
18 | OUT out[16];
19 |
20 | PARTS:
21 | // Put your code here:
22 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Mux8Way16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Mux8Way16.tst
5 |
6 | load Mux8Way16.hdl,
7 | output-file Mux8Way16.out,
8 | compare-to Mux8Way16.cmp,
9 | output-list a%B1.16.1 b%B1.16.1 c%B1.16.1 d%B1.16.1 e%B1.16.1 f%B1.16.1 g%B1.16.1 h%B1.16.1 sel%B2.3.2 out%B1.16.1;
10 |
11 | set a 0,
12 | set b 0,
13 | set c 0,
14 | set d 0,
15 | set e 0,
16 | set f 0,
17 | set g 0,
18 | set h 0,
19 | set sel 0,
20 | eval,
21 | output;
22 |
23 | set sel 1,
24 | eval,
25 | output;
26 |
27 | set sel 2,
28 | eval,
29 | output;
30 |
31 | set sel 3,
32 | eval,
33 | output;
34 |
35 | set sel 4,
36 | eval,
37 | output;
38 |
39 | set sel 5,
40 | eval,
41 | output;
42 |
43 | set sel 6,
44 | eval,
45 | output;
46 |
47 | set sel 7,
48 | eval,
49 | output;
50 |
51 | set a %B0001001000110100,
52 | set b %B0010001101000101,
53 | set c %B0011010001010110,
54 | set d %B0100010101100111,
55 | set e %B0101011001111000,
56 | set f %B0110011110001001,
57 | set g %B0111100010011010,
58 | set h %B1000100110101011,
59 | set sel 0,
60 | eval,
61 | output;
62 |
63 | set sel 1,
64 | eval,
65 | output;
66 |
67 | set sel 2,
68 | eval,
69 | output;
70 |
71 | set sel 3,
72 | eval,
73 | output;
74 |
75 | set sel 4,
76 | eval,
77 | output;
78 |
79 | set sel 5,
80 | eval,
81 | output;
82 |
83 | set sel 6,
84 | eval,
85 | output;
86 |
87 | set sel 7,
88 | eval,
89 | output;
90 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Not.cmp:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 0 | 1 |
3 | | 1 | 0 |
4 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Not.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Not.hdl
5 |
6 | /**
7 | * Not gate:
8 | * out = not in
9 | */
10 |
11 | CHIP Not {
12 | IN in;
13 | OUT out;
14 | PARTS:
15 | Nand (a=true,b=in,out=out);
16 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Not.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Not.tst
5 |
6 | load Not.hdl,
7 | output-file Not.out,
8 | compare-to Not.cmp,
9 | output-list in%B3.1.3 out%B3.1.3;
10 |
11 | set in 0,
12 | eval,
13 | output;
14 |
15 | set in 1,
16 | eval,
17 | output;
18 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Not16.cmp:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 0000000000000000 | 1111111111111111 |
3 | | 1111111111111111 | 0000000000000000 |
4 | | 1010101010101010 | 0101010101010101 |
5 | | 0011110011000011 | 1100001100111100 |
6 | | 0001001000110100 | 1110110111001011 |
7 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Not16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Not16.hdl
5 |
6 | /**
7 | * 16-bit Not:
8 | * for i=0..15: out[i] = not in[i]
9 | */
10 |
11 | CHIP Not16 {
12 | IN in[16];
13 | OUT out[16];
14 | PARTS:
15 | Not(in=in[0],out=out[0]);
16 | Not(in=in[1],out=out[1]);
17 | Not(in=in[2],out=out[2]);
18 | Not(in=in[3],out=out[3]);
19 | Not(in=in[4],out=out[4]);
20 | Not(in=in[5],out=out[5]);
21 | Not(in=in[6],out=out[6]);
22 | Not(in=in[7],out=out[7]);
23 | Not(in=in[8],out=out[8]);
24 | Not(in=in[9],out=out[9]);
25 | Not(in=in[10],out=out[10]);
26 | Not(in=in[11],out=out[11]);
27 | Not(in=in[12],out=out[12]);
28 | Not(in=in[13],out=out[13]);
29 | Not(in=in[14],out=out[14]);
30 | Not(in=in[15],out=out[15]);
31 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Not16.out:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 0000000000000000 | 1111111111111111 |
3 | | 1111111111111111 | 0000000000000000 |
4 | | 1010101010101010 | 0101010101010101 |
5 | | 0011110011000011 | 1100001100111100 |
6 | | 0001001000110100 | 1110110111001011 |
7 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Not16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Not16.tst
5 |
6 | load Not16.hdl,
7 | output-file Not16.out,
8 | compare-to Not16.cmp,
9 | output-list in%B1.16.1 out%B1.16.1;
10 |
11 | set in %B0000000000000000,
12 | eval,
13 | output;
14 |
15 | set in %B1111111111111111,
16 | eval,
17 | output;
18 |
19 | set in %B1010101010101010,
20 | eval,
21 | output;
22 |
23 | set in %B0011110011000011,
24 | eval,
25 | output;
26 |
27 | set in %B0001001000110100,
28 | eval,
29 | output;
--------------------------------------------------------------------------------
/hardware/bool_gate/Or.cmp:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0 | 0 | 0 |
3 | | 0 | 1 | 1 |
4 | | 1 | 0 | 1 |
5 | | 1 | 1 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or.hdl
5 |
6 | /**
7 | * Or gate:
8 | * out = 1 if (a == 1 or b == 1)
9 | * 0 otherwise
10 | */
11 |
12 | CHIP Or {
13 | IN a, b;
14 | OUT out;
15 |
16 | PARTS:
17 | Not (in=a,out=out1a);
18 | Not (in=b,out=out1b);
19 | And (a=out1a,b=out1b,out=out2);
20 | Not (in=out2,out=out);
21 | }
22 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or.out:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0 | 0 | 0 |
3 | | 0 | 1 | 1 |
4 | | 1 | 0 | 1 |
5 | | 1 | 1 | 1 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or.tst
5 |
6 | load Or.hdl,
7 | output-file Or.out,
8 | compare-to Or.cmp,
9 | output-list a%B3.1.3 b%B3.1.3 out%B3.1.3;
10 |
11 | set a 0,
12 | set b 0,
13 | eval,
14 | output;
15 |
16 | set a 0,
17 | set b 1,
18 | eval,
19 | output;
20 |
21 | set a 1,
22 | set b 0,
23 | eval,
24 | output;
25 |
26 | set a 1,
27 | set b 1,
28 | eval,
29 | output;
30 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or16.cmp:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 1111111111111111 |
4 | | 1111111111111111 | 1111111111111111 | 1111111111111111 |
5 | | 1010101010101010 | 0101010101010101 | 1111111111111111 |
6 | | 0011110011000011 | 0000111111110000 | 0011111111110011 |
7 | | 0001001000110100 | 1001100001110110 | 1001101001110110 |
8 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or16.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or16.hdl
5 |
6 | /**
7 | * 16-bit bitwise Or:
8 | * for i = 0..15 out[i] = (a[i] or b[i])
9 | */
10 |
11 | CHIP Or16 {
12 | IN a[16], b[16];
13 | OUT out[16];
14 | PARTS:
15 |
16 | Or(a=a[0],b=b[0],out=out[0]);
17 | Or(a=a[1],b=b[1],out=out[1]);
18 | Or(a=a[2],b=b[2],out=out[2]);
19 | Or(a=a[3],b=b[3],out=out[3]);
20 | Or(a=a[4],b=b[4],out=out[4]);
21 | Or(a=a[5],b=b[5],out=out[5]);
22 | Or(a=a[6],b=b[6],out=out[6]);
23 | Or(a=a[7],b=b[7],out=out[7]);
24 | Or(a=a[8],b=b[8],out=out[8]);
25 | Or(a=a[9],b=b[9],out=out[9]);
26 | Or(a=a[10],b=b[10],out=out[10]);
27 | Or(a=a[11],b=b[11],out=out[11]);
28 | Or(a=a[12],b=b[12],out=out[12]);
29 | Or(a=a[13],b=b[13],out=out[13]);
30 | Or(a=a[14],b=b[14],out=out[14]);
31 | Or(a=a[15],b=b[15],out=out[15]);
32 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Or16.out:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0000000000000000 | 0000000000000000 | 0000000000000000 |
3 | | 0000000000000000 | 1111111111111111 | 1111111111111111 |
4 | | 1111111111111111 | 1111111111111111 | 1111111111111111 |
5 | | 1010101010101010 | 0101010101010101 | 1111111111111111 |
6 | | 0011110011000011 | 0000111111110000 | 0011111111110011 |
7 | | 0001001000110100 | 1001100001110110 | 1001101001110110 |
8 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or16.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or16.tst
5 |
6 | load Or16.hdl,
7 | output-file Or16.out,
8 | compare-to Or16.cmp,
9 | output-list a%B1.16.1 b%B1.16.1 out%B1.16.1;
10 |
11 | set a %B0000000000000000,
12 | set b %B0000000000000000,
13 | eval,
14 | output;
15 |
16 | set a %B0000000000000000,
17 | set b %B1111111111111111,
18 | eval,
19 | output;
20 |
21 | set a %B1111111111111111,
22 | set b %B1111111111111111,
23 | eval,
24 | output;
25 |
26 | set a %B1010101010101010,
27 | set b %B0101010101010101,
28 | eval,
29 | output;
30 |
31 | set a %B0011110011000011,
32 | set b %B0000111111110000,
33 | eval,
34 | output;
35 |
36 | set a %B0001001000110100,
37 | set b %B1001100001110110,
38 | eval,
39 | output;
--------------------------------------------------------------------------------
/hardware/bool_gate/Or8Way.cmp:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 00000000 | 0 |
3 | | 11111111 | 1 |
4 | | 00010000 | 1 |
5 | | 00000001 | 1 |
6 | | 00100110 | 1 |
7 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or8Way.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or8Way.hdl
5 |
6 | /**
7 | * 8-way Or:
8 | * out = (in[0] or in[1] or ... or in[7])
9 | */
10 |
11 | CHIP Or8Way {
12 | IN in[8];
13 | OUT out;
14 |
15 | PARTS:
16 | Or(a=in[0],b=in[1],out=o1);
17 | Or(a=o1,b=in[2],out=o2);
18 | Or(a=o2,b=in[3],out=o3);
19 | Or(a=in[4],b=in[5],out=o4);
20 | Or(a=o4,b=in[6],out=o5);
21 | Or(a=o5,b=in[7],out=o6);
22 | Or(a=o3,b=o6,out=out);
23 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Or8Way.out:
--------------------------------------------------------------------------------
1 | | in | out |
2 | | 00000000 | 0 |
3 | | 11111111 | 1 |
4 | | 00010000 | 1 |
5 | | 00000001 | 1 |
6 | | 00100110 | 1 |
7 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Or8Way.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Or8Way.tst
5 |
6 | load Or8Way.hdl,
7 | output-file Or8Way.out,
8 | compare-to Or8Way.cmp,
9 | output-list in%B2.8.2 out%B2.1.2;
10 |
11 | set in %B00000000,
12 | eval,
13 | output;
14 |
15 | set in %B11111111,
16 | eval,
17 | output;
18 |
19 | set in %B00010000,
20 | eval,
21 | output;
22 |
23 | set in %B00000001,
24 | eval,
25 | output;
26 |
27 | set in %B00100110,
28 | eval,
29 | output;
--------------------------------------------------------------------------------
/hardware/bool_gate/Xor.cmp:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0 | 0 | 0 |
3 | | 0 | 1 | 1 |
4 | | 1 | 0 | 1 |
5 | | 1 | 1 | 0 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Xor.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Xor.hdl
5 |
6 | /**
7 | * Exclusive-or gate:
8 | * out = not (a == b)
9 | */
10 |
11 | CHIP Xor {
12 | IN a, b;
13 | OUT out;
14 | // Out = ^AB + A^B
15 | PARTS:
16 | Not(in=a,out=nota);
17 | And(a=nota,b=b,out=out1);
18 | Not(in=b,out=notb);
19 | And(a=a,b=notb,out=out2);
20 | Or(a=out1,b=out2,out=out);
21 | }
--------------------------------------------------------------------------------
/hardware/bool_gate/Xor.out:
--------------------------------------------------------------------------------
1 | | a | b | out |
2 | | 0 | 0 | 0 |
3 | | 0 | 1 | 1 |
4 | | 1 | 0 | 1 |
5 | | 1 | 1 | 0 |
6 |
--------------------------------------------------------------------------------
/hardware/bool_gate/Xor.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/01/Xor.tst
5 |
6 | load Xor.hdl,
7 | output-file Xor.out,
8 | compare-to Xor.cmp,
9 | output-list a%B3.1.3 b%B3.1.3 out%B3.1.3;
10 |
11 | set a 0,
12 | set b 0,
13 | eval,
14 | output;
15 |
16 | set a 0,
17 | set b 1,
18 | eval,
19 | output;
20 |
21 | set a 1,
22 | set b 0,
23 | eval,
24 | output;
25 |
26 | set a 1,
27 | set b 1,
28 | eval,
29 | output;
30 |
--------------------------------------------------------------------------------
/hardware/computer/AReg.hdl:
--------------------------------------------------------------------------------
1 |
2 |
3 | CHIP AReg {
4 |
5 | IN instruction[16],outM[16],inM[16];
6 | OUT out[16];
7 | PARTS:
8 | Not(in=instruction[15], out=isA);
9 | Not(in=isA, out=isC);
10 | And(a=isC, b=instruction[5], out=ALUtoA);
11 | Mux16(a=outM,b=instruction,sel=isA,out=outMu);
12 | Or(a=ALUtoA,b=isA,out=loadA);
13 | ARegister(in=outMu,load=loadA,out=A);
14 | // Define mnemonic(A or M)
15 | Mux16(a=A,b=inM,sel=instruction[12],out=out);
16 | }
--------------------------------------------------------------------------------
/hardware/computer/Add.hack:
--------------------------------------------------------------------------------
1 | 0000000000000010
2 | 1110110000010000
3 | 0000000000000011
4 | 1110000010010000
5 | 0000000000000000
6 | 1110001100001000
7 |
--------------------------------------------------------------------------------
/hardware/computer/CPU.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/CPU.hdl
5 |
6 | /**
7 | * The Hack CPU (Central Processing unit), consisting of an ALU,
8 | * two registers named A and D, and a program counter named PC.
9 | * The CPU is designed to fetch and execute instructions written in
10 | * the Hack machine language. In particular, functions as follows:
11 | * Executes the inputted instruction according to the Hack machine
12 | * language specification. The D and A in the language specification
13 | * refer to CPU-resident registers, while M refers to the external
14 | * memory location addressed by A, i.e. to Memory[A]. The inM input
15 | * holds the value of this location. If the current instruction needs
16 | * to write a value to M, the value is placed in outM, the address
17 | * of the target location is placed in the addressM output, and the
18 | * writeM control bit is asserted. (When writeM==0, any value may
19 | * appear in outM). The outM and writeM outputs are combinational:
20 | * they are affected instantaneously by the execution of the current
21 | * instruction. The addressM and pc outputs are clocked: although they
22 | * are affected by the execution of the current instruction, they commit
23 | * to their new values only in the next time step. If reset==1 then the
24 | * CPU jumps to address 0 (i.e. pc is set to 0 in next time step) rather
25 | * than to the address resulting from executing the current instruction.
26 | */
27 |
28 | CHIP CPU {
29 | IN inM[16], // M value input (M = contents of RAM[A])
30 | instruction[16], // Instruction for execution
31 | reset; // Signals whether to re-start the current
32 | // program (reset==1) or continue executing
33 | // the current program (reset==0).
34 |
35 | OUT outM[16], // M value output
36 | writeM, // Write to M?
37 | addressM[15], // Address in data memory (of M)
38 | pc[15]; // address of next instruction
39 |
40 | PARTS:
41 |
42 | // flag for ARegister
43 | Not(in=instruction[15], out=isA);
44 | Not(in=isA, out=isC);
45 | And(a=isC, b=instruction[5], out=ALUtoA);
46 |
47 | // Mux previous ARegister
48 | Mux16(a=ALUout,b=instruction,sel=isA,out=outMu);
49 |
50 | // ARegister
51 | Or(a=ALUtoA,b=isA,out=loadA);
52 | ARegister(in=outMu,load=loadA,out=A,out=out);
53 |
54 | // Define mnemonic(A or M)
55 | Mux16(a=A,b=inM,sel=instruction[12],out=AM);
56 |
57 | // DRegister
58 | And(a=isC, b=instruction[4], out=loadD);
59 | DRegister(in=outMu,load=loadD,out=D);
60 |
61 | // ALU
62 | ALU(x=D,y=AM,zx=instruction[11],nx=instruction[10],zy=instruction[9],ny=instruction[8],f=instruction[7],no=instruction[6],out=ALUout,zr=zr,ng=ng);
63 |
64 | // outM. not output directly from ALU,because of internal pin
65 | Or16(a=false,b=ALUout,out=outM);
66 |
67 | // writeM
68 | And(a=isC,b=instruction[3],out=writeM);
69 |
70 | // addressM
71 | Or16(a=false,b=A,out[0..14]=addressM);
72 |
73 | // PC
74 | // Calc isPositive
75 | Not(in=zr,out=nZr);
76 | Not(in=ng,out=nNg);
77 | And(a=nZr,b=nNg,out=isPositive);
78 | // JGT
79 | And(a=isPositive,b=instruction[0],out=JGT);
80 | // JEQ
81 | And(a=zr,b=instruction[1],out=JEQ);
82 | // JLT
83 | And(a=ng,b=instruction[2],out=JLT);
84 | // loadPc = JGT || JLT || JEQ
85 | Or(a=JGT,b=JLT,out=JNE);
86 | Or(a=JNE,b=JEQ,out=isJump);
87 | And(a=isC,b=isJump,out=loadPc);
88 | PC(in=A,load=loadPc,inc=true,reset=reset,out[0..14]=pc);
89 |
90 | }
--------------------------------------------------------------------------------
/hardware/computer/Computer.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/Computer.hdl
5 |
6 | /**
7 | * The HACK computer, including CPU, ROM and RAM.
8 | * When reset is 0, the program stored in the computer's ROM executes.
9 | * When reset is 1, the execution of the program restarts.
10 | * Thus, to start a program's execution, reset must be pushed "up" (1)
11 | * and "down" (0). From this point onward the user is at the mercy of
12 | * the software. In particular, depending on the program's code, the
13 | * screen may show some output and the user may be able to interact
14 | * with the computer via the keyboard.
15 | */
16 |
17 | CHIP Computer {
18 |
19 | IN reset;
20 | PARTS:
21 | ROM32K(address=pc,out=instruction);
22 | CPU(inM=inM,instruction=instruction,reset=reset,outM=outM,writeM=writeM,addressM=addressM,pc=pc);
23 | Memory(in=outM,load=writeM,address=addressM,out=inM);
24 | }
25 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerAdd-external.cmp:
--------------------------------------------------------------------------------
1 | | time |reset|RAM16K[0]|RAM16K[1]|RAM16K[2]|
2 | | 0 | 0 | 0 | 0 | 0 |
3 | | 1 | 0 | 0 | 0 | 0 |
4 | | 2 | 0 | 0 | 0 | 0 |
5 | | 3 | 0 | 0 | 0 | 0 |
6 | | 4 | 0 | 0 | 0 | 0 |
7 | | 5 | 0 | 0 | 0 | 0 |
8 | | 6 | 0 | 5 | 0 | 0 |
9 | | 7 | 1 | 0 | 0 | 0 |
10 | | 8 | 0 | 0 | 0 | 0 |
11 | | 9 | 0 | 0 | 0 | 0 |
12 | | 10 | 0 | 0 | 0 | 0 |
13 | | 11 | 0 | 0 | 0 | 0 |
14 | | 12 | 0 | 0 | 0 | 0 |
15 | | 13 | 0 | 5 | 0 | 0 |
16 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerAdd-external.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/ComputerAdd-external.tst
5 |
6 | load Computer.hdl,
7 | output-file ComputerAdd-external.out,
8 | compare-to ComputerAdd-external.cmp,
9 | output-list time%S1.4.1 reset%B2.1.2 RAM16K[0]%D1.7.1 RAM16K[1]%D1.7.1 RAM16K[2]%D1.7.1;
10 |
11 | // Load a program written in the Hack machine language.
12 | // The program adds the two constants 2 and 3 and writes the result in RAM[0].
13 | ROM32K load Add.hack,
14 | output;
15 |
16 | // First run (at the beginning PC=0)
17 | repeat 6 {
18 | tick, tock, output;
19 | }
20 |
21 | // Reset the PC
22 | set reset 1,
23 | set RAM16K[0] 0,
24 | tick, tock, output;
25 |
26 |
27 | // Second run, to check that the PC was reset correctly.
28 | set reset 0,
29 |
30 | repeat 6 {
31 | tick, tock, output;
32 | }
33 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerAdd.cmp:
--------------------------------------------------------------------------------
1 | | time |reset|ARegister|DRegister|PC[]|RAM16K[0]|RAM16K[1]|RAM16K[2]|
2 | | 0 | 0 | 0 | 0 | 0| 0 | 0 | 0 |
3 | | 1 | 0 | 2 | 0 | 1| 0 | 0 | 0 |
4 | | 2 | 0 | 2 | 2 | 2| 0 | 0 | 0 |
5 | | 3 | 0 | 3 | 2 | 3| 0 | 0 | 0 |
6 | | 4 | 0 | 3 | 5 | 4| 0 | 0 | 0 |
7 | | 5 | 0 | 0 | 5 | 5| 0 | 0 | 0 |
8 | | 6 | 0 | 0 | 5 | 6| 5 | 0 | 0 |
9 | | 7 | 1 | 0 | 5 | 0| 0 | 0 | 0 |
10 | | 8 | 0 | 2 | 5 | 1| 0 | 0 | 0 |
11 | | 9 | 0 | 2 | 2 | 2| 0 | 0 | 0 |
12 | | 10 | 0 | 3 | 2 | 3| 0 | 0 | 0 |
13 | | 11 | 0 | 3 | 5 | 4| 0 | 0 | 0 |
14 | | 12 | 0 | 0 | 5 | 5| 0 | 0 | 0 |
15 | | 13 | 0 | 0 | 5 | 6| 5 | 0 | 0 |
16 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerAdd.out:
--------------------------------------------------------------------------------
1 | | time |reset|ARegister|DRegister|PC[]|RAM16K[0]|RAM16K[1]|RAM16K[2]|
2 | | 0 | 0 | 0 | 0 | 0| 0 | 0 | 0 |
3 | | 1 | 0 | 2 | 0 | 1| 0 | 0 | 0 |
4 | | 2 | 0 | 2 | 2 | 2| 0 | 0 | 0 |
5 | | 3 | 0 | 3 | 2 | 3| 0 | 0 | 0 |
6 | | 4 | 0 | 3 | 5 | 4| 0 | 0 | 0 |
7 | | 5 | 0 | 0 | 5 | 5| 0 | 0 | 0 |
8 | | 6 | 0 | 0 | 5 | 6| 5 | 0 | 0 |
9 | | 7 | 1 | 0 | 5 | 0| 0 | 0 | 0 |
10 | | 8 | 0 | 2 | 5 | 1| 0 | 0 | 0 |
11 | | 9 | 0 | 2 | 2 | 2| 0 | 0 | 0 |
12 | | 10 | 0 | 3 | 2 | 3| 0 | 0 | 0 |
13 | | 11 | 0 | 3 | 5 | 4| 0 | 0 | 0 |
14 | | 12 | 0 | 0 | 5 | 5| 0 | 0 | 0 |
15 | | 13 | 0 | 0 | 5 | 6| 5 | 0 | 0 |
16 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerAdd.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/ComputerAdd.tst
5 |
6 | load Computer.hdl,
7 | output-file ComputerAdd.out,
8 | compare-to ComputerAdd.cmp,
9 | output-list time%S1.4.1 reset%B2.1.2 ARegister[0]%D1.7.1 DRegister[0]%D1.7.1 PC[]%D0.4.0 RAM16K[0]%D1.7.1 RAM16K[1]%D1.7.1 RAM16K[2]%D1.7.1;
10 |
11 | // Load a program written in the Hack machine language.
12 | // The program adds the two constants 2 and 3 and writes the result in RAM[0].
13 | ROM32K load Add.hack,
14 | output;
15 |
16 | // First run (at the beginning PC=0)
17 | repeat 6 {
18 | tick, tock, output;
19 | }
20 |
21 | // Reset the PC
22 | set reset 1,
23 | set RAM16K[0] 0,
24 | tick, tock, output;
25 |
26 |
27 | // Second run, to check that the PC was reset correctly.
28 | set reset 0,
29 |
30 | repeat 6 {
31 | tick, tock, output;
32 | }
33 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerMax-external.cmp:
--------------------------------------------------------------------------------
1 | | time |reset|RAM16K[0]|RAM16K[1]|RAM16K[2]|
2 | | 0 | 0 | 3 | 5 | 0 |
3 | | 1 | 0 | 3 | 5 | 0 |
4 | | 2 | 0 | 3 | 5 | 0 |
5 | | 3 | 0 | 3 | 5 | 0 |
6 | | 4 | 0 | 3 | 5 | 0 |
7 | | 5 | 0 | 3 | 5 | 0 |
8 | | 6 | 0 | 3 | 5 | 0 |
9 | | 7 | 0 | 3 | 5 | 0 |
10 | | 8 | 0 | 3 | 5 | 0 |
11 | | 9 | 0 | 3 | 5 | 0 |
12 | | 10 | 0 | 3 | 5 | 0 |
13 | | 11 | 0 | 3 | 5 | 0 |
14 | | 12 | 0 | 3 | 5 | 5 |
15 | | 13 | 0 | 3 | 5 | 5 |
16 | | 14 | 0 | 3 | 5 | 5 |
17 | | 15 | 1 | 3 | 5 | 5 |
18 | | 15 | 0 | 23456 | 12345 | 5 |
19 | | 16 | 0 | 23456 | 12345 | 5 |
20 | | 17 | 0 | 23456 | 12345 | 5 |
21 | | 18 | 0 | 23456 | 12345 | 5 |
22 | | 19 | 0 | 23456 | 12345 | 5 |
23 | | 20 | 0 | 23456 | 12345 | 5 |
24 | | 21 | 0 | 23456 | 12345 | 5 |
25 | | 22 | 0 | 23456 | 12345 | 5 |
26 | | 23 | 0 | 23456 | 12345 | 5 |
27 | | 24 | 0 | 23456 | 12345 | 5 |
28 | | 25 | 0 | 23456 | 12345 | 23456 |
29 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerMax-external.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/ComputerMax-external.tst
5 |
6 | load Computer.hdl,
7 | output-file ComputerMax-external.out,
8 | compare-to ComputerMax-external.cmp,
9 | output-list time%S1.4.1 reset%B2.1.2 RAM16K[0]%D1.7.1 RAM16K[1]%D1.7.1 RAM16K[2]%D1.7.1;
10 |
11 | // Load a program written in the Hack machine language.
12 | // The program computes the maximum of RAM[0] and RAM[1]
13 | // and writes the result in RAM[2].
14 | ROM32K load Max.hack,
15 |
16 | // first run: compute max(3,5)
17 | set RAM16K[0] 3,
18 | set RAM16K[1] 5,
19 | output;
20 |
21 | repeat 14 {
22 | tick, tock, output;
23 | }
24 |
25 | // reset the PC
26 | set reset 1,
27 | tick, tock, output;
28 |
29 | // second run: compute max(23456,12345)
30 | set reset 0,
31 | set RAM16K[0] 23456,
32 | set RAM16K[1] 12345,
33 | output;
34 |
35 | // The run on these inputs needs less cycles (different branching)
36 | repeat 10 {
37 | tick, tock, output;
38 | }
39 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerMax.cmp:
--------------------------------------------------------------------------------
1 | | time |reset|ARegister|DRegister|PC[]|RAM16K[0]|RAM16K[1]|RAM16K[2]|
2 | | 0 | 0 | 0 | 0 | 0| 3 | 5 | 0 |
3 | | 1 | 0 | 0 | 0 | 1| 3 | 5 | 0 |
4 | | 2 | 0 | 0 | 3 | 2| 3 | 5 | 0 |
5 | | 3 | 0 | 1 | 3 | 3| 3 | 5 | 0 |
6 | | 4 | 0 | 1 | -2 | 4| 3 | 5 | 0 |
7 | | 5 | 0 | 10 | -2 | 5| 3 | 5 | 0 |
8 | | 6 | 0 | 10 | -2 | 6| 3 | 5 | 0 |
9 | | 7 | 0 | 1 | -2 | 7| 3 | 5 | 0 |
10 | | 8 | 0 | 1 | 5 | 8| 3 | 5 | 0 |
11 | | 9 | 0 | 12 | 5 | 9| 3 | 5 | 0 |
12 | | 10 | 0 | 12 | 5 | 12| 3 | 5 | 0 |
13 | | 11 | 0 | 2 | 5 | 13| 3 | 5 | 0 |
14 | | 12 | 0 | 2 | 5 | 14| 3 | 5 | 5 |
15 | | 13 | 0 | 14 | 5 | 15| 3 | 5 | 5 |
16 | | 14 | 0 | 14 | 5 | 14| 3 | 5 | 5 |
17 | | 15 | 1 | 14 | 5 | 0| 3 | 5 | 5 |
18 | | 15 | 0 | 14 | 5 | 0| 23456 | 12345 | 5 |
19 | | 16 | 0 | 0 | 5 | 1| 23456 | 12345 | 5 |
20 | | 17 | 0 | 0 | 23456 | 2| 23456 | 12345 | 5 |
21 | | 18 | 0 | 1 | 23456 | 3| 23456 | 12345 | 5 |
22 | | 19 | 0 | 1 | 11111 | 4| 23456 | 12345 | 5 |
23 | | 20 | 0 | 10 | 11111 | 5| 23456 | 12345 | 5 |
24 | | 21 | 0 | 10 | 11111 | 10| 23456 | 12345 | 5 |
25 | | 22 | 0 | 0 | 11111 | 11| 23456 | 12345 | 5 |
26 | | 23 | 0 | 0 | 23456 | 12| 23456 | 12345 | 5 |
27 | | 24 | 0 | 2 | 23456 | 13| 23456 | 12345 | 5 |
28 | | 25 | 0 | 2 | 23456 | 14| 23456 | 12345 | 23456 |
29 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerMax.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/ComputerMax.tst
5 |
6 | load Computer.hdl,
7 | output-file ComputerMax.out,
8 | compare-to ComputerMax.cmp,
9 | output-list time%S1.4.1 reset%B2.1.2 ARegister[]%D1.7.1 DRegister[]%D1.7.1 PC[]%D0.4.0 RAM16K[0]%D1.7.1 RAM16K[1]%D1.7.1 RAM16K[2]%D1.7.1;
10 |
11 | // Load a program written in the Hack machine language.
12 | // The program computes the maximum of RAM[0] and RAM[1]
13 | // and writes the result in RAM[2].
14 |
15 | ROM32K load Max.hack,
16 |
17 | // first run: compute max(3,5)
18 | set RAM16K[0] 3,
19 | set RAM16K[1] 5,
20 | output;
21 |
22 | repeat 14 {
23 | tick, tock, output;
24 | }
25 |
26 | // reset the PC
27 | set reset 1,
28 | tick, tock, output;
29 |
30 | // second run: compute max(23456,12345)
31 | set reset 0,
32 | set RAM16K[0] 23456,
33 | set RAM16K[1] 12345,
34 | output;
35 |
36 | // The run on these inputs needs less cycles (different branching)
37 | repeat 10 {
38 | tick, tock, output;
39 | }
40 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerRect-external.cmp:
--------------------------------------------------------------------------------
1 | | time |
2 | | 0 |
3 | | 1 |
4 | | 2 |
5 | | 3 |
6 | | 4 |
7 | | 5 |
8 | | 6 |
9 | | 7 |
10 | | 8 |
11 | | 9 |
12 | | 10 |
13 | | 11 |
14 | | 12 |
15 | | 13 |
16 | | 14 |
17 | | 15 |
18 | | 16 |
19 | | 17 |
20 | | 18 |
21 | | 19 |
22 | | 20 |
23 | | 21 |
24 | | 22 |
25 | | 23 |
26 | | 24 |
27 | | 25 |
28 | | 26 |
29 | | 27 |
30 | | 28 |
31 | | 29 |
32 | | 30 |
33 | | 31 |
34 | | 32 |
35 | | 33 |
36 | | 34 |
37 | | 35 |
38 | | 36 |
39 | | 37 |
40 | | 38 |
41 | | 39 |
42 | | 40 |
43 | | 41 |
44 | | 42 |
45 | | 43 |
46 | | 44 |
47 | | 45 |
48 | | 46 |
49 | | 47 |
50 | | 48 |
51 | | 49 |
52 | | 50 |
53 | | 51 |
54 | | 52 |
55 | | 53 |
56 | | 54 |
57 | | 55 |
58 | | 56 |
59 | | 57 |
60 | | 58 |
61 | | 59 |
62 | | 60 |
63 | | 61 |
64 | | 62 |
65 | | 63 |
66 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerRect-external.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/ComputerRect-external.tst
5 |
6 | load Computer.hdl,
7 | output-file ComputerRect-external.out,
8 | compare-to ComputerRect-external.cmp,
9 | output-list time%S1.4.1;
10 |
11 | // Load a program written in the Hack machine language.
12 | // The program draws a rectangle of width 16 pixels and
13 | // length RAM[0] at the top left of the screen.
14 | ROM32K load Rect.hack,
15 |
16 | echo "Before you run this script, select the 'Screen' option from the 'View' menu";
17 |
18 | echo "A small rectangle should be drawn at the top left of the screen (the 'Screen' option of the 'View' menu should be selected.)";
19 |
20 | // draw a rectangle 16 pixels wide and 4 pixels long
21 | set RAM16K[0] 4,
22 | output;
23 |
24 | repeat 63 {
25 | tick, tock, output;
26 | }
27 |
--------------------------------------------------------------------------------
/hardware/computer/ComputerRect.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/ComputerRect.tst
5 |
6 | load Computer.hdl,
7 | output-file ComputerRect.out,
8 | compare-to ComputerRect.cmp,
9 | output-list time%S1.4.1 ARegister[]%D1.7.1 DRegister[]%D1.7.1 PC[]%D0.4.0 RAM16K[0]%D1.7.1 RAM16K[1]%D1.7.1 RAM16K[2]%D1.7.1;
10 |
11 | // Load a program written in the Hack machine language.
12 | // The program draws a rectangle of width 16 pixels and
13 | // length RAM[0] at the top left of the screen.
14 | ROM32K load Rect.hack,
15 |
16 | echo "Before you run this script, select the 'Screen' option from the 'View' menu";
17 |
18 | echo "A small rectangle should be drawn at the top left of the screen (the 'Screen' option of the 'View' menu should be selected.)";
19 |
20 | // Draws a rectangle 16 pixels wide and 4 pixels long
21 | set RAM16K[0] 4,
22 | output;
23 |
24 | repeat 63 {
25 | tick, tock, output;
26 | }
27 |
--------------------------------------------------------------------------------
/hardware/computer/Max.hack:
--------------------------------------------------------------------------------
1 | 0000000000000000
2 | 1111110000010000
3 | 0000000000000001
4 | 1111010011010000
5 | 0000000000001010
6 | 1110001100000001
7 | 0000000000000001
8 | 1111110000010000
9 | 0000000000001100
10 | 1110101010000111
11 | 0000000000000000
12 | 1111110000010000
13 | 0000000000000010
14 | 1110001100001000
15 | 0000000000001110
16 | 1110101010000111
17 |
--------------------------------------------------------------------------------
/hardware/computer/Memory.cmp:
--------------------------------------------------------------------------------
1 | | in |load | address | out |
2 | | 12345 | 1 | 010000000000000 | 0 |
3 | | 12345 | 1 | 010000000000000 | 12345 |
4 | | 12345 | 1 | 100000000000000 | 0 |
5 | | 12345 | 1 | 100000000000000 | 12345 |
6 | | -1 | 1 | 000000000000000 | 0 |
7 | | -1 | 1 | 000000000000000 | -1 |
8 | | 9999 | 0 | 000000000000000 | -1 |
9 | | 9999 | 0 | 000000000000000 | -1 |
10 | | 9999 | 0 | 010000000000000 | 12345 |
11 | | 9999 | 0 | 100000000000000 | 12345 |
12 | | 12345 | 1 | 000000000000000 | -1 |
13 | | 12345 | 1 | 000000000000000 | 12345 |
14 | | 12345 | 1 | 100000000000000 | 12345 |
15 | | 12345 | 1 | 100000000000000 | 12345 |
16 | | 2222 | 1 | 010000000000000 | 12345 |
17 | | 2222 | 1 | 010000000000000 | 2222 |
18 | | 9999 | 0 | 010000000000000 | 2222 |
19 | | 9999 | 0 | 010000000000000 | 2222 |
20 | | 9999 | 0 | 000000000000000 | 12345 |
21 | | 9999 | 0 | 100000000000000 | 12345 |
22 | | 9999 | 0 | 000000000000001 | 0 |
23 | | 9999 | 0 | 000000000000010 | 0 |
24 | | 9999 | 0 | 000000000000100 | 0 |
25 | | 9999 | 0 | 000000000001000 | 0 |
26 | | 9999 | 0 | 000000000010000 | 0 |
27 | | 9999 | 0 | 000000000100000 | 0 |
28 | | 9999 | 0 | 000000001000000 | 0 |
29 | | 9999 | 0 | 000000010000000 | 0 |
30 | | 9999 | 0 | 000000100000000 | 0 |
31 | | 9999 | 0 | 000001000000000 | 0 |
32 | | 9999 | 0 | 000010000000000 | 0 |
33 | | 9999 | 0 | 000100000000000 | 0 |
34 | | 9999 | 0 | 001000000000000 | 0 |
35 | | 9999 | 0 | 010000000000000 | 2222 |
36 | | 1234 | 1 | 001001000110100 | 0 |
37 | | 1234 | 1 | 001001000110100 | 1234 |
38 | | 1234 | 0 | 010001000110100 | 0 |
39 | | 1234 | 0 | 110001000110100 | 0 |
40 | | 2345 | 1 | 010001101000101 | 0 |
41 | | 2345 | 1 | 010001101000101 | 2345 |
42 | | 2345 | 0 | 000001101000101 | 0 |
43 | | 2345 | 0 | 100001101000101 | 0 |
44 | | 0 | 1 | 100000000000000 | 12345 |
45 | | 0 | 1 | 100000000000000 | 0 |
46 | | 0 | 1 | 110000000000000 | 75 |
47 | | 12345 | 1 | 000111111001111 | 0 |
48 | | 12345 | 1 | 000111111001111 | 12345 |
49 | | 12345 | 1 | 010111111001111 | 0 |
50 | | 12345 | 1 | 010111111001111 | 12345 |
51 | | -1 | 1 | 100111111001111 | -1 |
52 | | -1 | 1 | 101000001001111 | -1 |
53 | | -1 | 1 | 000111111001111 | 12345 |
54 | | -1 | 1 | 010111111001111 | 12345 |
55 | | -1 | 0 | 100111111001110 | 0 |
56 | | -1 | 0 | 100111111001101 | 0 |
57 | | -1 | 0 | 100111111001011 | 0 |
58 | | -1 | 0 | 100111111000111 | 0 |
59 | | -1 | 0 | 100111111011111 | 0 |
60 | | -1 | 0 | 100111111101111 | 0 |
61 | | -1 | 0 | 100111110001111 | 0 |
62 | | -1 | 0 | 100111101001111 | 0 |
63 | | -1 | 0 | 100111011001111 | 0 |
64 | | -1 | 0 | 100110111001111 | 0 |
65 | | -1 | 0 | 100101111001111 | 0 |
66 | | -1 | 0 | 100011111001111 | 0 |
67 | | -1 | 0 | 101111111001111 | 0 |
68 | | -1 | 0 | 110000000000000 | 89 |
69 |
--------------------------------------------------------------------------------
/hardware/computer/Memory.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/05/Memory.hdl
5 |
6 | /**
7 | * The complete address space of the Hack computer's memory,
8 | * including RAM and memory-mapped I/O.
9 | * The chip facilitates read and write operations, as follows:
10 | * Read: out(t) = Memory[address(t)](t)
11 | * Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
12 | * In words: the chip always outputs the value stored at the memory
13 | * location specified by address. If load==1, the in value is loaded
14 | * into the memory location specified by address. This value becomes
15 | * available through the out output from the next time step onward.
16 | * Address space rules:
17 | * Only the upper 16K+8K+1 words of the Memory chip are used.
18 | * Access to address>0x6000 is invalid. Access to any address in
19 | * the range 0x4000-0x5FFF results in accessing the screen memory
20 | * map. Access to address 0x6000 results in accessing the keyboard
21 | * memory map. The behavior in these addresses is described in the
22 | * Screen and Keyboard chip specifications given in the book.
23 | */
24 |
25 | CHIP Memory {
26 | IN in[16], load, address[15];
27 | OUT out[16];
28 |
29 | PARTS:
30 | DMux(in=load,sel=address[14],a=lr,b=lsk);
31 | RAM16K(in=in,load=lr,address=address[0..13],out=o1);
32 |
33 | DMux(in=lsk,sel=address[13],a=ls,b=lk);
34 |
35 | Screen(in=in,load=ls,address=address[0..12],out=o2);
36 | Keyboard(out=o3);
37 | Mux4Way16(a=o1, b=o1, c=o2, d=o3,sel=address[13..14],out=out);
38 | }
--------------------------------------------------------------------------------
/hardware/computer/Memory.out:
--------------------------------------------------------------------------------
1 | | in |load | address | out |
2 | | 12345 | 1 | 010000000000000 | 0 |
3 | | 12345 | 1 | 010000000000000 | 12345 |
4 | | 12345 | 1 | 100000000000000 | 0 |
5 | | 12345 | 1 | 100000000000000 | 12345 |
6 | | -1 | 1 | 000000000000000 | 0 |
7 | | -1 | 1 | 000000000000000 | -1 |
8 | | 9999 | 0 | 000000000000000 | -1 |
9 | | 9999 | 0 | 000000000000000 | -1 |
10 | | 9999 | 0 | 010000000000000 | 12345 |
11 | | 9999 | 0 | 100000000000000 | 12345 |
12 | | 12345 | 1 | 000000000000000 | -1 |
13 | | 12345 | 1 | 000000000000000 | 12345 |
14 | | 12345 | 1 | 100000000000000 | 12345 |
15 | | 12345 | 1 | 100000000000000 | 12345 |
16 | | 2222 | 1 | 010000000000000 | 12345 |
17 | | 2222 | 1 | 010000000000000 | 2222 |
18 | | 9999 | 0 | 010000000000000 | 2222 |
19 | | 9999 | 0 | 010000000000000 | 2222 |
20 | | 9999 | 0 | 000000000000000 | 12345 |
21 | | 9999 | 0 | 100000000000000 | 12345 |
22 | | 9999 | 0 | 000000000000001 | 0 |
23 | | 9999 | 0 | 000000000000010 | 0 |
24 | | 9999 | 0 | 000000000000100 | 0 |
25 | | 9999 | 0 | 000000000001000 | 0 |
26 | | 9999 | 0 | 000000000010000 | 0 |
27 | | 9999 | 0 | 000000000100000 | 0 |
28 | | 9999 | 0 | 000000001000000 | 0 |
29 | | 9999 | 0 | 000000010000000 | 0 |
30 | | 9999 | 0 | 000000100000000 | 0 |
31 | | 9999 | 0 | 000001000000000 | 0 |
32 | | 9999 | 0 | 000010000000000 | 0 |
33 | | 9999 | 0 | 000100000000000 | 0 |
34 | | 9999 | 0 | 001000000000000 | 0 |
35 | | 9999 | 0 | 010000000000000 | 2222 |
36 | | 1234 | 1 | 001001000110100 | 0 |
37 | | 1234 | 1 | 001001000110100 | 1234 |
38 | | 1234 | 0 | 010001000110100 | 0 |
39 | | 1234 | 0 | 110001000110100 | 0 |
40 | | 2345 | 1 | 010001101000101 | 0 |
41 | | 2345 | 1 | 010001101000101 | 2345 |
42 | | 2345 | 0 | 000001101000101 | 0 |
43 | | 2345 | 0 | 100001101000101 | 0 |
44 | | 0 | 1 | 100000000000000 | 12345 |
45 | | 0 | 1 | 100000000000000 | 0 |
46 | | 0 | 1 | 110000000000000 | 75 |
47 | | 12345 | 1 | 000111111001111 | 0 |
48 | | 12345 | 1 | 000111111001111 | 12345 |
49 | | 12345 | 1 | 010111111001111 | 0 |
50 | | 12345 | 1 | 010111111001111 | 12345 |
51 | | -1 | 1 | 100111111001111 | -1 |
52 | | -1 | 1 | 101000001001111 | -1 |
53 | | -1 | 1 | 000111111001111 | 12345 |
54 | | -1 | 1 | 010111111001111 | 12345 |
55 | | -1 | 0 | 100111111001110 | 0 |
56 | | -1 | 0 | 100111111001101 | 0 |
57 | | -1 | 0 | 100111111001011 | 0 |
58 | | -1 | 0 | 100111111000111 | 0 |
59 | | -1 | 0 | 100111111011111 | 0 |
60 | | -1 | 0 | 100111111101111 | 0 |
61 | | -1 | 0 | 100111110001111 | 0 |
62 | | -1 | 0 | 100111101001111 | 0 |
63 | | -1 | 0 | 100111011001111 | 0 |
64 | | -1 | 0 | 100110111001111 | 0 |
65 | | -1 | 0 | 100101111001111 | 0 |
66 | | -1 | 0 | 100011111001111 | 0 |
67 | | -1 | 0 | 101111111001111 | 0 |
68 | | -1 | 0 | 110000000000000 | 89 |
69 |
--------------------------------------------------------------------------------
/hardware/computer/Rect.hack:
--------------------------------------------------------------------------------
1 | 0000000000000000
2 | 1111110000010000
3 | 0000000000010111
4 | 1110001100000110
5 | 0000000000010000
6 | 1110001100001000
7 | 0100000000000000
8 | 1110110000010000
9 | 0000000000010001
10 | 1110001100001000
11 | 0000000000010001
12 | 1111110000100000
13 | 1110111010001000
14 | 0000000000010001
15 | 1111110000010000
16 | 0000000000100000
17 | 1110000010010000
18 | 0000000000010001
19 | 1110001100001000
20 | 0000000000010000
21 | 1111110010011000
22 | 0000000000001010
23 | 1110001100000001
24 | 0000000000010111
25 | 1110101010000111
26 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/Bit.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/a/Bit.hdl
5 |
6 | /**
7 | * 1-bit register:
8 | * If load[t] == 1 then out[t+1] = in[t]
9 | * else out does not change (out[t+1] = out[t])
10 | */
11 |
12 | CHIP Bit {
13 | IN in, load;
14 | OUT out;
15 | PARTS:
16 | Mux(a=fb,b=in,sel=load,out=out1);
17 | DFF(in=out1,out=out,out=fb);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/DFF16.hdl:
--------------------------------------------------------------------------------
1 |
2 |
3 | CHIP DFF16 {
4 | IN in[16];
5 | OUT out[16];
6 | PARTS:
7 | DFF(in=in[0],out=out[0]);
8 | DFF(in=in[1],out=out[1]);
9 | DFF(in=in[2],out=out[2]);
10 | DFF(in=in[3],out=out[3]);
11 | DFF(in=in[4],out=out[4]);
12 | DFF(in=in[5],out=out[5]);
13 | DFF(in=in[6],out=out[6]);
14 | DFF(in=in[7],out=out[7]);
15 | DFF(in=in[8],out=out[8]);
16 | DFF(in=in[9],out=out[9]);
17 | DFF(in=in[10],out=out[10]);
18 | DFF(in=in[11],out=out[11]);
19 | DFF(in=in[12],out=out[12]);
20 | DFF(in=in[13],out=out[13]);
21 | DFF(in=in[14],out=out[14]);
22 | DFF(in=in[15],out=out[15]);
23 | }
24 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/PC.cmp:
--------------------------------------------------------------------------------
1 | | time | in |reset|load | inc | out |
2 | | 0+ | 0 | 0 | 0 | 0 | 0 |
3 | | 1 | 0 | 0 | 0 | 0 | 0 |
4 | | 1+ | 0 | 0 | 0 | 1 | 0 |
5 | | 2 | 0 | 0 | 0 | 1 | 1 |
6 | | 2+ | -32123 | 0 | 0 | 1 | 1 |
7 | | 3 | -32123 | 0 | 0 | 1 | 2 |
8 | | 3+ | -32123 | 0 | 1 | 1 | 2 |
9 | | 4 | -32123 | 0 | 1 | 1 | -32123 |
10 | | 4+ | -32123 | 0 | 0 | 1 | -32123 |
11 | | 5 | -32123 | 0 | 0 | 1 | -32122 |
12 | | 5+ | -32123 | 0 | 0 | 1 | -32122 |
13 | | 6 | -32123 | 0 | 0 | 1 | -32121 |
14 | | 6+ | 12345 | 0 | 1 | 0 | -32121 |
15 | | 7 | 12345 | 0 | 1 | 0 | 12345 |
16 | | 7+ | 12345 | 1 | 1 | 0 | 12345 |
17 | | 8 | 12345 | 1 | 1 | 0 | 0 |
18 | | 8+ | 12345 | 0 | 1 | 1 | 0 |
19 | | 9 | 12345 | 0 | 1 | 1 | 12345 |
20 | | 9+ | 12345 | 1 | 1 | 1 | 12345 |
21 | | 10 | 12345 | 1 | 1 | 1 | 0 |
22 | | 10+ | 12345 | 0 | 0 | 1 | 0 |
23 | | 11 | 12345 | 0 | 0 | 1 | 1 |
24 | | 11+ | 12345 | 1 | 0 | 1 | 1 |
25 | | 12 | 12345 | 1 | 0 | 1 | 0 |
26 | | 12+ | 0 | 0 | 1 | 1 | 0 |
27 | | 13 | 0 | 0 | 1 | 1 | 0 |
28 | | 13+ | 0 | 0 | 0 | 1 | 0 |
29 | | 14 | 0 | 0 | 0 | 1 | 1 |
30 | | 14+ | 22222 | 1 | 0 | 0 | 1 |
31 | | 15 | 22222 | 1 | 0 | 0 | 0 |
32 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/PC.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/a/PC.hdl
5 |
6 | /**
7 | * A 16-bit counter with load and reset control bits.
8 | * if (reset[t] == 1) out[t+1] = 0
9 | * else if (load[t] == 1) out[t+1] = in[t]
10 | * else if (inc[t] == 1) out[t+1] = out[t] + 1 (integer addition)
11 | * else out[t+1] = out[t]
12 | */
13 |
14 | CHIP PC {
15 | IN in[16],load,inc,reset;
16 | OUT out[16];
17 |
18 | PARTS:
19 | Inc16(in=fb,out=o1);
20 | Mux16(a=fb,b=o1,sel=inc,out=o2);
21 | Mux16(a=o2,b=in,sel=load,out=o3);
22 | Mux16(a=o3,b=false,sel=reset,out=o4);
23 | DFF16(in=o4,out=out,out=fb);
24 | }
25 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/PC.out:
--------------------------------------------------------------------------------
1 | | time | in |reset|load | inc | out |
2 | | 0+ | 0 | 0 | 0 | 0 | 0 |
3 | | 1 | 0 | 0 | 0 | 0 | 0 |
4 | | 1+ | 0 | 0 | 0 | 1 | 0 |
5 | | 2 | 0 | 0 | 0 | 1 | 1 |
6 | | 2+ | -32123 | 0 | 0 | 1 | 1 |
7 | | 3 | -32123 | 0 | 0 | 1 | 2 |
8 | | 3+ | -32123 | 0 | 1 | 1 | 2 |
9 | | 4 | -32123 | 0 | 1 | 1 | -32123 |
10 | | 4+ | -32123 | 0 | 0 | 1 | -32123 |
11 | | 5 | -32123 | 0 | 0 | 1 | -32122 |
12 | | 5+ | -32123 | 0 | 0 | 1 | -32122 |
13 | | 6 | -32123 | 0 | 0 | 1 | -32121 |
14 | | 6+ | 12345 | 0 | 1 | 0 | -32121 |
15 | | 7 | 12345 | 0 | 1 | 0 | 12345 |
16 | | 7+ | 12345 | 1 | 1 | 0 | 12345 |
17 | | 8 | 12345 | 1 | 1 | 0 | 0 |
18 | | 8+ | 12345 | 0 | 1 | 1 | 0 |
19 | | 9 | 12345 | 0 | 1 | 1 | 12345 |
20 | | 9+ | 12345 | 1 | 1 | 1 | 12345 |
21 | | 10 | 12345 | 1 | 1 | 1 | 0 |
22 | | 10+ | 12345 | 0 | 0 | 1 | 0 |
23 | | 11 | 12345 | 0 | 0 | 1 | 1 |
24 | | 11+ | 12345 | 1 | 0 | 1 | 1 |
25 | | 12 | 12345 | 1 | 0 | 1 | 0 |
26 | | 12+ | 0 | 0 | 1 | 1 | 0 |
27 | | 13 | 0 | 0 | 1 | 1 | 0 |
28 | | 13+ | 0 | 0 | 0 | 1 | 0 |
29 | | 14 | 0 | 0 | 0 | 1 | 1 |
30 | | 14+ | 22222 | 1 | 0 | 0 | 1 |
31 | | 15 | 22222 | 1 | 0 | 0 | 0 |
32 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/PC.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/a/PC.tst
5 |
6 | load PC.hdl,
7 | output-file PC.out,
8 | compare-to PC.cmp,
9 | output-list time%S1.4.1 in%D1.6.1 reset%B2.1.2 load%B2.1.2 inc%B2.1.2 out%D1.6.1;
10 |
11 | set in 0,
12 | set reset 0,
13 | set load 0,
14 | set inc 0,
15 | tick,
16 | output;
17 |
18 | tock,
19 | output;
20 |
21 | set inc 1,
22 | tick,
23 | output;
24 |
25 | tock,
26 | output;
27 |
28 | set in -32123,
29 | tick,
30 | output;
31 |
32 | tock,
33 | output;
34 |
35 | set load 1,
36 | tick,
37 | output;
38 |
39 | tock,
40 | output;
41 |
42 | set load 0,
43 | tick,
44 | output;
45 |
46 | tock,
47 | output;
48 |
49 | tick,
50 | output;
51 |
52 | tock,
53 | output;
54 |
55 | set in 12345,
56 | set load 1,
57 | set inc 0,
58 | tick,
59 | output;
60 |
61 | tock,
62 | output;
63 |
64 | set reset 1,
65 | tick,
66 | output;
67 |
68 | tock,
69 | output;
70 |
71 | set reset 0,
72 | set inc 1,
73 | tick,
74 | output;
75 |
76 | tock,
77 | output;
78 |
79 | set reset 1,
80 | tick,
81 | output;
82 |
83 | tock,
84 | output;
85 |
86 | set reset 0,
87 | set load 0,
88 | tick,
89 | output;
90 |
91 | tock,
92 | output;
93 |
94 | set reset 1,
95 | tick,
96 | output;
97 |
98 | tock,
99 | output;
100 |
101 | set in 0,
102 | set reset 0,
103 | set load 1,
104 | tick,
105 | output;
106 |
107 | tock,
108 | output;
109 |
110 | set load 0,
111 | set inc 1,
112 | tick,
113 | output;
114 |
115 | tock,
116 | output;
117 |
118 | set in 22222,
119 | set reset 1,
120 | set inc 0,
121 | tick,
122 | output;
123 |
124 | tock,
125 | output;
126 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/RAM16K.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/b/RAM16K.hdl
5 |
6 | /**
7 | * Memory of 16K registers, each 16 bit-wide. Out holds the value
8 | * stored at the memory location specified by address. If load==1, then
9 | * the in value is loaded into the memory location specified by address
10 | * (the loaded value will be emitted to out from the next time step onward).
11 | */
12 |
13 | CHIP RAM16K {
14 | IN in[16], load, address[14];
15 | OUT out[16];
16 |
17 | PARTS:
18 | DMux4Way(in=load,sel=address[12..13],a=l1, b=l2, c=l3, d=l4);
19 | RAM4K(in=in,load=l1,address=address[0..11],out=o1);
20 | RAM4K(in=in,load=l2,address=address[0..11],out=o2);
21 | RAM4K(in=in,load=l3,address=address[0..11],out=o3);
22 | RAM4K(in=in,load=l4,address=address[0..11],out=o4);
23 | Mux4Way16(a=o1, b=o2, c=o3, d=o4,sel=address[12..13],out=out);
24 | }
--------------------------------------------------------------------------------
/hardware/sequential_circuit/RAM4K.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/b/RAM4K.hdl
5 |
6 | /**
7 | * Memory of 4K registers, each 16 bit-wide. Out holds the value
8 | * stored at the memory location specified by address. If load==1, then
9 | * the in value is loaded into the memory location specified by address
10 | * (the loaded value will be emitted to out from the next time step onward).
11 | */
12 |
13 | CHIP RAM4K {
14 | IN in[16], load, address[12];
15 | OUT out[16];
16 |
17 | PARTS:
18 | DMux8Way(in=load,sel=address[9..11],a=l1, b=l2, c=l3, d=l4, e=l5, f=l6, g=l7, h=l8);
19 | RAM512(in=in,load=l1,address=address[0..8],out=o1);
20 | RAM512(in=in,load=l2,address=address[0..8],out=o2);
21 | RAM512(in=in,load=l3,address=address[0..8],out=o3);
22 | RAM512(in=in,load=l4,address=address[0..8],out=o4);
23 | RAM512(in=in,load=l5,address=address[0..8],out=o5);
24 | RAM512(in=in,load=l6,address=address[0..8],out=o6);
25 | RAM512(in=in,load=l7,address=address[0..8],out=o7);
26 | RAM512(in=in,load=l8,address=address[0..8],out=o8);
27 | Mux8Way16(a=o1, b=o2, c=o3, d=o4, e=o5, f=o6, g=o7, h=o8,sel=address[9..11],out=out);
28 | }
--------------------------------------------------------------------------------
/hardware/sequential_circuit/RAM512.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of the materials accompanying the book
2 | // "The Elements of Computing Systems" by Nisan and Schocken,
3 | // MIT Press. Book site: www.idc.ac.il/tecs
4 | // File name: projects/03/b/RAM512.hdl
5 |
6 | /**
7 | * Memory of 512 registers, each 16 bit-wide. Out holds the value
8 | * stored at the memory location specified by address. If load==1, then
9 | * the in value is loaded into the memory location specified by address
10 | * (the loaded value will be emitted to out from the next time step onward).
11 | */
12 |
13 | CHIP RAM512 {
14 | IN in[16], load, address[9];
15 | OUT out[16];
16 |
17 | PARTS:
18 | // Put your code here:
19 | DMux8Way(in=load,sel=address[6..8],a=l1, b=l2, c=l3, d=l4, e=l5, f=l6, g=l7, h=l8);
20 | RAM64(in=in,load=l1,address=address[0..5],out=o1);
21 | RAM64(in=in,load=l2,address=address[0..5],out=o2);
22 | RAM64(in=in,load=l3,address=address[0..5],out=o3);
23 | RAM64(in=in,load=l4,address=address[0..5],out=o4);
24 | RAM64(in=in,load=l5,address=address[0..5],out=o5);
25 | RAM64(in=in,load=l6,address=address[0..5],out=o6);
26 | RAM64(in=in,load=l7,address=address[0..5],out=o7);
27 | RAM64(in=in,load=l8,address=address[0..5],out=o8);
28 | Mux8Way16(a=o1, b=o2, c=o3, d=o4, e=o5, f=o6, g=o7, h=o8,sel=address[6..8],out=out);
29 | }
--------------------------------------------------------------------------------
/hardware/sequential_circuit/RAM64.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/a/RAM64.hdl
5 |
6 | /**
7 | * Memory of 64 registers, each 16 bit-wide. Out holds the value
8 | * stored at the memory location specified by address. If load==1, then
9 | * the in value is loaded into the memory location specified by address
10 | * (the loaded value will be emitted to out from the next time step onward).
11 | */
12 |
13 | CHIP RAM64 {
14 | IN in[16], load, address[6];
15 | OUT out[16];
16 |
17 | PARTS:
18 | // Put your code here:
19 | DMux8Way(in=load,sel=address[3..5],a=l1, b=l2, c=l3, d=l4, e=l5, f=l6, g=l7, h=l8);
20 | RAM8(in=in,load=l1,address=address[0..2],out=o1);
21 | RAM8(in=in,load=l2,address=address[0..2],out=o2);
22 | RAM8(in=in,load=l3,address=address[0..2],out=o3);
23 | RAM8(in=in,load=l4,address=address[0..2],out=o4);
24 | RAM8(in=in,load=l5,address=address[0..2],out=o5);
25 | RAM8(in=in,load=l6,address=address[0..2],out=o6);
26 | RAM8(in=in,load=l7,address=address[0..2],out=o7);
27 | RAM8(in=in,load=l8,address=address[0..2],out=o8);
28 | Mux8Way16(a=o1, b=o2, c=o3, d=o4, e=o5, f=o6, g=o7, h=o8,sel=address[3..5],out=out);
29 | }
--------------------------------------------------------------------------------
/hardware/sequential_circuit/RAM8.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/a/RAM8.hdl
5 |
6 | /**
7 | * Memory of 8 registers, each 16 bit-wide. Out holds the value
8 | * stored at the memory location specified by address. If load==1, then
9 | * the in value is loaded into the memory location specified by address
10 | * (the loaded value will be emitted to out from the next time step onward).
11 | */
12 |
13 | CHIP RAM8 {
14 | IN in[16], load, address[3];
15 | OUT out[16];
16 |
17 | PARTS:
18 | DMux8Way(in=load,sel=address,a=l1, b=l2, c=l3, d=l4, e=l5, f=l6, g=l7, h=l8);
19 | Register(in=in,load=l1,out=o1);
20 | Register(in=in,load=l2,out=o2);
21 | Register(in=in,load=l3,out=o3);
22 | Register(in=in,load=l4,out=o4);
23 | Register(in=in,load=l5,out=o5);
24 | Register(in=in,load=l6,out=o6);
25 | Register(in=in,load=l7,out=o7);
26 | Register(in=in,load=l8,out=o8);
27 | Mux8Way16(a=o1, b=o2, c=o3, d=o4, e=o5, f=o6, g=o7, h=o8,sel=address,out=out);
28 | }
--------------------------------------------------------------------------------
/hardware/sequential_circuit/Register.hdl:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/03/a/Register.hdl
5 |
6 | /**
7 | * 16-bit register:
8 | * If load[t] == 1 then out[t+1] = in[t]
9 | * else out does not change
10 | */
11 |
12 | CHIP Register {
13 | IN in[16], load;
14 | OUT out[16];
15 |
16 | PARTS:
17 | // Put your code here:
18 | Bit(in=in[0],load=load,out=out[0]);
19 | Bit(in=in[1],load=load,out=out[1]);
20 | Bit(in=in[2],load=load,out=out[2]);
21 | Bit(in=in[3],load=load,out=out[3]);
22 | Bit(in=in[4],load=load,out=out[4]);
23 | Bit(in=in[5],load=load,out=out[5]);
24 | Bit(in=in[6],load=load,out=out[6]);
25 | Bit(in=in[7],load=load,out=out[7]);
26 | Bit(in=in[8],load=load,out=out[8]);
27 | Bit(in=in[9],load=load,out=out[9]);
28 | Bit(in=in[10],load=load,out=out[10]);
29 | Bit(in=in[11],load=load,out=out[11]);
30 | Bit(in=in[12],load=load,out=out[12]);
31 | Bit(in=in[13],load=load,out=out[13]);
32 | Bit(in=in[14],load=load,out=out[14]);
33 | Bit(in=in[15],load=load,out=out[15]);
34 | }
35 |
--------------------------------------------------------------------------------
/hardware/sequential_circuit/Register.out:
--------------------------------------------------------------------------------
1 | | time | in |load | out |
2 | | 0+ | 0 | 0 | 0 |
3 | | 1 | 0 | 0 | 0 |
4 | | 1+ | 0 | 1 | 0 |
5 | | 2 | 0 | 1 | 0 |
6 | | 2+ | -32123 | 0 | 0 |
7 | | 3 | -32123 | 0 | 0 |
8 | | 3+ | 11111 | 0 | 0 |
9 | | 4 | 11111 | 0 | 0 |
10 | | 4+ | -32123 | 1 | 0 |
11 | | 5 | -32123 | 1 | -32123 |
12 | | 5+ | -32123 | 1 | -32123 |
13 | | 6 | -32123 | 1 | -32123 |
14 | | 6+ | -32123 | 0 | -32123 |
15 | | 7 | -32123 | 0 | -32123 |
16 | | 7+ | 12345 | 1 | -32123 |
17 | | 8 | 12345 | 1 | 12345 |
18 | | 8+ | 0 | 0 | 12345 |
19 | | 9 | 0 | 0 | 12345 |
20 | | 9+ | 0 | 1 | 12345 |
21 | | 10 | 0 | 1 | 0 |
22 | | 10+ | 1 | 0 | 0 |
23 | | 11 | 1 | 0 | 0 |
24 |
--------------------------------------------------------------------------------
/jackcompiler/go.mod:
--------------------------------------------------------------------------------
1 | module jackcompiler
2 |
3 | go 1.16
4 |
--------------------------------------------------------------------------------
/jackcompiler/jack/Add/Main.jack:
--------------------------------------------------------------------------------
1 | class Main{
2 | function int add(int a, int b){
3 | var int sum;
4 | let sum = a + b;
5 | return sum;
6 | }
7 | function void main() {
8 | do Output.printInt(Main.add(Main.add(1,2),Main.add(3,4)));
9 | return;
10 | }
11 | }
--------------------------------------------------------------------------------
/jackcompiler/jack/Average/Main.jack:
--------------------------------------------------------------------------------
1 | class Main {
2 | function void main() {
3 | var Array a;
4 | var int length;
5 | var int i, sum;
6 |
7 | let length = Keyboard.readInt("How many numbers? ");
8 | let a = Array.new(length);
9 |
10 | let i = 0;
11 | while (i < length) {
12 | let a[i] = Keyboard.readInt("Enter a number: ");
13 | let sum = sum + a[i];
14 | let i = i + 1;
15 | }
16 |
17 | do Output.printString("The average is ");
18 | do Output.printInt(sum / length);
19 | return;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/jackcompiler/jack/ComplexArrays/Main.jack:
--------------------------------------------------------------------------------
1 | class Main {
2 |
3 | function void main() {
4 | var Array a, b, c;
5 |
6 | let a = Array.new(10);
7 | let b = Array.new(5);
8 | let c = Array.new(1);
9 |
10 | let a[3] = 2;
11 | let a[4] = 8;
12 | let a[5] = 4;
13 | let b[a[3]] = a[3] + 3;
14 | let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1];
15 | let c[0] = null;
16 | let c = c[0];
17 |
18 | do Output.printString("Test 1: expected result: 5; actual result: ");
19 | do Output.printInt(b[2]);
20 | do Output.println();
21 | do Output.printString("Test 2: expected result: 40; actual result: ");
22 | do Output.printInt(a[5]);
23 | do Output.println();
24 | do Output.printString("Test 3: expected result: 0; actual result: ");
25 | do Output.printInt(c);
26 | do Output.println();
27 |
28 | let c = null;
29 |
30 | if (c = null) {
31 | do Main.fill(a, 10);
32 | let c = a[3];
33 | let c[1] = 33;
34 | let c = a[7];
35 | let c[1] = 77;
36 | let b = a[3];
37 | let b[1] = b[1] + c[1];
38 | }
39 |
40 | do Output.printString("Test 4: expected result: 77; actual result: ");
41 | do Output.printInt(c[1]);
42 | do Output.println();
43 | do Output.printString("Test 5: expected result: 110; actual result: ");
44 | do Output.printInt(b[1]);
45 | do Output.println();
46 | return;
47 | }
48 |
49 | function int double(int a) {
50 | return a * 2;
51 | }
52 |
53 | function void fill(Array a, int size) {
54 | while (size > 0) {
55 | let size = size - 1;
56 | let a[size] = Array.new(3);
57 | }
58 | return;
59 | }
60 | }
--------------------------------------------------------------------------------
/jackcompiler/jack/ConsumptionTaxCalculator/ConsumptionTaxCalculator.jack:
--------------------------------------------------------------------------------
1 | class ConsumptionTaxCalculator {
2 |
3 | field int a;
4 |
5 | field ConsumptionTaxTwo ctt;
6 |
7 | constructor ConsumptionTaxCalculator new(int aTaxRate){
8 | let ctt=ConsumptionTaxTwo.new(aTaxRate);
9 | return this;
10 | }
11 |
12 | method int getTax(int num){
13 | return ctt.getTax(num);
14 | }
15 |
16 | method void printTaxRate(){
17 | do ctt.printTaxRate();
18 | return;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/jackcompiler/jack/ConsumptionTaxCalculator/ConsumptionTaxTwo.jack:
--------------------------------------------------------------------------------
1 | class ConsumptionTaxTwo {
2 |
3 | field int taxRate;
4 |
5 | constructor ConsumptionTaxTwo new(int aTaxRate){
6 | let taxRate = aTaxRate;
7 | do Output.printInt(getTax(100));
8 | do printTaxRate();
9 | return this;
10 | }
11 | method int getTax(int num){
12 | return num * taxRate;
13 | }
14 | method void printTaxRate(){
15 | do Output.printInt(taxRate);
16 | return ;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/jackcompiler/jack/ConsumptionTaxCalculator/Main.jack:
--------------------------------------------------------------------------------
1 | class Main{
2 | function void main() {
3 | var ConsumptionTaxCalculator ctc;
4 | let ctc = ConsumptionTaxCalculator.new(2);
5 | do Output.printInt(ctc.getTax(100));
6 | do Output.printInt(ctc.getTax(200));
7 | do ctc.printTaxRate();
8 | return;
9 | }
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/jackcompiler/jack/ConvertToBin/Main.jack:
--------------------------------------------------------------------------------
1 |
2 | class Main {
3 |
4 |
5 | function void main() {
6 | var int value;
7 | do Main.fillMemory(8001, 16, -1);
8 | let value = Memory.peek(8000);
9 | do Main.convert(value);
10 | return;
11 | }
12 | function void convert(int value) {
13 | var int mask, position;
14 | var boolean loop;
15 |
16 | let loop = true;
17 | while (loop) {
18 | let position = position + 1;
19 | let mask = Main.nextMask(mask);
20 |
21 | if (~(position > 16)) {
22 |
23 | if (~((value & mask) = 0)) {
24 | do Memory.poke(8000 + position, 1);
25 | }
26 | else {
27 | do Memory.poke(8000 + position, 0);
28 | }
29 | }
30 | else {
31 | let loop = false;
32 | }
33 | }
34 | return;
35 | }
36 | function int nextMask(int mask) {
37 | if (mask = 0) {
38 | return 1;
39 | }
40 | else {
41 | return mask * 2;
42 | }
43 | }
44 | function void fillMemory(int startAddress, int length, int value) {
45 | while (length > 0) {
46 | do Memory.poke(startAddress, value);
47 | let length = length - 1;
48 | let startAddress = startAddress + 1;
49 | }
50 | return;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/jackcompiler/jack/HelloWorld/Main.jack:
--------------------------------------------------------------------------------
1 | class Main {
2 | function void main() {
3 | do Output.printString("Hello,world");
4 | return;
5 | }
6 | }
--------------------------------------------------------------------------------
/jackcompiler/jack/Pong/Bat.jack:
--------------------------------------------------------------------------------
1 |
2 | class Bat {
3 |
4 | field int x, y;
5 | field int width, height;
6 | field int direction;
7 |
8 |
9 | constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) {
10 | let x = Ax;
11 | let y = Ay;
12 | let width = Awidth;
13 | let height = Aheight;
14 | let direction = 2;
15 | do show();
16 | return this;
17 | }
18 |
19 |
20 | method void dispose() {
21 | do Memory.deAlloc(this);
22 | return;
23 | }
24 |
25 |
26 | method void show() {
27 | do Screen.setColor(true);
28 | do draw();
29 | return;
30 | }
31 |
32 |
33 | method void hide() {
34 | do Screen.setColor(false);
35 | do draw();
36 | return;
37 | }
38 |
39 |
40 | method void draw() {
41 | do Screen.drawRectangle(x, y, x + width, y + height);
42 | return;
43 | }
44 |
45 |
46 | method void setDirection(int Adirection) {
47 | let direction = Adirection;
48 | return;
49 | }
50 |
51 |
52 | method int getLeft() {
53 | return x;
54 | }
55 |
56 |
57 | method int getRight() {
58 | return x + width;
59 | }
60 |
61 |
62 | method void setWidth(int Awidth) {
63 | do hide();
64 | let width = Awidth;
65 | do show();
66 | return;
67 | }
68 |
69 |
70 | method void move() {
71 | if (direction = 1) {
72 | let x = x - 4;
73 | if (x < 0) { let x = 0; }
74 | do Screen.setColor(false);
75 | do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height);
76 | do Screen.setColor(true);
77 | do Screen.drawRectangle(x, y, x + 3, y + height);
78 | }
79 | else {
80 | let x = x + 4;
81 | if ((x + width) > 511) { let x = 511 - width; }
82 | do Screen.setColor(false);
83 | do Screen.drawRectangle(x - 4, y, x - 1, y + height);
84 | do Screen.setColor(true);
85 | do Screen.drawRectangle((x + width) - 3, y, x + width, y + height);
86 | }
87 | return;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/jackcompiler/jack/Pong/Main.jack:
--------------------------------------------------------------------------------
1 |
2 | class Main {
3 | function void main() {
4 | var PongGame game;
5 | do PongGame.newInstance();
6 | let game = PongGame.getInstance();
7 | do game.run();
8 | do game.dispose();
9 | return;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/jackcompiler/jack/Pong/PongGame.jack:
--------------------------------------------------------------------------------
1 |
2 | class PongGame {
3 |
4 | static PongGame instance;
5 | field Bat bat;
6 | field Ball ball;
7 | field int wall;
8 | field boolean exit;
9 | field int score;
10 | field int lastWall;
11 |
12 |
13 | field int batWidth;
14 | constructor PongGame new() {
15 | do Screen.clearScreen();
16 | let batWidth = 50;
17 | let bat = Bat.new(230, 229, batWidth, 7);
18 | let ball = Ball.new(253, 222, 0, 511, 0, 229);
19 | do ball.setDestination(400,0);
20 | do Screen.drawRectangle(0, 238, 511, 240);
21 | do Output.moveCursor(22,0);
22 | do Output.printString("Score: 0");
23 |
24 | let exit = false;
25 | let score = 0;
26 | let wall = 0;
27 | let lastWall = 0;
28 |
29 | return this;
30 | }
31 |
32 |
33 | method void dispose() {
34 | do bat.dispose();
35 | do ball.dispose();
36 | do Memory.deAlloc(this);
37 | return;
38 | }
39 |
40 |
41 | function void newInstance() {
42 | let instance = PongGame.new();
43 | return;
44 | }
45 |
46 |
47 | function PongGame getInstance() {
48 | return instance;
49 | }
50 |
51 |
52 |
53 | method void run() {
54 | var char key;
55 |
56 | while (~exit) {
57 |
58 | while ((key = 0) & (~exit)) {
59 | let key = Keyboard.keyPressed();
60 | do bat.move();
61 | do moveBall();
62 | do Sys.wait(50);
63 | }
64 |
65 | if (key = 130) { do bat.setDirection(1); }
66 | else {
67 | if (key = 132) { do bat.setDirection(2); }
68 | else {
69 | if (key = 140) { let exit = true; }
70 | }
71 | }
72 |
73 |
74 | while ((~(key = 0)) & (~exit)) {
75 | let key = Keyboard.keyPressed();
76 | do bat.move();
77 | do moveBall();
78 | do Sys.wait(50);
79 | }
80 | }
81 |
82 | if (exit) {
83 | do Output.moveCursor(10,27);
84 | do Output.printString("Game Over");
85 | }
86 |
87 | return;
88 | }
89 |
90 |
91 | method void moveBall() {
92 | var int bouncingDirection, batLeft, batRight, ballLeft, ballRight;
93 |
94 | let wall = ball.move();
95 |
96 | if ((wall > 0) & (~(wall = lastWall))) {
97 | let lastWall = wall;
98 | let bouncingDirection = 0;
99 | let batLeft = bat.getLeft();
100 | let batRight = bat.getRight();
101 | let ballLeft = ball.getLeft();
102 | let ballRight = ball.getRight();
103 |
104 | if (wall = 4) {
105 | let exit = (batLeft > ballRight) | (batRight < ballLeft);
106 | if (~exit) {
107 | if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; }
108 | else {
109 | if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; }
110 | }
111 |
112 | let batWidth = batWidth - 2;
113 | do bat.setWidth(batWidth);
114 | let score = score + 1;
115 | do Output.moveCursor(22,7);
116 | do Output.printInt(score);
117 | }
118 | }
119 | do ball.bounce(bouncingDirection);
120 | }
121 | return;
122 | }
123 | }
--------------------------------------------------------------------------------
/jackcompiler/jack/Seven/Main.jack:
--------------------------------------------------------------------------------
1 |
2 | class Main {
3 | function void main() {
4 | do Output.printInt(1 + (2 * 3));
5 | return;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/jackcompiler/jack/SimpleArray/Main.jack:
--------------------------------------------------------------------------------
1 | class Main {
2 | function void main() {
3 | var Array a, b;
4 | let a = Array.new(10);
5 | let b = Array.new(5);
6 | let a[3] = 2;
7 | let a[4] = 8;
8 | let b[1] = a[4];
9 | do Output.printInt(b[1]);
10 | do Output.printInt(a[4]);
11 | return;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/jackcompiler/jack/SimpleIf/Main.jack:
--------------------------------------------------------------------------------
1 | class Main{
2 | function int getVal(int val){
3 | if(val < 10){
4 | return val * 10;
5 | }else{
6 | return val * 100;
7 | }
8 | }
9 | function void main() {
10 | do Output.printInt(Main.getVal(5));
11 | do Output.printInt(Main.getVal(100));
12 | return;
13 | }
14 | }
--------------------------------------------------------------------------------
/jackcompiler/jack/SimpleWhile/Main.jack:
--------------------------------------------------------------------------------
1 | class Main{
2 | function void printCount(){
3 | var int i;
4 | let i = 1;
5 | while(i < 11){
6 | do Output.printInt(i);
7 | let i = i + 1;
8 | }
9 | return;
10 | }
11 | function void main() {
12 | do Main.printCount();
13 | return;
14 | }
15 | }
--------------------------------------------------------------------------------
/jackcompiler/jack/Square/Main.jack:
--------------------------------------------------------------------------------
1 | class Main {
2 | function void main() {
3 | var SquareGame game;
4 | let game = SquareGame.new();
5 | do game.run();
6 | do game.dispose();
7 | return;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/jackcompiler/jack/Square/Square.jack:
--------------------------------------------------------------------------------
1 | class Square {
2 |
3 | field int x, y;
4 | field int size;
5 |
6 | constructor Square new(int Ax, int Ay, int Asize) {
7 | let x = Ax;
8 | let y = Ay;
9 | let size = Asize;
10 | do draw();
11 | return this;
12 | }
13 |
14 | method void dispose() {
15 | do Memory.deAlloc(this);
16 | return;
17 | }
18 |
19 | method void draw() {
20 | do Screen.setColor(true);
21 | do Screen.drawRectangle(x, y, x + size, y + size);
22 | return;
23 | }
24 |
25 |
26 | method void erase() {
27 | do Screen.setColor(false);
28 | do Screen.drawRectangle(x, y, x + size, y + size);
29 | return;
30 | }
31 |
32 | method void incSize() {
33 | if (((y + size) < 254) & ((x + size) < 510)) {
34 | do erase();
35 | let size = size + 2;
36 | do draw();
37 | }
38 | return;
39 | }
40 |
41 | method void decSize() {
42 | if (size > 2) {
43 | do erase();
44 | let size = size - 2;
45 | do draw();
46 | }
47 | return;
48 | }
49 |
50 | method void moveUp() {
51 | if (y > 1) {
52 | do Screen.setColor(false);
53 | do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
54 | let y = y - 2;
55 | do Screen.setColor(true);
56 | do Screen.drawRectangle(x, y, x + size, y + 1);
57 | }
58 | return;
59 | }
60 |
61 | method void moveDown() {
62 | if ((y + size) < 254) {
63 | do Screen.setColor(false);
64 | do Screen.drawRectangle(x, y, x + size, y + 1);
65 | let y = y + 2;
66 | do Screen.setColor(true);
67 | do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
68 | }
69 | return;
70 | }
71 |
72 | method void moveLeft() {
73 | if (x > 1) {
74 | do Screen.setColor(false);
75 | do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
76 | let x = x - 2;
77 | do Screen.setColor(true);
78 | do Screen.drawRectangle(x, y, x + 1, y + size);
79 | }
80 | return;
81 | }
82 |
83 | method void moveRight() {
84 | if ((x + size) < 510) {
85 | do Screen.setColor(false);
86 | do Screen.drawRectangle(x, y, x + 1, y + size);
87 | let x = x + 2;
88 | do Screen.setColor(true);
89 | do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
90 | }
91 | return;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/jackcompiler/jack/Square/SquareGame.jack:
--------------------------------------------------------------------------------
1 | class SquareGame {
2 | field Square square;
3 | field int direction;
4 |
5 | constructor SquareGame new() {
6 | let square = Square.new(0, 0, 30);
7 | let direction = 0;
8 | return this;
9 | }
10 | method void dispose() {
11 | do square.dispose();
12 | do Memory.deAlloc(this);
13 | return;
14 | }
15 |
16 | method void moveSquare() {
17 | if (direction = 1) { do square.moveUp(); }
18 | if (direction = 2) { do square.moveDown(); }
19 | if (direction = 3) { do square.moveLeft(); }
20 | if (direction = 4) { do square.moveRight(); }
21 | do Sys.wait(1);
22 | return;
23 | }
24 |
25 |
26 | method void run() {
27 | var char key;
28 | var boolean exit;
29 | let exit = false;
30 |
31 | while (~exit) {
32 | while (key = 0) {
33 | let key = Keyboard.keyPressed();
34 | do moveSquare();
35 | }
36 | if (key = 81) { let exit = true; }
37 | if (key = 90) { do square.decSize(); }
38 | if (key = 88) { do square.incSize(); }
39 | if (key = 131) { let direction = 1; }
40 | if (key = 133) { let direction = 2; }
41 | if (key = 130) { let direction = 3; }
42 | if (key = 132) { let direction = 4; }
43 | while (~(key = 0)) {
44 | let key = Keyboard.keyPressed();
45 | do moveSquare();
46 | }
47 | }
48 | return;
49 | }
50 | }
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/jackcompiler/jack/StaticTest/Main.jack:
--------------------------------------------------------------------------------
1 | class Main {
2 | function void main() {
3 | do StaticTest.printWord();
4 | return;
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/jackcompiler/jack/StaticTest/StaticTest.jack:
--------------------------------------------------------------------------------
1 | class StaticTest {
2 | static int number;
3 | constructor StaticTest new(){
4 | return this;
5 | }
6 | function void printWord() {
7 | let number = 111;
8 | do Output.printInt(number);
9 | return;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/jackcompiler/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "io/ioutil"
7 | "jackcompiler/ast"
8 | "jackcompiler/compilationengine"
9 | "jackcompiler/parser"
10 | "jackcompiler/symboltable"
11 | "jackcompiler/tokenizer"
12 | "jackcompiler/vmwriter"
13 | "os"
14 | "path/filepath"
15 | )
16 |
17 | func getJackFileListInDir(dirPath string) ([]string, error) {
18 | vmPathPattern := filepath.Join(dirPath, "*.jack")
19 | vmFileListInDir, err := filepath.Glob(vmPathPattern)
20 | if err != nil {
21 | return []string{}, err
22 | }
23 | return vmFileListInDir, nil
24 | }
25 |
26 | func main() {
27 | flag.Parse()
28 | pathToJack := flag.Arg(0)
29 |
30 | jackFileList := []string{}
31 |
32 | fileInfo, _ := os.Stat(pathToJack)
33 | if fileInfo.IsDir() {
34 | jackFileListInDir, err := getJackFileListInDir(pathToJack)
35 | if err != nil {
36 | panic(err)
37 | }
38 | jackFileList = jackFileListInDir
39 | } else {
40 | jackFileList = []string{pathToJack}
41 | }
42 |
43 | for _, jackFilename := range jackFileList {
44 | jackCode, err := ioutil.ReadFile(jackFilename)
45 | if err != nil {
46 | panic(err)
47 | }
48 |
49 | jt := tokenizer.New(string(jackCode))
50 | parser := parser.New(jt)
51 | programAst := parser.ParseProgram()
52 | classStmt, ok := programAst.Statements[0].(*ast.ClassStatement)
53 | if !ok {
54 | panic(fmt.Sprintf("Statement[0] should be ClassStatement, but got %T", classStmt))
55 | }
56 | className := classStmt.Name.Literal
57 | vm := vmwriter.New(fmt.Sprintf("vm/program/%s.vm", className), 0644)
58 | st := symboltable.New()
59 | ce := compilationengine.New(className, vm, st)
60 | ce.CompileProgram(programAst)
61 | ce.Close()
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/jackcompiler/symboltable/symboltable.go:
--------------------------------------------------------------------------------
1 | package symboltable
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | type SymbolTable struct {
8 | ClassScopeSymbolTable map[string]Symbol
9 | MethodScopeSymbolTable map[string]Symbol
10 | Scope Scope
11 | currentStaticIdx int
12 | currentFieldIdx int
13 | currentArgumentIdx int
14 | currentVarIdx int
15 | }
16 |
17 | type Symbol struct {
18 | Name string
19 | VarKind VarKind
20 | VarType string // not definite enum for this member. because varType is not only KeyWord.(className,FUnctionName...)
21 | Idx int
22 | }
23 |
24 | type VarKind string
25 |
26 | const (
27 | STATIC VarKind = "static"
28 | FIELD VarKind = "field"
29 | ARGUMENT VarKind = "argument"
30 | VAR VarKind = "var"
31 | NONE VarKind = "none"
32 | )
33 |
34 | type Scope int
35 |
36 | const (
37 | SubroutineScope Scope = iota
38 | ClassScope Scope = iota
39 | )
40 |
41 | func New() *SymbolTable {
42 | return &SymbolTable{Scope: ClassScope, MethodScopeSymbolTable: map[string]Symbol{}, ClassScopeSymbolTable: map[string]Symbol{}}
43 | }
44 |
45 | // TODO: TDD!
46 | func (st *SymbolTable) StartSubroutine() {
47 | st.MethodScopeSymbolTable = map[string]Symbol{}
48 | st.currentArgumentIdx = 0
49 | st.currentVarIdx = 0
50 | st.Scope = SubroutineScope
51 | }
52 |
53 | func (st *SymbolTable) Define(name string, varType string, varKind VarKind) error {
54 |
55 | symbol := Symbol{}
56 | symbol.Name = name
57 | symbol.VarKind = varKind
58 | symbol.VarType = varType
59 |
60 | switch varKind {
61 | case STATIC:
62 | symbol.Idx = st.currentStaticIdx
63 | st.currentStaticIdx++
64 | case FIELD:
65 | symbol.Idx = st.currentFieldIdx
66 | st.currentFieldIdx++
67 | case ARGUMENT:
68 | symbol.Idx = st.currentArgumentIdx
69 | st.currentArgumentIdx++
70 | case VAR:
71 | symbol.Idx = st.currentVarIdx
72 | st.currentVarIdx++
73 | default:
74 | return errors.New("") // TODO: Add Error
75 | }
76 |
77 | switch st.Scope {
78 | case SubroutineScope:
79 | st.MethodScopeSymbolTable[name] = symbol
80 | case ClassScope:
81 | st.ClassScopeSymbolTable[name] = symbol
82 | default:
83 | return errors.New("") // TODO: Add Error
84 | }
85 | return nil
86 | }
87 |
88 | func (st *SymbolTable) VarCount(varKind VarKind) int {
89 | table := map[string]Symbol{}
90 | switch st.Scope {
91 | case SubroutineScope:
92 | table = st.MethodScopeSymbolTable
93 | case ClassScope:
94 | table = st.ClassScopeSymbolTable
95 | }
96 | varCount := 0
97 | for _, symbol := range table {
98 | if symbol.VarKind == varKind {
99 | varCount++
100 | }
101 | }
102 | return varCount
103 | }
104 |
105 | func (st *SymbolTable) KindOf(name string) VarKind {
106 | symbol, ok := st.MethodScopeSymbolTable[name]
107 | if ok {
108 | return symbol.VarKind
109 | }
110 | symbol, ok = st.ClassScopeSymbolTable[name]
111 | if ok {
112 | return symbol.VarKind
113 | }
114 | return ""
115 | }
116 |
117 | func (st *SymbolTable) TypeOf(name string) string {
118 | symbol, ok := st.MethodScopeSymbolTable[name]
119 | if ok {
120 | return symbol.VarType
121 | }
122 | symbol, ok = st.ClassScopeSymbolTable[name]
123 | if ok {
124 | return symbol.VarType
125 | }
126 | return ""
127 | }
128 |
129 | func (st *SymbolTable) IndexOf(name string) int {
130 | symbol, ok := st.MethodScopeSymbolTable[name]
131 | if ok {
132 | return symbol.Idx
133 | }
134 | symbol, ok = st.ClassScopeSymbolTable[name]
135 | if ok {
136 | return symbol.Idx
137 | }
138 | return -1
139 | }
140 |
--------------------------------------------------------------------------------
/jackcompiler/token/token.go:
--------------------------------------------------------------------------------
1 | package token
2 |
3 | // TokenType is type of token
4 | type TokenType string
5 |
6 | // Token has memeber tokentype,tokenliteral
7 | type Token struct {
8 | Type TokenType
9 | Literal string
10 | }
11 |
12 | func (token *Token) String() string {
13 | return token.Literal
14 | }
15 |
16 | func (token *Token) Xml() string {
17 | switch token.Type {
18 | case KEYWORD:
19 | return " " + token.Literal + " "
20 | case SYMBOL:
21 | return " " + token.Literal + " "
22 | case IDENTIFIER:
23 | return " " + token.Literal + " "
24 | case INTCONST:
25 | return " " + token.Literal + " "
26 | case STARTINGCONST:
27 | return " " + token.Literal + " "
28 | default:
29 | return ""
30 | }
31 | }
32 |
33 | const (
34 | SYMBOL TokenType = "SYMBOL"
35 | KEYWORD TokenType = "KEYWORD"
36 | IDENTIFIER TokenType = "IDENTIFIER"
37 | INTCONST TokenType = "INT_CONST"
38 | STARTINGCONST TokenType = "STARTING_CONST"
39 | EOF TokenType = "EOF"
40 | )
41 |
42 | // KeyWord is keyword type
43 | type KeyWord string
44 |
45 | const (
46 | CLASS KeyWord = "class"
47 | METHOD KeyWord = "method"
48 | FUNCTION KeyWord = "function"
49 | CONSTRUCTOR KeyWord = "constructor"
50 | FIELD KeyWord = "field"
51 | STATIC KeyWord = "static"
52 | VAR KeyWord = "var"
53 | INT KeyWord = "int"
54 | CHAR KeyWord = "char"
55 | BOOLEAN KeyWord = "boolean"
56 | VOID KeyWord = "void"
57 | TRUE KeyWord = "true"
58 | FALSE KeyWord = "false"
59 | NULL KeyWord = "null"
60 | THIS KeyWord = "this"
61 | LET KeyWord = "let"
62 | DO KeyWord = "do"
63 | IF KeyWord = "if"
64 | ELSE KeyWord = "else"
65 | WHILE KeyWord = "while"
66 | RETURN KeyWord = "return"
67 | // EOF
68 | )
69 |
70 | type Symbol string
71 |
72 | var SymbolMap = map[byte]bool{'{': true, '}': true, '(': true, ')': true, '[': true, ']': true, '.': true, ':': true, ',': true, ';': true, '+': true, '-': true, '*': true, '/': true, '&': true, '|': true, '<': true, '>': true, '=': true, '~': true}
73 |
74 | const (
75 | COLON Symbol = ":"
76 | AMP Symbol = "&"
77 | OR Symbol = "|"
78 | BANG Symbol = "~"
79 | EQ Symbol = "="
80 | PLUS Symbol = "+"
81 | MINUS Symbol = "-"
82 | ASTERISK Symbol = "*"
83 | SLASH Symbol = "/"
84 | LT Symbol = "<"
85 | GT Symbol = ">"
86 | RPAREN Symbol = ")"
87 | LPAREN Symbol = "("
88 | RBRACE Symbol = "}"
89 | LBRACE Symbol = "{"
90 | COMMA Symbol = ","
91 | DOT Symbol = "."
92 | SEMICOLON Symbol = ";"
93 | LBRACKET Symbol = "["
94 | RBRACKET Symbol = "]"
95 | )
96 |
97 | var KeyWordMap = map[string]KeyWord{
98 | "class": CLASS,
99 | "method": METHOD,
100 | "function": FUNCTION,
101 | "constructor": CONSTRUCTOR,
102 | "field": FIELD,
103 | "static": STATIC,
104 | "var": VAR,
105 | "int": INT,
106 | "char": CHAR,
107 | "boolean": BOOLEAN,
108 | "void": VOID,
109 | "true": TRUE,
110 | "false": FALSE,
111 | "null": NULL,
112 | "this": THIS,
113 | "let": LET,
114 | "do": DO,
115 | "if": IF,
116 | "else": ELSE,
117 | "while": WHILE,
118 | "return": RETURN,
119 | }
120 |
--------------------------------------------------------------------------------
/jackcompiler/tokenizer/tokenizer.go:
--------------------------------------------------------------------------------
1 | package tokenizer
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "jackcompiler/token"
7 | )
8 |
9 | // JackTokenizer has member necessary for parsing
10 | type JackTokenizer struct {
11 | input string // code input
12 | position int
13 | readPosition int
14 | ch byte
15 | }
16 |
17 | // New is initializer of jack tokenizer
18 | func New(input string) *JackTokenizer {
19 | jt := &JackTokenizer{input: input}
20 | jt.readChar()
21 | return jt
22 | }
23 |
24 | // HasMoreTokens returns whether hasMoreToken
25 | func (jackTokenizer *JackTokenizer) HasMoreTokens() bool {
26 | return len(jackTokenizer.input) > jackTokenizer.position
27 | }
28 |
29 | // Advance returns next token
30 | func (jackTokenizer *JackTokenizer) Advance() (advanceToken token.Token, err error) {
31 | var tok token.Token
32 | // TODO: refactoring.
33 | jackTokenizer.skipWhitespace()
34 | if !jackTokenizer.HasMoreTokens() {
35 | return token.Token{Type: token.EOF}, nil
36 | }
37 | if _, ok := token.SymbolMap[jackTokenizer.ch]; ok {
38 | tok = token.Token{Type: token.SYMBOL, Literal: string(jackTokenizer.ch)}
39 | } else if isLetter(jackTokenizer.ch) { // KEYWORD or IDENTIFIER
40 | word := jackTokenizer.readWord()
41 | if _, ok := token.KeyWordMap[word]; ok {
42 | tok = token.Token{Type: token.KEYWORD, Literal: word}
43 | } else {
44 | tok = token.Token{Type: token.IDENTIFIER, Literal: word}
45 | }
46 | return tok, nil
47 | } else if isNumber(jackTokenizer.ch) {
48 | word := jackTokenizer.readNumber()
49 | tok = token.Token{Type: token.INTCONST, Literal: word}
50 | return tok, nil
51 | } else if isDoubleQuote(jackTokenizer.ch) {
52 | word := jackTokenizer.readString()
53 | tok = token.Token{Type: token.STARTINGCONST, Literal: word[1:]}
54 | return tok, nil
55 | } else {
56 | return tok, fmt.Errorf("invalid ch. got %s", string(jackTokenizer.ch))
57 | }
58 | jackTokenizer.readChar()
59 | return tok, nil
60 | }
61 |
62 | // KeyWord returns keyword type
63 | func KeyWord(tok token.Token) (keyword token.KeyWord, err error) {
64 | if tok.Type != token.KEYWORD {
65 | return token.NULL, errors.New("KeyWord Function can call only token type is KEYWORD")
66 | }
67 | return token.KeyWordMap[tok.Literal], nil
68 | }
69 |
70 | func (jackTokenizer *JackTokenizer) readChar() {
71 | if jackTokenizer.readPosition >= len(jackTokenizer.input) {
72 | jackTokenizer.ch = 0
73 | } else {
74 | jackTokenizer.ch = jackTokenizer.input[jackTokenizer.readPosition]
75 | }
76 | jackTokenizer.position = jackTokenizer.readPosition
77 |
78 | jackTokenizer.readPosition++
79 | }
80 |
81 | func (jackTokenizer *JackTokenizer) readWord() string {
82 | position := jackTokenizer.position
83 | for isLetter(jackTokenizer.ch) || isNumber(jackTokenizer.ch) || isUnderline(jackTokenizer.ch) {
84 | jackTokenizer.readChar()
85 | }
86 | return jackTokenizer.input[position:jackTokenizer.position]
87 | }
88 |
89 | func (jackTokenizer *JackTokenizer) readNumber() string {
90 | position := jackTokenizer.position
91 | for isNumber(jackTokenizer.ch) {
92 | jackTokenizer.readChar()
93 | }
94 | return jackTokenizer.input[position:jackTokenizer.position]
95 | }
96 |
97 | func (jackTokenizer *JackTokenizer) readString() string {
98 | position := jackTokenizer.position
99 | jackTokenizer.readChar() // read double quote
100 | for !isDoubleQuote(jackTokenizer.ch) {
101 | jackTokenizer.readChar()
102 | }
103 | jackTokenizer.readChar()
104 | return jackTokenizer.input[position : jackTokenizer.position-1]
105 | }
106 |
107 | func (jackTokenizer *JackTokenizer) skipWhitespace() {
108 | for jackTokenizer.ch == ' ' || jackTokenizer.ch == '\t' || jackTokenizer.ch == '\n' || jackTokenizer.ch == '\r' {
109 | jackTokenizer.readChar()
110 | }
111 | }
112 |
113 | func isLetter(ch byte) bool {
114 | return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z'
115 | }
116 |
117 | func isNumber(ch byte) bool {
118 | return '0' <= ch && ch <= '9'
119 | }
120 |
121 | func isUnderline(ch byte) bool {
122 | return ch == '_'
123 | }
124 |
125 | func isDoubleQuote(ch byte) bool {
126 | return ch == '"'
127 | }
128 |
--------------------------------------------------------------------------------
/jackcompiler/tokenizer/tokenizer_test.go:
--------------------------------------------------------------------------------
1 | package tokenizer
2 |
3 | import (
4 | "jackcompiler/token"
5 | "testing"
6 | )
7 |
8 | func TestNextToken(t *testing.T) {
9 | input := `
10 | class Main {
11 | static boolean test;
12 | function void main() {
13 | var SquareGame game;
14 | let game = game;
15 | do game.run();
16 | do game.dispose();
17 | return;
18 | }
19 | }`
20 | tests := []struct {
21 | expectedType token.TokenType
22 | expectedLiteral string
23 | }{
24 | {token.KEYWORD, "class"},
25 | {token.IDENTIFIER, "Main"},
26 | {token.SYMBOL, "{"},
27 | {token.KEYWORD, "static"},
28 | {token.KEYWORD, "boolean"},
29 | {token.IDENTIFIER, "test"},
30 | {token.SYMBOL, ";"},
31 | {token.KEYWORD, "function"},
32 | {token.KEYWORD, "void"},
33 | {token.IDENTIFIER, "main"},
34 | {token.SYMBOL, "("},
35 | {token.SYMBOL, ")"},
36 | {token.SYMBOL, "{"},
37 | {token.KEYWORD, "var"},
38 | {token.IDENTIFIER, "SquareGame"},
39 | {token.IDENTIFIER, "game"},
40 | {token.SYMBOL, ";"},
41 | {token.KEYWORD, "let"},
42 | {token.IDENTIFIER, "game"},
43 | {token.SYMBOL, "="},
44 | {token.IDENTIFIER, "game"},
45 | {token.SYMBOL, ";"},
46 | {token.KEYWORD, "do"},
47 | {token.IDENTIFIER, "game"},
48 | {token.SYMBOL, "."},
49 | {token.IDENTIFIER, "run"},
50 | {token.SYMBOL, "("},
51 | {token.SYMBOL, ")"},
52 | {token.SYMBOL, ";"},
53 | {token.KEYWORD, "do"},
54 | {token.IDENTIFIER, "game"},
55 | {token.SYMBOL, "."},
56 | {token.IDENTIFIER, "dispose"},
57 | {token.SYMBOL, "("},
58 | {token.SYMBOL, ")"},
59 | {token.SYMBOL, ";"},
60 | {token.KEYWORD, "return"},
61 | {token.SYMBOL, ";"},
62 | {token.SYMBOL, "}"},
63 | {token.SYMBOL, "}"},
64 | {token.EOF, ""},
65 | }
66 | jt := New(input)
67 | for i, tt := range tests {
68 | tok, _ := jt.Advance()
69 | if tok.Type != tt.expectedType {
70 | t.Fatalf("test[%d] - tokentype wrong. expected=%q,got %q. \n - tokenliteral : expected=%q,got %q", i, tt.expectedType, tok.Type, tt.expectedLiteral, tok.Literal)
71 | }
72 | if tok.Literal != tt.expectedLiteral {
73 | t.Fatalf("test[%d] - tokenliteral wrong. expected=%q,got %q", i, tt.expectedLiteral, tok.Literal)
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/jackcompiler/value/value.go:
--------------------------------------------------------------------------------
1 | package value
2 |
3 | var LF = "\n"
4 | var CR = "\r"
5 | var NEW_LINE = CR + LF
6 | var SPACE = " "
7 |
8 | var TAB = byte('\t')
9 |
10 | // var
11 |
--------------------------------------------------------------------------------
/jackcompiler/vm/Array.vm:
--------------------------------------------------------------------------------
1 | function Array.new 0
2 | push argument 0
3 | push constant 0
4 | gt
5 | not
6 | if-goto IF_TRUE0
7 | goto IF_FALSE0
8 | label IF_TRUE0
9 | push constant 2
10 | call Sys.error 1
11 | pop temp 0
12 | label IF_FALSE0
13 | push argument 0
14 | call Memory.alloc 1
15 | return
16 | function Array.dispose 0
17 | push argument 0
18 | pop pointer 0
19 | push pointer 0
20 | call Memory.deAlloc 1
21 | pop temp 0
22 | push constant 0
23 | return
24 |
--------------------------------------------------------------------------------
/jackcompiler/vm/Keyboard.vm:
--------------------------------------------------------------------------------
1 | function Keyboard.init 0
2 | push constant 0
3 | return
4 | function Keyboard.keyPressed 0
5 | push constant 24576
6 | call Memory.peek 1
7 | return
8 | function Keyboard.readChar 2
9 | push constant 0
10 | call Output.printChar 1
11 | pop temp 0
12 | label WHILE_EXP0
13 | push local 1
14 | push constant 0
15 | eq
16 | push local 0
17 | push constant 0
18 | gt
19 | or
20 | not
21 | if-goto WHILE_END0
22 | call Keyboard.keyPressed 0
23 | pop local 0
24 | push local 0
25 | push constant 0
26 | gt
27 | if-goto IF_TRUE0
28 | goto IF_FALSE0
29 | label IF_TRUE0
30 | push local 0
31 | pop local 1
32 | label IF_FALSE0
33 | goto WHILE_EXP0
34 | label WHILE_END0
35 | call String.backSpace 0
36 | call Output.printChar 1
37 | pop temp 0
38 | push local 1
39 | call Output.printChar 1
40 | pop temp 0
41 | push local 1
42 | return
43 | function Keyboard.readLine 5
44 | push constant 80
45 | call String.new 1
46 | pop local 3
47 | push argument 0
48 | call Output.printString 1
49 | pop temp 0
50 | call String.newLine 0
51 | pop local 1
52 | call String.backSpace 0
53 | pop local 2
54 | label WHILE_EXP0
55 | push local 4
56 | not
57 | not
58 | if-goto WHILE_END0
59 | call Keyboard.readChar 0
60 | pop local 0
61 | push local 0
62 | push local 1
63 | eq
64 | pop local 4
65 | push local 4
66 | not
67 | if-goto IF_TRUE0
68 | goto IF_FALSE0
69 | label IF_TRUE0
70 | push local 0
71 | push local 2
72 | eq
73 | if-goto IF_TRUE1
74 | goto IF_FALSE1
75 | label IF_TRUE1
76 | push local 3
77 | call String.eraseLastChar 1
78 | pop temp 0
79 | goto IF_END1
80 | label IF_FALSE1
81 | push local 3
82 | push local 0
83 | call String.appendChar 2
84 | pop local 3
85 | label IF_END1
86 | label IF_FALSE0
87 | goto WHILE_EXP0
88 | label WHILE_END0
89 | push local 3
90 | return
91 | function Keyboard.readInt 2
92 | push argument 0
93 | call Keyboard.readLine 1
94 | pop local 0
95 | push local 0
96 | call String.intValue 1
97 | pop local 1
98 | push local 0
99 | call String.dispose 1
100 | pop temp 0
101 | push local 1
102 | return
103 |
--------------------------------------------------------------------------------
/jackcompiler/vm/Sys.vm:
--------------------------------------------------------------------------------
1 | function Sys.init 0
2 | call Memory.init 0
3 | pop temp 0
4 | call Math.init 0
5 | pop temp 0
6 | call Screen.init 0
7 | pop temp 0
8 | call Output.init 0
9 | pop temp 0
10 | call Keyboard.init 0
11 | pop temp 0
12 | call Main.main 0
13 | pop temp 0
14 | call Sys.halt 0
15 | pop temp 0
16 | push constant 0
17 | return
18 | function Sys.halt 0
19 | label WHILE_EXP0
20 | push constant 0
21 | not
22 | not
23 | if-goto WHILE_END0
24 | goto WHILE_EXP0
25 | label WHILE_END0
26 | push constant 0
27 | return
28 | function Sys.wait 1
29 | push argument 0
30 | push constant 0
31 | lt
32 | if-goto IF_TRUE0
33 | goto IF_FALSE0
34 | label IF_TRUE0
35 | push constant 1
36 | call Sys.error 1
37 | pop temp 0
38 | label IF_FALSE0
39 | label WHILE_EXP0
40 | push argument 0
41 | push constant 0
42 | gt
43 | not
44 | if-goto WHILE_END0
45 | push constant 50
46 | pop local 0
47 | label WHILE_EXP1
48 | push local 0
49 | push constant 0
50 | gt
51 | not
52 | if-goto WHILE_END1
53 | push local 0
54 | push constant 1
55 | sub
56 | pop local 0
57 | goto WHILE_EXP1
58 | label WHILE_END1
59 | push argument 0
60 | push constant 1
61 | sub
62 | pop argument 0
63 | goto WHILE_EXP0
64 | label WHILE_END0
65 | push constant 0
66 | return
67 | function Sys.error 0
68 | push constant 69
69 | call Output.printChar 1
70 | pop temp 0
71 | push constant 82
72 | call Output.printChar 1
73 | pop temp 0
74 | push constant 82
75 | call Output.printChar 1
76 | pop temp 0
77 | push argument 0
78 | call Output.printInt 1
79 | pop temp 0
80 | call Sys.halt 0
81 | pop temp 0
82 | push constant 0
83 | return
84 |
--------------------------------------------------------------------------------
/jackcompiler/vm/program/Main.vm:
--------------------------------------------------------------------------------
1 | function Main.main 1
2 | call SquareGame.new 0
3 | pop local 0
4 | push local 0
5 | call SquareGame.run 1
6 | pop temp 0
7 | push local 0
8 | call SquareGame.dispose 1
9 | pop temp 0
10 | push constant 0
11 | return
12 |
--------------------------------------------------------------------------------
/jackcompiler/vm/program/SquareGame.vm:
--------------------------------------------------------------------------------
1 | function SquareGame.new 1
2 | push constant 2
3 | call Memory.alloc 1
4 | pop local 0
5 | push constant 0
6 | push constant 0
7 | push constant 30
8 | call Square.new 3
9 | push local 0
10 | pop pointer 0
11 | pop this 0
12 | push constant 0
13 | push local 0
14 | pop pointer 0
15 | pop this 1
16 | push local 0
17 | return
18 | function SquareGame.dispose 0
19 | push argument 0
20 | pop pointer 0
21 | push this 0
22 | call Square.dispose 1
23 | pop temp 0
24 | push argument 0
25 | call Memory.deAlloc 1
26 | pop temp 0
27 | push constant 0
28 | return
29 | function SquareGame.moveSquare 0
30 | push argument 0
31 | pop pointer 0
32 | push this 1
33 | push constant 1
34 | eq
35 | not
36 | if-goto ENDIF1
37 | push argument 0
38 | pop pointer 0
39 | push this 0
40 | call Square.moveUp 1
41 | pop temp 0
42 | label ENDIF1
43 | push argument 0
44 | pop pointer 0
45 | push this 1
46 | push constant 2
47 | eq
48 | not
49 | if-goto ENDIF2
50 | push argument 0
51 | pop pointer 0
52 | push this 0
53 | call Square.moveDown 1
54 | pop temp 0
55 | label ENDIF2
56 | push argument 0
57 | pop pointer 0
58 | push this 1
59 | push constant 3
60 | eq
61 | not
62 | if-goto ENDIF3
63 | push argument 0
64 | pop pointer 0
65 | push this 0
66 | call Square.moveLeft 1
67 | pop temp 0
68 | label ENDIF3
69 | push argument 0
70 | pop pointer 0
71 | push this 1
72 | push constant 4
73 | eq
74 | not
75 | if-goto ENDIF4
76 | push argument 0
77 | pop pointer 0
78 | push this 0
79 | call Square.moveRight 1
80 | pop temp 0
81 | label ENDIF4
82 | push constant 1
83 | call Sys.wait 1
84 | pop temp 0
85 | push constant 0
86 | return
87 | function SquareGame.run 2
88 | push constant 0
89 | pop local 1
90 | label WHILELOOP5
91 | push local 1
92 | not
93 | not
94 | if-goto WHILEEND5
95 | label WHILELOOP6
96 | push local 0
97 | push constant 0
98 | eq
99 | not
100 | if-goto WHILEEND6
101 | call Keyboard.keyPressed 0
102 | pop local 0
103 | push argument 0
104 | call SquareGame.moveSquare 1
105 | pop temp 0
106 | goto WHILELOOP6
107 | label WHILEEND6
108 | push local 0
109 | push constant 81
110 | eq
111 | not
112 | if-goto ENDIF7
113 | push constant 1
114 | neg
115 | pop local 1
116 | label ENDIF7
117 | push local 0
118 | push constant 90
119 | eq
120 | not
121 | if-goto ENDIF8
122 | push argument 0
123 | pop pointer 0
124 | push this 0
125 | call Square.decSize 1
126 | pop temp 0
127 | label ENDIF8
128 | push local 0
129 | push constant 88
130 | eq
131 | not
132 | if-goto ENDIF9
133 | push argument 0
134 | pop pointer 0
135 | push this 0
136 | call Square.incSize 1
137 | pop temp 0
138 | label ENDIF9
139 | push local 0
140 | push constant 131
141 | eq
142 | not
143 | if-goto ENDIF10
144 | push constant 1
145 | push argument 0
146 | pop pointer 0
147 | pop this 1
148 | label ENDIF10
149 | push local 0
150 | push constant 133
151 | eq
152 | not
153 | if-goto ENDIF11
154 | push constant 2
155 | push argument 0
156 | pop pointer 0
157 | pop this 1
158 | label ENDIF11
159 | push local 0
160 | push constant 130
161 | eq
162 | not
163 | if-goto ENDIF12
164 | push constant 3
165 | push argument 0
166 | pop pointer 0
167 | pop this 1
168 | label ENDIF12
169 | push local 0
170 | push constant 132
171 | eq
172 | not
173 | if-goto ENDIF13
174 | push constant 4
175 | push argument 0
176 | pop pointer 0
177 | pop this 1
178 | label ENDIF13
179 | label WHILELOOP14
180 | push local 0
181 | push constant 0
182 | eq
183 | not
184 | not
185 | if-goto WHILEEND14
186 | call Keyboard.keyPressed 0
187 | pop local 0
188 | push argument 0
189 | call SquareGame.moveSquare 1
190 | pop temp 0
191 | goto WHILELOOP14
192 | label WHILEEND14
193 | goto WHILELOOP5
194 | label WHILEEND5
195 | push constant 0
196 | return
197 |
--------------------------------------------------------------------------------
/jackcompiler/vmwriter/vmwriter.go:
--------------------------------------------------------------------------------
1 | package vmwriter
2 |
3 | import (
4 | "fmt"
5 | "io/fs"
6 | "io/ioutil"
7 | "jackcompiler/value"
8 | )
9 |
10 | type VMWriter struct {
11 | VMCode []byte
12 | Filename string
13 | perm fs.FileMode
14 | }
15 |
16 | type Command string
17 |
18 | const (
19 | ADD Command = "add"
20 | SUB Command = "sub"
21 | NEG Command = "neg"
22 | EQ Command = "eq"
23 | GT Command = "gt"
24 | LT Command = "lt"
25 | AND Command = "and"
26 | OR Command = "or"
27 | NOT Command = "not"
28 | )
29 |
30 | type Segment string
31 |
32 | const (
33 | CONST Segment = "constant"
34 | ARG Segment = "argument"
35 | LOCAL Segment = "local"
36 | STATIC Segment = "static"
37 | THIS Segment = "this"
38 | THAT Segment = "that"
39 | POINTER Segment = "pointer"
40 | TEMP Segment = "temp"
41 | )
42 |
43 | func New(filename string, permission fs.FileMode) *VMWriter {
44 | return &VMWriter{Filename: filename, VMCode: []byte{}, perm: permission}
45 | }
46 |
47 | func (vm *VMWriter) WritePush(segment Segment, idx int) {
48 | pushVmCode := fmt.Sprintf("push %s %d", segment, idx) + value.NEW_LINE
49 | vm.writeData(pushVmCode)
50 | }
51 |
52 | func (vm *VMWriter) WritePop(segment Segment, idx int) {
53 | popVmCode := fmt.Sprintf("pop %s %d", segment, idx) + value.NEW_LINE
54 | vm.writeData(popVmCode)
55 | }
56 |
57 | func (vm *VMWriter) WriteArithmetic(command Command) {
58 | vm.writeData(string(command) + value.NEW_LINE)
59 | }
60 |
61 | func (vm *VMWriter) WriteLabel(label string) {
62 | labelVmCode := fmt.Sprintf("label %s", label) + value.NEW_LINE
63 | vm.writeData(labelVmCode)
64 | }
65 |
66 | func (vm *VMWriter) WriteGoto(label string) {
67 | gotoVmCode := fmt.Sprintf("goto %s", label) + value.NEW_LINE
68 | vm.writeData(gotoVmCode)
69 | }
70 |
71 | func (vm *VMWriter) WriteIf(label string) {
72 | ifVmCode := fmt.Sprintf("if-goto %s", label) + value.NEW_LINE
73 | vm.writeData(ifVmCode)
74 | }
75 |
76 | func (vm *VMWriter) WriteCall(name string, nArgs int) {
77 | callVmCode := fmt.Sprintf("call %s %d", name, nArgs) + value.NEW_LINE
78 | vm.writeData(callVmCode)
79 | }
80 |
81 | func (vm *VMWriter) WriteFunction(name string, nLocals int) {
82 | functionVmCode := fmt.Sprintf("function %s %d", name, nLocals) + value.NEW_LINE
83 | vm.writeData(functionVmCode)
84 | }
85 |
86 | func (vm *VMWriter) WriteReturn() {
87 | vm.writeData("return" + value.NEW_LINE)
88 | }
89 |
90 | func (vm *VMWriter) writeData(vmCode string) {
91 | vm.VMCode = append(vm.VMCode, []byte(vmCode)...)
92 | }
93 |
94 | func (vm *VMWriter) Close() {
95 | err := ioutil.WriteFile(vm.Filename, vm.VMCode, vm.perm)
96 | if err != nil {
97 | panic(err)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/jackcompiler/vmwriter/vmwriter_test.go:
--------------------------------------------------------------------------------
1 | package vmwriter
2 |
3 | import (
4 | "bytes"
5 | "io/ioutil"
6 | "jackcompiler/value"
7 | "testing"
8 | )
9 |
10 | var filename = "test.vm"
11 |
12 | func TestClose(t *testing.T) {
13 | vmCode := []byte("Hello,World")
14 | vmWriter := &VMWriter{
15 | VMCode: vmCode, Filename: filename, perm: 0644,
16 | }
17 | vmWriter.Close()
18 | content, _ := ioutil.ReadFile(filename)
19 | if !bytes.Equal(content, vmCode) {
20 | t.Fatalf("vmCode should be %s. got %s", vmCode, content)
21 | }
22 | }
23 | func TestWriteData(t *testing.T) {
24 | vmCode := "Hello,World."
25 | vmWriter := &VMWriter{
26 | VMCode: []byte(vmCode), Filename: filename, perm: 0644,
27 | }
28 | addVmCode := "Good bye, World"
29 | vmWriter.writeData(addVmCode)
30 | if !bytes.Equal(vmWriter.VMCode, []byte(vmCode+addVmCode)) {
31 | t.Fatalf("vmCode should be %s. got %s", vmCode+addVmCode, vmWriter.VMCode)
32 | }
33 | }
34 |
35 | func TestWritePush(t *testing.T) {
36 | vmWriter := New("test.vm", 0644)
37 | vmWriter.WritePush(CONST, 0)
38 | if !bytes.Equal(vmWriter.VMCode, []byte("push constant 0"+value.NEW_LINE)) {
39 | t.Fatalf("vmCode should be %s. got %s", "push constant 0", vmWriter.VMCode)
40 | }
41 | }
42 |
43 | func TestWritePop(t *testing.T) {
44 | vmWriter := New("test.vm", 0644)
45 | vmWriter.WritePop(CONST, 0)
46 | if !bytes.Equal(vmWriter.VMCode, []byte("pop constant 0"+value.NEW_LINE)) {
47 | t.Fatalf("vmCode should be %s. got %s", "pop constant 0", vmWriter.VMCode)
48 | }
49 | }
50 | func TestWriteArithmetic(t *testing.T) {
51 | vmWriter := New("test.vm", 0644)
52 | vmWriter.WriteArithmetic(ADD)
53 | if !bytes.Equal(vmWriter.VMCode, []byte("add"+value.NEW_LINE)) {
54 | t.Fatalf("vmCode should be %s. got %s", "add", vmWriter.VMCode)
55 | }
56 | }
57 |
58 | func TestWriteLabel(t *testing.T) {
59 | vmWriter := New("test.vm", 0644)
60 | vmWriter.WriteLabel("LOOP")
61 | if !bytes.Equal(vmWriter.VMCode, []byte("label LOOP"+value.NEW_LINE)) {
62 | t.Fatalf("vmCode should be %s. got %s", "label LOOP", vmWriter.VMCode)
63 | }
64 | }
65 |
66 | func TestWriteGoto(t *testing.T) {
67 | vmWriter := New("test.vm", 0644)
68 | vmWriter.WriteGoto("LOOP")
69 | if !bytes.Equal(vmWriter.VMCode, []byte("goto LOOP"+value.NEW_LINE)) {
70 | t.Fatalf("vmCode should be %s. got %s", "goto LOOP", vmWriter.VMCode)
71 | }
72 | }
73 |
74 | func TestWriteIf(t *testing.T) {
75 | vmWriter := New("test.vm", 0644)
76 | vmWriter.WriteIf("LOOP")
77 | if !bytes.Equal(vmWriter.VMCode, []byte("if-goto LOOP"+value.NEW_LINE)) {
78 | t.Fatalf("vmCode should be %s. got %s", "if-goto LOOP", vmWriter.VMCode)
79 | }
80 | }
81 |
82 | func TestWriteCall(t *testing.T) {
83 | vmWriter := New("test.vm", 0644)
84 | vmWriter.WriteCall("hogeFunc", 3)
85 | if !bytes.Equal(vmWriter.VMCode, []byte("call hogeFunc 3"+value.NEW_LINE)) {
86 | t.Fatalf("vmCode should be %s. got %s", "call hogeFunc 3", vmWriter.VMCode)
87 | }
88 | }
89 |
90 | func TestWriteFunction(t *testing.T) {
91 | vmWriter := New("test.vm", 0644)
92 | vmWriter.WriteFunction("hogeFunc", 3)
93 | if !bytes.Equal(vmWriter.VMCode, []byte("function hogeFunc 3"+value.NEW_LINE)) {
94 | t.Fatalf("vmCode should be %s. got %s", "function hogeFunc 3", vmWriter.VMCode)
95 | }
96 | }
97 |
98 | func TestWriteReturn(t *testing.T) {
99 | vmWriter := New("test.vm", 0644)
100 | vmWriter.WriteReturn()
101 | if !bytes.Equal(vmWriter.VMCode, []byte("return"+value.NEW_LINE)) {
102 | t.Fatalf("vmCode should be %s. got %s", "return", vmWriter.VMCode)
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/vmtranslator/README.md:
--------------------------------------------------------------------------------
1 | # Nand2tetris VMTranslator by Golang 😺
2 |
3 | ## Overview
4 |
5 | - VMTranslator implementation by Golang ʕ◔ϖ◔ʔ.
6 | - VMTranslator translates intermediate language to assembly.
7 | - This package corresponds to chapter 7,8 of 「Building a Modern Computer from First Principles」
8 |
9 | ## Requirements
10 |
11 | - Go==1.16
12 |
13 | ## Intermediate language
14 |
15 | Intermediate code runs on virtual machine.
16 |
17 | Code below set the result of 2 + 3 to head of the stack.
18 |
19 | ```
20 | push constant 2
21 | push constant 3
22 | add
23 | ```
24 |
25 | ## How to work
26 |
27 | ### Generate assembly from intermediate code
28 |
29 | You can generate assembly from intermediate code by running:
30 |
31 | ```
32 | $ go run main.go {path to vm dir}
33 | ```
34 |
35 | Executing this command, assembly(.asm) program will be generated in the directory passed by argument
36 |
37 | **※You must pass path to directory which has vm files not path to vm file.(even if the target vm file is single)**
38 |
39 | For example, to translate `vm/BasicLoop` program which stores the result of 1 + 2 + ... + n (n is initialized by manipulating virtual machine manually) to stack to assembly, execute below:
40 |
41 | ```
42 | $ go run main.go vm/BasicLoop
43 | ```
44 |
45 | Executing this command, you can confirm that assembly program file(`BasicLoop.asm`) is generated in dir `vm/BasicLoop`
46 |
47 |
48 | ## Reference
49 |
50 | - [「Nand2Tetris Official Site」](https://www.nand2tetris.org/)
51 |
52 | - [「コンピュータシステムの理論と実装」](https://www.amazon.co.jp/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E2%80%95%E3%83%A2%E3%83%80%E3%83%B3%E3%81%AA%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-Noam-Nisan/dp/4873117127)
53 |
54 | - [「The Elements of Computing Systems: Building a Modern Computer from First Principles」](https://www.amazon.co.jp/Elements-Computing-Systems-Building-Principles/dp/0262640686)
55 |
56 | - [「Go 言語でつくるインタプリタ」](https://www.amazon.co.jp/Go%E8%A8%80%E8%AA%9E%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%97%E3%83%AA%E3%82%BF-Thorsten-Ball/dp/4873118220)
57 |
58 | - [「Writing An Interpreter In Go 」](https://www.amazon.co.jp/Writing-Interpreter-Go-Thorsten-Ball/dp/3982016118/ref=pd_bxgy_img_1/358-0651022-5160614?pd_rd_w=NJ0lb&pf_rd_p=d8f6e0ab-48ef-4eca-99d5-60d97e927468&pf_rd_r=H5DDRH744DZQWEC8887N&pd_rd_r=92fb3969-78f9-42fe-9c0b-f605fd3b7bc8&pd_rd_wg=B98nq&pd_rd_i=3982016118&psc=1)
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/vmtranslator/ast/ast_test.go:
--------------------------------------------------------------------------------
1 | package ast
2 |
3 | import "testing"
4 |
5 | func TestArithmeticCommandString(t *testing.T) {
6 | testCases := []struct {
7 | command *ArithmeticCommand
8 | commandStr string
9 | }{
10 | {&ArithmeticCommand{C_ARITHMETIC, ADD}, "add"},
11 | {&ArithmeticCommand{C_ARITHMETIC, NEG}, "neg"},
12 | {&ArithmeticCommand{C_ARITHMETIC, AND}, "and"},
13 | }
14 | for _, tt := range testCases {
15 | if tt.commandStr != tt.command.String() {
16 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
17 | }
18 | }
19 | }
20 |
21 | func TestPushCommandString(t *testing.T) {
22 | testCases := []struct {
23 | command *PushCommand
24 | commandStr string
25 | }{
26 | {&PushCommand{C_PUSH, PUSH, ARGUMENT, 4}, "push argument 4"},
27 | {&PushCommand{C_PUSH, PUSH, LOCAL, 111}, "push local 111"},
28 | {&PushCommand{C_PUSH, PUSH, THIS, 12}, "push this 12"},
29 | }
30 | for _, tt := range testCases {
31 | if tt.commandStr != tt.command.String() {
32 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
33 | }
34 | }
35 | }
36 |
37 | func TestPopCommandString(t *testing.T) {
38 | testCases := []struct {
39 | command *PopCommand
40 | commandStr string
41 | }{
42 | {&PopCommand{C_POP, POP, ARGUMENT, 4}, "pop argument 4"},
43 | {&PopCommand{C_POP, POP, LOCAL, 111}, "pop local 111"},
44 | {&PopCommand{C_POP, POP, THIS, 12}, "pop this 12"},
45 | }
46 | for _, tt := range testCases {
47 | if tt.commandStr != tt.command.String() {
48 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
49 | }
50 | }
51 | }
52 |
53 | func TestLabelCommandString(t *testing.T) {
54 | testCases := []struct {
55 | command *LabelCommand
56 | commandStr string
57 | }{
58 | {&LabelCommand{C_LABEL, LABEL, "IF_ELSE"}, "label IF_ELSE"},
59 | }
60 | for _, tt := range testCases {
61 | if tt.commandStr != tt.command.String() {
62 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
63 | }
64 | }
65 | }
66 |
67 | func TestGotoCommandString(t *testing.T) {
68 | testCases := []struct {
69 | command *GotoCommand
70 | commandStr string
71 | }{
72 | {&GotoCommand{C_LABEL, GOTO, "IF_ELSE"}, "goto IF_ELSE"},
73 | }
74 | for _, tt := range testCases {
75 | if tt.commandStr != tt.command.String() {
76 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
77 | }
78 | }
79 | }
80 |
81 | func TestIfCommandString(t *testing.T) {
82 | testCases := []struct {
83 | command *IfCommand
84 | commandStr string
85 | }{
86 | {&IfCommand{C_IF, IF_GOTO, "IF_ELSE"}, "if-goto IF_ELSE"},
87 | }
88 | for _, tt := range testCases {
89 | if tt.commandStr != tt.command.String() {
90 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
91 | }
92 | }
93 | }
94 |
95 | func TestCallCommandString(t *testing.T) {
96 | testCases := []struct {
97 | command *CallCommand
98 | commandStr string
99 | }{
100 | {&CallCommand{C_CALL, CALL, "func", 10}, "call func 10"},
101 | }
102 | for _, tt := range testCases {
103 | if tt.commandStr != tt.command.String() {
104 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
105 | }
106 | }
107 | }
108 |
109 | func TestFunctionCommandString(t *testing.T) {
110 | testCases := []struct {
111 | command *FunctionCommand
112 | commandStr string
113 | }{
114 | {&FunctionCommand{C_FUNCTION, FUNCTION, "func", 10}, "function func 10"},
115 | }
116 | for _, tt := range testCases {
117 | if tt.commandStr != tt.command.String() {
118 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
119 | }
120 | }
121 | }
122 |
123 | func TestReturnCommandString(t *testing.T) {
124 | testCases := []struct {
125 | command *ReturnCommand
126 | commandStr string
127 | }{
128 | {&ReturnCommand{C_RETURN, RETURN}, "return"},
129 | }
130 | for _, tt := range testCases {
131 | if tt.commandStr != tt.command.String() {
132 | t.Fatalf("command.String() should be %s , but got %s", tt.commandStr, tt.command.String())
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/vmtranslator/codewriter/codewriter_test.go:
--------------------------------------------------------------------------------
1 | package codewriter
2 |
3 | import (
4 | "bytes"
5 | "io/ioutil"
6 | "testing"
7 | "vmtranslator/ast"
8 | )
9 |
10 | func TestClose(t *testing.T) {
11 | assembly := []byte("Hello,World")
12 | filename := "test.asm"
13 | codeWriter := &CodeWriter{
14 | Assembly: assembly, Filename: filename,
15 | }
16 | codeWriter.Close()
17 | content, _ := ioutil.ReadFile(filename)
18 | if !bytes.Equal(content, assembly) {
19 | t.Fatalf("assembly should be %s. got %s", assembly, content)
20 | }
21 | }
22 |
23 | func TestWriteAssembly(t *testing.T) {
24 | assembly := "Hello,World"
25 | codeWriter := New("test.asm")
26 | codeWriter.writeAssembly(string(assembly))
27 | if !bytes.Equal(codeWriter.Assembly, []byte(assembly)) {
28 | t.Fatalf("assembly should be %s. got %s", assembly, codeWriter.Assembly)
29 | }
30 | }
31 |
32 | func TestGetPushAssembly(t *testing.T) {
33 | testCases := []struct {
34 | pushCommand *ast.PushCommand
35 | assembly string
36 | }{
37 | {&ast.PushCommand{Comamnd: ast.C_PUSH, Symbol: ast.PUSH, Segment: ast.CONSTANT, Index: 1111}, "@1111\r\nD=A\r\n@SP\r\nA=M\r\nM=D\r\n@SP\r\nM=M+1\r\n"},
38 | }
39 | codeWriter := New("test.asm")
40 | for _, tt := range testCases {
41 | assembly, _ := codeWriter.getPushAssembly(tt.pushCommand)
42 | if !bytes.Equal([]byte(assembly), []byte(tt.assembly)) {
43 | t.Fatalf("assembly should be %s. got %s", tt.assembly, assembly)
44 | }
45 | }
46 | }
47 |
48 | func TestGetArithmeticAssembly(t *testing.T) {
49 | testCases := []struct {
50 | arithmeticCommand *ast.ArithmeticCommand
51 | assembly string
52 | }{
53 | {arithmeticCommand: &ast.ArithmeticCommand{Command: ast.C_ARITHMETIC, Symbol: ast.ADD}, assembly: ""},
54 | }
55 | codeWriter := New("test.asm")
56 | for _, tt := range testCases {
57 | assembly, _ := codeWriter.getArithmeticAssembly(tt.arithmeticCommand)
58 | if !bytes.Equal([]byte(assembly), []byte(tt.assembly)) {
59 | t.Fatalf("assembly should be %s. got %s", tt.assembly, assembly)
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/vmtranslator/go.mod:
--------------------------------------------------------------------------------
1 | module vmtranslator
2 |
3 | go 1.16
4 |
--------------------------------------------------------------------------------
/vmtranslator/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "io/ioutil"
7 | "path"
8 | "path/filepath"
9 | "strings"
10 | "vmtranslator/ast"
11 | "vmtranslator/codewriter"
12 | "vmtranslator/parser"
13 | )
14 |
15 | func getVmFileListInDir(dirPath string) ([]string, error) {
16 | vmPathPattern := filepath.Join(dirPath, "*.vm")
17 | vmFileListInDir, err := filepath.Glob(vmPathPattern)
18 | if err != nil {
19 | return []string{}, err
20 | }
21 | return vmFileListInDir, nil
22 | }
23 |
24 | func removeExt(filename string) string {
25 | return strings.Trim(filename, filepath.Ext(filename))
26 | }
27 |
28 | func main() {
29 |
30 | flag.Parse()
31 | pathToVmDir := flag.Args()[0]
32 | asmFilename := fmt.Sprintf("%s.asm", path.Base(pathToVmDir))
33 |
34 | vmFileList, err := getVmFileListInDir(pathToVmDir)
35 | if err != nil {
36 | panic(err)
37 | }
38 | // join all vm code in dir.
39 | vmCodeList, vmClassNameList := []string{}, []string{}
40 | for _, vmFile := range vmFileList {
41 | vmCode, err := ioutil.ReadFile(vmFile)
42 | if err != nil {
43 | panic(err)
44 | }
45 | filename := filepath.Base(vmFile)
46 | vmClassNameList = append(vmClassNameList, removeExt(filename))
47 | vmCodeList = append(vmCodeList, string(vmCode))
48 | }
49 | codeWriter := codewriter.New(path.Join(pathToVmDir, asmFilename))
50 | // writeInit
51 | codeWriter.WriteInit()
52 | for i := range vmCodeList {
53 | parser := parser.New(vmCodeList[i])
54 | codeWriter.SetVmClassName(vmClassNameList[i])
55 | for parser.HasMoreCommand() {
56 | switch parser.CommandType() {
57 | case ast.C_PUSH:
58 | command, _ := parser.ParsePush()
59 | codeWriter.WritePushPop(command)
60 | case ast.C_POP:
61 | command, _ := parser.ParsePop()
62 | codeWriter.WritePushPop(command)
63 | case ast.C_ARITHMETIC:
64 | command, _ := parser.ParseArithmetic()
65 | codeWriter.WriteArithmetic(command)
66 | case ast.C_IF:
67 | command, _ := parser.ParseIf()
68 | codeWriter.WriteIf(command)
69 | case ast.C_LABEL:
70 | command, _ := parser.ParseLabel()
71 | codeWriter.WriteLabel(command)
72 | case ast.C_GOTO:
73 | command, _ := parser.ParseGoto()
74 | codeWriter.WriteGoto(command)
75 | case ast.C_FUNCTION:
76 | command, _ := parser.ParseFunction()
77 | codeWriter.WriteFunction(command)
78 | case ast.C_CALL:
79 | command, _ := parser.ParseCall()
80 | codeWriter.WriteCall(command)
81 | case ast.C_RETURN:
82 | command, _ := parser.ParseReturn()
83 | codeWriter.WriteReturn(command)
84 | }
85 | parser.Advance()
86 | }
87 | }
88 | codeWriter.Close()
89 | }
90 |
--------------------------------------------------------------------------------
/vmtranslator/main_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 | )
7 |
8 | func TestGetVmFileList(t *testing.T) {
9 | testCases := []struct {
10 | dirPath string
11 | vmFileList []string
12 | }{
13 | {"FunctionCalls/NestedCall", []string{"FunctionCalls/NestedCall/Sys.vm"}},
14 | {"FunctionCalls/FibonacciElement", []string{"FunctionCalls/FibonacciElement/Main.vm", "FunctionCalls/FibonacciElement/Sys.vm"}},
15 | }
16 | for _, tt := range testCases {
17 | vmFileList, err := getVmFileListInDir(tt.dirPath)
18 | if err != nil {
19 | t.Fatal(err)
20 | }
21 | if !reflect.DeepEqual(tt.vmFileList, vmFileList) {
22 | t.Fatalf("vmFileList should be %s, but got %s", tt.vmFileList, vmFileList)
23 | }
24 | }
25 | }
26 |
27 | func TestRemoveExt(t *testing.T) {
28 | testCases := []struct {
29 | filename string
30 | filenameExtRemoved string
31 | }{
32 | {"index.js", "index"},
33 | {"index.vm", "index"},
34 | }
35 | for _, tt := range testCases {
36 | filenameExtRemoved := removeExt(tt.filename)
37 | if tt.filenameExtRemoved != filenameExtRemoved {
38 | t.Fatalf("filenameExtRemoved should be %s, but got %s", tt.filenameExtRemoved, filenameExtRemoved)
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/vmtranslator/value/value.go:
--------------------------------------------------------------------------------
1 | package value
2 |
3 | var LF = "\n"
4 | var CR = "\r"
5 | var NEW_LINE = CR + LF
6 | var SPACE = " "
7 |
8 | var TAB = byte('\t')
9 |
10 | // var
11 |
--------------------------------------------------------------------------------
/vmtranslator/vm/BasicLoop/BasicLoop.cmp:
--------------------------------------------------------------------------------
1 | | RAM[0] |RAM[256]|
2 | | 257 | 6 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/BasicLoop/BasicLoop.out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YadaYuki/nand2tetris-golang/d659ecfb66648801edeb27c74f96c3c7c37717a9/vmtranslator/vm/BasicLoop/BasicLoop.out
--------------------------------------------------------------------------------
/vmtranslator/vm/BasicLoop/BasicLoop.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/ProgramFlow/BasicLoop/BasicLoop.tst
5 |
6 | load BasicLoop.asm,
7 | output-file BasicLoop.out,
8 | compare-to BasicLoop.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[256]%D1.6.1;
10 |
11 | set RAM[0] 256,
12 | set RAM[1] 300,
13 | set RAM[2] 400,
14 | set RAM[400] 3,
15 |
16 | repeat 600 {
17 | ticktock;
18 | }
19 |
20 | output;
21 |
--------------------------------------------------------------------------------
/vmtranslator/vm/BasicLoop/BasicLoop.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/ProgramFlow/BasicLoop/BasicLoop.vm
5 |
6 | // Computes the sum 1 + 2 + ... + argument[0] and pushes the
7 | // result onto the stack. Argument[0] is initialized by the test
8 | // script before this code starts running.
9 | push constant 0
10 | pop local 0 // initializes sum = 0
11 | label LOOP_START
12 | push argument 0
13 | push local 0
14 | add
15 | pop local 0 // sum = sum + counter
16 | push argument 0
17 | push constant 1
18 | sub
19 | pop argument 0 // counter--
20 | push argument 0
21 | if-goto LOOP_START // If counter != 0, goto LOOP_START
22 | push local 0
23 |
--------------------------------------------------------------------------------
/vmtranslator/vm/BasicLoop/BasicLoopVME.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/ProgramFlow/BasicLoop/BasicLoopVME.tst
5 |
6 | load BasicLoop.vm,
7 | output-file BasicLoop.out,
8 | compare-to BasicLoop.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[256]%D1.6.1;
10 |
11 | set sp 256,
12 | set local 300,
13 | set argument 400,
14 | set argument[0] 3,
15 |
16 | repeat 33 {
17 | vmstep;
18 | }
19 |
20 | output;
21 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciElement/FibonacciElement.cmp:
--------------------------------------------------------------------------------
1 | | RAM[0] |RAM[261]|
2 | | 262 | 3 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciElement/FibonacciElement.out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YadaYuki/nand2tetris-golang/d659ecfb66648801edeb27c74f96c3c7c37717a9/vmtranslator/vm/FibonacciElement/FibonacciElement.out
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciElement/FibonacciElement.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/FibonacciElement/FibonacciElement.tst
5 |
6 | // FibonacciElement.asm results from translating both Main.vm and Sys.vm into
7 | // a single assembly program, stored in the file FibonacciElement.asm.
8 |
9 | load FibonacciElement.asm,
10 | output-file FibonacciElement.out,
11 | compare-to FibonacciElement.cmp,
12 | output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
13 |
14 | repeat 2000 {
15 | ticktock;
16 | }
17 |
18 | output;
19 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciElement/FibonacciElementVME.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/FibonacciElement/FibonacciElementVME.tst
5 |
6 | load, // Load all the VM files from the current directory
7 | output-file FibonacciElement.out,
8 | compare-to FibonacciElement.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
10 |
11 | set sp 261,
12 |
13 | repeat 110 {
14 | vmstep;
15 | }
16 |
17 | output;
18 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciElement/Main.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/FibonacciElement/Main.vm
5 |
6 | // Computes the n'th element of the Fibonacci series, recursively.
7 | // n is given in argument[0]. Called by the Sys.init function
8 | // (part of the Sys.vm file), which also pushes the argument[0]
9 | // parameter before this code starts running.
10 |
11 | function Main.fibonacci 0
12 | push argument 0
13 | push constant 2
14 | lt // checks if n<2
15 | if-goto IF_TRUE
16 | goto IF_FALSE
17 | label IF_TRUE // if n<2, return n
18 | push argument 0
19 | return
20 | label IF_FALSE // if n>=2, returns fib(n-2)+fib(n-1)
21 | push argument 0
22 | push constant 2
23 | sub
24 | call Main.fibonacci 1 // computes fib(n-2)
25 | push argument 0
26 | push constant 1
27 | sub
28 | call Main.fibonacci 1 // computes fib(n-1)
29 | add // returns fib(n-1) + fib(n-2)
30 | return
31 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciElement/Sys.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/FibonacciElement/Sys.vm
5 |
6 | // Pushes a constant, say n, onto the stack, and calls the Main.fibonacii
7 | // function, which computes the n'th element of the Fibonacci series.
8 | // Note that by convention, the Sys.init function is called "automatically"
9 | // by the bootstrap code.
10 |
11 | function Sys.init 0
12 | push constant 4
13 | call Main.fibonacci 1 // computes the 4'th fibonacci element
14 | label WHILE
15 | goto WHILE // loops infinitely
16 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciSeries/FibonacciSeries.cmp:
--------------------------------------------------------------------------------
1 | |RAM[3000]|RAM[3001]|RAM[3002]|RAM[3003]|RAM[3004]|RAM[3005]|
2 | | 0 | 1 | 1 | 2 | 3 | 5 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciSeries/FibonacciSeries.out:
--------------------------------------------------------------------------------
1 | |RAM[3000]|RAM[3001]|RAM[3002]|RAM[3003]|RAM[3004]|RAM[3005]|
2 | | 0 | 1 | 1 | 2 | 3 | 5 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciSeries/FibonacciSeries.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/ProgramFlow/FibonacciSeries/FibonacciSeries.tst
5 |
6 | load FibonacciSeries.asm,
7 | output-file FibonacciSeries.out,
8 | compare-to FibonacciSeries.cmp,
9 | output-list RAM[3000]%D1.6.2 RAM[3001]%D1.6.2 RAM[3002]%D1.6.2
10 | RAM[3003]%D1.6.2 RAM[3004]%D1.6.2 RAM[3005]%D1.6.2;
11 |
12 | set RAM[0] 256,
13 | set RAM[1] 300,
14 | set RAM[2] 400,
15 | set RAM[400] 6,
16 | set RAM[401] 3000,
17 |
18 | repeat 1100 {
19 | ticktock;
20 | }
21 |
22 | output;
23 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciSeries/FibonacciSeries.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/ProgramFlow/FibonacciSeries/FibonacciSeries.vm
5 |
6 | // Puts the first argument[0] elements of the Fibonacci series
7 | // in the memory, starting in the address given in argument[1].
8 | // Argument[0] and argument[1] are initialized by the test script
9 | // before this code starts running.
10 |
11 | push argument 1
12 | pop pointer 1 // that = argument[1]
13 |
14 | push constant 0
15 | pop that 0 // first element in the series = 0
16 | push constant 1
17 | pop that 1 // second element in the series = 1
18 |
19 | push argument 0
20 | push constant 2
21 | sub
22 | pop argument 0 // num_of_elements -= 2 (first 2 elements are set)
23 |
24 | label MAIN_LOOP_START
25 |
26 | push argument 0
27 | if-goto COMPUTE_ELEMENT // if num_of_elements > 0, goto COMPUTE_ELEMENT
28 | goto END_PROGRAM // otherwise, goto END_PROGRAM
29 |
30 | label COMPUTE_ELEMENT
31 |
32 | push that 0
33 | push that 1
34 | add
35 | pop that 2 // that[2] = that[0] + that[1]
36 |
37 | push pointer 1
38 | push constant 1
39 | add
40 | pop pointer 1 // that += 1
41 |
42 | push argument 0
43 | push constant 1
44 | sub
45 | pop argument 0 // num_of_elements--
46 |
47 | goto MAIN_LOOP_START
48 |
49 | label END_PROGRAM
50 |
--------------------------------------------------------------------------------
/vmtranslator/vm/FibonacciSeries/FibonacciSeriesVME.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/ProgramFlow/FibonacciSeries/FibonacciSeriesVME.tst
5 |
6 | load FibonacciSeries.vm,
7 | output-file FibonacciSeries.out,
8 | compare-to FibonacciSeries.cmp,
9 | output-list RAM[3000]%D1.6.2 RAM[3001]%D1.6.2 RAM[3002]%D1.6.2
10 | RAM[3003]%D1.6.2 RAM[3004]%D1.6.2 RAM[3005]%D1.6.2;
11 |
12 | set sp 256,
13 | set local 300,
14 | set argument 400,
15 | set argument[0] 6,
16 | set argument[1] 3000,
17 |
18 | repeat 73 {
19 | vmstep;
20 | }
21 |
22 | output;
23 |
--------------------------------------------------------------------------------
/vmtranslator/vm/NestedCall/NestedCall.cmp:
--------------------------------------------------------------------------------
1 | | RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] | RAM[5] | RAM[6] |
2 | | 261 | 261 | 256 | 4000 | 5000 | 135 | 246 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/NestedCall/NestedCall.out:
--------------------------------------------------------------------------------
1 | | RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] | RAM[5] | RAM[6] |
2 |
--------------------------------------------------------------------------------
/vmtranslator/vm/NestedCall/NestedCall.tst:
--------------------------------------------------------------------------------
1 | // Test file for NestedCall test.
2 |
3 | load NestedCall.asm,
4 | output-file NestedCall.out,
5 | compare-to NestedCall.cmp,
6 | output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1 RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[5]%D1.6.1 RAM[6]%D1.6.1;
7 |
8 | set RAM[0] 261,
9 | set RAM[1] 261,
10 | set RAM[2] 256,
11 | set RAM[3] -3,
12 | set RAM[4] -4,
13 | set RAM[5] -1, // test results
14 | set RAM[6] -1,
15 | set RAM[256] 1234, // fake stack frame from call Sys.init
16 | set RAM[257] -1,
17 | set RAM[258] -2,
18 | set RAM[259] -3,
19 | set RAM[260] -4,
20 |
21 | set RAM[261] -1, // Initialize stack to check for local segment
22 | set RAM[262] -1, // being cleared to zero.
23 | set RAM[263] -1,
24 | set RAM[264] -1,
25 | set RAM[265] -1,
26 | set RAM[266] -1,
27 | set RAM[267] -1,
28 | set RAM[268] -1,
29 | set RAM[269] -1,
30 | set RAM[270] -1,
31 | set RAM[271] -1,
32 | set RAM[272] -1,
33 | set RAM[273] -1,
34 | set RAM[274] -1,
35 | set RAM[275] -1,
36 | set RAM[276] -1,
37 | set RAM[277] -1,
38 | set RAM[278] -1,
39 | set RAM[279] -1,
40 | set RAM[280] -1,
41 | set RAM[281] -1,
42 | set RAM[282] -1,
43 | set RAM[283] -1,
44 | set RAM[284] -1,
45 | set RAM[285] -1,
46 | set RAM[286] -1,
47 | set RAM[287] -1,
48 | set RAM[288] -1,
49 | set RAM[289] -1,
50 | set RAM[290] -1,
51 | set RAM[291] -1,
52 | set RAM[292] -1,
53 | set RAM[293] -1,
54 | set RAM[294] -1,
55 | set RAM[295] -1,
56 | set RAM[296] -1,
57 | set RAM[297] -1,
58 | set RAM[298] -1,
59 | set RAM[299] -1,
60 |
61 | repeat 4000 {
62 | ticktock;
63 | }
64 |
65 | output;
66 |
--------------------------------------------------------------------------------
/vmtranslator/vm/NestedCall/NestedCallVME.tst:
--------------------------------------------------------------------------------
1 | // Test file for NestedCall test.
2 |
3 | load Sys.vm,
4 | output-file NestedCall.out,
5 | compare-to NestedCall.cmp,
6 | output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1 RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[5]%D1.6.1 RAM[6]%D1.6.1;
7 |
8 | set RAM[0] 261,
9 | set RAM[1] 261,
10 | set RAM[2] 256,
11 | set RAM[3] -3,
12 | set RAM[4] -4,
13 | set RAM[5] -1, // test results
14 | set RAM[6] -1,
15 | set RAM[256] 1234, // fake stack frame from call Sys.init
16 | set RAM[257] -1,
17 | set RAM[258] -2,
18 | set RAM[259] -3,
19 | set RAM[260] -4,
20 |
21 | set RAM[261] -1, // Initialize stack to check for local segment
22 | set RAM[262] -1, // being cleared to zero.
23 | set RAM[263] -1,
24 | set RAM[264] -1,
25 | set RAM[265] -1,
26 | set RAM[266] -1,
27 | set RAM[267] -1,
28 | set RAM[268] -1,
29 | set RAM[269] -1,
30 | set RAM[270] -1,
31 | set RAM[271] -1,
32 | set RAM[272] -1,
33 | set RAM[273] -1,
34 | set RAM[274] -1,
35 | set RAM[275] -1,
36 | set RAM[276] -1,
37 | set RAM[277] -1,
38 | set RAM[278] -1,
39 | set RAM[279] -1,
40 | set RAM[280] -1,
41 | set RAM[281] -1,
42 | set RAM[282] -1,
43 | set RAM[283] -1,
44 | set RAM[284] -1,
45 | set RAM[285] -1,
46 | set RAM[286] -1,
47 | set RAM[287] -1,
48 | set RAM[288] -1,
49 | set RAM[289] -1,
50 | set RAM[290] -1,
51 | set RAM[291] -1,
52 | set RAM[292] -1,
53 | set RAM[293] -1,
54 | set RAM[294] -1,
55 | set RAM[295] -1,
56 | set RAM[296] -1,
57 | set RAM[297] -1,
58 | set RAM[298] -1,
59 | set RAM[299] -1,
60 |
61 | set sp 261,
62 | set local 261,
63 | set argument 256,
64 | set this 3000,
65 | set that 4000;
66 |
67 | repeat 50 {
68 | vmstep;
69 | }
70 | output;
71 |
--------------------------------------------------------------------------------
/vmtranslator/vm/NestedCall/Sys.vm:
--------------------------------------------------------------------------------
1 | // Sys.vm for NestedCall test.
2 |
3 | // Sys.init()
4 | //
5 | // Calls Sys.main() and stores return value in temp 1.
6 | // Does not return. (Enters infinite loop.)
7 |
8 | function Sys.init 0
9 | push constant 4000
10 | // test THIS and THAT context save
11 | pop pointer 0
12 | push constant 5000
13 | pop pointer 1
14 | call Sys.main 0
15 | pop temp 1
16 | label LOOP
17 | goto LOOP
18 |
19 | // Sys.main()
20 | //
21 | // Sets locals 1, 2 and 3, leaving locals 0 and 4 unchanged to test
22 | // default local initialization to 0. (RAM set to -1 by test setup.)
23 | // Calls Sys.add12(123) and stores return value (135) in temp 0.
24 | // Returns local 0 + local 1 + local 2 + local 3 + local 4 (456) to confirm
25 | // that locals were not mangled by function call.
26 |
27 | function Sys.main 5
28 | push constant 4001
29 | pop pointer 0
30 | push constant 5001
31 | pop pointer 1
32 | push constant 200
33 | pop local 1
34 | push constant 40
35 | pop local 2
36 | push constant 6
37 | pop local 3
38 | push constant 123
39 | call Sys.add12 1
40 | pop temp 0
41 | push local 0
42 | push local 1
43 | push local 2
44 | push local 3
45 | push local 4
46 | add
47 | add
48 | add
49 | add
50 | return
51 |
52 | // Sys.add12(int n)
53 | //
54 | // Returns n+12.
55 |
56 | function Sys.add12 0
57 | push constant 4002
58 | pop pointer 0
59 | push constant 5002
60 | pop pointer 1
61 | push argument 0
62 | push constant 12
63 | add
64 | return
65 |
--------------------------------------------------------------------------------
/vmtranslator/vm/SimpleFunction/SimpleFunction.cmp:
--------------------------------------------------------------------------------
1 | | RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] |RAM[310]|
2 | | 311 | 305 | 300 | 3010 | 4010 | 1196 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/SimpleFunction/SimpleFunction.out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YadaYuki/nand2tetris-golang/d659ecfb66648801edeb27c74f96c3c7c37717a9/vmtranslator/vm/SimpleFunction/SimpleFunction.out
--------------------------------------------------------------------------------
/vmtranslator/vm/SimpleFunction/SimpleFunction.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/SimpleFunction/SimpleFunction.tst
5 |
6 | load SimpleFunction.asm,
7 | output-file SimpleFunction.out,
8 | compare-to SimpleFunction.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1
10 | RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[310]%D1.6.1;
11 |
12 | set RAM[0] 317,
13 | set RAM[1] 317,
14 | set RAM[2] 310,
15 | set RAM[3] 3000,
16 | set RAM[4] 4000,
17 | set RAM[310] 1234,
18 | set RAM[311] 37,
19 | set RAM[312] 1000,
20 | set RAM[313] 305,
21 | set RAM[314] 300,
22 | set RAM[315] 3010,
23 | set RAM[316] 4010,
24 |
25 | repeat 300 {
26 | ticktock;
27 | }
28 |
29 | output;
30 |
--------------------------------------------------------------------------------
/vmtranslator/vm/SimpleFunction/SimpleFunction.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/SimpleFunction/SimpleFunction.vm
5 |
6 | // Performs a simple calculation and returns the result.
7 | function SimpleFunction.test 2
8 | push local 0
9 | push local 1
10 | add
11 | not
12 | push argument 0
13 | add
14 | push argument 1
15 | sub
16 | return
17 |
--------------------------------------------------------------------------------
/vmtranslator/vm/SimpleFunction/SimpleFunctionVME.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/SimpleFunction/SimpleFunctionVME.tst
5 |
6 | load SimpleFunction.vm,
7 | output-file SimpleFunction.out,
8 | compare-to SimpleFunction.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1
10 | RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[310]%D1.6.1;
11 |
12 | set sp 317,
13 | set local 317,
14 | set argument 310,
15 | set this 3000,
16 | set that 4000,
17 | set argument[0] 1234,
18 | set argument[1] 37,
19 | set argument[2] 9,
20 | set argument[3] 305,
21 | set argument[4] 300,
22 | set argument[5] 3010,
23 | set argument[6] 4010,
24 |
25 | repeat 10 {
26 | vmstep;
27 | }
28 |
29 | output;
30 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/Class1.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/StaticsTest/Class1.vm
5 |
6 | // Stores two supplied arguments in static[0] and static[1].
7 | function Class1.set 0
8 | push argument 0
9 | pop static 0
10 | push argument 1
11 | pop static 1
12 | push constant 0
13 | return
14 |
15 | // Returns static[0] - static[1].
16 | function Class1.get 0
17 | push static 0
18 | push static 1
19 | sub
20 | return
21 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/Class2.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/StaticsTest/Class2.vm
5 |
6 | // Stores two supplied arguments in static[0] and static[1].
7 | function Class2.set 0
8 | push argument 0
9 | pop static 0
10 | push argument 1
11 | pop static 1
12 | push constant 0
13 | return
14 |
15 | // Returns static[0] - static[1].
16 | function Class2.get 0
17 | push static 0
18 | push static 1
19 | sub
20 | return
21 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/StaticsTest.cmp:
--------------------------------------------------------------------------------
1 | | RAM[0] |RAM[261]|RAM[262]|
2 | | 263 | -2 | 8 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/StaticsTest.out:
--------------------------------------------------------------------------------
1 | | RAM[0] |RAM[261]|RAM[262]|
2 | | 263 | -2 | 8 |
3 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/StaticsTest.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/StaticsTest/StaticsTest.tst
5 |
6 | load StaticsTest.asm,
7 | output-file StaticsTest.out,
8 | compare-to StaticsTest.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
10 |
11 | set RAM[0] 256,
12 |
13 | repeat 2500 {
14 | ticktock;
15 | }
16 |
17 | output;
18 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/StaticsTestVME.tst:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/StaticsTest/StaticsTestVME.tst
5 |
6 | load, // loads all the VM files from the current directory.
7 | output-file StaticsTest.out,
8 | compare-to StaticsTest.cmp,
9 | output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
10 |
11 | set sp 261,
12 |
13 | repeat 36 {
14 | vmstep;
15 | }
16 |
17 | output;
18 |
--------------------------------------------------------------------------------
/vmtranslator/vm/StaticsTest/Sys.vm:
--------------------------------------------------------------------------------
1 | // This file is part of www.nand2tetris.org
2 | // and the book "The Elements of Computing Systems"
3 | // by Nisan and Schocken, MIT Press.
4 | // File name: projects/08/FunctionCalls/StaticsTest/Sys.vm
5 |
6 | // Tests that different functions, stored in two different
7 | // class files, manipulate the static segment correctly.
8 | function Sys.init 0
9 | push constant 6
10 | push constant 8
11 | call Class1.set 2
12 | pop temp 0 // Dumps the return value
13 | push constant 23
14 | push constant 15
15 | call Class2.set 2
16 | pop temp 0 // Dumps the return value
17 | call Class1.get 0
18 | call Class2.get 0
19 | label WHILE
20 | goto WHILE
21 |
--------------------------------------------------------------------------------