25#include "mlir/Dialect/Func/IR/FuncOps.h"
26#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
27#include "mlir/Dialect/SCF/IR/SCF.h"
28#include "mlir/IR/BuiltinTypes.h"
29#include "mlir/Pass/Pass.h"
30#include "mlir/Transforms/DialectConversion.h"
31#include "llvm/Support/MathExtras.h"
34#define GEN_PASS_DEF_LOWERLTLTOCORE
35#include "circt/Conversion/Passes.h.inc"
53 matchAndRewrite(verif::HasBeenResetOp op, OpAdaptor adaptor,
54 ConversionPatternRewriter &rewriter)
const override {
55 auto i1 = rewriter.getI1Type();
57 Value constZero = seq::createConstantInitialValue(
58 rewriter, op->getLoc(), rewriter.getIntegerAttr(i1, 0));
70 comb::OrOp::create(rewriter, op.getLoc(), adaptor.getReset(),
reg);
74 Value reset, resetval;
78 rewriter, op.getLoc(), orReset,
79 rewriter.createOrFold<seq::ToClockOp>(op.getLoc(), adaptor.getClock()),
80 rewriter.getStringAttr(
"hbr"), reset, resetval, constZero,
87 Value notReset = comb::XorOp::create(rewriter, op.getLoc(),
88 adaptor.getReset(), constOne);
95struct LTLImplicationConversion
100 matchAndRewrite(ltl::ImplicationOp op, OpAdaptor adaptor,
101 ConversionPatternRewriter &rewriter)
const override {
103 if (!isa<IntegerType>(op.getAntecedent().getType()) ||
104 !isa<IntegerType>(op.getConsequent().getType()))
107 auto loc = op.getLoc();
108 auto notA = comb::createOrFoldNot(rewriter, loc, adaptor.getAntecedent());
110 comb::OrOp::create(rewriter, loc, notA, adaptor.getConsequent());
111 rewriter.replaceOp(op, orOp);
120 matchAndRewrite(ltl::NotOp op, OpAdaptor adaptor,
121 ConversionPatternRewriter &rewriter)
const override {
123 if (!isa<IntegerType>(op.getInput().getType()))
125 auto loc = op.getLoc();
126 auto inverted = comb::createOrFoldNot(rewriter, loc, adaptor.getInput());
127 rewriter.replaceOp(op, inverted);
136 matchAndRewrite(ltl::AndOp op, OpAdaptor adaptor,
137 ConversionPatternRewriter &rewriter)
const override {
139 if (!isa<IntegerType>(op->getOperandTypes()[0]) ||
140 !isa<IntegerType>(op->getOperandTypes()[1]))
142 auto loc = op.getLoc();
145 comb::AndOp::create(rewriter, loc, adaptor.getOperands(),
false);
146 rewriter.replaceOp(op, andOp);
155 matchAndRewrite(ltl::OrOp op, OpAdaptor adaptor,
156 ConversionPatternRewriter &rewriter)
const override {
158 if (!isa<IntegerType>(op->getOperandTypes()[0]) ||
159 !isa<IntegerType>(op->getOperandTypes()[1]))
161 auto loc = op.getLoc();
163 auto orOp = comb::OrOp::create(rewriter, loc, adaptor.getOperands(),
false);
164 rewriter.replaceOp(op, orOp);
173 matchAndRewrite(ltl::IntersectOp op, OpAdaptor adaptor,
174 ConversionPatternRewriter &rewriter)
const override {
177 if (!isa<IntegerType>(op->getOperandTypes()[0]) ||
178 !isa<IntegerType>(op->getOperandTypes()[1]))
180 auto loc = op.getLoc();
183 comb::AndOp::create(rewriter, loc, adaptor.getOperands(),
false);
184 rewriter.replaceOp(op, andOp);
193 matchAndRewrite(ltl::PastOp op, OpAdaptor adaptor,
194 ConversionPatternRewriter &rewriter)
const override {
196 seq::ToClockOp::create(rewriter, op.getLoc(), adaptor.getClk());
197 Value cur = adaptor.getInput();
201 seq::ShiftRegOp::create(rewriter, op.getLoc(), op.getDelayAttr(), cur,
202 clock, ce, {}, {}, {}, {}, {});
203 rewriter.replaceOp(op, shiftreg);
215struct LowerLTLToCorePass
216 :
public circt::impl::LowerLTLToCoreBase<LowerLTLToCorePass> {
217 LowerLTLToCorePass() =
default;
218 void runOnOperation()
override;
223void LowerLTLToCorePass::runOnOperation() {
226 ConversionTarget target(getContext());
227 target.addLegalDialect<hw::HWDialect>();
228 target.addLegalDialect<comb::CombDialect>();
229 target.addLegalDialect<sv::SVDialect>();
230 target.addLegalDialect<seq::SeqDialect>();
231 target.addLegalDialect<ltl::LTLDialect>();
232 target.addLegalDialect<verif::VerifDialect>();
233 target.addIllegalOp<verif::HasBeenResetOp>();
234 target.addIllegalOp<ltl::PastOp>();
236 auto isLegal = [](Operation *op) {
237 auto hasNonAssertUsers = std::any_of(
238 op->getUsers().begin(), op->getUsers().end(), [](Operation *user) {
239 return !isa<verif::AssertOp, verif::ClockedAssertOp>(user);
241 auto hasIntegerResultTypes =
242 std::all_of(op->getResultTypes().begin(), op->getResultTypes().end(),
243 [](Type type) { return isa<IntegerType>(type); });
246 if (hasNonAssertUsers && !hasIntegerResultTypes)
251 op->getOperands().begin(), op->getOperands().end(),
252 [](Value operand) { return !isa<IntegerType>(operand.getType()); });
254 target.addDynamicallyLegalOp<ltl::ImplicationOp>(isLegal);
255 target.addDynamicallyLegalOp<ltl::NotOp>(isLegal);
256 target.addDynamicallyLegalOp<ltl::AndOp>(isLegal);
257 target.addDynamicallyLegalOp<ltl::OrOp>(isLegal);
258 target.addDynamicallyLegalOp<ltl::IntersectOp>(isLegal);
261 mlir::TypeConverter converter;
264 converter.addConversion([](IntegerType type) {
return type; });
265 converter.addConversion([](ltl::PropertyType type) {
266 return IntegerType::get(type.getContext(), 1);
268 converter.addConversion([](ltl::SequenceType type) {
269 return IntegerType::get(type.getContext(), 1);
273 converter.addTargetMaterialization(
274 [&](mlir::OpBuilder &builder, mlir::Type resultType,
275 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
276 if (inputs.size() != 1)
278 return UnrealizedConversionCastOp::create(builder, loc, resultType,
283 converter.addSourceMaterialization(
284 [&](mlir::OpBuilder &builder, mlir::Type resultType,
285 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
286 if (inputs.size() != 1)
288 return UnrealizedConversionCastOp::create(builder, loc, resultType,
294 RewritePatternSet
patterns(&getContext());
295 patterns.add<HasBeenResetOpConversion, LTLImplicationConversion,
296 LTLNotConversion, LTLAndOpConversion, LTLOrOpConversion,
297 LTLIntersectOpConversion, LTLPastOpConversion>(
301 applyPartialConversion(getOperation(), target, std::move(
patterns))))
302 return signalPassFailure();
305 getOperation().walk([&](Operation *op) {
306 if (!isa<verif::AssertOp, verif::ClockedAssertOp>(op))
308 Value prop = op->getOperand(0);
309 if (
auto cast = prop.getDefiningOp<UnrealizedConversionCastOp>()) {
312 if (auto intType = dyn_cast<IntegerType>(cast.getOperandTypes()[0]);
313 intType && intType.getWidth() == 1)
314 op->setOperand(0, cast.getInputs()[0]);
321 return std::make_unique<LowerLTLToCorePass>();
Instantiate one of these and use it to build typed backedges.
Backedge get(mlir::Type resultType, mlir::LocationAttr optionalLoc={})
Create a typed backedge.
Backedge is a wrapper class around a Value.
create(cls, result_type, reset=None, reset_value=None, name=None, sym_name=None, **kwargs)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createLowerLTLToCorePass()
reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)