fmt,cxxrtl: fix printing of non-decimal signed numbers.

Also fix interaction of `NUMERIC` justification with `show_base`.
This commit is contained in:
Catherine 2024-03-28 09:45:10 +00:00 committed by Marcelina Kościelnicka
parent 00c5b60dfd
commit ddf7b46955
2 changed files with 100 additions and 68 deletions

View File

@ -1058,6 +1058,7 @@ struct fmt_part {
// We might want to replace some of these bit() calls with direct // We might want to replace some of these bit() calls with direct
// chunk access if it turns out to be slow enough to matter. // chunk access if it turns out to be slow enough to matter.
std::string buf; std::string buf;
std::string prefix;
switch (type) { switch (type) {
case LITERAL: case LITERAL:
return str; return str;
@ -1096,24 +1097,38 @@ struct fmt_part {
} }
case INTEGER: { case INTEGER: {
bool negative = signed_ && val.is_neg();
if (negative) {
prefix = "-";
val = val.neg();
} else {
switch (sign) {
case MINUS: break;
case PLUS_MINUS: prefix = "+"; break;
case SPACE_MINUS: prefix = " "; break;
}
}
size_t width = Bits; size_t width = Bits;
if (base != 10) { if (base != 10) {
width = 0; width = 1;
for (size_t index = 0; index < Bits; index++) for (size_t index = 0; index < Bits; index++)
if (val.bit(index)) if (val.bit(index))
width = index + 1; width = index + 1;
} }
if (base == 2) { if (base == 2) {
if (show_base)
prefix += "0b";
for (size_t index = 0; index < width; index++) { for (size_t index = 0; index < width; index++) {
if (group && index > 0 && index % 4 == 0) if (group && index > 0 && index % 4 == 0)
buf += '_'; buf += '_';
buf += (val.bit(index) ? '1' : '0'); buf += (val.bit(index) ? '1' : '0');
} }
if (show_base)
buf += "b0";
std::reverse(buf.begin(), buf.end()); std::reverse(buf.begin(), buf.end());
} else if (base == 8 || base == 16) { } else if (base == 8 || base == 16) {
if (show_base)
prefix += (base == 16) ? (hex_upper ? "0X" : "0x") : "0o";
size_t step = (base == 16) ? 4 : 3; size_t step = (base == 16) ? 4 : 3;
for (size_t index = 0; index < width; index += step) { for (size_t index = 0; index < width; index += step) {
if (group && index > 0 && index % (4 * step) == 0) if (group && index > 0 && index % (4 * step) == 0)
@ -1123,13 +1138,10 @@ struct fmt_part {
value |= val.bit(index + 3) << 3; value |= val.bit(index + 3) << 3;
buf += (hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[value]; buf += (hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[value];
} }
if (show_base)
buf += (base == 16) ? (hex_upper ? "X0" : "x0") : "o0";
std::reverse(buf.begin(), buf.end()); std::reverse(buf.begin(), buf.end());
} else if (base == 10) { } else if (base == 10) {
bool negative = signed_ && val.is_neg(); if (show_base)
if (negative) prefix += "0d";
val = val.neg();
if (val.is_zero()) if (val.is_zero())
buf += '0'; buf += '0';
value<(Bits > 4 ? Bits : 4)> xval = val.template zext<(Bits > 4 ? Bits : 4)>(); value<(Bits > 4 ? Bits : 4)> xval = val.template zext<(Bits > 4 ? Bits : 4)>();
@ -1146,13 +1158,6 @@ struct fmt_part {
xval = quotient; xval = quotient;
index++; index++;
} }
if (show_base)
buf += "d0";
switch (sign) {
case MINUS: buf += negative ? "-" : ""; break;
case PLUS_MINUS: buf += negative ? "-" : "+"; break;
case SPACE_MINUS: buf += negative ? "-" : " "; break;
}
std::reverse(buf.begin(), buf.end()); std::reverse(buf.begin(), buf.end());
} else assert(false && "Unsupported base for fmt_part"); } else assert(false && "Unsupported base for fmt_part");
break; break;
@ -1170,17 +1175,29 @@ struct fmt_part {
std::string str; std::string str;
assert(width == 0 || padding != '\0'); assert(width == 0 || padding != '\0');
if (justify != LEFT && buf.size() < width) { if (prefix.size() + buf.size() < width) {
size_t pad_width = width - buf.size(); size_t pad_width = width - prefix.size() - buf.size();
if (justify == NUMERIC && (buf.front() == '+' || buf.front() == '-' || buf.front() == ' ')) { switch (justify) {
str += buf.front(); case LEFT:
buf.erase(0, 1); str += prefix;
} str += buf;
str += std::string(pad_width, padding); str += std::string(pad_width, padding);
break;
case RIGHT:
str += std::string(pad_width, padding);
str += prefix;
str += buf;
break;
case NUMERIC:
str += prefix;
str += std::string(pad_width, padding);
str += buf;
break;
}
} else {
str += prefix;
str += buf;
} }
str += buf;
if (justify == LEFT && buf.size() < width)
str += std::string(width - buf.size(), padding);
return str; return str;
} }
}; };

View File

@ -491,6 +491,8 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
if (part.type == FmtPart::INTEGER && part.base != 10 && part.sign != FmtPart::MINUS) if (part.type == FmtPart::INTEGER && part.base != 10 && part.sign != FmtPart::MINUS)
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1);
if (part.base != 10)
part.signed_ = false;
if (part.type == FmtPart::INTEGER && !has_leading_zero) if (part.type == FmtPart::INTEGER && !has_leading_zero)
apply_verilog_automatic_sizing_and_add(part); apply_verilog_automatic_sizing_and_add(part);
else else
@ -731,11 +733,34 @@ std::string Fmt::render() const
case FmtPart::STRING: case FmtPart::STRING:
case FmtPart::VLOG_TIME: { case FmtPart::VLOG_TIME: {
std::string buf; std::string buf;
std::string prefix;
if (part.type == FmtPart::INTEGER) { if (part.type == FmtPart::INTEGER) {
RTLIL::Const value = part.sig.as_const(); RTLIL::Const value = part.sig.as_const();
bool has_x = false, all_x = true, has_z = false, all_z = true;
for (State bit : value) {
if (bit == State::Sx)
has_x = true;
else
all_x = false;
if (bit == State::Sz)
has_z = true;
else
all_z = false;
}
if (!has_z && !has_x && part.signed_ && value[value.size() - 1]) {
prefix = "-";
value = RTLIL::const_neg(value, {}, part.signed_, {}, value.size() + 1);
} else {
switch (part.sign) {
case FmtPart::MINUS: break;
case FmtPart::PLUS_MINUS: prefix = "+"; break;
case FmtPart::SPACE_MINUS: prefix = " "; break;
}
}
if (part.base != 10) { if (part.base != 10) {
size_t minimum_size = 0; size_t minimum_size = 1;
for (size_t index = 0; index < (size_t)value.size(); index++) for (size_t index = 0; index < (size_t)value.size(); index++)
if (value[index] != State::S0) if (value[index] != State::S0)
minimum_size = index + 1; minimum_size = index + 1;
@ -743,6 +768,8 @@ std::string Fmt::render() const
} }
if (part.base == 2) { if (part.base == 2) {
if (part.show_base)
prefix += "0b";
for (size_t index = 0; index < (size_t)value.size(); index++) { for (size_t index = 0; index < (size_t)value.size(); index++) {
if (part.group && index > 0 && index % 4 == 0) if (part.group && index > 0 && index % 4 == 0)
buf += '_'; buf += '_';
@ -756,10 +783,10 @@ std::string Fmt::render() const
else /* if (bit == State::S0) */ else /* if (bit == State::S0) */
buf += '0'; buf += '0';
} }
if (part.show_base)
buf += "b0";
std::reverse(buf.begin(), buf.end()); std::reverse(buf.begin(), buf.end());
} else if (part.base == 8 || part.base == 16) { } else if (part.base == 8 || part.base == 16) {
if (part.show_base)
prefix += (part.base == 16) ? (part.hex_upper ? "0X" : "0x") : "0o";
size_t step = (part.base == 16) ? 4 : 3; size_t step = (part.base == 16) ? 4 : 3;
for (size_t index = 0; index < (size_t)value.size(); index += step) { for (size_t index = 0; index < (size_t)value.size(); index += step) {
if (part.group && index > 0 && index % (4 * step) == 0) if (part.group && index > 0 && index % (4 * step) == 0)
@ -787,21 +814,10 @@ std::string Fmt::render() const
else else
buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()]; buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()];
} }
if (part.show_base)
buf += (part.base == 16) ? (part.hex_upper ? "X0" : "x0") : "o0";
std::reverse(buf.begin(), buf.end()); std::reverse(buf.begin(), buf.end());
} else if (part.base == 10) { } else if (part.base == 10) {
bool has_x = false, all_x = true, has_z = false, all_z = true; if (part.show_base)
for (State bit : value) { prefix += "0d";
if (bit == State::Sx)
has_x = true;
else
all_x = false;
if (bit == State::Sz)
has_z = true;
else
all_z = false;
}
if (all_x) if (all_x)
buf += 'x'; buf += 'x';
else if (all_z) else if (all_z)
@ -811,30 +827,17 @@ std::string Fmt::render() const
else if (has_z) else if (has_z)
buf += 'Z'; buf += 'Z';
else { else {
bool negative = part.signed_ && value[value.size() - 1]; log_assert(value.is_fully_def());
RTLIL::Const absvalue; if (value.is_fully_zero())
if (negative)
absvalue = RTLIL::const_neg(value, {}, part.signed_, {}, value.size() + 1);
else
absvalue = value;
log_assert(absvalue.is_fully_def());
if (absvalue.is_fully_zero())
buf += '0'; buf += '0';
size_t index = 0; size_t index = 0;
while (!absvalue.is_fully_zero()) { while (!value.is_fully_zero()) {
if (part.group && index > 0 && index % 3 == 0) if (part.group && index > 0 && index % 3 == 0)
buf += '_'; buf += '_';
buf += '0' + RTLIL::const_mod(absvalue, 10, false, false, 4).as_int(); buf += '0' + RTLIL::const_mod(value, 10, false, false, 4).as_int();
absvalue = RTLIL::const_div(absvalue, 10, false, false, absvalue.size()); value = RTLIL::const_div(value, 10, false, false, value.size());
index++; index++;
} }
if (part.show_base)
buf += "d0";
switch (part.sign) {
case FmtPart::MINUS: buf += negative ? "-" : ""; break;
case FmtPart::PLUS_MINUS: buf += negative ? "-" : "+"; break;
case FmtPart::SPACE_MINUS: buf += negative ? "-" : " "; break;
}
std::reverse(buf.begin(), buf.end()); std::reverse(buf.begin(), buf.end());
} }
} else log_abort(); } else log_abort();
@ -846,17 +849,29 @@ std::string Fmt::render() const
} }
log_assert(part.width == 0 || part.padding != '\0'); log_assert(part.width == 0 || part.padding != '\0');
if (part.justify != FmtPart::LEFT && buf.size() < part.width) { if (prefix.size() + buf.size() < part.width) {
size_t pad_width = part.width - buf.size(); size_t pad_width = part.width - prefix.size() - buf.size();
if (part.justify == FmtPart::NUMERIC && (!buf.empty() && (buf.front() == '+' || buf.front() == '-' || buf.front() == ' '))) { switch (part.justify) {
str += buf.front(); case FmtPart::LEFT:
buf.erase(0, 1); str += prefix;
str += buf;
str += std::string(pad_width, part.padding);
break;
case FmtPart::RIGHT:
str += std::string(pad_width, part.padding);
str += prefix;
str += buf;
break;
case FmtPart::NUMERIC:
str += prefix;
str += std::string(pad_width, part.padding);
str += buf;
break;
} }
str += std::string(pad_width, part.padding); } else {
str += prefix;
str += buf;
} }
str += buf;
if (part.justify == FmtPart::LEFT && buf.size() < part.width)
str += std::string(part.width - buf.size(), part.padding);
break; break;
} }
} }