Nand2Tetris
Learning Computer by Building It
About the Speaker
● YehBan (aka: Yodalee)
● Blogger: http://yodalee.blogspot.tw/
● Programmer: https://github.com/yodalee
Outline
● Introduction to Nand2Tetris
● Detail content in each week
○ Part 1:
■ Week 1, 2: Nand to ALU
■ Week 3, 5: Sequential Logic to CPU
■ Week 4, 6: Assembly and Assembler
○ Part 2:
■ Week 1, 2: Stack Virtual Machine
■ Week 4, 5: Jack Compiler
■ Week 6: Runtime and OS
Introduction
● Course designed by Noam Nisan and Shimon Schocken
of Hebrew University of Jerusalem
● Build a computer from Nand Gate, and take a glance at
the mystery of computer
● Open on coursera
○ https://www.coursera.org/learn/build-a-computer
○ https://www.coursera.org/learn/nand2tetris2
https://www.ted.com/talks/shimon_schocken_the_self_organizing_computer_course
Course Diagram from Textbook
Part 1 week 1, 2: Nand to ALU
Combinational Circuit
From the Beginning: Nand
A B Nand(A, B)
0 0 1
0 1 1
1 0 1
1 1 0
● Nand is one kind of basic logic gate
○ Why Nand, not Nor?
● The truth table of Nand
https://electronics.stackexchange.com/questions/110649/why-is-nand-gate-preferred-over-nor-gate-in-industry
Nand is functionally complete
● Nand(X, X) == Not(X)
● Not(Nand(X, Y)) == And(X, Y)
● Nand(Not(X), Not(X)) == Or(X, Y)
○ (A+B)’’ = (A’B’)’
● Or(And(X, Not(Y)), And(Not(X), Y)) == Xor(X, Y)
● Given A, B, sel
○ Or(And(A, sel), And(B, Not(sel))) => Mux(A, B, sel)
● Given in, sel
○ A = And(in, sel); B = And(in, not(sel)) => Demux(in, sel)
https://en.wikipedia.org/wiki/Functional_completeness#Minimal_functionally_complete_operator_sets
More complex
● Extend to 16 bits gates
○ 16 way OR, AND, Mux, DMux ...
● Full Adder: Xor + And + Or
○ Extend to 16 bits Full Adder
● Custom ALU
○ Data in/out x, y/out
○ Control: zx, nx, zy, ny, f, no
○ Out bit: zr, ng
ALU Component in Detail
mux for zx,
zy
mux for nx, ny
Select
x+y or x & y Mux with no
Part 1 week 3:
Sequential Circuit
Sequential Circuit
● D Flip-Flop (Treat as basic element in course)
● Can be realized by connecting D-latch
D-Register & memory
Combine registers -> memory
D-Register
D-Register
D-Register
D-Register
D-Register
D-Register
D-Register
D-Register
Mux
Address
Demux
Address
Load input into D flip
flop when load is 1
Program Counter
Reset = 1 Out = 0 Boot
Load = 1 Out = Input Jump
Inc = 1 Out = Out + 1 Normal
execution
Part 1 Week 4, 5:
Instruction Set, CPU and Computer
A computer
● ROM: Store Instruction
● Memory
○ General memory 16 KB
○ Screen: 8 KB
○ Keyboard: 1 bytes
CPU Inside:Two Register
Address
Register
Data Register
Instruction Overview
● A Instruction: MSB = 0, load [14:0] to A register
○ Ex. 0000 0000 0000 0111: load 7 into A
● C Instruction: MSB = 1, format: 111A CCCCCC DDD JJJ
○ A: Data selection C: Arithmetic select
○ D: Destination select J: Jump select
C instruction: 111A CCCCCC DDD JJJ
Same as ALU, (X, Y) = (D, A) or (D, M), select by
A
CCCCC
C
A or C
instruction
CPU Inside
From
ROM
From
Memory
To memory
To ROM0
A or C
instruction
C instruction: 111A CCCCCC DDD JJJ
Select target register and memory
d2
d3
A or d1
CPU Inside:
destination
From
ROM
From
Memory
To memory
To ROM
C instruction: 111A CCCCCC DDD JJJ
Jump condition
CPU Inside: Jump Address
From
ROM
From
Memory
To memory
To ROM
Address Register: Store address
for Jump and memory access
JJJ and ALU output
A computer
● ROM: Instruction
● Memory
○ General memory 16 KB
○ Screen: 8 KB
○ Keyboard: 1 bytes
Part 1 Week 6:
Assembly
Hack Assembly
1. A instruction -> “@number” //load number into A register
2. Support label, like
(label) //define label
@label //load label address to A register
3. C instruction -> “dest = comp; jump"
a. Dest: combination of DMA
b. Comp: arithmetic on register
c. Jump: Jump condition
Ex. A = D+A; JMP
dest = comp; jump
Comp
Dest
Jump
Comp
Some Constant Label
Label Label Value
R0-R15 0-15
SP, LCL, ARG, THIS,
THAT
0, 1, 2, 3, 4
SCREEN 16384
KBD 24576
Some example and Assembler
//Memory[0] = 5
@2
D=A
@3
D=D+A
@0
M=D
//data+=32
@data
D=M
@32
D=D+A
@data
M=D
//loop 10 times
@10
D=A
@counter
M=D
(loop)
...
@counter
MD=M-1
@loop
D; JGT
Implement an Assembler
1. Scan (label) in program, record the address
2. Translate @label, @const to A instruction bitcode
3. Translate C instruction
● Directly map “string” to bitcode
● If Dest has M -> A = 1
● M -> 001, D -> 010, MD -> 011 ...
● JGT -> 001, JEQ -> 010, JMP -> 111 …
4. Input Assembly; Output Bitcode that can be programmed
to instruction ROM
Part 2 Week 1, 2:
Stack Virtual Machine
Stack Virtual Machine
● A structural way to manage
memory
● Using push/pop to manage the
top of stack
○ Ex. push constant 3, pop local 0
○ Ex. push constant 0, pop argument 0
Addr Start Push Pop
(SP) 258 259 258
(LCL) 256 256 256
... ... ... ...
256 0 0 3
257 0 0 0
258 0 3 3
259 0 0 0
Memory Segment
Section Memory addr
SP 0
LCL 1
ARG 2
THIS(class) 3
THAT(array
)
4
TEMP 5-12
Section Memory addr
register 13-15
Static 16-255
Stack 256-2048
Heap 2048-16384
Screen 16384-24576
Keyboard0 24576-24577
Stack Virtual Machine
● Push/Pop command, possible target
Constant Push only
Static File-scope static variable
Pointer Push/Pop to THIS/THAT register
Temp
Local Local variable in function
Argument Function argument
This Class
That Array
Stack Virtual Machine
● Arithmetic command like:
○ Add, sub, lt, gt, eq, and, or
○ not, neg
Addr Start Add Sub lt neg
SP 258 257 257 257 258
256 3 10 -4 -1 3
257 7 7 7 7 -7
Stack Virtual Machine
● Control command:
○ Label, goto, if-goto
● Function call and Return
○ Function functionname #locals
○ Call functionname #args
function Sys.main 0
push constant 123
call Sys.add42 1
pop temp 0
push constant 246
return
function Sys.add42 0
push argument 0
push constant 42
add
return
Implement Stack Machine in Assembly
//Push constant 7
@7
D=A
@SP
A=M
M=D
@SP
M=M+1
//Add
@SP
M=M-1
A=M
D=M
@SP
M=M-1
A=M
M=M+D
@SP
M=M+1
//Pop local 1
@1
D=A
@LCL
A=M
D=A+D
@R13
M=D
@SP
A=M
D=M
@R13
A=M
M=D
//Label, if-goto
@(file.LOOP)
@SP
M=M-1
A=M
D=M
@file.LOOP
D; JNE
Implement Stack Machine in Assembly
N Argument
Return Address
Preserve LCL
Preserve ARG
Preserve THIS
Preserve THAT
M Local Variable
Stack
New
ARG
New LCL
//Calling steps:
● Push argument
● Push Return Address
● Preserve Register
● ARG = SP - 5 - #Args
● LCL = SP
● @FunctionBody
● Jump
//Return steps:
● LCL -> R13
● Return Address ->
R14
● Copy Return value
(stack top) to ARG
● SP to ARG+1
● Restore Register
● Jump to Return
Address
//Function Body:
Push Stack M times for Local Variable
Boot
//Initial Stack
@256
D=A
@SP
M=D
@Sys.init
Jump
● Initialize stack in the first command
○ Start from ROM[0]
● Sys.init will call Main.main
● Sys.init will never return, usually go into
an infinite loop
Now we have an easy to use
computer
Part 2 Week 4, 5:
High Level Programming Language
High Level Programming Language and its Compiler
● Jack: high level programming language
○ Support Array and Class
○ No inheritance
● A compiler translate high level programming language to
VM implementation
○ Tokenizer
○ Syntax Analyzer
○ Code Generator
Tokenizer
while (i < length) {
let i = i + 1;
}
whil
e
( i < length ) { let
i = i + 1 ; }
Jack Grammar
● Most LL(1) LL1.5 grammar
○ No arithmetic precedence
Make it LL(1) in statements
LL(2) here
Code Generation: Symbol Table
● A table save the id of each variable
var Array a;
var int length;
var int i, sum;
let i = 0;
while (i < length)
a LCL 0
length LCL 1
i LCL 2
sum LCL 3
push constant 0
pop local 2
label Lwhile0
push local 2
push local 1
lt
not
if-goto Lwhile1
Code Generation: Object
● Size of class is constant at compile time
● Translate object constructor (special name “new”):
○ Alloc memory
○ Save to THIS register
○ Return THIS register
● Translate object method: ex. obj.method(arg1, arg2):
○ Push obj as Argument 0
○ Push Argument 1, Argument 2
○ Call method
○ In method: Save Argument 0 to THIS register
Code Generation: Array
● Array will call Array.new to allocate memory, save result to
variable (the address of Array)
● Access Array arr[expr]
○ Calculate index expr
○ Add arr address and index
○ Pop to THAT register
○ Push/Pop THAT register content
● Complex example: arrA[exprA] = arrB[exprB]
Part 2 Week 6:
Library and (part of) OS
Implement OS service
● Array // Array function
● Keyboard // read keyboard input
● Math // multiply, divide, power
● Memory // peek, poke, alloc, dealloc
● Output // Print text on screen
● Screen // Draw line, rectangle, circle on Screen
● String // String related function
● Sys // init, halt
http://nand2tetris.org/projects/12/Jack%20OS%20API.pdf
Memory: peek/poke
class Memory {
static array ram;
function void init() {
let ram = 0;
return;
}
function int peek(int address) {
return ram[address];
}
function void poke(
int address,
int value) {
let ram[address] = value;
return;
}
Memory: manage heap space
2786
2
15360
4
0
1024
2048 2786 15360
Next
Size
2786
2
3192
1
0
1024
2048 2789 3192
Next
Size
After Memory.Alloc(1)
0
1
data
2786
Alloc ListFree List
Conclusion
● Computer is a structural design from simple hardware
elements, all from Nand and D Flip-Flop
● Be a “Fullstack Hello World Engineer”
○ 自定義一組指令集
○ port 組譯器
○ port 編譯器
○ port 作業系統
○ port libc
○ 寫一個 hello world
Course Diagram from Textbook
Reference & Link
● My note on blog: (yodalee)
○ http://yodalee.blogspot.tw/2016/07/nand2tetris.html
○ http://yodalee.blogspot.tw/2017/05/nand2tetris-part2.html
● Nand2Tetris Website
○ http://nand2tetris.org/
Question ?

Introduction to nand2 tetris

