10 #include "mlir/IR/OpImplementation.h"
11 #include "llvm/ADT/StringExtras.h"
13 #define DEBUG_TYPE "fvint"
15 using namespace circt;
18 assert(radix == 2 || radix == 8 || radix == 10 || radix == 16);
23 unsigned radixLog2 = 0;
24 for (
unsigned r = radix - 1; r > 0; r >>= 1)
26 bool radixIsPow2 = (radix == (1U << radixLog2));
30 while (!str.empty()) {
31 unsigned digit = llvm::toLower(str[0]);
32 str = str.drop_front();
35 if (digit ==
'x' || digit ==
'z') {
39 result.unknown.setLowBits(radixLog2);
41 result.value.setLowBits(radixLog2);
46 if (digit >=
'0' && digit <=
'9')
48 else if (digit >=
'a' && digit <=
'z')
49 digit = digit -
'a' + 10;
58 result.value |= digit;
60 result.value *= radix;
61 result.value += digit;
69 bool uppercase)
const {
70 size_t strBaseLen = str.size();
71 assert(radix == 2 || radix == 8 || radix == 10 || radix == 16);
74 unsigned radixLog2 = 0;
75 for (
unsigned r = radix - 1; r > 0; r >>= 1)
77 bool radixIsPow2 = (radix == (1U << radixLog2));
78 unsigned radixMask = (1U << radixLog2) - 1;
83 value.toString(str, radix,
false,
false,
99 char chrA = uppercase ?
'A' :
'a';
100 char chrX = uppercase ?
'X' :
'x';
101 char chrZ = uppercase ?
'Z' :
'z';
104 unsigned digitValue =
value.getRawData()[0] & radixMask;
105 unsigned digitUnknown =
unknown.getRawData()[0] & radixMask;
106 unsigned shiftAmount = std::min(radixLog2,
getBitWidth());
107 value.lshrInPlace(shiftAmount);
108 unknown.lshrInPlace(shiftAmount);
113 if (digitUnknown != 0) {
114 if (digitUnknown != radixMask ||
115 (digitValue != 0 && digitValue != radixMask)) {
116 str.resize(strBaseLen);
119 str.push_back(digitValue == 0 ? chrX : chrZ);
125 str.push_back(digitValue +
'0');
127 str.push_back(digitValue - 10 + chrA);
131 std::reverse(str.begin() + strBaseLen, str.end());
136 SmallString<32> buffer;
148 SmallString<32> buffer;
150 (-value).tryToString(buffer)) {
167 auto valueLoc = p.getCurrentLocation();
168 if (succeeded(p.parseOptionalKeyword(&strValue))) {
171 if (strValue.consume_front(
"b")) {
173 }
else if (strValue.consume_front(
"h")) {
176 return p.emitError(valueLoc) <<
"expected `b` or `h` prefix";
182 return p.emitError(valueLoc)
183 <<
"expected base-" << base <<
" four-valued integer";
187 result = parsedValue->
zext(parsedValue->getBitWidth() + 1);
190 if (p.parseInteger(intValue))
192 result = std::move(intValue);
197 unsigned DenseMapInfo<FVInt, void>::getHashValue(
const FVInt &Key) {
198 return static_cast<unsigned>(
hash_value(Key));
assert(baseType &&"element must be base type")
Four-valued arbitrary precision integers.
static FVInt getZero(unsigned numBits)
Construct an FVInt with all bits set to 0.
bool isNegative() const
Determine whether the integer interpreted as a signed number would be negative.
static std::optional< FVInt > tryFromString(StringRef str, unsigned radix=10)
Convert a string into an FVInt.
const APInt & getRawUnknown() const
Return the underlying APInt used to store whether a bit is unknown (X or Z).
void print(raw_ostream &os) const
Print an FVInt to an output stream.
bool hasUnknown() const
Determine if any bits are X or Z.
FVInt zext(unsigned bitWidth) const
Zero-extend the integer to a new bit width.
unsigned getBitWidth() const
Return the number of bits this integer has.
const APInt & getRawValue() const
Return the underlying APInt used to store whether a bit is 0/X or 1/Z.
bool tryToString(SmallVectorImpl< char > &str, unsigned radix=10, bool uppercase=true) const
Convert an FVInt to a string.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
inline ::llvm::hash_code hash_value(const FieldRef &fieldRef)
Get a hash code for a FieldRef.
void printFVInt(AsmPrinter &p, const FVInt &value)
Print a four-valued integer usign an AsmPrinter.
ParseResult parseFVInt(AsmParser &p, FVInt &result)
Parse a four-valued integer using an AsmParser.
size_t hash_combine(size_t h1, size_t h2)
C++'s stdlib doesn't have a hash_combine function. This is a simple one.