RISC-Vの実装であるRocket-ChipはChiselと呼ばれるDSLで記述されているのだが、この書き方やテクニックについてはあまり知られていない(まあ知る必要もないが...)
ただし、AWSで動作するFireSimを改良したりだとか、Rocket-Coreを改造する場合にはこの知識は必須になるので、Chiselのチュートリアルを試して、理解してみることにした。
参考にしたのは以下の2つのリポジトリだが、このリポジトリを見ながら考えること以外に、参考になる文献が全くないのでかなりきつい。
とりあえず簡単なCPUを作ってみたいと思い、メモリから命令をフェッチするだけの簡単なステートマシンを作ってみたのだが、、、
src/main/scala/cpu/cpu.scala
class Cpu extends Module { val io = IO (new Bundle { val o_instAddr = Output(UInt(8.W)) val o_instReq = Output(Bool()) val i_instAck = Input(Bool()) val i_instData = Input(UInt(32.W)) }) val r_inst_addr = RegInit(0.U(8.W)) val r_inst_en = RegInit(true.B) when(io.i_instAck) { r_inst_addr := r_inst_addr + 4.U(8.W) } io.o_instAddr := r_inst_addr io.o_instReq := r_inst_en }
src/main/scala/cpu/memory.scala
class Memory extends Module { val io = IO(new Bundle { val i_wen = Input(Bool()) val i_wrAddr = Input(UInt(8.W)) val i_wrData = Input(UInt(32.W)) val i_ren = Input(Bool()) val i_rdAddr = Input(UInt(8.W)) val o_rdData = Output(UInt(32.W)) val o_rdEn = Output(Bool()) }) val memory = Mem(256, UInt(32.W)) val r_en = Reg(Bool()) when (io.i_wen) { memory(io.i_wrAddr) := io.i_wrData } r_en := io.i_ren io.o_rdData := memory(io.i_rdAddr) io.o_rdEn := r_en }
Topモジュールは以下のようにして定義した。CPUとメモリを接続しただけだ。
src/main/scala/cpu/cpu.scala
class CpuTop extends Module { val io = IO (new Bundle) val memory = Module(new Memory) val cpu = Module(new Cpu) // Connect CPU and Memory memory.io.i_ren := cpu.io.o_instReq memory.io.i_rdAddr := cpu.io.o_instAddr cpu.io.i_instAck := memory.io.o_rdEn cpu.io.i_instData := memory.io.o_rdData }
これでコンパイルして実行してみたのだが、"No implicit clock and reset."となりうまく行かない。
[info] CpuTopTester: [info] Basic test using Driver.execute [info] - should be used as an alternative way to run specification *** FAILED *** [info] chisel3.internal.ChiselException: Error: No implicit clock and reset. [info] at chisel3.internal.throwException$.apply(Error.scala:13) [info] at chisel3.internal.Builder$.forcedClockAndReset(Builder.scala:209) [info] at chisel3.internal.Builder$.forcedReset(Builder.scala:212) [info] at chisel3.core.Module$.reset(Module.scala:75) [info] at chisel3.core.printf$$anonfun$apply$2.apply(Printf.scala:89) [info] at chisel3.core.printf$$anonfun$apply$2.apply(Printf.scala:89) [info] at chisel3.core.WhenContext$$anonfun$1.apply(When.scala:72) [info] at chisel3.core.WhenContext$$anonfun$1.apply(When.scala:72) [info] at scala.Option.foreach(Option.scala:257) [info] at chisel3.core.WhenContext.<init>(When.scala:72)
なんとか修正していく。