前回まででループ展開の問題に対してある程度解決の目途が立った。しかしまだ調整できていない部分がある。
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]