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