14#include "mlir/Pass/Pass.h"
15#include "llvm/ADT/APSInt.h"
19#define GEN_PASS_DEF_LINT
20#include "circt/Dialect/FIRRTL/Passes.h.inc"
35 Linter(FModuleOp fModule, InstanceInfo &instanceInfo,
36 const LintOptions &options)
37 : fModule(fModule), instanceInfo(instanceInfo), options(options){};
40 LogicalResult lint() {
42 fModule.walk<WalkOrder::PreOrder>([&](Operation *op) {
44 return WalkResult::skip();
45 if (isa<AssertOp, VerifAssertIntrinsicOp>(op))
46 if (options.lintStaticAsserts && checkAssert(op).failed())
49 if (
auto xmrDerefOp = dyn_cast<XMRDerefOp>(op))
50 if (options.lintXmrsInDesign && checkXmr(xmrDerefOp).failed())
53 return WalkResult::advance();
64 InstanceInfo &instanceInfo;
65 const LintOptions &options;
67 LogicalResult checkAssert(Operation *op) {
69 if (
auto a = dyn_cast<AssertOp>(op)) {
70 if (
auto constant = a.getEnable().getDefiningOp<firrtl::ConstantOp>())
71 if (constant.getValue().isOne()) {
72 predicate = a.getPredicate();
74 }
else if (
auto a = dyn_cast<VerifAssertIntrinsicOp>(op))
75 predicate = a.getProperty();
79 if (
auto constant = predicate.getDefiningOp<firrtl::ConstantOp>())
80 if (constant.getValue().isZero())
81 return op->emitOpError(
82 "is guaranteed to fail simulation, as the predicate is "
84 .attachNote(constant.getLoc())
85 <<
"constant defined here";
87 if (
auto reset = predicate.getDefiningOp<firrtl::AsUIntPrimOp>())
89 reset.getInput().getType()))
90 return op->emitOpError(
"is guaranteed to fail simulation, as the "
91 "predicate is a reset signal")
92 .attachNote(reset.getInput().getLoc())
93 <<
"reset signal defined here";
98 LogicalResult checkXmr(XMRDerefOp op) {
100 if (op->getParentOfType<LayerBlockOp>() ||
101 op->getParentOfType<sv::IfDefOp>())
107 if (!instanceInfo.anyInstanceInDesign(fModule))
117 auto boundInstancePortUser = [&](
auto user) {
118 auto connect = dyn_cast<MatchingConnectOp>(user);
119 if (connect &&
connect.getSrc() == op.getResult())
120 if (
auto *definingOp =
connect.getDest().getDefiningOp())
121 if (
auto instanceOp = dyn_cast<InstanceOp>(definingOp))
122 if (instanceOp->hasAttr(
"lowerToBind"))
126 if (llvm::all_of(op.getResult().getUsers(), boundInstancePortUser))
131 <<
"is in the design. (Did you forget to put it under a layer?)";
132 diag.attachNote(fModule.getLoc()) <<
"op is instantiated in this module";
138struct LintPass :
public circt::firrtl::impl::LintBase<LintPass> {
139 using LintBase::LintBase;
141 void runOnOperation()
override {
143 CircuitOp circuitOp = getOperation();
144 auto instanceInfo = getAnalysis<InstanceInfo>();
146 auto reduce = [](LogicalResult a, LogicalResult b) -> LogicalResult {
147 if (succeeded(a) && succeeded(b))
151 auto transform = [&](FModuleOp moduleOp) -> LogicalResult {
152 return Linter(moduleOp, instanceInfo,
153 {lintStaticAsserts, lintXmrsInDesign})
157 SmallVector<FModuleOp> modules(circuitOp.getOps<FModuleOp>());
160 return signalPassFailure();
162 markAllAnalysesPreserved();
false return failure()
Parse an optional keyword or string and set instance into 'result'.
connect(destination, source)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
static ResultTy transformReduce(MLIRContext *context, IterTy begin, IterTy end, ResultTy init, ReduceFuncTy reduce, TransformFuncTy transform)
Wrapper for llvm::parallelTransformReduce that performs the transform_reduce serially when MLIR multi...