CIRCT  19.0.0git
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 
19 using namespace circt;
20 using namespace circt::systemc;
21 
22 Type systemc::getSignalBaseType(Type type) {
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 
29 std::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 
38 namespace circt {
39 namespace systemc {
40 namespace detail {
41 bool operator==(const PortInfo &a, const PortInfo &b) {
42  return a.name == b.name && a.type == b.type;
43 }
44 // NOLINTNEXTLINE(readability-identifier-naming)
45 llvm::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)>
58 Type 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)>
93 void 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 
105 namespace circt {
106 namespace systemc {
107 namespace detail {
108 
109 /// Integer Type Storage and Uniquing.
110 struct 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>())
125  IntegerWidthStorage(key);
126  }
127 
128  unsigned width : 32;
129 };
130 
131 } // namespace detail
132 } // namespace systemc
133 } // namespace circt
134 
135 //===----------------------------------------------------------------------===//
136 // Integer types
137 //===----------------------------------------------------------------------===//
138 
139 IntBaseType IntBaseType::get(MLIRContext *context) {
140  return Base::get(context);
141 }
142 
143 IntType IntType::get(MLIRContext *context, unsigned width) {
144  return Base::get(context, width);
145 }
146 
147 unsigned IntType::getWidth() { return getImpl()->width; }
148 
149 UIntBaseType UIntBaseType::get(MLIRContext *context) {
150  return Base::get(context);
151 }
152 
153 UIntType UIntType::get(MLIRContext *context, unsigned width) {
154  return Base::get(context, width);
155 }
156 unsigned UIntType::getWidth() { return getImpl()->width; }
157 
158 SignedType SignedType::get(MLIRContext *context) { return Base::get(context); }
159 
160 BigIntType BigIntType::get(MLIRContext *context, unsigned width) {
161  return Base::get(context, width);
162 }
163 unsigned BigIntType::getWidth() { return getImpl()->width; }
164 
165 UnsignedType UnsignedType::get(MLIRContext *context) {
166  return Base::get(context);
167 }
168 
169 BigUIntType BigUIntType::get(MLIRContext *context, unsigned width) {
170  return Base::get(context, width);
171 }
172 
173 unsigned BigUIntType::getWidth() { return getImpl()->width; }
174 
175 //===----------------------------------------------------------------------===//
176 // Bit-vector types
177 //===----------------------------------------------------------------------===//
178 
180  return Base::get(context);
181 }
182 
183 BitVectorType BitVectorType::get(MLIRContext *context, unsigned width) {
184  return Base::get(context, width);
185 }
186 
187 unsigned BitVectorType::getWidth() { return getImpl()->width; }
188 
190  return Base::get(context);
191 }
192 
193 LogicVectorType LogicVectorType::get(MLIRContext *context, unsigned width) {
194  return Base::get(context, width);
195 }
196 
197 unsigned 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 
206 void 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 
220 template <typename Ty>
221 static 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 
233 static 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()) {
256  return success();
257  }
258  if (mnemonic == LogicVectorBaseType::getMnemonic()) {
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 
278 static 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  })
286  BitVectorBaseType, LogicVectorBaseType>([&](auto ty) {
287  printer << ty.getMnemonic();
288  return success();
289  })
290  .Default([](auto ty) { return failure(); });
291 }
292 
293 /// Parse a type registered with this dialect.
294 Type 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.
314 void 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 ParseResult parseType(Type &result, StringRef name, AsmParser &parser)
Parse a type defined by this dialect.
int32_t width
Definition: FIRRTL.cpp:36
bool operator==(const ResetDomain &a, const ResetDomain &b)
Definition: InferResets.cpp:71
static mlir::OptionalParseResult customTypeParser(DialectAsmParser &parser, StringRef mnemonic, llvm::SMLoc loc, Type &type)
static LogicalResult parseIntegerOrBitVector(DialectAsmParser &parser, Type &type)
static LogicalResult customTypePrinter(Type type, DialectAsmPrinter &printer)
Represents a finite word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:181
static BigIntType get(MLIRContext *context, unsigned width)
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:185
Represents a finite word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:221
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:226
static BigUIntType get(MLIRContext *context, unsigned width)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:243
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:249
static BitVectorBaseType get(MLIRContext *context)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:264
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:269
static BitVectorType get(MLIRContext *context, unsigned width)
Represents a limited word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:82
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:88
static IntBaseType get(MLIRContext *context)
Represents a limited word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:102
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:106
static IntType get(MLIRContext *context, unsigned width)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:282
static LogicVectorBaseType get(MLIRContext *context)
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:288
Represents a finite word-length bit vector (of four-state values) in SystemC as described in IEEE 166...
Definition: SystemCTypes.h:304
static LogicVectorType get(MLIRContext *context, unsigned width)
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:309
Represents a finite word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:160
static SignedType get(MLIRContext *context)
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:167
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:120
static UIntBaseType get(MLIRContext *context)
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:127
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:141
static UIntType get(MLIRContext *context, unsigned width)
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:146
Represents a finite word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
Definition: SystemCTypes.h:199
static constexpr StringLiteral getMnemonic()
Definition: SystemCTypes.h:206
static UnsignedType get(MLIRContext *context)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
circt::hw::InOutType InOutType
Definition: SVTypes.h:25
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.
Definition: DebugAnalysis.h:21
inline ::llvm::hash_code hash_value(const FieldRef &fieldRef)
Get a hash code for a FieldRef.
Definition: FieldRef.h:92
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.
Definition: SystemCTypes.h:42