"CIRCT"は"Circuit IR Compiler and Tools"の略称で、MLIRを用いた回路構成を生成するコンパイラツールである。
ソースコードが構成されており、面白そうなのでダウンロードしてビルドしてみることにした。
まずはソースコードのダウンロードを行う。
$ cd ${HOME}/work/llvm/circt $ git clone git@github.com:circt/circt.git $ git submodule init $ git submodule update
LLVM/MLIRモジュールのビルドを行う。
$ cd circt $ mkdir llvm/build $ cd llvm/build $ cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="mlir" -DLLVM_TARGETS_TO_BUILD="X86;RISCV" \ -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=DEBUG $ ninja $ ninja check-mlir
CIRCTのビルドを行う。
$ mkdir circt/build $ cd circt/build $ cmake -G Ninja .. -DMLIR_DIR=${HOME}/work/llvm/circt/llvm/build/lib/cmake/mlir/ \ -DLLVM_DIR=${HOME}/work/llvm/circt/llvm/build/lib/cmake/llvm \ -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=DEBUG $ ninja $ ninja check-circt
すでに限定的ではあるが、FIRRTLをParseしてVerilogを生成することができる。試してみよう。
$ cd bin/test/EmitVerilog/Output
ls -1 verilog-basic.fir.script verilog-errors.mlir.script verilog-rtl-dialect.mlir.script verilog-weird.mlir.script
いくつかのFIRファイルが配置している。verilog-basic.fir.script
がFIRをコンパイルするためのスクリプトになっている。
set -o pipefail;{ : 'RUN: at line 1'; /home/msyksphinz/work/llvm/circt/build/bin/circt-translate -parse-fir --mlir-print-debuginfo /home/msyksphinz/work/llvm/circt/test/EmitVerilog/verilog-basic.fir | /home/msyksphinz/work/llvm/circt/build/bin/circt-translate -emit-verilog -verify-diagnostics | /home/msyksphinz/work/llvm/circt/llvm/build/bin/FileCheck /home/msyksphinz/work/llvm/circt/test/EmitVerilog/verilog-basic.fir --strict-whitespace; }
これに基づいて、自分でもCIRCTを動かしてみよう。
$ ${BUILD}/bin/circt-translate -parse-fir --mlir-print-debuginfo \ ${CIRCT}/test/EmitVerilog/verilog-basic.fir | \ ${BUILD}/bin/circt-translate -emit-verilog -verify-diagnostics
おお、Verilogファイルが生成できた。しかも超絶速い。FIRRTLなど話にならないほど高速だ。
... always @(posedge _M_write_clk) begin if (_M_write_en & _M_write_mask) begin _M_id[_M_write_addr] <= _M_write_data_id; // Decoupled.scala:209:24 _M_other[_M_write_addr] <= _M_write_data_other; // Decoupled.scala:209:24 end end // always @(posedge) endmodule module Attach( input a, b, c); `ifndef SYNTHESIS alias a = b = c; // Place.scala:101 `endif `ifdef SYNTHESIS assign a = b; // Place.scala:101 assign a = c; // Place.scala:101 assign b = a; // Place.scala:101 assign b = c; // Place.scala:101 assign c = a; // Place.scala:101 assign c = b; // Place.scala:101 `endif // SYNTHESIS endmodule module IsInvalid( output a); endmodule module Locations( input [3:0] a, output [3:0] b); ...