FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages

FIRRTLに入門する (23. 多次元配列の出力時のループ展開の調整(2))

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

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

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]