依据基本原理构建现代计算机:从与非门到俄罗斯方块。
前言
本文用于记录该课程学习过程中觉得有用的知识点,既方便以后的回忆,也为一同学习这门课程的同学做一个小小的参考。
这是一门有关计算机体系结构的课程,这门课程分为两个部分,第一部分为硬件部分,第二部分为软件部分。课程的目的在于从与非门构建出计算机。课程面向的人群为零基础人群。
Coursera上的课程链接为 Nand2Tetris I、Nand2Tetris II
课程官方网站 From Nand to Tetris
由于本人基础薄弱,难免出现各种错误,所写代码也难以做到很优秀。如果发现本文的问题欢迎指出。
一、第一周
1、introduction
这一节简单介绍了课程的流程与计划以及上课的准备工作。我们需要在官网上下载好课程所需的文件,以及配置好Java环境。都是一些基本的操作,这里不再赘述。
1.1、project 0
只是简单的需要找到从网站中下载的一个文件,以便于确保能够学会在网站上提交作业。由于我是以旁听的身份参与课程,因此找到文件即可。
2、Boolean Functions and Gate Logic
2.1、Unit 1.1: Boolean Logic
本节介绍了And和Or,以及一些运算的规律。
And仅当输入的都为1时才输出1。Or则只需输入有1时就输出1.
2.2、Unit 1.2: Boolean Functions Synthesis
本节首先介绍了用And和Not来表示Or的方法:
Not((Not(a))And (Not(b))) = a Or b
然后介绍了使用Nand来表示Not的方法:
a Nand a = Not(a)
最后介绍了使用Nand来表示And的方法:
Not(a Nand b) = a And b
Nand可以看作And取反,只有输入都为1时取0,其余取1。
所以,本节证明了只需要使用Nand即可表示And、Not和Or,因此可以通过Nand来建造一台计算机。
2.3、Unit 1.4: Hardware Description Language
本节讲述了Hardware Description Language,建议参考: HDL说明
2.4、Unit 1.5: Hardware Simulation
本节讲述了Hardware Simulation的操作,建议参考: Hardware Simulation使用说明
2.5、project 1
Not.hdl
// 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/01/Not.hdl
/**
* Not gate:
* out = not in
*/
//0 Nand 0 = 1,1 Nand 1 = 0
CHIP Not {
IN in;
OUT out;
PARTS:
// Put your code here:
Nand(a=in, b=in, out=out);
}
And.hdl
// 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/01/And.hdl
/**
* And gate:
* out = 1 if (a == 1 and b == 1)
* 0 otherwise
*/
//基本原件Nand取反即为And
CHIP And {
IN a, b;
OUT out;
PARTS:
// Put your code here:
Nand(a=a, b=b, out=w);
Not(in=w, out=out);
}
Or.hdl
// 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/01/Or.hdl
/**
* Or gate:
* out = 1 if (a == 1 or b == 1)
* 0 otherwise
*/
//Not((Not(a)) And (Not(b)) = a Or b
CHIP Or {
IN a, b;
OUT out;
PARTS:
// Put your code here:
Not(in=a, out=w1);
Not(in=b, out=w2);
And(a=w1, b=w2, out=w3);
Not(in=w3, out=out);
}
Xor.hdl
// 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/01/Xor.hdl
/**
* Exclusive-or gate:
* out = not (a == b)
*/
//((a) And (Not(b)))Or((Not(a) And (b)))
CHIP Xor {
IN a, b;
OUT out;
PARTS:
// Put your code here:
Not (in=a, out=nota);
Not (in=b, out=notb);
And (a=a, b=notb, out=w1);
And (a=nota, b=b, out=w2);
Or (a=w1,b=w2,out=out);
}
Mux.hdl
// 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/01/Mux.hdl
/**
* Multiplexor:
* out = a if sel == 0
* b otherwise
*/
//( (a) And ( Not (c) ) ) Or ( (b) And (c) )
CHIP Mux {
IN a, b, sel;
OUT out;
PARTS:
// Put your code here:
Not(in=sel,out=out1);
And(a=a, b=out1, out=out2);
And(a=b, b=sel, out=out3);
Or(a=out2, b=out3, out=out);
}
DMux.hdl
// 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/01/DMux.hdl
/**
* Demultiplexor:
* {a, b} = {in, 0} if sel == 0
* {0, in} if sel == 1
*/
CHIP DMux {
IN in, sel;
OUT a, b;
PARTS:
// Put your code here:
Not(in=sel, out=notsel);
And(a=in, b=notsel, out=a);
And(a=in, b=sel, out=b);
}
Not16.hdl
// 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/01/Not16.hdl
/**
* 16-bit Not:
* for i=0..15: out[i] = not in[i]
*/
CHIP Not16 {
IN in[16];
OUT out[16];
PARTS:
// Put your code here:
Not(in=in[0],out=out[0]);
Not(in=in[1],out=out[1]);
Not(in=in[2],out=out[2]);
Not(in=in[3],out=out[3]);
Not(in=in[4],out=out[4]);
Not(in=in[5],out=out[5]);
Not(in=in[6],out=out[6]);
Not(in=in[7],out=out[7]);
Not(in=in[8],out=out[8]);
Not(in=in[9],out=out[9]);
Not(in=in[10],out=out[10]);
Not(in=in[11],out=out[11]);
Not(in=in[12],out=out[12]);
Not(in=in[13],out=out[13]);
Not(in=in[14],out=out[14]);
Not(in=in[15],out=out[15]);
}
And16.hdl
// 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/01/And16.hdl
/**
* 16-bit bitwise And:
* for i = 0..15: out[i] = (a[i] and b[i])
*/
CHIP And16 {
IN a[16], b[16];
OUT out[16];
PARTS:
// Put your code here:
And(a=a[0],b=b[0],out=out[0]);
And(a=a[1],b=b[1],out=out[1]);
And(a=a[2],b=b[2],out=out[2]);
And(a=a[3],b=b[3],out=out[3]);
And(a=a[4],b=b[4],out=out[4]);
And(a=a[5],b=b[5],out=out[5]);
And(a=a[6],b=b[6],out=out[6]);
And(a=a[7],b=b[7],out=out[7]);
And(a=a[8],b=b[8],out=out[8]);
And(a=a[9],b=b[9],out=out[9]);
And(a=a[10],b=b[10],out=out[10]);
And(a=a[11],b=b[11],out=out[11]);
And(a=a[12],b=b[12],out=out[12]);
And(a=a[13],b=b[13],out=out[13]);
And(a=a[14],b=b[14],out=out[14]);
And(a=a[15],b=b[15],out=out[15]);
}
Or16.hdl
// 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/01/Or16.hdl
/**
* 16-bit bitwise Or:
* for i = 0..15 out[i] = (a[i] or b[i])
*/
CHIP Or16 {
IN a[16], b[16];
OUT out[16];
PARTS:
// Put your code here:
Or(a=a[0],b=b[0],out=out[0]);
Or(a=a[1],b=b[1],out=out[1]);
Or(a=a[2],b=b[2],out=out[2]);
Or(a=a[3],b=b[3],out=out[3]);
Or(a=a[4],b=b[4],out=out[4]);
Or(a=a[5],b=b[5],out=out[5]);
Or(a=a[6],b=b[6],out=out[6]);
Or(a=a[7],b=b[7],out=out[7]);
Or(a=a[8],b=b[8],out=out[8]);
Or(a=a[9],b=b[9],out=out[9]);
Or(a=a[10],b=b[10],out=out[10]);
Or(a=a[11],b=b[11],out=out[11]);
Or(a=a[12],b=b[12],out=out[12]);
Or(a=a[13],b=b[13],out=out[13]);
Or(a=a[14],b=b[14],out=out[14]);
Or(a=a[15],b=b[15],out=out[15]);
}
Mux16.hdl
// 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/01/Mux16.hdl
/**
* 16-bit multiplexor:
* for i = 0..15 out[i] = a[i] if sel == 0
* b[i] if sel == 1
*/
CHIP Mux16 {
IN a[16], b[16], sel;
OUT out[16];
PARTS:
// Put your code here:
Mux(a= a[0],b= b[0],sel= sel,out= out[0]);
Mux(a= a[1],b= b[1],sel= sel,out= out[1]);
Mux(a= a[2],b= b[2],sel= sel,out= out[2]);
Mux(a= a[3],b= b[3],sel= sel,out= out[3]);
Mux(a= a[4],b= b[4],sel= sel,out= out[4]);
Mux(a= a[5],b= b[5],sel= sel,out= out[5]);
Mux(a= a[6],b= b[6],sel= sel,out= out[6]);
Mux(a= a[7],b= b[7],sel= sel,out= out[7]);
Mux(a= a[8],b= b[8],sel= sel,out= out[8]);
Mux(a= a[9],b= b[9],sel= sel,out= out[9]);
Mux(a= a[10],b= b[10],sel= sel,out= out[10]);
Mux(a= a[11],b= b[11],sel= sel,out= out[11]);
Mux(a= a[12],b= b[12],sel= sel,out= out[12]);
Mux(a= a[13],b= b[13],sel= sel,out= out[13]);
Mux(a= a[14],b= b[14],sel= sel,out= out[14]);
Mux(a= a[15],b= b[15],sel= sel,out= out[15]);
}
Or8Way.hdl
// 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/01/Or8Way.hdl
/**
* 8-way Or:
* out = (in[0] or in[1] or ... or in[7])
*/
CHIP Or8Way {
IN in[8];
OUT out;
PARTS:
// Put your code here:
Or(a= in[0],b= in[1],out= Or1);
Or(a= Or1,b= in[2],out= Or2);
Or(a= Or2,b= in[3],out= Or3);
Or(a= Or3,b= in[4],out= Or4);
Or(a= Or4,b= in[5],out= Or5);
Or(a= Or5,b= in[6],out= Or6);
Or(a= Or6,b= in[7],out= out);
}
Mux4Way16.hdl
// 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/01/Mux4Way16.hdl
/**
* 4-way 16-bit multiplexor:
* out = a if sel == 00
* b if sel == 01
* c if sel == 10
* d if sel == 11
*/
CHIP Mux4Way16 {
IN a[16], b[16], c[16], d[16], sel[2];
OUT out[16];
PARTS:
// Put your code here:
Mux16(a= a,b= b,sel= sel[0],out= out1);
Mux16(a= c,b= d,sel= sel[0],out= out2);
Mux16(a= out1,b= out2,sel= sel[1],out= out);
}
Mux8Way16.hdl
// 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/01/Mux8Way16.hdl
/**
* 8-way 16-bit multiplexor:
* out = a if sel == 000
* b if sel == 001
* c if sel == 010
* d if sel == 011
* e if sel == 100
* f if sel == 101
* g if sel == 110
* h if sel == 111
*/
CHIP Mux8Way16 {
IN a[16], b[16], c[16], d[16],
e[16], f[16], g[16], h[16],
sel[3];
OUT out[16];
PARTS:
// Put your code here:
Mux16(a= a,b= b,sel= sel[0],out= out1);
Mux16(a= c,b= d,sel= sel[0],out= out2);
Mux16(a= e,b= f,sel= sel[0],out= out3);
Mux16(a= g,b= h,sel= sel[0],out= out4);
Mux16(a= out1,b= out2,sel= sel[1],out= out5);
Mux16(a= out3,b= out4,sel= sel[1],out= out6);
Mux16(a= out5,b= out6,sel= sel[2],out= out);
}
DMux4Way.hdl
// 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/01/DMux4Way.hdl
/**
* 4-way demultiplexor:
* {a, b, c, d} = {in, 0, 0, 0} if sel == 00
* {0, in, 0, 0} if sel == 01
* {0, 0, in, 0} if sel == 10
* {0, 0, 0, in} if sel == 11
*/
CHIP DMux4Way {
IN in, sel[2];
OUT a, b, c, d;
PARTS:
// Put your code here:
DMux(in= in,sel= sel[1],a= out1,b= out2);
DMux(in= out1,sel= sel[0],a= a,b= b);
DMux(in= out2,sel= sel[0],a= c,b= d);
}
DMux8Way.hdl
// 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/01/DMux8Way.hdl
/**
* 8-way demultiplexor:
* {a, b, c, d, e, f, g, h} = {in, 0, 0, 0, 0, 0, 0, 0} if sel == 000
* {0, in, 0, 0, 0, 0, 0, 0} if sel == 001
* {0, 0, in, 0, 0, 0, 0, 0} if sel == 010
* {0, 0, 0, in, 0, 0, 0, 0} if sel == 011
* {0, 0, 0, 0, in, 0, 0, 0} if sel == 100
* {0, 0, 0, 0, 0, in, 0, 0} if sel == 101
* {0, 0, 0, 0, 0, 0, in, 0} if sel == 110
* {0, 0, 0, 0, 0, 0, 0, in} if sel == 111
*/
CHIP DMux8Way {
IN in, sel[3];
OUT a, b, c, d, e, f, g, h;
PARTS:
// Put your code here:
DMux(in=in, sel=sel[2], a=out1, b=out2);
DMux(in=out1, sel=sel[1], a=out3, b=out4);
DMux(in=out2, sel=sel[1], a=out5, b=out6);
DMux(in=out3, sel=sel[0], a=a, b=b);
DMux(in=out4, sel=sel[0], a=c, b=d);
DMux(in=out5, sel=sel[0], a=e, b=f);
DMux(in=out6, sel=sel[0], a=g, b=h);
}
二、第二周
1、Boolean Arithmetic and the ALU
1.1、Unit 2.3: Negative Numbers
介绍的2‘s Complement representation是重点。
1.2、Unit 2.4: Arithmetic Logic Unit
1.3、project 2
HalfAdder.hdl
// 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/02/HalfAdder.hdl
/**
* Computes the sum of two bits.
*/
CHIP HalfAdder {
IN a, b; // 1-bit inputs
OUT sum, // Right bit of a + b
carry; // Left bit of a + b
PARTS:
// Put you code here:
Xor(a=a, b=b, out=sum);
And(a=a, b=b, out=carry);
}
FullAdder.hdl
// 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/02/FullAdder.hdl
/**
* Computes the sum of three bits.
*/
CHIP FullAdder {
IN a, b, c; // 1-bit inputs
OUT sum, // Right bit of a + b + c
carry; // Left bit of a + b + c
PARTS:
// Put you code here:
HalfAdder(a=a, b=b, sum=tempsum, carry=carry1);
HalfAdder(a=tempsum, b=c, sum=sum, carry=carry2);
Or(a=carry1, b=carry2, out=carry);
}
Add16.hdl
// 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/02/Adder16.hdl
/**
* Adds two 16-bit values.
* The most significant carry bit is ignored.
*/
CHIP Add16 {
IN a[16], b[16];
OUT out[16];
PARTS:
// Put you code here:
FullAdder(a=a[0], b=b[0], c=false, sum=out[0], carry=carry1);
FullAdder(a=a[1], b=b[1], c=carry1, sum=out[1], carry=carry2);
FullAdder(a=a[2], b=b[2], c=carry2, sum=out[2], carry=carry3);
FullAdder(a=a[3], b=b[3], c=carry3, sum=out[3], carry=carry4);
FullAdder(a=a[4], b=b[4], c=carry4, sum=out[4], carry=carry5);
FullAdder(a=a[5], b=b[5], c=carry5, sum=out[5], carry=carry6);
FullAdder(a=a[6], b=b[6], c=carry6, sum=out[6], carry=carry7);
FullAdder(a=a[7], b=b[7], c=carry7, sum=out[7], carry=carry8);
FullAdder(a=a[8], b=b[8], c=carry8, sum=out[8], carry=carry9);
FullAdder(a=a[9], b=b[9], c=carry9, sum=out[9], carry=carry10);
FullAdder(a=a[10], b=b[10], c=carry10, sum=out[10], carry=carry11);
FullAdder(a=a[11], b=b[11], c=carry11, sum=out[11], carry=carry12);
FullAdder(a=a[12], b=b[12], c=carry12, sum=out[12], carry=carry13);
FullAdder(a=a[13], b=b[13], c=carry13, sum=out[13], carry=carry14);
FullAdder(a=a[14], b=b[14], c=carry14, sum=out[14], carry=carry15);
FullAdder(a=a[15], b=b[15], c=carry15, sum=out[15], carry=carry16);
}
Inc16.hdl
// 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/02/Inc16.hdl
/**
* 16-bit incrementer:
* out = in + 1 (arithmetic addition)
*/
CHIP Inc16 {
IN in[16];
OUT out[16];
PARTS:
// Put you code here:
HalfAdder(a=in[0], b=true, sum=out[0], carry=carry1);
HalfAdder(a=in[1], b=carry1, sum=out[1], carry=carry2);
HalfAdder(a=in[2], b=carry2, sum=out[2], carry=carry3);
HalfAdder(a=in[3], b=carry3, sum=out[3], carry=carry4);
HalfAdder(a=in[4], b=carry4, sum=out[4], carry=carry5);
HalfAdder(a=in[5], b=carry5, sum=out[5], carry=carry6);
HalfAdder(a=in[6], b=carry6, sum=out[6], carry=carry7);
HalfAdder(a=in[7], b=carry7, sum=out[7], carry=carry8);
HalfAdder(a=in[8], b=carry8, sum=out[8], carry=carry9);
HalfAdder(a=in[9], b=carry9, sum=out[9], carry=carry10);
HalfAdder(a=in[10], b=carry10, sum=out[10], carry=carry11);
HalfAdder(a=in[11], b=carry11, sum=out[11], carry=carry12);
HalfAdder(a=in[12], b=carry12, sum=out[12], carry=carry13);
HalfAdder(a=in[13], b=carry13, sum=out[13], carry=carry14);
HalfAdder(a=in[14], b=carry14, sum=out[14], carry=carry15);
HalfAdder(a=in[15], b=carry15, sum=out[15], carry=carry16);
}
ALU.hdl
关于最后的zr和ng的判断,额外写了Or16Way.hdl和IsNg.hdl以便于计算。
// 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/02/ALU.hdl
/**
* The ALU (Arithmetic Logic Unit).
* Computes one of the following functions:
* x+y, x-y, y-x, 0, 1, -1, x, y, -x, -y, !x, !y,
* x+1, y+1, x-1, y-1, x&y, x|y on two 16-bit inputs,
* according to 6 input bits denoted zx,nx,zy,ny,f,no.
* In addition, the ALU computes two 1-bit outputs:
* if the ALU output == 0, zr is set to 1; otherwise zr is set to 0;
* if the ALU output < 0, ng is set to 1; otherwise ng is set to 0.
*/
// Implementation: the ALU logic manipulates the x and y inputs
// and operates on the resulting values, as follows:
// if (zx == 1) set x = 0 // 16-bit constant
// if (nx == 1) set x = !x // bitwise not
// if (zy == 1) set y = 0 // 16-bit constant
// if (ny == 1) set y = !y // bitwise not
// if (f == 1) set out = x + y // integer 2's complement addition
// if (f == 0) set out = x & y // bitwise and
// if (no == 1) set out = !out // bitwise not
// if (out == 0) set zr = 1
// if (out < 0) set ng = 1
CHIP ALU {
IN
x[16], y[16], // 16-bit inputs
zx, // zero the x input?
nx, // negate the x input?
zy, // zero the y input?
ny, // negate the y input?
f, // compute out = x + y (if 1) or x & y (if 0)
no; // negate the out output?
OUT
out[16], // 16-bit output
zr, // 1 if (out == 0), 0 otherwise
ng; // 1 if (out < 0), 0 otherwise
PARTS:
// Put you code here:
//zx
Mux16(a=x, b=false, sel=zx, out=x1);
//nx
Not16(in=x1, out=x2);
Mux16(a=x1, b=x2, sel=nx, out=x3);
//zy
Mux16(a=y, b=false, sel=zy, out=y1);
//ny
Not16(in=y1, out=y2);
Mux16(a=y1, b=y2, sel=ny, out=y3);
//f
And16(a=x3, b=y3, out=f1);
Add16(a=x3, b=y3, out=f2);
Mux16(a=f1, b=f2, sel=f, out=f3);
//no
Not16(in=f3, out=n1);
Mux16(a=f3, b=n1, sel=no, out=out,out=temp);
//zr
Or16Way(in=temp, out=o1);
Not(in=o1, out=zr);
//ng
IsNg(in=temp, out=ng);
}
Or16Way.hdl
// 自己写一个作为补充,方便ALU
/**
* 16-way Or:
* out = (in[0] or in[1] or ... or in[15])
*/
CHIP Or16Way {
IN in[16];
OUT out;
PARTS:
// Put your code here:
Or(a= in[0],b= in[1],out= Or1);
Or(a= Or1,b= in[2],out= Or2);
Or(a= Or2,b= in[3],out= Or3);
Or(a= Or3,b= in[4],out= Or4);
Or(a= Or4,b= in[5],out= Or5);
Or(a= Or5,b= in[6],out= Or6);
Or(a= Or6,b= in[7],out= Or7);
Or(a= Or7,b= in[8],out= Or8);
Or(a= Or8,b= in[9],out= Or9);
Or(a= Or9,b= in[10],out= Or10);
Or(a= Or10,b= in[11],out= Or11);
Or(a= Or11,b= in[12],out= Or12);
Or(a= Or12,b= in[13],out= Or13);
Or(a= Or13,b= in[14],out= Or14);
Or(a= Or14,b= in[15],out= out);
}
IsNg.hdl
// if (out < 0) set ng = 1
CHIP IsNg {
IN in[16];
OUT out;
PARTS:
// Put your code here:
Or(a=in[15], b=false, out=out);
}