13#include "llvm/ADT/DenseSet.h"
22#define GEN_PASS_DEF_LOWERSYMBOLICVALUESPASS
23#include "circt/Dialect/Verif/Passes.h.inc"
28struct LowerSymbolicValuesPass
29 : verif::impl::LowerSymbolicValuesPassBase<LowerSymbolicValuesPass> {
30 using LowerSymbolicValuesPassBase::LowerSymbolicValuesPassBase;
31 void runOnOperation()
override;
32 LogicalResult lowerToExtModule();
33 void lowerToAnySeqWire();
34 LogicalResult lowerToHWInputs();
38void LowerSymbolicValuesPass::runOnOperation() {
40 case SymbolicValueLowering::ExtModule:
41 if (failed(lowerToExtModule()))
44 case SymbolicValueLowering::Yosys:
47 case SymbolicValueLowering::HWInput:
48 if (failed(lowerToHWInputs()))
57LogicalResult LowerSymbolicValuesPass::lowerToExtModule() {
58 auto &symbolTable = getAnalysis<SymbolTable>();
59 DenseMap<Type, HWModuleExternOp> extmoduleOps;
60 auto result = getOperation().walk([&](SymbolicValueOp op) -> WalkResult {
62 auto numBits = hw::getBitWidth(op.getType());
64 return op.emitError() <<
"symbolic value bit width unknown";
68 auto builder = OpBuilder::atBlockEnd(getOperation().getBody());
69 auto flatType = builder.getIntegerType(numBits);
70 auto &extmoduleOp = extmoduleOps[flatType];
72 extmoduleOp = HWModuleExternOp::create(
74 builder.getStringAttr(Twine(
"circt.symbolic_value.") +
77 "circt_symbolic_value",
78 builder.getArrayAttr(ParamDeclAttr::get(
79 builder.getContext(), builder.getStringAttr(
"WIDTH"),
80 builder.getI32Type(), Attribute())));
81 symbolTable.insert(extmoduleOp);
86 builder.setInsertionPoint(op);
87 auto instOp = InstanceOp::create(
88 builder, op.getLoc(), extmoduleOp,
89 builder.getStringAttr(
"symbolic_value"), ArrayRef<Value>{},
90 builder.getArrayAttr(ParamDeclAttr::get(
91 builder.getContext(), builder.getStringAttr(
"WIDTH"),
92 builder.getI32Type(), builder.getI32IntegerAttr(numBits))));
93 Value value = instOp.getResult(0);
96 if (op.getType() != value.getType())
100 op.replaceAllUsesWith(value);
104 return failure(result.wasInterrupted());
108void LowerSymbolicValuesPass::lowerToAnySeqWire() {
109 getOperation().walk([&](SymbolicValueOp op) {
112 OpBuilder builder(op);
114 sv::NetType::get(op.getType()));
115 sv::addSVAttributes(wireOp,
116 sv::SVAttributeAttr::get(&getContext(),
"anyseq"));
120 op.replaceAllUsesWith(value);
126LogicalResult LowerSymbolicValuesPass::lowerToHWInputs() {
127 auto module = getOperation();
128 DenseSet<StringAttr> referencedModules;
129 module.walk([&](InstanceOp op) {
130 referencedModules.insert(op.getReferencedModuleNameAttr());
133 auto result =
module.walk([&](SymbolicValueOp op) -> WalkResult {
134 if (!op->getParentOfType<HWModuleOp>())
135 return op.emitError()
136 << "cannot lower symbolic value to hw.module input outside of an "
138 return WalkResult::advance();
140 if (result.wasInterrupted())
143 for (
auto hwModule : module.getOps<HWModuleOp>()) {
144 SmallVector<SymbolicValueOp> symbolicValues;
145 hwModule.walk([&](SymbolicValueOp op) { symbolicValues.push_back(op); });
146 if (symbolicValues.empty())
149 if (referencedModules.contains(hwModule.getModuleNameAttr())) {
151 <<
"cannot lower symbolic values in instantiated module '"
152 << hwModule.getModuleName()
153 <<
"' to HW inputs; run the 'hw-input' lowering strategy after "
154 "flattening modules";
158 for (
auto symbolicValue : symbolicValues) {
159 auto [name, arg] = hwModule.insertInput(
160 hwModule.getNumInputPorts(),
161 StringAttr::get(module.getContext(),
"symbolic_value"),
162 symbolicValue.getType());
164 symbolicValue.getResult().replaceAllUsesWith(arg);
165 symbolicValue.erase();
false return failure()
Parse an optional keyword or string and set instance into 'result'.
create(data_type, name=None, sym_name=None)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.