コンピューター理論、チョットデキルようになりたい

コンピュータサイエンスの学び直しです

学び直し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
    );
}

今日の筋トレ

酒飲んじゃったのでおやすみ。