diff --git a/include/circt/Dialect/BLIF/BLIFOps.td b/include/circt/Dialect/BLIF/BLIFOps.td index 90dfb08aa2d4..9bdae21aaae6 100644 --- a/include/circt/Dialect/BLIF/BLIFOps.td +++ b/include/circt/Dialect/BLIF/BLIFOps.td @@ -24,10 +24,19 @@ def ModelOp : BLIFOp<"model", [IsolatedFromAbove, RegionKindInterface, SingleBlo }]; let arguments = (ins SymbolNameAttr:$sym_name, - TypeAttrOf:$module_type); + TypeAttrOf:$module_type, + APIntAttr:$clocks); let results = (outs); let regions = (region SizedRegion<1>:$body); + let builders = [ + OpBuilder<(ins "StringRef":$name, + "ArrayRef":$inputs, + "ArrayRef":$outputs, + "ArrayRef":$clocks)> + ]; + + let extraClassDeclaration = [{ static mlir::RegionKind getRegionKind(unsigned index) { return mlir::RegionKind::Graph; diff --git a/include/circt/InitAllDialects.h b/include/circt/InitAllDialects.h index 8e53c5fe211a..a6ed7eb8e23b 100644 --- a/include/circt/InitAllDialects.h +++ b/include/circt/InitAllDialects.h @@ -16,6 +16,7 @@ #include "circt/Dialect/AIG/AIGDialect.h" #include "circt/Dialect/Arc/ArcDialect.h" +#include "circt/Dialect/BLIF/BLIFDialect.h" #include "circt/Dialect/Calyx/CalyxDialect.h" #include "circt/Dialect/Comb/CombDialect.h" #include "circt/Dialect/DC/DCDialect.h" @@ -58,6 +59,7 @@ inline void registerAllDialects(mlir::DialectRegistry ®istry) { registry.insert< aig::AIGDialect, arc::ArcDialect, + blif::BLIFDialect, calyx::CalyxDialect, chirrtl::CHIRRTLDialect, comb::CombDialect, diff --git a/lib/Dialect/BLIF/BLIFOps.cpp b/lib/Dialect/BLIF/BLIFOps.cpp index aa462fc9a403..f4c02746cb70 100644 --- a/lib/Dialect/BLIF/BLIFOps.cpp +++ b/lib/Dialect/BLIF/BLIFOps.cpp @@ -17,6 +17,41 @@ using namespace circt; using namespace blif; +void ModelOp::build(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, + StringRef name, ArrayRef inputs, + ArrayRef outputs, ArrayRef clocks) { + SmallVector modulePorts; + auto I1 = odsBuilder.getIntegerType(1); + auto uLoc = odsBuilder.getUnknownLoc(); + auto *r = odsState.addRegion(); + Block *b = new Block(); + r->push_back(b); + + for (auto input : inputs) { + modulePorts.push_back( + {odsBuilder.getStringAttr(input), I1, hw::ModulePort::Input}); + b->addArgument(I1, uLoc); + } + for (auto output : outputs) + modulePorts.push_back( + {odsBuilder.getStringAttr(output), I1, hw::ModulePort::Output}); + for (auto clock : clocks) { + modulePorts.push_back( + {odsBuilder.getStringAttr(clock), I1, hw::ModulePort::Input}); + b->addArgument(I1, uLoc); + } + auto moduleType = hw::ModuleType::get(odsBuilder.getContext(), modulePorts); + APInt clockVec(inputs.size() + outputs.size() + clocks.size(), 0); + for (size_t i = inputs.size() + outputs.size(); + i < inputs.size() + outputs.size() + clocks.size(); i++) + clockVec.setBit(i); + auto clockAttr = odsBuilder.getIntegerAttr( + odsBuilder.getIntegerType(clockVec.getBitWidth()), clockVec); + odsState.addAttribute("sym_name", odsBuilder.getStringAttr(name)); + odsState.addAttribute("module_type", TypeAttr::get(moduleType)); + odsState.addAttribute("clocks", clockAttr); +} + namespace mlir { LogicalResult convertFromAttribute(SmallVectorImpl &storage, Attribute attr, diff --git a/lib/Dialect/BLIF/Import/BLIFLexer.cpp b/lib/Dialect/BLIF/Import/BLIFLexer.cpp index 99f0ea108bb0..f215bb6b1669 100644 --- a/lib/Dialect/BLIF/Import/BLIFLexer.cpp +++ b/lib/Dialect/BLIF/Import/BLIFLexer.cpp @@ -214,13 +214,8 @@ BLIFToken BLIFLexer::lexTokenImpl() { // Handle whitespace. continue; - case '`': - case '_': - // Handle identifiers. - return lexIdentifierOrKeyword(tokStart); - case '.': - return formToken(BLIFToken::period, tokStart); + return lexPeriodOrKeyword(tokStart); case ',': return formToken(BLIFToken::comma, tokStart); case ':': @@ -262,7 +257,7 @@ BLIFToken BLIFLexer::lexTokenImpl() { // Unknown character, emit an error. return emitError(tokStart, "unexpected character"); - case ';': + case '#': skipComment(); continue; @@ -319,6 +314,33 @@ BLIFToken BLIFLexer::lexFileInfo(const char *tokStart) { } } +/// Lex a period or a keyword that starts with a period. +/// +/// Period ::= '.' +/// +BLIFToken BLIFLexer::lexPeriodOrKeyword(const char *tokStart) { + + // Match the rest of the identifier regex: [a-zA-Z_$-]* + while (llvm::isAlpha(*curPtr) || llvm::isDigit(*curPtr) || *curPtr == '_' || + *curPtr == '$' || *curPtr == '-') + ++curPtr; + + StringRef spelling(tokStart, curPtr - tokStart); + + // See if the identifier is a keyword. By default, it is a period. + BLIFToken::Kind kind = llvm::StringSwitch(spelling) +#define TOK_KEYWORD_DOT(SPELLING) .Case("." #SPELLING, BLIFToken::kw_##SPELLING) +#include "BLIFTokenKinds.def" + .Default(BLIFToken::period); + if (kind != BLIFToken::period) { + ++curPtr; + return formToken(kind, tokStart); + } + + // Otherwise, this is a period. + return formToken(BLIFToken::period, tokStart); +} + /// Lex an identifier or keyword that starts with a letter. /// /// LegalStartChar ::= [a-zA-Z_] diff --git a/lib/Dialect/BLIF/Import/BLIFLexer.h b/lib/Dialect/BLIF/Import/BLIFLexer.h index ec82969c9b09..10dd159b67cd 100644 --- a/lib/Dialect/BLIF/Import/BLIFLexer.h +++ b/lib/Dialect/BLIF/Import/BLIFLexer.h @@ -69,7 +69,7 @@ class BLIFToken { bool isKeyword() const; bool isModelHeaderKeyword() const { - return true; // isAny(kw_inputs, kw_outputs, kw_names, kw_latch, kw_end); + return isAny(kw_inputs, kw_outputs, kw_clock); } /// Given a token containing a string literal, return its value, including @@ -134,6 +134,7 @@ class BLIFLexer { BLIFToken lexNumber(const char *tokStart); void skipComment(); BLIFToken lexString(const char *tokStart, bool isVerbatim); + BLIFToken lexPeriodOrKeyword(const char *tokStart); const llvm::SourceMgr &sourceMgr; const mlir::StringAttr bufferNameIdentifier; diff --git a/lib/Dialect/BLIF/Import/BLIFParser.cpp b/lib/Dialect/BLIF/Import/BLIFParser.cpp index 823d0e3f882e..03411272b6b7 100644 --- a/lib/Dialect/BLIF/Import/BLIFParser.cpp +++ b/lib/Dialect/BLIF/Import/BLIFParser.cpp @@ -239,28 +239,27 @@ ParseResult BLIFParser::parseId(StringAttr &result, const Twine &message) { return success(); } - ParseResult BLIFParser::parseIdList(SmallVectorImpl &result, - const Twine &message, unsigned minCount) { - while(true) { - switch (getToken().getKind()) { - // The most common case is an identifier. - case BLIFToken::identifier: - result.push_back(getTokenSpelling()); - consumeToken(); - if (minCount) +ParseResult BLIFParser::parseIdList(SmallVectorImpl &result, + const Twine &message, unsigned minCount) { + while (true) { + switch (getToken().getKind()) { + // The most common case is an identifier. + case BLIFToken::identifier: + result.push_back(getTokenSpelling()); + consumeToken(); + if (minCount) --minCount; - break; - default: - if (minCount) { - emitError(message); - return failure(); + break; + default: + if (minCount) { + emitError(message); + return failure(); + } + return success(); } - return success(); - } } } - //===----------------------------------------------------------------------===// // BLIFModelParser //===----------------------------------------------------------------------===// @@ -418,7 +417,10 @@ namespace { /// This class implements the parser, namely models struct BLIFFileParser : public BLIFParser { explicit BLIFFileParser(BLIFLexer &lexer, ModuleOp mlirModule) - : BLIFParser(mlirModule.getContext(), lexer), mlirModule(mlirModule) {} + : BLIFParser(mlirModule.getContext(), lexer), mlirModule(mlirModule), + builder(UnknownLoc::get(getContext()), getContext()) { + builder.setInsertionPointToStart(mlirModule.getBody()); + } ParseResult parseFile(); @@ -426,6 +428,7 @@ struct BLIFFileParser : public BLIFParser { ParseResult parseModel(); ModuleOp mlirModule; + ImplicitLocOpBuilder builder; }; } // end anonymous namespace @@ -442,22 +445,29 @@ ParseResult BLIFFileParser::parseModel() { while (getToken().isModelHeaderKeyword()) { switch (getToken().getKind()) { case BLIFToken::kw_inputs: + consumeToken(BLIFToken::kw_inputs); if (parseIdList(inputs, "expected input list", 1)) return failure(); break; case BLIFToken::kw_outputs: + consumeToken(BLIFToken::kw_outputs); if (parseIdList(outputs, "expected output list", 1)) return failure(); break; case BLIFToken::kw_clock: + consumeToken(BLIFToken::kw_clock); if (parseIdList(clocks, "expected clock list", 1)) return failure(); break; default: - return emitError("unexpected token in model header"); + break; } } // Create the model + auto m = builder.create(name, inputs, outputs, clocks); + OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPointToEnd(&m.getBody().back()); + builder.create(ValueRange()); if (/*parseModelBody() ||*/ parseToken(BLIFToken::kw_end, "expected .end")) return failure(); diff --git a/lib/Dialect/BLIF/Import/BLIFTokenKinds.def b/lib/Dialect/BLIF/Import/BLIFTokenKinds.def index 2a797a2e37ac..3179b522333f 100644 --- a/lib/Dialect/BLIF/Import/BLIFTokenKinds.def +++ b/lib/Dialect/BLIF/Import/BLIFTokenKinds.def @@ -14,7 +14,7 @@ #if !defined(TOK_MARKER) && !defined(TOK_IDENTIFIER) && \ !defined(TOK_LITERAL) && !defined(TOK_PUNCTUATION) && \ !defined(TOK_KEYWORD) && !defined(TOK_LPKEYWORD) && \ - !defined(TOK_LPKEYWORD_PRIM) + !defined(TOK_KEYWORD_DOT) #error Must define one of the TOK_ macros. #endif diff --git a/test/Dialect/BLIF/parse-basic.blif b/test/Dialect/BLIF/parse-basic.blif index 10ba2ad8b81f..1de0b6f84f9b 100644 --- a/test/Dialect/BLIF/parse-basic.blif +++ b/test/Dialect/BLIF/parse-basic.blif @@ -1,13 +1,13 @@ -; RUN: circt-translate -import-blif -verify-diagnostics -split-input-file %s | circt-opt | FileCheck %s +# RUN: circt-translate -import-blif -verify-diagnostics -split-input-file %s | circt-opt | FileCheck %s .model simple .inputs a B .outputs c -.names a b c -11 1 +#.names a b c +#11 1 .end -;// ----- +#// ----- # unamed model .names a b \