From 577381b3c90a2b7593ed80cb85be1e34016faf2f Mon Sep 17 00:00:00 2001 From: Catherine Date: Thu, 28 Mar 2024 10:06:18 +0000 Subject: [PATCH] fmt: if enabled, group padding zeroes. Before this commit, the combination of `_` and `0` format characters would produce a result like `000000001010_1010`. After this commit, it would be `0000_0000_1010_1010`. This has a slight quirk where a format like `{:020_b}` results in the output `0_0000_0000_1010_1010`, which is one character longer than requested. Python has the same behavior, and it's not clear what would be strictly speaking correct, so Python behavior is implemented. --- backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 22 ++++++++++++++-------- kernel/fmt.cc | 12 +++++++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index f628051105e..bc26f2b2e03 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -1109,28 +1109,27 @@ struct fmt_part { } } - size_t width = Bits; + size_t val_width = Bits; if (base != 10) { - width = 1; + val_width = 1; for (size_t index = 0; index < Bits; index++) if (val.bit(index)) - width = index + 1; + val_width = index + 1; } if (base == 2) { if (show_base) prefix += "0b"; - for (size_t index = 0; index < width; index++) { + for (size_t index = 0; index < val_width; index++) { if (group && index > 0 && index % 4 == 0) buf += '_'; buf += (val.bit(index) ? '1' : '0'); } - std::reverse(buf.begin(), buf.end()); } else if (base == 8 || base == 16) { if (show_base) prefix += (base == 16) ? (hex_upper ? "0X" : "0x") : "0o"; size_t step = (base == 16) ? 4 : 3; - for (size_t index = 0; index < width; index += step) { + for (size_t index = 0; index < val_width; index += step) { if (group && index > 0 && index % (4 * step) == 0) buf += '_'; uint8_t value = val.bit(index) | (val.bit(index + 1) << 1) | (val.bit(index + 2) << 2); @@ -1138,7 +1137,6 @@ struct fmt_part { value |= val.bit(index + 3) << 3; buf += (hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[value]; } - std::reverse(buf.begin(), buf.end()); } else if (base == 10) { if (show_base) prefix += "0d"; @@ -1158,8 +1156,16 @@ struct fmt_part { xval = quotient; index++; } - std::reverse(buf.begin(), buf.end()); } else assert(false && "Unsupported base for fmt_part"); + if (justify == NUMERIC && group && padding == '0') { + int group_size = base == 10 ? 3 : 4; + while (prefix.size() + buf.size() < width) { + if (buf.size() % (group_size + 1) == group_size) + buf += '_'; + buf += '0'; + } + } + std::reverse(buf.begin(), buf.end()); break; } diff --git a/kernel/fmt.cc b/kernel/fmt.cc index 43d8feddfa4..cbf2d12e9ac 100644 --- a/kernel/fmt.cc +++ b/kernel/fmt.cc @@ -776,7 +776,6 @@ std::string Fmt::render() const else /* if (bit == State::S0) */ buf += '0'; } - std::reverse(buf.begin(), buf.end()); } else if (part.base == 8 || part.base == 16) { if (part.show_base) prefix += (part.base == 16) ? (part.hex_upper ? "0X" : "0x") : "0o"; @@ -807,7 +806,6 @@ std::string Fmt::render() const else buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()]; } - std::reverse(buf.begin(), buf.end()); } else if (part.base == 10) { if (part.show_base) prefix += "0d"; @@ -831,9 +829,17 @@ std::string Fmt::render() const value = RTLIL::const_div(value, 10, false, false, value.size()); index++; } - std::reverse(buf.begin(), buf.end()); } } else log_abort(); + if (part.justify == FmtPart::NUMERIC && part.group && part.padding == '0') { + int group_size = part.base == 10 ? 3 : 4; + while (prefix.size() + buf.size() < part.width) { + if (buf.size() % (group_size + 1) == group_size) + buf += '_'; + buf += '0'; + } + } + std::reverse(buf.begin(), buf.end()); } else if (part.type == FmtPart::STRING) { buf = part.sig.as_const().decode_string(); } else if (part.type == FmtPart::VLOG_TIME) {