CIRCT 22.0.0git
Loading...
Searching...
No Matches
MooreTypes.cpp
Go to the documentation of this file.
1//===- MooreTypes.cpp - Implement the Moore types -------------------------===//
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 Moore dialect type system.
10//
11//===----------------------------------------------------------------------===//
12
15#include "mlir/IR/Builders.h"
16#include "mlir/IR/DialectImplementation.h"
17#include "llvm/ADT/TypeSwitch.h"
18
19using namespace circt;
20using namespace circt::moore;
21using mlir::AsmParser;
22using mlir::AsmPrinter;
23
24bool moore::isIntType(Type type, unsigned width) {
25 if (auto intType = dyn_cast<IntType>(type))
26 return intType.getWidth() == width;
27 return false;
28}
29
30bool moore::isIntType(Type type, Domain domain) {
31 if (auto intType = dyn_cast<IntType>(type))
32 return intType.getDomain() == domain;
33 return false;
34}
35
36bool moore::isIntType(Type type, unsigned width, Domain domain) {
37 if (auto intType = dyn_cast<IntType>(type))
38 return intType.getWidth() == width && intType.getDomain() == domain;
39 return false;
40}
41
42bool moore::isRealType(Type type, unsigned width) {
43 if (auto realType = dyn_cast<RealType>(type))
44 if (realType.getWidth() == RealWidth::f32)
45 return width == 32;
46 return width == 64;
47}
48
49static LogicalResult parseMembers(AsmParser &parser,
50 SmallVector<StructLikeMember> &members);
51static void printMembers(AsmPrinter &printer,
52 ArrayRef<StructLikeMember> members);
53
54static ParseResult parseMooreType(AsmParser &parser, Type &type);
55static void printMooreType(Type type, AsmPrinter &printer);
56
57//===----------------------------------------------------------------------===//
58// Unpacked Type
59//===----------------------------------------------------------------------===//
60
62 return TypeSwitch<UnpackedType, Domain>(*this)
63 .Case<PackedType>([](auto type) { return type.getDomain(); })
64 .Case<UnpackedArrayType, OpenUnpackedArrayType, AssocArrayType,
65 QueueType>(
66 [&](auto type) { return type.getElementType().getDomain(); })
67 .Case<UnpackedStructType, UnpackedUnionType>([](auto type) {
68 for (const auto &member : type.getMembers())
69 if (member.type.getDomain() == Domain::FourValued)
70 return Domain::FourValued;
71 return Domain::TwoValued;
72 })
73 .Default([](auto) { return Domain::TwoValued; });
74}
75
76std::optional<unsigned> UnpackedType::getBitSize() const {
77 return TypeSwitch<UnpackedType, std::optional<unsigned>>(*this)
78 .Case<PackedType>([](auto type) { return type.getBitSize(); })
79 .Case<RealType>(
80 [](auto type) { return type.getWidth() == RealWidth::f32 ? 32 : 64; })
81 .Case<UnpackedArrayType>([](auto type) -> std::optional<unsigned> {
82 if (auto size = type.getElementType().getBitSize())
83 return (*size) * type.getSize();
84 return {};
85 })
86 .Case<UnpackedStructType>([](auto type) -> std::optional<unsigned> {
87 unsigned size = 0;
88 for (const auto &member : type.getMembers()) {
89 if (auto memberSize = member.type.getBitSize()) {
90 size += *memberSize;
91 } else {
92 return std::nullopt;
93 }
94 }
95 return size;
96 })
97 .Case<UnpackedUnionType>([](auto type) -> std::optional<unsigned> {
98 unsigned size = 0;
99 for (const auto &member : type.getMembers()) {
100 if (auto memberSize = member.type.getBitSize()) {
101 size = (*memberSize > size) ? *memberSize : size;
102 } else {
103 return std::nullopt;
104 }
105 }
106 return size;
107 })
108 .Default([](auto) { return std::nullopt; });
109}
110
111Type UnpackedType::parse(mlir::AsmParser &parser) {
112 Type type;
113 if (parseMooreType(parser, type))
114 return {};
115 return type;
116}
117
118void UnpackedType::print(mlir::AsmPrinter &printer) const {
119 printMooreType(*this, printer);
120}
121
122//===----------------------------------------------------------------------===//
123// Packed Type
124//===----------------------------------------------------------------------===//
125
127 return TypeSwitch<PackedType, Domain>(*this)
128 .Case<VoidType>([](auto) { return Domain::TwoValued; })
129 .Case<IntType>([&](auto type) { return type.getDomain(); })
130 .Case<TimeType>([](auto) { return Domain::FourValued; })
131 .Case<ArrayType, OpenArrayType>(
132 [&](auto type) { return type.getElementType().getDomain(); })
133 .Case<StructType, UnionType>([](auto type) {
134 for (const auto &member : type.getMembers())
135 if (member.type.getDomain() == Domain::FourValued)
136 return Domain::FourValued;
137 return Domain::TwoValued;
138 });
139}
140
141std::optional<unsigned> PackedType::getBitSize() const {
142 return TypeSwitch<PackedType, std::optional<unsigned>>(*this)
143 .Case<VoidType>([](auto) { return 0; })
144 .Case<IntType>([](auto type) { return type.getWidth(); })
145 .Case<TimeType>([](auto type) { return 64; })
146 .Case<ArrayType>([](auto type) -> std::optional<unsigned> {
147 if (auto size = type.getElementType().getBitSize())
148 return (*size) * type.getSize();
149 return {};
150 })
151 .Case<OpenArrayType>([](auto) { return std::nullopt; })
152 .Case<StructType>([](auto type) -> std::optional<unsigned> {
153 unsigned size = 0;
154 for (const auto &member : type.getMembers()) {
155 if (auto memberSize = member.type.getBitSize()) {
156 size += *memberSize;
157 } else {
158 return std::nullopt;
159 }
160 }
161 return size;
162 })
163 .Case<UnionType>([](auto type) -> std::optional<unsigned> {
164 unsigned size = 0;
165 for (const auto &member : type.getMembers()) {
166 if (auto memberSize = member.type.getBitSize()) {
167 size = (*memberSize > size) ? *memberSize : size;
168 } else {
169 return std::nullopt;
170 }
171 }
172 return size;
173 })
174 .Default([](auto) { return std::nullopt; });
175}
176
178 if (auto intType = dyn_cast<IntType>(*this))
179 return intType;
180 if (auto bitSize = getBitSize())
181 return IntType::get(getContext(), *bitSize, getDomain());
182 return {};
183}
184
186 return TypeSwitch<PackedType, bool>(*this)
187 .Case<VoidType, IntType>([](auto) { return false; })
188 .Case<TimeType>([](auto) { return true; })
189 .Case<ArrayType, OpenArrayType>(
190 [](auto type) { return type.getElementType().containsTimeType(); })
191 .Case<StructType, UnionType>([](auto type) {
192 return llvm::any_of(type.getMembers(), [](auto &member) {
193 return cast<PackedType>(member.type).containsTimeType();
194 });
195 });
196}
197
198//===----------------------------------------------------------------------===//
199// Structs
200//===----------------------------------------------------------------------===//
201
202/// Parse a list of struct members.
203static LogicalResult parseMembers(AsmParser &parser,
204 SmallVector<StructLikeMember> &members) {
205 return parser.parseCommaSeparatedList(AsmParser::Delimiter::Braces, [&]() {
206 std::string name;
207 UnpackedType type;
208 if (parser.parseKeywordOrString(&name) || parser.parseColon() ||
209 parser.parseCustomTypeWithFallback(type))
210 return failure();
211
212 members.push_back({StringAttr::get(parser.getContext(), name), type});
213 return success();
214 });
215}
216
217/// Print a list of struct members.
218static void printMembers(AsmPrinter &printer,
219 ArrayRef<StructLikeMember> members) {
220 printer << "{";
221 llvm::interleaveComma(members, printer.getStream(),
222 [&](const StructLikeMember &member) {
223 printer.printKeywordOrString(member.name);
224 printer << ": ";
225 printer.printStrippedAttrOrType(member.type);
226 });
227 printer << "}";
228}
229
230static LogicalResult
231verifyAllMembersPacked(function_ref<InFlightDiagnostic()> emitError,
232 ArrayRef<StructLikeMember> members) {
233 if (!llvm::all_of(members, [](const auto &member) {
234 return llvm::isa<PackedType>(member.type);
235 }))
236 return emitError() << "StructType/UnionType members must be packed types";
237 return success();
238}
239
240LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
241 ArrayRef<StructLikeMember> members) {
242 return verifyAllMembersPacked(emitError, members);
243}
244
245LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
246 ArrayRef<StructLikeMember> members) {
247 return verifyAllMembersPacked(emitError, members);
248}
249
250//===----------------------------------------------------------------------===//
251// Interfaces for destructurable
252//===----------------------------------------------------------------------===//
253
254static std::optional<DenseMap<Attribute, Type>>
255getAllSubelementIndexMap(ArrayRef<StructLikeMember> members) {
256 DenseMap<Attribute, Type> destructured;
257 for (const auto &member : members)
258 destructured.insert({member.name, RefType::get(member.type)});
259 return destructured;
260}
261
262static Type getTypeAtAllIndex(ArrayRef<StructLikeMember> members,
263 Attribute index) {
264 auto indexAttr = cast<StringAttr>(index);
265 if (!indexAttr)
266 return {};
267 for (const auto &member : members) {
268 if (member.name == indexAttr) {
269 return RefType::get(member.type);
270 }
271 }
272 return Type();
273}
274
275static std::optional<uint32_t>
276getFieldAllIndex(ArrayRef<StructLikeMember> members, StringAttr nameField) {
277 for (uint32_t fieldIndex = 0; fieldIndex < members.size(); fieldIndex++)
278 if (members[fieldIndex].name == nameField)
279 return fieldIndex;
280 return std::nullopt;
281}
282
283std::optional<DenseMap<Attribute, Type>> StructType::getSubelementIndexMap() {
284 return getAllSubelementIndexMap(getMembers());
285}
286
287Type StructType::getTypeAtIndex(Attribute index) {
288 return getTypeAtAllIndex(getMembers(), index);
289}
290
291std::optional<uint32_t> StructType::getFieldIndex(StringAttr nameField) {
292 return getFieldAllIndex(getMembers(), nameField);
293}
294
295std::optional<DenseMap<Attribute, Type>>
296UnpackedStructType::getSubelementIndexMap() {
297 return getAllSubelementIndexMap(getMembers());
298}
299
300Type UnpackedStructType::getTypeAtIndex(Attribute index) {
301 return getTypeAtAllIndex(getMembers(), index);
302}
303
304std::optional<uint32_t>
305UnpackedStructType::getFieldIndex(StringAttr nameField) {
306 return getFieldAllIndex(getMembers(), nameField);
307}
308
309std::optional<DenseMap<Attribute, Type>> UnionType::getSubelementIndexMap() {
310 return getAllSubelementIndexMap(getMembers());
311}
312
313Type UnionType::getTypeAtIndex(Attribute index) {
314 return getTypeAtAllIndex(getMembers(), index);
315}
316
317std::optional<uint32_t> UnionType::getFieldIndex(StringAttr nameField) {
318 return getFieldAllIndex(getMembers(), nameField);
319}
320
321std::optional<DenseMap<Attribute, Type>>
322UnpackedUnionType::getSubelementIndexMap() {
323 return getAllSubelementIndexMap(getMembers());
324}
325
326Type UnpackedUnionType::getTypeAtIndex(Attribute index) {
327 return getTypeAtAllIndex(getMembers(), index);
328}
329
330std::optional<uint32_t> UnpackedUnionType::getFieldIndex(StringAttr nameField) {
331 return getFieldAllIndex(getMembers(), nameField);
332}
333
334std::optional<DenseMap<Attribute, Type>> RefType::getSubelementIndexMap() {
335 return TypeSwitch<Type, std::optional<DenseMap<Attribute, Type>>>(
336 getNestedType())
337 .Case<StructType, UnpackedStructType>([](auto &type) {
338 return getAllSubelementIndexMap(type.getMembers());
339 })
340 .Default([](auto) { return std::nullopt; });
341}
342
343Type RefType::getTypeAtIndex(Attribute index) {
344 return TypeSwitch<Type, Type>(getNestedType())
345 .Case<StructType, UnpackedStructType>([&index](auto &type) {
346 return getTypeAtAllIndex(type.getMembers(), index);
347 })
348 .Default([](auto) { return Type(); });
349}
350
351std::optional<uint32_t> RefType::getFieldIndex(StringAttr nameField) {
352 return TypeSwitch<Type, std::optional<uint32_t>>(getNestedType())
353 .Case<StructType, UnpackedStructType>([&nameField](auto &type) {
354 return getFieldAllIndex(type.getMembers(), nameField);
355 })
356 .Default([](auto) { return std::nullopt; });
357}
358
359//===----------------------------------------------------------------------===//
360// Generated logic
361//===----------------------------------------------------------------------===//
362
363#define GET_TYPEDEF_CLASSES
364#include "circt/Dialect/Moore/MooreTypes.cpp.inc"
365
366void MooreDialect::registerTypes() {
367 addTypes<
368#define GET_TYPEDEF_LIST
369#include "circt/Dialect/Moore/MooreTypes.cpp.inc"
370 >();
371}
372
373//===----------------------------------------------------------------------===//
374// Parsing and printing
375//===----------------------------------------------------------------------===//
376
377/// Parse a type registered with this dialect.
378static ParseResult parseMooreType(AsmParser &parser, Type &type) {
379 llvm::SMLoc loc = parser.getCurrentLocation();
380
381 // Try the generated parser first.
382 StringRef mnemonic;
383 if (auto result = generatedTypeParser(parser, &mnemonic, type);
384 result.has_value())
385 return result.value();
386
387 // Handle abbreviated integer types such as `i42` and `l42`.
388 if (mnemonic.size() > 1 && (mnemonic[0] == 'i' || mnemonic[0] == 'l') &&
389 isdigit(mnemonic[1])) {
390 auto domain = mnemonic[0] == 'i' ? Domain::TwoValued : Domain::FourValued;
391 auto spelling = mnemonic.drop_front(1);
392 unsigned width;
393 if (spelling.getAsInteger(10, width))
394 return parser.emitError(loc, "integer width invalid");
395 type = IntType::get(parser.getContext(), width, domain);
396 return success();
397 }
398
399 if (mnemonic == "f32") {
400 type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f32);
401 return success();
402 }
403
404 if (mnemonic == "f64") {
405 type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f64);
406 return success();
407 }
408
409 parser.emitError(loc) << "unknown type `" << mnemonic
410 << "` in dialect `moore`";
411 return failure();
412}
413
414/// Print a type registered with this dialect.
415static void printMooreType(Type type, AsmPrinter &printer) {
416 // Handle abbreviated integer types such as `i42` and `l42`.
417 if (auto intType = dyn_cast<IntType>(type)) {
418 printer << (intType.getDomain() == Domain::TwoValued ? "i" : "l");
419 printer << intType.getWidth();
420 return;
421 }
422 if (auto rt = dyn_cast<moore::RealType>(type)) {
423 if (rt.getWidth() == RealWidth::f32) {
424 printer << "f32";
425 return;
426 }
427 printer << "f64";
428 return;
429 }
430
431 // Otherwise fall back to the generated printer.
432 if (succeeded(generatedTypePrinter(type, printer)))
433 return;
434 assert(false && "no printer for unknown `moore` dialect type");
435}
436
437/// Parse a type registered with this dialect.
438Type MooreDialect::parseType(DialectAsmParser &parser) const {
439 Type type;
440 if (parseMooreType(parser, type))
441 return {};
442 return type;
443}
444
445/// Print a type registered with this dialect.
446void MooreDialect::printType(Type type, DialectAsmPrinter &printer) const {
447 printMooreType(type, printer);
448}
assert(baseType &&"element must be base type")
#define isdigit(x)
Definition FIRLexer.cpp:26
static std::optional< uint32_t > getFieldAllIndex(ArrayRef< StructLikeMember > members, StringAttr nameField)
static LogicalResult verifyAllMembersPacked(function_ref< InFlightDiagnostic()> emitError, ArrayRef< StructLikeMember > members)
static LogicalResult parseMembers(AsmParser &parser, SmallVector< StructLikeMember > &members)
Parse a list of struct members.
static ParseResult parseMooreType(AsmParser &parser, Type &type)
Parse a type registered with this dialect.
static void printMembers(AsmPrinter &printer, ArrayRef< StructLikeMember > members)
Print a list of struct members.
static void printMooreType(Type type, AsmPrinter &printer)
Print a type registered with this dialect.
static Type getTypeAtAllIndex(ArrayRef< StructLikeMember > members, Attribute index)
static std::optional< DenseMap< Attribute, Type > > getAllSubelementIndexMap(ArrayRef< StructLikeMember > members)
A packed SystemVerilog type.
Definition MooreTypes.h:151
bool containsTimeType() const
Check if this is a TimeType, or an aggregate that contains a nested TimeType.
std::optional< unsigned > getBitSize() const
Get the size of this type in bits.
Domain getDomain() const
Get the value domain of this type.
IntType getSimpleBitVector() const
Get the simple bit vector type equivalent to this packed type.
An unpacked SystemVerilog type.
Definition MooreTypes.h:100
std::optional< unsigned > getBitSize() const
Get the size of this type in bits.
Domain getDomain() const
Get the value domain of this type.
static Type parse(mlir::AsmParser &odsParser)
void print(mlir::AsmPrinter &odsPrinter) const
bool isRealType(Type type, unsigned width)
Check if a type is a RealType type of the given width.
Domain
The number of values each bit of a type can assume.
Definition MooreTypes.h:48
@ FourValued
Four-valued types such as logic or integer.
@ TwoValued
Two-valued types such as bit or int.
bool isIntType(Type type, unsigned width)
Check if a type is an IntType type of the given width.
@ f32
A standard 32-Bit floating point number ("float")
@ f64
A 64-bit double-precision floation point number ("double")
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A member of a struct.
Definition MooreTypes.h:183