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