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>,
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;
89 DenseMap<size_t, size_t> inputLIDs;
95 SmallVector<Operation *> regOps;
99 llvm::SmallMapVector<Operation *, OperandRange::iterator, 16> worklist;
102 DenseSet<Operation *> handledOps;
105 static constexpr size_t noLID = -1UL;
106 [[maybe_unused]]
static constexpr int64_t noWidth = -1L;
116 size_t getOpLID(Operation *op) {
119 Operation *defOp = op;
120 auto &f = opLIDMap[defOp];
130 size_t setOpLID(Operation *op) {
131 size_t oplid = lid++;
132 opLIDMap[op] = oplid;
139 size_t getOpLID(Value value) {
140 Operation *defOp = value.getDefiningOp();
142 if (
auto it = opLIDMap.find(defOp); it != opLIDMap.end())
147 if (BlockArgument barg = dyn_cast<BlockArgument>(value)) {
149 size_t argIdx = barg.getArgNumber();
152 if (
auto it = inputLIDs.find(argIdx); it != inputLIDs.end())
164 size_t getSortLID(
size_t w) {
165 if (
auto it = sortToLIDMap.find(w); it != sortToLIDMap.end())
173 size_t setSortLID(
size_t w) {
174 size_t sortlid = lid;
176 sortToLIDMap[w] = lid++;
183 size_t getConstLID(int64_t val,
size_t w) {
184 if (
auto it = constToLIDMap.find(APInt(w, val)); it != constToLIDMap.end())
192 size_t setConstLID(int64_t val,
size_t w) {
193 size_t constlid = lid;
195 constToLIDMap[APInt(w, val)] = lid++;
203 void genSort(StringRef type,
size_t width) {
205 if (getSortLID(width) != noLID) {
209 size_t sortlid = setSortLID(width);
214 <<
" " << type <<
" " << width <<
"\n";
218 void genInput(
size_t inlid,
size_t width, StringRef name) {
220 size_t sid = sortToLIDMap.at(width);
225 <<
" " << sid <<
" " << name <<
"\n";
229 void genConst(APInt value,
size_t width, Operation *op) {
232 size_t opLID = getOpLID(op);
235 size_t sid = sortToLIDMap.at(width);
239 <<
" " << sid <<
" " << value <<
"\n";
243 size_t genZero(
size_t width) {
245 size_t zlid = getConstLID(0, width);
250 size_t sid = sortToLIDMap.at(width);
253 size_t constlid = setConstLID(0, width);
256 os << constlid <<
" "
258 <<
" " << sid <<
"\n";
264 void genInit(Operation *
reg, Value initVal, int64_t width) {
266 size_t regLID = getOpLID(
reg);
267 size_t sid = sortToLIDMap.at(width);
268 size_t initValLID = getOpLID(initVal);
274 <<
" " << sid <<
" " << regLID <<
" " << initValLID <<
"\n";
279 void genBinOp(StringRef inst, Operation *binop, Value op1, Value op2,
282 size_t opLID = getOpLID(binop);
285 size_t sid = sortToLIDMap.at(width);
289 size_t op1LID = getOpLID(op1);
290 size_t op2LID = getOpLID(op2);
293 os << opLID <<
" " << inst <<
" " << sid <<
" " << op1LID <<
" " << op2LID
298 void genVariadicOp(StringRef inst, Operation *op,
size_t width) {
299 auto operands = op->getOperands();
300 size_t sid = sortToLIDMap.at(width);
302 if (operands.size() == 0) {
303 op->emitError(
"variadic operations with no operands are not supported");
309 if (operands.size() == 1) {
310 auto existingLID = getOpLID(operands[0]);
313 assert(existingLID != noLID);
314 opLIDMap[op] = existingLID;
319 auto isConcat = isa<comb::ConcatOp>(op);
323 auto prevOperandLID = getOpLID(operands[0]);
326 auto currentWidth = operands[0].getType().getIntOrFloatBitWidth();
328 for (
auto operand : operands.drop_front()) {
333 currentWidth += operand.getType().getIntOrFloatBitWidth();
335 genSort(
"bitvec", currentWidth);
338 auto thisLid = lid++;
339 auto thisOperandLID = getOpLID(operand);
340 os << thisLid <<
" " << inst <<
" "
341 << (isConcat ? sortToLIDMap.at(currentWidth) : sid) <<
" "
342 << prevOperandLID <<
" " << thisOperandLID <<
"\n";
343 prevOperandLID = thisLid;
347 opLIDMap[op] = prevOperandLID;
351 void genSlice(Operation *srcop, Value op0,
size_t lowbit, int64_t width) {
353 size_t opLID = getOpLID(srcop);
356 size_t sid = sortToLIDMap.at(width);
360 size_t op0LID = getOpLID(op0);
365 <<
" " << sid <<
" " << op0LID <<
" " << (lowbit + width - 1) <<
" "
370 void genReplicateAsConcats(Operation *srcop, Value op0,
size_t count,
371 unsigned int inputWidth) {
372 auto currentWidth = inputWidth;
374 auto prevOperandLID = getOpLID(op0);
375 for (
size_t i = 1; i < count; ++i) {
376 currentWidth += inputWidth;
378 genSort(
"bitvec", currentWidth);
380 auto thisLid = lid++;
383 <<
" " << sortToLIDMap.at(currentWidth) <<
" " << prevOperandLID <<
" "
384 << getOpLID(op0) <<
"\n";
385 prevOperandLID = thisLid;
389 opLIDMap[srcop] = prevOperandLID;
393 void genUnaryOp(Operation *srcop, Operation *op0, StringRef inst,
396 size_t opLID = getOpLID(srcop);
399 size_t sid = sortToLIDMap.at(width);
403 size_t op0LID = getOpLID(op0);
405 os << opLID <<
" " << inst <<
" " << sid <<
" " << op0LID <<
"\n";
410 void genUnaryOp(Operation *srcop, Value op0, StringRef inst,
size_t width) {
411 genUnaryOp(srcop, op0.getDefiningOp(), inst, width);
415 size_t genUnaryOp(
size_t op0LID, StringRef inst,
size_t width) {
417 size_t curLid = lid++;
420 size_t sid = sortToLIDMap.at(width);
422 os << curLid <<
" " << inst <<
" " << sid <<
" " << op0LID <<
"\n";
427 size_t genUnaryOp(Operation *op0, StringRef inst,
size_t width) {
428 return genUnaryOp(getOpLID(op0), inst, width);
433 size_t genUnaryOp(Value op0, StringRef inst,
size_t width) {
434 return genUnaryOp(getOpLID(op0), inst, width);
440 void genBad(Operation *assertop) {
442 size_t assertLID = getOpLID(assertop);
449 void genBad(
size_t assertLID) {
454 <<
" " << assertLID <<
"\n";
459 void genConstraint(Value expr) {
461 size_t exprLID = getOpLID(expr);
463 genConstraint(exprLID);
468 void genConstraint(
size_t exprLID) {
473 <<
" " << exprLID <<
"\n";
478 void genIte(Operation *srcop, Value cond, Value t, Value f, int64_t width) {
480 size_t condLID = getOpLID(cond);
481 size_t tLID = getOpLID(t);
482 size_t fLID = getOpLID(f);
484 genIte(srcop, condLID, tLID, fLID, width);
489 void genIte(Operation *srcop,
size_t condLID,
size_t tLID,
size_t fLID,
492 size_t opLID = getOpLID(srcop);
495 size_t sid = sortToLIDMap.at(width);
500 <<
" " << sid <<
" " << condLID <<
" " << tLID <<
" " << fLID <<
"\n";
504 size_t genImplies(Operation *srcop, Value lhs, Value rhs) {
506 size_t lhsLID = getOpLID(lhs);
507 size_t rhsLID = getOpLID(rhs);
509 return genImplies(srcop, lhsLID, rhsLID);
513 size_t genImplies(Operation *srcop,
size_t lhsLID,
size_t rhsLID) {
515 size_t opLID = getOpLID(srcop);
516 return genImplies(opLID, lhsLID, rhsLID);
519 size_t genImplies(
size_t opLID,
size_t lhsLID,
size_t rhsLID) {
521 size_t sid = sortToLIDMap.at(1);
525 <<
" " << sid <<
" " << lhsLID <<
" " << rhsLID <<
"\n";
530 void genState(Operation *srcop, int64_t width, StringRef name) {
532 size_t opLID = getOpLID(srcop);
535 size_t sid = sortToLIDMap.at(width);
540 <<
" " << sid <<
" " << symbolNamespace.
newName(name) <<
"\n";
545 void genNext(Value next, Operation *
reg, int64_t width) {
547 size_t sid = sortToLIDMap.at(width);
550 size_t regLID = getOpLID(
reg);
551 size_t nextLID = getOpLID(next);
557 <<
" " << sid <<
" " << regLID <<
" " << nextLID <<
"\n";
562 void genModuleComment(StringRef name,
bool end =
false) {
563 os <<
"; **************************************"
565 <<
"; " << (
end ?
"END" :
"START") <<
" OF MODULE: " << name <<
"\n"
566 <<
"; **************************************"
572 int64_t requireSort(mlir::Type type) {
574 int64_t width = hw::getBitWidth(type);
583 genSort(
"bitvec", width);
589 Value extractRegNext(seq::FirRegOp
reg)
const {
return reg.getNext(); }
592 template <
typename RegT>
593 void extractRegArgs(RegT
reg, int64_t &width, Value &next, Value &reset,
594 Value &resetVal, Value &
clk)
const {
595 width = hw::getBitWidth(
reg.getType());
596 reset =
reg.getReset();
597 resetVal =
reg.getResetValue();
601 next = extractRegNext(
reg);
606 void finalizeRegVisit(Operation *op) {
608 Value next, reset, resetVal,
clk;
611 auto extract = TypeSwitch<Operation *, LogicalResult>(op)
613 extractRegArgs(
reg, width, next, reset, resetVal,
clk);
617 op->emitError(
"Invalid register operation !");
627 if (
clk != foundClock) {
628 op->emitError(
"Multi-clock designs are not currently supported.");
635 genSort(
"bitvec", width);
640 size_t nextLID = noLID;
644 if (BlockArgument barg = dyn_cast<BlockArgument>(next)) {
646 size_t argIdx = barg.getArgNumber();
649 nextLID = inputLIDs[argIdx];
652 nextLID = getOpLID(next);
657 size_t resetValLID = noLID;
661 size_t resetLID = noLID;
662 if (BlockArgument barg = dyn_cast<BlockArgument>(reset)) {
665 size_t argIdx = barg.getArgNumber();
668 resetLID = inputLIDs[argIdx];
671 resetLID = getOpLID(reset);
676 resetValLID = getOpLID(resetVal.getDefiningOp());
678 resetValLID = genZero(width);
681 setOpLID(next.getDefiningOp());
690 genIte(next.getDefiningOp(), resetLID, resetValLID, nextLID, width);
693 if (nextLID == noLID) {
694 next.getDefiningOp()->emitError(
695 "Register input does not point to a valid op!");
701 genNext(next, op, width);
707 void ignore(Operation *op) {}
719 if (port.
isInput() && !isa<seq::ClockType, seq::ImmutableType>(port.
type)) {
721 StringRef iName = port.
getName();
725 int64_t w = requireSort(port.
type);
732 inputLIDs[port.
argNum] = lid;
737 genInput(inlid, w, iName);
746 if (handledOps.contains(op))
750 int64_t w = requireSort(op.getType());
754 genConst(op.getValue(), w, op);
758 void visit(hw::WireOp op) {
759 op->emitError(
"Wires are not supported in btor!");
760 return signalPassFailure();
763 void visitTypeOp(Operation *op) { visitInvalidTypeOp(op); }
766 void visitInvalidTypeOp(Operation *op) {
768 dispatchCombinationalVisitor(op);
773 template <
typename Op>
774 void visitBinOp(Op op, StringRef inst) {
776 int64_t w = requireSort(op.getType());
779 Value op1 = op.getOperand(0);
780 Value op2 = op.getOperand(1);
783 genBinOp(inst, op, op1, op2, w);
786 template <
typename Op>
787 void visitVariadicOp(Op op, StringRef inst) {
789 int64_t w = requireSort(op.getType());
792 genVariadicOp(inst, op, w);
796 void visitComb(
comb::AddOp op) { visitVariadicOp(op,
"add"); }
797 void visitComb(
comb::SubOp op) { visitBinOp(op,
"sub"); }
798 void visitComb(
comb::MulOp op) { visitVariadicOp(op,
"mul"); }
799 void visitComb(
comb::DivSOp op) { visitBinOp(op,
"sdiv"); }
800 void visitComb(
comb::DivUOp op) { visitBinOp(op,
"udiv"); }
801 void visitComb(
comb::ModSOp op) { visitBinOp(op,
"smod"); }
802 void visitComb(
comb::ShlOp op) { visitBinOp(op,
"sll"); }
803 void visitComb(
comb::ShrUOp op) { visitBinOp(op,
"srl"); }
804 void visitComb(
comb::ShrSOp op) { visitBinOp(op,
"sra"); }
805 void visitComb(
comb::AndOp op) { visitVariadicOp(op,
"and"); }
806 void visitComb(
comb::OrOp op) { visitVariadicOp(op,
"or"); }
807 void visitComb(
comb::XorOp op) { visitVariadicOp(op,
"xor"); }
808 void visitComb(
comb::ConcatOp op) { visitVariadicOp(op,
"concat"); }
813 int64_t w = requireSort(op.getType());
817 Value op0 = op.getOperand();
818 size_t lb = op.getLowBit();
821 genSlice(op, op0, lb, w);
827 void visitComb(comb::ICmpOp op) {
828 Value lhs = op.getOperand(0);
829 Value rhs = op.getOperand(1);
833 StringRef pred = stringifyICmpPredicate(op.getPredicate());
838 else if (pred ==
"ule")
840 else if (pred ==
"sle")
842 else if (pred ==
"uge")
844 else if (pred ==
"sge")
848 genSort(
"bitvec", 1);
852 genBinOp(pred, op, lhs, rhs, 1);
858 Value pred = op.getCond();
859 Value tval = op.getTrueValue();
860 Value fval = op.getFalseValue();
864 int64_t w = requireSort(op.getType());
867 genIte(op, pred, tval, fval, w);
871 void visitComb(comb::ReplicateOp op) {
872 Value op0 = op.getOperand();
873 auto count = op.getMultiple();
874 auto inputWidth = op0.getType().getIntOrFloatBitWidth();
877 genReplicateAsConcats(op, op0, count, inputWidth);
880 void visitComb(Operation *op) { visitInvalidComb(op); }
883 void visitInvalidComb(Operation *op) { dispatchSVVisitor(op); }
886 void visitSV(sv::AssertOp op) {
888 Value expr = op.getExpression();
891 genSort(
"bitvec", 1);
897 if (
auto ifop = dyn_cast<sv::IfOp>(((Operation *)op)->getParentOp())) {
898 Value
en = ifop.getOperand();
901 genImplies(ifop,
en, expr);
904 genUnaryOp(op, ifop,
"not", 1);
907 genUnaryOp(op, expr,
"not", 1);
914 void visitSV(sv::AssumeOp op) {
916 Value expr = op.getExpression();
921 void visitSV(sv::AlwaysOp op) {
922 if (op.getEvents().size() > 1) {
923 op->emitError(
"Multiple events in sv.always are not supported.");
924 return signalPassFailure();
927 auto cond = op.getCondition(0);
929 if (cond.event != sv::EventControl::AtPosEdge) {
930 op->emitError(
"Only posedge clocking is supported in sv.always.");
931 return signalPassFailure();
934 if (isa<BlockArgument>(cond.value) ||
935 !isa<seq::FromClockOp>(cond.value.getDefiningOp())) {
936 op->emitError(
"This pass only currently supports sv.always ops that use "
937 "a top-level seq.clock input (converted using "
938 "seq.from_clock) as their clock.");
939 return signalPassFailure();
944 auto clk = cond.value.getDefiningOp()->getOperand(0);
946 if (
clk != foundClock) {
947 op->emitError(
"Multi-clock designs are not currently supported.");
948 return signalPassFailure();
955 void visitSV(Operation *op) { visitInvalidSV(op); }
958 void visitInvalidSV(Operation *op) { dispatchVerifVisitor(op); }
960 template <
typename Op>
961 void visitAssertLike(Op op) {
963 Value prop = op.getProperty();
964 Value
en = op.getEnable();
967 genSort(
"bitvec", 1);
969 size_t assertLID = noLID;
973 genImplies(op,
en, prop);
976 assertLID = genUnaryOp(op,
"not", 1);
979 assertLID = genUnaryOp(prop.getDefiningOp(),
"not", 1);
986 template <
typename Op>
987 void visitAssumeLike(Op op) {
989 Value prop = op.getProperty();
990 Value
en = op.getEnable();
992 size_t assumeLID = getOpLID(prop);
996 genSort(
"bitvec", 1);
998 assumeLID = genImplies(op,
en, prop);
1002 genConstraint(assumeLID);
1007 void visitVerif(verif::AssertOp op) { visitAssertLike(op); }
1008 void visitVerif(verif::ClockedAssertOp op) { visitAssertLike(op); }
1012 void visitVerif(verif::AssumeOp op) { visitAssumeLike(op); }
1013 void visitVerif(verif::ClockedAssumeOp op) { visitAssumeLike(op); }
1019 void visitVerif(verif::SymbolicValueOp op) {
1021 auto name = symbolNamespace.
newName(op.getName().value_or(
""));
1025 int64_t w = requireSort(op.getType());
1028 size_t inlid = setOpLID(op.getOperation());
1031 genInput(inlid, w, name);
1035 void visitUnhandledVerif(Operation *op) {
1036 op->emitError(
"not supported in btor2!");
1037 return signalPassFailure();
1041 void visitInvalidVerif(Operation *op) { visit(op); }
1045 void visit(Operation *op) {
1048 TypeSwitch<Operation *, void>(op)
1049 .Case<seq::FirRegOp,
seq::CompRegOp, seq::FromClockOp, seq::ToClockOp>(
1050 [&](
auto expr) { visit(expr); })
1051 .Default([&](
auto expr) { visitUnsupportedOp(op); });
1057 void visit(seq::FirRegOp
reg) {
1059 StringRef regName =
reg.getName();
1060 auto type =
reg.getType();
1061 if (!isa<mlir::IntegerType>(type)) {
1062 reg.emitError(
"Only integer typed seq.firregs are supported in BTOR2.");
1063 return signalPassFailure();
1065 int64_t w = requireSort(type);
1068 genState(
reg, w, regName);
1073 regOps.push_back(
reg);
1079 StringRef regName =
reg.getName().value();
1080 auto type =
reg.getType();
1081 if (!isa<mlir::IntegerType>(type)) {
1082 reg.emitError(
"Only integer typed seq.compregs are supported in BTOR2.");
1083 return signalPassFailure();
1085 int64_t w = requireSort(type);
1089 auto init =
reg.getInitialValue();
1090 auto resetVal =
reg.getResetValue();
1095 auto shouldInitReset = assumeInitReset && resetVal;
1098 if (init || shouldInitReset) {
1102 if (shouldInitReset) {
1104 if (!initialConstant) {
1106 "Reset value must be emitted directly by a hw.constant "
1107 "op when --assume-init-reset is in use.");
1111 if (!init.getDefiningOp<seq::InitialOp>()) {
1113 "Initial value must be emitted directly by a seq.initial op");
1119 if (!initialConstant)
1120 reg->emitError(
"initial value must be constant");
1124 dispatchTypeOpVisitor(initialConstant);
1127 handledOps.insert(initialConstant);
1130 genState(
reg, w, regName);
1133 genInit(
reg, initialConstant, w);
1136 genState(
reg, w, regName);
1142 regOps.push_back(
reg);
1145 void visit(seq::FromClockOp op) {
1146 for (
auto *user : op->getResult(0).getUsers()) {
1147 if (!isa<sv::AlwaysOp, verif::ClockedAssertOp>(user)) {
1148 op->emitError(
"This pass only supports seq.from_clock results being "
1149 "used by sv.always and verif.clocked_assert operations.");
1150 signalPassFailure();
1155 void visit(seq::ToClockOp op) {
1157 if (!isa<BlockArgument>(op.getInput())) {
1158 op->emitError(
"This pass only supports seq.to_clock operations that take "
1159 "a top-level input as their argument.");
1163 for (
auto *user : op->getResult(0).getUsers())
1164 if (!isa<seq::FirRegOp, seq::CompRegOp>(user)) {
1165 op->emitError(
"This pass only supports seq.to_clock results being "
1166 "used by seq.firreg and seq.compreg operations.");
1167 signalPassFailure();
1173 void visitUnsupportedOp(Operation *op) {
1176 TypeSwitch<Operation *, void>(op)
1178 .Case<sv::MacroDefOp, sv::MacroDeclOp, sv::VerbatimOp,
1179 sv::VerbatimExprOp, sv::VerbatimExprSEOp, sv::IfOp,
sv::IfDefOp,
1180 sv::IfDefProceduralOp, sv::AlwaysCombOp, seq::InitialOp,
1181 sv::AlwaysFFOp, seq::InitialOp, seq::YieldOp, hw::OutputOp,
1185 verif::FormatVerilogStringOp, verif::PrintOp>(
1186 [&](
auto expr) { ignore(op); })
1190 .Default([&](
auto expr) {
1191 op->emitOpError(
"is an unsupported operation");
1192 return signalPassFailure();
1199 for (
auto &port :
module.getPortList()) {
1201 if (port.isInput()) {
1202 auto portVal = module.getArgumentForInput(port.argNum);
1204 llvm::any_of(portVal.getUsers(), [](Operation *user) {
1205 return isa<seq::ToClockOp>(user);
1210 if (portVal.getNumUses() > 1) {
1212 "Inputs converted to clocks may only have one user.");
1226 bool isSuportedModule(Operation *module) {
1227 bool supported = isa<hw::HWModuleOp, verif::FormalOp>(module);
1229 module->emitError("Unsupported module type!");
1234 LogicalResult preVisitRegs(Operation *module) {
1236 if (!isSuportedModule(module))
1240 module->walk([&](Operation *op) {
1241 TypeSwitch<Operation *, void>(op)
1242 .Case<seq::FirRegOp, seq::CompRegOp>([&](auto reg) {
1244 handledOps.insert(op);
1246 .Default([&](
auto expr) {});
1253 LogicalResult visitBodyOps(Operation *module) {
1255 if (!isSuportedModule(module))
1259 module->walk([&](Operation *op) {
1261 if (isa<hw::InstanceOp>(op)) {
1262 op->emitOpError("not supported in BTOR2 conversion");
1263 return signalPassFailure();
1267 if (handledOps.contains(op))
1271 worklist.insert({op, op->operand_begin()});
1274 while (!worklist.empty()) {
1275 auto &[op, operandIt] = worklist.back();
1276 if (operandIt == op->operand_end()) {
1279 dispatchTypeOpVisitor(op);
1282 handledOps.insert(op);
1283 worklist.pop_back();
1289 Value operand = *(operandIt++);
1290 auto *defOp = operand.getDefiningOp();
1293 if (!defOp || handledOps.contains(defOp))
1298 if (!worklist.insert({defOp, defOp->operand_begin()}).second) {
1299 defOp->emitError(
"dependency cycle");
1300 return signalPassFailure();
1310 sortToLIDMap.clear();
1311 constToLIDMap.clear();
1320 LogicalResult handleTopLevel(Operation *module) {
1323 if (failed(preVisitRegs(module)))
1327 if (failed(visitBodyOps(module)))
1331 for (
size_t i = 0; i < regOps.size(); ++i)
1332 finalizeRegVisit(regOps[i]);
1342void ConvertHWToBTOR2Pass::runOnOperation() {
1347 auto top = getOperation();
1348 top.walk([&](Operation *op) {
1350 if (!isa<hw::HWModuleOp, verif::FormalOp>(op))
1354 auto moduleName = SymbolTable::getSymbolName(op);
1355 genModuleComment(moduleName);
1359 if (
auto module = dyn_cast<hw::HWModuleOp>(op))
1360 if (failed(visitPorts(module)))
1361 return signalPassFailure();
1364 if (failed(handleTopLevel(op)))
1365 return signalPassFailure();
1368 genModuleComment(moduleName,
true);
1376std::unique_ptr<mlir::Pass>
1378 return std::make_unique<ConvertHWToBTOR2Pass>(os);
1383 return std::make_unique<ConvertHWToBTOR2Pass>(llvm::outs());
assert(baseType &&"element must be base type")
A namespace that is used to store existing names and generate new names in some scope within the IR.
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
This helps visit Combinational nodes.
This helps visit TypeOp nodes.
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)
This holds the name, type, direction of a module's ports.
StringRef getName() const
size_t argNum
This is the argument index or the result index depending on the direction.