FPGA開発日記

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

FIRRTLに入門する (14. Bundleの改造と配列の解析)

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

FIRRTLの解析に際し、BundleTypeとVecTypeの解析を行っている。LowerType()の中で、どのように変換されているのか解析をする。

以下の3つのコードを用意した。

circuit VecModules :
  module VecModules :
    input in: UInt<32>[4]
    input sel: UInt<2>
    output out : UInt<32>
    out <= in[sel]
circuit BundleUInt :
  module BundleUInt :
    input in: { a: UInt<32>, b: UInt<32> }
    input sel: UInt<1>
    output out : UInt<32>
    out <= mux(sel, in.a, in.b)
circuit VecModules :
  module VecModules :
    input in: { a: UInt<32> }[4]
    input sel: UInt<2>
    output out : UInt<32>
    out <= in[sel].a

LowerTypeの時に、すべての配列型、Bundle型を分解されてしまう。これが具体的にどうなっているかを解析した。

  • firrtl/passes/LowerTypes.scala
  def lowerTypes(renames: RenameMap)(m: DefModule): DefModule = {
    val memDataTypeMap = new MemDataTypeMap
    renames.setModule(m.name)
    // Lower Ports
    val portsx = m.ports flatMap { p =>
...
    println(s"lowerTypes() p = ${p}")
    println(s"exps = ${exps}")
    println(s"names = ${names}")

まず、UIntだけを含む単純なVecModuleだが、

exps = Vector(WSubIndex(
                WRef(in,VectorType(UIntType(IntWidth(32)),4),PortKind,SourceFlow),
                0,
                UIntType(IntWidth(32)),SourceFlow),
              WSubIndex(
                WRef(in,VectorType(UIntType(IntWidth(32)),4),PortKind,SourceFlow),
                1,
                UIntType(IntWidth(32)),SourceFlow),
              WSubIndex(
                WRef(in,VectorType(UIntType(IntWidth(32)),4),PortKind,SourceFlow),
                2,
                UIntType(IntWidth(32)),SourceFlow),
              WSubIndex(
                WRef(in,VectorType(UIntType(IntWidth(32)),4),PortKind,SourceFlow),
                3,
                UIntType(IntWidth(32)),SourceFlow)
             )
  • VectorTypeは4つ分のExpsに分解される。それぞれは、WSubIndexというオブジェクトに変換される。

  • WSubIndexは、

    1. Vecの型の情報
    2. インデックス
    3. Vecの内部の型の情報

    から構成される。

つぎに、BundleIntだが、

exps = ArrayBuffer(WSubField(
                     WRef(
                       in,
                       BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))),
                                              Field(B,Default,UIntType(IntWidth(32))))),
                       PortKind,
                       SourceFlow),
                     A,
                     UIntType(IntWidth(32)),
                     SourceFlow),
                   WSubField(
                     WRef(
                       in,
                       BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))),
                                              Field(B,Default,UIntType(IntWidth(32))))),
                       PortKind,
                       SourceFlow),
                     B,
                     UIntType(IntWidth(32)),
                     SourceFlow)
                   )
  • 各フィールドは、WSubFieldに分解される。各SubFieldは、

    • WRefによりBundleTypeの型自体の情報
    • フィールドの名前
    • BundleTypeの内部の型の情報

つぎにVecBundleBundleTypeVectorTypeの融合なので、これが組み合わさっているだけだ。

exps = Vector(WSubField(
                WSubIndex(
                  WRef(in,VectorType(BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),4),PortKind,SourceFlow),
                  0,
                  BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),SourceFlow),
                A,
                UIntType(IntWidth(32)),
                SourceFlow),
              WSubField(
                WSubIndex(
                  WRef(in,VectorType(BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),4),PortKind,SourceFlow),
                  1,
                  BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),SourceFlow),
                A,
                UIntType(IntWidth(32)),
                SourceFlow),
              WSubField(
                WSubIndex(
                  WRef(in,VectorType(BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),4),PortKind,SourceFlow),
                  2,
                  BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),SourceFlow),
                A,
                UIntType(IntWidth(32)),
                SourceFlow),
              WSubField(
                WSubIndex(
                  WRef(in,VectorType(BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),4),PortKind,SourceFlow),
                  3,
                  BundleType(ArrayBuffer(Field(A,Default,UIntType(IntWidth(32))))),SourceFlow),
                A,
                UIntType(IntWidth(32)),
                SourceFlow)
              )