学び直し27日目:5章 コンピュータアーキテクチャ⑦:プロジェクト-CPU(3)
記録
やっと CPU 書き終えた。自力でがんばろうとしたけど、結局以下を参考にさせていただいてしまった。。
blog.tojiru.net
考え方はだいたいあっていたが、その先の地道な作業を考え抜く力が不足している。ともあれ、形にはなったので次の Computer の実装をがんばるぞ!
コツ
- instruction[15] で、A 命令か C 命令か頻繁にジャッジしてあげる必要があった。
- PC を inc するか load するかの判断は、やや面倒だが ALU 出力の正負零と instruction[0..2] をそれぞれ And 取ってあげたらよい。ALU 出力が正であることは、「ゼロでないかつ負でない」とすればよい。
- C 命令から ALU に命令を伝える方法は、機械語の仕様に従ってすなおにやればよい。よくできてるなぁ。
CPU
// 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/05/CPU.hdl /** * The Hack CPU (Central Processing unit), consisting of an ALU, * two registers named A and D, and a program counter named PC. * The CPU is designed to fetch and execute instructions written in * the Hack machine language. In particular, functions as follows: * Executes the inputted instruction according to the Hack machine * language specification. The D and A in the language specification * refer to CPU-resident registers, while M refers to the external * memory location addressed by A, i.e. to Memory[A]. The inM input * holds the value of this location. If the current instruction needs * to write a value to M, the value is placed in outM, the address * of the target location is placed in the addressM output, and the * writeM control bit is asserted. (When writeM==0, any value may * appear in outM). The outM and writeM outputs are combinational: * they are affected instantaneously by the execution of the current * instruction. The addressM and pc outputs are clocked: although they * are affected by the execution of the current instruction, they commit * to their new values only in the next time step. If reset==1 then the * CPU jumps to address 0 (i.e. pc is set to 0 in next time step) rather * than to the address resulting from executing the current instruction. */ 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: // Put your code here: // instruction // A : 0vvv vvvv vvvv vvvv // C : 111a cccc ccdd djjj // a = instruction[12] // c = instruction[6..11] // d1 = instruction[5] // d2 = instruction[4] // d3 = instruction[3] // j1 = instruction[2] // j2 = instruction[1] // j3 = instruction[0] // A-register への入出力 Mux16(a=instruction, b=outALU, sel=instruction[15], out=inA); Not(in=instruction[15], out=cmdA); Or(a=cmdA, b=instruction[5], out=loadA); ARegister(in=inA, load=loadA, out=outA, out[0..14]=addressM); // D-registerへの入出力 And(a=instruction[4], b=instruction[15], out=loadD); DRegister(in=outALU, load=loadD, out=outD); Mux16(a=outA, b=inM, sel=instruction[12], out=outAM); // ALU ALU( x=outD, y=outAM, zx=instruction[11], nx=instruction[10], zy=instruction[9], ny=instruction[8], f=instruction[7], no=instruction[6], out=outALU, out=outM, zr=zr, ng=ng ); // Memory への Write And(a=instruction[3], b=instruction[15], out=writeM); // PC And(a=ng, b=instruction[2], out=j1true); And(a=zr, b=instruction[1], out=j2true); And(a=plus, b=instruction[0], out=j3true); Or(a=ng, b=zr, out=notplus); Not(in=notplus, out=plus); Or(a=j1true, b=j2true, out=j12true); Or(a=j12true, b=j3true, out=j123true); And(a=j123true, b=instruction[15], out=loadPC); Not(in=loadPC, out=incPC); PC( in=outA, inc=incPC, load=loadPC, reset=reset, out[0..14]=pc ); }
今日の筋トレ
酒飲んじゃったのでおやすみ。