├── .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 | レシピページのDemo Gif 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 | ![cpu](https://user-images.githubusercontent.com/57289763/140737209-5759bd5c-e476-471f-bfb0-8cb00b0610a1.gif) 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 | ![hardware](https://user-images.githubusercontent.com/57289763/141056794-0eeefb5c-a7ee-458c-b8e6-1ab105b9a735.gif) 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 | --------------------------------------------------------------------------------