Loading [MathJax]/extensions/tex2jax.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
21#include "mlir/Pass/Pass.h"
22#include "llvm/ADT/TypeSwitch.h"
23
24namespace circt {
25namespace verif {
26#define GEN_PASS_DEF_VERIFYCLOCKEDASSERTLIKEPASS
27#include "circt/Dialect/Verif/Passes.h.inc"
28} // namespace verif
29} // namespace circt
30
31using namespace circt;
32using namespace verif;
33
34namespace {
35// Verify function for clocked assert / assume / cover ops.
36// This checks that they do not contiain any nested clocks or disable operations
37// Clocked assertlike ops are a simple form of assertions that only
38// contain one clock and one disable condition.
39struct VerifyClockedAssertLikePass
40 : verif::impl::VerifyClockedAssertLikePassBase<
41 VerifyClockedAssertLikePass> {
42private:
43 // Used to perform a DFS search through the module to visit all operands
44 // before they are used
45 llvm::SmallMapVector<Operation *, OperandRange::iterator, 16> worklist;
46
47 // Keeps track of operations that have been visited
48 llvm::DenseSet<Operation *> handledOps;
49
50public:
51 void runOnOperation() override;
52
53private:
54 void verify(Operation *clockedAssertLikeOp) {
55
56 Operation *property = clockedAssertLikeOp->getOperand(0).getDefiningOp();
57
58 if (!property)
59 return;
60
61 // Fill in our worklist
62 worklist.insert({property, property->operand_begin()});
63
64 // Process the elements in our worklist
65 while (!worklist.empty()) {
66 auto &[op, operandIt] = worklist.back();
67
68 if (operandIt == op->operand_end()) {
69 // Check that our property doesn't contain any illegal ops
70 if (isa<ltl::ClockOp>(op)) {
71 op->emitError("Nested clock or disable operations are not "
72 "allowed for clock_assertlike operations.");
73 return;
74 }
75
76 // Record that our op has been visited
77 handledOps.insert(op);
78 worklist.pop_back();
79 continue;
80 }
81
82 // Send the operands of our op to the worklist in case they are still
83 // un-visited
84 Value operand = *(operandIt++);
85 auto *defOp = operand.getDefiningOp();
86
87 // Make sure that we don't visit the same operand twice
88 if (!defOp || handledOps.contains(defOp))
89 continue;
90
91 worklist.insert({defOp, defOp->operand_begin()});
92 }
93
94 // Clear worklist and such
95 worklist.clear();
96 handledOps.clear();
97 }
98};
99} // namespace
100
101void VerifyClockedAssertLikePass::runOnOperation() {
102 getOperation()->walk([&](Operation *op) {
103 llvm::TypeSwitch<Operation *, void>(op)
104 .Case<verif::ClockedAssertOp, verif::ClockedAssumeOp,
105 verif::ClockedCoverOp>([&](auto clockedOp) { verify(clockedOp); })
106 .Default([&](auto) {});
107 });
108}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition verif.py:1