CIRCT 24.0.0git
Loading...
Searching...
No Matches
HWTypes.h
Go to the documentation of this file.
1//===- HWTypes.h - Types for the HW dialect ---------------------*- 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// Types for the HW dialect are mostly in tablegen. This file should contain
10// C++ types used in MLIR type parameters.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CIRCT_DIALECT_HW_TYPES_H
15#define CIRCT_DIALECT_HW_TYPES_H
16
19#include "mlir/IR/DialectInterface.h"
20#include "mlir/Interfaces/MemorySlotInterfaces.h"
21
23#include "circt/Support/LLVM.h"
24#include "mlir/IR/AttrTypeSubElements.h"
25#include "mlir/IR/BuiltinTypes.h"
26#include "mlir/IR/Types.h"
27
28namespace circt {
29namespace hw {
30
31struct ModulePort {
33 mlir::StringAttr name;
34 mlir::Type type;
36};
37
39 : public mlir::DialectInterface::Base<HWModulePortTypeInterface> {
40 HWModulePortTypeInterface(mlir::Dialect *dialect) : Base(dialect) {}
41
42 /// Return failure if `type` is not valid for a module port with the given
43 /// direction. Dialects can implement this to restrict non-HW-value handle
44 /// types in HW module signatures.
45 virtual mlir::LogicalResult verifyHWModulePortType(
46 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
47 ModulePort::Direction direction, mlir::Type type) const {
48 return mlir::success();
49 }
50};
51
52/// Interface for dialects to classify their types as valid probe payloads.
54 : public mlir::DialectInterface::Base<ProbeTypeDialectInterface> {
55 ProbeTypeDialectInterface(mlir::Dialect *dialect) : Base(dialect) {}
56
57 virtual bool isValidProbeElementType(mlir::Type type) const = 0;
58};
59
60/// Return true if `type` is a valid probe payload. Builtin integer types are
61/// always valid; other types are classified by their owning dialect.
62bool isValidProbeElementType(mlir::Type type);
63
64static bool operator==(const ModulePort &a, const ModulePort &b) {
65 return a.dir == b.dir && a.name == b.name && a.type == b.type;
66}
67static llvm::hash_code hash_value(const ModulePort &port) {
68 return llvm::hash_combine(port.dir, port.name, port.type);
69}
70
71namespace detail {
73 ModuleTypeStorage(ArrayRef<ModulePort> inPorts);
74
75 using KeyTy = ArrayRef<ModulePort>;
76
77 /// Define the comparison function for the key type.
78 bool operator==(const KeyTy &key) const { return llvm::equal(key, ports); }
79
80 /// Define a hash function for the key type.
81 static llvm::hash_code hashKey(const KeyTy &key) {
82 return llvm::hash_combine_range(key.begin(), key.end());
83 }
84
85 /// Define a construction method for creating a new instance of this storage.
86 static ModuleTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
87 const KeyTy &key) {
88 return new (allocator.allocate<ModuleTypeStorage>()) ModuleTypeStorage(key);
89 }
90
91 /// Construct an instance of the key from this storage class.
92 KeyTy getAsKey() const { return ports; }
93
94 ArrayRef<ModulePort> getPorts() const { return ports; }
95
96 /// The parametric data held by the storage class.
97 SmallVector<ModulePort> ports;
98 // Cache of common lookups
99 SmallVector<size_t> inputToAbs;
100 SmallVector<size_t> outputToAbs;
101 SmallVector<size_t> absToInput;
102 SmallVector<size_t> absToOutput;
103};
104} // namespace detail
105
106class HWSymbolCache;
107class ParamDeclAttr;
108class TypedeclOp;
109class ModuleType;
110
111namespace detail {
112
113ModuleType fnToMod(Operation *op, ArrayRef<Attribute> inputNames,
114 ArrayRef<Attribute> outputNames);
115ModuleType fnToMod(FunctionType fn, ArrayRef<Attribute> inputNames,
116 ArrayRef<Attribute> outputNames);
117
118/// Struct defining a field. Used in structs.
120
121/// Struct defining a field with an offset. Used in unions.
123 StringAttr name;
124 Type type;
125 size_t offset;
126};
127} // namespace detail
128} // namespace hw
129} // namespace circt
130
131namespace mlir {
132/// Expose the field names and types of union types to the generic attribute and
133/// type walking and replacement infrastructure. This allows walkers to recurse
134/// into the fields of `!hw.union` types, and replacers such as
135/// `mlir::AttrTypeReplacer` to replace types nested within the fields.
136template <>
137struct AttrTypeSubElementHandler<circt::hw::detail::OffsetFieldInfo> {
138 static void walk(const circt::hw::detail::OffsetFieldInfo &param,
139 AttrTypeImmediateSubElementWalker &walker) {
140 walker.walk(param.name);
141 walker.walk(param.type);
142 }
145 AttrSubElementReplacements &attrRepls,
146 TypeSubElementReplacements &typeRepls) {
147 return {cast<StringAttr>(attrRepls.take_front(1)[0]),
148 typeRepls.take_front(1)[0], param.offset};
149 }
150};
151} // namespace mlir
152
153#define GET_TYPEDEF_CLASSES
154#include "circt/Dialect/HW/HWTypes.h.inc"
155
156namespace circt {
157namespace hw {
158
159/// Recursively remove HW type aliases from a type and its subelements.
160mlir::Type getCanonicalType(mlir::Type type);
161
162/// Return true if the specified type is a value HW Integer type. This checks
163/// that it is a signless standard dialect type.
164bool isHWIntegerType(mlir::Type type);
165
166/// Return true if the specified type is a HW Enum type.
167bool isHWEnumType(mlir::Type type);
168
169/// Return true if the specified type can be used as an HW value type, that is
170/// the set of types that can be composed together to represent synthesized,
171/// hardware but not marker types like InOutType or unknown types from other
172/// dialects.
173bool isHWValueType(mlir::Type type);
174
175/// Return the hardware bit width of a type. Does not reflect any encoding,
176/// padding, or storage scheme, just the bit (and wire width) of a
177/// statically-size type. Reflects the number of wires needed to transmit a
178/// value of this type. Returns -1 if the type is not known or cannot be
179/// statically computed.
180int64_t getBitWidth(mlir::Type type);
181
182/// Return true if the specified type contains known marker types like
183/// InOutType. Unlike isHWValueType, this is not conservative, it only returns
184/// false on known InOut types, rather than any unknown types.
185bool hasHWInOutType(mlir::Type type);
186
187/// Convert an APInt value into a nested aggregate attribute matching the given
188/// HWAggregateType. Returns failure() if the type is not an HWAggregateType or
189/// recursively contains a type other than HWAggregateType or IntegerType.
190LogicalResult apIntToAggregateAttr(mlir::Type aggregateType,
191 const APInt &intVal, ArrayAttr &result);
192
193/// Convert an ArrayAttr into an APInt value matching the given type.
194/// The type is used to determine the bit width of the resulting APInt.
195/// Returns failure() if the attribute recursively contains anything other than
196/// ArrayAttr or IntegerAttr.
197LogicalResult aggregateAttrToAPInt(mlir::Type type, ArrayAttr attr,
198 APInt &result);
199
200template <typename... BaseTy>
201bool type_isa(Type type) {
202 // First check if the type is the requested type.
203 if (isa<BaseTy...>(type))
204 return true;
205
206 // Then check if it is a type alias wrapping the requested type.
207 if (auto alias = dyn_cast<TypeAliasType>(type))
208 return type_isa<BaseTy...>(alias.getInnerType());
209
210 return false;
211}
212
213// type_isa for a nullable argument.
214template <typename... BaseTy>
215bool type_isa_and_nonnull(Type type) { // NOLINT(readability-identifier-naming)
216 if (!type)
217 return false;
218 return type_isa<BaseTy...>(type);
219}
220
221template <typename BaseTy>
222BaseTy type_cast(Type type) {
223 assert(type_isa<BaseTy>(type) && "type must convert to requested type");
224
225 // If the type is the requested type, return it.
226 if (isa<BaseTy>(type))
227 return cast<BaseTy>(type);
228
229 // Otherwise, it must be a type alias wrapping the requested type.
230 return type_cast<BaseTy>(cast<TypeAliasType>(type).getInnerType());
231}
232
233template <typename BaseTy>
234BaseTy type_dyn_cast(Type type) {
235 if (!type_isa<BaseTy>(type))
236 return BaseTy();
237
238 return type_cast<BaseTy>(type);
239}
240
241/// Utility type that wraps a type that may be one of several possible Types.
242/// This is similar to std::variant but is implemented for mlir::Type, and it
243/// understands how to handle type aliases.
244template <typename... Types>
246 : public ::mlir::Type::TypeBase<TypeVariant<Types...>, mlir::Type,
247 mlir::TypeStorage> {
248 using mlir::Type::TypeBase<TypeVariant<Types...>, mlir::Type,
249 mlir::TypeStorage>::Base::Base;
250
251public:
252 // Support LLVM isa/cast/dyn_cast to one of the possible types.
253 static bool classof(Type other) { return type_isa<Types...>(other); }
254};
255
256template <typename BaseTy>
258 : public ::mlir::Type::TypeBase<TypeAliasOr<BaseTy>, mlir::Type,
259 mlir::TypeStorage> {
261 mlir::TypeStorage>::Base::Base;
262
263public:
264 // Support LLVM isa/cast/dyn_cast to BaseTy.
265 static bool classof(Type other) { return type_isa<BaseTy>(other); }
266
267 // Support C++ implicit conversions to BaseTy.
268 operator BaseTy() const { return type_cast<BaseTy>(*this); }
269};
270
271} // namespace hw
272} // namespace circt
273
274#endif // CIRCT_DIALECT_HW_TYPES_H
assert(baseType &&"element must be base type")
This stores lookup tables to make manipulating and working with the IR more efficient.
Definition HWSymCache.h:28
static bool classof(Type other)
Definition HWTypes.h:265
Utility type that wraps a type that may be one of several possible Types.
Definition HWTypes.h:247
static bool classof(Type other)
Definition HWTypes.h:253
::circt::FieldInfo FieldInfo
Struct defining a field. Used in structs.
Definition HWTypes.h:119
ModuleType fnToMod(Operation *op, ArrayRef< Attribute > inputNames, ArrayRef< Attribute > outputNames)
Definition HWTypes.cpp:1100
BaseTy type_cast(Type type)
Definition HWTypes.h:222
bool isHWIntegerType(mlir::Type type)
Return true if the specified type is a value HW Integer type.
Definition HWTypes.cpp:60
bool type_isa_and_nonnull(Type type)
Definition HWTypes.h:215
BaseTy type_dyn_cast(Type type)
Definition HWTypes.h:234
bool isHWValueType(mlir::Type type)
Return true if the specified type can be used as an HW value type, that is the set of types that can ...
bool type_isa(Type type)
Definition HWTypes.h:201
static bool operator==(const ModulePort &a, const ModulePort &b)
Definition HWTypes.h:64
static llvm::hash_code hash_value(const ModulePort &port)
Definition HWTypes.h:67
bool isValidProbeElementType(mlir::Type type)
Return true if type is a valid probe payload.
LogicalResult aggregateAttrToAPInt(mlir::Type type, ArrayAttr attr, APInt &result)
Convert an ArrayAttr into an APInt value matching the given type.
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
Definition HWTypes.cpp:122
LogicalResult apIntToAggregateAttr(mlir::Type aggregateType, const APInt &intVal, ArrayAttr &result)
Convert an APInt value into a nested aggregate attribute matching the given HWAggregateType.
bool isHWEnumType(mlir::Type type)
Return true if the specified type is a HW Enum type.
Definition HWTypes.cpp:73
mlir::Type getCanonicalType(mlir::Type type)
Recursively remove HW type aliases from a type and its subelements.
Definition HWTypes.cpp:51
bool hasHWInOutType(mlir::Type type)
Return true if the specified type contains known marker types like InOutType.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition hw.py:1
A named and typed field of an aggregate type.
Definition FieldInfo.h:27
virtual mlir::LogicalResult verifyHWModulePortType(llvm::function_ref< mlir::InFlightDiagnostic()> emitError, ModulePort::Direction direction, mlir::Type type) const
Return failure if type is not valid for a module port with the given direction.
Definition HWTypes.h:45
HWModulePortTypeInterface(mlir::Dialect *dialect)
Definition HWTypes.h:40
mlir::Type type
Definition HWTypes.h:34
mlir::StringAttr name
Definition HWTypes.h:33
virtual bool isValidProbeElementType(mlir::Type type) const =0
ProbeTypeDialectInterface(mlir::Dialect *dialect)
Definition HWTypes.h:55
SmallVector< ModulePort > ports
The parametric data held by the storage class.
Definition HWTypes.h:97
ModuleTypeStorage(ArrayRef< ModulePort > inPorts)
Definition HWTypes.cpp:1129
static llvm::hash_code hashKey(const KeyTy &key)
Define a hash function for the key type.
Definition HWTypes.h:81
SmallVector< size_t > absToInput
Definition HWTypes.h:101
bool operator==(const KeyTy &key) const
Define the comparison function for the key type.
Definition HWTypes.h:78
SmallVector< size_t > outputToAbs
Definition HWTypes.h:100
SmallVector< size_t > inputToAbs
Definition HWTypes.h:99
ArrayRef< ModulePort > KeyTy
Definition HWTypes.h:75
static ModuleTypeStorage * construct(mlir::TypeStorageAllocator &allocator, const KeyTy &key)
Define a construction method for creating a new instance of this storage.
Definition HWTypes.h:86
ArrayRef< ModulePort > getPorts() const
Definition HWTypes.h:94
KeyTy getAsKey() const
Construct an instance of the key from this storage class.
Definition HWTypes.h:92
SmallVector< size_t > absToOutput
Definition HWTypes.h:102
Struct defining a field with an offset. Used in unions.
Definition HWTypes.h:122
static void walk(const circt::hw::detail::OffsetFieldInfo &param, AttrTypeImmediateSubElementWalker &walker)
Definition HWTypes.h:138
static circt::hw::detail::OffsetFieldInfo replace(const circt::hw::detail::OffsetFieldInfo &param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Definition HWTypes.h:144