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