前回、多次元配列をそのままChiselで扱うためにはどうすればよいか考えたが、さらにまだ考えないといけないことがある。これに、構造体が入ってきた場合はどうするか、ということだ。つまり、以下のようなコードを考える。
circuit VecBundle2 :
module VecBundle2 :
input in: { a : UInt<32>[3] }[4]
input sel: UInt<2>
output out : { a : UInt<32>[3] }
out.a <= in[1].a
このようなコードの場合、まずはin: { a : UInt<32>[3] }[4]を扱う必要があるが、これを、
in_a : UInt<32>[3][4]
に置き換える必要がある。このために、create_expsを改造する。キモとしては、BundleTypeが来た場合、先に構造体の名前を出していって、構造体を分解していく。
def create_exps(e: Expression): Seq[Expression] = e match { case ex: Mux => val e1s = create_exps(ex.tval) ... case ex: WRef => { ex.tpe match { case (_: GroundType) => Seq(ex) case t: BundleType => { val ret = t.fields.flatMap(f => create_exps(WRef(loweredExpName(ex, f.name), f.tpe, ExpKind, flow(ex)))) ret }
各構造体のメンバに対してcreate_expsを適用していくのだが、新しい名前はloweredExpNameで生成し、その型は直下の型とする。これがcreate_exps(WRef(loweredExpName(ex, f.name), f.tpe, ExpKind, flow(ex))の意味するところだ。
これにより、上記のコードはいかのように変換される。
circuit VecBundle2 :
module VecBundle2 :
input in_a : UInt<32>[3][4]
input sel : UInt<2>
output out_a : UInt<32>[3]
skip
out_a <= in_a[1]
WSubIndexでなくても、WSubAccessでも同様に変換できることが確認できた。
circuit VecBundle2 :
module VecBundle2 :
input in_a : UInt<32>[3][4]
input sel : UInt<2>
output out_a : UInt<32>[3]
skip
out_a <= in_a[sel]