diff --git a/05/CPU-external.tst b/05/CPU-external.tst new file mode 100644 index 0000000..d24bd12 --- /dev/null +++ b/05/CPU-external.tst @@ -0,0 +1,161 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/CPU-external.tst + +// Tests the CPU by setting the instruction input to various binary values that +// code Hack instructions, and outputting the values of the registers that are +// supposed to be affected by the instructions. + +load CPU.hdl, +output-file CPU-external.out, +compare-to CPU-external.cmp, +// Tracks the time, the CPU inputs (inM, instruction, reset bit), and the CPU +// outputs (outM, writeM bit, address, pc). +output-list time%S1.3.1 inM%D0.6.0 instruction%B0.16.0 reset%B2.1.2 outM%D1.6.0 writeM%B3.1.2 addressM%D1.5.1 pc%D0.5.0; + +set instruction %B0011000000111001, // @12345 +tick, output, tock, output; + +set instruction %B1110110000010000, // D=A +tick, output, tock, output; + +set instruction %B0101101110100000, // @23456 +tick, output, tock, output; + +set instruction %B1110000111110000, // AD=A-D +tick, output, tock, output; + +set instruction %B0000001111101011, // @1003 +tick, output, tock, output; + +set instruction %B1110001100001000, // M=D +tick, output, tock, output; + +set instruction %B0000001111101100, // @1004 +tick, output, tock, output; + +set instruction %B1110001110011000, // MD=D-1 +tick, output, tock, output; + +set instruction %B0000001111101000, // @1000 +tick, output, tock, output; + +set instruction %B1111010011110000, // AD=D-M +set inM 11111, +tick, output, tock, output; + +set instruction %B0000000000001110, // @14 +tick, output, tock, output; + +set instruction %B1110001100000100, // D;jlt +tick, output, tock, output; + +set instruction %B0000001111100111, // @999 +tick, output, tock, output; + +set instruction %B1111110111100000, // A=M+1 +tick, output, tock, output; + +set instruction %B1110001100101000, // AM=D +tick, output, tock, output; + +set instruction %B0000000000010101, // @21 +tick, output, tock, output; + +set instruction %B1110011111000010, // D+1;jeq +tick, output, tock, output; + +set instruction %B0000000000000010, // @2 +tick, output, tock, output; + +set instruction %B1110000010111000, // AMD=D+A +tick, output, tock, output; + +set instruction %B1111110111001000, // M=M+1 +tick, output, tock, output; + +set instruction %B1111110010101000, // AM=M-1 +tick, output, tock, output; + +set instruction %B0000001111101000, // @1000 +tick, output, tock, output; + +set instruction %B1110111010010000, // D=-1 +tick, output, tock, output; + +set instruction %B1110001100000001, // D;JGT +tick, output, tock, output; + +set instruction %B1110001100000010, // D;JEQ +tick, output, tock, output; + +set instruction %B1110001100000011, // D;JGE +tick, output, tock, output; + +set instruction %B1110001100000100, // D;JLT +tick, output, tock, output; + +set instruction %B1110001100000101, // D;JNE +tick, output, tock, output; + +set instruction %B1110001100000110, // D;JLE +tick, output, tock, output; + +set instruction %B1110001100000111, // D;JMP +tick, output, tock, output; + +set instruction %B1110101010010000, // D=0 +tick, output, tock, output; + +set instruction %B1110001100000001, // D;JGT +tick, output, tock, output; + +set instruction %B1110001100000010, // D;JEQ +tick, output, tock, output; + +set instruction %B1110001100000011, // D;JGE +tick, output, tock, output; + +set instruction %B1110001100000100, // D;JLT +tick, output, tock, output; + +set instruction %B1110001100000101, // D;JNE +tick, output, tock, output; + +set instruction %B1110001100000110, // D;JLE +tick, output, tock, output; + +set instruction %B1110001100000111, // D;JMP +tick, output, tock, output; + +set instruction %B1110111111010000, // D=1 +tick, output, tock, output; + +set instruction %B1110001100000001, // D;JGT +tick, output, tock, output; + +set instruction %B1110001100000010, // D;JEQ +tick, output, tock, output; + +set instruction %B1110001100000011, // D;JGE +tick, output, tock, output; + +set instruction %B1110001100000100, // D;JLT +tick, output, tock, output; + +set instruction %B1110001100000101, // D;JNE +tick, output, tock, output; + +set instruction %B1110001100000110, // D;JLE +tick, output, tock, output; + +set instruction %B1110001100000111, // D;JMP +tick, output, tock, output; + +set reset 1; +tick, output, tock, output; + +set instruction %B0111111111111111, // @32767 +set reset 0; +tick, output, tock, output; diff --git a/05/CPU.hdl b/05/CPU.hdl new file mode 100644 index 0000000..bc30e47 --- /dev/null +++ b/05/CPU.hdl @@ -0,0 +1,36 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/CPU.hdl +/** + * The Hack Central Processing unit (CPU). + * Parses the binary code in the instruction input and executes it according to the + * Hack machine language specification. In the case of a C-instruction, computes the + * function specified by the instruction. If the instruction specifies to read a memory + * value, the inM input is expected to contain this value. If the instruction specifies + * to write a value to the memory, sets the outM output to this value, sets the addressM + * output to the target address, and asserts the writeM output (when writeM = 0, any + * value may appear in outM). + * If the reset input is 0, computes the address of the next instruction and sets the + * pc output to that value. If the reset input is 1, sets pc to 0. + * Note: The outM and writeM outputs are combinational: they are affected by the + * instruction's execution during the current cycle. The addressM and pc outputs are + * clocked: although they are affected by the instruction's execution, they commit to + * their new values only in the next cycle. + */ +CHIP CPU { + + IN inM[16], // M value input (M = contents of RAM[A]) + instruction[16], // Instruction for execution + reset; // Signals whether to re-start the current + // program (reset==1) or continue executing + // the current program (reset==0). + + OUT outM[16], // M value output + writeM, // Write to M? + addressM[15], // Address in data memory (of M) + pc[15]; // address of next instruction + + PARTS: + //// Replace this comment with your code. +} \ No newline at end of file diff --git a/05/CPU.tst b/05/CPU.tst new file mode 100644 index 0000000..1057990 --- /dev/null +++ b/05/CPU.tst @@ -0,0 +1,161 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/CPU.tst + +// Tests the CPU by setting the instruction input to various binary values that +// code Hack instructions, and outputting the values of the registers that are +// supposed to be affected by the instructions. + +load CPU.hdl, +output-file CPU.out, +compare-to CPU.cmp, +// Tracks the time, the CPU inputs (inM, instruction, reset bit), the CPU +// outputs (outM, writeM bit, address, pc), and the value of the D-register. +output-list time%S1.3.1 inM%D0.6.0 instruction%B0.16.0 reset%B2.1.2 outM%D1.6.0 writeM%B3.1.2 addressM%D1.5.1 pc%D0.5.0 DRegister[]%D1.7.1; + +set instruction %B0011000000111001, // @12345 +tick, output, tock, output; + +set instruction %B1110110000010000, // D=A +tick, output, tock, output; + +set instruction %B0101101110100000, // @23456 +tick, output, tock, output; + +set instruction %B1110000111110000, // AD=A-D +tick, output, tock, output; + +set instruction %B0000001111101011, // @1003 +tick, output, tock, output; + +set instruction %B1110001100001000, // M=D +tick, output, tock, output; + +set instruction %B0000001111101100, // @1004 +tick, output, tock, output; + +set instruction %B1110001110011000, // MD=D-1 +tick, output, tock, output; + +set instruction %B0000001111101000, // @1000 +tick, output, tock, output; + +set instruction %B1111010011110000, // AD=D-M +set inM 11111, +tick, output, tock, output; + +set instruction %B0000000000001110, // @14 +tick, output, tock, output; + +set instruction %B1110001100000100, // D;jlt +tick, output, tock, output; + +set instruction %B0000001111100111, // @999 +tick, output, tock, output; + +set instruction %B1111110111100000, // A=M+1 +tick, output, tock, output; + +set instruction %B1110001100101000, // AM=D +tick, output, tock, output; + +set instruction %B0000000000010101, // @21 +tick, output, tock, output; + +set instruction %B1110011111000010, // D+1;jeq +tick, output, tock, output; + +set instruction %B0000000000000010, // @2 +tick, output, tock, output; + +set instruction %B1110000010111000, // AMD=D+A +tick, output, tock, output; + +set instruction %B1111110111001000, // M=M+1 +tick, output, tock, output; + +set instruction %B1111110010101000, // AM=M-1 +tick, output, tock, output; + +set instruction %B0000001111101000, // @1000 +tick, output, tock, output; + +set instruction %B1110111010010000, // D=-1 +tick, output, tock, output; + +set instruction %B1110001100000001, // D;JGT +tick, output, tock, output; + +set instruction %B1110001100000010, // D;JEQ +tick, output, tock, output; + +set instruction %B1110001100000011, // D;JGE +tick, output, tock, output; + +set instruction %B1110001100000100, // D;JLT +tick, output, tock, output; + +set instruction %B1110001100000101, // D;JNE +tick, output, tock, output; + +set instruction %B1110001100000110, // D;JLE +tick, output, tock, output; + +set instruction %B1110001100000111, // D;JMP +tick, output, tock, output; + +set instruction %B1110101010010000, // D=0 +tick, output, tock, output; + +set instruction %B1110001100000001, // D;JGT +tick, output, tock, output; + +set instruction %B1110001100000010, // D;JEQ +tick, output, tock, output; + +set instruction %B1110001100000011, // D;JGE +tick, output, tock, output; + +set instruction %B1110001100000100, // D;JLT +tick, output, tock, output; + +set instruction %B1110001100000101, // D;JNE +tick, output, tock, output; + +set instruction %B1110001100000110, // D;JLE +tick, output, tock, output; + +set instruction %B1110001100000111, // D;JMP +tick, output, tock, output; + +set instruction %B1110111111010000, // D=1 +tick, output, tock, output; + +set instruction %B1110001100000001, // D;JGT +tick, output, tock, output; + +set instruction %B1110001100000010, // D;JEQ +tick, output, tock, output; + +set instruction %B1110001100000011, // D;JGE +tick, output, tock, output; + +set instruction %B1110001100000100, // D;JLT +tick, output, tock, output; + +set instruction %B1110001100000101, // D;JNE +tick, output, tock, output; + +set instruction %B1110001100000110, // D;JLE +tick, output, tock, output; + +set instruction %B1110001100000111, // D;JMP +tick, output, tock, output; + +set reset 1; +tick, output, tock, output; + +set instruction %B0111111111111111, // @32767 +set reset 0; +tick, output, tock, output; diff --git a/05/Computer.hdl b/05/Computer.hdl new file mode 100644 index 0000000..e5cb1e3 --- /dev/null +++ b/05/Computer.hdl @@ -0,0 +1,22 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/Computer.hdl +/** + * The Hack computer, consisting of CPU, ROM and RAM. + * When reset = 0, the program stored in the ROM executes. + * When reset = 1, the program's execution restarts. + * Thus, to start running the currently loaded program, + * set reset to 1, and then set it to 0. + * From this point onwards, the user is at the mercy of the software. + * Depending on the program's code, and whether the code is correct, + * the screen may show some output, the user may be expected to enter + * some input using the keyboard, or the program may do some procerssing. + */ +CHIP Computer { + + IN reset; + + PARTS: + //// Replace this comment with your code. +} diff --git a/05/ComputerAdd.tst b/05/ComputerAdd.tst new file mode 100644 index 0000000..a8baa28 --- /dev/null +++ b/05/ComputerAdd.tst @@ -0,0 +1,35 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/ComputerAdd.tst + +// Tests the Computer chip by having it execute the program Add.hack. +// The program adds up the constants 2 and 3 and writes the result in RAM[0]. + +load Computer.hdl, +output-file ComputerAdd.out, +compare-to ComputerAdd.cmp, +// Tracks the values of the time, reset bit, A-register, D-register, +// program counter, R0, R1, and R2. +output-list time%S1.3.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; + +// Loads the binary program Add.hack into the computer's instruction memory +ROM32K load Add.hack, +output; + +// First run (at the beginning PC=0) +repeat 6 { + tick, tock, output; +} + +// Resets the PC +set reset 1, +set RAM16K[0] 0, +tick, tock, output; + +// Second run, to check that the PC was reset correctly. +set reset 0, + +repeat 6 { + tick, tock, output; +} diff --git a/05/ComputerMax.tst b/05/ComputerMax.tst new file mode 100644 index 0000000..b60c22c --- /dev/null +++ b/05/ComputerMax.tst @@ -0,0 +1,41 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/ComputerMax.tst + +// Tests the Computer chip by having it execute the program Max.hack. +// The program computes maximum(R0, R1) and writes the result in RAM[2]. + +load Computer.hdl, +output-file ComputerMax.out, +compare-to ComputerMax.cmp, +// Tracks the values of the time, reset bit, A-register, D-register, +// program counter, R0, R1, and R2. +output-list time%S1.3.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; + +// Loads the binary program Add.hack into the computer's instruction memory +ROM32K load Max.hack, + +// first run: computes max(3,5) +set RAM16K[0] 3, +set RAM16K[1] 5, +output; + +repeat 14 { + tick, tock, output; +} + +// resets the PC +set reset 1, +tick, tock, output; + +// second run: computes max(23456,12345) +set reset 0, +set RAM16K[0] 23456, +set RAM16K[1] 12345, +output; + +// The run on these inputs requires less cycles (different branching) +repeat 10 { + tick, tock, output; +} diff --git a/05/ComputerRect.tst b/05/ComputerRect.tst new file mode 100644 index 0000000..73d5ae0 --- /dev/null +++ b/05/ComputerRect.tst @@ -0,0 +1,29 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/ComputerRect.tst + +// Tests the Computer chip by having it execute the program Rect.hack. +// The program draws a rectangle of width 16 pixels and length RAM[0] +// at the top left corner of the screen. + +load Computer.hdl, +output-file ComputerRect.out, +compare-to ComputerRect.cmp, +// Tracks the values of the time, A-register, D-register, program counter, R0, R1, and R2. +output-list time%S1.3.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; + +// Loads the binary program Rect.hack into the computer's instruction memory +ROM32K load Rect.hack, + +echo "Before you run this script, select the 'Screen' option from the 'View' menu"; + +echo "A small rectangle should be drawn at the top left of the screen (the 'Screen' option of the 'View' menu should be selected.)"; + +// Draws a rectangle consisting of 4 rows (each 16 pixels wide) +set RAM16K[0] 4, +output; + +repeat 63 { + tick, tock, output; +} diff --git a/05/Memory.hdl b/05/Memory.hdl new file mode 100644 index 0000000..79df0e2 --- /dev/null +++ b/05/Memory.hdl @@ -0,0 +1,29 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/5/Memory.hdl +/** + * The complete address space of the Hack computer's memory, + * including RAM and memory-mapped I/O. + * The chip facilitates read and write operations, as follows: + * Read: out(t) = Memory[address(t)](t) + * Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1) + * In words: the chip always outputs the value stored at the memory + * location specified by address. If load=1, the in value is loaded + * into the memory location specified by address. This value becomes + * available through the out output from the next time step onward. + * Address space rules: + * Only the upper 16K+8K+1 words of the Memory chip are used. + * Access to address>0x6000 is invalid. Access to any address in + * the range 0x4000-0x5FFF results in accessing the screen memory + * map. Access to address 0x6000 results in accessing the keyboard + * memory map. The behavior in these addresses is described in the Screen + * and Keyboard chip specifications given in the lectures and the book. + */ +CHIP Memory { + IN in[16], load, address[15]; + OUT out[16]; + + PARTS: + //// Replace this comment with your code. +} \ No newline at end of file diff --git a/05/Memory.tst b/05/Memory.tst new file mode 100644 index 0000000..5d504a7 --- /dev/null +++ b/05/Memory.tst @@ -0,0 +1,191 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/05/Memory.tst + +// Tests the Memory chip by inputting values to selected addresses, +// verifying that these addresses were indeed written to, and verifying +// that other addresses were not accessed by mistake. In particular, we +// focus on probing the registers in addresses 'lower RAM', 'upper RAM', +// and 'Screen', which correspond to 0, %X2000, and %X4000 in Hexadecimal +// (0, 8192 (8K), and 16385 (16K+1) in decimal). + +load Memory.hdl, +output-file Memory.out, +compare-to Memory.cmp, +output-list in%D1.6.1 load%B2.1.2 address%B1.15.1 out%D1.6.1; + +echo "Before you run this script, select the 'Screen' option from the 'View' menu"; + +// We've noticed a common design mistake in several students' Memory.hdl files. +// This error leads to zeros being written in the offset of inactive memory segments +// instead of the intended location. To identify this issue, the test should check not +// only for incorrect writes into the wrong segment but also for any unexpected changes. +// To prepare for this, we've initialized the memory with a specific number in the areas +// where these erroneous writes might happen. + +//// Sets RAM[2000], RAM[4000] = 12345 (for the following overwrite test) +set in 12345, set load 1, set address %X2000, tick, output; tock, output; +set address %X4000, tick, output; tock, output; + +set in -1, // Sets RAM[0] = -1 +set load 1, +set address 0, +tick, +output; +tock, +output; + +set in 9999, // RAM[0] holds value +set load 0, +tick, +output; +tock, +output; + +set address %X2000, // Did not also write to upper RAM or Screen +eval, +output; +set address %X4000, +eval, +output; + +//// Sets RAM[0], RAM[4000] = 12345 (for following overwrite test) +set in 12345, set load 1, set address %X0000, tick, output; tock, output; +set address %X4000, tick, output; tock, output; + +set in 2222, // Sets RAM[2000] = 2222 +set load 1, +set address %X2000, +tick, +output; +tock, +output; + +set in 9999, // RAM[2000] holds value +set load 0, +tick, +output; +tock, +output; + +set address 0, // Did not also write to lower RAM or Screen +eval, +output; +set address %X4000, +eval, +output; + +set load 0, // Low order address bits connected +set address %X0001, eval, output; +set address %X0002, eval, output; +set address %X0004, eval, output; +set address %X0008, eval, output; +set address %X0010, eval, output; +set address %X0020, eval, output; +set address %X0040, eval, output; +set address %X0080, eval, output; +set address %X0100, eval, output; +set address %X0200, eval, output; +set address %X0400, eval, output; +set address %X0800, eval, output; +set address %X1000, eval, output; +set address %X2000, eval, output; + +set address %X1234, // RAM[1234] = 1234 +set in 1234, +set load 1, +tick, +output; +tock, +output; + +set load 0, +set address %X2234, // Did not also write to upper RAM or Screen +eval, output; +set address %X6234, +eval, output; + +set address %X2345, // RAM[2345] = 2345 +set in 2345, +set load 1, +tick, +output; +tock, +output; + +set load 0, +set address %X0345, // Did not also write to lower RAM or Screen +eval, output; +set address %X4345, +eval, output; + +//// Clears the overwrite detection value from the screen +set in 0, set load 1, set address %X4000, tick, output; tock, output; + +// Keyboard test + +set address 24576, +echo "Click the Keyboard icon and hold down the 'K' key (uppercase) until you see the next message...", +// It's important to keep holding the key down since if the system is busy, +// the memory will zero itself before being outputted. + +while out <> 75 { + tick, tock, // tick, tock prevents hang if sync. parts used in KB path. +} + +clear-echo, +output; + +// Screen test + +//// Sets RAM[0FCF], RAM[2FCF] = 12345 (for following overwrite test) +set in 12345, set load 1, set address %X0FCF, tick, output; tock, output; +set address %X2FCF, tick, output; tock, output; + +set load 1, +set in -1, +set address %X4FCF, +tick, +tock, +output, + +set address %X504F, +tick, +tock, +output; + +set address %X0FCF, // Did not also write to lower or upper RAM +eval, +output; +set address %X2FCF, +eval, +output; + +set load 0, // Low order address bits connected +set address %X4FCE, eval, output; +set address %X4FCD, eval, output; +set address %X4FCB, eval, output; +set address %X4FC7, eval, output; +set address %X4FDF, eval, output; +set address %X4FEF, eval, output; +set address %X4F8F, eval, output; +set address %X4F4F, eval, output; +set address %X4ECF, eval, output; +set address %X4DCF, eval, output; +set address %X4BCF, eval, output; +set address %X47CF, eval, output; +set address %X5FCF, eval, output; + +set load 0, +set address 24576, +echo "Two horizontal lines should be in the middle of the screen. Hold down 'Y' (uppercase) until you see the next message ...", +// It's important to keep holding the key down since if the system is busy, +// the memory will zero itself before being outputted. + +while out <> 89 { + tick, tock, // tick, tock prevents hang if sync. parts used in KB path. +} + +clear-echo, +output;