CIRCT 23.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 if (type.floatKind == slang::ast::FloatingType::Kind::Real)
42 return moore::RealType::get(context.getContext(), moore::RealWidth::f64);
43 return moore::RealType::get(context.getContext(), moore::RealWidth::f32);
44 }
45
46 Type visit(const slang::ast::PredefinedIntegerType &type) {
47 if (type.integerKind == slang::ast::PredefinedIntegerType::Kind::Time)
48 return moore::TimeType::get(context.getContext());
49 return getSimpleBitVectorType(type);
50 }
51
52 Type visit(const slang::ast::PackedArrayType &type) {
53 // Handle simple bit vector types of the form `bit [41:0]`.
54 if (type.elementType.as_if<slang::ast::ScalarType>())
55 return getSimpleBitVectorType(type);
56
57 // Handle all other packed arrays.
58 auto innerType = type.elementType.visit(*this);
59 if (!innerType)
60 return {};
61 // The Slang frontend guarantees the inner type to be packed.
62 return moore::ArrayType::get(type.range.width(),
63 cast<moore::PackedType>(innerType));
64 }
65
66 Type visit(const slang::ast::QueueType &type) {
67 auto innerType = type.elementType.visit(*this);
68 if (!innerType)
69 return {};
70 return moore::QueueType::get(cast<moore::UnpackedType>(innerType),
71 type.maxBound);
72 }
73
74 Type visit(const slang::ast::AssociativeArrayType &type) {
75 auto innerType = type.elementType.visit(*this);
76 if (!innerType)
77 return {};
78 if (!type.indexType) {
79 mlir::emitError(
80 loc, "unsupported type: associative arrays with wildcard index");
81 return {};
82 }
83 auto indexType = type.indexType->visit(*this);
84 if (!indexType)
85 return {};
86 return moore::AssocArrayType::get(cast<moore::UnpackedType>(innerType),
87 cast<moore::UnpackedType>(indexType));
88 }
89
90 Type visit(const slang::ast::FixedSizeUnpackedArrayType &type) {
91 auto innerType = type.elementType.visit(*this);
92 if (!innerType)
93 return {};
94 return moore::UnpackedArrayType::get(type.range.width(),
95 cast<moore::UnpackedType>(innerType));
96 }
97
98 Type visit(const slang::ast::DynamicArrayType &type) {
99 auto innerType = type.elementType.visit(*this);
100 if (!innerType)
101 return {};
102 return moore::OpenUnpackedArrayType::get(
103 cast<moore::UnpackedType>(innerType));
104 }
105
106 Type visit(const slang::ast::DPIOpenArrayType &type) {
107 auto innerType = type.elementType.visit(*this);
108 if (!innerType)
109 return {};
110 if (type.isPacked)
111 return moore::OpenArrayType::get(cast<moore::PackedType>(innerType));
112 return moore::OpenUnpackedArrayType::get(
113 cast<moore::UnpackedType>(innerType));
114 }
115
116 // Handle type defs.
117 Type visit(const slang::ast::TypeAliasType &type) {
118 // Simply return the underlying type.
119 return type.targetType.getType().visit(*this);
120 }
121
122 // Handle enums.
123 Type visit(const slang::ast::EnumType &type) {
124 // Simply return the underlying type.
125 return type.baseType.visit(*this);
126 }
127
128 // Collect the members in a struct or union.
129 LogicalResult
130 collectMembers(const slang::ast::Scope &structType,
131 SmallVectorImpl<moore::StructLikeMember> &members) {
132 for (auto &field : structType.membersOfType<slang::ast::FieldSymbol>()) {
133 auto name = StringAttr::get(context.getContext(), field.name);
134 auto innerType = context.convertType(*field.getDeclaredType());
135 if (!innerType)
136 return failure();
137 members.push_back({name, cast<moore::UnpackedType>(innerType)});
138 }
139 return success();
140 }
141
142 // Handle packed and unpacked structs.
143 Type visit(const slang::ast::PackedStructType &type) {
144 SmallVector<moore::StructLikeMember> members;
145 if (failed(collectMembers(type, members)))
146 return {};
147 return moore::StructType::get(context.getContext(), members);
148 }
149
150 Type visit(const slang::ast::UnpackedStructType &type) {
151 SmallVector<moore::StructLikeMember> members;
152 if (failed(collectMembers(type, members)))
153 return {};
154 return moore::UnpackedStructType::get(context.getContext(), members);
155 }
156
157 Type visit(const slang::ast::PackedUnionType &type) {
158 SmallVector<moore::StructLikeMember> members;
159 if (failed(collectMembers(type, members)))
160 return {};
161 return moore::UnionType::get(context.getContext(), members);
162 }
163
164 Type visit(const slang::ast::UnpackedUnionType &type) {
165 SmallVector<moore::StructLikeMember> members;
166 if (failed(collectMembers(type, members)))
167 return {};
168 return moore::UnpackedUnionType::get(context.getContext(), members);
169 }
170
171 Type visit(const slang::ast::StringType &type) {
172 return moore::StringType::get(context.getContext());
173 }
174
175 Type visit(const slang::ast::CHandleType &type) {
176 return moore::ChandleType::get(context.getContext());
177 }
178
179 Type visit(const slang::ast::ClassType &type) {
180 if (failed(context.buildClassProperties(type)))
181 return {};
182 auto *lowering = context.declareClass(type);
183 if (!lowering) {
184 mlir::emitError(loc) << "no lowering generated for class type `"
185 << type.toString() << "`";
186 return {};
187 }
188 mlir::StringAttr symName = lowering->op.getSymNameAttr();
189 mlir::FlatSymbolRefAttr symRef = mlir::FlatSymbolRefAttr::get(symName);
190 return moore::ClassHandleType::get(context.getContext(), symRef);
191 }
192
193 Type visit(const slang::ast::NullType &type) {
194 return moore::NullType::get(context.getContext());
195 }
196
197 Type visit(const slang::ast::EventType &type) {
198 // Treat `event` types as simple `i1` values where an event is signaled by
199 // toggling the value.
200 return moore::IntType::getInt(context.getContext(), 1);
201 }
202
203 /// Emit an error for all other types.
204 template <typename T>
205 Type visit(T &&node) {
206 auto d = mlir::emitError(loc, "unsupported type: ")
207 << slang::ast::toString(node.kind);
208 d.attachNote() << node.template as<slang::ast::Type>().toString();
209 return {};
210 }
211 // NOLINTEND(misc-no-recursion)
212};
213} // namespace
214
215// NOLINTBEGIN(misc-no-recursion)
216Type Context::convertType(const slang::ast::Type &type, LocationAttr loc) {
217 if (!loc)
218 loc = convertLocation(type.location);
219 return type.visit(TypeVisitor(*this, loc));
220}
221
222Type Context::convertType(const slang::ast::DeclaredType &type) {
223 LocationAttr loc;
224 if (auto *ts = type.getTypeSyntax())
225 loc = convertLocation(ts->sourceRange().start());
226 return convertType(type.getType(), loc);
227}
228// NOLINTEND(misc-no-recursion)
mlir::Type innerType(mlir::Type type)
Definition ESITypes.cpp:422
Domain
The number of values each bit of a type can assume.
Definition MooreTypes.h:49
@ 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:216
ClassLowering * declareClass(const slang::ast::ClassType &cls)
LogicalResult buildClassProperties(const slang::ast::ClassType &classdecl)
MLIRContext * getContext()
Return the MLIR context.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.