FPGA開発日記

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

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

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

前回までの多次元構造体の処理を見直して、もう少し簡単になるんじゃないかということで作り直した。基本的な考え方は以下の通りだ。

  • 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つのテストをコンパイルする。WSubIndexWSubAccessを使うケースだ。どちらも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]

上手くできた。この配列分解の検討は、とりあえずここまでかな。