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 const auto *mainBuffer =
138 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
139 StringRef bufferName = mainBuffer->getBufferIdentifier();
140 if (bufferName.empty())
141 bufferName =
"<unknown>";
142 return StringAttr::get(
context, bufferName);
146 void skipWhitespace();
149 void skipUntilNewline();
152 AIGERToken lexNumber();
155 AIGERToken lexIdentifier();
158 AIGERToken makeToken(AIGERTokenKind kind,
const char *start) {
159 return AIGERToken(kind, StringRef(start, curPtr - start),
160 SMLoc::getFromPointer(start));
175 AIGERParser(
const llvm::SourceMgr &sourceMgr, MLIRContext *
context,
178 options(options), builder(
context) {}
191 unsigned maxVarIndex = 0;
192 unsigned numInputs = 0;
193 unsigned numLatches = 0;
194 unsigned numOutputs = 0;
195 unsigned numAnds = 0;
198 unsigned numConstraints = 0;
199 unsigned numJustice = 0;
200 unsigned numFairness = 0;
202 bool isBinaryFormat =
false;
206 enum SymbolKind :
unsigned {
215 DenseMap<std::pair<SymbolKind, unsigned>, StringAttr> symbolTable;
218 SmallVector<unsigned> inputLiterals;
219 SmallVector<std::tuple<unsigned, unsigned, SMLoc>>
221 SmallVector<std::pair<unsigned, SMLoc>> outputLiterals;
222 SmallVector<std::tuple<unsigned, unsigned, unsigned, SMLoc>>
224 SmallVector<std::pair<unsigned, SMLoc>> badStateLiterals;
225 SmallVector<std::pair<unsigned, SMLoc>> constraintLiterals;
226 SmallVector<std::pair<unsigned, SMLoc>> fairnessLiterals;
227 SmallVector<SmallVector<std::pair<unsigned, SMLoc>>>
231 ParseResult parseHeader();
234 ParseResult parseInputs();
237 ParseResult parseLatches();
240 ParseResult parseOutputs();
243 ParseResult parseAndGates();
246 ParseResult parseAndGatesASCII();
249 ParseResult parseAndGatesBinary();
252 ParseResult parseSymbolTable();
255 ParseResult parseComments();
258 ParseResult parseBadStates();
261 ParseResult parseConstraints();
264 ParseResult parseJustice();
267 ParseResult parseFairness();
275 Value getLiteralValue(
unsigned literal,
276 DenseMap<unsigned, Backedge> &backedges, Location loc);
279 ParseResult createModule();
281 InFlightDiagnostic emitError(llvm::SMLoc loc,
const Twine &message) {
282 return mlir::emitError(lexer.translateLocation(loc), message);
286 InFlightDiagnostic emitError(
const Twine &message) {
287 return emitError(lexer.getCurrentLoc(), message);
290 InFlightDiagnostic emitWarning(llvm::SMLoc loc,
const Twine &message) {
291 return mlir::emitWarning(lexer.translateLocation(loc), message);
295 InFlightDiagnostic emitWarning(
const Twine &message) {
296 return emitWarning(lexer.getCurrentLoc(), message);
300 ParseResult parseNumber(
unsigned &result, SMLoc *loc =
nullptr);
303 ParseResult parseOptionalNumber(
unsigned &result, SMLoc *loc =
nullptr);
308 parseLiteralSection(
unsigned count,
309 SmallVectorImpl<std::pair<unsigned, SMLoc>> &out,
310 StringRef sectionName);
313 ParseResult parseBinaryNumber(
unsigned &result);
316 ParseResult parseNewLine();
325void AIGERLexer::skipWhitespace() {
326 while (curPtr < curBuffer.end()) {
328 if (*curPtr ==
' ' || *curPtr ==
'\t' || *curPtr ==
'\r') {
335 if (*curPtr ==
'/' &&
336 (curPtr + 1 < curBuffer.end() && *(curPtr + 1) ==
'/')) {
344void AIGERLexer::skipUntilNewline() {
345 while (curPtr < curBuffer.end() && *curPtr !=
'\n')
347 if (curPtr < curBuffer.end() && *curPtr ==
'\n')
351AIGERToken AIGERLexer::lexNumber() {
352 const char *start = curPtr;
353 while (curPtr < curBuffer.end() && llvm::isDigit(*curPtr))
355 return makeToken(AIGERTokenKind::Number, start);
358AIGERToken AIGERLexer::lexIdentifier() {
359 const char *start = curPtr;
360 while (curPtr < curBuffer.end() && (llvm::isAlnum(*curPtr) || *curPtr ==
'_'))
363 StringRef spelling(start, curPtr - start);
364 AIGERTokenKind kind = AIGERTokenKind::Identifier;
366 return makeToken(kind, start);
369AIGERToken AIGERLexer::nextToken() {
372 auto impl = [
this]() {
373 if (curPtr >= curBuffer.end())
374 return makeToken(AIGERTokenKind::EndOfFile, curPtr);
376 const char *start = curPtr;
381 return makeToken(AIGERTokenKind::Newline, start);
385 llvm_unreachable(
"Whitespace should have been skipped");
386 return makeToken(AIGERTokenKind::Error, start);
388 if (llvm::isDigit(c)) {
392 if (llvm::isAlpha(c) || c ==
'_') {
394 return lexIdentifier();
396 assert((c !=
'/' || *curPtr !=
'/') &&
"// should have been skipped");
397 return makeToken(AIGERTokenKind::Error, start);
405AIGERToken AIGERLexer::lexAsSymbol() {
407 const char *start = curPtr;
408 while (curPtr < curBuffer.end() &&
409 (llvm::isPrint(*curPtr) && !llvm::isSpace(*curPtr)))
411 return makeToken(AIGERTokenKind::Identifier, start);
414AIGERToken AIGERLexer::peekToken() {
415 const char *savedPtr = curPtr;
416 AIGERToken token = nextToken();
421ParseResult AIGERLexer::readLEB128(
unsigned &result) {
424 llvm::decodeULEB128(
reinterpret_cast<const uint8_t *
>(curPtr), &len,
425 reinterpret_cast<const uint8_t *
>(curBuffer.end()));
426 if (len == 0 || value > std::numeric_limits<unsigned>::max())
429 result =
static_cast<unsigned>(value);
437ParseResult AIGERParser::parse() {
438 if (parseHeader() || parseInputs() || parseLatches() || parseOutputs() ||
439 parseBadStates() || parseConstraints() || parseJustice() ||
440 parseFairness() || parseAndGates() || parseSymbolTable() ||
444 return createModule();
447ParseResult AIGERParser::parseNumber(
unsigned &result, SMLoc *loc) {
448 auto token = lexer.nextToken();
450 *loc = token.location;
452 if (token.kind != AIGERTokenKind::Number)
453 return emitError(token.location,
"expected number");
455 if (token.spelling.getAsInteger(10, result))
456 return emitError(token.location,
"invalid number format");
461ParseResult AIGERParser::parseOptionalNumber(
unsigned &result, SMLoc *loc) {
462 auto token = lexer.peekToken();
463 if (token.kind == AIGERTokenKind::Newline ||
464 token.kind == AIGERTokenKind::EndOfFile)
467 if (token.kind != AIGERTokenKind::Number)
468 return emitError(token.location,
"expected number");
469 return parseNumber(result, loc);
472ParseResult AIGERParser::parseLiteralSection(
473 unsigned count, SmallVectorImpl<std::pair<unsigned, SMLoc>> &out,
474 StringRef sectionName) {
475 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << count <<
" " << sectionName
477 for (
unsigned i = 0; i < count; ++i) {
480 if (parseNumber(literal, &loc) || parseNewLine())
481 return emitError(loc,
"failed to parse " + sectionName +
" literal");
483 LLVM_DEBUG(llvm::dbgs()
484 << sectionName <<
" " << i <<
": " << literal <<
"\n");
485 out.push_back({literal, loc});
490ParseResult AIGERParser::parseBinaryNumber(
unsigned &result) {
491 return lexer.readLEB128(result);
494ParseResult AIGERParser::parseHeader() {
495 LLVM_DEBUG(llvm::dbgs() <<
"Parsing AIGER header\n");
498 while (lexer.peekToken().kind != AIGERTokenKind::Identifier)
501 auto formatToken = lexer.nextToken();
502 if (formatToken.spelling ==
"aag") {
503 isBinaryFormat =
false;
504 LLVM_DEBUG(llvm::dbgs() <<
"Format: aag (ASCII)\n");
505 }
else if (formatToken.spelling ==
"aig") {
506 isBinaryFormat =
true;
507 LLVM_DEBUG(llvm::dbgs() <<
"Format: aig (binary)\n");
509 return emitError(formatToken.location,
510 "expected 'aag' or 'aig' format identifier");
515 if (parseNumber(maxVarIndex, &loc))
516 return emitError(loc,
"failed to parse M (max variable index)");
518 if (parseNumber(numInputs, &loc))
519 return emitError(loc,
"failed to parse I (number of inputs)");
521 if (parseNumber(numLatches, &loc))
522 return emitError(loc,
"failed to parse L (number of latches)");
524 if (parseNumber(numOutputs, &loc))
525 return emitError(loc,
"failed to parse O (number of outputs)");
527 if (parseNumber(numAnds, &loc))
528 return emitError(loc,
"failed to parse A (number of AND gates)");
533 if (parseOptionalNumber(numBad, &loc))
534 return emitError(loc,
"failed to parse B (number of bad states)");
536 if (parseOptionalNumber(numConstraints, &loc))
537 return emitError(loc,
"failed to parse C (number of constraints)");
539 if (parseOptionalNumber(numJustice, &loc))
540 return emitError(loc,
"failed to parse J (number of justice properties)");
542 if (parseOptionalNumber(numFairness, &loc))
543 return emitError(loc,
"failed to parse F (number of fairness constraints)");
545 LLVM_DEBUG(llvm::dbgs() <<
"Header: M=" << maxVarIndex <<
" I=" << numInputs
546 <<
" L=" << numLatches <<
" O=" << numOutputs
547 <<
" A=" << numAnds <<
" B=" << numBad
548 <<
" C=" << numConstraints <<
" J=" << numJustice
549 <<
" F=" << numFairness <<
"\n");
552 return parseNewLine();
555ParseResult AIGERParser::parseNewLine() {
556 auto token = lexer.nextToken();
557 if (token.kind != AIGERTokenKind::Newline)
558 return emitError(token.location,
"expected newline");
563ParseResult AIGERParser::parseInputs() {
564 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numInputs <<
" inputs\n");
565 if (isBinaryFormat) {
567 for (
unsigned i = 0; i < numInputs; ++i)
568 inputLiterals.push_back(2 * (i + 1));
572 for (
unsigned i = 0; i < numInputs; ++i) {
575 if (parseNumber(literal, &loc) || parseNewLine())
576 return emitError(loc,
"failed to parse input literal");
577 inputLiterals.push_back(literal);
583ParseResult AIGERParser::parseLatches() {
584 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numLatches <<
" latches\n");
585 if (isBinaryFormat) {
587 for (
unsigned i = 0; i < numLatches; ++i) {
590 if (parseNumber(literal, &loc))
591 return emitError(loc,
"failed to parse latch next state literal");
595 if (parseOptionalNumber(init))
596 return emitError(
"failed to parse latch initial value");
598 latchDefs.push_back({2 * (i + 1 + numInputs), literal, loc});
608 for (
unsigned i = 0; i < numLatches; ++i) {
609 unsigned currentState, nextState;
611 if (parseNumber(currentState, &loc) || parseNumber(nextState))
612 return emitError(loc,
"failed to parse latch definition");
616 if (parseOptionalNumber(init))
617 return emitError(
"failed to parse latch initial value");
619 if (parseNewLine()) {
620 return emitError(loc,
"failed to parse latch definition");
623 LLVM_DEBUG(llvm::dbgs() <<
"Latch " << i <<
": " << currentState <<
" -> "
624 << nextState <<
"\n");
627 if (currentState % 2 != 0 || currentState == 0)
628 return emitError(loc,
"invalid latch current state literal");
630 latchDefs.push_back({currentState, nextState, loc});
636ParseResult AIGERParser::parseOutputs() {
637 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numOutputs <<
" outputs\n");
640 for (
unsigned i = 0; i < numOutputs; ++i) {
643 if (parseNumber(literal, &loc) || parseNewLine())
644 return emitError(loc,
"failed to parse output literal");
646 LLVM_DEBUG(llvm::dbgs() <<
"Output " << i <<
": " << literal <<
"\n");
649 outputLiterals.push_back({literal, loc});
655ParseResult AIGERParser::parseAndGates() {
656 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numAnds <<
" AND gates\n");
658 if (isBinaryFormat) {
659 return parseAndGatesBinary();
661 return parseAndGatesASCII();
664ParseResult AIGERParser::parseAndGatesASCII() {
666 for (
unsigned i = 0; i < numAnds; ++i) {
667 unsigned lhs, rhs0, rhs1;
669 if (parseNumber(lhs, &loc) || parseNumber(rhs0) || parseNumber(rhs1) ||
671 return emitError(loc,
"failed to parse AND gate definition");
673 LLVM_DEBUG(llvm::dbgs() <<
"AND Gate " << i <<
": " << lhs <<
" = " << rhs0
674 <<
" & " << rhs1 <<
"\n");
677 if (lhs % 2 != 0 || lhs == 0)
678 return emitError(loc,
"invalid AND gate LHS literal");
681 if (lhs / 2 > maxVarIndex || rhs0 / 2 > maxVarIndex ||
682 rhs1 / 2 > maxVarIndex)
683 return emitError(loc,
"AND gate literal exceeds maximum variable index");
685 andGateDefs.push_back({lhs, rhs0, rhs1, loc});
691ParseResult AIGERParser::parseAndGatesBinary() {
696 LLVM_DEBUG(llvm::dbgs() <<
"Starting binary AND gate parsing\n");
704 auto currentLHS = 2 * (numInputs + numLatches + 1);
706 LLVM_DEBUG(llvm::dbgs() <<
"First AND gate LHS should be: " << currentLHS
709 for (
unsigned i = 0; i < numAnds; ++i) {
710 unsigned delta0, delta1;
711 SMLoc loc = lexer.getCurrentLoc();
712 if (parseBinaryNumber(delta0) || parseBinaryNumber(delta1))
713 return emitError(loc,
"failed to parse binary AND gate deltas");
715 auto lhs =
static_cast<int64_t
>(currentLHS);
718 if (delta0 > lhs || delta1 > (lhs - delta0)) {
719 LLVM_DEBUG(llvm::dbgs() <<
"Delta underflow: lhs=" << lhs <<
", delta0="
720 << delta0 <<
", delta1=" << delta1 <<
"\n");
721 return emitError(
"invalid binary AND gate: delta causes underflow");
724 auto rhs0 = lhs - delta0;
725 auto rhs1 = rhs0 - delta1;
727 LLVM_DEBUG(llvm::dbgs() <<
"Binary AND Gate " << i <<
": " << lhs <<
" = "
728 << rhs0 <<
" & " << rhs1 <<
" (deltas: " << delta0
729 <<
", " << delta1 <<
")\n");
731 if (lhs / 2 > maxVarIndex || rhs0 / 2 > maxVarIndex ||
732 rhs1 / 2 > maxVarIndex)
734 "binary AND gate literal exceeds maximum variable index");
736 assert(lhs > rhs0 && rhs0 >= rhs1 &&
737 "invalid binary AND gate: ordering constraint violated");
739 andGateDefs.push_back({
static_cast<unsigned>(lhs),
740 static_cast<unsigned>(rhs0),
741 static_cast<unsigned>(rhs1), loc});
748ParseResult AIGERParser::parseBadStates() {
750 return parseLiteralSection(numBad, badStateLiterals,
"bad state");
753ParseResult AIGERParser::parseConstraints() {
755 return parseLiteralSection(numConstraints, constraintLiterals,
756 "invariant constraint");
759ParseResult AIGERParser::parseJustice() {
761 emitWarning(
"AIGER justice properties are not yet supported");
763 LLVM_DEBUG(llvm::dbgs() <<
"Parsing " << numJustice
764 <<
" number of justice properties \n");
765 SmallVector<unsigned> sizes;
767 for (
unsigned i = 0; i < numJustice; ++i) {
770 if (parseNumber(size, &loc) || parseNewLine())
771 return emitError(loc,
"failed to parse justice property size");
772 sizes.push_back(size);
773 LLVM_DEBUG(llvm::dbgs()
774 <<
"Justice property " << i <<
": " << size <<
'\n');
776 justiceLiterals.resize(numJustice);
778 for (
unsigned i = 0; i < numJustice; ++i) {
779 for (
unsigned j = 0; j < sizes[i]; ++j) {
782 if (parseNumber(literal, &loc) || parseNewLine())
783 return emitError(loc,
"failed to parse justice literal");
785 justiceLiterals[i].push_back({literal, loc});
786 LLVM_DEBUG(llvm::dbgs()
787 <<
"Justice " << i <<
"[" << j <<
"]: " << literal <<
'\n');
793ParseResult AIGERParser::parseFairness() {
795 emitWarning(
"AIGER fairness constraints are not yet supported");
797 return parseLiteralSection(numFairness, fairnessLiterals,
798 "fairness constraint");
801ParseResult AIGERParser::parseSymbolTable() {
805 while (!lexer.isAtEOF()) {
806 auto token = lexer.peekToken();
807 if (token.kind != AIGERTokenKind::Identifier)
809 (void)lexer.nextToken();
811 char symbolType = token.spelling.front();
815 if (token.spelling ==
"c")
818 if (symbolType !=
'i' && symbolType !=
'l' && symbolType !=
'o' &&
819 symbolType !=
'b' && symbolType !=
'c' && symbolType !=
'j' &&
824 if (token.spelling.drop_front().getAsInteger(10, literal))
825 return emitError(
"failed to parse symbol position");
828 switch (symbolType) {
830 kind = SymbolKind::Input;
833 kind = SymbolKind::Latch;
836 kind = SymbolKind::Output;
839 kind = SymbolKind::Bad;
842 kind = SymbolKind::Constraint;
845 kind = SymbolKind::Justice;
848 kind = SymbolKind::Fairness;
852 auto nextToken = lexer.lexAsSymbol();
853 if (nextToken.kind != AIGERTokenKind::Identifier)
854 return emitError(
"expected symbol name");
856 LLVM_DEBUG(llvm::dbgs()
857 <<
"Symbol " << literal <<
": " << nextToken.spelling <<
"\n");
859 symbolTable[{kind, literal}] = StringAttr::get(
context, nextToken.spelling);
867ParseResult AIGERParser::parseComments() {
869 auto token = lexer.peekToken();
870 if (token.kind == AIGERTokenKind::Identifier && token.spelling ==
"c") {
878Value AIGERParser::getLiteralValue(
unsigned literal,
879 DenseMap<unsigned, Backedge> &backedges,
881 LLVM_DEBUG(llvm::dbgs() <<
"Getting value for literal " << literal <<
"\n");
887 builder, loc, builder.getI1Type(),
888 builder.getIntegerAttr(builder.getI1Type(), 0));
894 builder, loc, builder.getI1Type(),
895 builder.getIntegerAttr(builder.getI1Type(), 1));
899 unsigned variable = literal / 2;
900 bool inverted = literal % 2;
901 unsigned baseLiteral = variable * 2;
903 LLVM_DEBUG(llvm::dbgs() <<
" Variable: " << variable
904 <<
", inverted: " << inverted
905 <<
", baseLiteral: " << baseLiteral <<
"\n");
908 if (variable > maxVarIndex) {
909 LLVM_DEBUG(llvm::dbgs() <<
" ERROR: Variable " << variable
910 <<
" exceeds maxVarIndex " << maxVarIndex <<
"\n");
915 auto backedgeIt = backedges.find(baseLiteral);
916 if (backedgeIt == backedges.end()) {
917 LLVM_DEBUG(llvm::dbgs() <<
" ERROR: No backedge found for literal "
918 << baseLiteral <<
"\n");
922 Value baseValue = backedgeIt->second;
924 LLVM_DEBUG(llvm::dbgs() <<
" ERROR: Backedge value is null for literal "
925 << baseLiteral <<
"\n");
932 SmallVector<bool> inverts = {
true};
933 return aig::AndInverterOp::create(builder, loc, builder.getI1Type(),
934 ValueRange{baseValue}, inverts);
940ParseResult AIGERParser::createModule() {
943 if (moduleName.empty())
944 moduleName =
"aiger_top";
947 builder.setInsertionPointToStart(module.getBody());
950 SmallVector<hw::PortInfo> ports;
953 for (
unsigned i = 0; i < numInputs; ++i) {
955 auto name = symbolTable.lookup({SymbolKind::Input, i});
957 name ? name : builder.getStringAttr(
"input_" + std::to_string(i));
958 port.
type = builder.getI1Type();
959 port.
dir = hw::ModulePort::Direction::Input;
961 ports.push_back(port);
965 for (
unsigned i = 0; i < numOutputs; ++i) {
967 auto name = symbolTable.lookup({SymbolKind::Output, i});
969 name ? name : builder.getStringAttr(
"output_" + std::to_string(i));
970 port.
type = builder.getI1Type();
971 port.
dir = hw::ModulePort::Direction::Output;
972 port.
argNum = numInputs + i;
973 ports.push_back(port);
977 if (numLatches > 0) {
978 hw::PortInfo clockPort;
979 clockPort.
name = builder.getStringAttr(
"clock");
980 clockPort.
type = seq::ClockType::get(builder.getContext());
981 clockPort.
dir = hw::ModulePort::Direction::Input;
982 clockPort.
argNum = numInputs + numOutputs;
983 ports.push_back(clockPort);
988 hw::HWModuleOp::create(builder, builder.getUnknownLoc(),
989 builder.getStringAttr(moduleName), ports);
992 builder.setInsertionPointToStart(hwModule.getBodyBlock());
997 clockValue = hwModule.getBodyBlock()->getArgument(numInputs);
1000 BackedgeBuilder bb(builder, builder.getUnknownLoc());
1001 DenseMap<unsigned, Backedge> backedges;
1004 for (
unsigned i = 0; i < numInputs; ++i) {
1005 auto literal = inputLiterals[i];
1006 backedges[literal] = bb.get(builder.getI1Type());
1008 for (
auto [currentState, nextState, _] : latchDefs)
1009 backedges[currentState] = bb.get(builder.getI1Type());
1011 for (
auto [lhs, rhs0, rhs1, loc] : andGateDefs)
1012 backedges[lhs] = bb.get(builder.getI1Type());
1015 for (
unsigned i = 0; i < numInputs; ++i) {
1016 auto inputValue = hwModule.getBodyBlock()->getArgument(i);
1017 auto literal = inputLiterals[i];
1018 backedges[literal].setValue(inputValue);
1022 for (
auto [i, latchDef] : llvm::enumerate(latchDefs)) {
1023 auto [currentState, nextState, loc] = latchDef;
1025 auto nextBackedge = bb.get(builder.getI1Type());
1029 builder, lexer.translateLocation(loc), (Value)nextBackedge, clockValue);
1030 if (
auto name = symbolTable.lookup({SymbolKind::Latch, i}))
1031 regValue.setNameAttr(name);
1034 backedges[currentState].setValue(regValue);
1038 for (
auto [lhs, rhs0, rhs1, loc] : andGateDefs) {
1040 auto location = lexer.translateLocation(loc);
1041 auto rhs0Value = getLiteralValue(rhs0 & ~1u, backedges, location);
1042 auto rhs1Value = getLiteralValue(rhs1 & ~1u, backedges, location);
1044 if (!rhs0Value || !rhs1Value)
1045 return emitError(loc,
"failed to get operand values for AND gate");
1048 SmallVector<bool> inverts = {
static_cast<bool>(rhs0 % 2),
1049 static_cast<bool>(rhs1 % 2)};
1053 aig::AndInverterOp::create(builder, location, builder.getI1Type(),
1054 ValueRange{rhs0Value, rhs1Value}, inverts);
1057 backedges[lhs].setValue(andResult);
1063 for (
auto [currentState, nextState, sourceLoc] : latchDefs) {
1064 auto loc = lexer.translateLocation(sourceLoc);
1065 auto nextValue = getLiteralValue(nextState, backedges, loc);
1067 return emitError(sourceLoc,
"undefined literal in latch next state");
1070 Value currentValue = backedges[currentState];
1071 if (
auto regOp = currentValue.getDefiningOp<seq::CompRegOp>())
1072 regOp.getInputMutable().assign(nextValue);
1074 return emitError(sourceLoc,
"failed to find register for latch");
1078 SmallVector<Value> outputValues;
1079 for (
auto [literal, sourceLoc] : outputLiterals) {
1080 auto loc = lexer.translateLocation(sourceLoc);
1081 auto outputValue = getLiteralValue(literal, backedges, loc);
1083 return emitError(sourceLoc,
"undefined literal in output");
1084 outputValues.push_back(outputValue);
1088 auto *outputOp = hwModule.getBodyBlock()->getTerminator();
1089 outputOp->setOperands(outputValues);
1091 for (
auto [i, badState] : llvm::enumerate(badStateLiterals)) {
1092 auto [literal, sourceLoc] = badState;
1093 auto loc = lexer.translateLocation(sourceLoc);
1094 auto value = getLiteralValue(literal, backedges, loc);
1096 return emitError(sourceLoc,
"undefined literal in bad state");
1098 auto negated = aig::AndInverterOp::create(builder, loc, builder.getI1Type(),
1100 auto label = symbolTable.lookup({SymbolKind::Bad, i});
1101 verif::AssertOp::create(builder, loc, negated.getResult(), Value{}, label);
1104 for (
auto [i, constraint] : llvm::enumerate(constraintLiterals)) {
1105 auto [literal, sourceLoc] = constraint;
1106 auto loc = lexer.translateLocation(sourceLoc);
1107 auto value = getLiteralValue(literal, backedges, loc);
1109 return emitError(sourceLoc,
"undefined literal in invariant constraint");
1111 auto label = symbolTable.lookup({SymbolKind::Constraint, i});
1112 verif::AssumeOp::create(builder, loc, value, Value{}, label);
1124 mlir::TimingScope &ts, ModuleOp module,
1125 const ImportAIGEROptions *options) {
1127 context->loadDialect<hw::HWDialect>();
1128 context->loadDialect<synth::SynthDialect>();
1129 context->loadDialect<seq::SeqDialect>();
1130 context->loadDialect<verif::VerifDialect>();
1133 ImportAIGEROptions defaultOptions;
1135 options = &defaultOptions;
1138 AIGERParser parser(sourceMgr,
context, module, *options);
1139 return parser.parse();
1147 static mlir::TranslateToMLIRRegistration fromAIGER(
1148 "import-aiger",
"import AIGER file",
1149 [](llvm::SourceMgr &sourceMgr, MLIRContext *
context) {
1150 mlir::TimingScope ts;
1152 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)
false return failure()
Parse an optional keyword or string and set instance into 'result'.
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.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Options for AIGER import.
std::string topLevelModule
The name to use for the top-level module.
size_t argNum
This is the argument index or the result index depending on the direction.