nand2tetris_hack计算机
终于来到了这一步!!
前文里,我们学习了hack编程语言,大概知道需要实现的hack计算机是什么样子,需要实现哪些功能。同时在更早的时候,我们建造了ALU和RAM组件,加上老师内置的ROM和键盘屏幕外设,那么开干!
等一下,在开始之前,我想先聊聊当今通用计算机的体系结构,也就是大名鼎鼎的冯诺依曼体系,我们的hack计算机也是依据于此
冯诺依曼体系介绍
“有道无术,术尚可求;有术无道,止于术”,三体里秦始皇欲建造人型计算机,b站里的大神用excel实现的cpu,当然还有我们这门课程里将要在模拟器里实现的hack计算机,他们都遵循着冯诺依曼体系框架。从b站评论里看来的,“理论上,只要是可以实现与非门和时钟的,都可以用来用来实现计算机”
这张图,我记得在大一的计算机组成原理里看见过,哈哈哈,只记得冯诺依曼这四个字了
我们通常有三种信息类型在系统间传递。数据,当我们进行加法运算时,输入需要从内存移动到寄存器中,再到实际的运算单元,进行计算后返回;地址,实现执行的是什么指令和需要访问内存中的哪些数据,这些都在地址里的;控制,系统的每一个组成部分需要知道,在特定的时间点做什么事情
下面,让我们看看计算机里面的不同组件,他们可以接收什么信息和发出什么信息
CPU
我们的CPU分为两个组件,一是算术逻辑单元ALU,二是寄存器。算术逻辑单元能够加减数字,也能够进行逻辑运算;寄存器则是暂存一些数据,这些数据,在后续的计算中将要使用
ALU需要接入数据总线,因为需要拉取数据计算,然后返回;同时,他需要控制总线的信息,告诉他要执行的操作类型是什么,可能是相加,可能是取反;另一方面,根据计算结果,alu会返回标志位信息,如 结果是否大于0,这些需要放在控制总线上,告诉系统的其他部分做什么操作,比如下一个指令是否跳转
寄存器在概念上很简单,作为cpu的缓冲单元,理所当然的需要接入数据总线;同时寄存器在设计上,还支持指定地址这种来取/设值,这实际是间接寻址到RAM或者ROM上,这就需要寄存器连接到地址总线上
综上,cpu需要通过数据总线/地址总线获取输入数据,通过控制总线得到运算函数,计算得到的结果输出至数据/地址总线上,同时计算结果标志位反馈到控制总线,等待下一次计算
内存
标准的冯洛伊曼体系,应该是使用一块内存,数据和指令均放入其中,这里简化处理为数据和指令独立放在一块内存中(哈佛结构),还有一些别的原因,不在这里说明了,仍以冯洛伊曼体系介绍
内存最直接的需求就是数据读写,需要连接在数据总线上;同时上面提到的CPU的输入和输出均可以是地址,内存同样需要连接到地址总线上;其次指令内存需要知道下一条待执行的指令内容,这里cpu输出的指令地址被归纳进控制总线里
这里贴两张数据内存和指令内存的数据流转图,帮助理解内存在整个链路扮演的角色
综上,内存通过控制控制总线取出指令地址,通过地址总线取出输入数据,然后经cpu计算后,通过地址总线和数据总线写回输出数据至内存中,同时控制总线上返回下一次待执行的地址
这里,描述的有点乱。三条总线只是一个概念模型,理解每个组件做什么的就好了。知道大概是这样的思路,重要的还是引出下面的CPU和RAM的输入输出参数设计
计算机设计
总体架构
看起来复杂,实际对于计算机来说,只是单纯的取指令,执行再取
CPU
想从白纸实现出来,我感觉难度相当高,课程老师估计也知道,直接给了实现结构图,照着连线就好。我这里如果说你问我,为什么这个结构可以实现cpu,我是知道的,但若你问我cpu还有没有别的实现结构,我就懵了
白板
实现结构图
实现思路
这里照着图实现思路,就很清晰了。把指令里的每一位取出来,然后进行不同的判断,稍微复杂一点的就是现在ALU的返回值也需要用到了;这部分详细可以参照视频
跳转实现思路
RAM
这里很简单,想想怎么区分不同的地址段即可
ROM
这是内置芯片,提供的接口就是取指
计算机
计算机就是把上面的几个芯片,组装起来
hdl实现
这里还是贴一下代码,不要以后自己想看的时候,忘记了 哈哈
cpu
CHIP CPU {
IN inM[16], // M value input (M = contents of RAM[A])
instruction[16], // Instruction for execution
reset; // Signals whether to re-start the current
// program (reset==1) or continue executing
// the current program (reset==0).
OUT outM[16], // M value output
writeM, // Write to M?
addressM[15], // Address in data memory (of M)
pc[15]; // address of next instruction
PARTS:
Mux16(a=instruction[0..15],b=aluout,sel=instruction[15],out=ain);
// allow `A` @x -> set A
Not(in=instruction[15],out=opnot);
Or(a=opnot,b=instruction[5], out=ac);
ARegister(in=ain,load=ac,out=aout,out[0..14]=addressM);
// D only load from `C`
And(a=instruction[15],b=instruction[4], out=dc);
DRegister(in=aluout,load=dc,out=aluin1);
Mux16(a=aout,b=inM,sel=instruction[12],out=aluin2);
ALU(x=aluin1,y=aluin2,zx=instruction[11],nx=instruction[10],zy=instruction[9],ny=instruction[8],f=instruction[7],no=instruction[6],out=aluout,out=outM,zr=zr,ng=ng);
And(a=instruction[15],b=instruction[3],out=writeM);
// PC
Not(in=zr,out=notzr);
Not(in=ng,out=notng);
// great!
DMux8Way(in=instruction[15], sel=instruction[0..2], a=null, b=jgt, c=jeq, d=jge, e=jlt, f=jne, g=jle, h=jmp);
And(a=notzr,b=notng,out=jgt1);
And(a=jgt,b=jgt1,out=jgt2);
And(a=jeq,b=zr,out=jeq1);
And(a=jge,b=notng,out=jge1);
And(a=jlt,b=ng,out=jlt1);
And(a=jne,b=notzr,out=jne1);
Or(a=zr,b=ng,out=jle1);
And(a=jle,b=jle1,out=jle2);
Or8Way(in[0]=false, in[1]=jgt2, in[2]=jeq1, in[3]=jge1, in[4]=jlt1, in[5]=jne1, in[6]=jle2, in[7]=jmp, out=jumpout);
PC(in=aout,inc=true,load=jumpout,reset=reset,out[0..14]=pc);
}
memory
CHIP Memory {
IN in[16], load, address[15];
OUT out[16];
PARTS:
DMux(in=load, sel=address[14], a=m1, b=m2);
RAM16K(in=in, load=m1, address=address[0..13], out=out1);
DMux(in=m2, sel=address[13], a=r1, b=r2);
Screen(in=in, load=r1, address=address[0..12], out=out2);
Keyboard(out=out3);
Mux16(a=out2,b=out3,sel=address[13],out=out4);
Mux16(a=out1,b=out4,sel=address[14],out=out);
}
computer
CHIP Computer {
IN reset;
PARTS:
CPU(inM=inM,instruction=instruction,reset=reset,outM=outM,writeM=writeM,addressM=addressM,pc=pc);
Memory(address=addressM,in=outM,load=writeM,out=inM);
ROM32K(address=pc,out=instruction);
}
总结
到这里,这门课程其实就结束了,后面还有一章是编译器,我当时是直接用笔完成的,也没有写代码。哈哈哈,代码写多了,反而喜欢朴素的方式来实现,还是懒吧。这章是4月做完的,已经过去了5,6,7,三个月了。这学习啊,一放下就会不经意过去好久了。
记得当时学完课程就开始写这个博客了,并没有预期的那么兴奋,总觉得少了什么,所以一直没有写完,这次只是草草贴了几张图收尾。现在想来,大概是时钟这个概念还是没有理解,这门课程最大的收获可能就是cpu不再那么神秘了,它真的是由与非门实现的,这里还是有很多细节的,不过还是尽快开始下一门课吧。再放下去,今年就过去了。
好读书,不求甚解;每有会意,便欣然忘食。