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 <<
"targets$" << 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 <<
"targets$" << 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>();
106 auto &symbolTable = getAnalysis<SymbolTable>();
108 OpBuilder builder(circuit.getContext());
109 builder.setInsertionPointToStart(circuit.getBodyBlock());
111 llvm::DenseSet<StringAttr> createdInstanceMacros;
112 bool changed =
false;
115 for (
auto optionOp : circuit.getOps<OptionOp>()) {
116 auto optionName = optionOp.getSymNameAttr();
118 for (
auto caseOp : optionOp.getOps<OptionCaseOp>()) {
120 if (caseOp.getCaseMacroAttr())
123 auto caseName = caseOp.getSymNameAttr();
124 SmallString<128> caseMacroName;
125 getOptionCaseMacroName(optionName, caseName, caseMacroName);
127 FlatSymbolRefAttr::get(circuit.getContext(), caseMacroName);
130 if (
auto *existingSymbol = symbolTable.lookup(caseMacroName)) {
132 if (
auto existingMacro = dyn_cast<sv::MacroDeclOp>(existingSymbol)) {
133 caseOp.setCaseMacroAttr(caseMacro);
138 caseOp.emitError() <<
"case macro name conflicts with existing symbol '"
139 << caseMacroName <<
"' (existing symbol is '"
140 << existingSymbol->getName() <<
"')";
141 return signalPassFailure();
145 caseOp.setCaseMacroAttr(caseMacro);
149 auto macroDecl = sv::MacroDeclOp::create(builder, circuit.getLoc(),
150 caseMacro.getValue());
151 auto symbolName = symbolTable.insert(macroDecl);
153 assert(symbolName.getValue() == caseMacroName &&
154 "Symbol must have been inserted with the expected name");
156 LLVM_DEBUG(llvm::dbgs() <<
"Assigned case macro '" << caseMacro.getValue()
157 <<
"' to option case '" << caseName
158 <<
"' in option '" << optionName <<
"'\n");
164 auto module = dyn_cast<FModuleLike>(node.getModule().getOperation());
168 for (
auto *record : node) {
169 auto op = record->getInstance<InstanceChoiceOp>();
173 auto instanceMacro = assignSymbol(op);
179 if (createdInstanceMacros.insert(instanceMacro.getAttr()).second) {
180 auto decl = sv::MacroDeclOp::create(builder, circuit.getLoc(),
181 instanceMacro.getAttr());
182 symbolTable.insert(decl);
187 circuitNamespace.reset();
189 return markAllAnalysesPreserved();
191 markAnalysesPreserved<InstanceGraph, InstanceInfo, SymbolTable>();
assert(baseType &&"element must be base type")
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.