这是《计算机系统要素:从零开始构建现代计算机》的学习笔记,刚刚启程学习,记录博客好提醒自己不要半途而废。 书籍获取,代码实现与书籍介绍,可关注这位大佬,视频课程:coursera/B站 偷一张大佬github截图作为介绍:
ALU(Algorithmic Ligic Unit),算术逻辑单元,是CPU的核心部件,本书中实现的ALU是最小ALU,实现起来难度不大。中枢单元的函数竟然简单到只由小小电路就可以实现,真是从来没想过,前人的抽象能力真是让人佩服。
ALU有八个输入:x[16],y[16],zx,nx,zy,ny,f,no 三个输出:out[16],zr,ng 其中zx,nx,zy,ny,f,no为六个控制位,控制ALU进行不同的运算 六个控制位,每个控制位可取0或1,因此ALU可以进行 2 6 = 64 2^6=64 26=64种不同的运算 x[16]和y[16]为ALU的16位输入 out[16]为16位运算结果 zr和ng指示out的输出符号: out=0时,zr输出true out<0时,ng输出true
列出了64个函数中的18个
zxnxzynyfnooutif zx then x=0if nx then x=!xif zy then y=0if ny then y=!yif f then out=x+yelse out=x&yif no then out=!outf(x,y)=10101001111111111010-1001100x110000y001101!x110001!y110001-x110011-y011111x+1110111y+1001110x-1110010y-1000010x+y010011x-y000111y-x000000x&y010101xALU的输入都有明确的含义,不需要通过真值表来推导ALU电路,相反,真值表是从控制位的含义得来的。若从真值表倒推电路,不仅费力不讨好而且本末倒置还容易出错。 可以看到控制位都是if … else…的功能,我们可以通过Mux来实现这种分支控制 先看一下HDL代码(来自github/woai3c) ALU.hdl:
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: // 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=o1); // no Not16(in=o1, out=o2); Mux16(a=o1, b=o2, sel=no, out=out, out=o3); // zr Or16Way(in=o3, out=zr1); Not(in=zr1,out=zr); // ng IsNeg(in=o3,out=ng); }可以看到if else内部都是Mux
画一下看看,出人意料的简单: 其中Or16Way电路,输入的16位中只要有1就会输出true,因此输出false时表示输入的是全0数字,因此在Or16Way之后连接一个Not可以实现为0时输出true,实现zr检测 Or16Way.hdl
CHIP Or16Way { IN in[16]; OUT out; PARTS: Or(a = in[0], b = in[1], out = o1); Or(a = o1, b = in[2], out = o2); Or(a = o2, b = in[3], out = o3); Or(a = o3, b = in[4], out = o4); Or(a = o4, b = in[5], out = o5); Or(a = o5, b = in[6], out = o6); Or(a = o6, b = in[7], out = o7); Or(a = o7, b = in[8], out = o8); Or(a = o8, b = in[9], out = o9); Or(a = o9, b = in[10], out = o10); Or(a = o10, b = in[11], out = o11); Or(a = o11, b = in[12], out = o12); Or(a = o12, b = in[13], out = o13); Or(a = o13, b = in[14], out = o14); Or(a = o14, b = in[15], out = out); }IsNeg的功能是判断输出是否是负数,而负数检测只需要判断最高位in[15]是否为1, 通过将in[15]和false输入一个Or门,实现in[15]为1时输出1,为0时输出0: IsNeg.hdl
CHIP IsNeg { IN in[16]; OUT out; PARTS: Or(a=in[15],b=false,out=out); }学到这里,结合前面构建的电路,有了一点想法,在这里记录一下。 前面实现的每个电路,都是一个固定的布尔函数,实际上也可以看作是一个固定的程序。 推广开来看,所有程序都可以看作是一个固定的电路,而ALU的思想,指令集的思想在于抽象出所有这些电路的共同语言,从上面对ALU的解剖可以看到,这些共同语言都是最基础最简单的布尔函数,前人真是太厉害了,挖出来喂鸡腿😄