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"
26using namespace firrtl;
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();
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>())
88 if (firrtl::type_isa<ResetType, AsyncResetType>(
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>() ||
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();
bool anyInstanceInDesign(igraph::ModuleOpInterface op)
Return true if any instance of this module is within (or transitively within) the design.
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...