FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Chisel-Templateを使ってオリジナルデザインを作ってみるチュートリアル (1. デザインの作成)

f:id:msyksphinz:20180702001454p:plain

RISC-Vの実装であるRocket-ChipはChiselと呼ばれるDSLで記述されているのだが、この書き方やテクニックについてはあまり知られていない(まあ知る必要もないが...)

ただし、AWSで動作するFireSimを改良したりだとか、Rocket-Coreを改造する場合にはこの知識は必須になるので、Chiselのチュートリアルを試して、理解してみることにした。

参考にしたのは以下の2つのリポジトリだが、このリポジトリを見ながら考えること以外に、参考になる文献が全くないのでかなりきつい。

github.com

github.com

とりあえず簡単な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)

なんとか修正していく。