14#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
15#include "mlir/Dialect/Arith/IR/Arith.h"
16#include "mlir/Dialect/Func/IR/FuncOps.h"
17#include "mlir/Dialect/SCF/IR/SCF.h"
18#include "mlir/Dialect/SMT/IR/SMTOps.h"
19#include "mlir/Dialect/SMT/IR/SMTTypes.h"
20#include "mlir/IR/ValueRange.h"
21#include "mlir/Pass/Pass.h"
22#include "mlir/Transforms/DialectConversion.h"
23#include "llvm/ADT/SmallVector.h"
26#define GEN_PASS_DEF_CONVERTVERIFTOSMT
27#include "circt/Conversion/Passes.h.inc"
45 matchAndRewrite(verif::AssertOp op, OpAdaptor adaptor,
46 ConversionPatternRewriter &rewriter)
const override {
47 Value cond = typeConverter->materializeTargetConversion(
48 rewriter, op.getLoc(), smt::BoolType::get(getContext()),
49 adaptor.getProperty());
50 Value notCond = smt::NotOp::create(rewriter, op.getLoc(), cond);
51 rewriter.replaceOpWithNewOp<smt::AssertOp>(op, notCond);
61 matchAndRewrite(verif::AssumeOp op, OpAdaptor adaptor,
62 ConversionPatternRewriter &rewriter)
const override {
63 Value cond = typeConverter->materializeTargetConversion(
64 rewriter, op.getLoc(), smt::BoolType::get(getContext()),
65 adaptor.getProperty());
66 rewriter.replaceOpWithNewOp<smt::AssertOp>(op, cond);
71template <
typename OpTy>
76 using ConversionPattern::typeConverter;
78 createOutputsDifferentOps(Operation *firstOutputs, Operation *secondOutputs,
79 Location &loc, ConversionPatternRewriter &rewriter,
80 SmallVectorImpl<Value> &outputsDifferent)
const {
85 for (
auto [out1, out2] :
86 llvm::zip(firstOutputs->getOperands(), secondOutputs->getOperands())) {
87 Value o1 = typeConverter->materializeTargetConversion(
88 rewriter, loc, typeConverter->convertType(out1.getType()), out1);
89 Value o2 = typeConverter->materializeTargetConversion(
90 rewriter, loc, typeConverter->convertType(out1.getType()), out2);
91 outputsDifferent.emplace_back(
92 smt::DistinctOp::create(rewriter, loc, o1, o2));
96 void replaceOpWithSatCheck(OpTy &op, Location &loc,
97 ConversionPatternRewriter &rewriter,
98 smt::SolverOp &solver)
const {
103 if (op.getNumResults() == 0) {
104 auto checkOp = smt::CheckOp::create(rewriter, loc, TypeRange{});
105 rewriter.createBlock(&
checkOp.getSatRegion());
106 smt::YieldOp::create(rewriter, loc);
107 rewriter.createBlock(&
checkOp.getUnknownRegion());
108 smt::YieldOp::create(rewriter, loc);
109 rewriter.createBlock(&
checkOp.getUnsatRegion());
110 smt::YieldOp::create(rewriter, loc);
111 rewriter.setInsertionPointAfter(
checkOp);
112 smt::YieldOp::create(rewriter, loc);
115 rewriter.eraseOp(op);
118 arith::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
false));
120 arith::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
true));
121 auto checkOp = smt::CheckOp::create(rewriter, loc, rewriter.getI1Type());
122 rewriter.createBlock(&
checkOp.getSatRegion());
123 smt::YieldOp::create(rewriter, loc, falseVal);
124 rewriter.createBlock(&
checkOp.getUnknownRegion());
125 smt::YieldOp::create(rewriter, loc, falseVal);
126 rewriter.createBlock(&
checkOp.getUnsatRegion());
127 smt::YieldOp::create(rewriter, loc, trueVal);
128 rewriter.setInsertionPointAfter(
checkOp);
129 smt::YieldOp::create(rewriter, loc,
checkOp->getResults());
131 rewriter.replaceOp(op, solver->getResults());
141struct LogicEquivalenceCheckingOpConversion
142 : CircuitRelationCheckOpConversion<verif::LogicEquivalenceCheckingOp> {
143 using CircuitRelationCheckOpConversion<
144 verif::LogicEquivalenceCheckingOp>::CircuitRelationCheckOpConversion;
147 matchAndRewrite(verif::LogicEquivalenceCheckingOp op, OpAdaptor adaptor,
148 ConversionPatternRewriter &rewriter)
const override {
149 Location loc = op.getLoc();
150 auto *firstOutputs = adaptor.getFirstCircuit().front().getTerminator();
151 auto *secondOutputs = adaptor.getSecondCircuit().front().getTerminator();
153 auto hasNoResult = op.getNumResults() == 0;
155 if (firstOutputs->getNumOperands() == 0) {
158 rewriter.eraseOp(op);
160 Value trueVal = arith::ConstantOp::create(rewriter, loc,
161 rewriter.getBoolAttr(
true));
162 rewriter.replaceOp(op, trueVal);
169 smt::SolverOp solver;
171 solver = smt::SolverOp::create(rewriter, loc, TypeRange{}, ValueRange{});
173 solver = smt::SolverOp::create(rewriter, loc, rewriter.getI1Type(),
175 rewriter.createBlock(&solver.getBodyRegion());
178 if (failed(rewriter.convertRegionTypes(&adaptor.getFirstCircuit(),
181 if (failed(rewriter.convertRegionTypes(&adaptor.getSecondCircuit(),
186 SmallVector<Value> inputs;
187 for (
auto arg : adaptor.getFirstCircuit().getArguments())
188 inputs.push_back(smt::DeclareFunOp::create(rewriter, loc, arg.getType()));
197 rewriter.mergeBlocks(&adaptor.getFirstCircuit().front(), solver.getBody(),
199 rewriter.mergeBlocks(&adaptor.getSecondCircuit().front(), solver.getBody(),
201 rewriter.setInsertionPointToEnd(solver.getBody());
204 SmallVector<Value> outputsDifferent;
205 createOutputsDifferentOps(firstOutputs, secondOutputs, loc, rewriter,
208 rewriter.eraseOp(firstOutputs);
209 rewriter.eraseOp(secondOutputs);
212 if (outputsDifferent.size() == 1)
213 toAssert = outputsDifferent[0];
215 toAssert = smt::OrOp::create(rewriter, loc, outputsDifferent);
217 smt::AssertOp::create(rewriter, loc, toAssert);
220 replaceOpWithSatCheck(op, loc, rewriter, solver);
225struct RefinementCheckingOpConversion
226 : CircuitRelationCheckOpConversion<verif::RefinementCheckingOp> {
227 using CircuitRelationCheckOpConversion<
228 verif::RefinementCheckingOp>::CircuitRelationCheckOpConversion;
231 matchAndRewrite(verif::RefinementCheckingOp op, OpAdaptor adaptor,
232 ConversionPatternRewriter &rewriter)
const override {
236 SmallVector<Value> srcNonDetValues;
238 for (
auto ndOp : op.getFirstCircuit().getOps<smt::DeclareFunOp>()) {
239 if (!isa<smt::IntType, smt::BoolType, smt::BitVectorType>(
241 ndOp.emitError(
"Uninterpreted function of non-primitive type cannot be "
245 srcNonDetValues.push_back(ndOp.getResult());
250 if (srcNonDetValues.empty()) {
254 auto eqOp = verif::LogicEquivalenceCheckingOp::create(
255 rewriter, op.getLoc(), op.getNumResults() != 0);
256 rewriter.moveBlockBefore(&op.getFirstCircuit().front(),
257 &eqOp.getFirstCircuit(),
258 eqOp.getFirstCircuit().end());
259 rewriter.moveBlockBefore(&op.getSecondCircuit().front(),
260 &eqOp.getSecondCircuit(),
261 eqOp.getSecondCircuit().end());
262 rewriter.replaceOp(op, eqOp);
266 Location loc = op.getLoc();
267 auto *firstOutputs = adaptor.getFirstCircuit().front().getTerminator();
268 auto *secondOutputs = adaptor.getSecondCircuit().front().getTerminator();
270 auto hasNoResult = op.getNumResults() == 0;
272 if (firstOutputs->getNumOperands() == 0) {
275 rewriter.eraseOp(op);
277 Value trueVal = arith::ConstantOp::create(rewriter, loc,
278 rewriter.getBoolAttr(
true));
279 rewriter.replaceOp(op, trueVal);
286 smt::SolverOp solver;
288 solver = smt::SolverOp::create(rewriter, loc, TypeRange{}, ValueRange{});
290 solver = smt::SolverOp::create(rewriter, loc, rewriter.getI1Type(),
292 rewriter.createBlock(&solver.getBodyRegion());
295 if (failed(rewriter.convertRegionTypes(&adaptor.getFirstCircuit(),
298 if (failed(rewriter.convertRegionTypes(&adaptor.getSecondCircuit(),
303 SmallVector<Value> inputs;
304 for (
auto arg : adaptor.getFirstCircuit().getArguments())
305 inputs.push_back(smt::DeclareFunOp::create(rewriter, loc, arg.getType()));
308 rewriter.mergeBlocks(&adaptor.getSecondCircuit().front(), solver.getBody(),
310 rewriter.setInsertionPointToEnd(solver.getBody());
314 auto forallOp = smt::ForallOp::create(
315 rewriter, op.getLoc(), TypeRange(srcNonDetValues),
316 [&](OpBuilder &builder,
auto, ValueRange args) -> Value {
318 Block *body = builder.getBlock();
319 rewriter.mergeBlocks(&adaptor.getFirstCircuit().front(), body,
324 for (
auto [freeVar, boundVar] :
llvm::zip(srcNonDetValues, args))
325 rewriter.replaceOp(freeVar.getDefiningOp(), boundVar);
328 rewriter.setInsertionPointToEnd(body);
329 SmallVector<Value> outputsDifferent;
330 createOutputsDifferentOps(firstOutputs, secondOutputs, loc, rewriter,
332 if (outputsDifferent.size() == 1)
333 return outputsDifferent[0];
335 return rewriter.createOrFold<smt::OrOp>(loc, outputsDifferent);
338 rewriter.eraseOp(firstOutputs);
339 rewriter.eraseOp(secondOutputs);
342 rewriter.setInsertionPointAfter(forallOp);
343 smt::AssertOp::create(rewriter, op.getLoc(), forallOp.getResult());
346 replaceOpWithSatCheck(op, loc, rewriter, solver);
353struct VerifBoundedModelCheckingOpConversion
357 VerifBoundedModelCheckingOpConversion(
359 bool risingClocksOnly, SmallVectorImpl<Operation *> &propertylessBMCOps)
361 risingClocksOnly(risingClocksOnly),
362 propertylessBMCOps(propertylessBMCOps) {}
364 matchAndRewrite(verif::BoundedModelCheckingOp op, OpAdaptor adaptor,
365 ConversionPatternRewriter &rewriter)
const override {
366 Location loc = op.getLoc();
368 if (std::find(propertylessBMCOps.begin(), propertylessBMCOps.end(), op) !=
369 propertylessBMCOps.end()) {
374 arith::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
true));
375 rewriter.replaceOp(op, trueVal);
379 SmallVector<Type> oldLoopInputTy(op.getLoop().getArgumentTypes());
380 SmallVector<Type> oldCircuitInputTy(op.getCircuit().getArgumentTypes());
384 SmallVector<Type> loopInputTy, circuitInputTy, initOutputTy,
386 if (failed(typeConverter->convertTypes(oldLoopInputTy, loopInputTy)))
388 if (failed(typeConverter->convertTypes(oldCircuitInputTy, circuitInputTy)))
390 if (failed(typeConverter->convertTypes(
391 op.getInit().front().back().getOperandTypes(), initOutputTy)))
393 if (failed(typeConverter->convertTypes(
394 op.getCircuit().front().back().getOperandTypes(), circuitOutputTy)))
396 if (failed(rewriter.convertRegionTypes(&op.getInit(), *typeConverter)))
398 if (failed(rewriter.convertRegionTypes(&op.getLoop(), *typeConverter)))
400 if (failed(rewriter.convertRegionTypes(&op.getCircuit(), *typeConverter)))
403 unsigned numRegs = op.getNumRegs();
404 auto initialValues = op.getInitialValues();
406 auto initFuncTy = rewriter.getFunctionType({}, initOutputTy);
409 auto loopFuncTy = rewriter.getFunctionType(loopInputTy, initOutputTy);
411 rewriter.getFunctionType(circuitInputTy, circuitOutputTy);
413 func::FuncOp initFuncOp, loopFuncOp, circuitFuncOp;
416 OpBuilder::InsertionGuard guard(rewriter);
417 rewriter.setInsertionPointToEnd(
418 op->getParentOfType<ModuleOp>().getBody());
419 initFuncOp = func::FuncOp::create(rewriter, loc,
420 names.newName(
"bmc_init"), initFuncTy);
421 rewriter.inlineRegionBefore(op.getInit(), initFuncOp.getFunctionBody(),
423 loopFuncOp = func::FuncOp::create(rewriter, loc,
424 names.newName(
"bmc_loop"), loopFuncTy);
425 rewriter.inlineRegionBefore(op.getLoop(), loopFuncOp.getFunctionBody(),
427 circuitFuncOp = func::FuncOp::create(
428 rewriter, loc, names.newName(
"bmc_circuit"), circuitFuncTy);
429 rewriter.inlineRegionBefore(op.getCircuit(),
430 circuitFuncOp.getFunctionBody(),
431 circuitFuncOp.end());
432 auto funcOps = {&initFuncOp, &loopFuncOp, &circuitFuncOp};
434 auto outputTys = {initOutputTy, initOutputTy, circuitOutputTy};
435 for (
auto [funcOp, outputTy] :
llvm::zip(funcOps, outputTys)) {
436 auto operands = funcOp->getBody().front().back().getOperands();
437 rewriter.eraseOp(&funcOp->getFunctionBody().front().back());
438 rewriter.setInsertionPointToEnd(&funcOp->getBody().front());
439 SmallVector<Value> toReturn;
440 for (
unsigned i = 0; i < outputTy.size(); ++i)
441 toReturn.push_back(typeConverter->materializeTargetConversion(
442 rewriter, loc, outputTy[i], operands[i]));
443 func::ReturnOp::create(rewriter, loc, toReturn);
447 auto solver = smt::SolverOp::create(rewriter, loc, rewriter.getI1Type(),
449 rewriter.createBlock(&solver.getBodyRegion());
452 ValueRange initVals =
453 func::CallOp::create(rewriter, loc, initFuncOp)->getResults();
456 smt::PushOp::create(rewriter, loc, 1);
461 size_t initIndex = 0;
462 SmallVector<Value> inputDecls;
463 SmallVector<int> clockIndexes;
464 for (
auto [curIndex, oldTy, newTy] :
465 llvm::enumerate(oldCircuitInputTy, circuitInputTy)) {
466 if (isa<seq::ClockType>(oldTy)) {
467 inputDecls.push_back(initVals[initIndex++]);
468 clockIndexes.push_back(curIndex);
471 if (curIndex >= oldCircuitInputTy.size() - numRegs) {
473 initialValues[curIndex - oldCircuitInputTy.size() + numRegs];
474 if (
auto initIntAttr = dyn_cast<IntegerAttr>(initVal)) {
475 const auto &cstInt = initIntAttr.getValue();
476 assert(cstInt.getBitWidth() ==
477 cast<smt::BitVectorType>(newTy).getWidth() &&
478 "Width mismatch between initial value and target type");
479 inputDecls.push_back(
480 smt::BVConstantOp::create(rewriter, loc, cstInt));
484 inputDecls.push_back(smt::DeclareFunOp::create(rewriter, loc, newTy));
487 auto numStateArgs = initVals.size() - initIndex;
489 for (; initIndex < initVals.size(); ++initIndex)
490 inputDecls.push_back(initVals[initIndex]);
493 arith::ConstantOp::create(rewriter, loc, rewriter.getI32IntegerAttr(0));
495 arith::ConstantOp::create(rewriter, loc, rewriter.getI32IntegerAttr(1));
497 arith::ConstantOp::create(rewriter, loc, adaptor.getBoundAttr());
499 arith::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
false));
501 arith::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(
true));
502 inputDecls.push_back(constFalse);
507 auto forOp = scf::ForOp::create(
508 rewriter, loc, lowerBound, upperBound, step, inputDecls,
509 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
511 smt::PopOp::create(builder, loc, 1);
512 smt::PushOp::create(builder, loc, 1);
515 ValueRange circuitCallOuts =
516 func::CallOp::create(
517 builder, loc, circuitFuncOp,
518 iterArgs.take_front(circuitFuncOp.getNumArguments()))
525 auto insideForPoint = builder.saveInsertionPoint();
529 auto ignoreAssertionsUntil =
530 op->getAttrOfType<IntegerAttr>(
"ignore_asserts_until");
531 if (ignoreAssertionsUntil) {
532 auto ignoreUntilConstant = arith::ConstantOp::create(
534 rewriter.getI32IntegerAttr(
535 ignoreAssertionsUntil.getValue().getZExtValue()));
537 arith::CmpIOp::create(builder, loc, arith::CmpIPredicate::ult,
538 i, ignoreUntilConstant);
539 auto ifShouldIgnore = scf::IfOp::create(
540 builder, loc, builder.getI1Type(), shouldIgnore,
true);
542 builder.setInsertionPointToEnd(
543 &ifShouldIgnore.getThenRegion().front());
544 scf::YieldOp::create(builder, loc, ValueRange(iterArgs.back()));
545 builder.setInsertionPointToEnd(
546 &ifShouldIgnore.getElseRegion().front());
547 yieldedValue = ifShouldIgnore.getResult(0);
551 smt::CheckOp::create(rewriter, loc, builder.getI1Type());
553 OpBuilder::InsertionGuard guard(builder);
554 builder.createBlock(&
checkOp.getSatRegion());
555 smt::YieldOp::create(builder, loc, constTrue);
556 builder.createBlock(&
checkOp.getUnknownRegion());
557 smt::YieldOp::create(builder, loc, constTrue);
558 builder.createBlock(&
checkOp.getUnsatRegion());
559 smt::YieldOp::create(builder, loc, constFalse);
562 Value violated = arith::OrIOp::create(
563 builder, loc,
checkOp.getResult(0), iterArgs.back());
567 if (ignoreAssertionsUntil) {
568 scf::YieldOp::create(builder, loc, violated);
570 violated = yieldedValue;
574 builder.restoreInsertionPoint(insideForPoint);
577 SmallVector<Value> loopCallInputs;
579 for (
auto index : clockIndexes)
580 loopCallInputs.push_back(iterArgs[index]);
582 for (
auto stateArg : iterArgs.drop_back().take_back(numStateArgs))
583 loopCallInputs.push_back(stateArg);
584 ValueRange loopVals =
585 func::CallOp::create(builder, loc, loopFuncOp, loopCallInputs)
588 size_t loopIndex = 0;
590 SmallVector<Value> newDecls;
591 for (
auto [oldTy, newTy] :
592 llvm::zip(TypeRange(oldCircuitInputTy).drop_back(numRegs),
593 TypeRange(circuitInputTy).drop_back(numRegs))) {
594 if (isa<seq::ClockType>(oldTy))
595 newDecls.push_back(loopVals[loopIndex++]);
598 smt::DeclareFunOp::create(builder, loc, newTy));
605 if (clockIndexes.size() == 1) {
606 SmallVector<Value> regInputs = circuitCallOuts.take_back(numRegs);
607 if (risingClocksOnly) {
610 newDecls.append(regInputs);
612 auto clockIndex = clockIndexes[0];
613 auto oldClock = iterArgs[clockIndex];
616 auto newClock = loopVals[0];
617 auto oldClockLow = smt::BVNotOp::create(builder, loc, oldClock);
619 smt::BVAndOp::create(builder, loc, oldClockLow, newClock);
621 auto trueBV = smt::BVConstantOp::create(builder, loc, 1, 1);
623 smt::EqOp::create(builder, loc, isPosedgeBV, trueBV);
625 iterArgs.take_front(circuitFuncOp.getNumArguments())
627 SmallVector<Value> nextRegStates;
628 for (
auto [regState, regInput] :
629 llvm::zip(regStates, regInputs)) {
633 nextRegStates.push_back(smt::IteOp::create(
634 builder, loc, isPosedge, regInput, regState));
636 newDecls.append(nextRegStates);
641 for (; loopIndex < loopVals.size(); ++loopIndex)
642 newDecls.push_back(loopVals[loopIndex]);
644 newDecls.push_back(violated);
646 scf::YieldOp::create(builder, loc, newDecls);
649 Value res = arith::XOrIOp::create(rewriter, loc, forOp->getResults().back(),
651 smt::YieldOp::create(rewriter, loc, res);
652 rewriter.replaceOp(op, solver.getResults());
657 bool risingClocksOnly;
658 SmallVectorImpl<Operation *> &propertylessBMCOps;
668struct ConvertVerifToSMTPass
669 :
public circt::impl::ConvertVerifToSMTBase<ConvertVerifToSMTPass> {
671 void runOnOperation()
override;
677 bool risingClocksOnly, SmallVectorImpl<Operation *> &propertylessBMCOps) {
678 patterns.add<VerifAssertOpConversion, VerifAssumeOpConversion,
679 LogicEquivalenceCheckingOpConversion,
680 RefinementCheckingOpConversion>(converter,
682 patterns.add<VerifBoundedModelCheckingOpConversion>(
683 converter,
patterns.getContext(), names, risingClocksOnly,
687void ConvertVerifToSMTPass::runOnOperation() {
688 ConversionTarget target(getContext());
689 target.addIllegalDialect<verif::VerifDialect>();
690 target.addLegalDialect<smt::SMTDialect, arith::ArithDialect, scf::SCFDialect,
691 func::FuncDialect>();
692 target.addLegalOp<UnrealizedConversionCastOp>();
696 SymbolTable symbolTable(getOperation());
697 SmallVector<Operation *> propertylessBMCOps;
698 WalkResult assertionCheck = getOperation().walk(
700 if (
auto bmcOp = dyn_cast<verif::BoundedModelCheckingOp>(op)) {
703 auto regTypes = TypeRange(bmcOp.getCircuit().getArgumentTypes())
704 .take_back(bmcOp.getNumRegs());
705 for (
auto [regType, initVal] :
706 llvm::zip(regTypes, bmcOp.getInitialValues())) {
707 if (!isa<UnitAttr>(initVal)) {
708 if (!isa<IntegerType>(regType)) {
709 op->emitError(
"initial values are currently only supported for "
710 "registers with integer types");
711 return WalkResult::interrupt();
713 auto tyAttr = dyn_cast<TypedAttr>(initVal);
714 if (!tyAttr || tyAttr.getType() != regType) {
715 op->emitError(
"type of initial value does not match type of "
716 "initialized register");
717 return WalkResult::interrupt();
722 auto numClockArgs = 0;
723 for (
auto argType : bmcOp.getCircuit().getArgumentTypes())
724 if (isa<
seq::ClockType>(argType))
728 if (numClockArgs > 1) {
730 "only modules with one or zero clocks are currently supported");
731 return WalkResult::interrupt();
733 SmallVector<mlir::Operation *> worklist;
734 int numAssertions = 0;
735 op->walk([&](Operation *curOp) {
736 if (isa<verif::AssertOp>(curOp))
738 if (
auto inst = dyn_cast<InstanceOp>(curOp))
739 worklist.push_back(symbolTable.lookup(inst.getModuleName()));
740 if (
auto func = dyn_cast<func::CallOp>(curOp))
741 worklist.push_back(symbolTable.lookup(func.getCallee()));
745 while (!worklist.empty()) {
746 auto *
module = worklist.pop_back_val();
747 module->walk([&](Operation *curOp) {
748 if (isa<verif::AssertOp>(curOp))
750 if (
auto inst = dyn_cast<InstanceOp>(curOp))
751 worklist.push_back(symbolTable.lookup(inst.getModuleName()));
752 if (
auto func = dyn_cast<func::CallOp>(curOp))
753 worklist.push_back(symbolTable.lookup(func.getCallee()));
755 if (numAssertions > 1)
758 if (numAssertions == 0) {
759 op->emitWarning(
"no property provided to check in module - will "
760 "trivially find no violations.");
761 propertylessBMCOps.push_back(bmcOp);
763 if (numAssertions > 1) {
765 "bounded model checking problems with multiple assertions are "
767 "correctly handled - instead, you can assert the "
768 "conjunction of your assertions");
769 return WalkResult::interrupt();
772 return WalkResult::advance();
774 if (assertionCheck.wasInterrupted())
775 return signalPassFailure();
776 RewritePatternSet
patterns(&getContext());
777 TypeConverter converter;
786 risingClocksOnly, propertylessBMCOps);
788 if (failed(mlir::applyPartialConversion(getOperation(), target,
790 return signalPassFailure();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static LogicalResult checkOp(Operation *op)
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateVerifToSMTConversionPatterns(TypeConverter &converter, RewritePatternSet &patterns, Namespace &names, bool risingClocksOnly, SmallVectorImpl< Operation * > &propertylessBMCOps)
Get the Verif to SMT conversion patterns.
void populateHWToSMTTypeConverter(TypeConverter &converter)
Get the HW to SMT type conversions.