CIRCT 20.0.0git
Loading...
Searching...
No Matches
SystemCTypes.cpp
Go to the documentation of this file.
1//===- SystemCTypes.cpp - Implement the SystemC 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 SystemC 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::systemc;
21
23 return TypeSwitch<Type, Type>(type)
24 .Case<InputType, OutputType, InOutType, SignalType>(
25 [](auto ty) { return ty.getBaseType(); })
26 .Default([](auto ty) { return Type(); });
27}
28
29std::optional<size_t> systemc::getBitWidth(Type type) {
30 return llvm::TypeSwitch<Type, std::optional<size_t>>(type)
31 .Case<IntegerType, IntType, UIntType, BigIntType, BigUIntType,
33 [](auto ty) { return ty.getWidth(); })
34 .Case<LogicType>([](auto ty) { return 1; })
35 .Default([](auto ty) { return std::nullopt; });
36}
37
38namespace circt {
39namespace systemc {
40namespace detail {
41bool operator==(const PortInfo &a, const PortInfo &b) {
42 return a.name == b.name && a.type == b.type;
43}
44// NOLINTNEXTLINE(readability-identifier-naming)
45llvm::hash_code hash_value(const PortInfo &pi) {
46 return llvm::hash_combine(pi.name, pi.type);
47}
48} // namespace detail
49} // namespace systemc
50} // namespace circt
51
52//===----------------------------------------------------------------------===//
53// ModuleType
54//===----------------------------------------------------------------------===//
55
56/// Parses a systemc::ModuleType of the format:
57/// !systemc.module<moduleName(portName1: type1, portName2: type2)>
58Type ModuleType::parse(AsmParser &odsParser) {
59 if (odsParser.parseLess())
60 return Type();
61
62 StringRef moduleName;
63 if (odsParser.parseKeyword(&moduleName))
64 return Type();
65
66 SmallVector<ModuleType::PortInfo> ports;
67
68 if (odsParser.parseCommaSeparatedList(
69 AsmParser::Delimiter::Paren, [&]() -> ParseResult {
70 StringRef name;
71 PortInfo port;
72 if (odsParser.parseKeyword(&name) || odsParser.parseColon() ||
73 odsParser.parseType(port.type))
74 return failure();
75
76 port.name = StringAttr::get(odsParser.getContext(), name);
77 ports.push_back(port);
78
79 return success();
80 }))
81 return Type();
82
83 if (odsParser.parseGreater())
84 return Type();
85
86 return ModuleType::getChecked(
87 UnknownLoc::get(odsParser.getContext()), odsParser.getContext(),
88 StringAttr::get(odsParser.getContext(), moduleName), ports);
89}
90
91/// Prints a systemc::ModuleType in the format:
92/// !systemc.module<moduleName(portName1: type1, portName2: type2)>
93void ModuleType::print(AsmPrinter &odsPrinter) const {
94 odsPrinter << '<' << getModuleName().getValue() << '(';
95 llvm::interleaveComma(getPorts(), odsPrinter, [&](auto port) {
96 odsPrinter << port.name.getValue() << ": " << port.type;
97 });
98 odsPrinter << ")>";
99}
100
101//===----------------------------------------------------------------------===//
102// Type storages
103//===----------------------------------------------------------------------===//
104
105namespace circt {
106namespace systemc {
107namespace detail {
108
109/// Integer Type Storage and Uniquing.
110struct IntegerWidthStorage : public TypeStorage {
112
113 /// The hash key used for uniquing.
114 using KeyTy = unsigned;
115
116 static llvm::hash_code hashKey(const KeyTy &key) {
117 return llvm::hash_value(key);
118 }
119
120 bool operator==(const KeyTy &key) const { return KeyTy(width) == key; }
121
122 static IntegerWidthStorage *construct(mlir::TypeStorageAllocator &allocator,
123 KeyTy key) {
124 return new (allocator.allocate<IntegerWidthStorage>())
126 }
127
128 unsigned width : 32;
129};
130
131} // namespace detail
132} // namespace systemc
133} // namespace circt
134
135//===----------------------------------------------------------------------===//
136// Integer types
137//===----------------------------------------------------------------------===//
138
139IntBaseType IntBaseType::get(MLIRContext *context) {
140 return Base::get(context);
141}
142
143IntType IntType::get(MLIRContext *context, unsigned width) {
144 return Base::get(context, width);
145}
146
147unsigned IntType::getWidth() { return getImpl()->width; }
148
149UIntBaseType UIntBaseType::get(MLIRContext *context) {
150 return Base::get(context);
151}
152
153UIntType UIntType::get(MLIRContext *context, unsigned width) {
154 return Base::get(context, width);
155}
156unsigned UIntType::getWidth() { return getImpl()->width; }
157
158SignedType SignedType::get(MLIRContext *context) { return Base::get(context); }
159
160BigIntType BigIntType::get(MLIRContext *context, unsigned width) {
161 return Base::get(context, width);
162}
163unsigned BigIntType::getWidth() { return getImpl()->width; }
164
165UnsignedType UnsignedType::get(MLIRContext *context) {
166 return Base::get(context);
167}
168
169BigUIntType BigUIntType::get(MLIRContext *context, unsigned width) {
170 return Base::get(context, width);
171}
172
173unsigned BigUIntType::getWidth() { return getImpl()->width; }
174
175//===----------------------------------------------------------------------===//
176// Bit-vector types
177//===----------------------------------------------------------------------===//
178
180 return Base::get(context);
181}
182
183BitVectorType BitVectorType::get(MLIRContext *context, unsigned width) {
184 return Base::get(context, width);
185}
186
187unsigned BitVectorType::getWidth() { return getImpl()->width; }
188
190 return Base::get(context);
191}
192
193LogicVectorType LogicVectorType::get(MLIRContext *context, unsigned width) {
194 return Base::get(context, width);
195}
196
197unsigned LogicVectorType::getWidth() { return getImpl()->width; }
198
199//===----------------------------------------------------------------------===//
200// Generated logic
201//===----------------------------------------------------------------------===//
202
203#define GET_TYPEDEF_CLASSES
204#include "circt/Dialect/SystemC/SystemCTypes.cpp.inc"
205
206void SystemCDialect::registerTypes() {
207 addTypes<
208#define GET_TYPEDEF_LIST
209#include "circt/Dialect/SystemC/SystemCTypes.cpp.inc"
210 >();
214}
215
216//===----------------------------------------------------------------------===//
217// Custom type parsers and printers
218//===----------------------------------------------------------------------===//
219
220template <typename Ty>
221static LogicalResult parseIntegerOrBitVector(DialectAsmParser &parser,
222 Type &type) {
223 unsigned width;
224 auto *ctxt = parser.getContext();
225
226 if (parser.parseLess() || parser.parseInteger(width) || parser.parseGreater())
227 return failure();
228
229 type = Ty::get(ctxt, width);
230 return success();
231}
232
233static mlir::OptionalParseResult customTypeParser(DialectAsmParser &parser,
234 StringRef mnemonic,
235 llvm::SMLoc loc, Type &type) {
236 auto *ctxt = parser.getContext();
237
238 if (mnemonic == IntBaseType::getMnemonic()) {
239 type = IntBaseType::get(ctxt);
240 return success();
241 }
242 if (mnemonic == UIntBaseType::getMnemonic()) {
243 type = UIntBaseType::get(ctxt);
244 return success();
245 }
246 if (mnemonic == SignedType::getMnemonic()) {
247 type = SignedType::get(ctxt);
248 return success();
249 }
250 if (mnemonic == UnsignedType::getMnemonic()) {
251 type = UnsignedType::get(ctxt);
252 return success();
253 }
254 if (mnemonic == BitVectorBaseType::getMnemonic()) {
255 type = BitVectorBaseType::get(ctxt);
256 return success();
257 }
258 if (mnemonic == LogicVectorBaseType::getMnemonic()) {
259 type = LogicVectorBaseType::get(ctxt);
260 return success();
261 }
262 if (mnemonic == IntType::getMnemonic())
263 return parseIntegerOrBitVector<IntType>(parser, type);
264 if (mnemonic == UIntType::getMnemonic())
265 return parseIntegerOrBitVector<UIntType>(parser, type);
266 if (mnemonic == BigIntType::getMnemonic())
267 return parseIntegerOrBitVector<BigIntType>(parser, type);
268 if (mnemonic == BigUIntType::getMnemonic())
269 return parseIntegerOrBitVector<BigUIntType>(parser, type);
270 if (mnemonic == BitVectorType::getMnemonic())
271 return parseIntegerOrBitVector<BitVectorType>(parser, type);
272 if (mnemonic == LogicVectorType::getMnemonic())
273 return parseIntegerOrBitVector<LogicVectorType>(parser, type);
274
275 return failure();
276}
277
278static LogicalResult customTypePrinter(Type type, DialectAsmPrinter &printer) {
279 return TypeSwitch<Type, LogicalResult>(type)
281 LogicVectorType>([&](auto ty) {
282 printer << ty.getMnemonic() << "<" << ty.getWidth() << ">";
283 return success();
284 })
287 printer << ty.getMnemonic();
288 return success();
289 })
290 .Default([](auto ty) { return failure(); });
291}
292
293/// Parse a type registered with this dialect.
294Type SystemCDialect::parseType(DialectAsmParser &parser) const {
295 Type type;
296 llvm::SMLoc loc = parser.getCurrentLocation();
297 StringRef mnemonic;
298
299 mlir::OptionalParseResult result =
300 generatedTypeParser(parser, &mnemonic, type);
301 if (result.has_value() && !result.value())
302 return type;
303
304 result = customTypeParser(parser, mnemonic, loc, type);
305 if (result.has_value() && !result.value())
306 return type;
307
308 parser.emitError(loc) << "unknown type `" << mnemonic
309 << "` in dialect `systemc`";
310 return {};
311}
312
313/// Print a type registered with this dialect.
314void SystemCDialect::printType(Type type, DialectAsmPrinter &printer) const {
315 if (succeeded(generatedTypePrinter(type, printer)) ||
316 succeeded(customTypePrinter(type, printer)))
317 return;
318
319 assert(false && "no printer for unknown `systemc` dialect type");
320 printer << "<<UnknownType>>";
321}
assert(baseType &&"element must be base type")
static LogicalResult customTypePrinter(Type type, AsmPrinter &os)
Print a type with a custom printer implementation.
static OptionalParseResult customTypeParser(AsmParser &parser, StringRef name, Type &result)
Parse a type with a custom parser implementation.
static LogicalResult parseIntegerOrBitVector(DialectAsmParser &parser, Type &type)
Represents a finite word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
static BigIntType get(MLIRContext *context, unsigned width)
static constexpr StringLiteral getMnemonic()
Represents a finite word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
static constexpr StringLiteral getMnemonic()
static BigUIntType get(MLIRContext *context, unsigned width)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
static constexpr StringLiteral getMnemonic()
static BitVectorBaseType get(MLIRContext *context)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
static constexpr StringLiteral getMnemonic()
static BitVectorType get(MLIRContext *context, unsigned width)
Represents a limited word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
static constexpr StringLiteral getMnemonic()
static IntBaseType get(MLIRContext *context)
Represents a limited word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
static constexpr StringLiteral getMnemonic()
static IntType get(MLIRContext *context, unsigned width)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
static LogicVectorBaseType get(MLIRContext *context)
static constexpr StringLiteral getMnemonic()
Represents a finite word-length bit vector (of four-state values) in SystemC as described in IEEE 166...
static LogicVectorType get(MLIRContext *context, unsigned width)
static constexpr StringLiteral getMnemonic()
Represents a finite word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
static SignedType get(MLIRContext *context)
static constexpr StringLiteral getMnemonic()
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
static UIntBaseType get(MLIRContext *context)
static constexpr StringLiteral getMnemonic()
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
static UIntType get(MLIRContext *context, unsigned width)
static constexpr StringLiteral getMnemonic()
Represents a finite word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
static constexpr StringLiteral getMnemonic()
static UnsignedType get(MLIRContext *context)
bool operator==(const PortInfo &a, const PortInfo &b)
llvm::hash_code hash_value(const PortInfo &pi)
Type getSignalBaseType(Type type)
Get the type wrapped by a signal or port (in, inout, out) type.
std::optional< size_t > getBitWidth(Type type)
Return the bitwidth of a type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Integer Type Storage and Uniquing.
bool operator==(const KeyTy &key) const
unsigned KeyTy
The hash key used for uniquing.
static llvm::hash_code hashKey(const KeyTy &key)
static IntegerWidthStorage * construct(mlir::TypeStorageAllocator &allocator, KeyTy key)
A struct containing minimal information for a systemc module port.