CIRCTは、FIRのファイルを受け取りMLIRの構造に変換し、それをVerilogに変換する構造になっている。このFIRParserを理解し、MLIRについての理解を深めるためには自分で別のPassを作りそこに同じような実装を加えてみるのがいいだろう。そこで、まずは既存のFIRParserをそのままコピーしてSimpleFIRParserを作り、これをcirct-translateに埋め込んでみる。
FIRParserの実装はcirct/lib/FIRParserに実装されている。
CMakeLists.txt FIRLexer.cpp FIRLexer.h FIRParser.cpp FIRTokenKinds.def
これをまるっとコピーしてSimpleFIRParserのディレクトリを作成し、FIRParser、FIRLexerをすべてSimpleFIRParser、SimpleFIRLexerに変更する。
さらにPassをレジストレーションする部分を少し書き換えて、オプションとして--parse-simplefirを有効にする。
circt/lib/SimpleFIRParser/SimpleFIRParser.cpp
void circt::registerSimpleFIRParserTranslation() { static TranslateToMLIRRegistration fromFIR( "parse-simplefir", [](llvm::SourceMgr &sourceMgr, MLIRContext *context) { return parseFIRFile(sourceMgr, context); }); }
さらにこのregisterSimpleFIRParserTranslation()をcirct-translate.cppに追加した。
circt/tools/circt-translate/circt-translate.cpp
int main(int argc, char **argv) { // Register MLIR stuff. registerAsmPrinterCLOptions(); registerMLIRContextCLOptions(); registerDialect<StandardOpsDialect>(); // RTL. registerDialect<rtl::RTLDialect>(); // Register FIRRTL stuff. registerDialect<firrtl::FIRRTLDialect>(); registerFIRParserTranslation(); registerVerilogEmitterTranslation(); // これを追加した。 registerSimpleFIRParserTranslation(); // LLHD ...
これでCIRCTをコンパイルしてみる。
$ ninja check-circt
これにより新しいPassが認識され、オプションが追加されていることが分かる。
$ ./bin/circit-translate
OVERVIEW: CIRCT translation driver
...
--mlir-print-stacktrace-on-diagnostic - When a diagnostic is emitted, also print the stack trace as an attached note
-o=<filename> - Output filename
Translation to perform
--emit-verilog - emit-verilog
--llhd-to-verilog - llhd-to-verilog
--parse-fir - parse-fir
--parse-simplefir - parse-simplefir // これが追加された。
--split-input-file - Split the input file into pieces and process each chunk independently
--verify-diagnostics - Check that emitted diagnostics match expected-* lines on the corresponding line