Skip to content

Commit

Permalink
fmt,cxxrtl: add support for NUMERIC justification.
Browse files Browse the repository at this point in the history
Before this commit, the existing alignments were `LEFT` and `RIGHT`,
which added the `padding` character to the right and left just before
finishing formatting. However, if `padding == '0'` and the alignment is
to the right, then the padding character (digit zero) was added after
the sign, if one is present.

After this commit, the special case for `padding == '0'` is removed,
and the new justification `NUMERIC` adds the padding character like
the justification `RIGHT`, except after the sign, if one is present.
(Space, for the `SPACE_MINUS` sign mode, counts as the sign.)
  • Loading branch information
whitequark committed Mar 28, 2024
1 parent 4096e1e commit 54097ba
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 8 deletions.
5 changes: 3 additions & 2 deletions backends/cxxrtl/runtime/cxxrtl/cxxrtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,7 @@ struct fmt_part {
enum {
RIGHT = 0,
LEFT = 1,
NUMERIC = 2,
} justify; // = RIGHT;
char padding; // = '\0';
size_t width; // = 0;
Expand Down Expand Up @@ -1131,9 +1132,9 @@ struct fmt_part {

std::string str;
assert(width == 0 || padding != '\0');
if (justify == RIGHT && buf.size() < width) {
if (justify != LEFT && buf.size() < width) {
size_t pad_width = width - buf.size();
if (padding == '0' && (buf.front() == '+' || buf.front() == '-')) {
if (justify == NUMERIC && (buf.front() == '+' || buf.front() == '-' || buf.front() == ' ')) {
str += buf.front();
buf.erase(0, 1);
}
Expand Down
23 changes: 17 additions & 6 deletions kernel/fmt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ void Fmt::parse_rtlil(const RTLIL::Cell *cell) {
part.justify = FmtPart::RIGHT;
else if (fmt[i] == '<')
part.justify = FmtPart::LEFT;
else if (fmt[i] == '=')
part.justify = FmtPart::NUMERIC;
else
log_assert(false && "Unexpected justification in format substitution");
if (++i == fmt.size())
Expand Down Expand Up @@ -201,6 +203,8 @@ void Fmt::emit_rtlil(RTLIL::Cell *cell) const {
fmt += '>';
else if (part.justify == FmtPart::LEFT)
fmt += '<';
else if (part.justify == FmtPart::NUMERIC)
fmt += '=';
else log_abort();
log_assert(part.width == 0 || part.padding != '\0');
fmt += part.padding != '\0' ? part.padding : ' ';
Expand Down Expand Up @@ -452,8 +456,14 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1);
}

if (part.padding == '\0')
part.padding = (has_leading_zero && part.justify == FmtPart::RIGHT) ? '0' : ' ';
if (part.padding == '\0') {
if (has_leading_zero && part.justify == FmtPart::RIGHT) {
part.padding = '0';
part.justify = FmtPart::NUMERIC;
} else {
part.padding = ' ';
}
}

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);
Expand Down Expand Up @@ -626,8 +636,9 @@ void Fmt::emit_cxxrtl(std::ostream &os, std::string indent, std::function<void(c
os << escape_cxx_string(part.str) << ", ";
os << "fmt_part::";
switch (part.justify) {
case FmtPart::LEFT: os << "LEFT"; break;
case FmtPart::RIGHT: os << "RIGHT"; break;
case FmtPart::LEFT: os << "LEFT"; break;
case FmtPart::RIGHT: os << "RIGHT"; break;
case FmtPart::NUMERIC: os << "NUMERIC"; break;
}
os << ", ";
os << "(char)" << (int)part.padding << ", ";
Expand Down Expand Up @@ -754,9 +765,9 @@ std::string Fmt::render() const
}

log_assert(part.width == 0 || part.padding != '\0');
if (part.justify == FmtPart::RIGHT && buf.size() < part.width) {
if (part.justify != FmtPart::LEFT && buf.size() < part.width) {
size_t pad_width = part.width - buf.size();
if (part.padding == '0' && (!buf.empty() && (buf.front() == '+' || buf.front() == '-'))) {
if (part.justify == FmtPart::NUMERIC && (!buf.empty() && (buf.front() == '+' || buf.front() == '-' || buf.front() == ' '))) {
str += buf.front();
buf.erase(0, 1);
}
Expand Down
1 change: 1 addition & 0 deletions kernel/fmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct FmtPart {
enum {
RIGHT = 0,
LEFT = 1,
NUMERIC = 2,
} justify = RIGHT;
char padding = '\0';
size_t width = 0;
Expand Down

0 comments on commit 54097ba

Please sign in to comment.