aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaire Wolf <clifford@clifford.at>2020-04-20 14:51:40 +0200
committerGitHub <noreply@github.com>2020-04-20 14:51:40 +0200
commitae115fa3aac9acf7534b3f7c08afaa1b86bfc4ad (patch)
treefab88c1359aa800d95871d8dbcee254e620077a4
parent2b1fb8c0a06e6f7b2107c9f623ed9e55b002a7f6 (diff)
parent35990b95ec3b306f5ff0edf84c7d83aada1005d0 (diff)
downloadyosys-ae115fa3aac9acf7534b3f7c08afaa1b86bfc4ad.tar.gz
yosys-ae115fa3aac9acf7534b3f7c08afaa1b86bfc4ad.tar.bz2
yosys-ae115fa3aac9acf7534b3f7c08afaa1b86bfc4ad.zip
Merge pull request #1964 from YosysHQ/claire/sformatf
Extend support for format strings in Verilog front-end
-rw-r--r--frontends/ast/simplify.cc46
1 files changed, 38 insertions, 8 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 372dcf95c..467afdd87 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -64,6 +64,21 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
continue;
}
+ bool got_len = false;
+ bool got_zlen = false;
+ int len_value = 0;
+
+ while ('0' <= cformat && cformat <= '9')
+ {
+ if (!got_len && cformat == '0')
+ got_zlen = true;
+
+ got_len = true;
+ len_value = 10*len_value + (cformat - '0');
+
+ cformat = sformat[++i];
+ }
+
// Simplify the argument
AstNode *node_arg = nullptr;
@@ -74,6 +89,9 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
case 'S':
case 'd':
case 'D':
+ if (got_len)
+ goto unsupported_format;
+ /* fall through */
case 'x':
case 'X':
if (next_arg >= GetSize(children))
@@ -88,9 +106,12 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
case 'm':
case 'M':
+ if (got_len)
+ goto unsupported_format;
break;
default:
+ unsupported_format:
log_file_error(filename, location.first_line, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
break;
}
@@ -104,19 +125,28 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
case 'd':
case 'D':
- {
- char tmp[128];
- snprintf(tmp, sizeof(tmp), "%d", node_arg->bitsAsConst().as_int());
- sout += tmp;
- }
+ sout += stringf("%d", node_arg->bitsAsConst().as_int());
break;
case 'x':
case 'X':
{
- char tmp[128];
- snprintf(tmp, sizeof(tmp), "%x", node_arg->bitsAsConst().as_int());
- sout += tmp;
+ Const val = node_arg->bitsAsConst();
+
+ while (GetSize(val) % 4 != 0)
+ val.bits.push_back(State::S0);
+
+ int len = GetSize(val) / 4;
+ for (int i = len; i < len_value; i++)
+ sout += got_zlen ? '0' : ' ';
+
+ for (int i = len-1; i >= 0; i--) {
+ Const digit = val.extract(4*i, 4);
+ if (digit.is_fully_def())
+ sout += stringf(cformat == 'x' ? "%x" : "%X", digit.as_int());
+ else
+ sout += cformat == 'x' ? "x" : "X";
+ }
}
break;