FPGA開発日記

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

FIRRTLに入門する (5. ANTLR4 用のFIRRTL.g4を使ってC++の簡易パーサを作ってみる)

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

FIRRTLのパーサがANTLRで作られていることが分かったので、これを使えば遊べるような気がしてきた。C++向けにFIRRTLの文法ファイルを変換して、C++で簡易パーサを作って遊んでみる。

まず、ANTLR4のランタイムをダウンロードした。C++用のANTLRランタイムをダウンロードしてコンパイルしておく。s

https://www.antlr.org/download.html

mkdir runtime
cd runtime
wget https://www.antlr.org/download/antlr4-cpp-runtime-4.7.2-source.zip
unzip antlr4-cpp-runtime-4.7.2-source.zip
cd runtime
cmake .
make -j8

FIRRTLのFIRRTL.g4の配置してあるディレクトリに移動し、ANTRLでC++用のクラスファイルを生成した。

antlr4 -Dlanguage=Cpp FIRRTL.g4

生成したFIRRTLParser.cpp, FIRRTLLexer.cppを呼び出すためのラッパーであるmain.cppを作っておく。

  • main.cpp
#include <iostream>

#include "antlr4-runtime.h"
#include "FIRRTLLexer.h"
#include "FIRRTLParser.h"
#include "FIRRTLBaseListener.h"

using namespace antlr4;

int main(int argc, const char* argv[]) {
  std::ifstream stream;
  stream.open(argv[1]);
  ANTLRInputStream input(stream);
  FIRRTLLexer lexer(&input);
  CommonTokenStream tokens(&lexer);
  FIRRTLParser parser(&tokens);

  FIRRTLParser::CircuitContext* tree = parser.circuit();

  std::cout << tree->toStringTree(&parser);
  return 0;
}

ランタイムライブラリと、main.cppと、FIRRTLParser.cpp, FIRRTLLexer.cppをまとめてコンパイルして実行ファイルを作成する。

g++ -o firrtl_cpp *.cpp -I./runtime/runtime/src runtime/dist/libantlr4-runtime.a

完成したので、以下の簡単なFIRファイルを読ませて解析させる。

  • simple_circuit.fir
circuit SimpleCircuit :
  module SimpleCircuit :
    output io : {flip in : UInt<32>, out : UInt<32>}

    io.out <= io.in
./firrtl_cpp simple_test.fir
line 1:23 mismatched input '\n  ' expecting {FileInfo, INDENT}
(circuit circuit (id SimpleCircuit) : \n   module SimpleCircuit : \n     output io : { flip in : UInt < 32 > out : UInt < 32 > } \n \n     io . out <= io . in \n)

何となく構文解析した結果がダンプできているような気がする。でも、最初のmismatched inputが良く分からないし、もう少し改造して綺麗に表示できないものかね。とりあえずFIRファイルを構文解析できたので良しとする。