diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 19e62668b..ee1be3781 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -48,22 +48,27 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_ for (size_t index = first_arg_at; index < children.size(); index++) { AstNode *node_arg = children[index]; while (node_arg->simplify(true, false, stage, -1, false, false)) { } - if (node_arg->type != AST_CONSTANT) - input_error("Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); VerilogFmtArg arg = {}; arg.filename = filename; arg.first_line = location.first_line; - if (node_arg->is_string) { + if (node_arg->type == AST_CONSTANT && node_arg->is_string) { arg.type = VerilogFmtArg::STRING; arg.str = node_arg->bitsAsConst().decode_string(); // and in case this will be used as an argument... arg.sig = node_arg->bitsAsConst(); arg.signed_ = false; - } else { + } else if (node_arg->type == AST_IDENTIFIER && node_arg->str == "$time") { + arg.type = VerilogFmtArg::TIME; + } else if (node_arg->type == AST_IDENTIFIER && node_arg->str == "$realtime") { + arg.type = VerilogFmtArg::TIME; + arg.realtime = true; + } else if (node_arg->type == AST_CONSTANT) { arg.type = VerilogFmtArg::INTEGER; arg.sig = node_arg->bitsAsConst(); arg.signed_ = node_arg->is_signed; + } else { + log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); } args.push_back(arg); } diff --git a/kernel/fmt.cc b/kernel/fmt.cc index 9d9e95ac3..0fac64175 100644 --- a/kernel/fmt.cc +++ b/kernel/fmt.cc @@ -606,6 +606,7 @@ std::string Fmt::render() const break; case FmtPart::INTEGER: + case FmtPart::TIME: case FmtPart::CHARACTER: { std::string buf; if (part.type == FmtPart::INTEGER) { @@ -689,6 +690,9 @@ std::string Fmt::render() const } else log_abort(); } else if (part.type == FmtPart::CHARACTER) { buf = part.sig.as_const().decode_string(); + } else if (part.type == FmtPart::TIME) { + // We only render() during initial, so time is always zero. + buf = "0"; } log_assert(part.width == 0 || part.padding != '\0'); @@ -705,12 +709,6 @@ std::string Fmt::render() const str += std::string(part.width - buf.size(), part.padding); break; } - - case FmtPart::TIME: { - // We only render() during initial, so time is always zero. - str += "0"; - break; - } } } diff --git a/tests/fmt/initial_display.v b/tests/fmt/initial_display.v index 26a39d0ec..d3ef9ed76 100644 --- a/tests/fmt/initial_display.v +++ b/tests/fmt/initial_display.v @@ -193,6 +193,16 @@ module m; initial $display(":%020b:", 16'shaaaa); initial $display(":%-020b:", 16'shaaaa); + initial $display("==> time %%t"); + initial $display(":%t:", $time); + initial $display(":%-t:", $time); + initial $display(":%0t:", $time); + initial $display(":%-0t:", $time); + initial $display(":%10t:", $time); + initial $display(":%-10t:", $time); + initial $display(":%015t:", $time); + initial $display(":%-015t:", $time); + initial $display("===> %%s"); initial $display(":%10s:", "foo"); initial $display(":%010s:", "foo");