MLIRの勉強のために、CIRCTにSystemVerilogの新しいツールを追加してみよう。やり方が分からないので試行錯誤でやってみる。FIRRTLのディレクトリを参考にしながら以下のようにファイルを追加してみる。
Dialect/SV/Import CMakeLists.txt SVAnnotations.cpp SVLexer.cpp SVLexer.h SVParser.cpp SVTokenKinds.def circt/Dialect/SV/SVAnnotations.h circt/Dialect/SV/SVParser.h tools/CMakeLists.txt sv-translate/ CMakeLists.txt sv-translate.cpp
基本的にすべてFIRRTLの実装からコピーしてきている。sv-translate
というツールを使ってみることにする。
diff --git a/lib/Dialect/SV/CMakeLists.txt b/lib/Dialect/SV/CMakeLists.txt index c9d7fe6d..d213a1f8 100644 --- a/lib/Dialect/SV/CMakeLists.txt +++ b/lib/Dialect/SV/CMakeLists.txt @@ -20,4 +20,5 @@ add_circt_dialect_library(CIRCTSV add_dependencies(circt-headers MLIRSVIncGen) add_subdirectory(Analyses) +add_subdirectory(Import) add_subdirectory(Transforms)
この状態でCIRCTのビルドを行ってみるとどうなるか。以下のようなエラーが表示された。
../lib/Dialect/SV/Import/SVParser.cpp:249:25: error: 'SVType' has not been declared ParseResult parseType(SVType &result, const Twine &message); ^~~~~~ ../lib/Dialect/SV/Import/SVParser.cpp:251:32: error: 'RUWAttr' has not been declared ParseResult parseOptionalRUW(RUWAttr &result); ^~~~~~~ ../lib/Dialect/SV/Import/SVParser.cpp:679:33: error: 'mlir::ParseResult {anonymous}::SVParser::parseType' is not a static data member of 'struct {anonymous}::SVParser' ParseResult SVParser::parseType(SVType &result, const Twine &message) { ^~~~~~ ../lib/Dialect/SV/Import/SVParser.cpp:679:33: error: 'SVType' was not declared in this scope ../lib/Dialect/SV/Import/SVParser.cpp:679:33: note: suggested alternative: 'wctype' ParseResult SVParser::parseType(SVType &result, const Twine &message) { ^~~~~~ wctype
適当にコンバートしたが、SVType
という型を作成しなければならないらしい。これはもともとFIRRTLType
だったので、これはどのように生成されているのか。
lib/Dialect/FIRRTL/Import/FIRParser.cpp
ParseResult parseType(FIRRTLType &result, const Twine &message);
と思ったら普通にヘッダファイルで定義されていた。
include/circt/Dialect/FIRRTL/FIRRTLTypes.h
// This is a common base class for all FIRRTL types. class FIRRTLType : public Type { public: void print(raw_ostream &os) const; /// Return true if this is a "passive" type - one that contains no "flip" /// types recursively within itself. bool isPassive() { return getRecursiveTypeProperties().first; } /// Return true if this is a 'ground' type, aka a non-aggregate type. bool isGround(); /// Return true if this is or contains an Analog type. bool containsAnalog() { return getRecursiveTypeProperties().second; } /// Return a pair with the 'isPassive' and 'containsAnalog' bits. std::pair<bool, bool> getRecursiveTypeProperties(); /// Return this type with any flip types recursively removed from itself. FIRRTLType getPassiveType(); /// Return this type with all ground types replaced with UInt<1>. This is /// used for `mem` operations. FIRRTLType getMaskType(); /// Return this type with widths of all ground types removed. This /// enables two types to be compared by structure and name ignoring /// widths. FIRRTLType getWidthlessType(); /// If this is an IntType, AnalogType, or sugar type for a single bit (Clock, /// Reset, etc) then return the bitwidth. Return -1 if the is one of these /// types but without a specified bitwidth. Return -2 if this isn't a simple /// type. int32_t getBitWidthOrSentinel(); /// Support method to enable LLVM-style type casting. static bool classof(Type type) { return llvm::isa<FIRRTLDialect>(type.getDialect()); } /// Return true if this is a valid "reset" type. bool isResetType(); protected: using Type::Type; };
そこでSVType
を以下のように定義した。
+// This is a common base class for all SV types. +class SVType : public Type { +public: + void print(raw_ostream &os) const; + + /// Return true if this is a "passive" type - one that contains no "flip" + /// types recursively within itself. + bool isPassive() { return getRecursiveTypeProperties().first; } + + /// Return true if this is a 'ground' type, aka a non-aggregate type. + bool isGround(); + + /// Return true if this is or contains an Analog type. ...
さらに、FIRRTLのRUWAttr
は以下で定義されていた。
circt/Dialect/FIRRTL/FIRRTLTypes.td
/// RUWAttr: Undefined/Old/New. def RUW_Undefined: I32EnumAttrCase<"Undefined", 0>; def RUW_Old: I32EnumAttrCase<"Old", 1>; def RUW_New: I32EnumAttrCase<"New", 2>; def RUWAttr: I32EnumAttr<"RUWAttr", "Read Under Write Enum", [RUW_Undefined, RUW_Old, RUW_New]>;
このI32EnumAttr
とかI32EnumAttrCase
はこの辺かな?
https://mlir.llvm.org/docs/OpDefinitions/
これは列挙型なのか。
https://mlir.llvm.org/docs/OpDefinitions/#enum-attributes
- A read-under-write flag indicating the behaviour when a memory location is written to while a read to that location is in progress.