Update linfstwriter from upstream (#7193 prep) (#8181)

This commit is contained in:
Wilson Snyder
2026-08-21 16:35:15 +02:00
committed by GitHub
parent e656b11cd1
commit 99c26d3994
3 changed files with 161 additions and 61 deletions
+124 -53
View File
@@ -423,18 +423,26 @@ public:
void emitValueChange(uint64_t current_time_index, const uint32_t *val, EncodingType encoding) {
auto wh = emitValueChangeCommonPart(current_time_index, encoding);
for (unsigned i = 0; i < bitPerEncodedBit(encoding); ++i) {
// C++17: replace this with if constexpr
if (sizeof(T) == 8) {
// C++17: replace this with if constexpr
if (sizeof(T) == 8) {
if (encoding == EncodingType::VERILOG) {
uint64_t v = val[2]; // high bits
v <<= 32;
v |= val[0]; // low bits
wh.template write<uint64_t>(v);
v = val[3]; // high bits
v <<= 32;
v |= val[1]; // low bits
wh.template write<uint64_t>(v);
} else {
uint64_t v = val[1]; // high bits
v <<= 32;
v |= val[0]; // low bits
wh.template write<uint64_t>(v);
val += 2;
} else {
wh.template write<T>(val[0]);
val += 1;
}
} else {
wh.template write<T>(val[0]);
if (encoding == EncodingType::VERILOG) wh.template write<T>(val[1]);
}
}
@@ -517,7 +525,7 @@ public:
} else {
unsigned val = 0;
for (unsigned i = 0; i < num_element; ++i) {
val |= rh.peek<T>(i);
val |= rh.peek<T>(i) << i;
}
uint64_t delta_time_index = time_index - prev_time_index;
prev_time_index = time_index;
@@ -525,8 +533,8 @@ public:
// clang-format off
case 0: delta_time_index = (delta_time_index<<2) | (0<<1) | 0; break; // '0'
case 1: delta_time_index = (delta_time_index<<2) | (1<<1) | 0; break; // '1'
case 2: delta_time_index = (delta_time_index<<4) | (0<<1) | 1; break; // 'X'
case 3: delta_time_index = (delta_time_index<<4) | (1<<1) | 1; break; // 'Z'
case 2: delta_time_index = (delta_time_index<<4) | (1<<1) | 1; break; // 'Z'
case 3: delta_time_index = (delta_time_index<<4) | (0<<1) | 1; break; // 'X'
// Not supporting VHDL now
// LCOV_EXCL_START
case 4: delta_time_index = (delta_time_index<<4) | (2<<1) | 1; break; // 'H'
@@ -556,13 +564,29 @@ public:
if (first) {
first = false;
} else {
FST_CHECK(enc == EncodingType::BINARY); // TODO
const bool has_non_binary = enc != EncodingType::BINARY;
const uint64_t delta_time_index = time_index - prev_time_index;
prev_time_index = time_index;
h //
.writeLEB128((delta_time_index << 1) | has_non_binary)
.writeUIntPartialForValueChange(rh.peek<T>(), bitwidth);
switch (enc) {
case EncodingType::BINARY: {
h //
.writeLEB128(delta_time_index << 1)
.writeUIntPartialForValueChange(rh.peek<T>(), bitwidth);
} break;
case EncodingType::VERILOG: {
h.writeLEB128((delta_time_index << 1) | 1);
const T val = rh.peek<T>();
const T xz = rh.peek<T>(1);
for (int j = bitwidth; j > 0;) {
--j;
h.writeUIntBE(
kEncodedBitToCharTable[(((xz >> j) << 1) & 2) | ((val >> j) & 1)]
);
}
} break;
[[unlikely]] case EncodingType::VHDL: {
FST_FAIL_STRING("VHDL format is unsupported with wide values");
} break;
}
}
rh.skip(num_byte);
}
@@ -573,16 +597,26 @@ public:
class VariableInfoLongInt {
VariableInfo &info;
unsigned num_words() const { return (info.bitwidth() + 63) / 64; }
unsigned num_words32() const { return (info.bitwidth() + 31) / 32; }
public:
VariableInfoLongInt(VariableInfo &info_) : info(info_) {}
public:
size_t computeBytesNeededNoHeader(EncodingType encoding) const {
switch (encoding) {
case EncodingType::BINARY:
return num_words() * sizeof(uint64_t);
case EncodingType::VERILOG:
return num_words32() * sizeof(uint32_t) * 2;
[[unlikely]] case EncodingType::VHDL:
FST_FAIL_STRING("VHDL format is unsupported with wide values");
}
FST_UNREACHABLE;
}
size_t computeBytesNeeded(EncodingType encoding) const {
return (
kEmitTimeIndexAndEncodingSize +
num_words() * sizeof(uint64_t) * bitPerEncodedBit(encoding)
);
return kEmitTimeIndexAndEncodingSize + computeBytesNeededNoHeader(encoding);
}
EmitWriterHelper emitValueChangeCommonPart(uint64_t current_time_index, EncodingType encoding) {
@@ -600,13 +634,12 @@ public:
public:
void construct() {
const size_t nw = num_words();
const size_t nw = num_words32();
info.resize(computeBytesNeeded(EncodingType::VERILOG));
EmitWriterHelper wh(info.data_ptr());
wh //
.writeTimeIndexAndEncoding(0, EncodingType::VERILOG)
.fill(uint64_t(0), nw)
.fill(uint64_t(-1), nw);
.fill(static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) << 32, nw);
}
void emitValueChange(uint64_t current_time_index, const uint64_t val) {
@@ -616,12 +649,12 @@ public:
}
void emitValueChange(uint64_t current_time_index, const uint32_t *val, EncodingType encoding) {
const unsigned nw32 = (info.bitwidth() + 31) / 32;
const unsigned bpb = bitPerEncodedBit(encoding);
const unsigned nw32 = num_words32();
auto wh = emitValueChangeCommonPart(current_time_index, encoding);
for (unsigned i = 0; i < bpb; ++i) {
switch (encoding) {
case EncodingType::BINARY: {
for (unsigned j = 0; j < nw32 / 2; ++j) {
uint64_t v = val[1]; // high bits
v <<= 32;
@@ -634,13 +667,25 @@ public:
wh.write(v);
val += 1;
}
} break;
case EncodingType::VERILOG: {
for (unsigned j = 0; j < nw32; ++j) {
uint64_t v = val[1]; // high bits
v <<= 32;
v |= val[0]; // low bits
wh.write(v);
val += 2;
}
} break;
[[unlikely]] case EncodingType::VHDL:
FST_FAIL_STRING("VHDL format is unsupported with wide values");
}
}
void emitValueChange(uint64_t current_time_index, const uint64_t *val, EncodingType encoding) {
const unsigned nw_encoded = num_words() * bitPerEncodedBit(encoding);
auto wh = emitValueChangeCommonPart(current_time_index, encoding);
wh.write(val, nw_encoded);
FST_CHECK(encoding == EncodingType::BINARY);
wh.write(val, num_words());
}
void dumpInitialBits(std::vector<uint8_t> &buf) const {
@@ -663,15 +708,16 @@ public:
break;
}
case EncodingType::VERILOG: {
for (unsigned word_index = nw; word_index-- > 0;) {
const uint64_t v0 = rh.peek<uint64_t>(nw * 0 + word_index);
const uint64_t v1 = rh.peek<uint64_t>(nw * 1 + word_index);
for (unsigned word_index = num_words32(); word_index-- > 0;) {
const uint64_t val = rh.peek<uint64_t>(word_index);
const uint32_t aval = static_cast<uint32_t>(val);
const uint32_t bval = static_cast<uint32_t>(val >> 32);
const unsigned num_bit =
(word_index * 64 + 64 > info.bitwidth()) ? (info.bitwidth() % 64) : 64;
(word_index * 32 + 32 > info.bitwidth()) ? (info.bitwidth() % 32) : 32;
for (unsigned bit_index = num_bit; bit_index-- > 0;) {
const bool b0 = ((v0 >> bit_index) & uint64_t(1));
const bool b1 = ((v1 >> bit_index) & uint64_t(1));
const char c = kEncodedBitToCharTable[(b1 << 1) | b0];
const bool a = ((aval >> bit_index) & 1);
const bool b = ((bval >> bit_index) & 1);
const char c = kEncodedBitToCharTable[(b << 1) | a];
buf.push_back(c);
}
}
@@ -717,33 +763,58 @@ public:
FST_DCHECK_GT(tail, rh.ptr);
const auto time_index = rh.read<uint64_t>();
const auto enc = rh.read<EncodingType>();
const auto num_element = bitPerEncodedBit(enc);
const auto num_byte = num_element * nw * sizeof(uint64_t);
const auto num_byte = computeBytesNeededNoHeader(enc);
if (first) {
// Note: [0] is initial value, which is already dumped in dumpInitialBits()
first = false;
} else {
FST_CHECK(enc == EncodingType::BINARY); // TODO
const bool has_non_binary = enc != EncodingType::BINARY;
const uint64_t delta_time_index = time_index - prev_time_index;
prev_time_index = time_index;
h.writeLEB128((delta_time_index << 1) | has_non_binary);
if (bitwidth % 64 != 0) {
const unsigned remaining = bitwidth % 64;
uint64_t hi64 = rh.peek<uint64_t>(nw - 1);
// write from nw-1 to 1
for (unsigned j = nw - 1; j > 0; --j) {
uint64_t lo64 = rh.peek<uint64_t>(j - 1);
h.writeUIntBE((hi64 << (64 - remaining)) | (lo64 >> remaining));
hi64 = lo64;
switch (enc) {
case EncodingType::BINARY: {
h.writeLEB128((delta_time_index << 1));
if (bitwidth % 64 != 0) {
const unsigned remaining = bitwidth % 64;
uint64_t hi64 = rh.peek<uint64_t>(nw - 1);
// write from nw-1 to 1
for (unsigned j = nw - 1; j > 0; --j) {
uint64_t lo64 = rh.peek<uint64_t>(j - 1);
h.writeUIntBE((hi64 << (64 - remaining)) | (lo64 >> remaining));
hi64 = lo64;
}
// write 0
h.writeUIntPartialForValueChange(hi64, remaining);
} else {
// write from nw-1 to 0
for (unsigned j = nw; j-- > 0;) {
h.writeUIntBE(rh.peek<uint64_t>(j));
}
}
// write 0
h.writeUIntPartialForValueChange(hi64, remaining);
} else {
// write from nw-1 to 0
for (unsigned j = nw; j-- > 0;) {
h.writeUIntBE(rh.peek<uint64_t>(j));
} break;
case EncodingType::VERILOG: {
h.writeLEB128((delta_time_index << 1) | 1);
const int fullWords = (bitwidth / 32);
if (int j = bitwidth % 32) {
const uint64_t val = rh.peek<uint64_t>(fullWords);
while (j > 0) {
--j;
const uint64_t v = val >> j;
h.writeUIntBE(kEncodedBitToCharTable[((v >> 31) & 2) | (v & 1)]);
}
}
for (size_t i = fullWords; i > 0;) {
--i;
const uint64_t val = rh.peek<uint64_t>(i);
for (int j = 32; j > 0;) {
--j;
const uint64_t v = val >> j;
h.writeUIntBE(kEncodedBitToCharTable[((v >> 31) & 2) | (v & 1)]);
}
}
} break;
[[unlikely]] case EncodingType::VHDL: {
FST_FAIL_STRING("VHDL format is unsupported with wide values");
} break;
}
}
rh.skip(num_byte);