  • 1.
  • 2.
    About the Speaker ●YehBan (aka: Yodalee) ● Blogger: http://yodalee.blogspot.tw/ ● Programmer: https://github.com/yodalee
  • 3.
    Outline ● Introduction toNand2Tetris ● Detail content in each week ○ Part 1: ■ Week 1, 2: Nand to ALU ■ Week 3, 5: Sequential Logic to CPU ■ Week 4, 6: Assembly and Assembler ○ Part 2: ■ Week 1, 2: Stack Virtual Machine ■ Week 4, 5: Jack Compiler ■ Week 6: Runtime and OS
  • 4.
    Introduction ● Course designedby Noam Nisan and Shimon Schocken of Hebrew University of Jerusalem ● Build a computer from Nand Gate, and take a glance at the mystery of computer ● Open on coursera ○ https://www.coursera.org/learn/build-a-computer ○ https://www.coursera.org/learn/nand2tetris2 https://www.ted.com/talks/shimon_schocken_the_self_organizing_computer_course
  • 5.
  • 6.
    Part 1 week1, 2: Nand to ALU Combinational Circuit
  • 7.
    From the Beginning:Nand A B Nand(A, B) 0 0 1 0 1 1 1 0 1 1 1 0 ● Nand is one kind of basic logic gate ○ Why Nand, not Nor? ● The truth table of Nand https://electronics.stackexchange.com/questions/110649/why-is-nand-gate-preferred-over-nor-gate-in-industry
  • 8.
    Nand is functionallycomplete ● Nand(X, X) == Not(X) ● Not(Nand(X, Y)) == And(X, Y) ● Nand(Not(X), Not(X)) == Or(X, Y) ○ (A+B)’’ = (A’B’)’ ● Or(And(X, Not(Y)), And(Not(X), Y)) == Xor(X, Y) ● Given A, B, sel ○ Or(And(A, sel), And(B, Not(sel))) => Mux(A, B, sel) ● Given in, sel ○ A = And(in, sel); B = And(in, not(sel)) => Demux(in, sel) https://en.wikipedia.org/wiki/Functional_completeness#Minimal_functionally_complete_operator_sets
  • 9.
    More complex ● Extendto 16 bits gates ○ 16 way OR, AND, Mux, DMux ... ● Full Adder: Xor + And + Or ○ Extend to 16 bits Full Adder ● Custom ALU ○ Data in/out x, y/out ○ Control: zx, nx, zy, ny, f, no ○ Out bit: zr, ng
  • 11.
    ALU Component inDetail mux for zx, zy mux for nx, ny Select x+y or x & y Mux with no
  • 12.
    Part 1 week3: Sequential Circuit
  • 13.
    Sequential Circuit ● DFlip-Flop (Treat as basic element in course) ● Can be realized by connecting D-latch
  • 14.
    D-Register & memory Combineregisters -> memory D-Register D-Register D-Register D-Register D-Register D-Register D-Register D-Register Mux Address Demux Address Load input into D flip flop when load is 1
  • 15.
    Program Counter Reset =1 Out = 0 Boot Load = 1 Out = Input Jump Inc = 1 Out = Out + 1 Normal execution
  • 16.
    Part 1 Week4, 5: Instruction Set, CPU and Computer
  • 17.
    A computer ● ROM:Store Instruction ● Memory ○ General memory 16 KB ○ Screen: 8 KB ○ Keyboard: 1 bytes
  • 18.
  • 19.
    Instruction Overview ● AInstruction: MSB = 0, load [14:0] to A register ○ Ex. 0000 0000 0000 0111: load 7 into A ● C Instruction: MSB = 1, format: 111A CCCCCC DDD JJJ ○ A: Data selection C: Arithmetic select ○ D: Destination select J: Jump select
  • 20.
    C instruction: 111ACCCCCC DDD JJJ Same as ALU, (X, Y) = (D, A) or (D, M), select by A
  • 21.
    CCCCC C A or C instruction CPUInside From ROM From Memory To memory To ROM0 A or C instruction
  • 22.
    C instruction: 111ACCCCCC DDD JJJ Select target register and memory
  • 23.
    d2 d3 A or d1 CPUInside: destination From ROM From Memory To memory To ROM
  • 24.
    C instruction: 111ACCCCCC DDD JJJ Jump condition
  • 25.
    CPU Inside: JumpAddress From ROM From Memory To memory To ROM Address Register: Store address for Jump and memory access JJJ and ALU output
  • 26.
    A computer ● ROM:Instruction ● Memory ○ General memory 16 KB ○ Screen: 8 KB ○ Keyboard: 1 bytes
  • 27.
    Part 1 Week6: Assembly
  • 28.
    Hack Assembly 1. Ainstruction -> “@number” //load number into A register 2. Support label, like (label) //define label @label //load label address to A register 3. C instruction -> “dest = comp; jump" a. Dest: combination of DMA b. Comp: arithmetic on register c. Jump: Jump condition Ex. A = D+A; JMP
  • 29.
    dest = comp;jump Comp Dest Jump Comp
  • 30.
    Some Constant Label LabelLabel Value R0-R15 0-15 SP, LCL, ARG, THIS, THAT 0, 1, 2, 3, 4 SCREEN 16384 KBD 24576
  • 31.
    Some example andAssembler //Memory[0] = 5 @2 D=A @3 D=D+A @0 M=D //data+=32 @data D=M @32 D=D+A @data M=D //loop 10 times @10 D=A @counter M=D (loop) ... @counter MD=M-1 @loop D; JGT
  • 32.
    Implement an Assembler 1.Scan (label) in program, record the address 2. Translate @label, @const to A instruction bitcode 3. Translate C instruction ● Directly map “string” to bitcode ● If Dest has M -> A = 1 ● M -> 001, D -> 010, MD -> 011 ... ● JGT -> 001, JEQ -> 010, JMP -> 111 … 4. Input Assembly; Output Bitcode that can be programmed to instruction ROM
  • 33.
    Part 2 Week1, 2: Stack Virtual Machine
  • 34.
    Stack Virtual Machine ●A structural way to manage memory ● Using push/pop to manage the top of stack ○ Ex. push constant 3, pop local 0 ○ Ex. push constant 0, pop argument 0 Addr Start Push Pop (SP) 258 259 258 (LCL) 256 256 256 ... ... ... ... 256 0 0 3 257 0 0 0 258 0 3 3 259 0 0 0
  • 35.
    Memory Segment Section Memoryaddr SP 0 LCL 1 ARG 2 THIS(class) 3 THAT(array ) 4 TEMP 5-12 Section Memory addr register 13-15 Static 16-255 Stack 256-2048 Heap 2048-16384 Screen 16384-24576 Keyboard0 24576-24577
  • 36.
    Stack Virtual Machine ●Push/Pop command, possible target Constant Push only Static File-scope static variable Pointer Push/Pop to THIS/THAT register Temp Local Local variable in function Argument Function argument This Class That Array
  • 37.
    Stack Virtual Machine ●Arithmetic command like: ○ Add, sub, lt, gt, eq, and, or ○ not, neg Addr Start Add Sub lt neg SP 258 257 257 257 258 256 3 10 -4 -1 3 257 7 7 7 7 -7
  • 38.
    Stack Virtual Machine ●Control command: ○ Label, goto, if-goto ● Function call and Return ○ Function functionname #locals ○ Call functionname #args function Sys.main 0 push constant 123 call Sys.add42 1 pop temp 0 push constant 246 return function Sys.add42 0 push argument 0 push constant 42 add return
  • 39.
    Implement Stack Machinein Assembly //Push constant 7 @7 D=A @SP A=M M=D @SP M=M+1 //Add @SP M=M-1 A=M D=M @SP M=M-1 A=M M=M+D @SP M=M+1 //Pop local 1 @1 D=A @LCL A=M D=A+D @R13 M=D @SP A=M D=M @R13 A=M M=D //Label, if-goto @(file.LOOP) @SP M=M-1 A=M D=M @file.LOOP D; JNE
  • 40.
    Implement Stack Machinein Assembly N Argument Return Address Preserve LCL Preserve ARG Preserve THIS Preserve THAT M Local Variable Stack New ARG New LCL //Calling steps: ● Push argument ● Push Return Address ● Preserve Register ● ARG = SP - 5 - #Args ● LCL = SP ● @FunctionBody ● Jump //Return steps: ● LCL -> R13 ● Return Address -> R14 ● Copy Return value (stack top) to ARG ● SP to ARG+1 ● Restore Register ● Jump to Return Address //Function Body: Push Stack M times for Local Variable
  • 41.
    Boot //Initial Stack @256 D=A @SP M=D @Sys.init Jump ● Initializestack in the first command ○ Start from ROM[0] ● Sys.init will call Main.main ● Sys.init will never return, usually go into an infinite loop Now we have an easy to use computer
  • 42.
    Part 2 Week4, 5: High Level Programming Language
  • 43.
    High Level ProgrammingLanguage and its Compiler ● Jack: high level programming language ○ Support Array and Class ○ No inheritance ● A compiler translate high level programming language to VM implementation ○ Tokenizer ○ Syntax Analyzer ○ Code Generator
  • 44.
    Tokenizer while (i <length) { let i = i + 1; } whil e ( i < length ) { let i = i + 1 ; }
  • 45.
    Jack Grammar ● MostLL(1) LL1.5 grammar ○ No arithmetic precedence
  • 46.
    Make it LL(1)in statements LL(2) here
  • 47.
    Code Generation: SymbolTable ● A table save the id of each variable var Array a; var int length; var int i, sum; let i = 0; while (i < length) a LCL 0 length LCL 1 i LCL 2 sum LCL 3 push constant 0 pop local 2 label Lwhile0 push local 2 push local 1 lt not if-goto Lwhile1
  • 48.
    Code Generation: Object ●Size of class is constant at compile time ● Translate object constructor (special name “new”): ○ Alloc memory ○ Save to THIS register ○ Return THIS register ● Translate object method: ex. obj.method(arg1, arg2): ○ Push obj as Argument 0 ○ Push Argument 1, Argument 2 ○ Call method ○ In method: Save Argument 0 to THIS register
  • 49.
    Code Generation: Array ●Array will call Array.new to allocate memory, save result to variable (the address of Array) ● Access Array arr[expr] ○ Calculate index expr ○ Add arr address and index ○ Pop to THAT register ○ Push/Pop THAT register content ● Complex example: arrA[exprA] = arrB[exprB]
  • 50.
    Part 2 Week6: Library and (part of) OS
  • 51.
    Implement OS service ●Array // Array function ● Keyboard // read keyboard input ● Math // multiply, divide, power ● Memory // peek, poke, alloc, dealloc ● Output // Print text on screen ● Screen // Draw line, rectangle, circle on Screen ● String // String related function ● Sys // init, halt http://nand2tetris.org/projects/12/Jack%20OS%20API.pdf
  • 52.
    Memory: peek/poke class Memory{ static array ram; function void init() { let ram = 0; return; } function int peek(int address) { return ram[address]; } function void poke( int address, int value) { let ram[address] = value; return; }
  • 53.
    Memory: manage heapspace 2786 2 15360 4 0 1024 2048 2786 15360 Next Size 2786 2 3192 1 0 1024 2048 2789 3192 Next Size After Memory.Alloc(1) 0 1 data 2786 Alloc ListFree List
  • 54.
    Conclusion ● Computer isa structural design from simple hardware elements, all from Nand and D Flip-Flop ● Be a “Fullstack Hello World Engineer” ○ 自定義一組指令集 ○ port 組譯器 ○ port 編譯器 ○ port 作業系統 ○ port libc ○ 寫一個 hello world
  • 55.
  • 56.
    Reference & Link ●My note on blog: (yodalee) ○ http://yodalee.blogspot.tw/2016/07/nand2tetris.html ○ http://yodalee.blogspot.tw/2017/05/nand2tetris-part2.html ● Nand2Tetris Website ○ http://nand2tetris.org/
  • 57.

Editor's Notes

  • #10 Zr: output is totally zero Ng: sign bit is true
  • #49 Example: SquareGame: new SquareGame: call Square moveUp
  • #50 Example: Average