05/Memory

This commit is contained in:
Nemo 2020-05-28 18:07:07 +05:30
parent 262e336fcd
commit 69a32190dc
4 changed files with 110 additions and 36 deletions

View File

@ -14,30 +14,33 @@ PC
Fill.asm Fill.asm
: Figured out that my RAM16K implementation was wrong while working on this. The rough pseudocode would be: : Figured out that my RAM16K implementation was wrong while working on this. The rough pseudocode would be:
```c ```c
int r0=*screen; int r0=*screen;
while(true) { while(true) {
int color = 0; int color = 0;
if (*kbd > 0) { if (*kbd > 0) {
color = -1; color = -1;
} }
// This sets an entire row of pixels to color // This sets an entire row of pixels to color
// each row has 32 registers (512/16) that we set to color // each row has 32 registers (512/16) that we set to color
*r0 = color; *r0 = color;
*r0+1 = color; *r0+1 = color;
*r0+2 = color; *r0+2 = color;
*r0+3 = color; *r0+3 = color;
*r0+4 = color; *r0+4 = color;
// and so on // and so on
*r0+31 = color; *r0+31 = color;
// if we are on the last row // if we are on the last row
if (r0-24575 <=0) { if (r0-24575 <=0) {
r0 = *screen; 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.

View File

@ -61,7 +61,7 @@ Counting number of instructions by `wc -l $file.hack`
## [Project 5: Computer Architecture](https://www.nand2tetris.org/project05) ## [Project 5: Computer Architecture](https://www.nand2tetris.org/project05)
- [ ] `Memory.hdl` - [x] `Memory.hdl` (2xMux16, 2xNot, 3xAnd)
- [ ] `CPU.hdl` - [ ] `CPU.hdl`
- [ ] `Computer.hdl` - [ ] `Computer.hdl`

View File

@ -5,20 +5,20 @@
/** /**
* The complete address space of the Hack computer's memory, * 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: * The chip facilitates read and write operations, as follows:
* Read: out(t) = Memory[address(t)](t) * Read: out(t) = Memory[address(t)](t)
* Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1) * 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 * In words: the chip always outputs the value stored at the memory
* location specified by address. If load==1, the in value is loaded * location specified by address. If load==1, the in value is loaded
* into the memory location specified by address. This value becomes * into the memory location specified by address. This value becomes
* available through the out output from the next time step onward. * available through the out output from the next time step onward.
* Address space rules: * Address space rules:
* Only the upper 16K+8K+1 words of the Memory chip are used. * Only the upper 16K+8K+1 words of the Memory chip are used.
* Access to address>0x6000 is invalid. Access to any address in * Access to address>0x6000 is invalid. Access to any address in
* the range 0x4000-0x5FFF results in accessing the screen memory * the range 0x4000-0x5FFF results in accessing the screen memory
* map. Access to address 0x6000 results in accessing the keyboard * map. Access to address 0x6000 results in accessing the keyboard
* memory map. The behavior in these addresses is described in the * memory map. The behavior in these addresses is described in the
* Screen and Keyboard chip specifications given in the book. * Screen and Keyboard chip specifications given in the book.
*/ */
@ -27,5 +27,22 @@ CHIP Memory {
OUT out[16]; OUT out[16];
PARTS: PARTS:
// Put your code here: // 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);
}

54
projects/05/Memory.out Normal file
View File

@ -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 |