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