CIRCT 24.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// Wrapper Type
124//===----------------------------------------------------------------------===//
125
127 return TypeSwitch<WrapperType, UnpackedType>(*this).Case<RefType, NetType>(
128 [](auto type) { return type.getNestedType(); });
129}
130
132 return TypeSwitch<WrapperType, WrapperType>(*this).Case<RefType, NetType>(
133 [&](auto type) { return decltype(type)::get(nestedType); });
134}
135
136//===----------------------------------------------------------------------===//
137// Packed Type
138//===----------------------------------------------------------------------===//
139
141 return TypeSwitch<PackedType, Domain>(*this)
142 .Case<VoidType>([](auto) { return Domain::TwoValued; })
143 .Case<IntType>([&](auto type) { return type.getDomain(); })
144 .Case<TimeType>([](auto) { return Domain::FourValued; })
145 .Case<ArrayType, OpenArrayType>(
146 [&](auto type) { return type.getElementType().getDomain(); })
147 .Case<StructType, UnionType>([](auto type) {
148 for (const auto &member : type.getMembers())
149 if (member.type.getDomain() == Domain::FourValued)
150 return Domain::FourValued;
151 return Domain::TwoValued;
152 });
153}
154
155std::optional<unsigned> PackedType::getBitSize() const {
156 return TypeSwitch<PackedType, std::optional<unsigned>>(*this)
157 .Case<VoidType>([](auto) { return 0; })
158 .Case<IntType>([](auto type) { return type.getWidth(); })
159 .Case<TimeType>([](auto type) { return 64; })
160 .Case<ArrayType>([](auto type) -> std::optional<unsigned> {
161 if (auto size = type.getElementType().getBitSize())
162 return (*size) * type.getSize();
163 return {};
164 })
165 .Case<OpenArrayType>([](auto) { return std::nullopt; })
166 .Case<StructType>([](auto type) -> std::optional<unsigned> {
167 unsigned size = 0;
168 for (const auto &member : type.getMembers()) {
169 if (auto memberSize = member.type.getBitSize()) {
170 size += *memberSize;
171 } else {
172 return std::nullopt;
173 }
174 }
175 return size;
176 })
177 .Case<UnionType>([](auto type) -> std::optional<unsigned> {
178 unsigned size = 0;
179 for (const auto &member : type.getMembers()) {
180 if (auto memberSize = member.type.getBitSize()) {
181 size = (*memberSize > size) ? *memberSize : size;
182 } else {
183 return std::nullopt;
184 }
185 }
186 return size;
187 })
188 .Default([](auto) { return std::nullopt; });
189}
190
192 if (auto intType = dyn_cast<IntType>(*this))
193 return intType;
194 if (auto bitSize = getBitSize())
195 return IntType::get(getContext(), *bitSize, getDomain());
196 return {};
197}
198
200 return TypeSwitch<PackedType, bool>(*this)
201 .Case<VoidType, IntType>([](auto) { return false; })
202 .Case<TimeType>([](auto) { return true; })
203 .Case<ArrayType, OpenArrayType>(
204 [](auto type) { return type.getElementType().containsTimeType(); })
205 .Case<StructType, UnionType>([](auto type) {
206 return llvm::any_of(type.getMembers(), [](auto &member) {
207 return cast<PackedType>(member.type).containsTimeType();
208 });
209 });
210}
211
212//===----------------------------------------------------------------------===//
213// Structs
214//===----------------------------------------------------------------------===//
215
216/// Parse a list of struct members.
217static LogicalResult parseMembers(AsmParser &parser,
218 SmallVector<StructLikeMember> &members) {
219 return parser.parseCommaSeparatedList(AsmParser::Delimiter::Braces, [&]() {
220 std::string name;
221 UnpackedType type;
222 if (parser.parseKeywordOrString(&name) || parser.parseColon() ||
223 parser.parseCustomTypeWithFallback(type))
224 return failure();
225
226 members.push_back({StringAttr::get(parser.getContext(), name), type});
227 return success();
228 });
229}
230
231/// Print a list of struct members.
232static void printMembers(AsmPrinter &printer,
233 ArrayRef<StructLikeMember> members) {
234 printer << "{";
235 llvm::interleaveComma(members, printer.getStream(),
236 [&](const StructLikeMember &member) {
237 printer.printKeywordOrString(member.name);
238 printer << ": ";
239 printer.printStrippedAttrOrType(member.type);
240 });
241 printer << "}";
242}
243
244static LogicalResult
245verifyAllMembersPacked(function_ref<InFlightDiagnostic()> emitError,
246 ArrayRef<StructLikeMember> members) {
247 if (!llvm::all_of(members, [](const auto &member) {
248 return llvm::isa<PackedType>(member.type);
249 }))
250 return emitError() << "StructType/UnionType members must be packed types";
251 return success();
252}
253
254LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
255 ArrayRef<StructLikeMember> members) {
256 return verifyAllMembersPacked(emitError, members);
257}
258
259LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
260 ArrayRef<StructLikeMember> members) {
261 return verifyAllMembersPacked(emitError, members);
262}
263
264//===----------------------------------------------------------------------===//
265// Interfaces for destructurable
266//===----------------------------------------------------------------------===//
267
268template <typename WrapperTy = RefType>
269static std::optional<DenseMap<Attribute, Type>>
270getAllSubelementIndexMap(ArrayRef<StructLikeMember> members) {
271 DenseMap<Attribute, Type> destructured;
272 for (const auto &member : members)
273 destructured.insert({member.name, WrapperTy::get(member.type)});
274 return destructured;
275}
276
277template <typename WrapperTy = RefType>
278static Type getTypeAtAllIndex(ArrayRef<StructLikeMember> members,
279 Attribute index) {
280 auto indexAttr = cast<StringAttr>(index);
281 if (!indexAttr)
282 return {};
283 for (const auto &member : members) {
284 if (member.name == indexAttr) {
285 return WrapperTy::get(member.type);
286 }
287 }
288 return Type();
289}
290
291static std::optional<uint32_t>
292getFieldAllIndex(ArrayRef<StructLikeMember> members, StringAttr nameField) {
293 for (uint32_t fieldIndex = 0; fieldIndex < members.size(); fieldIndex++)
294 if (members[fieldIndex].name == nameField)
295 return fieldIndex;
296 return std::nullopt;
297}
298
299std::optional<DenseMap<Attribute, Type>> StructType::getSubelementIndexMap() {
300 return getAllSubelementIndexMap(getMembers());
301}
302
303Type StructType::getTypeAtIndex(Attribute index) {
304 return getTypeAtAllIndex(getMembers(), index);
305}
306
307std::optional<uint32_t> StructType::getFieldIndex(StringAttr nameField) {
308 return getFieldAllIndex(getMembers(), nameField);
309}
310
311std::optional<DenseMap<Attribute, Type>>
312UnpackedStructType::getSubelementIndexMap() {
313 return getAllSubelementIndexMap(getMembers());
314}
315
316Type UnpackedStructType::getTypeAtIndex(Attribute index) {
317 return getTypeAtAllIndex(getMembers(), index);
318}
319
320std::optional<uint32_t>
321UnpackedStructType::getFieldIndex(StringAttr nameField) {
322 return getFieldAllIndex(getMembers(), nameField);
323}
324
325std::optional<DenseMap<Attribute, Type>> UnionType::getSubelementIndexMap() {
326 return getAllSubelementIndexMap(getMembers());
327}
328
329Type UnionType::getTypeAtIndex(Attribute index) {
330 return getTypeAtAllIndex(getMembers(), index);
331}
332
333std::optional<uint32_t> UnionType::getFieldIndex(StringAttr nameField) {
334 return getFieldAllIndex(getMembers(), nameField);
335}
336
337std::optional<DenseMap<Attribute, Type>>
338UnpackedUnionType::getSubelementIndexMap() {
339 return getAllSubelementIndexMap(getMembers());
340}
341
342Type UnpackedUnionType::getTypeAtIndex(Attribute index) {
343 return getTypeAtAllIndex(getMembers(), index);
344}
345
346std::optional<uint32_t> UnpackedUnionType::getFieldIndex(StringAttr nameField) {
347 return getFieldAllIndex(getMembers(), nameField);
348}
349
350std::optional<DenseMap<Attribute, Type>> RefType::getSubelementIndexMap() {
351 return TypeSwitch<Type, std::optional<DenseMap<Attribute, Type>>>(
352 getNestedType())
353 .Case<StructType, UnpackedStructType>([](auto &type) {
354 return getAllSubelementIndexMap(type.getMembers());
355 })
356 .Default([](auto) { return std::nullopt; });
357}
358
359Type RefType::getTypeAtIndex(Attribute index) {
360 return TypeSwitch<Type, Type>(getNestedType())
361 .Case<StructType, UnpackedStructType>([&index](auto &type) {
362 return getTypeAtAllIndex(type.getMembers(), index);
363 })
364 .Default([](auto) { return Type(); });
365}
366
367std::optional<uint32_t> RefType::getFieldIndex(StringAttr nameField) {
368 return TypeSwitch<Type, std::optional<uint32_t>>(getNestedType())
369 .Case<StructType, UnpackedStructType>([&nameField](auto &type) {
370 return getFieldAllIndex(type.getMembers(), nameField);
371 })
372 .Default([](auto) { return std::nullopt; });
373}
374
375std::optional<DenseMap<Attribute, Type>> NetType::getSubelementIndexMap() {
376 return TypeSwitch<Type, std::optional<DenseMap<Attribute, Type>>>(
377 getNestedType())
378 .Case<StructType, UnpackedStructType>([](auto &type) {
379 return getAllSubelementIndexMap<NetType>(type.getMembers());
380 })
381 .Default([](auto) { return std::nullopt; });
382}
383
384Type NetType::getTypeAtIndex(Attribute index) {
385 return TypeSwitch<Type, Type>(getNestedType())
386 .Case<StructType, UnpackedStructType>([&index](auto &type) {
387 return getTypeAtAllIndex<NetType>(type.getMembers(), index);
388 })
389 .Default([](auto) { return Type(); });
390}
391
392std::optional<uint32_t> NetType::getFieldIndex(StringAttr nameField) {
393 return TypeSwitch<Type, std::optional<uint32_t>>(getNestedType())
394 .Case<StructType, UnpackedStructType>([&nameField](auto &type) {
395 return getFieldAllIndex(type.getMembers(), nameField);
396 })
397 .Default([](auto) { return std::nullopt; });
398}
399
400//===----------------------------------------------------------------------===//
401// Generated logic
402//===----------------------------------------------------------------------===//
403
404#define GET_TYPEDEF_CLASSES
405#include "circt/Dialect/Moore/MooreTypes.cpp.inc"
406
407void MooreDialect::registerTypes() {
408 addTypes<
409#define GET_TYPEDEF_LIST
410#include "circt/Dialect/Moore/MooreTypes.cpp.inc"
411 >();
412}
413
414//===----------------------------------------------------------------------===//
415// Parsing and printing
416//===----------------------------------------------------------------------===//
417
418/// Parse a type registered with this dialect.
419static ParseResult parseMooreType(AsmParser &parser, Type &type) {
420 llvm::SMLoc loc = parser.getCurrentLocation();
421
422 // Try the generated parser first.
423 StringRef mnemonic;
424 if (auto result = generatedTypeParser(parser, &mnemonic, type);
425 result.has_value())
426 return result.value();
427
428 // Handle abbreviated integer types such as `i42` and `l42`.
429 if (mnemonic.size() > 1 && (mnemonic[0] == 'i' || mnemonic[0] == 'l') &&
430 isdigit(mnemonic[1])) {
431 auto domain = mnemonic[0] == 'i' ? Domain::TwoValued : Domain::FourValued;
432 auto spelling = mnemonic.drop_front(1);
433 unsigned width;
434 if (spelling.getAsInteger(10, width))
435 return parser.emitError(loc, "integer width invalid");
436 type = IntType::get(parser.getContext(), width, domain);
437 return success();
438 }
439
440 if (mnemonic == "f32") {
441 type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f32);
442 return success();
443 }
444
445 if (mnemonic == "f64") {
446 type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f64);
447 return success();
448 }
449
450 parser.emitError(loc) << "unknown type `" << mnemonic
451 << "` in dialect `moore`";
452 return failure();
453}
454
455/// Print a type registered with this dialect.
456static void printMooreType(Type type, AsmPrinter &printer) {
457 // Handle abbreviated integer types such as `i42` and `l42`.
458 if (auto intType = dyn_cast<IntType>(type)) {
459 printer << (intType.getDomain() == Domain::TwoValued ? "i" : "l");
460 printer << intType.getWidth();
461 return;
462 }
463 if (auto rt = dyn_cast<moore::RealType>(type)) {
464 if (rt.getWidth() == RealWidth::f32) {
465 printer << "f32";
466 return;
467 }
468 printer << "f64";
469 return;
470 }
471
472 // Otherwise fall back to the generated printer.
473 if (succeeded(generatedTypePrinter(type, printer)))
474 return;
475 assert(false && "no printer for unknown `moore` dialect type");
476}
477
478/// Parse a type registered with this dialect.
479Type MooreDialect::parseType(DialectAsmParser &parser) const {
480 Type type;
481 if (parseMooreType(parser, type))
482 return {};
483 return type;
484}
485
486/// Print a type registered with this dialect.
487void MooreDialect::printType(Type type, DialectAsmPrinter &printer) const {
488 printMooreType(type, printer);
489}
assert(baseType &&"element must be base type")
#define isdigit(x)
Definition FIRLexer.cpp:26
false return failure()
Parse an optional keyword or string and set instance into 'result'.
return success()
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 Type getTypeAtAllIndex(ArrayRef< StructLikeMember > members, Attribute index)
static void printMooreType(Type type, AsmPrinter &printer)
Print a type registered with this dialect.
static std::optional< DenseMap< Attribute, Type > > getAllSubelementIndexMap(ArrayRef< StructLikeMember > members)
A packed SystemVerilog type.
Definition MooreTypes.h:155
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:103
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
UnpackedType getNestedType() const
Get the wrapped type.
WrapperType withNestedType(UnpackedType nestedType) const
Get a wrapper of the same kind around a different nested type.
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:51
@ FourValued
Four-valued types such as logic or integer.
Definition MooreTypes.h:55
@ TwoValued
Two-valued types such as bit or int.
Definition MooreTypes.h:53
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").
Definition MooreTypes.h:61
@ f64
A 64-bit double-precision floation point number ("double").
Definition MooreTypes.h:63
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A member of a struct.
Definition MooreTypes.h:205