32#include "mlir/Pass/Pass.h"
33#include "llvm/ADT/MapVector.h"
34#include "llvm/ADT/TypeSwitch.h"
35#include "llvm/Support/raw_ostream.h"
38#define GEN_PASS_DEF_CONVERTHWTOBTOR2
39#include "circt/Conversion/Passes.h.inc"
48struct ConvertHWToBTOR2Pass
49 :
public circt::impl::ConvertHWToBTOR2Base<ConvertHWToBTOR2Pass>,
50 public comb::CombinationalVisitor<ConvertHWToBTOR2Pass>,
51 public sv::Visitor<ConvertHWToBTOR2Pass>,
52 public hw::TypeOpVisitor<ConvertHWToBTOR2Pass>,
55 using verif::Visitor<ConvertHWToBTOR2Pass>::visitVerif;
57 ConvertHWToBTOR2Pass(raw_ostream &os) : os(os) {}
59 void runOnOperation()
override;
75 DenseMap<size_t, size_t> sortToLIDMap;
80 DenseMap<APInt, size_t> constToLIDMap;
85 DenseMap<Operation *, size_t> opLIDMap;
88 DenseMap<Operation *, size_t> regToInputLIDMap;
92 DenseMap<size_t, size_t> inputLIDs;
98 SmallVector<Operation *> regOps;
102 llvm::SmallMapVector<Operation *, OperandRange::iterator, 16> worklist;
105 DenseSet<Operation *> handledOps;
108 static constexpr size_t noLID = -1UL;
109 [[maybe_unused]]
static constexpr int64_t noWidth = -1L;
112 Namespace symbolNamespace;
119 size_t getOpLID(Operation *op) {
122 Operation *defOp = op;
123 auto &f = opLIDMap[defOp];
133 size_t setOpLID(Operation *op) {
134 size_t oplid = lid++;
135 opLIDMap[op] = oplid;
142 size_t getOpLID(Value value) {
143 Operation *defOp = value.getDefiningOp();
145 if (
auto it = opLIDMap.find(defOp); it != opLIDMap.end())
150 if (BlockArgument barg = dyn_cast<BlockArgument>(value)) {
152 size_t argIdx = barg.getArgNumber();
155 if (
auto it = inputLIDs.find(argIdx); it != inputLIDs.end())
164 size_t getRegInputLID(Operation *regOp) {
165 auto &f = regToInputLIDMap[regOp];
177 size_t getSortLID(
size_t w) {
178 if (
auto it = sortToLIDMap.find(w); it != sortToLIDMap.end())
186 size_t setSortLID(
size_t w) {
187 size_t sortlid = lid;
189 sortToLIDMap[w] = lid++;
196 size_t getConstLID(int64_t val,
size_t w) {
197 if (
auto it = constToLIDMap.find(APInt(w, val)); it != constToLIDMap.end())
205 size_t setConstLID(int64_t val,
size_t w) {
206 size_t constlid = lid;
208 constToLIDMap[APInt(w, val)] = lid++;
216 void genSort(StringRef type,
size_t width) {
218 if (getSortLID(width) != noLID) {
222 size_t sortlid = setSortLID(width);
227 <<
" " << type <<
" " << width <<
"\n";
231 void genInput(
size_t inlid,
size_t width, StringRef name) {
233 size_t sid = sortToLIDMap.at(width);
238 <<
" " << sid <<
" " << name <<
"\n";
242 void genConst(APInt value,
size_t width, Operation *op) {
245 size_t opLID = getOpLID(op);
248 size_t sid = sortToLIDMap.at(width);
252 <<
" " << sid <<
" " << value <<
"\n";
256 size_t genZero(
size_t width) {
258 size_t zlid = getConstLID(0, width);
263 size_t sid = sortToLIDMap.at(width);
266 size_t constlid = setConstLID(0, width);
269 os << constlid <<
" "
271 <<
" " << sid <<
"\n";
277 void genInit(Operation *
reg, Value initVal, int64_t width) {
279 size_t regLID = getOpLID(
reg);
280 size_t sid = sortToLIDMap.at(width);
281 size_t initValLID = getOpLID(initVal);
287 <<
" " << sid <<
" " << regLID <<
" " << initValLID <<
"\n";
292 void genBinOp(StringRef inst, Operation *binop, Value op1, Value op2,
295 size_t opLID = getOpLID(binop);
298 size_t sid = sortToLIDMap.at(width);
302 size_t op1LID = getOpLID(op1);
303 size_t op2LID = getOpLID(op2);
306 os << opLID <<
" " << inst <<
" " << sid <<
" " << op1LID <<
" " << op2LID
311 void genVariadicOp(StringRef inst, Operation *op,
size_t width) {
312 auto operands = op->getOperands();
313 size_t sid = sortToLIDMap.at(width);
315 if (operands.size() == 0) {
316 op->emitError(
"variadic operations with no operands are not supported");
322 if (operands.size() == 1) {
323 auto existingLID = getOpLID(operands[0]);
326 assert(existingLID != noLID);
327 opLIDMap[op] = existingLID;
332 auto isConcat = isa<comb::ConcatOp>(op);
336 auto prevOperandLID = getOpLID(operands[0]);
339 auto currentWidth = operands[0].getType().getIntOrFloatBitWidth();
341 for (
auto operand : operands.drop_front()) {
346 currentWidth += operand.getType().getIntOrFloatBitWidth();
348 genSort(
"bitvec", currentWidth);
351 auto thisLid = lid++;
352 auto thisOperandLID = getOpLID(operand);
353 os << thisLid <<
" " << inst <<
" "
354 << (isConcat ? sortToLIDMap.at(currentWidth) : sid) <<
" "
355 << prevOperandLID <<
" " << thisOperandLID <<
"\n";
356 prevOperandLID = thisLid;
360 opLIDMap[op] = prevOperandLID;
364 void genSlice(Operation *srcop, Value op0,
size_t lowbit, int64_t width) {
366 size_t opLID = getOpLID(srcop);
369 size_t sid = sortToLIDMap.at(width);
373 size_t op0LID = getOpLID(op0);
378 <<
" " << sid <<
" " << op0LID <<
" " << (lowbit + width - 1) <<
" "
383 void genReplicateAsConcats(Operation *srcop, Value op0,
size_t count,
384 unsigned int inputWidth) {
385 auto currentWidth = inputWidth;
387 auto prevOperandLID = getOpLID(op0);
388 for (
size_t i = 1; i < count; ++i) {
389 currentWidth += inputWidth;
391 genSort(
"bitvec", currentWidth);
393 auto thisLid = lid++;
396 <<
" " << sortToLIDMap.at(currentWidth) <<
" " << prevOperandLID <<
" "
397 << getOpLID(op0) <<
"\n";
398 prevOperandLID = thisLid;
402 opLIDMap[srcop] = prevOperandLID;
406 void genUnaryOp(Operation *srcop, Operation *op0, StringRef inst,
409 size_t opLID = getOpLID(srcop);
412 size_t sid = sortToLIDMap.at(width);
416 size_t op0LID = getOpLID(op0);
418 os << opLID <<
" " << inst <<
" " << sid <<
" " << op0LID <<
"\n";
423 void genUnaryOp(Operation *srcop, Value op0, StringRef inst,
size_t width) {
424 genUnaryOp(srcop, op0.getDefiningOp(), inst, width);
428 size_t genUnaryOp(
size_t op0LID, StringRef inst,
size_t width) {
430 size_t curLid = lid++;
433 size_t sid = sortToLIDMap.at(width);
435 os << curLid <<
" " << inst <<
" " << sid <<
" " << op0LID <<
"\n";
440 size_t genUnaryOp(Operation *op0, StringRef inst,
size_t width) {
441 return genUnaryOp(getOpLID(op0), inst, width);
446 size_t genUnaryOp(Value op0, StringRef inst,
size_t width) {
447 return genUnaryOp(getOpLID(op0), inst, width);
453 void genBad(Operation *assertop) {
455 size_t assertLID = getOpLID(assertop);
462 void genBad(
size_t assertLID) {
467 <<
" " << assertLID <<
"\n";
472 void genConstraint(Value expr) {
474 size_t exprLID = getOpLID(expr);
476 genConstraint(exprLID);
481 void genConstraint(
size_t exprLID) {
486 <<
" " << exprLID <<
"\n";
491 void genIte(Operation *srcop, Value cond, Value t, Value f, int64_t width,
492 bool forReset =
false) {
494 size_t condLID = getOpLID(cond);
495 size_t tLID = getOpLID(t);
496 size_t fLID = getOpLID(f);
498 genIte(srcop, condLID, tLID, fLID, width, forReset);
503 void genIte(Operation *srcop,
size_t condLID,
size_t tLID,
size_t fLID,
504 int64_t width,
bool forReset =
false) {
509 iteLID = forReset ? getRegInputLID(srcop) : getOpLID(srcop);
512 size_t sid = sortToLIDMap.at(width);
517 <<
" " << sid <<
" " << condLID <<
" " << tLID <<
" " << fLID <<
"\n";
521 size_t genImplies(Operation *srcop, Value lhs, Value rhs) {
523 size_t lhsLID = getOpLID(lhs);
524 size_t rhsLID = getOpLID(rhs);
526 return genImplies(srcop, lhsLID, rhsLID);
530 size_t genImplies(Operation *srcop,
size_t lhsLID,
size_t rhsLID) {
532 size_t opLID = getOpLID(srcop);
533 return genImplies(opLID, lhsLID, rhsLID);
536 size_t genImplies(
size_t opLID,
size_t lhsLID,
size_t rhsLID) {
538 size_t sid = sortToLIDMap.at(1);
542 <<
" " << sid <<
" " << lhsLID <<
" " << rhsLID <<
"\n";
547 void genState(Operation *srcop, int64_t width, StringRef name) {
549 size_t opLID = getOpLID(srcop);
552 size_t sid = sortToLIDMap.at(width);
557 <<
" " << sid <<
" " << symbolNamespace.newName(name) <<
"\n";
561 void genNext(Operation *
reg, int64_t width) {
563 size_t sid = sortToLIDMap.at(width);
566 size_t regLID = getOpLID(
reg);
567 size_t nextLID = getRegInputLID(
reg);
573 <<
" " << sid <<
" " << regLID <<
" " << nextLID <<
"\n";
578 void genModuleComment(StringRef name,
bool end =
false) {
579 os <<
"; **************************************"
581 <<
"; " << (
end ?
"END" :
"START") <<
" OF MODULE: " << name <<
"\n"
582 <<
"; **************************************"
588 int64_t requireSort(mlir::Type type) {
590 int64_t width = hw::getBitWidth(type);
599 genSort(
"bitvec", width);
604 Value extractRegNext(seq::CompRegOp
reg)
const {
return reg.getInput(); }
605 Value extractRegNext(seq::FirRegOp
reg)
const {
return reg.getNext(); }
608 template <
typename RegT>
609 void extractRegArgs(RegT
reg, int64_t &width, Value &next, Value &reset,
610 Value &resetVal, Value &
clk)
const {
611 width = hw::getBitWidth(
reg.getType());
612 reset =
reg.getReset();
613 resetVal =
reg.getResetValue();
617 next = extractRegNext(
reg);
622 void finalizeRegVisit(Operation *op) {
624 Value next, reset, resetVal,
clk;
627 auto extract = TypeSwitch<Operation *, LogicalResult>(op)
628 .Case<seq::CompRegOp, seq::FirRegOp>([&](
auto reg) {
629 extractRegArgs(
reg, width, next, reset, resetVal,
clk);
633 op->emitError(
"Invalid register operation !");
643 if (
clk != foundClock) {
644 op->emitError(
"Multi-clock designs are not currently supported.");
651 genSort(
"bitvec", width);
656 size_t nextLID = noLID;
660 if (BlockArgument barg = dyn_cast<BlockArgument>(next)) {
662 size_t argIdx = barg.getArgNumber();
665 nextLID = inputLIDs[argIdx];
668 nextLID = getOpLID(next);
673 size_t resetValLID = noLID;
677 size_t resetLID = noLID;
678 if (BlockArgument barg = dyn_cast<BlockArgument>(reset)) {
681 size_t argIdx = barg.getArgNumber();
684 resetLID = inputLIDs[argIdx];
687 resetLID = getOpLID(reset);
692 if (
auto resetValArg = dyn_cast<BlockArgument>(resetVal))
693 resetValLID = inputLIDs[resetValArg.getArgNumber()];
695 resetValLID = getOpLID(resetVal.getDefiningOp());
697 resetValLID = genZero(width);
706 genIte(op, resetLID, resetValLID, nextLID, width,
true);
709 if (nextLID == noLID) {
710 next.getDefiningOp()->emitError(
711 "Register input does not point to a valid op!");
715 regToInputLIDMap[op] = nextLID;
725 void ignore(Operation *op) {}
733 void visit(hw::PortInfo &port) {
737 if (port.
isInput() && !isa<seq::ClockType, seq::ImmutableType>(port.
type)) {
739 StringRef iName = port.
getName();
743 int64_t w = requireSort(port.
type);
750 inputLIDs[port.
argNum] = lid;
755 genInput(inlid, w, iName);
762 void visitTypeOp(hw::ConstantOp op) {
764 if (handledOps.contains(op))
768 int64_t w = requireSort(op.getType());
772 genConst(op.getValue(), w, op);
776 void visit(hw::WireOp op) {
777 op->emitError(
"Wires are not supported in btor!");
778 return signalPassFailure();
781 void visitTypeOp(Operation *op) { visitInvalidTypeOp(op); }
784 void visitInvalidTypeOp(Operation *op) {
786 dispatchCombinationalVisitor(op);
791 template <
typename Op>
792 void visitBinOp(Op op, StringRef inst) {
794 int64_t w = requireSort(op.getType());
797 Value op1 = op.getOperand(0);
798 Value op2 = op.getOperand(1);
801 genBinOp(inst, op, op1, op2, w);
804 template <
typename Op>
805 void visitVariadicOp(Op op, StringRef inst) {
807 int64_t w = requireSort(op.getType());
810 genVariadicOp(inst, op, w);
814 void visitComb(comb::AddOp op) { visitVariadicOp(op,
"add"); }
815 void visitComb(comb::SubOp op) { visitBinOp(op,
"sub"); }
816 void visitComb(comb::MulOp op) { visitVariadicOp(op,
"mul"); }
817 void visitComb(comb::DivSOp op) { visitBinOp(op,
"sdiv"); }
818 void visitComb(comb::DivUOp op) { visitBinOp(op,
"udiv"); }
819 void visitComb(comb::ModSOp op) { visitBinOp(op,
"smod"); }
820 void visitComb(comb::ShlOp op) { visitBinOp(op,
"sll"); }
821 void visitComb(comb::ShrUOp op) { visitBinOp(op,
"srl"); }
822 void visitComb(comb::ShrSOp op) { visitBinOp(op,
"sra"); }
823 void visitComb(comb::AndOp op) { visitVariadicOp(op,
"and"); }
824 void visitComb(comb::OrOp op) { visitVariadicOp(op,
"or"); }
825 void visitComb(comb::XorOp op) { visitVariadicOp(op,
"xor"); }
826 void visitComb(comb::ConcatOp op) { visitVariadicOp(op,
"concat"); }
830 void visitComb(comb::ExtractOp op) {
831 int64_t w = requireSort(op.getType());
835 Value op0 = op.getOperand();
836 size_t lb = op.getLowBit();
839 genSlice(op, op0, lb, w);
845 void visitComb(comb::ICmpOp op) {
846 Value lhs = op.getOperand(0);
847 Value rhs = op.getOperand(1);
851 StringRef pred = stringifyICmpPredicate(op.getPredicate());
856 else if (pred ==
"ule")
858 else if (pred ==
"sle")
860 else if (pred ==
"uge")
862 else if (pred ==
"sge")
866 genSort(
"bitvec", 1);
870 genBinOp(pred, op, lhs, rhs, 1);
874 void visitComb(comb::MuxOp op) {
876 Value pred = op.getCond();
877 Value tval = op.getTrueValue();
878 Value fval = op.getFalseValue();
882 int64_t w = requireSort(op.getType());
885 genIte(op, pred, tval, fval, w);
889 void visitComb(comb::ReplicateOp op) {
890 Value op0 = op.getOperand();
891 auto count = op.getMultiple();
892 auto inputWidth = op0.getType().getIntOrFloatBitWidth();
895 genReplicateAsConcats(op, op0, count, inputWidth);
898 void visitComb(Operation *op) { visitInvalidComb(op); }
901 void visitInvalidComb(Operation *op) { dispatchSVVisitor(op); }
904 void visitSV(sv::AssertOp op) {
906 Value expr = op.getExpression();
909 genSort(
"bitvec", 1);
915 if (
auto ifop = dyn_cast<sv::IfOp>(((Operation *)op)->getParentOp())) {
916 Value
en = ifop.getOperand();
919 genImplies(ifop,
en, expr);
922 genUnaryOp(op, ifop,
"not", 1);
925 genUnaryOp(op, expr,
"not", 1);
932 void visitSV(sv::AssumeOp op) {
934 Value expr = op.getExpression();
939 void visitSV(sv::AlwaysOp op) {
940 if (op.getEvents().size() > 1) {
941 op->emitError(
"Multiple events in sv.always are not supported.");
942 return signalPassFailure();
945 auto cond = op.getCondition(0);
947 if (cond.event != sv::EventControl::AtPosEdge) {
948 op->emitError(
"Only posedge clocking is supported in sv.always.");
949 return signalPassFailure();
952 if (isa<BlockArgument>(cond.value) ||
953 !isa<seq::FromClockOp>(cond.value.getDefiningOp())) {
954 op->emitError(
"This pass only currently supports sv.always ops that use "
955 "a top-level seq.clock input (converted using "
956 "seq.from_clock) as their clock.");
957 return signalPassFailure();
962 auto clk = cond.value.getDefiningOp()->getOperand(0);
964 if (
clk != foundClock) {
965 op->emitError(
"Multi-clock designs are not currently supported.");
966 return signalPassFailure();
973 void visitSV(Operation *op) { visitInvalidSV(op); }
976 void visitInvalidSV(Operation *op) { dispatchVerifVisitor(op); }
978 template <
typename Op>
979 void visitAssertLike(Op op) {
981 Value prop = op.getProperty();
982 Value
en = op.getEnable();
985 genSort(
"bitvec", 1);
987 size_t assertLID = noLID;
991 genImplies(op,
en, prop);
994 assertLID = genUnaryOp(op,
"not", 1);
997 assertLID = genUnaryOp(prop.getDefiningOp(),
"not", 1);
1004 template <
typename Op>
1005 void visitAssumeLike(Op op) {
1007 Value prop = op.getProperty();
1008 Value
en = op.getEnable();
1010 size_t assumeLID = getOpLID(prop);
1014 genSort(
"bitvec", 1);
1016 assumeLID = genImplies(op,
en, prop);
1020 genConstraint(assumeLID);
1025 void visitVerif(verif::AssertOp op) { visitAssertLike(op); }
1026 void visitVerif(verif::ClockedAssertOp op) { visitAssertLike(op); }
1030 void visitVerif(verif::AssumeOp op) { visitAssumeLike(op); }
1031 void visitVerif(verif::ClockedAssumeOp op) { visitAssumeLike(op); }
1037 void visitVerif(verif::SymbolicValueOp op) {
1039 auto name = symbolNamespace.newName(op.getName().value_or(
""));
1043 int64_t w = requireSort(op.getType());
1046 size_t inlid = setOpLID(op.getOperation());
1049 genInput(inlid, w, name);
1053 void visitUnhandledVerif(Operation *op) {
1054 op->emitError(
"not supported in btor2!");
1055 return signalPassFailure();
1059 void visitInvalidVerif(Operation *op) { visit(op); }
1063 void visit(Operation *op) {
1066 TypeSwitch<Operation *, void>(op)
1067 .Case<seq::FirRegOp, seq::CompRegOp, seq::FromClockOp, seq::ToClockOp>(
1068 [&](
auto expr) { visit(expr); })
1069 .Default([&](
auto expr) { visitUnsupportedOp(op); });
1075 void visit(seq::FirRegOp
reg) {
1077 StringRef regName =
reg.getName();
1078 auto type =
reg.getType();
1079 if (!isa<mlir::IntegerType>(type)) {
1080 reg.emitError(
"Only integer typed seq.firregs are supported in BTOR2.");
1081 return signalPassFailure();
1083 int64_t w = requireSort(type);
1086 genState(
reg, w, regName);
1091 regOps.push_back(
reg);
1095 void visit(seq::CompRegOp
reg) {
1097 StringRef regName =
reg.getName().value();
1098 auto type =
reg.getType();
1099 if (!isa<mlir::IntegerType>(type)) {
1100 reg.emitError(
"Only integer typed seq.compregs are supported in BTOR2.");
1101 return signalPassFailure();
1103 int64_t w = requireSort(type);
1107 auto init =
reg.getInitialValue();
1108 auto resetVal =
reg.getResetValue();
1113 auto shouldInitReset = assumeInitReset && resetVal;
1116 if (init || shouldInitReset) {
1117 hw::ConstantOp initialConstant;
1120 if (shouldInitReset) {
1121 initialConstant = resetVal.getDefiningOp<hw::ConstantOp>();
1122 if (!initialConstant) {
1124 "Reset value must be emitted directly by a hw.constant "
1125 "op when --assume-init-reset is in use.");
1129 if (!init.getDefiningOp<seq::InitialOp>()) {
1131 "Initial value must be emitted directly by a seq.initial op");
1136 .getDefiningOp<hw::ConstantOp>();
1137 if (!initialConstant)
1138 reg->emitError(
"initial value must be constant");
1142 dispatchTypeOpVisitor(initialConstant);
1145 handledOps.insert(initialConstant);
1148 genState(
reg, w, regName);
1151 genInit(
reg, initialConstant, w);
1154 genState(
reg, w, regName);
1160 regOps.push_back(
reg);
1163 void visit(seq::FromClockOp op) {
1164 for (
auto *user : op->getResult(0).getUsers()) {
1165 if (!isa<sv::AlwaysOp, verif::ClockedAssertOp>(user)) {
1166 op->emitError(
"This pass only supports seq.from_clock results being "
1167 "used by sv.always and verif.clocked_assert operations.");
1168 signalPassFailure();
1173 void visit(seq::ToClockOp op) {
1175 if (!isa<BlockArgument>(op.getInput())) {
1176 op->emitError(
"This pass only supports seq.to_clock operations that take "
1177 "a top-level input as their argument.");
1181 for (
auto *user : op->getResult(0).getUsers())
1182 if (!isa<seq::FirRegOp, seq::CompRegOp>(user)) {
1183 op->emitError(
"This pass only supports seq.to_clock results being "
1184 "used by seq.firreg and seq.compreg operations.");
1185 signalPassFailure();
1191 void visitUnsupportedOp(Operation *op) {
1194 TypeSwitch<Operation *, void>(op)
1196 .Case<sv::MacroDefOp, sv::MacroDeclOp, sv::VerbatimOp,
1197 sv::VerbatimExprOp, sv::VerbatimExprSEOp, sv::IfOp, sv::IfDefOp,
1198 sv::IfDefProceduralOp, sv::AlwaysCombOp, seq::InitialOp,
1199 sv::AlwaysFFOp, seq::InitialOp, seq::YieldOp, hw::OutputOp,
1200 hw::HWModuleOp, verif::FormalOp,
1203 verif::FormatVerilogStringOp, verif::PrintOp>(
1204 [&](
auto expr) { ignore(op); })
1208 .Default([&](
auto expr) {
1209 op->emitOpError(
"is an unsupported operation");
1210 return signalPassFailure();
1215 LogicalResult visitPorts(hw::HWModuleOp module) {
1217 for (
auto &port : module.getPortList()) {
1220 auto portVal =
module.getArgumentForInput(port.argNum);
1222 llvm::any_of(portVal.getUsers(), [](Operation *user) {
1223 return isa<seq::ToClockOp>(user);
1228 if (portVal.getNumUses() > 1) {
1230 "Inputs converted to clocks may only have one user.");
1244 bool isSuportedModule(Operation *module) {
1245 bool supported = isa<hw::HWModuleOp, verif::FormalOp>(module);
1247 module->emitError("Unsupported module type!");
1252 LogicalResult preVisitRegs(Operation *module) {
1254 if (!isSuportedModule(module))
1258 module->walk([&](Operation *op) {
1259 TypeSwitch<Operation *, void>(op)
1260 .Case<seq::FirRegOp, seq::CompRegOp>([&](auto reg) {
1262 handledOps.insert(op);
1264 .Default([&](
auto expr) {});
1271 LogicalResult visitBodyOps(Operation *module) {
1273 if (!isSuportedModule(module))
1277 module->walk([&](Operation *op) {
1279 if (isa<hw::InstanceOp>(op)) {
1280 op->emitOpError("not supported in BTOR2 conversion");
1281 return signalPassFailure();
1285 if (handledOps.contains(op))
1289 worklist.insert({op, op->operand_begin()});
1292 while (!worklist.empty()) {
1293 auto &[op, operandIt] = worklist.back();
1294 if (operandIt == op->operand_end()) {
1297 dispatchTypeOpVisitor(op);
1300 handledOps.insert(op);
1301 worklist.pop_back();
1307 Value operand = *(operandIt++);
1308 auto *defOp = operand.getDefiningOp();
1311 if (!defOp || handledOps.contains(defOp))
1316 if (!worklist.insert({defOp, defOp->operand_begin()}).second) {
1317 defOp->emitError(
"dependency cycle");
1318 return signalPassFailure();
1328 sortToLIDMap.clear();
1329 constToLIDMap.clear();
1338 LogicalResult handleTopLevel(Operation *module) {
1341 if (failed(preVisitRegs(module)))
1345 if (failed(visitBodyOps(module)))
1349 for (
size_t i = 0; i < regOps.size(); ++i)
1350 finalizeRegVisit(regOps[i]);
1360void ConvertHWToBTOR2Pass::runOnOperation() {
1365 auto top = getOperation();
1366 top.walk([&](Operation *op) {
1368 if (!isa<hw::HWModuleOp, verif::FormalOp>(op))
1372 auto moduleName = SymbolTable::getSymbolName(op);
1373 genModuleComment(moduleName);
1377 if (
auto module = dyn_cast<hw::HWModuleOp>(op))
1378 if (failed(visitPorts(module)))
1379 return signalPassFailure();
1382 if (failed(handleTopLevel(op)))
1383 return signalPassFailure();
1386 genModuleComment(moduleName,
true);
1394std::unique_ptr<mlir::Pass>
1396 return std::make_unique<ConvertHWToBTOR2Pass>(os);
1401 return std::make_unique<ConvertHWToBTOR2Pass>(llvm::outs());
assert(baseType &&"element must be base type")
false return failure()
Parse an optional keyword or string and set instance into 'result'.
Value unwrapImmutableValue(mlir::TypedValue< seq::ImmutableType > immutableVal)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createConvertHWToBTOR2Pass()
reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
StringRef getName() const
size_t argNum
This is the argument index or the result index depending on the direction.