From 9542deeb483a00b6fabed7574720926ce97d7511 Mon Sep 17 00:00:00 2001 From: Frederick Yin Date: Tue, 16 Aug 2022 11:54:23 +0800 Subject: Projects, 01-06 completed --- projects/12/MemoryTest/MemoryDiag/Main.jack | 183 ++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 projects/12/MemoryTest/MemoryDiag/Main.jack (limited to 'projects/12/MemoryTest/MemoryDiag/Main.jack') diff --git a/projects/12/MemoryTest/MemoryDiag/Main.jack b/projects/12/MemoryTest/MemoryDiag/Main.jack new file mode 100644 index 0000000..de439d0 --- /dev/null +++ b/projects/12/MemoryTest/MemoryDiag/Main.jack @@ -0,0 +1,183 @@ +// 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 { + + /** Test Memory.peek(), poke(), alloc() and deAlloc(). + * + * This test is also a diagnostic. RAM[17000] is incremented before and + * after every call so that the failure point can be accurately determined + * when using command line testing. Return values from all alloc() calls + * are also stored in the test results to aid debugging. + */ + function void main() { + var int temp; + var Array a, b, c, out; + + let out = 17000; // Address where test results will be stored. + + // Test poke() and peek(). + + let out[0] = 10; // poke test + do Memory.poke(out + 1, 333); // RAM[17001] = 333 + + let out[0] = 11; // peek test + let temp = Memory.peek(out + 1); + let out[2] = temp + 1; // RAM[17002] = 334 + let out[0] = 12; // peek/poke test complete + + // Allocate a memory block. + // Validate that the returned block is entirely within the heap, + // Test aborts if the block is not valid. + + let out[0] = 20; + let a = Memory.alloc(20); + let out[3] = a; // RAM[17003] = block address + + let out[0] = 21; + do Main.checkRange(a, 20); + let out[0] = 22; + + // Allocate a SMALLER memory block. + // Validate that the returned block is entirely within the heap, + // and that it does not overlap block 'a'. + // Test aborts if the block is not valid or overlaps. + // + // Common failure: first block was not removed from free list so space + // for this block was found within the first block. + + let out[0] = 30; + let b = Memory.alloc(3); + let out[4] = b; // RAM[17004] = block address + + let out[0] = 31; + do Main.checkRange(b, 3); + let out[0] = 32; + do Main.checkOverlap(b, 3, a, 3); + let out[0] = 33; + + // Allocate a memory block. + // Validate that the returned block is entirely within the heap, + // and that it does not overlap blocks 'a' or 'b'. + // Test aborts if the block is not valid or overlaps. + + let out[0] = 40; + let c = Memory.alloc(500); + let out[5] = c; // RAM[17005] = block address + + let out[0] = 41; + do Main.checkRange(c, 500); + let out[0] = 42; + do Main.checkOverlap(c, 500, a, 3); + let out[0] = 43; + do Main.checkOverlap(c, 500, b, 3); + let out[0] = 44; + + // Deallocate blocks 'a' and 'b', retaining 'c'. + // + // Common failure: free list corrupted by deAlloc(). + + let out[0] = 50; + do Memory.deAlloc(a); + + let out[0] = 51; + do Memory.deAlloc(b); + let out[0] = 52; + + // Allocate a memory block. + // Validate that the returned block is entirely within the heap, + // and that it does not overlap blocks 'c'. + // Test aborts if the block is not valid or overlaps. + // + // Common failure: free list corrupted by deAlloc(). + + let out[0] = 60; + let b = Memory.alloc(3); + let out[6] = b; // RAM[17006] = block address + + let out[0] = 61; + do Main.checkRange(b, 3); + let out[0] = 62; + do Main.checkOverlap(b, 3, c, 500); + let out[0] = 63; + + // Deallocate blocks 'b' and 'c'. + + let out[0] = 70; + do Memory.deAlloc(c); + + let out[0] = 71; + do Memory.deAlloc(b); + let out[0] = 72; + + // Test that deallocated blocks are placed on the free list and can + // be reused. + + let out[0] = 70; + let a = Memory.alloc(8000); + let out[7] = a; // RAM[17007] = block address + + let out[0] = 71; + do Main.checkRange(a, 8000); + + let out[0] = 72; + do Memory.deAlloc(a); + + let out[0] = 73; + let a = Memory.alloc(7000); + + let out[0] = 74; + do Main.checkRange(a, 7000); + + let out[0] = 75; + do Memory.deAlloc(a); + let out[8] = a; // RAM[17008] = block address + + // Test complete. + let out[0] = 100; + + // At this point all allocated blocks have been deallocated. + // + // You can inspect the free list and confirm that all of the heap is + // contained in the free segments. + // + // If you implemented defragmentation in dealloc(), the free list + // should contain only one segment, consisting of the entire heap. + + return; + } + + + /** Check that block a(a_len) is in the heap. + * + * If the block begins or ends outside of the heap, calls Sys.halt() + */ + function void checkRange(int a, int a_len) { + var int a_high; + let a_high = (a + a_len)-1; + if ((a < 2048) | ((a_high) > 16383)) { + // Block is not entirely within heap. + do Sys.halt(); + } + return; + } + + /** Check that block a(a_len) does not overlap block b(b_len). + * Assumes that both blocks have been range checked. + * + * If the blocks overlap, calls Sys.halt() + */ + function void checkOverlap(int a, int a_len, int b, int b_len) { + var int a_high, b_high; + let a_high = (a + a_len)-1; + let b_high = (b + b_len)-1; + if ( ~ ((a > b_high) | (a_high < b))) { + // Block overlaps excluded range. + do Sys.halt(); + } + return; + } +} -- cgit v1.2.3