前回まででループ展開の問題に対してある程度解決の目途が立った。しかしまだ調整できていない部分がある。
ExpandWhes
によりデフォルト値が挿入されるのだが、これはなぜかというとポートであるout
と記述とout.a[0], out.a[1], out.a[2], out.a[3]
がずれているため、デフォルト値が挿入されているようだ。
circuit VecExtract : module VecExtract : input in : UInt<32>[4][4][4] input sel1 : UInt<2> input sel2 : UInt<2> output out : { a : UInt<32>[4]} out.a[0] <= in[sel1][sel2][0] out.a[1] <= in[sel1][sel2][1] out.a[2] <= in[sel1][sel2][2] out.a[3] <= in[sel1][sel2][3]
からの、
skip out.a <= VOID out.a[0] <= in[sel1][sel2][0] out.a[1] <= in[sel1][sel2][1] out.a[2] <= in[sel1][sel2][2] out.a[3] <= in[sel1][sel2][3]
でout.a
にVOIDが挿入されてしまう問題。これは、output out : { a : UInt<32>[4]}
が展開されないため出力のout
が使用されていないと勘違いされてしまい、これにより余計に挿入されてしまう文である。
これを解決するために色々試行錯誤したのだが、結局自前のcreate_exps
を挿入してポート部分の配列は展開して対処することにした。
src/main/scala/firrtl/passes/ExpandWhens.scala
/** Returns all references to all Female leaf subcomponents of a reference */ private def getFemaleRefs(n: String, t: Type, g: Flow): Seq[Expression] = { val exps = create_exps_port(n, t, g) // create_expsの代わりにcreate_exps_portを使用する val ret = exps.flatMap { case exp => ...
create_exps_port
の実装は以下のようにした。要するにTypeに応じて生成するExpression
を切り替える。
def create_exps_port(n: String, t: Type, g: Flow): Seq[Expression] = { val base_wref = WRef(n, t, ExpKind, g) val base_exp = create_exps(base_wref) t match { case (_: GroundType) => base_exp case t: BundleType => t.fields.flatMap(f => create_exps_connect(WSubField(base_wref, f.name, f.tpe, times(g, f.flip)))) case t: VectorType => (0 until t.size).flatMap(i => create_exps_connect(WSubIndex(base_wref, i, t.tpe, g))) } }
これにより以下のように配列が展開される。
circuit VecArray : module VecArray : input in : UInt<8>[2][4][8] input sel : UInt<3> output out : UInt<8>[2][4] out[0][0] <= in[sel][0][0] out[0][1] <= in[sel][0][1] out[1][0] <= in[sel][1][0] out[1][1] <= in[sel][1][1] out[2][0] <= in[sel][2][0] out[2][1] <= in[sel][2][1] out[3][0] <= in[sel][3][0] out[3][1] <= in[sel][3][1]
また、以下のような配列に対しても正常に展開可能だ。
module VecBundle9 : input in: { a : { b : { c : UInt<8>[4] } [8] } [16] }[32] input sel1: UInt<5> input sel2: UInt<4> input sel3: UInt<3> output out : { b : UInt<8>[4] } out.b <= in[sel1].a[sel2].b[sel3].c
module VecBundle9 : input in_a_b_c : UInt<8>[4][8][16][32] input sel1 : UInt<5> input sel2 : UInt<4> input sel3 : UInt<3> output out_b : UInt<8>[4] out_b[0] <= in_a_b_c[sel1][sel2][sel3][0] out_b[1] <= in_a_b_c[sel1][sel2][sel3][1] out_b[2] <= in_a_b_c[sel1][sel2][sel3][2] out_b[3] <= in_a_b_c[sel1][sel2][sel3][3]