前回までの多次元構造体の処理を見直して、もう少し簡単になるんじゃないかということで作り直した。基本的な考え方は以下の通りだ。
SubField
(構造体のメンバへのアクセス)が発生すると、WSubField
の構造を取り除き、WRef
と足し込む名前(ex.name
)を記憶して次に進む。WSubIndex
およびWSubAccess
が発生すると、そのままの形を保持する。WRef
の場合、これまでにため込んだ構造体のWSubField
の値を足し込む。
以下のようなソースコードになった。
src/main/scala/firrtl/passes/LowerTypes.scala
def lowerTypesExp(memDataTypeMap: MemDataTypeMap, info: Info, mname: String, subfield_name: String = "")(e: Expression): Expression = { e match { case e: WRef => { val new_subfield_name = subfield_name match { case "" => e.name case x => e.name + "_" + x } e.copy(name = new_subfield_name) }
case e: WSubAccess => { val exps = lowerTypesExp(memDataTypeMap, info, mname, subfield_name)(e.expr) WSubAccess(exps, e.index, e.tpe, flow(e)) }
case e: WSubField => { ... case _ => { val new_subfield_name = subfield_name match { case "" => e.name case x => e.name + "_" + x } lowerTypesExp(memDataTypeMap, info, mname, new_subfield_name)(e.expr) }
case e: WSubIndex => { ... case _ => { val exps = lowerTypesExp(memDataTypeMap, info, mname, subfield_name)(e.expr) WSubIndex(exps, e.value, e.tpe, flow(e)) }
以下の2つのテストをコンパイルする。WSubIndex
とWSubAccess
を使うケースだ。どちらもWSubField
を3階層使用している。
VecBundle.fir
module VecBundle8 : input in: { a : { b : { c : UInt<8>[4] } [8] } [16] }[32] output out : { b : UInt<8>[4] } out.b <= in[0].a[1].b[2].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 <= in[sel1].a[sel2].b[sel3].c
module VecBundle8 : input in_a_b_c : UInt<8>[4][8][16][32] output out_b : UInt<8>[4] out_b <= in_a_b_c[0][1][2] 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_a_b_c[sel1][sel2][sel3]
上手くできた。この配列分解の検討は、とりあえずここまでかな。