FPGA開発日記

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

FIRRTLに入門する (16. LowerType時に配列を分解せずにBundleを分解する手法の調査(2))

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

LowerTypeの調査を続けている、前回の記事からずいぶんと時間が経ってしまったが、Bundleを分解する方法について調査している。つまり、FIRRTLで以下のように記述されているコードを、Vectorを分解せずにBundleのみ分解するということである。

circuit VecBundle :
  module VecBundle :
    input in: { a : UInt<32>, b : UInt<32> }[4]
    input sel: UInt<2>
    output out : { a : UInt<32>, b : UInt<32> }

    out.a <= in[sel].a
    out.b <= in[sel].b

上記のFIRのコードを分解する。下記のようになれば良い。

circuit VecBundle :
  module VecBundle :
    input in_a : UInt<32>[4]
    input in_b : UInt<32>[4]
    input sel : UInt<2>
    output out_a : UInt<32>
    output out_b : UInt<32>

    skip
    out_a <= in_a[sel]
    out_b <= in_b[sel]

このためにLowerType内のメソッドにおいて、loweredNameにおいて、

  • VectorTypeの場合、VectorType自体は維持したまま内部の型を変換する。
  • BundleTypeの場合、Bundleの内部の値を取り出して_でつなげる。
  • WRefの場合、値をそのまま連結して返す。

という手順を取ることにする。これを実現するために、以下のloweredTypeName()を実装した。

  val delim = "_"
  def loweredTypeName(e: Expression): String = loweredTypeName(e, "")
  def loweredTypeName(e: Expression, substr: String): String = e match {
    case e: WRef => {
      if (substr == "") { e.name }
      else              { e.name + "_" + substr }
    }
    case e: WSubField => s"${loweredTypeName(e.expr, substr + e.name)}"
    case e: WSubIndex => s"${loweredTypeName(e.expr, substr)}$delim${e.value}"
    case e: WSubAccess => s"${loweredTypeName(e.expr)}_${substr}[${loweredTypeName(e.index)}]"
  }

これにより、上記のサンプルコードを処理してみる。

sbt assembly && ./utils/bin/firrtl -td regress -i ./regress/VecBundle.fir -X sverilog -ll trace 2>&1 | tee VecBundle.log

まだエラーが出るが、LowerTypeの段階で以下のようになった。

circuit VecBundle :
  module VecBundle :
    input in_a : UInt<32>[4]
    input in_b : UInt<32>[4]
    input sel : UInt<2>
    output out_a : UInt<32>
    output out_b : UInt<32>

    skip
    out_a <= in_a[sel]
    out_b <= in_b[sel]

とりあえず変換はできるようになった。問題は、in_a[sel]が正しく変数に分解できていないということだ。これを処理するためにまだResolveKindsでエラーが発生している。

Exception in thread "main" firrtl.FirrtlInternalException: Internal Error! Please file an issue at https://github.com/ucb-bar/firrtl/issues
        at firrtl.Utils$.error(Utils.scala:423)
        at firrtl.Utils$.throwInternalError(Utils.scala:164)
        at firrtl.stage.FirrtlStage.run(FirrtlStage.scala:35)
        at firrtl.options.Stage$$anon$1.transform(Stage.scala:43)
        at firrtl.options.Stage$$anon$1.transform(Stage.scala:43)
...
        at firrtl.stage.FirrtlMain.main(FirrtlStage.scala)
Caused by: java.util.NoSuchElementException: key not found: in_a[sel]
        at scala.collection.MapLike.default(MapLike.scala:235)
...