From 510d137996c3beb7588aa86687315908928a9778 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Fri, 22 Sep 2023 17:56:34 +0200 Subject: [PATCH] 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. --- frontends/ast/ast.h | 2 +- frontends/ast/simplify.cc | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 97903d0a0..31679e4df 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -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 get_tern_choice(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 51ed95621..d45b53db5 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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 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