CIRCT  20.0.0git
LLHDOps.cpp
Go to the documentation of this file.
1 //===- LLHDOps.cpp - Implement the LLHD operations ------------------------===//
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 // This file implements the LLHD ops.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "circt/Dialect/HW/HWOps.h"
16 #include "mlir/IR/Attributes.h"
17 #include "mlir/IR/BuiltinTypes.h"
18 #include "mlir/IR/Matchers.h"
19 #include "mlir/IR/PatternMatch.h"
20 #include "mlir/IR/Region.h"
21 #include "mlir/IR/Types.h"
22 #include "mlir/IR/Value.h"
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/ADT/SmallVector.h"
25 
26 using namespace circt;
27 using namespace mlir;
28 using namespace llhd;
29 
30 unsigned circt::llhd::getLLHDTypeWidth(Type type) {
31  if (auto sig = dyn_cast<hw::InOutType>(type))
32  type = sig.getElementType();
33  else if (auto ptr = dyn_cast<llhd::PtrType>(type))
34  type = ptr.getElementType();
35  if (auto array = dyn_cast<hw::ArrayType>(type))
36  return array.getNumElements();
37  if (auto tup = dyn_cast<hw::StructType>(type))
38  return tup.getElements().size();
39  return type.getIntOrFloatBitWidth();
40 }
41 
43  if (auto sig = dyn_cast<hw::InOutType>(type))
44  type = sig.getElementType();
45  else if (auto ptr = dyn_cast<llhd::PtrType>(type))
46  type = ptr.getElementType();
47  if (auto array = dyn_cast<hw::ArrayType>(type))
48  return array.getElementType();
49  return type;
50 }
51 
52 //===----------------------------------------------------------------------===//
53 // ConstantTimeOp
54 //===----------------------------------------------------------------------===//
55 
56 OpFoldResult llhd::ConstantTimeOp::fold(FoldAdaptor adaptor) {
57  assert(adaptor.getOperands().empty() && "const has no operands");
58  return getValueAttr();
59 }
60 
61 void llhd::ConstantTimeOp::build(OpBuilder &builder, OperationState &result,
62  unsigned time, const StringRef &timeUnit,
63  unsigned delta, unsigned epsilon) {
64  auto *ctx = builder.getContext();
65  auto attr = TimeAttr::get(ctx, time, timeUnit, delta, epsilon);
66  return build(builder, result, TimeType::get(ctx), attr);
67 }
68 
69 //===----------------------------------------------------------------------===//
70 // SignalOp
71 //===----------------------------------------------------------------------===//
72 
74  if (getName() && !getName()->empty())
75  setNameFn(getResult(), *getName());
76 }
77 
78 //===----------------------------------------------------------------------===//
79 // SigExtractOp and PtrExtractOp
80 //===----------------------------------------------------------------------===//
81 
82 template <class Op>
83 static OpFoldResult foldSigPtrExtractOp(Op op, ArrayRef<Attribute> operands) {
84 
85  if (!operands[1])
86  return nullptr;
87 
88  // llhd.sig.extract(input, 0) with inputWidth == resultWidth => input
89  if (op.getResultWidth() == op.getInputWidth() &&
90  cast<IntegerAttr>(operands[1]).getValue().isZero())
91  return op.getInput();
92 
93  return nullptr;
94 }
95 
96 OpFoldResult llhd::SigExtractOp::fold(FoldAdaptor adaptor) {
97  return foldSigPtrExtractOp(*this, adaptor.getOperands());
98 }
99 
100 OpFoldResult llhd::PtrExtractOp::fold(FoldAdaptor adaptor) {
101  return foldSigPtrExtractOp(*this, adaptor.getOperands());
102 }
103 
104 //===----------------------------------------------------------------------===//
105 // SigArraySliceOp and PtrArraySliceOp
106 //===----------------------------------------------------------------------===//
107 
108 template <class Op>
109 static OpFoldResult foldSigPtrArraySliceOp(Op op,
110  ArrayRef<Attribute> operands) {
111  if (!operands[1])
112  return nullptr;
113 
114  // llhd.sig.array_slice(input, 0) with inputWidth == resultWidth => input
115  if (op.getResultWidth() == op.getInputWidth() &&
116  cast<IntegerAttr>(operands[1]).getValue().isZero())
117  return op.getInput();
118 
119  return nullptr;
120 }
121 
122 OpFoldResult llhd::SigArraySliceOp::fold(FoldAdaptor adaptor) {
123  return foldSigPtrArraySliceOp(*this, adaptor.getOperands());
124 }
125 
126 OpFoldResult llhd::PtrArraySliceOp::fold(FoldAdaptor adaptor) {
127  return foldSigPtrArraySliceOp(*this, adaptor.getOperands());
128 }
129 
130 template <class Op>
131 static LogicalResult canonicalizeSigPtrArraySliceOp(Op op,
132  PatternRewriter &rewriter) {
133  IntegerAttr indexAttr;
134  if (!matchPattern(op.getLowIndex(), m_Constant(&indexAttr)))
135  return failure();
136 
137  // llhd.sig.array_slice(llhd.sig.array_slice(target, a), b)
138  // => llhd.sig.array_slice(target, a+b)
139  IntegerAttr a;
140  if (matchPattern(op.getInput(),
141  m_Op<Op>(matchers::m_Any(), m_Constant(&a)))) {
142  auto sliceOp = op.getInput().template getDefiningOp<Op>();
143  rewriter.modifyOpInPlace(op, [&]() {
144  op.getInputMutable().assign(sliceOp.getInput());
145  Value newIndex = rewriter.create<hw::ConstantOp>(
146  op->getLoc(), a.getValue() + indexAttr.getValue());
147  op.getLowIndexMutable().assign(newIndex);
148  });
149 
150  return success();
151  }
152 
153  return failure();
154 }
155 
156 LogicalResult llhd::SigArraySliceOp::canonicalize(llhd::SigArraySliceOp op,
157  PatternRewriter &rewriter) {
158  return canonicalizeSigPtrArraySliceOp(op, rewriter);
159 }
160 
161 LogicalResult llhd::PtrArraySliceOp::canonicalize(llhd::PtrArraySliceOp op,
162  PatternRewriter &rewriter) {
163  return canonicalizeSigPtrArraySliceOp(op, rewriter);
164 }
165 
166 //===----------------------------------------------------------------------===//
167 // SigStructExtractOp and PtrStructExtractOp
168 //===----------------------------------------------------------------------===//
169 
170 template <class SigPtrType>
172  MLIRContext *context, std::optional<Location> loc, ValueRange operands,
173  DictionaryAttr attrs, mlir::OpaqueProperties properties,
174  mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
175  Type type =
176  cast<hw::StructType>(
177  cast<SigPtrType>(operands[0].getType()).getElementType())
178  .getFieldType(
179  cast<StringAttr>(attrs.getNamed("field")->getValue()).getValue());
180  if (!type) {
181  context->getDiagEngine().emit(loc.value_or(UnknownLoc()),
182  DiagnosticSeverity::Error)
183  << "invalid field name specified";
184  return failure();
185  }
186  results.push_back(SigPtrType::get(type));
187  return success();
188 }
189 
191  MLIRContext *context, std::optional<Location> loc, ValueRange operands,
192  DictionaryAttr attrs, mlir::OpaqueProperties properties,
193  mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
194  return inferReturnTypesOfStructExtractOp<hw::InOutType>(
195  context, loc, operands, attrs, properties, regions, results);
196 }
197 
199  MLIRContext *context, std::optional<Location> loc, ValueRange operands,
200  DictionaryAttr attrs, mlir::OpaqueProperties properties,
201  mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
202  return inferReturnTypesOfStructExtractOp<llhd::PtrType>(
203  context, loc, operands, attrs, properties, regions, results);
204 }
205 
206 //===----------------------------------------------------------------------===//
207 // DrvOp
208 //===----------------------------------------------------------------------===//
209 
210 LogicalResult llhd::DrvOp::fold(FoldAdaptor adaptor,
211  SmallVectorImpl<OpFoldResult> &result) {
212  if (!getEnable())
213  return failure();
214 
215  if (matchPattern(getEnable(), m_One())) {
216  getEnableMutable().clear();
217  return success();
218  }
219 
220  return failure();
221 }
222 
223 LogicalResult llhd::DrvOp::canonicalize(llhd::DrvOp op,
224  PatternRewriter &rewriter) {
225  if (!op.getEnable())
226  return failure();
227 
228  if (matchPattern(op.getEnable(), m_Zero())) {
229  rewriter.eraseOp(op);
230  return success();
231  }
232 
233  return failure();
234 }
235 
236 //===----------------------------------------------------------------------===//
237 // WaitOp
238 //===----------------------------------------------------------------------===//
239 
240 // Implement this operation for the BranchOpInterface
241 SuccessorOperands llhd::WaitOp::getSuccessorOperands(unsigned index) {
242  assert(index == 0 && "invalid successor index");
243  return SuccessorOperands(getDestOpsMutable());
244 }
245 
246 //===----------------------------------------------------------------------===//
247 // ConnectOp
248 //===----------------------------------------------------------------------===//
249 
250 LogicalResult llhd::ConnectOp::canonicalize(llhd::ConnectOp op,
251  PatternRewriter &rewriter) {
252  if (op.getLhs() == op.getRhs())
253  rewriter.eraseOp(op);
254  return success();
255 }
256 
257 #include "circt/Dialect/LLHD/IR/LLHDEnums.cpp.inc"
258 
259 #define GET_OP_CLASSES
260 #include "circt/Dialect/LLHD/IR/LLHD.cpp.inc"
assert(baseType &&"element must be base type")
static InstancePath empty
static LogicalResult inferReturnTypesOfStructExtractOp(MLIRContext *context, std::optional< Location > loc, ValueRange operands, DictionaryAttr attrs, mlir::OpaqueProperties properties, mlir::RegionRange regions, SmallVectorImpl< Type > &results)
Definition: LLHDOps.cpp:171
static OpFoldResult foldSigPtrArraySliceOp(Op op, ArrayRef< Attribute > operands)
Definition: LLHDOps.cpp:109
static LogicalResult canonicalizeSigPtrArraySliceOp(Op op, PatternRewriter &rewriter)
Definition: LLHDOps.cpp:131
static OpFoldResult foldSigPtrExtractOp(Op op, ArrayRef< Attribute > operands)
Definition: LLHDOps.cpp:83
static LogicalResult canonicalize(Op op, PatternRewriter &rewriter)
Definition: VerifOps.cpp:66
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
LogicalResult inferReturnTypes(MLIRContext *context, std::optional< Location > loc, ValueRange operands, DictionaryAttr attrs, mlir::OpaqueProperties properties, mlir::RegionRange regions, SmallVectorImpl< Type > &results, llvm::function_ref< FIRRTLType(ValueRange, ArrayRef< NamedAttribute >, std::optional< Location >)> callback)
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
void getAsmResultNames(OpAsmSetValueNameFn setNameFn, StringRef instanceName, ArrayAttr resultNames, ValueRange results)
Suggest a name for each result value based on the saved result names attribute.
unsigned getLLHDTypeWidth(Type type)
Definition: LLHDOps.cpp:30
Type getLLHDElementType(Type type)
Definition: LLHDOps.cpp:42
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
Definition: LLVM.h:182