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
: 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.

View File

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

View File

@ -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:
}
// 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 |