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

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

Chisel Bootcamp - Module3.6(3) - Chiselの異なるデータ型の接続について

スポンサーリンク

前回のChisel-Bootcampの学習ではScalaunapplyと部分関数についてを見ていった。

www.tech-diningyo.info

今回も引き続きModule3.6を見ていく。今日はChiselの型についてもう少し詳しく見ていく。

型安全な接続

Chiselの型同士を接続する場合に何がチェックされているのか、、という部分についての項目。 多くの場合についてはChiselは接続時にチェックを行ってくれていてまずい場合にはエラーを出してくれる。

とりあえずサンプルコードは以下。

class Bundle1 extends Bundle {
  val a = UInt(8.W)
  override def cloneType = (new Bundle1).asInstanceOf[this.type]
}

class Bundle2 extends Bundle1 {
  val b = UInt(16.W)
  override def cloneType = (new Bundle2).asInstanceOf[this.type]
}

class BadTypeModule extends Module {
  val io = IO(new Bundle {
    val c  = Input(Clock())
    val in = Input(UInt(2.W))
    val out = Output(Bool())

    val bundleIn = Input(new Bundle2)
    val bundleOut = Output(new Bundle1)
  })

  //io.out := io.c // 型が異なるためエラーになる

  // 接続可能だがOutputのビット幅に合わせて下位の1bit以外は落とされる
  io.out := io.in

  // コンパイル可能;Chiselは2つのBundleから共通する要素同士を接続する(この場合だと、"a"のみが接続される)
  io.bundleOut := io.bundleIn
}
  • 上記の回路からRTLを生成した結果
[info] [0.000] Elaborating design...
[info] [0.009] Done elaborating.
Total FIRRTL Compile Time: 19.3 ms
module cmd10HelperBadTypeModule( // @[:@3.2]
  input         clock, // @[:@4.4]
  input         reset, // @[:@5.4]
  input         io_c, // @[:@6.4]
  input  [1:0]  io_in, // @[:@6.4]
  output        io_out, // @[:@6.4]
  input  [7:0]  io_bundleIn_a, // @[:@6.4]
  input  [15:0] io_bundleIn_b, // @[:@6.4]
  output [7:0]  io_bundleOut_a // @[:@6.4]
);
  assign io_out = io_in[0];
  assign io_bundleOut_a = io_bundleIn_a;
endmodule

上記のコメント中にあるとおり、ClockはChiselおいては別の型になるので、これをUIntBoolに接続するとエラーになる。 UIntBoolBoolUIntは接続可能。これはBoolUIntを継承して作れらた型になっているから。

sealed class Bool(lit: Option[ULit] = None) extends UInt(1.W, lit) with Reset {

3つめのBundleを使った例では、Bundle2Bundle1を継承した結果Bundle2にもaが存在しているので、そのaのみが接続される結果となる。 因みにこれは:=を使って接続した場合で、<>を使って接続しようとするとbが存在しないためエラーになる。

chisel3.internal.ChiselException: Connection between left
(ammonite.$sess.cmd6$Helper$Bundle1@27) and source (ammonite.$sess.cmd6$Helper$Bundle2@22)
failed @.b: Left Record missing field (b).

一方でSIntUIntSIntBoolについては何もせずに接続すると以下のようなエラーが発生する。

chisel3.internal.ChiselException: Connection between sink (chisel3.core.SInt@20)
and source (chisel3.core.UInt@1e) failed @: Sink (chisel3.core.SInt@20) and Source
(chisel3.core.UInt@1e) have different types.

ということでざっくりまとめると以下のような感じか。

接続 結果
ClockBool or UInt エラー
SIntBool or UInt エラー
BoolUInt 接続可能だが、接続先のビット幅に合わせて上位ビットの切り捨て又は上位ビットへのパディング
Bundle ABundle B:=を使用した場合) 型と名前が一致するポートのみが接続される
Bundle ABundle B<>を使用した場合) 全変数の名前と型が一致する場合のみ接続可能

一応補足すると、IOの接続に置いてはポートの方向はいずれの場合でもチェックされるため、接続の方向がぶつかった場合にはエラーになる。Verilogだと警告出てもエラーにならなかったりするよね、これ。
ということでUIntBoolで意図しない接続がされてないか、、という部分はチェックが必要だけど、それ以外についてはChiselのエラボレート時にかなり細かく見てくれるので、これに結構助けられるケースはあるはず。

あっさり目だけど、キリもいいので今日はここまで。