ハードウェアの気になるあれこれ

技術的に興味のあることを調べて書いてくブログ。主にハードウェアがネタ。

Chisel Bootcamp - Module2.1 (3) - Verilog/FIRRTLの確認とprintfデバッグ

スポンサーリンク

前回の記事ではChisel BootcampのModule2.1の大体の学習が終わったところだった。

www.tech-diningyo.info

今回はModule2.1の最初のモジュールの残りを片付ける。内容的には主にデバッグの際にどうすればいいかというものだ。

Module 2.1: 最初のChiselモジュール

生成されるVeirlog/FIRRTLの確認方法

生成されたハードウェアが何か問題を持っていて、VerilogやFIRRTLを確認したい場合のために、Chiselの実行時にVerilogを確認する方法が用意されているそうだ。

// Viewing the Verilog for debugging
println(getVerilog(new Passthrough))

こちらは既に使われていたが一応実行すると以下のように生成されたVerilogコードが表示できる。

[info] [0.000] Elaborating design...
[info] [0.057] Done elaborating.
Total FIRRTL Compile Time: 8.7 ms
module cmd8HelperPassthrough( // @[:@3.2]
  input        clock, // @[:@4.4]
  input        reset, // @[:@5.4]
  input  [3:0] io_in, // @[:@6.4]
  output [3:0] io_out // @[:@6.4]
);
  assign io_out = io_in;
endmodule
  • FIRRTL
// Viewing the firrtl for debugging
println(getFirrtl(new Passthrough))

こちらはFIRRTL

[info] [0.000] Elaborating design...
[info] [0.003] Done elaborating.
;buildInfoPackage: chisel3, version: 3.1.0, scalaVersion: 2.11.12, sbtVersion: 1.1.1, builtAtString: 2018-04-17 19:22:56.455, builtAtMillis: 1523992976455
circuit cmd8HelperPassthrough : 
  module cmd8HelperPassthrough : 
    input clock : Clock
    input reset : UInt<1>
    output io : {flip in : UInt<4>, out : UInt<4>}
    
    io.out <= io.in @[cmd8.sc 6:10]

FIRRTLって知ってるふうに書いてみたけど、知らんので一応調べてみた。

https://github.com/freechipsproject/firrtl

Firrtl is an intermediate representation (IR) for digital circuits designed as a platform for writing circuit-level transformations. This repository consists of a collection of transformations (written in Scala) which simplify, verify, transform, or emit their input circuit.

RTLの中間表現みたいなものの様子。仕様とかも公開されてるみたいなので後でチェックしてみよう。

補足A:"printf"デバッグ

"補足"となっているが、重要なセクションな気がするので本文を丸々訳して引用させてもらう

printfデバッグはいつでも最適な方法というわけではないが、何かが思い通りに動かない場合に最初に試すには簡単な方法だ。Chiselはハードウェアを生成する言語なので、ジェネレータや回路の状態を出力するにはいくつかの微妙な部分がある。そのためデバッグの際に”いつプリント文を実行するのか”と”何を出力するのか”についてを覚えておくことは重要なことで、一般的には何を出力するかについて3つのシナリオがあり、それぞれに以下のような重要な違いがある:

  1. Chiselが回路生成に出力する文
  2. 回路が回路シミュレーション中に出力する文
  3. テスターがテスト時に出力する文

pringlnはコンソールへの出力を行うビルトイン関数であり、生成されたVerilogやFIRRTLはScalaではないため回路シミュレーション中のプリント出力に使うことは出来ない

ということで回路シミュレーション中にプリント出力を行うために別の手段が用意されているようで、その例が以下のサンプルに含まれている。

class PrintingModule extends Module {
    val io = IO(new Bundle {
        val in = Input(UInt(4.W))
        val out = Output(UInt(4.W))
    })
    io.out := io.in

    printf("Print during simulation: Input is %d\n", io.in)
    // chisel printf has its own string interpolator too
    printf(p"Print during simulation: IO is $io\n")

    println(s"Print during generation: Input is ${io.in}")
}

class PrintingModuleTester(c: PrintingModule) extends PeekPokeTester(c) {
    poke(c.io.in, 3)
    step(5) // circuit will print
    
    println(s"Print during testing: Input is ${peek(c.io.in)}")
}
chisel3.iotesters.Driver( () => new PrintingModule ) { c => new PrintingModuleTester(c) }

上記を実行すると以下の出力が得られる。

[info] [0.000] Elaborating design...
Print during generation: Input is chisel3.core.UInt@e
[info] [0.024] Done elaborating.
Total FIRRTL Compile Time: 31.1 ms
Total FIRRTL Compile Time: 13.0 ms
End of dependency graph
Circuit state created
[info] [0.000] SEED 1539504126474
Print during simulation: Input is 3
Print during simulation: IO is Bundle(in -> 3, out -> 3)
Print during simulation: Input is 3
Print during simulation: IO is Bundle(in -> 3, out -> 3)
Print during simulation: Input is 3
Print during simulation: IO is Bundle(in -> 3, out -> 3)
Print during simulation: Input is 3
Print during simulation: IO is Bundle(in -> 3, out -> 3)
Print during simulation: Input is 3
Print during simulation: IO is Bundle(in -> 3, out -> 3)
[info] [0.010] Print during testing: Input is 3
test cmd15HelperPrintingModule Success: 0 tests passed in 10 cycles taking 0.018664 seconds
[info] [0.011] RAN 5 CYCLES PASSED

いくつか見たことの無いコードが例には含まれていたが、大事なのは以下の違いになる。

  • PrintingModule中のprintlnはエラボーレションの直後に一回だけ出力される
  • PrintingModule中のprintfはテスト時の各ステップにおいて毎ステップ表示される

ということなので、

  • 回路シミュレーション中にデバッグプリントを仕込む場合にはChiselのprintfを使う

ということで良さそう。

これでModule2.1 最初のモジュールが完了なので次の学習に進もう。