Loading [MathJax]/jax/input/TeX/config.js
CIRCT 22.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SpecializeOption.cpp
Go to the documentation of this file.
1//===- SpecializeOption.cpp -------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "mlir/IR/ImplicitLocOpBuilder.h"
12#include "mlir/IR/Threading.h"
13#include "mlir/Pass/Pass.h"
14
15namespace circt {
16namespace firrtl {
17#define GEN_PASS_DEF_SPECIALIZEOPTION
18#include "circt/Dialect/FIRRTL/Passes.h.inc"
19} // namespace firrtl
20} // namespace circt
21
22using namespace mlir;
23using namespace circt;
24using namespace firrtl;
25
26namespace {
27struct SpecializeOptionPass
28 : public circt::firrtl::impl::SpecializeOptionBase<SpecializeOptionPass> {
29 using Base::Base;
30
31 void runOnOperation() override {
32 auto circuit = getOperation();
33
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();
43 }
44
45 std::string optionName = optionAndCase.substr(0, eq);
46 auto optionOp = circuit.lookupSymbol<OptionOp>(optionName);
47 if (!optionOp) {
48 mlir::emitError(circuit.getLoc(), "unknown option \"")
49 << optionName << '"';
50 return signalPassFailure();
51 }
52
53 std::string caseName = optionAndCase.substr(eq + 1);
54 auto caseOp = optionOp.lookupSymbol<OptionCaseOp>(caseName);
55 if (!caseOp) {
56 mlir::emitError(circuit.getLoc(), "invalid option case \"")
57 << caseName << '"';
58 return signalPassFailure();
59 }
60 selected[StringAttr::get(&getContext(), optionName)] = caseOp;
61 }
62 }
63
64 bool failed = false;
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();
74 failed = true;
75 return;
76 }
77 target = inst.getDefaultTargetAttr();
78 } else
79 target = inst.getTargetOrDefaultAttr(it->second);
80
81 ImplicitLocOpBuilder builder(inst.getLoc(), inst);
82 auto newInst = builder.create<InstanceOp>(
83 inst->getResultTypes(), target, inst.getNameAttr(),
84 inst.getNameKindAttr(), inst.getPortDirectionsAttr(),
85 inst.getPortNamesAttr(), inst.getAnnotationsAttr(),
86 inst.getPortAnnotationsAttr(), builder.getArrayAttr({}),
87 UnitAttr{}, UnitAttr{}, inst.getInnerSymAttr());
88 inst.replaceAllUsesWith(newInst);
89 inst.erase();
90
91 ++numInstances;
92 });
93 });
94
95 bool analysisPreserved = numInstances == 0;
96 circuit->walk([&](OptionOp optionOp) {
97 optionOp->erase();
98 analysisPreserved = false;
99 });
100 if (analysisPreserved)
101 markAllAnalysesPreserved();
102
103 if (failed)
104 signalPassFailure();
105 }
106};
107} // namespace
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.