FPGA開発日記

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

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

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

前回、多次元配列をそのままChiselで扱うためにはどうすればよいか考えたが、さらにまだ考えないといけないことがある。さらに、以下のような構文について考えた。

circuit VecBundle2 :
  module VecBundle2 :
    input in: { a : { b : UInt<8>[2] } [3] }[4]
    input sel: UInt<2>
    output out : { b : UInt<8>[2] }
    out.b <= in[0].a[1].b

BundleTypeが多重構造になっているタイプだ。さらに、配列で覆いかぶせている。今回はとりあえずWSubIndexで固定値のインデックスを取っている。これを扱うためには、最終的に以下のようになってほしい。

circuit VecBundle2 :
  module VecBundle2 :
    input in_a_b : UInt<8>[2][3][4]
    input sel : UInt<2>
    output out_b : UInt<8>[2]

    out_b <= in_a_b[0][1]

このような、in[0].a[1].bをどのように変換するかという問題だが、これはSubFieldが登場するたびにそのメンバ変数の名前を覚えておき、それを順繰りに並べてin_a_b[0][1]とすれば良い。まあこれを作るのにもかなり苦労したけど。

  def lowerTypesExp(memDataTypeMap: MemDataTypeMap,
    info: Info, mname: String, subfield_name: String = "")(e: Expression): Expression = {
    e match {
      case e: WRef => e.copy(name = subfield_name)
...
      case e: WSubField => {
        kind(e) match {
          case InstanceKind =>
...
          case _ => {
            val new_subfield_name = subfield_name match {
              case "" => e.name
              case x => e.name + x
            }
            val exps = lowerTypesExp(memDataTypeMap, info, mname, new_subfield_name)(e.expr)
            exps match {
              case ex: WSubAccess => WSubAccess(WRef(loweredExpName(e), e.tpe, kind(e), flow(e)), ex.index, ex.tpe, flow(ex))
              case ex: WSubIndex  => ex
...

new_subfield_nameという変数を新たに定義した。これはSubFieldの名前が来るたびに順繰りに文字列として繋げていく。最終的には_a_bという文字列を作り、WRefの参照が来たときに、

      case e: WRef => e.copy(name = subfield_name)

で名前を更新する。そしてWSubIndexのときに変数名の最初にため込んだ値を埋め込む、という訳だ。

  def lowerTypesExp(memDataTypeMap: MemDataTypeMap,
...
      case (e: WSubIndex) => kind(e) match {
...
        case _ => {
          val exps = lowerTypesExp(memDataTypeMap, info, mname, subfield_name)(e.expr)
          exps match {
            case ex: WSubAccess => WSubIndex(WSubAccess(WRef(loweredExpName(e), e.tpe, kind(e), flow(e)), ex.index, ex.tpe, flow(ex)), e.value, e.tpe, flow(e))
            case ex: WSubIndex  => WSubIndex(WSubIndex(WRef(loweredExpName(e) + "_" + subfield_name, e.tpe, kind(e), flow(e)), ex.value, ex.tpe, flow(ex)), e.value, e.tpe, flow(e))

これで上記の回路の変換を試行した。

circuit VecBundle2 :
  module VecBundle2 :
    input in_a_b : UInt<8>[2][3][4]
    input sel : UInt<2>
    output out_b : UInt<8>[2]

    out_b <= in_a_b[0][1]

一応想定通りの形にはなったようだ。