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_paramとmul_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_paramsのBitWidthはDefaultConfigのAdderBitWidthを引き継ぎ、mul_paramsのBitWidthはDefaultConfigのMulBitWidthを引き継ぐことになる。これにより、同じ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