FPGA開発日記

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

Parameter / Conifgで作るコンフィグレーション可能なChiselデザイン

upによるパラメータのオーバーライド

前回から調査しているChiselデザインのParameterization、site(), here(), up()の調査の中で、今回はup()の調査を行う。

up()の使用方法は、とりあえずサンプルデザインを見るのがいいだろう。以下では、Adder()Mul()の2つのモジュールを定義している。p(BitWidth)で入出力ビット数を定義している。Adder()Mul()のビット幅を全く別物で定義したい場合どうするかという問題を考える。

class Adder()(implicit p: Parameters) extends Module {
  val bitwidth = p(BitWidth)
  val io = IO(new Bundle{
    val a = Input(SInt(bitwidth.W))
    val b = Input(SInt(bitwidth.W))
    val c = Output(SInt(bitwidth.W))
  })

  io.c := io.a + io.b
}

class Mul()(implicit p: Parameters) extends Module {
  val bitwidth = p(BitWidth)
  val io = IO(new Bundle{
    val a = Input(SInt(bitwidth.W))
    val b = Input(SInt(bitwidth.W))
    val c = Output(SInt((bitwidth * 2).W))
  })

  io.c := io.a * io.b
}

この時、Adder()Mul()のパラメータは以下のように定義している。Adder()は64ビット、Mul()は128ビットの入力ビット幅でインスタンス化するものとする。

case object AdderBitWidth extends Field[Int]
case object MulBitWidth extends Field[Int]

class DefaultConfig() extends Config((site, here, up) => {
  case AdderBitWidth => 64
  case MulBitWidth => 128
})

Adder()Mul()インスタンス時にそれぞれのパラメータをオーバライドするわけだが、adder_parammul_paramを新たに定義して渡すことになる。

  val Adder_mod = Module(new Adder()(adder_params))
  Adder_mod.io.a := io.a
  Adder_mod.io.b := io.b
  io.Adder_c := Adder_mod.io.c

  val mul_mod = Module(new Mul()(mul_params))
  mul_mod.io.a := io.a
  mul_mod.io.b := io.b
  io.mul_c := mul_mod.io.c

ここで、adder_paramsは上記のDefaultConfigを引き継ぎつつ、BitWidthパラメータを継承前のDefaultConfigで使用しているパラメータで引き継ぐ。この時にup()を使用する。これにより、`

  val adder_params = p.alter((site, here, up) => {
    case BitWidth => up(AdderBitWidth)
  })

  val mul_params = p.alter((site, here, up) => {
    case BitWidth => up(MulBitWidth)
  })

adder_paramsBitWidthDefaultConfigAdderBitWidthを引き継ぎ、mul_paramsBitWidthDefaultConfigMulBitWidthを引き継ぐことになる。これにより、同じBitWidthパラメータでも別々のパラメータを引き継ぐことが可能になる。

結果は以下の通り、Adderの入力ビット幅はAddrBitWidthを引き継いで64ビットとなり、Mulの入力ビット幅はMulBitWidthを引き継いで128ビットとなった。

module Adder(
  input  [63:0] io_a,
  input  [63:0] io_b,
  output [63:0] io_c
);
  assign io_c = $signed(io_a) + $signed(io_b); // @[up_example.scala 48:8]
endmodule
module Mul(
  input  [127:0] io_a,
  input  [127:0] io_b,
  output [255:0] io_c
);
  assign io_c = $signed(io_a) * $signed(io_b); // @[up_example.scala 59:8]
endmodule