$ sbt assembly && ./utils/bin/firrtl -td regress -i ./regress/ICache.fir -X sverilog -ll trace 2>&1 | tee ICache.log
======== Starting Transform CheckInitialization$ ======== Exception in thread "main" firrtl.passes.PassExceptions: firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.data[1] <= mux(refill_done, mux(_T_321[1], _T_304[1], VOID), VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.mask[0] <= mux(refill_done, _GEN_7, VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.data[3] <= mux(refill_done, mux(_T_321[3], _T_304[3], VOID), VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.mask[3] <= mux(refill_done, _GEN_10, VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.data[0] <= mux(refill_done, mux(_T_321[0], _T_304[0], VOID), VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.data[2] <= mux(refill_done, mux(_T_321[2], _T_304[2], VOID), VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.mask[2] <= mux(refill_done, _GEN_9, VOID) firrtl.passes.CheckInitialization$RefNotInitializedException: @[ICache.scala 97:25] : [module ICache] Reference tag_array is not fully initialized. : tag_array._T_328.mask[1] <= mux(refill_done, _GEN_8, VOID)
いろいろ調査した結果、どうもSRAMを最初に展開しておかないといけないのが問題らしい。つまり、以下のようなFIRコードを考える。
circuit VecMem : module VecMem : input clock : Clock input in: UInt<32> input wr_en: UInt<1> input rd_en: UInt<1> input addr: UInt<6> input data: UInt<1> output rdata : UInt<32>[4] smem array : UInt<32>[4][64] when rd_en : read mport rdata_tmp = array[addr], clock when wr_en : write mport wdata = array[addr], clock rdata <= rdata_tmp
このときにExpandConnect()
においてIsInvalid
の場合、ちゃんと展開しておかなければならない。
src/main/scala/firrtl/passes/Passes.scala
object ExpandConnects extends Pass { ... case sx: DefMemory => flows(sx.name) = SourceFlow; sx case sx: DefNode => flows(sx.name) = SourceFlow; sx case sx: IsInvalid => // create_expsからcreate_exps_connectに置き換える。 val invalids = create_exps_connect(sx.expr).flatMap { case expx => flow(set_flow(expx)) match { case DuplexFlow => Some(IsInvalid(sx.info, expx)) case SinkFlow => Some(IsInvalid(sx.info, expx))
これでFIRRTLを実行してみる。
sbt assembly && ./utils/bin/firrtl -td regress -i regress/VecMem.fir -X sverilog -ll trace 2>&1 | tee VecMem.log
ExpandConnect()
実行前。
... array.wdata.data is invalid array.wdata.mask is invalid ...
ExpandConnect()
実行後。
array.wdata.data[0] is invalid array.wdata.data[1] is invalid array.wdata.data[2] is invalid array.wdata.data[3] is invalid array.wdata.mask[0] is invalid array.wdata.mask[1] is invalid array.wdata.mask[2] is invalid array.wdata.mask[3] is invalid
このように展開しておく。これで一応エラーなく実行できるようになったようだ。
logic [31:0][3:0] array [0:63]; ... assign array_rdata_tmp_addr = array_rdata_tmp_addr_pipe_0; assign array_rdata_tmp_data = array[array_rdata_tmp_addr]; ...
ただしこれでもまだおかしいところがある。また解析して作り直そう。