CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
22#include "mlir/Pass/Pass.h"
23#include "llvm/ADT/TypeSwitch.h"
24
25namespace circt {
26namespace verif {
27#define GEN_PASS_DEF_VERIFYCLOCKEDASSERTLIKEPASS
28#include "circt/Dialect/Verif/Passes.h.inc"
29} // namespace verif
30} // namespace circt
31
32using namespace circt;
33using namespace verif;
34
35namespace {
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.
40struct VerifyClockedAssertLikePass
41 : verif::impl::VerifyClockedAssertLikePassBase<
42 VerifyClockedAssertLikePass> {
43private:
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
51public:
52 void runOnOperation() override;
53
54private:
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
102void 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}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition verif.py:1