CIRCT 22.0.0git
Loading...
Searching...
No Matches
ESILowerTypes.cpp
Go to the documentation of this file.
1//===- ESILowerTypes.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//
9// Lower high-level ESI types to HW conversions and pass.
10//
11//===----------------------------------------------------------------------===//
12
13#include "../PassDetails.h"
14
19
20#include "mlir/IR/BuiltinTypes.h"
21#include "mlir/Interfaces/ControlFlowInterfaces.h"
22#include "mlir/Pass/Pass.h"
23#include "mlir/Transforms/DialectConversion.h"
24
25namespace circt {
26namespace esi {
27#define GEN_PASS_DEF_LOWERESITYPES
28#include "circt/Dialect/ESI/ESIPasses.h.inc"
29} // namespace esi
30} // namespace circt
31
32using namespace circt;
33using namespace circt::esi;
34
35namespace {
36/// Lower all "high-level" ESI types on modules to some lower construct.
37struct ESILowerTypesPass
38 : public circt::esi::impl::LowerESITypesBase<ESILowerTypesPass> {
39 void runOnOperation() override;
40};
41} // anonymous namespace
42
43namespace {
44/// Materializations and type conversions to lower ESI data windows.
45class LowerTypesConverter : public TypeConverter {
46public:
47 LowerTypesConverter() {
48 addConversion([](Type t) { return t; });
49 addConversion([](WindowType window) { return window.getLoweredType(); });
50 addSourceMaterialization(wrapMaterialization);
51 addTargetMaterialization(unwrapMaterialization);
52 }
53
54private:
55 static mlir::Value wrapMaterialization(OpBuilder &b, WindowType resultType,
56 ValueRange inputs, Location loc) {
57 if (inputs.size() != 1)
58 return mlir::Value();
59 return b.createOrFold<WrapWindow>(loc, resultType, inputs[0]);
60 }
61
62 static mlir::Value unwrapMaterialization(OpBuilder &b, Type resultType,
63 ValueRange inputs, Location loc) {
64 if (inputs.size() != 1 || !isa<WindowType>(inputs[0].getType()))
65 return mlir::Value();
66 return b.createOrFold<UnwrapWindow>(loc, resultType, inputs[0]);
67 }
68};
69} // namespace
70
71void ESILowerTypesPass::runOnOperation() {
72 ConversionTarget target(getContext());
73
74 // We need to lower instances, modules, and outputs with data windows.
75 target.markUnknownOpDynamicallyLegal([](Operation *op) {
76 return TypeSwitch<Operation *, bool>(op)
77 .Case([](igraph::InstanceOpInterface inst) {
78 return !(
79 llvm::any_of(inst->getOperandTypes(), hw::type_isa<WindowType>) ||
80 llvm::any_of(inst->getResultTypes(), hw::type_isa<WindowType>));
81 })
82 .Case([](hw::HWMutableModuleLike mod) {
83 auto isWindowPort = [](hw::PortInfo p) {
84 return hw::type_isa<WindowType>(p.type);
85 };
86 return !(llvm::any_of(mod.getPortList(), isWindowPort));
87 })
88 .Default([](Operation *op) {
89 if (op->hasTrait<OpTrait::ReturnLike>())
90 return !llvm::any_of(op->getOperandTypes(),
91 hw::type_isa<WindowType>);
92 return true;
93 });
94 });
95
96 LowerTypesConverter types;
97 RewritePatternSet patterns(&getContext());
98 patterns.add<TypeConversionPattern>(types, &getContext());
99 if (failed(
100 applyPartialConversion(getOperation(), target, std::move(patterns))))
101 signalPassFailure();
102
103 // Now do a canonicalization pass to clean up any unnecessary wrap-unwrap
104 // pairs.
105 mlir::ConversionConfig config;
106 config.foldingMode = mlir::DialectConversionFoldingMode::BeforePatterns;
107 ConversionTarget partialCanonicalizedTarget(getContext());
108 RewritePatternSet partialPatterns(&getContext());
109 partialCanonicalizedTarget.addIllegalOp<WrapWindow, UnwrapWindow>();
110 WrapWindow::getCanonicalizationPatterns(partialPatterns, &getContext());
111 UnwrapWindow::getCanonicalizationPatterns(partialPatterns, &getContext());
112 if (failed(mlir::applyPartialConversion(getOperation(),
113 partialCanonicalizedTarget,
114 std::move(partialPatterns), config)))
115 signalPassFailure();
116}
117
118std::unique_ptr<OperationPass<ModuleOp>>
120 return std::make_unique<ESILowerTypesPass>();
121}
std::unique_ptr< OperationPass< ModuleOp > > createESITypeLoweringPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition esi.py:1
Generic pattern which replaces an operation by one of the same operation name, but with converted att...
This holds the name, type, direction of a module's ports.