随分とほったらかしにしていたが、Chiselを使ってオリジナルデザイン開発を再開した。
簡単なRISC-VコアをフルスクラッチでChiselで作ってみて、Chiselの理解を深めようと思う。
各種命令の実装
まずはシンプルな算術演算命令の実装を行う。ALUの実装はまずはこの程度だ。
class Alu extends Module { val io = IO (new Bundle { val func = Input (UInt(4.W)) val op0 = Input (SInt(64.W)) val op1 = Input (SInt(64.W)) val res = Output (SInt(64.W)) }) val w_res = Wire(SInt(64.W)) when (io.func === ALU_ADD) { w_res := io.op0 + io.op1 } .elsewhen (io.func === ALU_SUB) { w_res := io.op0 - io.op1 } .elsewhen (io.func === ALU_SLL) { w_res := (io.op0.asUInt << io.op1(5,0).asUInt).asSInt } .elsewhen (io.func === ALU_SRL) { w_res := (io.op0.asUInt >> io.op1(5,0).asUInt).asSInt } .elsewhen (io.func === ALU_SRA) { w_res := (io.op0 >> io.op1(5,0).asUInt).asSInt } .elsewhen (io.func === ALU_AND) { w_res := io.op0 & io.op1 } .elsewhen (io.func === ALU_OR) { w_res := io.op0 | io.op1 } .elsewhen (io.func === ALU_XOR) { w_res := io.op0 ^ io.op1 } .elsewhen (io.func === ALU_SLT) { w_res := Mux(io.op0 < io.op1, 1.S, 0.S) } .elsewhen (io.func === ALU_SLTU) { w_res := Mux(io.op0.asUInt < io.op1.asUInt, 1.S, 0.S) } .elsewhen (io.func === ALU_COPY1) { w_res := io.op0 } .otherwise { w_res := io.op0 } val r_res = Reg(SInt(64.W)) r_res := w_res io.res := w_res }
2018/11/20追記。よく見てみたらChiselではcase文が使えるんだった。書き直した。
val w_res = Wire(SInt(64.W)) w_res := 0.S switch (io.func) { is (ALU_ADD ) { w_res := io.op0 + io.op1 } is (ALU_SUB ) { w_res := io.op0 - io.op1 } is (ALU_SLL ) { w_res := (io.op0.asUInt << io.op1(5,0).asUInt).asSInt } is (ALU_SRL ) { w_res := (io.op0.asUInt >> io.op1(5,0).asUInt).asSInt } is (ALU_SRA ) { w_res := (io.op0 >> io.op1(5,0).asUInt).asSInt } is (ALU_AND ) { w_res := io.op0 & io.op1 } is (ALU_OR ) { w_res := io.op0 | io.op1 } is (ALU_XOR ) { w_res := io.op0 ^ io.op1 } is (ALU_SLT ) { w_res := Mux(io.op0 > io.op1, 1.S, 0.S) } is (ALU_SLTU ) { w_res := Mux(io.op0.asUInt > io.op1.asUInt, 1.S, 0.S) } is (ALU_SNE ) { w_res := Mux(io.op0 =/= io.op1, 1.S, 0.S) } is (ALU_SEQ ) { w_res := Mux(io.op0 === io.op1, 1.S, 0.S) } is (ALU_SGE ) { w_res := Mux(io.op0 > io.op1, 1.S, 0.S) } is (ALU_SGEU ) { w_res := Mux(io.op0.asUInt > io.op1.asUInt, 1.S, 0.S) } is (ALU_COPY1) { w_res := io.op0 } }
テストパタンの作成
テストパタンは、以下のようなパタンを作ってISSと比較した。
addi x1, x10, 0x610 andi x2, x11, 0x580 ori x3, x12, 0x0cb xori x4, x13, 0x553 slti x5, x14, 0x292 sltiu x6, x15, 0x7f5 slli x7, x16, 0x6 srai x8, x17, 0x7 srli x9, x18, 0x2 sll x1, x10, x20 add x2, x11, x21 sub x3, x12, x22 slt x4, x13, x23 sltu x5, x14, x24 and x6, x15, x25 or x7, x16, x26 xor x8, x17, x27 sra x9, x18, x28 srl x10, x19, x29 addiw x1, x10, 0x170 slliw x2, x11, 0xb srliw x3, x12, 0xc sraiw x4, x13, 0x8 addw x5, x14, x24 subw x6, x15, x25 sllw x7, x16, x26 srlw x8, x17, x27 sraw x9, x18, x28