CIRCT  20.0.0git
FVInt.h
Go to the documentation of this file.
1 //===- FVInt.h - Four-valued integer ----------------------------*- 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 implements a class to represent arbitrary precision integers where
10 // each bit can be one of four values. This corresponds to SystemVerilog's
11 // four-valued `logic` type (originally defined in IEEE 1364, later merged into
12 // IEEE 1800).
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef CIRCT_SUPPORT_FVINT_H
17 #define CIRCT_SUPPORT_FVINT_H
18 
19 #include "circt/Support/LLVM.h"
20 #include "llvm/ADT/APInt.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 namespace llvm {
26 template <typename T, typename Enable>
27 struct DenseMapInfo;
28 } // namespace llvm
29 
30 namespace circt {
31 
32 /// Four-valued arbitrary precision integers.
33 ///
34 /// Each bit of the integer can be 0, 1, X, or Z. Internally the bits are stored
35 /// in a pair of `APInt`s, one of which specifies the value of each bit (0/X or
36 /// 1/Z), and the other whether the bit is unknown (X or Z).
37 class FVInt {
38 public:
39  /// Default constructor that creates an zero-bit zero value.
40  explicit FVInt() : FVInt(0, 0) {}
41 
42  /// Construct an `FVInt` from a 64-bit value. The result has no X or Z bits.
43  FVInt(unsigned numBits, uint64_t value, bool isSigned = false)
44  : FVInt(APInt(numBits, value, isSigned)) {}
45 
46  /// Construct an `FVInt` from an `APInt`. The result has no X or Z bits.
47  FVInt(const APInt &value)
48  : value(value), unknown(APInt::getZero(value.getBitWidth())) {}
49 
50  /// Construct an `FVInt` from two `APInt`s used internally to store the bit
51  /// data. The first argument specifies whether each bit is 0/X or 1/Z. The
52  /// second argument specifies whether each bit is 0/1 or X/Z. Both `APInt`s
53  /// must have the same bitwidth. The two arguments correspond to the results
54  /// of `getRawValue()` and `getRawUnknown()`.
55  FVInt(APInt &&rawValue, APInt &&rawUnknown)
56  : value(rawValue), unknown(rawUnknown) {
57  assert(rawValue.getBitWidth() == rawUnknown.getBitWidth());
58  }
59 
60  /// Construct an `FVInt` with all bits set to 0.
61  static FVInt getZero(unsigned numBits) {
62  return FVInt(APInt::getZero(numBits));
63  }
64 
65  /// Construct an `FVInt` with all bits set to 1.
66  static FVInt getAllOnes(unsigned numBits) {
67  return FVInt(APInt::getAllOnes(numBits));
68  }
69 
70  /// Construct an `FVInt` with all bits set to X.
71  static FVInt getAllX(unsigned numBits) {
72  return FVInt(APInt::getZero(numBits), APInt::getAllOnes(numBits));
73  }
74 
75  /// Construct an `FVInt` with all bits set to Z.
76  static FVInt getAllZ(unsigned numBits) {
77  return FVInt(APInt::getAllOnes(numBits), APInt::getAllOnes(numBits));
78  }
79 
80  /// Return the number of bits this integer has.
81  unsigned getBitWidth() const { return value.getBitWidth(); }
82 
83  /// Compute the number of active bits in the value. This is the smallest bit
84  /// width to which the value can be truncated without losing information in
85  /// the most significant bits. Or put differently, the value truncated to its
86  /// active bits and zero-extended back to its original width produces the
87  /// original value.
88  unsigned getActiveBits() const {
89  return std::max(value.getActiveBits(), unknown.getActiveBits());
90  }
91 
92  /// Compute the minimum bit width necessary to accurately represent this
93  /// integer's value and sign. This is the smallest bit width to which the
94  /// value can be truncated without losing information in the most significant
95  /// bits and without flipping from negative to positive or vice versa. Or put
96  /// differently, the value truncated to its significant bits and sign-extended
97  /// back to its original width produces the original value.
98  unsigned getSignificantBits() const {
99  return std::max(value.getSignificantBits(), unknown.getSignificantBits());
100  }
101 
102  /// Return the underlying `APInt` used to store whether a bit is 0/X or 1/Z.
103  const APInt &getRawValue() const { return value; }
104 
105  /// Return the underlying `APInt` used to store whether a bit is unknown (X or
106  /// Z).
107  const APInt &getRawUnknown() const { return unknown; }
108 
109  /// Convert the four-valued `FVInt` to a two-valued `APInt` by mapping X and Z
110  /// bits to either 0 or 1.
111  APInt toAPInt(bool unknownBitMapping) const {
112  auto v = value;
113  if (unknownBitMapping)
114  v |= unknown; // set unknown bits to 1
115  else
116  v &= ~unknown; // set unknown bits to 0
117  return v;
118  }
119 
120  //===--------------------------------------------------------------------===//
121  // Resizing
122  //===--------------------------------------------------------------------===//
123 
124  /// Truncate the integer to a smaller bit width. This simply discards the
125  /// high-order bits. If the integer is truncated to a bit width less than its
126  /// "active bits", information will be lost and the resulting integer will
127  /// have a different value.
128  FVInt trunc(unsigned bitWidth) const {
129  assert(bitWidth <= getBitWidth());
130  return FVInt(value.trunc(bitWidth), unknown.trunc(bitWidth));
131  }
132 
133  /// Zero-extend the integer to a new bit width. The additional high-order bits
134  /// are filled in with zero.
135  FVInt zext(unsigned bitWidth) const {
136  assert(bitWidth >= getBitWidth());
137  return FVInt(value.zext(bitWidth), unknown.zext(bitWidth));
138  }
139 
140  /// Sign-extend the integer to a new bit width. The additional high-order bits
141  /// are filled in with the sign bit (top-most bit) of the original number,
142  /// also when that sign bit is X or Z. Zero-width integers are extended with
143  /// zeros.
144  FVInt sext(unsigned bitWidth) const {
145  assert(bitWidth >= getBitWidth());
146  return FVInt(value.sext(bitWidth), unknown.sext(bitWidth));
147  }
148 
149  /// Truncate or zero-extend to a target bit width.
150  FVInt zextOrTrunc(unsigned bitWidth) const {
151  return bitWidth > getBitWidth() ? zext(bitWidth) : trunc(bitWidth);
152  }
153 
154  /// Truncate or sign-extend to a target bit width.
155  FVInt sextOrTrunc(unsigned bitWidth) const {
156  return bitWidth > getBitWidth() ? sext(bitWidth) : trunc(bitWidth);
157  }
158 
159  //===--------------------------------------------------------------------===//
160  // Value Tests
161  //===--------------------------------------------------------------------===//
162 
163  /// Determine if any bits are X or Z.
164  bool hasUnknown() const { return !unknown.isZero(); }
165 
166  /// Determine if all bits are 0. This is true for zero-width values.
167  bool isZero() const { return value.isZero() && unknown.isZero(); }
168 
169  /// Determine if all bits are 1. This is true for zero-width values.
170  bool isAllOnes() const { return value.isAllOnes() && unknown.isZero(); }
171 
172  /// Determine if all bits are X. This is true for zero-width values.
173  bool isAllX() const { return value.isZero() && unknown.isAllOnes(); }
174 
175  /// Determine if all bits are Z. This is true for zero-width values.
176  bool isAllZ() const { return value.isAllOnes() && unknown.isAllOnes(); }
177 
178  /// Determine whether the integer interpreted as a signed number would be
179  /// negative. Returns true if the sign bit is 1, and false if it is 0, X, or
180  /// Z.
181  bool isNegative() const {
182  auto idx = getBitWidth() - 1;
183  return value[idx] && !unknown[idx];
184  }
185 
186  //===--------------------------------------------------------------------===//
187  // Bit Manipulation
188  //===--------------------------------------------------------------------===//
189 
190  /// The value of an individual bit. Can be 0, 1, X, or Z.
191  enum Bit { V0 = 0b00, V1 = 0b01, X = 0b10, Z = 0b11 };
192 
193  /// Get the value of an individual bit.
194  Bit getBit(unsigned index) const {
195  return static_cast<Bit>(value[index] | unknown[index] << 1);
196  }
197 
198  /// Set the value of an individual bit.
199  void setBit(unsigned index, Bit bit) {
200  value.setBitVal(index, (bit >> 0) & 1);
201  unknown.setBitVal(index, (bit >> 1) & 1);
202  }
203 
204  void setBit(unsigned index, bool val) {
205  setBit(index, static_cast<Bit>(val));
206  }
207 
208  /// Compute a mask of all the 0 bits in this integer.
209  APInt getZeroBits() const { return ~value & ~unknown; }
210 
211  /// Compute a mask of all the 1 bits in this integer.
212  APInt getOneBits() const { return value & ~unknown; }
213 
214  /// Compute a mask of all the X bits in this integer.
215  APInt getXBits() const { return ~value & unknown; }
216 
217  /// Compute a mask of all the Z bits in this integer.
218  APInt getZBits() const { return value & unknown; }
219 
220  /// Compute a mask of all the X and Z bits in this integer.
221  APInt getUnknownBits() const { return unknown; }
222 
223  /// Set the value of all bits in the mask to 0.
224  template <typename T>
225  void setZeroBits(const T &mask) {
226  value &= ~mask;
227  unknown &= ~mask;
228  }
229 
230  /// Set the value of all bits in the mask to 1.
231  template <typename T>
232  void setOneBits(const T &mask) {
233  value |= mask;
234  unknown &= ~mask;
235  }
236 
237  /// Set the value of all bits in the mask to X.
238  template <typename T>
239  void setXBits(const T &mask) {
240  value &= ~mask;
241  unknown |= mask;
242  }
243 
244  /// Set the value of all bits in the mask to Z.
245  template <typename T>
246  void setZBits(const T &mask) {
247  value |= mask;
248  unknown |= mask;
249  }
250 
251  /// Set all bits to 0.
252  void setAllZero() {
253  value.clearAllBits();
254  unknown.clearAllBits();
255  }
256 
257  /// Set all bits to 1.
258  void setAllOne() {
259  value.setAllBits();
260  unknown.clearAllBits();
261  }
262 
263  /// Set all bits to X.
264  void setAllX() {
265  value.clearAllBits();
266  unknown.setAllBits();
267  }
268 
269  /// Set all bits to Z.
270  void setAllZ() {
271  value.setAllBits();
272  unknown.setAllBits();
273  }
274 
275  /// Replace all Z bits with X. This is useful since most logic operations will
276  /// treat X and Z bits the same way and produce an X bit in the output. By
277  /// mapping Z bits to X, these operations can then just handle 0, 1, and X
278  /// bits.
279  void replaceZWithX() {
280  // Z bits have value and unknown set to 1. X bits have value set to 0 and
281  // unknown set to 1. To convert between the two, make sure that value is 0
282  // wherever unknown is 1.
283  value &= ~unknown;
284  }
285 
286  /// If any bits are X or Z, set the entire integer to X.
288  if (hasUnknown())
289  setAllX();
290  }
291 
292  /// If any bits in this integer or another integer are X or Z, set the entire
293  /// integer to X. This is useful for binary operators which want to set their
294  /// result to X if either of the two inputs contained an X or Z bit.
295  void setAllXIfAnyUnknown(const FVInt &other) {
296  if (hasUnknown() || other.hasUnknown())
297  setAllX();
298  }
299 
300  //===--------------------------------------------------------------------===//
301  // Shift Operators
302  //===--------------------------------------------------------------------===//
303 
304  /// Perform a logical left-shift. If any bits in the shift amount are unknown,
305  /// the entire result is X.
306  FVInt &operator<<=(const FVInt &amount) {
307  if (amount.hasUnknown()) {
308  setAllX();
309  } else {
310  value <<= amount.value;
311  unknown <<= amount.value;
312  }
313  return *this;
314  }
315 
316  /// Perform a logical left-shift by a two-valued amount.
317  template <typename T>
318  FVInt &operator<<=(const T &amount) {
319  value <<= amount;
320  unknown <<= amount;
321  return *this;
322  }
323 
324  //===--------------------------------------------------------------------===//
325  // Logic Operators
326  //===--------------------------------------------------------------------===//
327 
328  /// Compute the logical NOT of this integer. This implements the following
329  /// bit-wise truth table:
330  /// ```
331  /// 0 | 1
332  /// 1 | 0
333  /// X | X
334  /// Z | X
335  /// ```
336  void flipAllBits() {
337  value = ~value;
338  replaceZWithX();
339  }
340 
341  /// Compute the logical NOT.
342  FVInt operator~() const {
343  auto v = *this;
344  v.flipAllBits();
345  return v;
346  }
347 
348  /// Compute the logical AND of this integer and another. This implements the
349  /// following bit-wise truth table:
350  /// ```
351  /// 0 1 X Z
352  /// +--------
353  /// 0 | 0 0 0 0
354  /// 1 | 0 1 X X
355  /// X | 0 X X X
356  /// Z | 0 X X X
357  /// ```
358  FVInt &operator&=(const FVInt &other) {
359  auto zeros = getZeroBits() | other.getZeroBits();
360  value &= other.value;
361  unknown |= other.unknown;
362  unknown &= ~zeros;
363  replaceZWithX();
364  return *this;
365  }
366 
367  /// Compute the logical AND of this integer and a two-valued integer.
368  template <typename T>
369  FVInt &operator&=(T other) {
370  value &= other;
371  unknown &= other; // make 0 bits known
372  replaceZWithX();
373  return *this;
374  }
375 
376  /// Compute the logical AND.
377  template <typename T>
378  FVInt operator&(const T &other) const {
379  auto v = *this;
380  v &= other;
381  return v;
382  }
383 
384  /// Compute the logical OR of this integer and another. This implements the
385  /// following bit-wise truth table:
386  /// ```
387  /// 0 1 X Z
388  /// +--------
389  /// 0 | 0 1 X X
390  /// 1 | 1 1 1 1
391  /// X | X 1 X X
392  /// Z | X 1 X X
393  /// ```
394  FVInt &operator|=(const FVInt &other) {
395  auto ones = getOneBits() | other.getOneBits();
396  value |= other.value;
397  unknown |= other.unknown;
398  unknown &= ~ones;
399  replaceZWithX();
400  return *this;
401  }
402 
403  /// Compute the logical OR of this integer and a two-valued integer.
404  template <typename T>
405  FVInt &operator|=(T other) {
406  value |= other;
407  unknown &= ~other; // make 1 bits known
408  replaceZWithX();
409  return *this;
410  }
411 
412  /// Compute the logical OR.
413  template <typename T>
414  FVInt operator|(const T &other) const {
415  auto v = *this;
416  v |= other;
417  return v;
418  }
419 
420  /// Compute the logical XOR of this integer and another. This implements the
421  /// following bit-wise truth table:
422  /// ```
423  /// 0 1 X Z
424  /// +--------
425  /// 0 | 0 1 X X
426  /// 1 | 1 0 X X
427  /// X | X X X X
428  /// Z | X X X X
429  /// ```
430  FVInt &operator^=(const FVInt &other) {
431  value ^= other.value;
432  unknown |= other.unknown;
433  replaceZWithX();
434  return *this;
435  }
436 
437  /// Compute the logical XOR of this integer and a two-valued integer.
438  template <typename T>
439  FVInt &operator^=(const T &other) {
440  value ^= other;
441  replaceZWithX();
442  return *this;
443  }
444 
445  /// Compute the logical XOR.
446  template <typename T>
447  FVInt operator^(const T &other) const {
448  auto v = *this;
449  v ^= other;
450  return v;
451  }
452 
453  //===--------------------------------------------------------------------===//
454  // Arithmetic Operators
455  //===--------------------------------------------------------------------===//
456 
457  /// Compute the negation of this integer. If any bits are unknown, the entire
458  /// result is X.
459  void negate() {
460  value.negate();
462  }
463 
464  /// Compute the negation of this integer.
465  FVInt operator-() const {
466  auto v = *this;
467  v.negate();
468  return v;
469  }
470 
471  /// Compute the addition of this integer and another. If any bits in either
472  /// integer are unknown, the entire result is X.
473  FVInt &operator+=(const FVInt &other) {
474  value += other.value;
475  setAllXIfAnyUnknown(other);
476  return *this;
477  }
478 
479  /// Compute the addition of this integer and a two-valued integer. If any bit
480  /// in the integer is unknown, the entire result is X.
481  template <typename T>
482  FVInt &operator+=(const T &other) {
483  value += other;
485  return *this;
486  }
487 
488  /// Compute an addition.
489  template <typename T>
490  FVInt operator+(const T &other) const {
491  auto v = *this;
492  v += other;
493  return v;
494  }
495 
496  /// Compute the subtraction of this integer and another. If any bits in either
497  /// integer are unknown, the entire result is X.
498  FVInt &operator-=(const FVInt &other) {
499  value -= other.value;
500  setAllXIfAnyUnknown(other);
501  return *this;
502  }
503 
504  /// Compute the subtraction of this integer and a two-valued integer. If any
505  /// bit in the integer is unknown, the entire result is X.
506  template <typename T>
507  FVInt &operator-=(const T &other) {
508  value -= other;
510  return *this;
511  }
512 
513  /// Compute an subtraction.
514  template <typename T>
515  FVInt operator-(const T &other) const {
516  auto v = *this;
517  v -= other;
518  return v;
519  }
520 
521  /// Compute the multiplication of this integer and another. If any bits in
522  /// either integer are unknown, the entire result is X.
523  FVInt &operator*=(const FVInt &other) {
524  value *= other.value;
525  setAllXIfAnyUnknown(other);
526  return *this;
527  }
528 
529  /// Compute the multiplication of this integer and a two-valued integer. If
530  /// any bit in the integer is unknown, the entire result is X.
531  template <typename T>
532  FVInt &operator*=(const T &other) {
533  value *= other;
535  return *this;
536  }
537 
538  /// Compute a multiplication.
539  template <typename T>
540  FVInt operator*(const T &other) const {
541  auto v = *this;
542  v *= other;
543  return v;
544  }
545 
546  //===--------------------------------------------------------------------===//
547  // Comparison
548  //===--------------------------------------------------------------------===//
549 
550  /// Determine whether this integer is equal to another. Note that this
551  /// corresponds to SystemVerilog's `===` operator. Returns false if the two
552  /// integers have different bit width.
553  bool operator==(const FVInt &other) const {
554  if (getBitWidth() != other.getBitWidth())
555  return false;
556  return value == other.value && unknown == other.unknown;
557  }
558 
559  /// Determine whether this integer is equal to a two-valued integer. Note that
560  /// this corresponds to SystemVerilog's `===` operator.
561  template <typename T>
562  bool operator==(const T &other) const {
563  return value == other && !hasUnknown();
564  }
565 
566  /// Determine whether this integer is not equal to another. Returns true if
567  /// the two integers have different bit width.
568  bool operator!=(const FVInt &other) const { return !((*this) == other); }
569 
570  /// Determine whether this integer is not equal to a two-valued integer.
571  template <typename T>
572  bool operator!=(const T &other) const {
573  return !((*this) == other);
574  }
575 
576  //===--------------------------------------------------------------------===//
577  // String Conversion
578  //===--------------------------------------------------------------------===//
579 
580  /// Convert a string into an `FVInt`.
581  ///
582  /// The radix can be 2, 8, 10, or 16. For radix 2, the input string may
583  /// contain the characters `x` or `X` to indicate an unknown X bit, and `z` or
584  /// `Z` to indicate an unknown Z bit. For radix 8, each X or Z counts as 3
585  /// bits. For radix 16, each X and Z counts as 4 bits. When radix is 10 the
586  /// input cannot contain any X or Z.
587  ///
588  /// Returns the parsed integer if the string is non-empty and a well-formed
589  /// number, otherwise returns none.
590  static std::optional<FVInt> tryFromString(StringRef str, unsigned radix = 10);
591 
592  /// Convert a string into an `FVInt`. Same as `tryFromString`, but aborts if
593  /// the string is malformed.
594  static FVInt fromString(StringRef str, unsigned radix = 10) {
595  auto v = tryFromString(str, radix);
596  assert(v.has_value() && "string is not a well-formed FVInt");
597  return *v;
598  }
599 
600  /// Convert an `FVInt` to a string.
601  ///
602  /// The radix can be 2, 8, 10, or 16. For radix 8 or 16, the integer can only
603  /// contain unknown bits in groups of 3 or 4, respectively, such that a `X` or
604  /// `Z` can be printed for the entire group of bits. For radix 10, the integer
605  /// cannot contain any unknown bits. In case the output contains letters,
606  /// `uppercase` specifies whether they are printed as uppercase letters.
607  ///
608  /// Appends the output characters to `str` and returns true if the integer
609  /// could be printed with the given configuration. Otherwise returns false and
610  /// leaves `str` in its original state. Always succeeds for radix 2.
611  bool tryToString(SmallVectorImpl<char> &str, unsigned radix = 10,
612  bool uppercase = true) const;
613 
614  /// Convert an `FVInt` to a string. Same as `tryToString`, but directly
615  /// returns the string and aborts if the conversion is unsuccessful.
616  SmallString<16> toString(unsigned radix = 10, bool uppercase = true) const {
617  SmallString<16> str;
618  bool success = tryToString(str, radix, uppercase);
619  assert(success && "radix cannot represent FVInt");
620  return str;
621  }
622 
623  /// Print an `FVInt` to an output stream.
624  void print(raw_ostream &os) const;
625 
626 private:
627  APInt value;
628  APInt unknown;
629 };
630 
631 inline FVInt operator&(uint64_t a, const FVInt &b) { return b & a; }
632 inline FVInt operator|(uint64_t a, const FVInt &b) { return b | a; }
633 inline FVInt operator^(uint64_t a, const FVInt &b) { return b ^ a; }
634 inline FVInt operator+(uint64_t a, const FVInt &b) { return b + a; }
635 inline FVInt operator*(uint64_t a, const FVInt &b) { return b * a; }
636 
637 inline FVInt operator&(const APInt &a, const FVInt &b) { return b & a; }
638 inline FVInt operator|(const APInt &a, const FVInt &b) { return b | a; }
639 inline FVInt operator^(const APInt &a, const FVInt &b) { return b ^ a; }
640 inline FVInt operator+(const APInt &a, const FVInt &b) { return b + a; }
641 inline FVInt operator*(const APInt &a, const FVInt &b) { return b * a; }
642 
643 inline FVInt operator-(uint64_t a, const FVInt &b) {
644  return FVInt(b.getBitWidth(), a) - b;
645 }
646 
647 inline FVInt operator-(const APInt &a, const FVInt &b) { return FVInt(a) - b; }
648 
649 inline bool operator==(uint64_t a, const FVInt &b) { return b == a; }
650 inline bool operator!=(uint64_t a, const FVInt &b) { return b != a; }
651 
652 inline raw_ostream &operator<<(raw_ostream &os, const FVInt &value) {
653  value.print(os);
654  return os;
655 }
656 
657 llvm::hash_code hash_value(const FVInt &a);
658 
659 /// Print a four-valued integer usign an `AsmPrinter`. This produces the
660 /// following output formats:
661 ///
662 /// - Decimal notation if the integer has no unknown bits. The sign bit is used
663 /// to determine whether the value is printed as negative number or not.
664 /// - Hexadecimal notation with a leading `h` if the integer the bits in each
665 /// hex digit are either all known, all X, or all Z.
666 /// - Binary notation with a leading `b` in all other cases.
667 void printFVInt(AsmPrinter &p, const FVInt &value);
668 
669 /// Parse a four-valued integer using an `AsmParser`. This accepts the following
670 /// formats:
671 ///
672 /// - `42`/`-42`: positive or negative integer in decimal notation. The sign bit
673 /// of the result indicates whether the value was negative. Cannot contain
674 /// unknown X or Z digits.
675 /// - `h123456789ABCDEF0XZ`: signless integer in hexadecimal notation. Can
676 /// contain unknown X or Z digits.
677 /// - `b10XZ`: signless integer in binary notation. Can contain unknown X or Z
678 /// digits.
679 ///
680 /// The result has enough bits to fully represent the parsed integer, and to
681 /// have the sign bit encode whether the integer was written as a negative
682 /// number in the input. The result's bit width may be larger than the minimum
683 /// number of bits required to represent its value.
684 ParseResult parseFVInt(AsmParser &p, FVInt &result);
685 
686 } // namespace circt
687 
688 namespace llvm {
689 /// Provide DenseMapInfo for FVInt.
690 template <>
691 struct DenseMapInfo<circt::FVInt, void> {
692  static inline circt::FVInt getEmptyKey() {
694  }
695 
696  static inline circt::FVInt getTombstoneKey() {
698  }
699 
700  static unsigned getHashValue(const circt::FVInt &Key);
701 
702  static bool isEqual(const circt::FVInt &LHS, const circt::FVInt &RHS) {
703  return LHS == RHS;
704  }
705 };
706 } // namespace llvm
707 
708 #endif // CIRCT_SUPPORT_FVINT_H
assert(baseType &&"element must be base type")
Four-valued arbitrary precision integers.
Definition: FVInt.h:37
void setAllXIfAnyUnknown()
If any bits are X or Z, set the entire integer to X.
Definition: FVInt.h:287
void setAllOne()
Set all bits to 1.
Definition: FVInt.h:258
FVInt & operator^=(const FVInt &other)
Compute the logical XOR of this integer and another.
Definition: FVInt.h:430
FVInt(APInt &&rawValue, APInt &&rawUnknown)
Construct an FVInt from two APInts used internally to store the bit data.
Definition: FVInt.h:55
static FVInt getZero(unsigned numBits)
Construct an FVInt with all bits set to 0.
Definition: FVInt.h:61
FVInt & operator|=(T other)
Compute the logical OR of this integer and a two-valued integer.
Definition: FVInt.h:405
void setBit(unsigned index, bool val)
Definition: FVInt.h:204
FVInt & operator<<=(const T &amount)
Perform a logical left-shift by a two-valued amount.
Definition: FVInt.h:318
FVInt operator&(const T &other) const
Compute the logical AND.
Definition: FVInt.h:378
void negate()
Compute the negation of this integer.
Definition: FVInt.h:459
Bit
The value of an individual bit. Can be 0, 1, X, or Z.
Definition: FVInt.h:191
void setAllZ()
Set all bits to Z.
Definition: FVInt.h:270
FVInt(const APInt &value)
Construct an FVInt from an APInt. The result has no X or Z bits.
Definition: FVInt.h:47
FVInt & operator&=(T other)
Compute the logical AND of this integer and a two-valued integer.
Definition: FVInt.h:369
APInt value
Definition: FVInt.h:627
bool operator==(const T &other) const
Determine whether this integer is equal to a two-valued integer.
Definition: FVInt.h:562
APInt getOneBits() const
Compute a mask of all the 1 bits in this integer.
Definition: FVInt.h:212
Bit getBit(unsigned index) const
Get the value of an individual bit.
Definition: FVInt.h:194
FVInt & operator+=(const T &other)
Compute the addition of this integer and a two-valued integer.
Definition: FVInt.h:482
FVInt()
Default constructor that creates an zero-bit zero value.
Definition: FVInt.h:40
FVInt & operator-=(const FVInt &other)
Compute the subtraction of this integer and another.
Definition: FVInt.h:498
APInt getXBits() const
Compute a mask of all the X bits in this integer.
Definition: FVInt.h:215
static FVInt getAllZ(unsigned numBits)
Construct an FVInt with all bits set to Z.
Definition: FVInt.h:76
FVInt sextOrTrunc(unsigned bitWidth) const
Truncate or sign-extend to a target bit width.
Definition: FVInt.h:155
void setAllXIfAnyUnknown(const FVInt &other)
If any bits in this integer or another integer are X or Z, set the entire integer to X.
Definition: FVInt.h:295
bool operator==(const FVInt &other) const
Determine whether this integer is equal to another.
Definition: FVInt.h:553
void setAllZero()
Set all bits to 0.
Definition: FVInt.h:252
FVInt zextOrTrunc(unsigned bitWidth) const
Truncate or zero-extend to a target bit width.
Definition: FVInt.h:150
APInt getZeroBits() const
Compute a mask of all the 0 bits in this integer.
Definition: FVInt.h:209
FVInt operator|(const T &other) const
Compute the logical OR.
Definition: FVInt.h:414
bool isNegative() const
Determine whether the integer interpreted as a signed number would be negative.
Definition: FVInt.h:181
FVInt & operator<<=(const FVInt &amount)
Perform a logical left-shift.
Definition: FVInt.h:306
FVInt & operator*=(const T &other)
Compute the multiplication of this integer and a two-valued integer.
Definition: FVInt.h:532
FVInt operator*(const T &other) const
Compute a multiplication.
Definition: FVInt.h:540
FVInt operator-() const
Compute the negation of this integer.
Definition: FVInt.h:465
FVInt operator^(const T &other) const
Compute the logical XOR.
Definition: FVInt.h:447
void setZeroBits(const T &mask)
Set the value of all bits in the mask to 0.
Definition: FVInt.h:225
FVInt & operator+=(const FVInt &other)
Compute the addition of this integer and another.
Definition: FVInt.h:473
bool isAllZ() const
Determine if all bits are Z. This is true for zero-width values.
Definition: FVInt.h:176
FVInt & operator|=(const FVInt &other)
Compute the logical OR of this integer and another.
Definition: FVInt.h:394
void setAllX()
Set all bits to X.
Definition: FVInt.h:264
void replaceZWithX()
Replace all Z bits with X.
Definition: FVInt.h:279
FVInt & operator&=(const FVInt &other)
Compute the logical AND of this integer and another.
Definition: FVInt.h:358
void setOneBits(const T &mask)
Set the value of all bits in the mask to 1.
Definition: FVInt.h:232
APInt unknown
Definition: FVInt.h:628
static std::optional< FVInt > tryFromString(StringRef str, unsigned radix=10)
Convert a string into an FVInt.
Definition: FVInt.cpp:17
FVInt & operator*=(const FVInt &other)
Compute the multiplication of this integer and another.
Definition: FVInt.h:523
bool isAllX() const
Determine if all bits are X. This is true for zero-width values.
Definition: FVInt.h:173
FVInt operator-(const T &other) const
Compute an subtraction.
Definition: FVInt.h:515
APInt getZBits() const
Compute a mask of all the Z bits in this integer.
Definition: FVInt.h:218
static FVInt fromString(StringRef str, unsigned radix=10)
Convert a string into an FVInt.
Definition: FVInt.h:594
static FVInt getAllOnes(unsigned numBits)
Construct an FVInt with all bits set to 1.
Definition: FVInt.h:66
FVInt operator+(const T &other) const
Compute an addition.
Definition: FVInt.h:490
const APInt & getRawUnknown() const
Return the underlying APInt used to store whether a bit is unknown (X or Z).
Definition: FVInt.h:107
bool operator!=(const T &other) const
Determine whether this integer is not equal to a two-valued integer.
Definition: FVInt.h:572
FVInt sext(unsigned bitWidth) const
Sign-extend the integer to a new bit width.
Definition: FVInt.h:144
unsigned getSignificantBits() const
Compute the minimum bit width necessary to accurately represent this integer's value and sign.
Definition: FVInt.h:98
void flipAllBits()
Compute the logical NOT of this integer.
Definition: FVInt.h:336
SmallString< 16 > toString(unsigned radix=10, bool uppercase=true) const
Convert an FVInt to a string.
Definition: FVInt.h:616
void setXBits(const T &mask)
Set the value of all bits in the mask to X.
Definition: FVInt.h:239
static FVInt getAllX(unsigned numBits)
Construct an FVInt with all bits set to X.
Definition: FVInt.h:71
void print(raw_ostream &os) const
Print an FVInt to an output stream.
Definition: FVInt.cpp:135
void setBit(unsigned index, Bit bit)
Set the value of an individual bit.
Definition: FVInt.h:199
bool hasUnknown() const
Determine if any bits are X or Z.
Definition: FVInt.h:164
APInt toAPInt(bool unknownBitMapping) const
Convert the four-valued FVInt to a two-valued APInt by mapping X and Z bits to either 0 or 1.
Definition: FVInt.h:111
FVInt & operator^=(const T &other)
Compute the logical XOR of this integer and a two-valued integer.
Definition: FVInt.h:439
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition: FVInt.h:88
bool isAllOnes() const
Determine if all bits are 1. This is true for zero-width values.
Definition: FVInt.h:170
FVInt operator~() const
Compute the logical NOT.
Definition: FVInt.h:342
FVInt zext(unsigned bitWidth) const
Zero-extend the integer to a new bit width.
Definition: FVInt.h:135
FVInt & operator-=(const T &other)
Compute the subtraction of this integer and a two-valued integer.
Definition: FVInt.h:507
APInt getUnknownBits() const
Compute a mask of all the X and Z bits in this integer.
Definition: FVInt.h:221
unsigned getBitWidth() const
Return the number of bits this integer has.
Definition: FVInt.h:81
bool isZero() const
Determine if all bits are 0. This is true for zero-width values.
Definition: FVInt.h:167
FVInt(unsigned numBits, uint64_t value, bool isSigned=false)
Construct an FVInt from a 64-bit value. The result has no X or Z bits.
Definition: FVInt.h:43
void setZBits(const T &mask)
Set the value of all bits in the mask to Z.
Definition: FVInt.h:246
const APInt & getRawValue() const
Return the underlying APInt used to store whether a bit is 0/X or 1/Z.
Definition: FVInt.h:103
bool tryToString(SmallVectorImpl< char > &str, unsigned radix=10, bool uppercase=true) const
Convert an FVInt to a string.
Definition: FVInt.cpp:68
bool operator!=(const FVInt &other) const
Determine whether this integer is not equal to another.
Definition: FVInt.h:568
FVInt trunc(unsigned bitWidth) const
Truncate the integer to a smaller bit width.
Definition: FVInt.h:128
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
FVInt operator^(uint64_t a, const FVInt &b)
Definition: FVInt.h:633
FVInt operator|(uint64_t a, const FVInt &b)
Definition: FVInt.h:632
inline ::llvm::hash_code hash_value(const FieldRef &fieldRef)
Get a hash code for a FieldRef.
Definition: FieldRef.h:92
FVInt operator*(uint64_t a, const FVInt &b)
Definition: FVInt.h:635
void printFVInt(AsmPrinter &p, const FVInt &value)
Print a four-valued integer usign an AsmPrinter.
Definition: FVInt.cpp:147
ParseResult parseFVInt(AsmParser &p, FVInt &result)
Parse a four-valued integer using an AsmParser.
Definition: FVInt.cpp:162
FVInt operator&(uint64_t a, const FVInt &b)
Definition: FVInt.h:631
FVInt operator-(uint64_t a, const FVInt &b)
Definition: FVInt.h:643
bool operator==(uint64_t a, const FVInt &b)
Definition: FVInt.h:649
bool operator!=(uint64_t a, const FVInt &b)
Definition: FVInt.h:650
raw_ostream & operator<<(raw_ostream &os, const FVInt &value)
Definition: FVInt.h:652
FVInt operator+(uint64_t a, const FVInt &b)
Definition: FVInt.h:634
static circt::FVInt getEmptyKey()
Definition: FVInt.h:692
static unsigned getHashValue(const circt::FVInt &Key)
static bool isEqual(const circt::FVInt &LHS, const circt::FVInt &RHS)
Definition: FVInt.h:702
static circt::FVInt getTombstoneKey()
Definition: FVInt.h:696