11 #include "mlir/IR/ImplicitLocOpBuilder.h"
12 #include "mlir/IR/Threading.h"
13 #include "mlir/Pass/Pass.h"
17 #define GEN_PASS_DEF_SPECIALIZEOPTION
18 #include "circt/Dialect/FIRRTL/Passes.h.inc"
23 using namespace circt;
24 using namespace firrtl;
27 struct SpecializeOptionPass
28 :
public circt::firrtl::impl::SpecializeOptionBase<SpecializeOptionPass> {
29 using SpecializeOptionBase::numInstances;
30 using SpecializeOptionBase::selectDefaultInstanceChoice;
32 void runOnOperation()
override {
33 auto circuit = getOperation();
35 DenseMap<StringAttr, OptionCaseOp> selected;
36 if (
auto choiceAttr = circuit.getSelectInstChoiceAttr()) {
37 for (
auto attr : choiceAttr.getAsRange<StringAttr>()) {
38 const auto optionAndCase = attr.getValue().str();
39 size_t eq = optionAndCase.find(
"=");
40 if (eq == std::string::npos) {
41 mlir::emitError(circuit.getLoc(),
42 "invalid option format: \"" + optionAndCase +
'"');
43 return signalPassFailure();
46 std::string optionName = optionAndCase.substr(0, eq);
47 auto optionOp = circuit.lookupSymbol<OptionOp>(optionName);
49 mlir::emitError(circuit.getLoc(),
"unknown option \"")
51 return signalPassFailure();
54 std::string caseName = optionAndCase.substr(eq + 1);
55 auto caseOp = optionOp.lookupSymbol<OptionCaseOp>(caseName);
57 mlir::emitError(circuit.getLoc(),
"invalid option case \"")
59 return signalPassFailure();
66 mlir::parallelForEach(
67 &getContext(), circuit.getOps<FModuleOp>(), [&](
auto module) {
68 module.walk([&](firrtl::InstanceChoiceOp inst) {
69 auto it = selected.find(inst.getOptionNameAttr());
70 FlatSymbolRefAttr target;
71 if (it == selected.end()) {
72 if (!selectDefaultInstanceChoice) {
73 inst.emitError(
"missing specialization for option ")
74 << inst.getOptionNameAttr();
78 target = inst.getDefaultTargetAttr();
80 target = inst.getTargetOrDefaultAttr(it->second);
82 ImplicitLocOpBuilder builder(inst.getLoc(), inst);
83 auto newInst = builder.create<InstanceOp>(
84 inst->getResultTypes(), target, inst.getNameAttr(),
85 inst.getNameKindAttr(), inst.getPortDirectionsAttr(),
86 inst.getPortNamesAttr(), inst.getAnnotationsAttr(),
87 inst.getPortAnnotationsAttr(), builder.getArrayAttr({}),
88 UnitAttr{}, inst.getInnerSymAttr());
89 inst.replaceAllUsesWith(newInst);
96 bool analysisPreserved = numInstances == 0;
97 circuit->walk([&](OptionOp optionOp) {
99 analysisPreserved =
false;
101 if (analysisPreserved)
102 markAllAnalysesPreserved();
110 std::unique_ptr<Pass>
112 auto pass = std::make_unique<SpecializeOptionPass>();
113 pass->selectDefaultInstanceChoice = selectDefaultInstanceChoice;
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
std::unique_ptr< mlir::Pass > createSpecializeOptionPass(bool selectDefaultInstanceChoice=false)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.