From 69a32190dc5b74173b5fe9b5d7287a420a39a18d Mon Sep 17 00:00:00 2001 From: Nemo Date: Thu, 28 May 2020 18:07:07 +0530 Subject: [PATCH] 05/Memory --- NOTES.md | 51 ++++++++++++++++++++------------------- README.md | 2 +- projects/05/Memory.hdl | 39 +++++++++++++++++++++--------- projects/05/Memory.out | 54 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 projects/05/Memory.out diff --git a/NOTES.md b/NOTES.md index 0b8bc7a..f176897 100644 --- a/NOTES.md +++ b/NOTES.md @@ -14,30 +14,33 @@ PC Fill.asm : Figured out that my RAM16K implementation was wrong while working on this. The rough pseudocode would be: - ```c - int r0=*screen; - while(true) { - int color = 0; - if (*kbd > 0) { - color = -1; - } +```c +int r0=*screen; +while(true) { + int color = 0; + if (*kbd > 0) { + color = -1; + } - // This sets an entire row of pixels to color - // each row has 32 registers (512/16) that we set to color - *r0 = color; - *r0+1 = color; - *r0+2 = color; - *r0+3 = color; - *r0+4 = color; - // and so on - *r0+31 = color; + // This sets an entire row of pixels to color + // each row has 32 registers (512/16) that we set to color + *r0 = color; + *r0+1 = color; + *r0+2 = color; + *r0+3 = color; + *r0+4 = color; + // and so on + *r0+31 = color; - // if we are on the last row - if (r0-24575 <=0) { - r0 = *screen; - } - } + // if we are on the last row + if (r0-24575 <=0) { + r0 = *screen; + } +} - ``` - So every "cycle" of the loop, we are coloring an entire row. The row is decided by R0, which is set to @SCREEN at the start. So if you press a key while we are on the middle of the loop (say 120th row), everything from that row onwards would get painted in black, and then the loop resets r0=*screen once we cross the limits. The next iteration of the loop then starts filling the white pixels we'd left in the previous iteration. I kept the smallest paint unit as the row, but it doesn't really matter that much. The only difference is that I'm reading kbd a total of 256 times to paint the screen. Reading once per register also would work, and reading once per "screenfill" would also work. But that changes the 'delay' b/w your keyboard press and the screen fill start. I thought per row was a good compromise. - **assembly**: Since our assembly doesn't have any functions, writing Assembly is much tougher than I thought it would be. All state is global, there are no functions, and you can only jump using goto. +``` + +So every "cycle" of the loop, we are coloring an entire row. The row is decided by R0, which is set to @SCREEN at the start. So if you press a key while we are on the middle of the loop (say 120th row), everything from that row onwards would get painted in black, and then the loop resets r0=\*screen once we cross the limits. The next iteration of the loop then starts filling the white pixels we'd left in the previous iteration. I kept the smallest paint unit as the row, but it doesn't really matter that much. The only difference is that I'm reading kbd a total of 256 times to paint the screen. Reading once per register also would work, and reading once per "screenfill" would also work. But that changes the 'delay' b/w your keyboard press and the screen fill start. I thought per row was a good compromise. + +Memory +: Started by using a Mux4Way16, but then decided against making the same mistake I did in PC. Switched to 2 Mux16s instead. diff --git a/README.md b/README.md index f3719b9..990be65 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Counting number of instructions by `wc -l $file.hack` ## [Project 5: Computer Architecture](https://www.nand2tetris.org/project05) -- [ ] `Memory.hdl` +- [x] `Memory.hdl` (2xMux16, 2xNot, 3xAnd) - [ ] `CPU.hdl` - [ ] `Computer.hdl` diff --git a/projects/05/Memory.hdl b/projects/05/Memory.hdl index 1e46a75..b90c8c0 100644 --- a/projects/05/Memory.hdl +++ b/projects/05/Memory.hdl @@ -5,20 +5,20 @@ /** * The complete address space of the Hack computer's memory, - * including RAM and memory-mapped I/O. + * 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 + * 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 + * 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 book. */ @@ -27,5 +27,22 @@ CHIP Memory { OUT out[16]; PARTS: - // Put your code here: -} \ No newline at end of file + // loadscreen = address[14] && (!address[13]) && load + Not(in=address[13], out=notkbd); + And(a=address[14], b=notkbd, out=pickscreen); + And(a=pickscreen,b=load, out=loadscreen); + + // loadram = !address[14] && load + Not(in=address[14], out=pickram); + And(a=pickram,b=load, out=loadram); + RAM16K(in=in,load=loadram,address=address[0..13], out=ramout); + + // This is only called if MSB(address) == 1 + Screen(in=in, load=loadscreen, address=address[0..12], out=screenout); + Keyboard(out=kbdout); + + // MSB(0|1) = RAM|(screen|keyboard) + Mux16(a=ramout, b=kbdorscreenout, sel=address[14], out=out); + // address[13] = screen|keyboard + Mux16(a=screenout, b=kbdout, sel=address[13], out=kbdorscreenout); +} diff --git a/projects/05/Memory.out b/projects/05/Memory.out new file mode 100644 index 0000000..1dbf7ed --- /dev/null +++ b/projects/05/Memory.out @@ -0,0 +1,54 @@ +| in |load | address | out | +| -1 | 1 | 000000000000000 | 0 | +| -1 | 1 | 000000000000000 | -1 | +| 9999 | 0 | 000000000000000 | -1 | +| 9999 | 0 | 000000000000000 | -1 | +| 9999 | 0 | 010000000000000 | 0 | +| 9999 | 0 | 100000000000000 | 0 | +| 2222 | 1 | 010000000000000 | 0 | +| 2222 | 1 | 010000000000000 | 2222 | +| 9999 | 0 | 010000000000000 | 2222 | +| 9999 | 0 | 010000000000000 | 2222 | +| 9999 | 0 | 000000000000000 | -1 | +| 9999 | 0 | 100000000000000 | 0 | +| 9999 | 0 | 000000000000001 | 0 | +| 9999 | 0 | 000000000000010 | 0 | +| 9999 | 0 | 000000000000100 | 0 | +| 9999 | 0 | 000000000001000 | 0 | +| 9999 | 0 | 000000000010000 | 0 | +| 9999 | 0 | 000000000100000 | 0 | +| 9999 | 0 | 000000001000000 | 0 | +| 9999 | 0 | 000000010000000 | 0 | +| 9999 | 0 | 000000100000000 | 0 | +| 9999 | 0 | 000001000000000 | 0 | +| 9999 | 0 | 000010000000000 | 0 | +| 9999 | 0 | 000100000000000 | 0 | +| 9999 | 0 | 001000000000000 | 0 | +| 9999 | 0 | 010000000000000 | 2222 | +| 1234 | 1 | 001001000110100 | 0 | +| 1234 | 1 | 001001000110100 | 1234 | +| 1234 | 0 | 010001000110100 | 0 | +| 1234 | 0 | 110001000110100 | 0 | +| 2345 | 1 | 010001101000101 | 0 | +| 2345 | 1 | 010001101000101 | 2345 | +| 2345 | 0 | 000001101000101 | 0 | +| 2345 | 0 | 100001101000101 | 0 | +| 2345 | 0 | 110000000000000 | 75 | +| -1 | 1 | 100111111001111 | -1 | +| -1 | 1 | 101000001001111 | -1 | +| -1 | 1 | 000111111001111 | 0 | +| -1 | 1 | 010111111001111 | 0 | +| -1 | 0 | 100111111001110 | 0 | +| -1 | 0 | 100111111001101 | 0 | +| -1 | 0 | 100111111001011 | 0 | +| -1 | 0 | 100111111000111 | 0 | +| -1 | 0 | 100111111011111 | 0 | +| -1 | 0 | 100111111101111 | 0 | +| -1 | 0 | 100111110001111 | 0 | +| -1 | 0 | 100111101001111 | 0 | +| -1 | 0 | 100111011001111 | 0 | +| -1 | 0 | 100110111001111 | 0 | +| -1 | 0 | 100101111001111 | 0 | +| -1 | 0 | 100011111001111 | 0 | +| -1 | 0 | 101111111001111 | 0 | +| -1 | 0 | 110000000000000 | 89 |