15#include "mlir/IR/Builders.h"
16#include "mlir/IR/OpImplementation.h"
17#include "mlir/IR/PatternMatch.h"
18#include "mlir/IR/SymbolTable.h"
19#include "mlir/IR/TypeRange.h"
20#include "mlir/Interfaces/FunctionImplementation.h"
21#include "mlir/Interfaces/SideEffectInterfaces.h"
22#include "llvm/ADT/MapVector.h"
30 case ltl::ClockEdge::Pos:
31 return ClockEdge::Pos;
32 case ltl::ClockEdge::Neg:
33 return ClockEdge::Neg;
34 case ltl::ClockEdge::Both:
35 return ClockEdge::Both;
37 llvm_unreachable(
"Unknown event control kind");
44OpFoldResult HasBeenResetOp::fold(FoldAdaptor adaptor) {
48 if (adaptor.getReset())
49 return BoolAttr::get(getContext(),
false);
53 if (!adaptor.getAsync() && adaptor.getClock())
54 return BoolAttr::get(getContext(),
false);
65template <
typename TargetOp,
typename Op>
66static LogicalResult
canonicalize(Op op, PatternRewriter &rewriter) {
68 Value
property = op.getProperty();
69 auto clockOp =
property.getDefiningOp<ltl::ClockOp>();
75 rewriter.replaceOpWithNewOp<TargetOp>(
77 clockOp.getClock(), op.getEnable(), op.getLabelAttr());
84LogicalResult AssertOp::canonicalize(AssertOp op, PatternRewriter &rewriter) {
85 return AssertLikeOp::canonicalize<ClockedAssertOp>(op, rewriter);
88LogicalResult AssumeOp::canonicalize(AssumeOp op, PatternRewriter &rewriter) {
89 return AssertLikeOp::canonicalize<ClockedAssumeOp>(op, rewriter);
92LogicalResult CoverOp::canonicalize(CoverOp op, PatternRewriter &rewriter) {
93 return AssertLikeOp::canonicalize<ClockedCoverOp>(op, rewriter);
100LogicalResult LogicEquivalenceCheckingOp::verifyRegions() {
101 if (getFirstCircuit().getArgumentTypes() !=
102 getSecondCircuit().getArgumentTypes())
103 return emitOpError() <<
"block argument types of both regions must match";
104 if (getFirstCircuit().front().getTerminator()->getOperandTypes() !=
105 getSecondCircuit().front().getTerminator()->getOperandTypes())
107 <<
"types of the yielded values of both regions must match";
116LogicalResult BoundedModelCheckingOp::verifyRegions() {
117 if (!getInit().getArgumentTypes().
empty())
118 return emitOpError() <<
"init region must have no arguments";
119 auto *initYieldOp = getInit().front().getTerminator();
120 auto *loopYieldOp = getLoop().front().getTerminator();
121 if (initYieldOp->getOperandTypes() != loopYieldOp->getOperandTypes())
123 <<
"init and loop regions must yield the same types of values";
124 if (initYieldOp->getOperandTypes() != getLoop().front().getArgumentTypes())
126 <<
"loop region arguments must match the types of the values "
127 "yielded by the init and loop regions";
128 size_t totalClocks = 0;
129 auto circuitArgTy = getCircuit().getArgumentTypes();
130 for (
auto input : circuitArgTy)
131 if (isa<
seq::ClockType>(input))
133 auto initYields = initYieldOp->getOperands();
135 if (initYields.size() < totalClocks)
137 <<
"init and loop regions must yield at least as many clock "
138 "values as there are clock arguments to the circuit region";
139 for (
size_t i = 0; i < totalClocks; i++) {
140 if (!isa<seq::ClockType>(initYieldOp->getOperand(i).getType()))
142 <<
"init and loop regions must yield as many clock values as "
143 "there are clock arguments in the circuit region "
144 "before any other values";
146 if (getNumRegs() > 0 && totalClocks == 0)
147 return emitOpError(
"num_regs is non-zero, but the circuit region has no "
148 "clock inputs to clock the registers");
149 auto initialValues = getInitialValues();
150 if (initialValues.size() != getNumRegs()) {
152 <<
"number of initial values must match the number of registers";
154 for (
auto attr : initialValues) {
155 if (!isa<IntegerAttr, UnitAttr>(attr))
157 <<
"initial values must be integer or unit attributes";
166#define GET_OP_CLASSES
167#include "circt/Dialect/Verif/Verif.cpp.inc"
static InstancePath empty
static ClockEdge ltlToVerifClockEdge(ltl::ClockEdge ce)
static LogicalResult canonicalize(Op op, PatternRewriter &rewriter)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.