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