CIRCT 23.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/Interfaces/MemorySlotInterfaces.h"
20
21#include "circt/Support/LLVM.h"
22#include "mlir/IR/AttrTypeSubElements.h"
23#include "mlir/IR/BuiltinTypes.h"
24#include "mlir/IR/Types.h"
25
26namespace circt {
27namespace hw {
28
29struct ModulePort {
31 mlir::StringAttr name;
32 mlir::Type type;
34};
35
36static bool operator==(const ModulePort &a, const ModulePort &b) {
37 return a.dir == b.dir && a.name == b.name && a.type == b.type;
38}
39static llvm::hash_code hash_value(const ModulePort &port) {
40 return llvm::hash_combine(port.dir, port.name, port.type);
41}
42
43namespace detail {
44struct ModuleTypeStorage : public TypeStorage {
45 ModuleTypeStorage(ArrayRef<ModulePort> inPorts);
46
47 using KeyTy = ArrayRef<ModulePort>;
48
49 /// Define the comparison function for the key type.
50 bool operator==(const KeyTy &key) const {
51 return std::equal(key.begin(), key.end(), ports.begin(), ports.end());
52 }
53
54 /// Define a hash function for the key type.
55 static llvm::hash_code hashKey(const KeyTy &key) {
56 return llvm::hash_combine_range(key.begin(), key.end());
57 }
58
59 /// Define a construction method for creating a new instance of this storage.
60 static ModuleTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
61 const KeyTy &key) {
62 return new (allocator.allocate<ModuleTypeStorage>()) ModuleTypeStorage(key);
63 }
64
65 /// Construct an instance of the key from this storage class.
66 KeyTy getAsKey() const { return ports; }
67
68 ArrayRef<ModulePort> getPorts() const { return ports; }
69
70 /// The parametric data held by the storage class.
71 SmallVector<ModulePort> ports;
72 // Cache of common lookups
73 SmallVector<size_t> inputToAbs;
74 SmallVector<size_t> outputToAbs;
75 SmallVector<size_t> absToInput;
76 SmallVector<size_t> absToOutput;
77};
78} // namespace detail
79
80class HWSymbolCache;
81class ParamDeclAttr;
82class TypedeclOp;
83class ModuleType;
84
85namespace detail {
86
87ModuleType fnToMod(Operation *op, ArrayRef<Attribute> inputNames,
88 ArrayRef<Attribute> outputNames);
89ModuleType fnToMod(FunctionType fn, ArrayRef<Attribute> inputNames,
90 ArrayRef<Attribute> outputNames);
91
92/// Struct defining a field. Used in structs.
93struct FieldInfo {
94 mlir::StringAttr name;
95 mlir::Type type;
96};
97
98/// Struct defining a field with an offset. Used in unions.
100 StringAttr name;
101 Type type;
102 size_t offset;
103};
104} // namespace detail
105} // namespace hw
106} // namespace circt
107
108namespace mlir {
109/// Expose the field names and types of struct and union types to the generic
110/// attribute and type walking and replacement infrastructure. This allows
111/// walkers to recurse into the fields of `!hw.struct` and `!hw.union` types,
112/// and replacers such as `mlir::AttrTypeReplacer` to replace types nested
113/// within the fields.
114template <>
115struct AttrTypeSubElementHandler<circt::hw::detail::FieldInfo> {
116 static void walk(const circt::hw::detail::FieldInfo &param,
117 AttrTypeImmediateSubElementWalker &walker) {
118 walker.walk(param.name);
119 walker.walk(param.type);
120 }
123 AttrSubElementReplacements &attrRepls,
124 TypeSubElementReplacements &typeRepls) {
125 return {cast<StringAttr>(attrRepls.take_front(1)[0]),
126 typeRepls.take_front(1)[0]};
127 }
128};
129template <>
130struct AttrTypeSubElementHandler<circt::hw::detail::OffsetFieldInfo> {
131 static void walk(const circt::hw::detail::OffsetFieldInfo &param,
132 AttrTypeImmediateSubElementWalker &walker) {
133 walker.walk(param.name);
134 walker.walk(param.type);
135 }
138 AttrSubElementReplacements &attrRepls,
139 TypeSubElementReplacements &typeRepls) {
140 return {cast<StringAttr>(attrRepls.take_front(1)[0]),
141 typeRepls.take_front(1)[0], param.offset};
142 }
143};
144} // namespace mlir
145
146#define GET_TYPEDEF_CLASSES
147#include "circt/Dialect/HW/HWTypes.h.inc"
148
149namespace circt {
150namespace hw {
151
152// Returns the canonical type of a HW type (inner type of a type alias).
153mlir::Type getCanonicalType(mlir::Type type);
154
155/// Return true if the specified type is a value HW Integer type. This checks
156/// that it is a signless standard dialect type.
157bool isHWIntegerType(mlir::Type type);
158
159/// Return true if the specified type is a HW Enum type.
160bool isHWEnumType(mlir::Type type);
161
162/// Return true if the specified type can be used as an HW value type, that is
163/// the set of types that can be composed together to represent synthesized,
164/// hardware but not marker types like InOutType or unknown types from other
165/// dialects.
166bool isHWValueType(mlir::Type type);
167
168/// Return the hardware bit width of a type. Does not reflect any encoding,
169/// padding, or storage scheme, just the bit (and wire width) of a
170/// statically-size type. Reflects the number of wires needed to transmit a
171/// value of this type. Returns -1 if the type is not known or cannot be
172/// statically computed.
173int64_t getBitWidth(mlir::Type type);
174
175/// Return true if the specified type contains known marker types like
176/// InOutType. Unlike isHWValueType, this is not conservative, it only returns
177/// false on known InOut types, rather than any unknown types.
178bool hasHWInOutType(mlir::Type type);
179
180template <typename... BaseTy>
181bool type_isa(Type type) {
182 // First check if the type is the requested type.
183 if (isa<BaseTy...>(type))
184 return true;
185
186 // Then check if it is a type alias wrapping the requested type.
187 if (auto alias = dyn_cast<TypeAliasType>(type))
188 return type_isa<BaseTy...>(alias.getInnerType());
189
190 return false;
191}
192
193// type_isa for a nullable argument.
194template <typename... BaseTy>
195bool type_isa_and_nonnull(Type type) { // NOLINT(readability-identifier-naming)
196 if (!type)
197 return false;
198 return type_isa<BaseTy...>(type);
199}
200
201template <typename BaseTy>
202BaseTy type_cast(Type type) {
203 assert(type_isa<BaseTy>(type) && "type must convert to requested type");
204
205 // If the type is the requested type, return it.
206 if (isa<BaseTy>(type))
207 return cast<BaseTy>(type);
208
209 // Otherwise, it must be a type alias wrapping the requested type.
210 return type_cast<BaseTy>(cast<TypeAliasType>(type).getInnerType());
211}
212
213template <typename BaseTy>
214BaseTy type_dyn_cast(Type type) {
215 if (!type_isa<BaseTy>(type))
216 return BaseTy();
217
218 return type_cast<BaseTy>(type);
219}
220
221/// Utility type that wraps a type that may be one of several possible Types.
222/// This is similar to std::variant but is implemented for mlir::Type, and it
223/// understands how to handle type aliases.
224template <typename... Types>
226 : public ::mlir::Type::TypeBase<TypeVariant<Types...>, mlir::Type,
227 mlir::TypeStorage> {
228 using mlir::Type::TypeBase<TypeVariant<Types...>, mlir::Type,
229 mlir::TypeStorage>::Base::Base;
230
231public:
232 // Support LLVM isa/cast/dyn_cast to one of the possible types.
233 static bool classof(Type other) { return type_isa<Types...>(other); }
234};
235
236template <typename BaseTy>
238 : public ::mlir::Type::TypeBase<TypeAliasOr<BaseTy>, mlir::Type,
239 mlir::TypeStorage> {
241 mlir::TypeStorage>::Base::Base;
242
243public:
244 // Support LLVM isa/cast/dyn_cast to BaseTy.
245 static bool classof(Type other) { return type_isa<BaseTy>(other); }
246
247 // Support C++ implicit conversions to BaseTy.
248 operator BaseTy() const { return type_cast<BaseTy>(*this); }
249};
250
251} // namespace hw
252} // namespace circt
253
254#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:245
Utility type that wraps a type that may be one of several possible Types.
Definition HWTypes.h:227
static bool classof(Type other)
Definition HWTypes.h:233
ModuleType fnToMod(Operation *op, ArrayRef< Attribute > inputNames, ArrayRef< Attribute > outputNames)
Definition HWTypes.cpp:1052
BaseTy type_cast(Type type)
Definition HWTypes.h:202
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:195
BaseTy type_dyn_cast(Type type)
Definition HWTypes.h:214
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:181
static bool operator==(const ModulePort &a, const ModulePort &b)
Definition HWTypes.h:36
static llvm::hash_code hash_value(const ModulePort &port)
Definition HWTypes.h:39
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
Definition HWTypes.cpp:110
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)
Definition HWTypes.cpp:49
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
mlir::Type type
Definition HWTypes.h:32
mlir::StringAttr name
Definition HWTypes.h:31
Struct defining a field. Used in structs.
Definition HWTypes.h:93
mlir::StringAttr name
Definition HWTypes.h:94
SmallVector< ModulePort > ports
The parametric data held by the storage class.
Definition HWTypes.h:71
static llvm::hash_code hashKey(const KeyTy &key)
Define a hash function for the key type.
Definition HWTypes.h:55
SmallVector< size_t > absToInput
Definition HWTypes.h:75
bool operator==(const KeyTy &key) const
Define the comparison function for the key type.
Definition HWTypes.h:50
SmallVector< size_t > outputToAbs
Definition HWTypes.h:74
SmallVector< size_t > inputToAbs
Definition HWTypes.h:73
ArrayRef< ModulePort > KeyTy
Definition HWTypes.h:47
static ModuleTypeStorage * construct(mlir::TypeStorageAllocator &allocator, const KeyTy &key)
Define a construction method for creating a new instance of this storage.
Definition HWTypes.h:60
ArrayRef< ModulePort > getPorts() const
Definition HWTypes.h:68
KeyTy getAsKey() const
Construct an instance of the key from this storage class.
Definition HWTypes.h:66
SmallVector< size_t > absToOutput
Definition HWTypes.h:76
Struct defining a field with an offset. Used in unions.
Definition HWTypes.h:99
static void walk(const circt::hw::detail::FieldInfo &param, AttrTypeImmediateSubElementWalker &walker)
Definition HWTypes.h:116
static circt::hw::detail::FieldInfo replace(const circt::hw::detail::FieldInfo &param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Definition HWTypes.h:122
static void walk(const circt::hw::detail::OffsetFieldInfo &param, AttrTypeImmediateSubElementWalker &walker)
Definition HWTypes.h:131
static circt::hw::detail::OffsetFieldInfo replace(const circt::hw::detail::OffsetFieldInfo &param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Definition HWTypes.h:137