CIRCT 22.0.0git
Loading...
Searching...
No Matches
Types.cpp
Go to the documentation of this file.
1//===- Types.cpp - Slang type conversion ----------------------------------===//
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
10#include "slang/syntax/AllSyntax.h"
11
12using namespace circt;
13using namespace ImportVerilog;
14using moore::Domain;
15
16namespace {
17struct TypeVisitor {
18 Context &context;
19 Location loc;
20 TypeVisitor(Context &context, Location loc) : context(context), loc(loc) {}
21
22 // Handle simple bit vector types such as `bit`, `int`, or `bit [41:0]`.
23 Type getSimpleBitVectorType(const slang::ast::IntegralType &type) {
24 return moore::IntType::get(context.getContext(), type.bitWidth,
25 type.isFourState ? Domain::FourValued
26 : Domain::TwoValued);
27 }
28
29 // NOLINTBEGIN(misc-no-recursion)
30 Type visit(const slang::ast::VoidType &type) {
31 return moore::VoidType::get(context.getContext());
32 }
33
34 Type visit(const slang::ast::ScalarType &type) {
35 return getSimpleBitVectorType(type);
36 }
37
38 Type visit(const slang::ast::FloatingType &type) {
39 if (type.floatKind == slang::ast::FloatingType::Kind::RealTime)
40 return moore::TimeType::get(context.getContext());
41 return moore::RealType::get(context.getContext());
42 }
43
44 Type visit(const slang::ast::PredefinedIntegerType &type) {
45 if (type.integerKind == slang::ast::PredefinedIntegerType::Kind::Time)
46 return moore::TimeType::get(context.getContext());
47 return getSimpleBitVectorType(type);
48 }
49
50 Type visit(const slang::ast::PackedArrayType &type) {
51 // Handle simple bit vector types of the form `bit [41:0]`.
52 if (type.elementType.as_if<slang::ast::ScalarType>())
53 return getSimpleBitVectorType(type);
54
55 // Handle all other packed arrays.
56 auto innerType = type.elementType.visit(*this);
57 if (!innerType)
58 return {};
59 // The Slang frontend guarantees the inner type to be packed.
60 return moore::ArrayType::get(type.range.width(),
61 cast<moore::PackedType>(innerType));
62 }
63
64 Type visit(const slang::ast::QueueType &type) {
65 auto innerType = type.elementType.visit(*this);
66 if (!innerType)
67 return {};
68 return moore::QueueType::get(cast<moore::UnpackedType>(innerType),
69 type.maxBound);
70 }
71
72 Type visit(const slang::ast::AssociativeArrayType &type) {
73 auto innerType = type.elementType.visit(*this);
74 if (!innerType)
75 return {};
76 if (!type.indexType) {
77 mlir::emitError(
78 loc, "unsupported type: associative arrays with wildcard index");
79 return {};
80 }
81 auto indexType = type.indexType->visit(*this);
82 if (!indexType)
83 return {};
84 return moore::AssocArrayType::get(cast<moore::UnpackedType>(innerType),
85 cast<moore::UnpackedType>(indexType));
86 }
87
88 Type visit(const slang::ast::FixedSizeUnpackedArrayType &type) {
89 auto innerType = type.elementType.visit(*this);
90 if (!innerType)
91 return {};
92 return moore::UnpackedArrayType::get(type.range.width(),
93 cast<moore::UnpackedType>(innerType));
94 }
95
96 Type visit(const slang::ast::DynamicArrayType &type) {
97 auto innerType = type.elementType.visit(*this);
98 if (!innerType)
99 return {};
100 return moore::OpenUnpackedArrayType::get(
101 cast<moore::UnpackedType>(innerType));
102 }
103
104 // Handle type defs.
105 Type visit(const slang::ast::TypeAliasType &type) {
106 // Simply return the underlying type.
107 return type.targetType.getType().visit(*this);
108 }
109
110 // Handle enums.
111 Type visit(const slang::ast::EnumType &type) {
112 // Simply return the underlying type.
113 return type.baseType.visit(*this);
114 }
115
116 // Collect the members in a struct or union.
117 LogicalResult
118 collectMembers(const slang::ast::Scope &structType,
119 SmallVectorImpl<moore::StructLikeMember> &members) {
120 for (auto &field : structType.membersOfType<slang::ast::FieldSymbol>()) {
121 auto name = StringAttr::get(context.getContext(), field.name);
122 auto innerType = context.convertType(*field.getDeclaredType());
123 if (!innerType)
124 return failure();
125 members.push_back({name, cast<moore::UnpackedType>(innerType)});
126 }
127 return success();
128 }
129
130 // Handle packed and unpacked structs.
131 Type visit(const slang::ast::PackedStructType &type) {
132 SmallVector<moore::StructLikeMember> members;
133 if (failed(collectMembers(type, members)))
134 return {};
135 return moore::StructType::get(context.getContext(), members);
136 }
137
138 Type visit(const slang::ast::UnpackedStructType &type) {
139 SmallVector<moore::StructLikeMember> members;
140 if (failed(collectMembers(type, members)))
141 return {};
142 return moore::UnpackedStructType::get(context.getContext(), members);
143 }
144
145 Type visit(const slang::ast::PackedUnionType &type) {
146 SmallVector<moore::StructLikeMember> members;
147 if (failed(collectMembers(type, members)))
148 return {};
149 return moore::UnionType::get(context.getContext(), members);
150 }
151
152 Type visit(const slang::ast::UnpackedUnionType &type) {
153 SmallVector<moore::StructLikeMember> members;
154 if (failed(collectMembers(type, members)))
155 return {};
156 return moore::UnpackedUnionType::get(context.getContext(), members);
157 }
158
159 Type visit(const slang::ast::StringType &type) {
160 return moore::StringType::get(context.getContext());
161 }
162
163 /// Emit an error for all other types.
164 template <typename T>
165 Type visit(T &&node) {
166 auto d = mlir::emitError(loc, "unsupported type: ")
167 << slang::ast::toString(node.kind);
168 d.attachNote() << node.template as<slang::ast::Type>().toString();
169 return {};
170 }
171 // NOLINTEND(misc-no-recursion)
172};
173} // namespace
174
175// NOLINTBEGIN(misc-no-recursion)
176Type Context::convertType(const slang::ast::Type &type, LocationAttr loc) {
177 if (!loc)
178 loc = convertLocation(type.location);
179 return type.visit(TypeVisitor(*this, loc));
180}
181
182Type Context::convertType(const slang::ast::DeclaredType &type) {
183 LocationAttr loc;
184 if (auto *ts = type.getTypeSyntax())
185 loc = convertLocation(ts->sourceRange().start());
186 return convertType(type.getType(), loc);
187}
188// NOLINTEND(misc-no-recursion)
mlir::Type innerType(mlir::Type type)
Definition ESITypes.cpp:227
Domain
The number of values each bit of a type can assume.
Definition MooreTypes.h:48
@ TwoValued
Two-valued types such as bit or int.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
Definition Types.cpp:176
MLIRContext * getContext()
Return the MLIR context.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.