FPGA開発日記

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

FIRRTLに入門する (4. FIRRTLの.firファイルの読み取り方法)

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

FIRRTLは入力ファイルとして.firファイルを指定することができる。ということは、FIRファイルのファイルを読み込んで、Parseして、構文解析木を生成する場所があるはずである。それを調査した。

どうやらFIRRTLのコマンドラインを立ち上げたときは、FirrtlCli.scalaFirrtlCliトレイトが含まれるようで、こちらにFIRファイルをオープンする記述が含まれているようだ。

  • firrtl/stage/FirrtlCli.scala
trait FirrtlCli { this: Shell =>
  parser.note("FIRRTL Compiler Options")
  Seq( FirrtlFileAnnotation,
       OutputFileAnnotation,
       InfoModeAnnotation,
       FirrtlSourceAnnotation,  // FIRファイルを読み込むためのアノテーション
       CompilerAnnotation,
       RunFirrtlTransformAnnotation,
       firrtl.EmitCircuitAnnotation,
       firrtl.EmitAllModulesAnnotation )
    .map(_.addOptions(parser))

  phases.DriverCompatibility.TopNameAnnotation.addOptions(parser)
  phases.DriverCompatibility.EmitOneFilePerModuleAnnotation.addOptions(parser)
}

FirrtlSourceAnnotationを開いてみると、ファイルをオープンして、ANTLR構文解析木に渡すようだった。

  • firrtl/stage/FirrtlAnnotations.scala
object FirrtlSourceAnnotation extends HasShellOptions {

  val options = Seq(
    new ShellOption[String](
      longOption      = "firrtl-source",
      toAnnotationSeq = a => Seq(FirrtlSourceAnnotation(a)),
      helpText        = "An input FIRRTL circuit string",
      shortOption     = Some("<string>") ) )

}
/** Holds a [[scala.Predef.String String]] containing FIRRTL source to read as input
  *  - set with `--firrtl-source`
  * @param value FIRRTL source as a [[scala.Predef.String String]]
  */
case class FirrtlSourceAnnotation(source: String) extends NoTargetAnnotation with CircuitOption {

  def toCircuit(info: Parser.InfoMode): FirrtlCircuitAnnotation =
    FirrtlCircuitAnnotation(Parser.parseString(source, info))

}
  • firrtl/Parser.scala
  /** Parses a org.antlr.v4.runtime.CharStream and returns a parsed [[firrtl.ir.Circuit Circuit]] */
  def parseCharStream(charStream: CharStream, infoMode: InfoMode): Circuit = {
    val (parseTimeMillis, cst) = time {
      val parser = {
        val lexer = new FIRRTLLexer(charStream)
        val parser = new FIRRTLParser(new CommonTokenStream(lexer))
        parser
      }