Loading [MathJax]/jax/output/HTML-CSS/config.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LowerSymbolicValues.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
12
13using namespace circt;
14using namespace mlir;
15using namespace verif;
16using namespace hw;
17
18namespace circt {
19namespace verif {
20#define GEN_PASS_DEF_LOWERSYMBOLICVALUESPASS
21#include "circt/Dialect/Verif/Passes.h.inc"
22} // namespace verif
23} // namespace circt
24
25namespace {
26struct LowerSymbolicValuesPass
27 : verif::impl::LowerSymbolicValuesPassBase<LowerSymbolicValuesPass> {
28 using LowerSymbolicValuesPassBase::LowerSymbolicValuesPassBase;
29 void runOnOperation() override;
30 LogicalResult lowerToExtModule();
31 void lowerToAnySeqWire();
32};
33} // namespace
34
35void LowerSymbolicValuesPass::runOnOperation() {
36 switch (mode) {
37 case SymbolicValueLowering::ExtModule:
38 if (failed(lowerToExtModule()))
39 signalPassFailure();
40 break;
41 case SymbolicValueLowering::Yosys:
42 lowerToAnySeqWire();
43 break;
44 }
45}
46
47/// Replace all `SymbolicValueOp`s with instances of corresponding extmodules.
48/// This allows tools to treat the modules as blackboxes, or definitions of the
49/// modules may be provided later by the user.
50LogicalResult LowerSymbolicValuesPass::lowerToExtModule() {
51 auto &symbolTable = getAnalysis<SymbolTable>();
52 DenseMap<Type, HWModuleExternOp> extmoduleOps;
53 auto result = getOperation().walk([&](SymbolicValueOp op) -> WalkResult {
54 // Determine the number of bits needed for the symbolic value.
55 auto numBits = hw::getBitWidth(op.getType());
56 if (numBits < 0)
57 return op.emitError() << "symbolic value bit width unknown";
58
59 // If we don't already have an extmodule for this number of bits, create
60 // one.
61 auto builder = OpBuilder::atBlockEnd(getOperation().getBody());
62 auto flatType = builder.getIntegerType(numBits);
63 auto &extmoduleOp = extmoduleOps[flatType];
64 if (!extmoduleOp) {
65 extmoduleOp = builder.create<HWModuleExternOp>(
66 op.getLoc(),
67 builder.getStringAttr(Twine("circt.symbolic_value.") +
68 Twine(numBits)),
69 PortInfo{{builder.getStringAttr("z"), flatType, ModulePort::Output}},
70 "circt_symbolic_value",
71 builder.getArrayAttr(ParamDeclAttr::get(
72 builder.getContext(), builder.getStringAttr("WIDTH"),
73 builder.getI32Type(), Attribute())));
74 symbolTable.insert(extmoduleOp);
75 }
76
77 // Instantiate the extmodule as a means of generating a symbolic value with
78 // the correct number of bits.
79 builder.setInsertionPoint(op);
80 auto instOp = builder.create<InstanceOp>(
81 op.getLoc(), extmoduleOp, builder.getStringAttr("symbolic_value"),
82 ArrayRef<Value>{},
83 builder.getArrayAttr(ParamDeclAttr::get(
84 builder.getContext(), builder.getStringAttr("WIDTH"),
85 builder.getI32Type(), builder.getI32IntegerAttr(numBits))));
86 Value value = instOp.getResult(0);
87
88 // Insert a bit cast if needed to obtain the original symbolic value's type.
89 if (op.getType() != value.getType())
90 value = builder.create<BitcastOp>(op.getLoc(), op.getType(), value);
91
92 // Replace the `verif.symbolic_value` op.
93 op.replaceAllUsesWith(value);
94 op.erase();
95 return success();
96 });
97 return failure(result.wasInterrupted());
98}
99
100/// Replace `SymbolicValueOp`s with an `(* anyseq *)` wire declaration.
101void LowerSymbolicValuesPass::lowerToAnySeqWire() {
102 getOperation().walk([&](SymbolicValueOp op) {
103 // Create a replacement wire declaration with a `(* anyseq *)` Verilog
104 // attribute.
105 OpBuilder builder(op);
106 auto wireOp = builder.create<sv::WireOp>(op.getLoc(), op.getType());
107 sv::addSVAttributes(wireOp,
108 sv::SVAttributeAttr::get(&getContext(), "anyseq"));
109
110 // Create a read from the wire and replace the `verif.symbolic_value` op.
111 Value value = builder.create<sv::ReadInOutOp>(op.getLoc(), wireOp);
112 op.replaceAllUsesWith(value);
113 op.erase();
114 });
115}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition hw.py:1
Definition verif.py:1
This holds the name, type, direction of a module's ports.