CIRCT  20.0.0git
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 
23 using namespace circt;
24 using 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.
Definition: DebugAnalysis.h:21