FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

FIRRTLに入門する (19. 多次元配列及び構造体に関する処理の検討)

https://raw.githubusercontent.com/freechipsproject/firrtl/master/doc/images/firrtl_logo.svg?sanitize=true

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