CIRCT 24.0.0git
Loading...
Searching...
No Matches
PIROps.cpp
Go to the documentation of this file.
1//===- PIROps.cpp ==-------------------------------------------------------===//
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
15#include "mlir/IR/Builders.h"
16#include "mlir/IR/OpImplementation.h"
17#include "mlir/IR/PatternMatch.h"
18
19using namespace circt;
20using namespace pir;
21using namespace mlir;
22
23//===----------------------------------------------------------------------===//
24// Generated code
25//===----------------------------------------------------------------------===//
26
27#define GET_OP_CLASSES
28#include "circt/Dialect/PIR/PIR.cpp.inc"
29
30//===----------------------------------------------------------------------===//
31// InputOp
32//===----------------------------------------------------------------------===//
33
34/// Attribute every name in input to its related result
35void InputOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
36 // Retrieve the names array
37 auto namesAttr = (*this)->getAttrOfType<ArrayAttr>("names");
38
39 // Check if any names were given
40 if (!namesAttr.empty()) {
41 auto results = getResults();
42
43 // Match every name with its associated result
44 for (size_t i = 0; i < results.size(); ++i) {
45 // Check for string attributes in the array
46 if (auto name = dyn_cast<StringAttr>(namesAttr[i])) {
47 setNameFn(results[i], name);
48 } else {
49 // This should be unreachable, but in case raise an error
50 (*this)->emitOpError("Non-string attribute in string array!");
51 }
52 }
53 }
54}
55
56//===----------------------------------------------------------------------===//
57// AssertLike Canonicalizations
58//===----------------------------------------------------------------------===//
59
60namespace {
61/// Remove enable if trivial, i.e. if enable == true
62template <typename Op>
63struct RemoveEnableTrue : public OpRewritePattern<Op> {
64 using OpRewritePattern<Op>::OpRewritePattern;
65
66 LogicalResult matchAndRewrite(Op op,
67 PatternRewriter &rewriter) const override {
68 // Check if an enable exists
69 Value enable = op.getEnable();
70 if (!enable)
71 return failure();
72
73 // Only modify if the enable is `hw.constant true`
74 auto enableConst = enable.getDefiningOp<hw::ConstantOp>();
75 if (!enableConst || !enableConst.getValue().isOne())
76 return failure();
77
78 // Erase enable signal
79 rewriter.modifyOpInPlace(op, [&]() { op.getEnableMutable().clear(); });
80 return success();
81 }
82};
83
84/// Delete operation if enable is `false`.
85template <typename Op>
86struct EraseIfEnableFalse : public OpRewritePattern<Op> {
87 using OpRewritePattern<Op>::OpRewritePattern;
88
89 LogicalResult matchAndRewrite(Op op,
90 PatternRewriter &rewriter) const override {
91 // Check if there is an enable signal
92 Value enable = op.getEnable();
93 if (!enable)
94 return failure();
95
96 // Only modify is enable is `hw.constant false`
97 auto enableConst = enable.getDefiningOp<hw::ConstantOp>();
98 if (!enableConst || !enableConst.getValue().isZero())
99 return failure();
100
101 rewriter.eraseOp(op);
102 return success();
103 }
104};
105
106/// Remove disable if trivial, i.e. if disable == false
107template <typename Op>
108struct RemoveDisableFalse : public OpRewritePattern<Op> {
109 using OpRewritePattern<Op>::OpRewritePattern;
110
111 LogicalResult matchAndRewrite(Op op,
112 PatternRewriter &rewriter) const override {
113 // Check for a disable signal
114 Value disable = op.getDisable();
115 if (!disable)
116 return failure();
117
118 // Only modify is disable is `hw.constant false`
119 auto disableConst = disable.getDefiningOp<hw::ConstantOp>();
120 if (!disableConst || !disableConst.getValue().isZero())
121 return failure();
122
123 // Erase the disable input since it's useless
124 rewriter.modifyOpInPlace(op, [&]() { op.getDisableMutable().clear(); });
125 return success();
126 }
127};
128
129/// Delete operation if disable is `true`.
130template <typename Op>
131struct EraseIfDisableTrue : public OpRewritePattern<Op> {
132 using OpRewritePattern<Op>::OpRewritePattern;
133
134 LogicalResult matchAndRewrite(Op op,
135 PatternRewriter &rewriter) const override {
136 Value disable = op.getDisable();
137 // Do nothing if no disable was given
138 if (!disable)
139 return failure();
140
141 // Skip any case where the disable is not `hw.constant true`
142 auto disableConst = disable.getDefiningOp<hw::ConstantOp>();
143 if (!disableConst || !disableConst.getValue().isOne())
144 return failure();
145
146 rewriter.eraseOp(op);
147 return success();
148 }
149};
150
151/// Delete operation if property is trivial, i.e. property is either
152/// (bool-to-clk-prop true) or
153/// (clk-seq-to-clk-prop (bool-to-clk-seq true))
154template <typename Op>
155struct EraseIfPropertyTrivial : public OpRewritePattern<Op> {
156 using OpRewritePattern<Op>::OpRewritePattern;
157
158 LogicalResult matchAndRewrite(Op op,
159 PatternRewriter &rewriter) const override {
160 Value property = op.getProperty();
161
162 // Check for (pir.bool_to_clocked_prop (hw.constant true))
163 if (auto boolToProp =
164 property.template getDefiningOp<BoolToClockedPropOp>()) {
165 if (auto constOp =
166 boolToProp.getInput().getDefiningOp<hw::ConstantOp>()) {
167 if (constOp.getValue().isOne()) {
168 rewriter.eraseOp(op);
169 return success();
170 }
171 }
172 }
173
174 // Check for (pir.clocked_seq_to_clocked_prop
175 // (pir.bool_to_clocked_seq
176 // (hw.constant true)))
177 if (auto clkSeqToClkProp =
178 property.template getDefiningOp<ClockedSeqToClockedPropOp>()) {
179 if (auto boolToClkSeq =
180 clkSeqToClkProp.getInput().getDefiningOp<BoolToClockedSeqOp>()) {
181 if (auto constOp =
182 boolToClkSeq.getInput().getDefiningOp<hw::ConstantOp>()) {
183 if (constOp.getValue().isOne()) {
184 rewriter.eraseOp(op);
185 return success();
186 }
187 }
188 }
189 }
190
191 return failure();
192 }
193};
194
195} // namespace
196
197//===----------------------------------------------------------------------===//
198// Assertions
199//===----------------------------------------------------------------------===//
200
201void AssertPropertyOp::getCanonicalizationPatterns(RewritePatternSet &results,
202 MLIRContext *context) {
203 results.add<EraseIfEnableFalse<AssertPropertyOp>,
204 EraseIfPropertyTrivial<AssertPropertyOp>,
205 EraseIfDisableTrue<AssertPropertyOp>,
206 RemoveEnableTrue<AssertPropertyOp>,
207 RemoveDisableFalse<AssertPropertyOp>>(context);
208}
209
210void AssumePropertyOp::getCanonicalizationPatterns(RewritePatternSet &results,
211 MLIRContext *context) {
212 results.add<EraseIfEnableFalse<AssumePropertyOp>,
213 EraseIfPropertyTrivial<AssumePropertyOp>,
214 EraseIfDisableTrue<AssumePropertyOp>,
215 RemoveEnableTrue<AssumePropertyOp>,
216 RemoveDisableFalse<AssumePropertyOp>>(context);
217}
218
219void RestrictOp::getCanonicalizationPatterns(RewritePatternSet &results,
220 MLIRContext *context) {
221 results
222 .add<EraseIfEnableFalse<RestrictOp>, EraseIfPropertyTrivial<RestrictOp>,
223 EraseIfDisableTrue<RestrictOp>, RemoveEnableTrue<RestrictOp>,
224 RemoveDisableFalse<RestrictOp>>(context);
225}
226
227void CoverPropertyOp::getCanonicalizationPatterns(RewritePatternSet &results,
228 MLIRContext *context) {
229 results.add<EraseIfEnableFalse<CoverPropertyOp>,
230 EraseIfPropertyTrivial<CoverPropertyOp>,
231 EraseIfDisableTrue<CoverPropertyOp>,
232 RemoveEnableTrue<CoverPropertyOp>,
233 RemoveDisableFalse<CoverPropertyOp>>(context);
234}
235
236//===----------------------------------------------------------------------===//
237// Type Conversion Ops
238//===----------------------------------------------------------------------===//
239
240/// (clk-seq-to-clk-prop (bool-to-clk-seq b)) ==> (bool-to-clk-prop b)
241LogicalResult
242ClockedSeqToClockedPropOp::canonicalize(ClockedSeqToClockedPropOp op,
243 PatternRewriter &rewriter) {
244 if (auto bToClkSeq = op.getInput().getDefiningOp<BoolToClockedSeqOp>()) {
245 rewriter.replaceOpWithNewOp<BoolToClockedPropOp>(op, bToClkSeq.getInput());
246 return success();
247 }
248 return failure();
249}
250
251//===----------------------------------------------------------------------===//
252// Clocking Ops
253//===----------------------------------------------------------------------===//
254
255/// Result type is always the same as the input property/sequence
256LogicalResult
257ClockedOp::inferReturnTypes(MLIRContext *context, std::optional<Location> loc,
258 ValueRange operands, DictionaryAttr attributes,
259 PropertyRef properties, RegionRange regions,
260 SmallVectorImpl<Type> &inferredReturnTypes) {
261 if (isa<ClockedPropertyType>(operands[1].getType())) {
262 inferredReturnTypes.push_back(ClockedPropertyType::get(context));
263 } else {
264 inferredReturnTypes.push_back(ClockedSequenceType::get(context));
265 }
266 return success();
267}
static std::unique_ptr< Context > context
false return failure()
Parse an optional keyword or string and set instance into 'result'.
return success()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
Definition LLVM.h:193