Chiselにはバージョンがあり、Chisel2とChisel3が公開されている。 微妙に文法が異なっているので要注意だ。
Chisel2ではVerilogとC++を生成する方法が公開されているが、Chisel3ではどうだろう。
Chisel2でのVerilogとC++の生成方法については、以下のサイトにまとめられている。 と思っていろいろ探したら自分のブログだった。
src/main/scala/hello/Hello.scala
package Hello import Chisel._ class Hello extends Module { val io = new Bundle { val out = UInt(OUTPUT, 8) } io.out := UInt(42) } class HelloTests(c: Hello) extends Tester(c) { step(1) expect(c.io.out, 42) } object Hello { def main(args: Array[String]): Unit = { val tutArgs = args.slice(1, args.length) chiselMainTest(tutArgs, () => Module(new Hello())) { c => new HelloTests(c) } } }
Chisel3を触っているとわかる。微妙に違う。まず、import Chisel._
ではなくChisel3だとimport chisel3._
になる。次にBundleにカッコが入っていない。
次に、chiselMainTest
などという関数はない。これらを修正していく必要がある。
Chisel2では、chiselMainTest
のargsを変更することによりC++を出力することができる。
つまり、--backend c
を追加することでC++のコードが生成できる。
しかし、Chisel3ではできない。どのようにすればよいのか。
まず、上記のデザインはChisel3では以下のようになる。
package hello import chisel3._ import chisel3.iotesters.{PeekPokeTester, Driver} class Hello extends Module { val io = IO(new Bundle { val out = Output(UInt(8.W)) }) io.out := 42.U } class HelloTests(c: Hello) extends PeekPokeTester(c) { step(1) expect(c.io.out, 42) } object Hello { def main(args: Array[String]): Unit = { if (!Driver(() => new Hello())(c => new HelloTests(c))) System.exit(1) } }
細かな文法の違いはあるが、大きくはchiselMainTest()
が消える。その代わり、iotestersのDriverが直接呼び出される。
このAPIはVerilogを生成するためのAPIである。じゃあC++を生成するためにはどうすればよいのか。
[https://chisel.eecs.berkeley.edu/api/latest/chisel3/Driver$.html#execute(args:Array[String],dut:()=%3Echisel3.experimental.RawModule):chisel3.ChiselExecutionResult:title]
同じiotestersにverilogToCpp
というメソッドがあるけど、これは何か違う気がする。
[https://chisel.eecs.berkeley.edu/api/latest/chisel3/Driver$.html#verilogToCpp(dutFile:String,dir:java.io.File,vSources:Seq[java.io.File],cppHarness:java.io.File,suppressVcd:Boolean):scala.sys.process.ProcessBuilder:title]
結論から言うと、Chisel3でC++を生成するのは直接的には不可能で、VerilatorでシミュレーションするためにC++を生成するという考え方に近い。
このiotestersのDriverにはどのような機能があるのか。オプションを与えるように変更していろいろと変えてみる。
object Hello { def main(args: Array[String]): Unit = { chisel3.Driver.execute(args, () => new Hello) } }
sbt実行時に`sbt "run Hello.Hello --help"とか入れてみる。
common options -tn, --top-name <top-level-circuit-name> This options defines the top level circuit, defaults to dut when possible -td, --target-dir <target-directory> This options defines a work directory for intermediate files, default is . -ll, --log-level <Error|Warn|Info|Debug|Trace> This options defines a work directory for intermediate files, default is . -cll, --class-log-level <FullClassName:[Error|Warn|Info|Debug|Trace]>[,...] This options defines a work directory for intermediate files, default is . -ltf, --log-to-file default logs to stdout, this flags writes to topName.log or firrtl.log if no topName -lcn, --log-class-names shows class names and log level in logging output, useful for target --class-log-level --help prints this usage text <arg>... optional unbounded args chisel3 options -chnrf, --no-run-firrtl Stop after chisel emits chirrtl file firrtl options -i, --input-file <firrtl-source> use this to override the default input file name , default is empty -o, --output-file <output> use this to override the default output file name, default is empty -faf, --annotation-file <input-anno-file> Used to specify annotation files (can appear multiple times) -foaf, --output-annotation-file <output-anno-file> use this to set the annotation output file -X, --compiler <high|middle|low|verilog|sverilog> compiler to use, default is verilog --info-mode <ignore|use|gen|append> specifies the source info handling, default is append -fct, --custom-transforms <package>.<class> runs these custom transforms during compilation. -fil, --inline <circuit>[.<module>[.<instance>]][,..], Inline one or more module (comma separated, no spaces) module looks like "MyModule" or "MyModule.myinstance -firw, --infer-rw <circuit> Enable readwrite port inference for the target circuit -frsq, --repl-seq-mem -c:<circuit>:-i:<filename>:-o:<filename> Replace sequential memories with blackboxes + configuration file -clks, --list-clocks -c:<circuit>:-m:<module>:-o:<filename> List which signal drives each clock of every descendent of specified module -fsm, --split-modules Emit each module to its own file in the target directory. --no-check-comb-loops Do NOT check for combinational loops (not recommended) --no-dce Do NOT run dead code elimination
--compiler
オプションがあるが、ここにはhigh|middle|low|verilog|sverilog
とだけあり、high|middle|low
はFIRのレベル、sverilogに至っては生成されるものはVerilogと同一である。
このあたりのオプションがChisel2とChisel3ではかなり異なっている。注意して扱う必要がありそうだ。