Add solutions for part 1
This commit is contained in:
42
projects/12/MemoryTest/Main.jack
Normal file
42
projects/12/MemoryTest/Main.jack
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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/12/MemoryTest/Main.jack
|
||||
|
||||
/** Test program for the OS Memory class. */
|
||||
class Main {
|
||||
|
||||
/** Performs various memory manipulations. */
|
||||
function void main() {
|
||||
var int temp;
|
||||
var Array a, b, c;
|
||||
|
||||
do Memory.poke(8000, 333); // RAM[8000] = 333
|
||||
let temp = Memory.peek(8000);
|
||||
do Memory.poke(8001, temp + 1); // RAM[8001] = 334
|
||||
|
||||
let a = Array.new(3); // uses Memory.alloc
|
||||
let a[2] = 222;
|
||||
do Memory.poke(8002, a[2]); // RAM[8002] = 222
|
||||
|
||||
let b = Array.new(3);
|
||||
let b[1] = a[2] - 100;
|
||||
do Memory.poke(8003, b[1]); // RAM[8003] = 122
|
||||
|
||||
let c = Array.new(500);
|
||||
let c[499] = a[2] - b[1];
|
||||
do Memory.poke(8004, c[499]); // RAM[8004] = 100
|
||||
|
||||
do a.dispose(); // uses Memory.deAlloc
|
||||
do b.dispose();
|
||||
|
||||
let b = Array.new(3);
|
||||
let b[0] = c[499] - 90;
|
||||
do Memory.poke(8005, b[0]); // RAM[8005] = 10
|
||||
|
||||
do c.dispose();
|
||||
do b.dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
120
projects/12/MemoryTest/Memory.jack
Normal file
120
projects/12/MemoryTest/Memory.jack
Normal file
@@ -0,0 +1,120 @@
|
||||
// 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/12/Memory.jack
|
||||
|
||||
/**
|
||||
* This library provides two services: direct access to the computer's main
|
||||
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
|
||||
* consists of 32,768 words, each holding a 16-bit binary number.
|
||||
*/
|
||||
class Memory {
|
||||
static Array ram;
|
||||
static Array heap;
|
||||
static Array freeList;
|
||||
|
||||
/** Initializes the class. */
|
||||
function void init() {
|
||||
let ram = 0;
|
||||
let heap = 2048;
|
||||
let freeList = heap;
|
||||
let freeList[0] = 0; // next
|
||||
let freeList[1] = 14334; // length
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the RAM value at the given address. */
|
||||
function int peek(int address) {
|
||||
return ram[address];
|
||||
}
|
||||
|
||||
/** Sets the RAM value at the given address to the given value. */
|
||||
function void poke(int address, int value) {
|
||||
let ram[address] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Finds an available RAM block of the given size and returns
|
||||
* a reference to its base address. */
|
||||
function int alloc(int size) {
|
||||
var Array previousBlock;
|
||||
var Array currentBlock;
|
||||
var Array resultBlock;
|
||||
var int currentBlockSize;
|
||||
var int remainingSize;
|
||||
var int currentBlockNext;
|
||||
|
||||
if (freeList = 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX: I am not happy with having the whole code duplicated just because
|
||||
// we have the "special case" that we select the first block.
|
||||
|
||||
// Using the first block is a special case, because we have to
|
||||
// update freeList instead of simply taking the block out of the list
|
||||
// by doing `let previousBlock.next = currentBlock.next`.
|
||||
let currentBlockSize = freeList[1];
|
||||
if (currentBlockSize > size) {
|
||||
let remainingSize = currentBlockSize - size;
|
||||
let resultBlock = freeList;
|
||||
if (remainingSize < 4) {
|
||||
// If remainingSize is smaller than 4 it does not make sense to split
|
||||
// the block. Just return it as a whole.
|
||||
let freeList = freeList[0]; // point to freeList.next
|
||||
} else {
|
||||
// If remainingSize is big enough we split the block. In that case
|
||||
// we have to update the size of the block we return as well as
|
||||
// the block (aka the remainder of the current block).
|
||||
let resultBlock[1] = size;
|
||||
let freeList = resultBlock + 2 + size;
|
||||
let freeList[0] = resultBlock[0];
|
||||
let freeList[1] = currentBlockSize - size - 2;
|
||||
}
|
||||
return resultBlock + 2;
|
||||
}
|
||||
|
||||
let previousBlock = freeList;
|
||||
// The following excludes the first block which is what we want
|
||||
// because we handled it separately before.
|
||||
while (~(previousBlock[0] = 0)) {
|
||||
let currentBlock = previousBlock[0];
|
||||
let currentBlockSize = currentBlock[1];
|
||||
if (currentBlockSize > size) {
|
||||
let resultBlock = currentBlock;
|
||||
let remainingSize = currentBlockSize - size;
|
||||
if (remainingSize < 4) {
|
||||
let previousBlock[0] = resultBlock[0];
|
||||
} else {
|
||||
let resultBlock[1] = size;
|
||||
let currentBlock = resultBlock + 2 + size;
|
||||
let currentBlock[0] = resultBlock[0];
|
||||
let currentBlock[1] = currentBlockSize - size - 2;
|
||||
let previousBlock[0] = currentBlock;
|
||||
}
|
||||
return resultBlock;
|
||||
} else {
|
||||
let previousBlock = currentBlock;
|
||||
}
|
||||
}
|
||||
|
||||
// Not enough heap available. Call defragment and try again.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** De-allocates the given object (cast as an array) by making
|
||||
* it available for future allocations. */
|
||||
function void deAlloc(Array o) {
|
||||
var Array currentBlock;
|
||||
if (freeList = 0) {
|
||||
let freeList = o - 2;
|
||||
}
|
||||
let currentBlock = freeList;
|
||||
while (~(currentBlock[0] = 0)) {
|
||||
let currentBlock = currentBlock[0];
|
||||
}
|
||||
|
||||
let currentBlock[0] = o - 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
2
projects/12/MemoryTest/MemoryTest.cmp
Normal file
2
projects/12/MemoryTest/MemoryTest.cmp
Normal file
@@ -0,0 +1,2 @@
|
||||
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
|
||||
| 333 | 334 | 222 | 122 | 100 | 10 |
|
||||
15
projects/12/MemoryTest/MemoryTest.tst
Normal file
15
projects/12/MemoryTest/MemoryTest.tst
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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/12/MemoryTest/MemoryTest.tst
|
||||
|
||||
load,
|
||||
output-file MemoryTest.out,
|
||||
compare-to MemoryTest.cmp,
|
||||
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1;
|
||||
|
||||
repeat 1000000 {
|
||||
vmstep;
|
||||
}
|
||||
|
||||
output;
|
||||
Reference in New Issue
Block a user