CIRCT  19.0.0git
VerifyClockedAssertLike.cpp
Go to the documentation of this file.
1 //===- VerifyClockedAssertLike.cpp - Check Clocked Asserts -------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //===----------------------------------------------------------------------===//
7 //
8 // Checks that clocked assert-like ops are constructed correctly.
9 //
10 //===----------------------------------------------------------------------===//
11 
14 #include "circt/Dialect/HW/HWOps.h"
22 #include "mlir/Pass/Pass.h"
23 #include "llvm/ADT/TypeSwitch.h"
24 
25 namespace circt {
26 namespace verif {
27 #define GEN_PASS_DEF_VERIFYCLOCKEDASSERTLIKE
28 #include "circt/Dialect/Verif/Passes.h.inc"
29 } // namespace verif
30 } // namespace circt
31 
32 using namespace circt;
33 using namespace verif;
34 
35 namespace {
36 // Verify function for clocked assert / assume / cover ops.
37 // This checks that they do not contiain any nested clocks or disable operations
38 // Clocked assertlike ops are a simple form of assertions that only
39 // contain one clock and one disable condition.
40 struct VerifyClockedAssertLikePass
41  : circt::verif::impl::VerifyClockedAssertLikeBase<
42  VerifyClockedAssertLikePass> {
43 private:
44  // Used to perform a DFS search through the module to visit all operands
45  // before they are used
46  llvm::SmallMapVector<Operation *, OperandRange::iterator, 16> worklist;
47 
48  // Keeps track of operations that have been visited
49  llvm::DenseSet<Operation *> handledOps;
50 
51 public:
52  void runOnOperation() override;
53 
54 private:
55  void verify(Operation *clockedAssertLikeOp) {
56 
57  Operation *property = clockedAssertLikeOp->getOperand(0).getDefiningOp();
58 
59  // Fill in our worklist
60  worklist.insert({property, property->operand_begin()});
61 
62  // Process the elements in our worklist
63  while (!worklist.empty()) {
64  auto &[op, operandIt] = worklist.back();
65 
66  if (operandIt == op->operand_end()) {
67  // Check that our property doesn't contain any illegal ops
68  if (isa<ltl::ClockOp>(op)) {
69  op->emitError("Nested clock or disable operations are not "
70  "allowed for clock_assertlike operations.");
71  return;
72  }
73 
74  // Record that our op has been visited
75  handledOps.insert(op);
76  worklist.pop_back();
77  continue;
78  }
79 
80  // Send the operands of our op to the worklist in case they are still
81  // un-visited
82  Value operand = *(operandIt++);
83  auto *defOp = operand.getDefiningOp();
84 
85  // Make sure that we don't visit the same operand twice
86  if (!defOp || handledOps.contains(defOp))
87  continue;
88 
89  worklist.insert({defOp, defOp->operand_begin()});
90  }
91 
92  // Clear worklist and such
93  worklist.clear();
94  handledOps.clear();
95  }
96 };
97 } // namespace
98 
99 void VerifyClockedAssertLikePass::runOnOperation() {
100  getOperation()->walk([&](Operation *op) {
101  llvm::TypeSwitch<Operation *, void>(op)
102  .Case<verif::ClockedAssertOp, verif::ClockedAssumeOp,
103  verif::ClockedCoverOp>([&](auto clockedOp) { verify(clockedOp); })
104  .Default([&](auto) {});
105  });
106 }
107 
108 std::unique_ptr<mlir::Pass> circt::verif::createVerifyClockedAssertLikePass() {
109  return std::make_unique<VerifyClockedAssertLikePass>();
110 }
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Definition: SVOps.cpp:2443
std::unique_ptr< mlir::Pass > createVerifyClockedAssertLikePass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Definition: verif.py:1