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);
100template <
typename OpTy>
102 if (op.getFirstCircuit().getArgumentTypes() !=
103 op.getSecondCircuit().getArgumentTypes())
104 return op.emitOpError()
105 <<
"block argument types of both regions must match";
106 if (op.getFirstCircuit().front().getTerminator()->getOperandTypes() !=
107 op.getSecondCircuit().front().getTerminator()->getOperandTypes())
108 return op.emitOpError()
109 <<
"types of the yielded values of both regions must match";
118LogicalResult LogicEquivalenceCheckingOp::verifyRegions() {
126LogicalResult RefinementCheckingOp::verifyRegions() {
134LogicalResult BoundedModelCheckingOp::verifyRegions() {
135 if (!getInit().getArgumentTypes().
empty())
136 return emitOpError() <<
"init region must have no arguments";
137 auto *initYieldOp = getInit().front().getTerminator();
138 auto *loopYieldOp = getLoop().front().getTerminator();
139 if (initYieldOp->getOperandTypes() != loopYieldOp->getOperandTypes())
141 <<
"init and loop regions must yield the same types of values";
142 if (initYieldOp->getOperandTypes() != getLoop().front().getArgumentTypes())
144 <<
"loop region arguments must match the types of the values "
145 "yielded by the init and loop regions";
146 size_t totalClocks = 0;
147 auto circuitArgTy = getCircuit().getArgumentTypes();
148 for (
auto input : circuitArgTy)
149 if (isa<
seq::ClockType>(input))
151 auto initYields = initYieldOp->getOperands();
153 if (initYields.size() < totalClocks)
155 <<
"init and loop regions must yield at least as many clock "
156 "values as there are clock arguments to the circuit region";
157 for (
size_t i = 0; i < totalClocks; i++) {
158 if (!isa<seq::ClockType>(initYieldOp->getOperand(i).getType()))
160 <<
"init and loop regions must yield as many clock values as "
161 "there are clock arguments in the circuit region "
162 "before any other values";
164 if (getNumRegs() > 0 && totalClocks == 0)
165 return emitOpError(
"num_regs is non-zero, but the circuit region has no "
166 "clock inputs to clock the registers");
167 auto initialValues = getInitialValues();
168 if (initialValues.size() != getNumRegs()) {
170 <<
"number of initial values must match the number of registers";
172 for (
auto attr : initialValues) {
173 if (!isa<IntegerAttr, UnitAttr>(attr))
175 <<
"initial values must be integer or unit attributes";
184LogicalResult SimulationOp::verifyRegions() {
185 if (getBody()->getNumArguments() != 2)
186 return emitOpError() <<
"must have two block arguments";
187 if (!isa<seq::ClockType>(getBody()->getArgument(0).getType()))
188 return emitOpError() <<
"block argument #0 must be of type `!seq.clock`";
189 if (!getBody()->getArgument(1).getType().isSignlessInteger(1))
190 return emitOpError() <<
"block argument #1 must be of type `i1`";
192 auto *yieldOp = getBody()->getTerminator();
193 if (yieldOp->getNumOperands() != 2)
194 return yieldOp->emitOpError() <<
"must have two operands";
195 if (!yieldOp->getOperand(0).getType().isSignlessInteger(1))
196 return yieldOp->emitOpError() <<
"operand #0 must be of type `i1`";
197 if (!yieldOp->getOperand(1).getType().isSignlessInteger(1))
198 return yieldOp->emitOpError() <<
"operand #1 must be of type `i1`";
203void SimulationOp::getAsmBlockArgumentNames(Region ®ion,
205 if (region.empty() || region.getNumArguments() != 2)
207 setNameFn(region.getArgument(0),
"clock");
208 setNameFn(region.getArgument(1),
"init");
215#define GET_OP_CLASSES
216#include "circt/Dialect/Verif/Verif.cpp.inc"
static InstancePath empty
static ClockEdge ltlToVerifClockEdge(ltl::ClockEdge ce)
static LogicalResult verifyCircuitRelationCheckOpRegions(OpTy &op)
static LogicalResult canonicalize(Op op, PatternRewriter &rewriter)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn