前回、多次元配列をそのまま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]