fmt: Allow non-constant $display calls in initial blocks

These are useful for formal verification with SBY where they can be used
to display solver chosen `rand const reg` signals and signals derived
from those.

The previous error message for non-constant initial $display statements
is downgraded to a log message. Constant initial $display statements
will be shown both during elaboration and become part of the RTLIL so
that the `sim` output is complete.
This commit is contained in:
Jannis Harder 2023-09-22 17:56:34 +02:00 committed by Dag Lem
parent 57b4e16acd
commit 510d137996
2 changed files with 9 additions and 3 deletions

View File

@ -287,7 +287,7 @@ namespace AST
bool is_simple_const_expr();
// helper for parsing format strings
Fmt processFormat(int stage, bool sformat_like, int default_base = 10, size_t first_arg_at = 0);
Fmt processFormat(int stage, bool sformat_like, int default_base = 10, size_t first_arg_at = 0, bool may_fail = false);
bool is_recursive_function() const;
std::pair<AstNode*, AstNode*> get_tern_choice();

View File

@ -145,7 +145,7 @@ void AstNode::fixup_hierarchy_flags(bool force_descend)
// Process a format string and arguments for $display, $write, $sprintf, etc
Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_t first_arg_at) {
Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_t first_arg_at, bool may_fail) {
std::vector<VerilogFmtArg> args;
for (size_t index = first_arg_at; index < children.size(); index++) {
AstNode *node_arg = children[index];
@ -169,6 +169,9 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_
arg.type = VerilogFmtArg::INTEGER;
arg.sig = node_arg->bitsAsConst();
arg.signed_ = node_arg->is_signed;
} else if (may_fail) {
log_file_info(filename, location.first_line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
return Fmt();
} 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);
}
@ -1065,10 +1068,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
default_base = 16;
// when $display()/$write() functions are used in an initial block, print them during synthesis
Fmt fmt = processFormat(stage, /*sformat_like=*/false, default_base);
Fmt fmt = processFormat(stage, /*sformat_like=*/false, default_base, /*first_arg_at=*/0, /*may_fail=*/true);
if (str.substr(0, 8) == "$display")
fmt.append_string("\n");
log("%s", fmt.render().c_str());
for (auto node : children)
while (node->simplify(true, stage, -1, false)) {}
return false;
} else {
// when $display()/$write() functions are used in an always block, simplify the expressions and
// convert them to a special cell later in genrtlil