CIRCT  18.0.0git
MooreTypes.h
Go to the documentation of this file.
1 //===- MooreTypes.h - Declare Moore dialect types ----------------*- C++-*-===//
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 declares the types for the Moore dialect.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef CIRCT_DIALECT_MOORE_MOORETYPES_H
14 #define CIRCT_DIALECT_MOORE_MOORETYPES_H
15 
16 #include "circt/Support/LLVM.h"
17 #include "mlir/IR/Attributes.h"
18 #include "mlir/IR/BuiltinAttributes.h"
19 #include "mlir/IR/Location.h"
20 #include "mlir/IR/Types.h"
21 #include <variant>
22 
23 namespace circt {
24 namespace moore {
25 
26 /// The number of values each bit of a type can assume.
27 enum class Domain {
28  /// Two-valued types such as `bit` or `int`.
29  TwoValued,
30  /// Four-valued types such as `logic` or `integer`.
31  FourValued,
32 };
33 
34 /// Whether a type is signed or unsigned.
35 enum class Sign {
36  /// An `unsigned` type.
37  Unsigned,
38  /// A `signed` type.
39  Signed,
40 };
41 
42 /// Map a `Sign` to the corresponding keyword.
43 StringRef getKeywordFromSign(const Sign &sign);
44 /// Map the keywords `unsigned` and `signed` to the corresponding `Sign`.
45 std::optional<Sign> getSignFromKeyword(StringRef keyword);
46 
47 template <typename Os>
48 Os &operator<<(Os &os, const Sign &sign) {
49  os << getKeywordFromSign(sign);
50  return os;
51 }
52 
53 /// Which side is greater in a range `[a:b]`.
54 enum class RangeDir {
55  /// `a < b`
56  Up,
57  /// `a >= b`
58  Down,
59 };
60 
61 /// The `[a:b]` part in a vector/array type such as `logic [a:b]`.
62 struct Range {
63  /// The total number of bits, given as `|a-b|+1`.
64  unsigned size;
65  /// The direction of the vector, i.e. whether `a > b` or `a < b`.
67  /// The starting offset of the range.
68  int offset;
69 
70  /// Construct a range `[size-1:0]`.
71  explicit Range(unsigned size) : Range(size, RangeDir::Down, 0) {}
72 
73  /// Construct a range `[offset+size-1:offset]` if `dir` is `Down`, or
74  /// `[offset:offset+size-1]` if `dir` is `Up`.
75  Range(unsigned size, RangeDir dir, int offset)
76  : size(size), dir(dir), offset(offset) {}
77 
78  /// Construct a range [left:right]`, with the direction inferred as `Down` if
79  /// `left >= right`, or `Up` otherwise.
80  Range(int left, int right) {
81  if (left >= right) {
82  size = left + 1 - right;
84  offset = right;
85  } else {
86  size = right + 1 - left;
87  dir = RangeDir::Up;
88  offset = left;
89  }
90  }
91 
92  bool operator==(const Range &other) const {
93  return size == other.size && dir == other.dir && offset == other.offset;
94  }
95 
96  /// Get the `$left` dimension.
97  int left() const { return dir == RangeDir::Up ? low() : high(); }
98  /// Get the `$right` dimension.
99  int right() const { return dir == RangeDir::Up ? high() : low(); }
100  /// Get the `$low` dimension.
101  int low() const { return offset; }
102  /// Get the `$high` dimension.
103  int high() const { return offset + size - 1; }
104  /// Get the `$increment` size.
105  int increment() const { return dir == RangeDir::Up ? 1 : -1; }
106 
107  /// Format this range as a string.
108  std::string toString() const {
109  std::string buffer;
110  llvm::raw_string_ostream(buffer) << *this;
111  return buffer;
112  }
113 };
114 
115 // NOLINTNEXTLINE(readability-identifier-naming)
116 inline llvm::hash_code hash_value(const Range &x) {
117  return llvm::hash_combine(x.size, x.dir, x.offset);
118 }
119 
120 template <typename Os>
121 Os &operator<<(Os &os, const Range &range) {
122  os << range.left() << ":" << range.right();
123  return os;
124 }
125 
126 class PackedType;
127 
128 /// A simple bit vector type.
129 ///
130 /// The SystemVerilog standard somewhat loosely defines a "Simple Bit Vector"
131 /// type. In essence, this is a zero or one-dimensional integer type. For
132 /// example, `bit`, `logic [0:0]`, `reg [31:0]`, or `int` are SBVs, but `bit
133 /// [1:0][2:0]`, `int [4:0]`, `bit [5:2]`, or `bit []` are not.
135  /// Create a null SBVT.
137 
138  /// Create a new SBVT with the given domain, sign, and size. The resulting
139  /// type will expand exactly to `bit signed? [size-1:0]`.
141  bool usedAtom = false, bool explicitSign = false,
142  bool explicitSize = true)
145  assert(size > 0 && "SBVT requires non-zero size");
146  }
147 
148  /// Convert this SBVT to an actual type.
149  PackedType getType(MLIRContext *context) const;
150 
151  /// Check whether the type is unsigned.
152  bool isUnsigned() const { return sign == Sign::Unsigned; }
153 
154  /// Check whether the type is signed.
155  bool isSigned() const { return sign == Sign::Signed; }
156 
157  /// Get the range of the type.
158  Range getRange() const { return Range(size, RangeDir::Down, 0); }
159 
160  /// Check whether this type is equivalent to another.
161  bool isEquivalent(const SimpleBitVectorType &other) const {
162  return domain == other.domain && sign == other.sign && size == other.size;
163  }
164 
165  bool operator==(const SimpleBitVectorType &other) const {
166  if (size == 0 || other.size == 0)
167  return size == other.size; // if either is null, the other has to be null
168  return isEquivalent(other) && usedAtom == other.usedAtom &&
169  explicitSign == other.explicitSign &&
170  explicitSize == other.explicitSize;
171  }
172 
173  /// Check whether this is a null type.
174  operator bool() const { return size > 0; }
175 
176  /// Format this simple bit vector type as a string.
177  std::string toString() const {
178  std::string buffer;
179  llvm::raw_string_ostream(buffer) << *this;
180  return buffer;
181  }
182 
183  /// The size of the vector.
184  unsigned size = 0;
185  /// The domain, which dictates whether this is a `bit` or `logic` vector.
187  /// The sign.
188  Sign sign : 8;
189 
190  // The following flags ensure that converting a `PackedType` to an SBVT and
191  // then back to a `PackedType` will yield exactly the original type. For
192  // example, the packed type `int` maps to an SBVT `{32, TwoValued, Signed}`,
193  // which should be converted back to `int` instead of `bit signed [31:0]`.
194 
195  /// Whether the type used an integer atom like `int` in the source text.
196  bool usedAtom : 1;
197  /// Whether the sign was explicit in the source text.
198  bool explicitSign : 1;
199  /// Whether the single-bit vector had an explicit range in the source text.
200  /// Essentially whether it was `bit` or `bit[a:a]`.
201  bool explicitSize : 1;
202 };
203 
204 // NOLINTNEXTLINE(readability-identifier-naming)
205 inline llvm::hash_code hash_value(const SimpleBitVectorType &x) {
206  if (x)
207  return llvm::hash_combine(x.size, x.domain, x.sign, x.usedAtom,
209  return {};
210 }
211 
212 template <typename Os>
213 Os &operator<<(Os &os, const SimpleBitVectorType &type) {
214  if (!type) {
215  os << "<<<NULL SBVT>>>";
216  return os;
217  }
218  os << (type.domain == Domain::TwoValued ? "bit" : "logic");
219  if (type.sign != Sign::Unsigned || type.explicitSign)
220  os << " " << type.sign;
221  if (type.size > 1 || type.explicitSize)
222  os << " [" << type.getRange() << "]";
223  return os;
224 }
225 
226 namespace detail {
227 struct RealTypeStorage;
228 struct IntTypeStorage;
229 struct IndirectTypeStorage;
230 struct DimStorage;
231 struct UnsizedDimStorage;
232 struct RangeDimStorage;
233 struct SizedDimStorage;
234 struct AssocDimStorage;
235 struct EnumTypeStorage;
236 struct StructTypeStorage;
237 } // namespace detail
238 
239 /// Base class for all SystemVerilog types in the Moore dialect.
240 class SVType : public Type {
241 protected:
242  using Type::Type;
243 };
244 
245 //===----------------------------------------------------------------------===//
246 // Unpacked Type
247 //===----------------------------------------------------------------------===//
248 
249 class PackedType;
250 class StringType;
251 class ChandleType;
252 class EventType;
253 class RealType;
255 class UnpackedDim;
256 class UnpackedStructType;
257 
258 /// An unpacked SystemVerilog type.
259 ///
260 /// Unpacked types are a second level of types in SystemVerilog. They extend a
261 /// core unpacked type with a variety of unpacked dimensions, depending on which
262 /// syntactic construct generated the type (variable or otherwise). The core
263 /// unpacked types are:
264 ///
265 /// - Packed types
266 /// - Non-integer types: `shortreal`, `real`, `realtime`
267 /// - Unpacked structs and unions
268 /// - `string`, `chandle`, `event`
269 /// - Virtual interfaces
270 /// - Class types
271 /// - Covergroups
272 /// - Unpacked named types
273 /// - Unpacked type references
274 ///
275 /// The unpacked dimensions are:
276 ///
277 /// - Unsized (`[]`)
278 /// - Arrays (`[x]`)
279 /// - Ranges (`[x:y]`)
280 /// - Associative (`[T]` or `[*]`)
281 /// - Queues (`[$]` or `[$:x]`)
282 class UnpackedType : public SVType {
283 public:
284  static bool classof(Type type) {
285  return type.isa<PackedType>() || type.isa<StringType>() ||
286  type.isa<ChandleType>() || type.isa<EventType>() ||
287  type.isa<RealType>() || type.isa<UnpackedIndirectType>() ||
288  type.isa<UnpackedDim>() || type.isa<UnpackedStructType>();
289  }
290 
291  /// Resolve one level of name or type reference indirection.
292  ///
293  /// For example, given `typedef int foo; typedef foo bar;`, resolves `bar`
294  /// to `foo`.
295  UnpackedType resolved() const;
296 
297  /// Resolve all name or type reference indirections.
298  ///
299  /// For example, given `typedef int foo; typedef foo bar;`, resolves `bar`
300  /// to `int`.
301  UnpackedType fullyResolved() const;
302 
303  /// Get the value domain of this type.
304  Domain getDomain() const;
305 
306  /// Get the sign for this type.
307  Sign getSign() const;
308 
309  /// Get the size of this type in bits.
310  ///
311  /// Returns `None` if any of the type's dimensions is unsized, associative, or
312  /// a queue, or the core type itself has no known size.
313  std::optional<unsigned> getBitSize() const;
314 
315  /// Get this type as a simple bit vector, if it is one. Returns a null type
316  /// otherwise.
318 
319  /// Check whether this is a simple bit vector type.
320  bool isSimpleBitVector() const { return !!getSimpleBitVectorOrNull(); }
321 
322  /// Get this type as a simple bit vector. Aborts if it is no simple bit
323  /// vector.
325  auto sbv = getSimpleBitVectorOrNull();
326  assert(sbv && "getSimpleBitVector called on type that is no SBV");
327  return sbv;
328  }
329 
330  /// Cast this type to a simple bit vector. Returns null if this type cannot be
331  /// cast to a simple bit vector.
333 
334  /// Check whether this type can be cast to a simple bit vector type.
336  return !!castToSimpleBitVectorOrNull();
337  }
338 
339  /// Cast this type to a simple bit vector. Aborts if this type cannot be cast
340  /// to a simple bit vector.
342  auto sbv = castToSimpleBitVectorOrNull();
343  assert(
344  sbv &&
345  "castToSimpleBitVector called on type that cannot be cast to an SBV");
346  return sbv;
347  }
348 
349  /// Format this type in SystemVerilog syntax into an output stream. Useful to
350  /// present the type back to the user in diagnostics.
351  void
352  format(llvm::raw_ostream &os,
353  llvm::function_ref<void(llvm::raw_ostream &os)> around = {}) const;
354 
355  void format(llvm::raw_ostream &os, StringRef around) const {
356  format(os, [&](llvm::raw_ostream &os) { os << around; });
357  }
358 
359  /// Format this type in SystemVerilog syntax into a string. Useful to present
360  /// the type back to the user in diagnostics. Prefer the `format` function if
361  /// possible, as that does not need to allocate a string.
362  template <typename... Args>
363  std::string toString(Args... args) const {
364  std::string buffer;
365  llvm::raw_string_ostream os(buffer);
366  format(os, args...);
367  return buffer;
368  }
369 
370 protected:
371  using SVType::SVType;
372 };
373 
374 template <
375  typename Ty,
376  std::enable_if_t<std::is_base_of<UnpackedType, Ty>::value, bool> = true>
377 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, Ty type) {
378  type.format(os);
379  return os;
380 }
381 
382 //===----------------------------------------------------------------------===//
383 // Packed Type
384 //===----------------------------------------------------------------------===//
385 
386 class VoidType;
387 class IntType;
388 class PackedIndirectType;
389 class PackedDim;
390 class EnumType;
391 class PackedStructType;
392 
393 /// A packed SystemVerilog type.
394 ///
395 /// Packed types are the core types of SystemVerilog. They combine a core packed
396 /// type with an optional sign and zero or more packed dimensions. The core
397 /// packed types are:
398 ///
399 /// - Integer vector types: `bit`, `logic`, `reg`
400 /// - Integer atom types: `byte`, `shortint`, `int`, `longint`, `integer`,
401 /// `time`
402 /// - Packed structs and unions
403 /// - Enums
404 /// - Packed named types
405 /// - Packed type references
406 ///
407 /// The packed dimensions can be:
408 ///
409 /// - Unsized (`[]`)
410 /// - Ranges (`[x:y]`)
411 ///
412 /// Note that every packed type is also a valid unpacked type. But unpacked
413 /// types are *not* valid packed types.
414 class PackedType : public UnpackedType {
415 public:
416  static bool classof(Type type) {
417  return type.isa<VoidType>() || type.isa<IntType>() ||
418  type.isa<PackedIndirectType>() || type.isa<PackedDim>() ||
419  type.isa<EnumType>() || type.isa<PackedStructType>();
420  }
421 
422  /// Resolve one level of name or type reference indirection.
423  ///
424  /// For example, given `typedef int foo; typedef foo bar;`, resolves `bar`
425  /// to `foo`.
426  PackedType resolved() const;
427 
428  /// Resolve all name or type reference indirections.
429  ///
430  /// For example, given `typedef int foo; typedef foo bar;`, resolves `bar`
431  /// to `int`.
432  PackedType fullyResolved() const;
433 
434  /// Get the value domain of this type.
435  Domain getDomain() const;
436 
437  /// Get the sign for this type.
438  Sign getSign() const;
439 
440  /// Get the size of this type in bits.
441  ///
442  /// Returns `None` if any of the type's dimensions is unsized.
443  std::optional<unsigned> getBitSize() const;
444 
445  /// Format this type in SystemVerilog syntax into an output stream. Useful to
446  /// present the type back to the user in diagnostics.
447  void format(llvm::raw_ostream &os) const;
448 
449 protected:
450  using UnpackedType::UnpackedType;
451 };
452 
453 //===----------------------------------------------------------------------===//
454 // Unit Types
455 //===----------------------------------------------------------------------===//
456 
457 /// The `void` type.
458 class VoidType
459  : public Type::TypeBase<VoidType, PackedType, DefaultTypeStorage> {
460 public:
461  static VoidType get(MLIRContext *context);
462 
463 protected:
464  using Base::Base;
465 };
466 
467 /// The `string` type.
469  : public Type::TypeBase<StringType, UnpackedType, DefaultTypeStorage> {
470 public:
471  static StringType get(MLIRContext *context);
472 
473 protected:
474  using Base::Base;
475 };
476 
477 /// The `chandle` type.
479  : public Type::TypeBase<ChandleType, UnpackedType, DefaultTypeStorage> {
480 public:
481  static ChandleType get(MLIRContext *context);
482 
483 protected:
484  using Base::Base;
485 };
486 
487 /// The `event` type.
489  : public Type::TypeBase<EventType, UnpackedType, DefaultTypeStorage> {
490 public:
491  static EventType get(MLIRContext *context);
492 
493 protected:
494  using Base::Base;
495 };
496 
497 //===----------------------------------------------------------------------===//
498 // Packed Integers
499 //===----------------------------------------------------------------------===//
500 
501 /// An integer vector or atom type.
502 class IntType
503  : public Type::TypeBase<IntType, PackedType, detail::IntTypeStorage> {
504 public:
505  enum Kind {
506  // The integer vector types. These are the builtin single-bit integer types.
507  /// A `bit`.
509  /// A `logic`.
511  /// A `reg`.
513 
514  // The integer atom types. These are the builtin multi-bit integer types.
515  /// A `byte`.
517  /// A `shortint`.
519  /// An `int`.
521  /// A `longint`.
523  /// An `integer`.
525  /// A `time`.
527  };
528 
529  /// Get the integer type that corresponds to a keyword (like `bit`).
530  static std::optional<Kind> getKindFromKeyword(StringRef keyword);
531  /// Get the keyword (like `bit`) for one of the integer types.
532  static StringRef getKeyword(Kind kind);
533  /// Get the default sign for one of the integer types.
534  static Sign getDefaultSign(Kind kind);
535  /// Get the value domain for one of the integer types.
536  static Domain getDomain(Kind kind);
537  /// Get the size of one of the integer types.
538  static unsigned getBitSize(Kind kind);
539  /// Get the integer type that corresponds to a domain and bit size. For
540  /// example, returns `int` for `(TwoValued, 32)`.
541  static std::optional<Kind> getKindFromDomainAndSize(Domain domain,
542  unsigned size);
543 
544  static IntType get(MLIRContext *context, Kind kind,
545  std::optional<Sign> sign = {});
546 
547  /// Create a `logic` type.
548  static IntType getLogic(MLIRContext *context) { return get(context, Logic); }
549 
550  /// Create a `int` type.
551  static IntType getInt(MLIRContext *context) { return get(context, Int); }
552 
553  /// Create a `time` type.
554  static IntType getTime(MLIRContext *context) { return get(context, Time); }
555 
556  /// Get the concrete integer vector or atom type.
557  Kind getKind() const;
558  /// Get the sign of this type.
559  Sign getSign() const;
560  /// Whether the sign of the type was specified explicitly. This allows us to
561  /// distinguish `bit unsigned` from `bit`.
562  bool isSignExplicit() const;
563 
564  /// Get the keyword (like `bit`) for this type.
565  StringRef getKeyword() const { return getKeyword(getKind()); }
566  /// Get the default sign for this type.
567  Sign getDefaultSign() const { return getDefaultSign(getKind()); }
568  /// Get the value domain for this type.
569  Domain getDomain() const { return getDomain(getKind()); }
570  /// Get the size of this type.
571  unsigned getBitSize() const { return getBitSize(getKind()); }
572 
573  /// Format this type in SystemVerilog syntax. Useful to present the type back
574  /// to the user in diagnostics.
575  void format(llvm::raw_ostream &os) const;
576 
577 protected:
578  using Base::Base;
579 };
580 
581 //===----------------------------------------------------------------------===//
582 // Unpacked Reals
583 //===----------------------------------------------------------------------===//
584 
585 /// A real type.
586 class RealType
587  : public Type::TypeBase<RealType, UnpackedType, detail::RealTypeStorage> {
588 public:
589  enum Kind {
590  /// A `shortreal`.
592  /// A `real`.
594  /// A `realtime`.
596  };
597 
598  /// Get the integer type that corresponds to a keyword (like `bit`).
599  static std::optional<Kind> getKindFromKeyword(StringRef keyword);
600  /// Get the keyword (like `bit`) for one of the integer types.
601  static StringRef getKeyword(Kind kind);
602  /// Get the size of one of the integer types.
603  static unsigned getBitSize(Kind kind);
604 
605  static RealType get(MLIRContext *context, Kind kind);
606 
607  /// Get the concrete integer vector or atom type.
608  Kind getKind() const;
609 
610  /// Get the keyword (like `bit`) for this type.
611  StringRef getKeyword() const { return getKeyword(getKind()); }
612  /// Get the size of this type.
613  unsigned getBitSize() const { return getBitSize(getKind()); }
614 
615 protected:
616  using Base::Base;
617 };
618 
619 //===----------------------------------------------------------------------===//
620 // Packed and Unpacked Type Indirections
621 //===----------------------------------------------------------------------===//
622 
623 class PackedNamedType;
624 class PackedRefType;
625 class UnpackedNamedType;
626 class UnpackedRefType;
627 
628 namespace detail {
629 UnpackedType getIndirectTypeInner(const TypeStorage *impl);
630 Location getIndirectTypeLoc(const TypeStorage *impl);
631 StringAttr getIndirectTypeName(const TypeStorage *impl);
632 } // namespace detail
633 
634 /// Common base class for name and type reference indirections.
635 ///
636 /// These handle the cases where the source text uses a `typedef` or
637 /// `type(<decl>)` construct to build a type. We keep track of these
638 /// indirections alongside the location in the source text where they were
639 /// created, in order to be able to reproduce the exact source text type in
640 /// diagnostics.
641 ///
642 /// We use this templated base class to construct separate packed and unpacked
643 /// indirect types, where holding a packed indirect type guarantees that the
644 /// inner type is a packed type as well. The resulting inheritance trees are:
645 ///
646 /// - `PackedNamedType -> PackedIndirectType -> PackedType`
647 /// - `PackedRefType -> PackedIndirectType -> PackedType`
648 /// - `UnpackedNamedType -> UnpackedIndirectType -> UnpackedType`
649 /// - `UnpackedRefType -> UnpackedIndirectType -> UnpackedType`
650 template <class BaseTy>
651 class IndirectTypeBase : public BaseTy {
652 protected:
653  using InnerType = BaseTy;
654  using BaseTy::BaseTy;
656 
657 public:
658  /// Get the type this indirection wraps.
659  BaseTy getInner() const {
660  return detail::getIndirectTypeInner(this->impl).template cast<BaseTy>();
661  }
662 
663  /// Get the location in the source text where the indirection was generated.
664  Location getLoc() const { return detail::getIndirectTypeLoc(this->impl); }
665 
666  /// Resolve one level of name or type reference indirection. This simply
667  /// returns the inner type, which removes the name indirection introduced by
668  /// this type. See `PackedType::resolved` and `UnpackedType::resolved`.
669  BaseTy resolved() const { return getInner(); }
670 
671  /// Resolve all name or type reference indirections. This always returns the
672  /// fully resolved inner type. See `PackedType::fullyResolved` and
673  /// `UnpackedType::fullyResolved`.
674  BaseTy fullyResolved() const { return getInner().fullyResolved(); }
675 };
676 
677 /// A named type.
678 ///
679 /// Named types are user-defined types that are introduced with a `typedef
680 /// <inner> <name>` construct in the source file. They are composed of the
681 /// following information:
682 ///
683 /// - `inner: The type that this name expands to.
684 /// - `name`: How the user originally called the type.
685 /// - `loc`: The location of the typedef in the source file.
686 template <class ConcreteTy, class BaseTy>
688  : public Type::TypeBase<ConcreteTy, BaseTy, detail::IndirectTypeStorage> {
689 protected:
690  using InnerType = typename BaseTy::InnerType;
691  using Type::TypeBase<ConcreteTy, BaseTy,
692  detail::IndirectTypeStorage>::TypeBase;
694 
695 public:
696  static ConcreteTy get(InnerType inner, StringAttr name, Location loc);
697  static ConcreteTy get(InnerType inner, StringRef name, Location loc) {
698  return get(inner, StringAttr::get(inner.getContext(), name), loc);
699  }
700 
701  /// Get the name assigned to the wrapped type.
702  StringAttr getName() const { return detail::getIndirectTypeName(this->impl); }
703 };
704 
705 /// A type reference.
706 ///
707 /// Type references are introduced with a `type(<decl>)` construct in the source
708 /// file. They are composed of the following information:
709 ///
710 /// - `inner`: The type that this reference expands to.
711 /// - `loc`: The location of the `type(...)` in the source file.
712 template <class ConcreteTy, class BaseTy>
714  : public Type::TypeBase<ConcreteTy, BaseTy, detail::IndirectTypeStorage> {
715 protected:
716  using InnerType = typename BaseTy::InnerType;
717  using Type::TypeBase<ConcreteTy, BaseTy,
718  detail::IndirectTypeStorage>::TypeBase;
720 
721 public:
722  static ConcreteTy get(InnerType inner, Location loc);
723 };
724 
725 /// A packed type indirection. See `IndirectTypeBase` for details.
726 class PackedIndirectType : public IndirectTypeBase<PackedType> {
727 public:
728  static bool classof(Type type) {
729  return type.isa<PackedNamedType>() || type.isa<PackedRefType>();
730  }
731 
732 protected:
733  using Base::Base;
734 };
735 
736 /// An unpacked type indirection. See `IndirectTypeBase` for details.
737 class UnpackedIndirectType : public IndirectTypeBase<UnpackedType> {
738 public:
739  static bool classof(Type type) {
740  return type.isa<UnpackedNamedType>() || type.isa<UnpackedRefType>();
741  }
742 
743 protected:
744  using Base::Base;
745 };
746 
747 /// A packed named type. See `NamedTypeBase` for details.
749  : public NamedTypeBase<PackedNamedType, PackedIndirectType> {
750 protected:
751  using NamedBase::NamedBase;
752 };
753 
754 /// An unpacked named type. See `NamedTypeBase` for details.
756  : public NamedTypeBase<UnpackedNamedType, UnpackedIndirectType> {
757 protected:
758  using NamedBase::NamedBase;
759 };
760 
761 /// A packed named type. See `NamedTypeBase` for details.
762 class PackedRefType : public RefTypeBase<PackedRefType, PackedIndirectType> {
763 protected:
764  using RefBase::RefBase;
765 };
766 
767 /// An unpacked named type. See `NamedTypeBase` for details.
769  : public RefTypeBase<UnpackedRefType, UnpackedIndirectType> {
770 protected:
771  using RefBase::RefBase;
772 };
773 
774 //===----------------------------------------------------------------------===//
775 // Packed Dimensions
776 //===----------------------------------------------------------------------===//
777 
778 class PackedRangeDim;
779 class PackedUnsizedDim;
780 
781 /// A packed dimension.
782 class PackedDim : public PackedType {
783 public:
784  static bool classof(Type type) {
785  return type.isa<PackedRangeDim>() || type.isa<PackedUnsizedDim>();
786  }
787 
788  /// Get the element type of the dimension. This is the `x` in `x[a:b]`.
789  PackedType getInner() const;
790 
791  /// Format this type in SystemVerilog syntax. Useful to present the type back
792  /// to the user in diagnostics.
793  void format(llvm::raw_ostream &os) const;
794  /// Format just the dimension part, `[...]`.
795  void formatDim(llvm::raw_ostream &os) const;
796 
797  /// Resolve one level of name or type reference indirection. See
798  /// `PackedType::resolved`.
799  PackedType resolved() const;
800 
801  /// Resolve all name or type reference indirections. See
802  /// `PackedType::fullyResolved`.
803  PackedType fullyResolved() const;
804 
805  /// Get the dimension's range, or `None` if it is unsized.
806  std::optional<Range> getRange() const;
807  /// Get the dimension's size, or `None` if it is unsized.
808  std::optional<unsigned> getSize() const;
809 
810 protected:
811  using PackedType::PackedType;
812  const detail::DimStorage *getImpl() const;
813 };
814 
815 /// A packed unsized dimension, like `[]`.
816 class PackedUnsizedDim : public Type::TypeBase<PackedUnsizedDim, PackedDim,
817  detail::UnsizedDimStorage,
818  ::mlir::TypeTrait::IsMutable> {
819 public:
820  static PackedUnsizedDim get(PackedType inner);
821 
822 protected:
823  using Base::Base;
824  friend struct detail::DimStorage;
825 };
826 
827 /// A packed range dimension, like `[a:b]`.
829  : public Type::TypeBase<PackedRangeDim, PackedDim, detail::RangeDimStorage,
830  ::mlir::TypeTrait::IsMutable> {
831 public:
832  static PackedRangeDim get(PackedType inner, Range range);
833 
834  /// Get a packed range with arguments forwarded to the `Range` constructor.
835  /// See `Range::Range` for details.
836  template <typename... Args>
837  static PackedRangeDim get(PackedType inner, Args... args) {
838  return get(inner, Range(args...));
839  }
840 
841  /// Get the range of this dimension.
842  Range getRange() const;
843 
844  /// Allow implicit casts from `PackedRangeDim` to the actual range.
845  operator Range() const { return getRange(); }
846 
847 protected:
848  using Base::Base;
849  friend struct detail::DimStorage;
850 };
851 
852 //===----------------------------------------------------------------------===//
853 // Unpacked Dimensions
854 //===----------------------------------------------------------------------===//
855 
856 class UnpackedUnsizedDim;
857 class UnpackedArrayDim;
858 class UnpackedRangeDim;
859 class UnpackedAssocDim;
860 class UnpackedQueueDim;
861 
862 /// An unpacked dimension.
863 class UnpackedDim : public UnpackedType {
864 public:
865  static bool classof(Type type) {
866  return type.isa<UnpackedUnsizedDim>() || type.isa<UnpackedArrayDim>() ||
867  type.isa<UnpackedRangeDim>() || type.isa<UnpackedAssocDim>() ||
868  type.isa<UnpackedQueueDim>();
869  }
870 
871  /// Get the element type of the dimension. This is the `x` in `x[a:b]`.
872  UnpackedType getInner() const;
873 
874  /// Format this type in SystemVerilog syntax. Useful to present the type back
875  /// to the user in diagnostics. The unpacked dimensions are separated from any
876  /// packed dimensions by calling the provided `around` callback, or a `$` if
877  /// no callback has been provided. This can be useful when printing
878  /// declarations like `bit [7:0] foo [16]` to have the type properly surround
879  /// the declaration name `foo`, and to easily tell packed from unpacked
880  /// dimensions in types like `bit [7:0] $ [15]`.
881  void format(llvm::raw_ostream &os,
882  llvm::function_ref<void(llvm::raw_ostream &)> around = {}) const;
883  /// Format just the dimension part, `[...]`.
884  void formatDim(llvm::raw_ostream &os) const;
885 
886  /// Resolve one level of name or type reference indirection. See
887  /// `UnpackedType::resolved`.
888  UnpackedType resolved() const;
889 
890  /// Resolve all name or type reference indirections. See
891  /// `UnpackedType::fullyResolved`.
892  UnpackedType fullyResolved() const;
893 
894 protected:
895  using UnpackedType::UnpackedType;
896  const detail::DimStorage *getImpl() const;
897 };
898 
899 /// An unpacked unsized dimension, like `[]`.
901  : public Type::TypeBase<UnpackedUnsizedDim, UnpackedDim,
902  detail::UnsizedDimStorage,
903  ::mlir::TypeTrait::IsMutable> {
904 public:
905  static UnpackedUnsizedDim get(UnpackedType inner);
906 
907 protected:
908  using Base::Base;
909  friend struct detail::DimStorage;
910 };
911 
912 /// An unpacked array dimension, like `[a]`.
913 class UnpackedArrayDim : public Type::TypeBase<UnpackedArrayDim, UnpackedDim,
914  detail::SizedDimStorage,
915  ::mlir::TypeTrait::IsMutable> {
916 public:
917  static UnpackedArrayDim get(UnpackedType inner, unsigned size);
918 
919  /// Get the size of the array, i.e. the `a` in `[a]`.
920  unsigned getSize() const;
921 
922 protected:
923  using Base::Base;
924  friend struct detail::DimStorage;
925 };
926 
927 /// An unpacked range dimension, like `[a:b]`.
928 class UnpackedRangeDim : public Type::TypeBase<UnpackedRangeDim, UnpackedDim,
929  detail::RangeDimStorage,
930  ::mlir::TypeTrait::IsMutable> {
931 public:
932  static UnpackedRangeDim get(UnpackedType inner, Range range);
933 
934  /// Get a packed range with arguments forwarded to the `Range` constructor.
935  /// See `Range::Range` for details.
936  template <typename... Args>
937  static UnpackedRangeDim get(UnpackedType inner, Args... args) {
938  return get(inner, Range(args...));
939  }
940 
941  /// Get the range of this dimension.
942  Range getRange() const;
943 
944  /// Allow implicit casts from `UnpackedRangeDim` to the actual range.
945  operator Range() const { return getRange(); }
946 
947 protected:
948  using Base::Base;
949  friend struct detail::DimStorage;
950 };
951 
952 /// An unpacked associative dimension, like `[T]` or `[*]`.
953 ///
954 /// Associative arrays in SystemVerilog can have a concrete index type (`[T]`),
955 /// or a wildcard index type (`[*]`, §7.8.1). The latter is exceptionally
956 /// strange, as it applies only to integer indices, but supports arbitrarily
957 /// sized indices by always removing leading zeros from any index that is used
958 /// in the lookup. This is interesting if a `string` is used to index into such
959 /// an array, because strings are automatically cast to a bit vector of
960 /// equivalent size, which results in a sort-of string key lookup. However, note
961 /// that there are also dedicated semantics for using `string` as the actual
962 /// index type (§7.8.2).
963 ///
964 /// See IEEE 1800-2017 §7.8 "Associative arrays".
965 class UnpackedAssocDim : public Type::TypeBase<UnpackedAssocDim, UnpackedDim,
966  detail::AssocDimStorage,
967  ::mlir::TypeTrait::IsMutable> {
968 public:
969  static UnpackedAssocDim get(UnpackedType inner, UnpackedType indexType = {});
970 
971  /// Get the index type of the associative dimension. This returns either the
972  /// type `T` in a dimension `[T]`, or a null type in a dimension `[*]`.
973  UnpackedType getIndexType() const;
974 
975 protected:
976  using Base::Base;
977  friend struct detail::DimStorage;
978 };
979 
980 /// An unpacked queue dimension with optional bound, like `[$]` or `[$:a]`.
981 class UnpackedQueueDim : public Type::TypeBase<UnpackedQueueDim, UnpackedDim,
982  detail::SizedDimStorage,
983  ::mlir::TypeTrait::IsMutable> {
984 public:
985  static UnpackedQueueDim get(UnpackedType inner,
986  std::optional<unsigned> bound = {});
987 
988  /// Get the bound of the queue, i.e. the `a` in `[$:a]`. Returns `None` if the
989  /// queue is unbounded.
990  std::optional<unsigned> getBound() const;
991 
992 protected:
993  using Base::Base;
994  friend struct detail::DimStorage;
995 };
996 
997 //===----------------------------------------------------------------------===//
998 // Enumerations
999 //===----------------------------------------------------------------------===//
1000 
1001 /// An enum type.
1003  : public Type::TypeBase<EnumType, PackedType, detail::EnumTypeStorage> {
1004 public:
1005  static EnumType get(StringAttr name, Location loc, PackedType base = {});
1006 
1007  /// Get the base type of the enumeration.
1008  PackedType getBase() const;
1009  /// Returns whether the base type was explicitly specified by the user. This
1010  /// allows us to distinguish `enum` from `enum int`.
1011  bool isBaseExplicit() const;
1012  /// Get the name of the surrounding typedef, if this enum is embedded in a
1013  /// typedef. Otherwise this returns a null attribute.
1014  StringAttr getName() const;
1015  /// Get the location in the source text where the enum was declared. This
1016  /// shall be the location of the `enum` keyword or, if the enum is embedded in
1017  /// a typedef, the location of the typedef name.
1018  Location getLoc() const;
1019 
1020  /// Format this enum in SystemVerilog syntax. Useful to present the enum back
1021  /// to the user in diagnostics.
1022  void format(llvm::raw_ostream &os) const;
1023 
1024 protected:
1025  using Base::Base;
1026 };
1027 
1028 //===----------------------------------------------------------------------===//
1029 // Packed and Unpacked Structs
1030 //===----------------------------------------------------------------------===//
1031 
1032 /// Whether a struct is a `struct`, `union`, or `union tagged`.
1033 enum class StructKind {
1034  /// A `struct`.
1035  Struct,
1036  /// A `union`.
1037  Union,
1038  /// A `union tagged`.
1039  TaggedUnion,
1040 };
1041 
1042 /// Map a `StructKind` to the corresponding mnemonic.
1043 StringRef getMnemonicFromStructKind(StructKind kind);
1044 /// Map a mnemonic to the corresponding `StructKind`.
1045 std::optional<StructKind> getStructKindFromMnemonic(StringRef mnemonic);
1046 
1047 template <typename Os>
1048 Os &operator<<(Os &os, const StructKind &kind) {
1049  static constexpr StringRef keywords[] = {"struct", "union", "union tagged"};
1050  os << keywords[static_cast<unsigned>(kind)];
1051  return os;
1052 }
1053 
1054 /// A member of a struct.
1056  /// The name of this member.
1057  StringAttr name;
1058  /// The location in the source text where this member was declared.
1059  Location loc;
1060  /// The type of this member.
1062 
1063  bool operator==(const StructMember &other) const {
1064  return name == other.name && loc == other.loc && type == other.type;
1065  }
1066 };
1067 
1068 // NOLINTNEXTLINE(readability-identifier-naming)
1069 inline llvm::hash_code hash_value(const StructMember &x) {
1070  return llvm::hash_combine(x.name, x.loc, x.type);
1071 }
1072 
1073 /// A struct.
1074 ///
1075 /// This represents both packed and unpacked structs. Which one it is depends on
1076 /// whether this struct is embedded in a `PackedStructType` or a
1077 /// `UnpackedStructType`. For the packed version the struct members are
1078 /// guaranteed to be packed types as well.
1079 struct Struct {
1080  /// Whether this is a `struct`, `union`, or `union tagged`.
1082  /// The list of members.
1083  SmallVector<StructMember, 4> members;
1084  /// The value domain of this struct. If all members are two-valued, the
1085  /// overall struct is two-valued. Otherwise the struct is four-valued.
1087  /// The size of this struct in bits. This is `None` if any member type has an
1088  /// unknown size. This is commonly the case for unpacked member types, or
1089  /// dimensions with unknown size such as `[]` or `[$]`.
1090  std::optional<unsigned> bitSize;
1091  /// The name of the surrounding typedef, if this struct is embedded in a
1092  /// typedef. Otherwise this is a null attribute.
1093  StringAttr name;
1094  /// The location in the source text where the struct was declared. This shall
1095  /// be the location of the `struct` or `union` keyword, or, if the struct is
1096  /// embedded in a typedef, the location of the typedef name.
1097  Location loc;
1098 
1099  /// Create a new struct.
1100  Struct(StructKind kind, ArrayRef<StructMember> members, StringAttr name,
1101  Location loc);
1102 
1103  /// Format this struct in SystemVerilog syntax. Useful to present the struct
1104  /// back to the user in diagnostics.
1105  void format(llvm::raw_ostream &os, bool packed = false,
1106  std::optional<Sign> signing = {}) const;
1107 };
1108 
1109 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
1110  const Struct &strukt) {
1111  strukt.format(os);
1112  return os;
1113 }
1114 
1115 /// A packed struct.
1116 class PackedStructType : public Type::TypeBase<PackedStructType, PackedType,
1117  detail::StructTypeStorage,
1118  ::mlir::TypeTrait::IsMutable> {
1119 public:
1120  static PackedStructType get(StructKind kind, ArrayRef<StructMember> members,
1121  StringAttr name, Location loc,
1122  std::optional<Sign> sign = {});
1123  static PackedStructType get(const Struct &strukt,
1124  std::optional<Sign> sign = {}) {
1125  return get(strukt.kind, strukt.members, strukt.name, strukt.loc, sign);
1126  }
1127 
1128  /// Get the sign of this struct.
1129  Sign getSign() const;
1130  /// Returns whether the sign was explicitly mentioned by the user.
1131  bool isSignExplicit() const;
1132  /// Get the struct definition.
1133  const Struct &getStruct() const;
1134 
1135  /// Format this struct in SystemVerilog syntax. Useful to present the struct
1136  /// back to the user in diagnostics.
1137  void format(llvm::raw_ostream &os) const {
1138  getStruct().format(os, true,
1139  isSignExplicit() ? std::optional<Sign>(getSign())
1140  : std::optional<Sign>());
1141  }
1142 
1143  /// Allow implicit casts from `PackedStructType` to the actual struct
1144  /// definition.
1145  operator const Struct &() const { return getStruct(); }
1146 
1147 protected:
1148  using Base::Base;
1149 };
1150 
1151 /// An unpacked struct.
1153  : public Type::TypeBase<UnpackedStructType, UnpackedType,
1154  detail::StructTypeStorage,
1155  ::mlir::TypeTrait::IsMutable> {
1156 public:
1157  static UnpackedStructType get(StructKind kind, ArrayRef<StructMember> members,
1158  StringAttr name, Location loc);
1159  static UnpackedStructType get(const Struct &strukt) {
1160  return get(strukt.kind, strukt.members, strukt.name, strukt.loc);
1161  }
1162 
1163  /// Get the struct definition.
1164  const Struct &getStruct() const;
1165 
1166  /// Format this struct in SystemVerilog syntax. Useful to present the struct
1167  /// back to the user in diagnostics.
1168  void format(llvm::raw_ostream &os) const { getStruct().format(os); }
1169 
1170  /// Allow implicit casts from `UnpackedStructType` to the actual struct
1171  /// definition.
1172  operator const Struct &() const { return getStruct(); }
1173 
1174 protected:
1175  using Base::Base;
1176 };
1177 
1178 } // namespace moore
1179 } // namespace circt
1180 
1181 //===----------------------------------------------------------------------===//
1182 // Hashing
1183 //===----------------------------------------------------------------------===//
1184 
1185 namespace llvm {
1186 
1187 template <>
1188 struct DenseMapInfo<circt::moore::Range> {
1190  static inline Range getEmptyKey() { return Range(-1); }
1191  static inline Range getTombstoneKey() { return Range(-2); }
1192  static unsigned getHashValue(const Range &x) {
1193  return circt::moore::hash_value(x);
1194  }
1195  static bool isEqual(const Range &lhs, const Range &rhs) { return lhs == rhs; }
1196 };
1197 
1198 } // namespace llvm
1199 
1200 // Include generated types.
1201 #define GET_TYPEDEF_CLASSES
1202 #include "circt/Dialect/Moore/MooreTypes.h.inc"
1203 
1204 #endif // CIRCT_DIALECT_MOORE_MOORETYPES_H
assert(baseType &&"element must be base type")
static int64_t size(hw::ArrayType mType, capnp::schema::Field::Reader cField)
Returns the expected size of an array (capnp list) in 64-bit words.
Definition: Schema.cpp:193
The chandle type.
Definition: MooreTypes.h:479
static ChandleType get(MLIRContext *context)
Definition: MooreTypes.cpp:313
StringAttr getName() const
Get the name of the surrounding typedef, if this enum is embedded in a typedef.
Definition: MooreTypes.cpp:987
PackedType getBase() const
Get the base type of the enumeration.
Definition: MooreTypes.cpp:983
static EnumType get(StringAttr name, Location loc, PackedType base={})
Definition: MooreTypes.cpp:978
void format(llvm::raw_ostream &os) const
Format this enum in SystemVerilog syntax.
Definition: MooreTypes.cpp:991
Location getLoc() const
Get the location in the source text where the enum was declared.
Definition: MooreTypes.cpp:989
bool isBaseExplicit() const
Returns whether the base type was explicitly specified by the user.
Definition: MooreTypes.cpp:985
The event type.
Definition: MooreTypes.h:489
static EventType get(MLIRContext *context)
Definition: MooreTypes.cpp:317
Common base class for name and type reference indirections.
Definition: MooreTypes.h:651
BaseTy resolved() const
Resolve one level of name or type reference indirection.
Definition: MooreTypes.h:669
BaseTy getInner() const
Get the type this indirection wraps.
Definition: MooreTypes.h:659
IndirectTypeBase< PackedType > Base
Definition: MooreTypes.h:655
Location getLoc() const
Get the location in the source text where the indirection was generated.
Definition: MooreTypes.h:664
BaseTy fullyResolved() const
Resolve all name or type reference indirections.
Definition: MooreTypes.h:674
An integer vector or atom type.
Definition: MooreTypes.h:503
Sign getDefaultSign() const
Get the default sign for this type.
Definition: MooreTypes.h:567
Sign getSign() const
Get the sign of this type.
Definition: MooreTypes.cpp:487
Domain getDomain() const
Get the value domain for this type.
Definition: MooreTypes.h:569
static IntType getLogic(MLIRContext *context)
Create a logic type.
Definition: MooreTypes.h:548
static IntType getTime(MLIRContext *context)
Create a time type.
Definition: MooreTypes.h:554
static std::optional< Kind > getKindFromDomainAndSize(Domain domain, unsigned size)
Get the integer type that corresponds to a domain and bit size.
Definition: MooreTypes.cpp:447
Kind getKind() const
Get the concrete integer vector or atom type.
Definition: MooreTypes.cpp:485
static IntType getInt(MLIRContext *context)
Create a int type.
Definition: MooreTypes.h:551
bool isSignExplicit() const
Whether the sign of the type was specified explicitly.
Definition: MooreTypes.cpp:489
static IntType get(MLIRContext *context, Kind kind, std::optional< Sign > sign={})
Definition: MooreTypes.cpp:478
unsigned getBitSize() const
Get the size of this type.
Definition: MooreTypes.h:571
static std::optional< Kind > getKindFromKeyword(StringRef keyword)
Get the integer type that corresponds to a keyword (like bit).
Definition: MooreTypes.cpp:353
StringRef getKeyword() const
Get the keyword (like bit) for this type.
Definition: MooreTypes.h:565
void format(llvm::raw_ostream &os) const
Format this type in SystemVerilog syntax.
Definition: MooreTypes.cpp:491
@ LongInt
A longint.
Definition: MooreTypes.h:522
@ Integer
An integer.
Definition: MooreTypes.h:524
@ ShortInt
A shortint.
Definition: MooreTypes.h:518
typename BaseTy::InnerType InnerType
Definition: MooreTypes.h:690
NamedTypeBase< PackedNamedType, PackedIndirectType > NamedBase
Definition: MooreTypes.h:693
StringAttr getName() const
Get the name assigned to the wrapped type.
Definition: MooreTypes.h:702
static ConcreteTy get(InnerType inner, StringAttr name, Location loc)
static ConcreteTy get(InnerType inner, StringRef name, Location loc)
Definition: MooreTypes.h:697
A packed dimension.
Definition: MooreTypes.h:782
std::optional< Range > getRange() const
Get the dimension's range, or None if it is unsized.
Definition: MooreTypes.cpp:767
void formatDim(llvm::raw_ostream &os) const
Format just the dimension part, [...].
Definition: MooreTypes.cpp:751
const detail::DimStorage * getImpl() const
Definition: MooreTypes.cpp:777
static bool classof(Type type)
Definition: MooreTypes.h:784
PackedType resolved() const
Resolve one level of name or type reference indirection.
Definition: MooreTypes.cpp:759
PackedType getInner() const
Get the element type of the dimension. This is the x in x[a:b].
Definition: MooreTypes.cpp:729
void format(llvm::raw_ostream &os) const
Format this type in SystemVerilog syntax.
Definition: MooreTypes.cpp:733
std::optional< unsigned > getSize() const
Get the dimension's size, or None if it is unsized.
Definition: MooreTypes.cpp:773
PackedType fullyResolved() const
Resolve all name or type reference indirections.
Definition: MooreTypes.cpp:763
A packed type indirection. See IndirectTypeBase for details.
Definition: MooreTypes.h:726
static bool classof(Type type)
Definition: MooreTypes.h:728
A packed named type. See NamedTypeBase for details.
Definition: MooreTypes.h:749
A packed range dimension, like [a:b].
Definition: MooreTypes.h:830
Range getRange() const
Get the range of this dimension.
Definition: MooreTypes.cpp:793
static PackedRangeDim get(PackedType inner, Args... args)
Get a packed range with arguments forwarded to the Range constructor.
Definition: MooreTypes.h:837
static PackedRangeDim get(PackedType inner, Range range)
Definition: MooreTypes.cpp:787
A packed named type. See NamedTypeBase for details.
Definition: MooreTypes.h:762
void format(llvm::raw_ostream &os) const
Format this struct in SystemVerilog syntax.
Definition: MooreTypes.h:1137
const Struct & getStruct() const
Get the struct definition.
static PackedStructType get(const Struct &strukt, std::optional< Sign > sign={})
Definition: MooreTypes.h:1123
static PackedStructType get(StructKind kind, ArrayRef< StructMember > members, StringAttr name, Location loc, std::optional< Sign > sign={})
Sign getSign() const
Get the sign of this struct.
bool isSignExplicit() const
Returns whether the sign was explicitly mentioned by the user.
A packed SystemVerilog type.
Definition: MooreTypes.h:414
Sign getSign() const
Get the sign for this type.
Definition: MooreTypes.cpp:266
PackedType resolved() const
Resolve one level of name or type reference indirection.
Definition: MooreTypes.cpp:241
std::optional< unsigned > getBitSize() const
Get the size of this type in bits.
Definition: MooreTypes.cpp:276
Domain getDomain() const
Get the value domain of this type.
Definition: MooreTypes.cpp:255
static bool classof(Type type)
Definition: MooreTypes.h:416
void format(llvm::raw_ostream &os) const
Format this type in SystemVerilog syntax into an output stream.
Definition: MooreTypes.cpp:293
PackedType fullyResolved() const
Resolve all name or type reference indirections.
Definition: MooreTypes.cpp:248
A packed unsized dimension, like [].
Definition: MooreTypes.h:818
static PackedUnsizedDim get(PackedType inner)
Definition: MooreTypes.cpp:781
StringRef getKeyword() const
Get the keyword (like bit) for this type.
Definition: MooreTypes.h:611
static std::optional< Kind > getKindFromKeyword(StringRef keyword)
Get the integer type that corresponds to a keyword (like bit).
Definition: MooreTypes.cpp:524
static RealType get(MLIRContext *context, Kind kind)
Definition: MooreTypes.cpp:556
@ ShortReal
A shortreal.
Definition: MooreTypes.h:591
@ RealTime
A realtime.
Definition: MooreTypes.h:595
unsigned getBitSize() const
Get the size of this type.
Definition: MooreTypes.h:613
Kind getKind() const
Get the concrete integer vector or atom type.
Definition: MooreTypes.cpp:560
A type reference.
Definition: MooreTypes.h:714
static ConcreteTy get(InnerType inner, Location loc)
RefTypeBase< PackedRefType, PackedIndirectType > RefBase
Definition: MooreTypes.h:719
typename BaseTy::InnerType InnerType
Definition: MooreTypes.h:716
Base class for all SystemVerilog types in the Moore dialect.
Definition: MooreTypes.h:240
The string type.
Definition: MooreTypes.h:469
static StringType get(MLIRContext *context)
Definition: MooreTypes.cpp:311
An unpacked array dimension, like [a].
Definition: MooreTypes.h:915
static UnpackedArrayDim get(UnpackedType inner, unsigned size)
Definition: MooreTypes.cpp:904
unsigned getSize() const
Get the size of the array, i.e. the a in [a].
Definition: MooreTypes.cpp:910
An unpacked associative dimension, like [T] or [*].
Definition: MooreTypes.h:967
static UnpackedAssocDim get(UnpackedType inner, UnpackedType indexType={})
Definition: MooreTypes.cpp:920
UnpackedType getIndexType() const
Get the index type of the associative dimension.
Definition: MooreTypes.cpp:927
An unpacked dimension.
Definition: MooreTypes.h:863
UnpackedType resolved() const
Resolve one level of name or type reference indirection.
Definition: MooreTypes.cpp:888
void format(llvm::raw_ostream &os, llvm::function_ref< void(llvm::raw_ostream &)> around={}) const
Format this type in SystemVerilog syntax.
Definition: MooreTypes.cpp:839
const detail::DimStorage * getImpl() const
Definition: MooreTypes.cpp:894
UnpackedType fullyResolved() const
Resolve all name or type reference indirections.
Definition: MooreTypes.cpp:890
static bool classof(Type type)
Definition: MooreTypes.h:865
void formatDim(llvm::raw_ostream &os) const
Format just the dimension part, [...].
Definition: MooreTypes.cpp:864
UnpackedType getInner() const
Get the element type of the dimension. This is the x in x[a:b].
Definition: MooreTypes.cpp:837
An unpacked type indirection. See IndirectTypeBase for details.
Definition: MooreTypes.h:737
static bool classof(Type type)
Definition: MooreTypes.h:739
An unpacked named type. See NamedTypeBase for details.
Definition: MooreTypes.h:756
An unpacked queue dimension with optional bound, like [$] or [$:a].
Definition: MooreTypes.h:983
static UnpackedQueueDim get(UnpackedType inner, std::optional< unsigned > bound={})
Definition: MooreTypes.cpp:931
std::optional< unsigned > getBound() const
Get the bound of the queue, i.e.
Definition: MooreTypes.cpp:938
An unpacked range dimension, like [a:b].
Definition: MooreTypes.h:930
static UnpackedRangeDim get(UnpackedType inner, Args... args)
Get a packed range with arguments forwarded to the Range constructor.
Definition: MooreTypes.h:937
Range getRange() const
Get the range of this dimension.
Definition: MooreTypes.cpp:918
static UnpackedRangeDim get(UnpackedType inner, Range range)
Definition: MooreTypes.cpp:912
An unpacked named type. See NamedTypeBase for details.
Definition: MooreTypes.h:769
const Struct & getStruct() const
Get the struct definition.
void format(llvm::raw_ostream &os) const
Format this struct in SystemVerilog syntax.
Definition: MooreTypes.h:1168
static UnpackedStructType get(const Struct &strukt)
Definition: MooreTypes.h:1159
static UnpackedStructType get(StructKind kind, ArrayRef< StructMember > members, StringAttr name, Location loc)
An unpacked SystemVerilog type.
Definition: MooreTypes.h:282
UnpackedType resolved() const
Resolve one level of name or type reference indirection.
Definition: MooreTypes.cpp:99
SimpleBitVectorType getSimpleBitVectorOrNull() const
Get this type as a simple bit vector, if it is one.
Definition: MooreTypes.cpp:160
SimpleBitVectorType castToSimpleBitVectorOrNull() const
Cast this type to a simple bit vector.
Definition: MooreTypes.cpp:190
UnpackedType fullyResolved() const
Resolve all name or type reference indirections.
Definition: MooreTypes.cpp:106
std::optional< unsigned > getBitSize() const
Get the size of this type in bits.
Definition: MooreTypes.cpp:131
Domain getDomain() const
Get the value domain of this type.
Definition: MooreTypes.cpp:113
Sign getSign() const
Get the sign for this type.
Definition: MooreTypes.cpp:123
bool isSimpleBitVector() const
Check whether this is a simple bit vector type.
Definition: MooreTypes.h:320
SimpleBitVectorType castToSimpleBitVector() const
Cast this type to a simple bit vector.
Definition: MooreTypes.h:341
std::string toString(Args... args) const
Format this type in SystemVerilog syntax into a string.
Definition: MooreTypes.h:363
static bool classof(Type type)
Definition: MooreTypes.h:284
SimpleBitVectorType getSimpleBitVector() const
Get this type as a simple bit vector.
Definition: MooreTypes.h:324
void format(llvm::raw_ostream &os, llvm::function_ref< void(llvm::raw_ostream &os)> around={}) const
Format this type in SystemVerilog syntax into an output stream.
Definition: MooreTypes.cpp:210
void format(llvm::raw_ostream &os, StringRef around) const
Definition: MooreTypes.h:355
bool isCastableToSimpleBitVector() const
Check whether this type can be cast to a simple bit vector type.
Definition: MooreTypes.h:335
An unpacked unsized dimension, like [].
Definition: MooreTypes.h:903
static UnpackedUnsizedDim get(UnpackedType inner)
Definition: MooreTypes.cpp:898
The void type.
Definition: MooreTypes.h:459
static VoidType get(MLIRContext *context)
Definition: MooreTypes.cpp:309
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:53
UnpackedType getIndirectTypeInner(const TypeStorage *impl)
Definition: MooreTypes.cpp:593
StringAttr getIndirectTypeName(const TypeStorage *impl)
Definition: MooreTypes.cpp:601
Location getIndirectTypeLoc(const TypeStorage *impl)
Definition: MooreTypes.cpp:597
Domain
The number of values each bit of a type can assume.
Definition: MooreTypes.h:27
@ FourValued
Four-valued types such as logic or integer.
@ TwoValued
Two-valued types such as bit or int.
llvm::hash_code hash_value(const Range &x)
Definition: MooreTypes.h:116
RangeDir
Which side is greater in a range [a:b].
Definition: MooreTypes.h:54
Sign
Whether a type is signed or unsigned.
Definition: MooreTypes.h:35
@ Signed
A signed type.
@ Unsigned
An unsigned type.
StringRef getKeywordFromSign(const Sign &sign)
Map a Sign to the corresponding keyword.
Definition: MooreTypes.cpp:51
Os & operator<<(Os &os, const Sign &sign)
Definition: MooreTypes.h:48
StringRef getMnemonicFromStructKind(StructKind kind)
Map a StructKind to the corresponding mnemonic.
StructKind
Whether a struct is a struct, union, or union tagged.
Definition: MooreTypes.h:1033
@ TaggedUnion
A union tagged.
std::optional< StructKind > getStructKindFromMnemonic(StringRef mnemonic)
Map a mnemonic to the corresponding StructKind.
std::optional< Sign > getSignFromKeyword(StringRef keyword)
Map the keywords unsigned and signed to the corresponding Sign.
Definition: MooreTypes.cpp:61
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
The [a:b] part in a vector/array type such as logic [a:b].
Definition: MooreTypes.h:62
Range(unsigned size, RangeDir dir, int offset)
Construct a range [offset+size-1:offset] if dir is Down, or [offset:offset+size-1] if dir is Up.
Definition: MooreTypes.h:75
unsigned size
The total number of bits, given as |a-b|+1.
Definition: MooreTypes.h:64
int offset
The starting offset of the range.
Definition: MooreTypes.h:68
bool operator==(const Range &other) const
Definition: MooreTypes.h:92
int left() const
Get the $left dimension.
Definition: MooreTypes.h:97
int high() const
Get the $high dimension.
Definition: MooreTypes.h:103
RangeDir dir
The direction of the vector, i.e. whether a > b or a < b.
Definition: MooreTypes.h:66
std::string toString() const
Format this range as a string.
Definition: MooreTypes.h:108
Range(unsigned size)
Construct a range [size-1:0].
Definition: MooreTypes.h:71
int right() const
Get the $right dimension.
Definition: MooreTypes.h:99
int low() const
Get the $low dimension.
Definition: MooreTypes.h:101
int increment() const
Get the $increment size.
Definition: MooreTypes.h:105
Range(int left, int right)
Construct a range [left:right], with the direction inferred asDownif left >= right,...
Definition: MooreTypes.h:80
A simple bit vector type.
Definition: MooreTypes.h:134
std::string toString() const
Format this simple bit vector type as a string.
Definition: MooreTypes.h:177
SimpleBitVectorType(Domain domain, Sign sign, unsigned size, bool usedAtom=false, bool explicitSign=false, bool explicitSize=true)
Create a new SBVT with the given domain, sign, and size.
Definition: MooreTypes.h:140
unsigned size
The size of the vector.
Definition: MooreTypes.h:184
bool explicitSize
Whether the single-bit vector had an explicit range in the source text.
Definition: MooreTypes.h:201
bool isSigned() const
Check whether the type is signed.
Definition: MooreTypes.h:155
bool usedAtom
Whether the type used an integer atom like int in the source text.
Definition: MooreTypes.h:196
bool explicitSign
Whether the sign was explicit in the source text.
Definition: MooreTypes.h:198
PackedType getType(MLIRContext *context) const
Convert this SBVT to an actual type.
Definition: MooreTypes.cpp:72
bool isEquivalent(const SimpleBitVectorType &other) const
Check whether this type is equivalent to another.
Definition: MooreTypes.h:161
Range getRange() const
Get the range of the type.
Definition: MooreTypes.h:158
bool operator==(const SimpleBitVectorType &other) const
Definition: MooreTypes.h:165
SimpleBitVectorType()
Create a null SBVT.
Definition: MooreTypes.h:136
Domain domain
The domain, which dictates whether this is a bit or logic vector.
Definition: MooreTypes.h:186
bool isUnsigned() const
Check whether the type is unsigned.
Definition: MooreTypes.h:152
A member of a struct.
Definition: MooreTypes.h:1055
Location loc
The location in the source text where this member was declared.
Definition: MooreTypes.h:1059
StringAttr name
The name of this member.
Definition: MooreTypes.h:1057
UnpackedType type
The type of this member.
Definition: MooreTypes.h:1061
bool operator==(const StructMember &other) const
Definition: MooreTypes.h:1063
std::optional< unsigned > bitSize
The size of this struct in bits.
Definition: MooreTypes.h:1090
StructKind kind
Whether this is a struct, union, or union tagged.
Definition: MooreTypes.h:1081
StringAttr name
The name of the surrounding typedef, if this struct is embedded in a typedef.
Definition: MooreTypes.h:1093
Location loc
The location in the source text where the struct was declared.
Definition: MooreTypes.h:1097
void format(llvm::raw_ostream &os, bool packed=false, std::optional< Sign > signing={}) const
Format this struct in SystemVerilog syntax.
Domain domain
The value domain of this struct.
Definition: MooreTypes.h:1086
SmallVector< StructMember, 4 > members
The list of members.
Definition: MooreTypes.h:1083
Struct(StructKind kind, ArrayRef< StructMember > members, StringAttr name, Location loc)
Create a new struct.
static bool isEqual(const Range &lhs, const Range &rhs)
Definition: MooreTypes.h:1195
static unsigned getHashValue(const Range &x)
Definition: MooreTypes.h:1192