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" 
   24using namespace firrtl;
 
   27struct SpecializeOptionPass
 
   28    : 
public circt::firrtl::impl::SpecializeOptionBase<SpecializeOptionPass> {
 
   31  void runOnOperation()
 override {
 
   32    auto circuit = getOperation();
 
   34    DenseMap<StringAttr, OptionCaseOp> selected;
 
   35    if (
auto choiceAttr = circuit.getSelectInstChoiceAttr()) {
 
   36      for (
auto attr : choiceAttr.getAsRange<StringAttr>()) {
 
   37        const auto optionAndCase = attr.getValue().str();
 
   38        size_t eq = optionAndCase.find(
"=");
 
   39        if (eq == std::string::npos) {
 
   40          mlir::emitError(circuit.getLoc(),
 
   41                          "invalid option format: \"" + optionAndCase + 
'"');
 
   42          return signalPassFailure();
 
   45        std::string optionName = optionAndCase.substr(0, eq);
 
   46        auto optionOp = circuit.lookupSymbol<OptionOp>(optionName);
 
   48          mlir::emitError(circuit.getLoc(), 
"unknown option \"")
 
   50          return signalPassFailure();
 
   53        std::string caseName = optionAndCase.substr(eq + 1);
 
   54        auto caseOp = optionOp.lookupSymbol<OptionCaseOp>(caseName);
 
   56          mlir::emitError(circuit.getLoc(), 
"invalid option case \"")
 
   58          return signalPassFailure();
 
   60        selected[StringAttr::get(&getContext(), optionName)] = caseOp;
 
   65    mlir::parallelForEach(
 
   66        &getContext(), circuit.getOps<FModuleOp>(), [&](
auto module) {
 
   67          module.walk([&](firrtl::InstanceChoiceOp inst) {
 
   68            auto it = selected.find(inst.getOptionNameAttr());
 
   69            FlatSymbolRefAttr target;
 
   70            if (it == selected.end()) {
 
   71              if (!selectDefaultInstanceChoice) {
 
   72                inst.emitError(
"missing specialization for option ")
 
   73                    << inst.getOptionNameAttr();
 
   77              target = inst.getDefaultTargetAttr();
 
   79              target = inst.getTargetOrDefaultAttr(it->second);
 
   81            ImplicitLocOpBuilder builder(inst.getLoc(), inst);
 
   82            auto newInst = InstanceOp::create(
 
   83                builder, inst->getResultTypes(), target, inst.getNameAttr(),
 
   84                inst.getNameKindAttr(), inst.getPortDirectionsAttr(),
 
   85                inst.getPortNamesAttr(), inst.getDomainInfoAttr(),
 
   86                inst.getAnnotationsAttr(), inst.getPortAnnotationsAttr(),
 
   87                builder.getArrayAttr({}), UnitAttr{}, UnitAttr{},
 
   88                inst.getInnerSymAttr());
 
   89            inst.replaceAllUsesWith(newInst);
 
   96    bool analysisPreserved = numInstances == 0;
 
   97    circuit->walk([&](OptionOp optionOp) {
 
   99      analysisPreserved = 
false;
 
  101    if (analysisPreserved)
 
  102      markAllAnalysesPreserved();
 
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.