CIRCT  20.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  if (!property)
60  return;
61 
62  // Fill in our worklist
63  worklist.insert({property, property->operand_begin()});
64 
65  // Process the elements in our worklist
66  while (!worklist.empty()) {
67  auto &[op, operandIt] = worklist.back();
68 
69  if (operandIt == op->operand_end()) {
70  // Check that our property doesn't contain any illegal ops
71  if (isa<ltl::ClockOp>(op)) {
72  op->emitError("Nested clock or disable operations are not "
73  "allowed for clock_assertlike operations.");
74  return;
75  }
76 
77  // Record that our op has been visited
78  handledOps.insert(op);
79  worklist.pop_back();
80  continue;
81  }
82 
83  // Send the operands of our op to the worklist in case they are still
84  // un-visited
85  Value operand = *(operandIt++);
86  auto *defOp = operand.getDefiningOp();
87 
88  // Make sure that we don't visit the same operand twice
89  if (!defOp || handledOps.contains(defOp))
90  continue;
91 
92  worklist.insert({defOp, defOp->operand_begin()});
93  }
94 
95  // Clear worklist and such
96  worklist.clear();
97  handledOps.clear();
98  }
99 };
100 } // namespace
101 
102 void VerifyClockedAssertLikePass::runOnOperation() {
103  getOperation()->walk([&](Operation *op) {
104  llvm::TypeSwitch<Operation *, void>(op)
105  .Case<verif::ClockedAssertOp, verif::ClockedAssumeOp,
106  verif::ClockedCoverOp>([&](auto clockedOp) { verify(clockedOp); })
107  .Default([&](auto) {});
108  });
109 }
110 
111 std::unique_ptr<mlir::Pass> circt::verif::createVerifyClockedAssertLikePass() {
112  return std::make_unique<VerifyClockedAssertLikePass>();
113 }
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Definition: SVOps.cpp:2452
std::unique_ptr< mlir::Pass > createVerifyClockedAssertLikePass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Definition: verif.py:1