20#include "mlir/Pass/Pass.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/Support/Debug.h"
24#define DEBUG_TYPE "firrtl-populate-instance-choice-symbols"
28#define GEN_PASS_DEF_POPULATEINSTANCECHOICESYMBOLS
29#include "circt/Dialect/FIRRTL/Passes.h.inc"
34using namespace firrtl;
38void getOptionCaseMacroName(StringAttr optionName, StringAttr caseName,
39 SmallVectorImpl<char> ¯oName) {
40 llvm::raw_svector_ostream os(macroName);
41 os <<
"__option_" << optionName.getValue() <<
"_" << caseName.getValue();
44class PopulateInstanceChoiceSymbolsPass
45 :
public impl::PopulateInstanceChoiceSymbolsBase<
46 PopulateInstanceChoiceSymbolsPass> {
48 void runOnOperation()
override;
54 FlatSymbolRefAttr assignSymbol(InstanceChoiceOp op);
58 std::optional<CircuitNamespace> circuitNamespace;
60 if (!circuitNamespace)
62 return *circuitNamespace;
68PopulateInstanceChoiceSymbolsPass::assignSymbol(InstanceChoiceOp op) {
70 if (op.getInstanceMacroAttr())
74 auto parentModule = op->getParentOfType<FModuleLike>();
77 auto optionName = op.getOptionNameAttr();
82 SmallString<128> instanceMacroName;
84 llvm::raw_svector_ostream os(instanceMacroName);
85 os <<
"__target_" << optionName.getValue() <<
"_"
86 << parentModule.getModuleName() <<
"_" << op.getInstanceName();
90 auto uniqueName = StringAttr::get(op.getContext(),
91 getNamespace().newName(instanceMacroName));
92 auto instanceMacro = FlatSymbolRefAttr::get(uniqueName);
93 op.setInstanceMacroAttr(instanceMacro);
95 LLVM_DEBUG(llvm::dbgs() <<
"Assigned instance macro '" << uniqueName
96 <<
"' to instance choice '" << op.getInstanceName()
97 <<
"' in module '" << parentModule.getModuleName()
100 return instanceMacro;
103void PopulateInstanceChoiceSymbolsPass::runOnOperation() {
104 auto circuit = getOperation();
105 auto &instanceGraph = getAnalysis<InstanceGraph>();
107 OpBuilder builder(circuit.getContext());
108 builder.setInsertionPointToStart(circuit.getBodyBlock());
110 llvm::DenseSet<StringAttr> createdInstanceMacros;
111 bool changed =
false;
114 for (
auto optionOp : circuit.getOps<OptionOp>()) {
115 auto optionName = optionOp.getSymNameAttr();
117 for (
auto caseOp : optionOp.getOps<OptionCaseOp>()) {
119 if (caseOp.getCaseMacroAttr())
122 auto caseName = caseOp.getSymNameAttr();
123 SmallString<128> caseMacroName;
124 getOptionCaseMacroName(optionName, caseName, caseMacroName);
127 auto caseMacro = FlatSymbolRefAttr::get(
128 circuit.getContext(), getNamespace().newName(caseMacroName));
131 caseOp.setCaseMacroAttr(caseMacro);
135 sv::MacroDeclOp::create(builder, circuit.getLoc(), caseMacro.getValue());
137 LLVM_DEBUG(llvm::dbgs() <<
"Assigned case macro '" << caseMacro.getValue()
138 <<
"' to option case '" << caseName
139 <<
"' in option '" << optionName <<
"'\n");
145 auto module = dyn_cast<FModuleLike>(node.getModule().getOperation());
149 for (
auto *record : node) {
150 auto op = record->getInstance<InstanceChoiceOp>();
154 auto instanceMacro = assignSymbol(op);
160 if (createdInstanceMacros.insert(instanceMacro.getAttr()).second)
161 sv::MacroDeclOp::create(builder, circuit.getLoc(),
162 instanceMacro.getAttr());
166 circuitNamespace.reset();
168 return markAllAnalysesPreserved();
170 markAnalysesPreserved<InstanceGraph, InstanceInfo>();
This is a Node in the InstanceGraph.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
The namespace of a CircuitOp, generally inhabited by modules.