CIRCT 20.0.0git
Loading...
Searching...
No Matches
FIRParserAsserts.cpp
Go to the documentation of this file.
1//===- FIRParserAsserts.cpp - Printf-encoded assert handling --------------===//
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//
9// This file implements handling of printf-encoded verification operations
10// embedded in when blocks.
11//
12// While no longer supported, this file retains enough to classify printf
13// operations so that we may error on their unsupported use.
14//
15//===----------------------------------------------------------------------===//
16
17#include "FIRAnnotations.h"
19#include "circt/Support/LLVM.h"
20#include "mlir/IR/ImplicitLocOpBuilder.h"
21#include "llvm/ADT/TypeSwitch.h"
22
23using namespace circt;
24using namespace firrtl;
25
26/// Chisel has a tendency to emit complex assert/assume/cover statements encoded
27/// as print operations with special formatting and metadata embedded in the
28/// message literal. One variant looks like:
29///
30/// when invCond:
31/// printf(clock, UInt<1>(1), "...[verif-library-assert]...")
32/// stop(clock, UInt<1>(1), 1)
33///
34/// Depending on the nature the verification operation, the `stop` may be
35/// optional. The Scala implementation simply removes all `stop`s that have the
36/// same condition as the printf.
37///
38/// This is no longer supported.
39/// This method retains enough support to accurately detect when this is used
40/// and returns whether this is a recognized (legacy) printf+when-encoded verif.
42 auto whenStmt = dyn_cast<WhenOp>(printOp->getParentOp());
43
44 // If the parent of printOp is not when, printOp doesn't encode a
45 // verification.
46 if (!whenStmt)
47 return false;
48
49 // The when blocks we're interested in don't have an else region.
50 if (whenStmt.hasElseRegion())
51 return false;
52
53 // The when blocks we're interested in contain a `PrintFOp` and an optional
54 // `StopOp` with the same clock and condition as the print.
55 Block &thenBlock = whenStmt.getThenBlock();
56 auto opIt = std::next(printOp->getIterator());
57 auto opEnd = thenBlock.end();
58
59 // Detect if we're dealing with a verification statement.
60 auto fmt = printOp.getFormatString();
61 if (!(fmt.contains("[verif-library-assert]") ||
62 fmt.contains("[verif-library-assume]") ||
63 fmt.contains("[verif-library-cover]") || fmt.starts_with("assert:") ||
64 fmt.starts_with("assume:") || fmt.starts_with("cover:") ||
65 fmt.starts_with("assertNotX:") || fmt.starts_with("Assertion failed")))
66 return false;
67
68 // optional `stop(clock, enable, ...)`
69 //
70 // NOTE: This code is retained as-is from when these were fully supported,
71 // to maintain the classification portion. Previously this code would then
72 // delete the "stop" operation, which it no longer does.
73 if (opIt != opEnd) {
74 auto stopOp = dyn_cast<StopOp>(*opIt++);
75 if (!stopOp || opIt != opEnd || stopOp.getClock() != printOp.getClock() ||
76 stopOp.getCond() != printOp.getCond())
77 return false;
78 // (This code used to erase the stop operation here)
79 }
80 return true;
81}
bool isRecognizedPrintfEncodedVerif(PrintFOp printOp)
Classifier for legacy verif intent captured in printf + when's.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.