20#include "mlir/IR/Builders.h"
21#include "mlir/IR/BuiltinOps.h"
22#include "mlir/IR/Diagnostics.h"
23#include "mlir/IR/Location.h"
24#include "mlir/IR/MLIRContext.h"
25#include "mlir/Support/FileUtilities.h"
26#include "mlir/Support/LogicalResult.h"
27#include "mlir/Support/Timing.h"
28#include "mlir/Tools/mlir-translate/Translation.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/StringExtras.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/LEB128.h"
35#include "llvm/Support/SMLoc.h"
36#include "llvm/Support/SourceMgr.h"
37#include "llvm/Support/raw_ostream.h"
50#define DEBUG_TYPE "import-aiger"
55enum class AIGERTokenKind {
74 AIGERToken(AIGERTokenKind kind, StringRef spelling, SMLoc location)
75 : kind(kind), spelling(spelling), location(location) {}
85 AIGERLexer(
const llvm::SourceMgr &sourceMgr, MLIRContext *
context)
86 : sourceMgr(sourceMgr),
89 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID())->getBuffer()),
90 curPtr(curBuffer.begin()) {}
93 AIGERToken nextToken();
96 AIGERToken lexAsSymbol();
99 AIGERToken peekToken();
102 bool isAtEOF()
const {
return curPtr >= curBuffer.end(); }
105 ParseResult readLEB128(
unsigned &result);
108 SMLoc getCurrentLoc()
const {
return SMLoc::getFromPointer(curPtr); }
112 Location translateLocation(llvm::SMLoc loc) {
114 unsigned mainFileID = sourceMgr.getMainFileID();
115 auto lineAndColumn = sourceMgr.getLineAndColumn(loc, mainFileID);
116 return FileLineColLoc::get(bufferNameIdentifier, lineAndColumn.first,
117 lineAndColumn.second);
121 AIGERToken emitError(
const char *loc,
const Twine &message) {
122 mlir::emitError(translateLocation(SMLoc::getFromPointer(loc)), message);
123 return AIGERToken(AIGERTokenKind::Error, StringRef(loc, 1),
124 SMLoc::getFromPointer(loc));
128 const llvm::SourceMgr &sourceMgr;
129 StringAttr bufferNameIdentifier;
137 auto mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
138 StringRef bufferName = mainBuffer->getBufferIdentifier();
139 if (bufferName.empty())
140 bufferName =
"<unknown>";
141 return StringAttr::get(
context, bufferName);
145 void skipWhitespace();
148 void skipUntilNewline();
151 AIGERToken lexNumber();
154 AIGERToken lexIdentifier();
157 AIGERToken makeToken(AIGERTokenKind kind,
const char *start) {
158 return AIGERToken(kind, StringRef(start, curPtr - start),
159 SMLoc::getFromPointer(start));
174 AIGERParser(
const llvm::SourceMgr &sourceMgr, MLIRContext *context,
176 : lexer(sourceMgr, context), context(context), module(module),
177 options(options), builder(context) {}
184 MLIRContext *context;
190 unsigned maxVarIndex = 0;
191 unsigned numInputs = 0;
192 unsigned numLatches = 0;
193 unsigned numOutputs = 0;
194 unsigned numAnds = 0;
197 unsigned numConstraints = 0;
198 unsigned numJustice = 0;
199 unsigned numFairness = 0;
201 bool isBinaryFormat =
false;
205 enum SymbolKind :
unsigned {
214 DenseMap<std::pair<SymbolKind, unsigned>, StringAttr> symbolTable;
217 SmallVector<unsigned> inputLiterals;
218 SmallVector<std::tuple<unsigned, unsigned, SMLoc>>
220 SmallVector<std::pair<unsigned, SMLoc>> outputLiterals;
221 SmallVector<std::tuple<unsigned, unsigned, unsigned, SMLoc>>
223 SmallVector<std::pair<unsigned, SMLoc>> badStateLiterals;
224 SmallVector<std::pair<unsigned, SMLoc>> constraintLiterals;
225 SmallVector<std::pair<unsigned, SMLoc>> fairnessLiterals;
226 SmallVector<SmallVector<std::pair<unsigned, SMLoc>>>
230 ParseResult parseHeader();
233 ParseResult parseInputs();
236 ParseResult parseLatches();
239 ParseResult parseOutputs();
242 ParseResult parseAndGates();
245 ParseResult parseAndGatesASCII();
248 ParseResult parseAndGatesBinary();
251 ParseResult parseSymbolTable();
254 ParseResult parseComments();
257 ParseResult parseBadStates();
260 ParseResult parseConstraints();
263 ParseResult parseJustice();
266 ParseResult parseFairness();
274 Value getLiteralValue(
unsigned literal,
275 DenseMap<unsigned, Backedge> &backedges, Location loc);
278 ParseResult createModule();
280 InFlightDiagnostic emitError(llvm::SMLoc loc,
const Twine &message) {
281 return mlir::emitError(lexer.translateLocation(loc), message);
285 InFlightDiagnostic emitError(
const Twine &message) {
286 return emitError(lexer.getCurrentLoc(), message);
289 InFlightDiagnostic emitWarning(llvm::SMLoc loc,
const Twine &message) {
290 return mlir::emitWarning(lexer.translateLocation(loc), message);
294 InFlightDiagnostic emitWarning(
const Twine &message) {
295 return emitWarning(lexer.getCurrentLoc(), message);
299 ParseResult parseNumber(
unsigned &result, SMLoc *loc =
nullptr);
302 ParseResult parseOptionalNumber(
unsigned &result, SMLoc *loc =
nullptr);
307 parseLiteralSection(
unsigned count,
308 SmallVectorImpl<std::pair<unsigned, SMLoc>> &out,
309 StringRef sectionName);
312 ParseResult parseBinaryNumber(
unsigned &result);
315 ParseResult parseNewLine();
324void AIGERLexer::skipWhitespace() {
325 while (curPtr < curBuffer.end()) {
327 if (*curPtr ==
' ' || *curPtr ==
'\t' || *curPtr ==
'\r') {
334 if (*curPtr ==
'/' &&
335 (curPtr + 1 < curBuffer.end() && *(curPtr + 1) ==
'/')) {
343void AIGERLexer::skipUntilNewline() {
344 while (curPtr < curBuffer.end() && *curPtr !=
'\n')
346 if (curPtr < curBuffer.end() && *curPtr ==
'\n')
350AIGERToken AIGERLexer::lexNumber() {
351 const char *start = curPtr;
352 while (curPtr < curBuffer.end() && llvm::isDigit(*curPtr))
354 return makeToken(AIGERTokenKind::Number, start);
357AIGERToken AIGERLexer::lexIdentifier() {
358 const char *start = curPtr;
359 while (curPtr < curBuffer.end() && (llvm::isAlnum(*curPtr) || *curPtr ==
'_'))
362 StringRef spelling(start, curPtr - start);
363 AIGERTokenKind kind = AIGERTokenKind::Identifier;
365 return makeToken(kind, start);
368AIGERToken AIGERLexer::nextToken() {
371 auto impl = [
this]() {
372 if (curPtr >= curBuffer.end())
373 return makeToken(AIGERTokenKind::EndOfFile, curPtr);
375 const char *start = curPtr;
380 return makeToken(AIGERTokenKind::Newline, start);
384 llvm_unreachable(
"Whitespace should have been skipped");
385 return makeToken(AIGERTokenKind::Error, start);
387 if (llvm::isDigit(c)) {
391 if (llvm::isAlpha(c) || c ==
'_') {
393 return lexIdentifier();
395 assert((c !=
'/' || *curPtr !=
'/') &&
"// should have been skipped");
396 return makeToken(AIGERTokenKind::Error, start);
404AIGERToken AIGERLexer::lexAsSymbol() {
406 const char *start = curPtr;
407 while (curPtr < curBuffer.end() &&
408 (llvm::isPrint(*curPtr) && !llvm::isSpace(*curPtr)))
410 return makeToken(AIGERTokenKind::Identifier, start);
413AIGERToken AIGERLexer::peekToken() {
414 const char *savedPtr = curPtr;
415 AIGERToken token = nextToken();
420ParseResult AIGERLexer::readLEB128(
unsigned &result) {
423 llvm::decodeULEB128(
reinterpret_cast<const uint8_t *
>(curPtr), &len,
424 reinterpret_cast<const uint8_t *
>(curBuffer.end()));
425 if (len == 0 || value > std::numeric_limits<unsigned>::max())
428 result =
static_cast<unsigned>(value);
436ParseResult AIGERParser::parse() {
437 if (parseHeader() || parseInputs() || parseLatches() || parseOutputs() ||
438 parseBadStates() || parseConstraints() || parseJustice() ||
439 parseFairness() || parseAndGates() || parseSymbolTable() ||
443 return createModule();
446ParseResult AIGERParser::parseNumber(
unsigned &result, SMLoc *loc) {
447 auto token = lexer.nextToken();
449 *loc = token.location;
451 if (token.kind != AIGERTokenKind::Number)
452 return emitError(token.location,
"expected number");
454 if (token.spelling.getAsInteger(10, result))
455 return emitError(token.location,
"invalid number format");
460ParseResult AIGERParser::parseOptionalNumber(
unsigned &result, SMLoc *loc) {
461 auto token = lexer.peekToken();
462 if (token.kind == AIGERTokenKind::Newline ||
463 token.kind == AIGERTokenKind::EndOfFile)
466 if (token.kind != AIGERTokenKind::Number)
467 return emitError(token.location,
"expected number");
468 return parseNumber(result, loc);
471ParseResult AIGERParser::parseLiteralSection(
472 unsigned count, SmallVectorImpl<std::pair<unsigned, SMLoc>> &out,
473 StringRef sectionName) {
474 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << count <<
" " << sectionName
476 for (
unsigned i = 0; i < count; ++i) {
479 if (parseNumber(literal, &loc) || parseNewLine())
480 return emitError(loc,
"failed to parse " + sectionName +
" literal");
482 LLVM_DEBUG(llvm::dbgs()
483 << sectionName <<
" " << i <<
": " << literal <<
"\n");
484 out.push_back({literal, loc});
489ParseResult AIGERParser::parseBinaryNumber(
unsigned &result) {
490 return lexer.readLEB128(result);
493ParseResult AIGERParser::parseHeader() {
494 LLVM_DEBUG(llvm::dbgs() <<
"Parsing AIGER header\n");
497 while (lexer.peekToken().kind != AIGERTokenKind::Identifier)
500 auto formatToken = lexer.nextToken();
501 if (formatToken.spelling ==
"aag") {
502 isBinaryFormat =
false;
503 LLVM_DEBUG(llvm::dbgs() <<
"Format: aag (ASCII)\n");
504 }
else if (formatToken.spelling ==
"aig") {
505 isBinaryFormat =
true;
506 LLVM_DEBUG(llvm::dbgs() <<
"Format: aig (binary)\n");
508 return emitError(formatToken.location,
509 "expected 'aag' or 'aig' format identifier");
514 if (parseNumber(maxVarIndex, &loc))
515 return emitError(loc,
"failed to parse M (max variable index)");
517 if (parseNumber(numInputs, &loc))
518 return emitError(loc,
"failed to parse I (number of inputs)");
520 if (parseNumber(numLatches, &loc))
521 return emitError(loc,
"failed to parse L (number of latches)");
523 if (parseNumber(numOutputs, &loc))
524 return emitError(loc,
"failed to parse O (number of outputs)");
526 if (parseNumber(numAnds, &loc))
527 return emitError(loc,
"failed to parse A (number of AND gates)");
532 if (parseOptionalNumber(numBad, &loc))
533 return emitError(loc,
"failed to parse B (number of bad states)");
535 if (parseOptionalNumber(numConstraints, &loc))
536 return emitError(loc,
"failed to parse C (number of constraints)");
538 if (parseOptionalNumber(numJustice, &loc))
539 return emitError(loc,
"failed to parse J (number of justice properties)");
541 if (parseOptionalNumber(numFairness, &loc))
542 return emitError(loc,
"failed to parse F (number of fairness constraints)");
544 LLVM_DEBUG(llvm::dbgs() <<
"Header: M=" << maxVarIndex <<
" I=" << numInputs
545 <<
" L=" << numLatches <<
" O=" << numOutputs
546 <<
" A=" << numAnds <<
" B=" << numBad
547 <<
" C=" << numConstraints <<
" J=" << numJustice
548 <<
" F=" << numFairness <<
"\n");
551 return parseNewLine();
554ParseResult AIGERParser::parseNewLine() {
555 auto token = lexer.nextToken();
556 if (token.kind != AIGERTokenKind::Newline)
557 return emitError(token.location,
"expected newline");
562ParseResult AIGERParser::parseInputs() {
563 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numInputs <<
" inputs\n");
564 if (isBinaryFormat) {
566 for (
unsigned i = 0; i < numInputs; ++i)
567 inputLiterals.push_back(2 * (i + 1));
571 for (
unsigned i = 0; i < numInputs; ++i) {
574 if (parseNumber(literal, &loc) || parseNewLine())
575 return emitError(loc,
"failed to parse input literal");
576 inputLiterals.push_back(literal);
582ParseResult AIGERParser::parseLatches() {
583 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numLatches <<
" latches\n");
584 if (isBinaryFormat) {
586 for (
unsigned i = 0; i < numLatches; ++i) {
589 if (parseNumber(literal, &loc))
590 return emitError(loc,
"failed to parse latch next state literal");
594 if (parseOptionalNumber(init))
595 return emitError(
"failed to parse latch initial value");
597 latchDefs.push_back({2 * (i + 1 + numInputs), literal, loc});
607 for (
unsigned i = 0; i < numLatches; ++i) {
608 unsigned currentState, nextState;
610 if (parseNumber(currentState, &loc) || parseNumber(nextState))
611 return emitError(loc,
"failed to parse latch definition");
615 if (parseOptionalNumber(init))
616 return emitError(
"failed to parse latch initial value");
618 if (parseNewLine()) {
619 return emitError(loc,
"failed to parse latch definition");
622 LLVM_DEBUG(llvm::dbgs() <<
"Latch " << i <<
": " << currentState <<
" -> "
623 << nextState <<
"\n");
626 if (currentState % 2 != 0 || currentState == 0)
627 return emitError(loc,
"invalid latch current state literal");
629 latchDefs.push_back({currentState, nextState, loc});
635ParseResult AIGERParser::parseOutputs() {
636 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numOutputs <<
" outputs\n");
639 for (
unsigned i = 0; i < numOutputs; ++i) {
642 if (parseNumber(literal, &loc) || parseNewLine())
643 return emitError(loc,
"failed to parse output literal");
645 LLVM_DEBUG(llvm::dbgs() <<
"Output " << i <<
": " << literal <<
"\n");
648 outputLiterals.push_back({literal, loc});
654ParseResult AIGERParser::parseAndGates() {
655 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numAnds <<
" AND gates\n");
657 if (isBinaryFormat) {
658 return parseAndGatesBinary();
660 return parseAndGatesASCII();
663ParseResult AIGERParser::parseAndGatesASCII() {
665 for (
unsigned i = 0; i < numAnds; ++i) {
666 unsigned lhs, rhs0, rhs1;
668 if (parseNumber(lhs, &loc) || parseNumber(rhs0) || parseNumber(rhs1) ||
670 return emitError(loc,
"failed to parse AND gate definition");
672 LLVM_DEBUG(llvm::dbgs() <<
"AND Gate " << i <<
": " << lhs <<
" = " << rhs0
673 <<
" & " << rhs1 <<
"\n");
676 if (lhs % 2 != 0 || lhs == 0)
677 return emitError(loc,
"invalid AND gate LHS literal");
680 if (lhs / 2 > maxVarIndex || rhs0 / 2 > maxVarIndex ||
681 rhs1 / 2 > maxVarIndex)
682 return emitError(loc,
"AND gate literal exceeds maximum variable index");
684 andGateDefs.push_back({lhs, rhs0, rhs1, loc});
690ParseResult AIGERParser::parseAndGatesBinary() {
695 LLVM_DEBUG(llvm::dbgs() <<
"Starting binary AND gate parsing\n");
703 auto currentLHS = 2 * (numInputs + numLatches + 1);
705 LLVM_DEBUG(llvm::dbgs() <<
"First AND gate LHS should be: " << currentLHS
708 for (
unsigned i = 0; i < numAnds; ++i) {
709 unsigned delta0, delta1;
710 SMLoc loc = lexer.getCurrentLoc();
711 if (parseBinaryNumber(delta0) || parseBinaryNumber(delta1))
712 return emitError(loc,
"failed to parse binary AND gate deltas");
714 auto lhs =
static_cast<int64_t
>(currentLHS);
717 if (delta0 > lhs || delta1 > (lhs - delta0)) {
718 LLVM_DEBUG(llvm::dbgs() <<
"Delta underflow: lhs=" << lhs <<
", delta0="
719 << delta0 <<
", delta1=" << delta1 <<
"\n");
720 return emitError(
"invalid binary AND gate: delta causes underflow");
723 auto rhs0 = lhs - delta0;
724 auto rhs1 = rhs0 - delta1;
726 LLVM_DEBUG(llvm::dbgs() <<
"Binary AND Gate " << i <<
": " << lhs <<
" = "
727 << rhs0 <<
" & " << rhs1 <<
" (deltas: " << delta0
728 <<
", " << delta1 <<
")\n");
730 if (lhs / 2 > maxVarIndex || rhs0 / 2 > maxVarIndex ||
731 rhs1 / 2 > maxVarIndex)
733 "binary AND gate literal exceeds maximum variable index");
735 assert(lhs > rhs0 && rhs0 >= rhs1 &&
736 "invalid binary AND gate: ordering constraint violated");
738 andGateDefs.push_back({
static_cast<unsigned>(lhs),
739 static_cast<unsigned>(rhs0),
740 static_cast<unsigned>(rhs1), loc});
747ParseResult AIGERParser::parseBadStates() {
749 return parseLiteralSection(numBad, badStateLiterals,
"bad state");
752ParseResult AIGERParser::parseConstraints() {
754 return parseLiteralSection(numConstraints, constraintLiterals,
755 "invariant constraint");
758ParseResult AIGERParser::parseJustice() {
760 emitWarning(
"AIGER justice properties are not yet supported");
762 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numJustice
763 <<
" number of justice properties \n");
764 SmallVector<unsigned> sizes;
766 for (
unsigned i = 0; i < numJustice; ++i) {
769 if (parseNumber(size, &loc) || parseNewLine())
770 return emitError(loc,
"failed to parse justice property size");
771 sizes.push_back(size);
772 LLVM_DEBUG(llvm::dbgs()
773 <<
"Justice property " << i <<
": " << size <<
'\n');
775 justiceLiterals.resize(numJustice);
777 for (
unsigned i = 0; i < numJustice; ++i) {
778 for (
unsigned j = 0; j < sizes[i]; ++j) {
781 if (parseNumber(literal, &loc) || parseNewLine())
782 return emitError(loc,
"failed to parse justice literal");
784 justiceLiterals[i].push_back({literal, loc});
785 LLVM_DEBUG(llvm::dbgs()
786 <<
"Justice " << i <<
"[" << j <<
"]: " << literal <<
'\n');
792ParseResult AIGERParser::parseFairness() {
794 emitWarning(
"AIGER fairness constraints are not yet supported");
796 return parseLiteralSection(numFairness, fairnessLiterals,
797 "fairness constraint");
800ParseResult AIGERParser::parseSymbolTable() {
804 while (!lexer.isAtEOF()) {
805 auto token = lexer.peekToken();
806 if (token.kind != AIGERTokenKind::Identifier)
808 (void)lexer.nextToken();
810 char symbolType = token.spelling.front();
814 if (token.spelling ==
"c")
817 if (symbolType !=
'i' && symbolType !=
'l' && symbolType !=
'o' &&
818 symbolType !=
'b' && symbolType !=
'c' && symbolType !=
'j' &&
823 if (token.spelling.drop_front().getAsInteger(10, literal))
824 return emitError(
"failed to parse symbol position");
827 switch (symbolType) {
829 kind = SymbolKind::Input;
832 kind = SymbolKind::Latch;
835 kind = SymbolKind::Output;
838 kind = SymbolKind::Bad;
841 kind = SymbolKind::Constraint;
844 kind = SymbolKind::Justice;
847 kind = SymbolKind::Fairness;
851 auto nextToken = lexer.lexAsSymbol();
852 if (nextToken.kind != AIGERTokenKind::Identifier)
853 return emitError(
"expected symbol name");
855 LLVM_DEBUG(llvm::dbgs()
856 <<
"Symbol " << literal <<
": " << nextToken.spelling <<
"\n");
858 symbolTable[{kind, literal}] = StringAttr::get(
context, nextToken.spelling);
866ParseResult AIGERParser::parseComments() {
868 auto token = lexer.peekToken();
869 if (token.kind == AIGERTokenKind::Identifier && token.spelling ==
"c") {
877Value AIGERParser::getLiteralValue(
unsigned literal,
878 DenseMap<unsigned, Backedge> &backedges,
880 LLVM_DEBUG(llvm::dbgs() <<
"Getting value for literal " << literal <<
"\n");
886 builder, loc, builder.getI1Type(),
887 builder.getIntegerAttr(builder.getI1Type(), 0));
893 builder, loc, builder.getI1Type(),
894 builder.getIntegerAttr(builder.getI1Type(), 1));
898 unsigned variable = literal / 2;
899 bool inverted = literal % 2;
900 unsigned baseLiteral = variable * 2;
902 LLVM_DEBUG(llvm::dbgs() <<
" Variable: " << variable
903 <<
", inverted: " << inverted
904 <<
", baseLiteral: " << baseLiteral <<
"\n");
907 if (variable > maxVarIndex) {
908 LLVM_DEBUG(llvm::dbgs() <<
" ERROR: Variable " << variable
909 <<
" exceeds maxVarIndex " << maxVarIndex <<
"\n");
914 auto backedgeIt = backedges.find(baseLiteral);
915 if (backedgeIt == backedges.end()) {
916 LLVM_DEBUG(llvm::dbgs() <<
" ERROR: No backedge found for literal "
917 << baseLiteral <<
"\n");
921 Value baseValue = backedgeIt->second;
923 LLVM_DEBUG(llvm::dbgs() <<
" ERROR: Backedge value is null for literal "
924 << baseLiteral <<
"\n");
931 SmallVector<bool> inverts = {
true};
932 return aig::AndInverterOp::create(builder, loc, builder.getI1Type(),
933 ValueRange{baseValue}, inverts);
939ParseResult AIGERParser::createModule() {
941 std::string moduleName = options.topLevelModule;
942 if (moduleName.empty())
943 moduleName =
"aiger_top";
946 builder.setInsertionPointToStart(module.getBody());
949 SmallVector<hw::PortInfo> ports;
952 for (
unsigned i = 0; i < numInputs; ++i) {
954 auto name = symbolTable.lookup({SymbolKind::Input, i});
956 name ? name : builder.getStringAttr(
"input_" + std::to_string(i));
957 port.
type = builder.getI1Type();
958 port.
dir = hw::ModulePort::Direction::Input;
960 ports.push_back(port);
964 for (
unsigned i = 0; i < numOutputs; ++i) {
966 auto name = symbolTable.lookup({SymbolKind::Output, i});
968 name ? name : builder.getStringAttr(
"output_" + std::to_string(i));
969 port.
type = builder.getI1Type();
970 port.
dir = hw::ModulePort::Direction::Output;
971 port.
argNum = numInputs + i;
972 ports.push_back(port);
976 if (numLatches > 0) {
978 clockPort.
name = builder.getStringAttr(
"clock");
979 clockPort.
type = seq::ClockType::get(builder.getContext());
980 clockPort.
dir = hw::ModulePort::Direction::Input;
981 clockPort.
argNum = numInputs + numOutputs;
982 ports.push_back(clockPort);
987 hw::HWModuleOp::create(builder, builder.getUnknownLoc(),
988 builder.getStringAttr(moduleName), ports);
991 builder.setInsertionPointToStart(hwModule.getBodyBlock());
996 clockValue = hwModule.getBodyBlock()->getArgument(numInputs);
1000 DenseMap<unsigned, Backedge> backedges;
1003 for (
unsigned i = 0; i < numInputs; ++i) {
1004 auto literal = inputLiterals[i];
1005 backedges[literal] = bb.get(builder.getI1Type());
1007 for (
auto [currentState, nextState, _] : latchDefs)
1008 backedges[currentState] = bb.
get(builder.getI1Type());
1010 for (
auto [lhs, rhs0, rhs1, loc] : andGateDefs)
1011 backedges[lhs] = bb.
get(builder.getI1Type());
1014 for (
unsigned i = 0; i < numInputs; ++i) {
1015 auto inputValue = hwModule.getBodyBlock()->getArgument(i);
1016 auto literal = inputLiterals[i];
1017 backedges[literal].setValue(inputValue);
1021 for (
auto [i, latchDef] :
llvm::enumerate(latchDefs)) {
1022 auto [currentState, nextState, loc] = latchDef;
1024 auto nextBackedge = bb.get(builder.getI1Type());
1028 builder, lexer.translateLocation(loc), (Value)nextBackedge, clockValue);
1029 if (
auto name = symbolTable.lookup({SymbolKind::Latch, i}))
1030 regValue.setNameAttr(name);
1033 backedges[currentState].setValue(regValue);
1037 for (
auto [lhs, rhs0, rhs1, loc] : andGateDefs) {
1039 auto location = lexer.translateLocation(loc);
1040 auto rhs0Value = getLiteralValue(rhs0 & ~1u, backedges, location);
1041 auto rhs1Value = getLiteralValue(rhs1 & ~1u, backedges, location);
1043 if (!rhs0Value || !rhs1Value)
1044 return emitError(loc,
"failed to get operand values for AND gate");
1047 SmallVector<bool> inverts = {
static_cast<bool>(rhs0 % 2),
1048 static_cast<bool>(rhs1 % 2)};
1052 aig::AndInverterOp::create(builder, location, builder.getI1Type(),
1053 ValueRange{rhs0Value, rhs1Value}, inverts);
1056 backedges[lhs].setValue(andResult);
1062 for (
auto [currentState, nextState, sourceLoc] : latchDefs) {
1063 auto loc = lexer.translateLocation(sourceLoc);
1064 auto nextValue = getLiteralValue(nextState, backedges, loc);
1066 return emitError(sourceLoc,
"undefined literal in latch next state");
1069 Value currentValue = backedges[currentState];
1071 regOp.getInputMutable().assign(nextValue);
1073 return emitError(sourceLoc,
"failed to find register for latch");
1077 SmallVector<Value> outputValues;
1078 for (
auto [literal, sourceLoc] : outputLiterals) {
1079 auto loc = lexer.translateLocation(sourceLoc);
1080 auto outputValue = getLiteralValue(literal, backedges, loc);
1082 return emitError(sourceLoc,
"undefined literal in output");
1083 outputValues.push_back(outputValue);
1087 auto *outputOp = hwModule.getBodyBlock()->getTerminator();
1088 outputOp->setOperands(outputValues);
1090 for (
auto [i, badState] :
llvm::enumerate(badStateLiterals)) {
1091 auto [literal, sourceLoc] = badState;
1092 auto loc = lexer.translateLocation(sourceLoc);
1093 auto value = getLiteralValue(literal, backedges, loc);
1095 return emitError(sourceLoc,
"undefined literal in bad state");
1097 auto negated = aig::AndInverterOp::create(builder, loc, builder.getI1Type(),
1099 auto label = symbolTable.lookup({SymbolKind::Bad, i});
1100 verif::AssertOp::create(builder, loc, negated.getResult(), Value{}, label);
1103 for (
auto [i, constraint] :
llvm::enumerate(constraintLiterals)) {
1104 auto [literal, sourceLoc] = constraint;
1105 auto loc = lexer.translateLocation(sourceLoc);
1106 auto value = getLiteralValue(literal, backedges, loc);
1108 return emitError(sourceLoc,
"undefined literal in invariant constraint");
1110 auto label = symbolTable.lookup({SymbolKind::Constraint, i});
1111 verif::AssumeOp::create(builder, loc, value, Value{}, label);
1123 mlir::TimingScope &ts, ModuleOp module,
1126 context->loadDialect<hw::HWDialect>();
1127 context->loadDialect<synth::SynthDialect>();
1128 context->loadDialect<seq::SeqDialect>();
1129 context->loadDialect<verif::VerifDialect>();
1134 options = &defaultOptions;
1137 AIGERParser parser(sourceMgr,
context, module, *options);
1138 return parser.parse();
1146 static mlir::TranslateToMLIRRegistration fromAIGER(
1147 "import-aiger",
"import AIGER file",
1148 [](llvm::SourceMgr &sourceMgr, MLIRContext *
context) {
1149 mlir::TimingScope ts;
1151 ModuleOp::create(UnknownLoc::get(
context)));
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static StringAttr getMainBufferNameIdentifier(const llvm::SourceMgr &sourceMgr, MLIRContext *context)
Instantiate one of these and use it to build typed backedges.
create(cls, result_type, reset=None, reset_value=None, name=None, sym_name=None, **kwargs)
mlir::LogicalResult importAIGER(llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context, mlir::TimingScope &ts, mlir::ModuleOp module, const ImportAIGEROptions *options=nullptr)
Parse an AIGER file and populate the given MLIR module with corresponding AIG dialect operations.
void registerImportAIGERTranslation()
Register the import-aiger MLIR translation.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Options for AIGER import.
This holds the name, type, direction of a module's ports.
size_t argNum
This is the argument index or the result index depending on the direction.