18 #include "mlir/IR/Diagnostics.h"
19 #include "mlir/IR/ImplicitLocOpBuilder.h"
21 using namespace circt;
22 using namespace firrtl;
29 struct LowerIntmodulesPass :
public LowerIntmodulesBase<LowerIntmodulesPass> {
30 void runOnOperation()
override;
31 using LowerIntmodulesBase::fixupEICGWrapper;
37 return mod.emitError(name)
38 <<
" cannot have annotations since it is an intrinsic";
45 return inst.emitError(name)
46 <<
" instance cannot have annotations since it is an intrinsic";
51 void LowerIntmodulesPass::runOnOperation() {
52 auto &ig = getAnalysis<InstanceGraph>();
58 llvm::make_early_inc_range(getOperation().getOps<FIntModuleOp>())) {
59 auto *node = ig.lookup(op);
63 return signalPassFailure();
65 for (
auto *use : llvm::make_early_inc_range(node->uses())) {
66 auto inst = use->getInstance<InstanceOp>();
68 return signalPassFailure();
72 ImplicitLocOpBuilder
builder(op.getLoc(), inst);
77 BundleType::BundleElement element;
79 SmallVector<OutputInfo>
outputs;
80 for (
auto [idx, result] : llvm::enumerate(inst.getResults())) {
83 auto w =
builder.create<WireOp>(result.getLoc(), result.getType())
85 result.replaceAllUsesWith(w);
92 auto ftype = dyn_cast<FIRRTLBaseType>(inst.getType(idx));
94 inst.emitError(
"intrinsic has non-FIRRTL or non-base port type")
100 OutputInfo{inst.getResult(idx),
101 BundleType::BundleElement(inst.getPortName(idx),
108 builder.create<GenericIntrinsicOp>(Type(),
109 op.getIntrinsicAttr(),
inputs,
112 }
else if (
outputs.size() == 1) {
114 auto resultType =
outputs.front().element.type;
115 auto intop =
builder.create<GenericIntrinsicOp>(
116 resultType, op.getIntrinsicAttr(),
inputs, op.getParameters());
117 outputs.front().result.replaceAllUsesWith(intop.getResult());
121 auto resultType =
builder.getType<BundleType>(llvm::map_to_vector(
122 outputs, [](
const auto &info) {
return info.element; }));
123 auto intop =
builder.create<GenericIntrinsicOp>(
124 resultType, op.getIntrinsicAttr(),
inputs, op.getParameters());
126 output.result.replaceAllUsesWith(
builder.create<SubfieldOp>(
127 intop.getResult(), output.element.name));
141 if (fixupEICGWrapper) {
142 constexpr StringRef eicgName =
"EICG_wrapper";
144 llvm::make_early_inc_range(getOperation().getOps<FExtModuleOp>())) {
145 if (op.getDefname() != eicgName)
153 <<
" on EICG_wrapper is dropped";
156 return signalPassFailure();
158 auto *node = ig.lookup(op);
160 for (
auto *use : llvm::make_early_inc_range(node->uses())) {
161 auto inst = use->getInstance<InstanceOp>();
163 return signalPassFailure();
165 ImplicitLocOpBuilder
builder(op.getLoc(), inst);
166 auto replaceResults = [](OpBuilder &b,
auto &&range) {
167 return llvm::map_to_vector(range, [&b](
auto v) {
168 auto w = b.create<WireOp>(v.getLoc(), v.getType()).getResult();
169 v.replaceAllUsesWith(w);
174 auto inputs = replaceResults(
builder, inst.getResults().drop_back());
175 auto intop =
builder.create<GenericIntrinsicOp>(
178 inst.getResults().back().replaceAllUsesWith(intop.getResult());
190 markAnalysesPreserved<InstanceGraph>();
193 markAllAnalysesPreserved();
197 std::unique_ptr<mlir::Pass>
199 auto pass = std::make_unique<LowerIntmodulesPass>();
200 pass->fixupEICGWrapper = fixupEICGWrapper;
static InstancePath empty
static LogicalResult checkModForAnnotations(FModuleLike mod, StringRef name)
static LogicalResult checkInstForAnnotations(FInstanceLike inst, StringRef name)
llvm::SmallVector< StringAttr > inputs
llvm::SmallVector< StringAttr > outputs
This class provides a read-only projection over the MLIR attributes that represent a set of annotatio...
bool removeAnnotations(llvm::function_ref< bool(Annotation)> predicate)
Remove all annotations from this annotation set for which predicate returns true.
std::unique_ptr< mlir::Pass > createLowerIntmodulesPass(bool fixupEICGWrapper=false)
This is the pass constructor.
constexpr const char * dedupGroupAnnoClass
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.