Fix table misoptimizing away display (#3488).

This commit is contained in:
Wilson Snyder 2022-07-09 07:55:46 -04:00
parent 3d71716a8a
commit a4fddb3fbe
6 changed files with 96 additions and 2 deletions

View File

@ -14,6 +14,8 @@ Verilator 4.225 devel
**Minor:** **Minor:**
* Fix incorrect bit op tree optimization (#3470). [algrobman] * Fix incorrect bit op tree optimization (#3470). [algrobman]
* Fix table misoptimizing away display (#3488). [Stefan Post]
Verilator 4.224 2022-06-19 Verilator 4.224 2022-06-19
========================== ==========================

View File

@ -100,6 +100,7 @@ private:
bool m_anyAssignDly; ///< True if found a delayed assignment bool m_anyAssignDly; ///< True if found a delayed assignment
bool m_anyAssignComb; ///< True if found a non-delayed assignment bool m_anyAssignComb; ///< True if found a non-delayed assignment
bool m_inDlyAssign; ///< Under delayed assignment bool m_inDlyAssign; ///< Under delayed assignment
bool m_isOutputter; // Creates output
int m_instrCount; ///< Number of nodes int m_instrCount; ///< Number of nodes
int m_dataCount; ///< Bytes of data int m_dataCount; ///< Bytes of data
AstJumpGo* m_jumpp; ///< Jump label we're branching from AstJumpGo* m_jumpp; ///< Jump label we're branching from
@ -205,6 +206,7 @@ public:
AstNode* whyNotNodep() const { return m_whyNotNodep; } AstNode* whyNotNodep() const { return m_whyNotNodep; }
bool isAssignDly() const { return m_anyAssignDly; } bool isAssignDly() const { return m_anyAssignDly; }
bool isOutputter() const { return m_isOutputter; }
int instrCount() const { return m_instrCount; } int instrCount() const { return m_instrCount; }
int dataCount() const { return m_dataCount; } int dataCount() const { return m_dataCount; }
@ -342,15 +344,16 @@ private:
nodep->user2p((void*)valuep); nodep->user2p((void*)valuep);
} }
void checkNodeInfo(AstNode* nodep) { void checkNodeInfo(AstNode* nodep, bool ignorePredict = false) {
if (m_checkOnly) { if (m_checkOnly) {
m_instrCount += nodep->instrCount(); m_instrCount += nodep->instrCount();
m_dataCount += nodep->width(); m_dataCount += nodep->width();
} }
if (!nodep->isPredictOptimizable()) { if (!ignorePredict && !nodep->isPredictOptimizable()) {
// UINFO(9, " !predictopt " << nodep << endl); // UINFO(9, " !predictopt " << nodep << endl);
clearOptimizable(nodep, "Isn't predictable"); clearOptimizable(nodep, "Isn't predictable");
} }
if (nodep->isOutputter()) m_isOutputter = true;
} }
void badNodeType(AstNode* nodep) { void badNodeType(AstNode* nodep) {
@ -756,6 +759,7 @@ private:
virtual void visit(AstNodeAssign* nodep) override { virtual void visit(AstNodeAssign* nodep) override {
if (jumpingOver(nodep)) return; if (jumpingOver(nodep)) return;
if (!optimizable()) return; // Accelerate if (!optimizable()) return; // Accelerate
checkNodeInfo(nodep);
if (VN_IS(nodep, AssignForce)) { if (VN_IS(nodep, AssignForce)) {
clearOptimizable(nodep, "Force"); clearOptimizable(nodep, "Force");
} else if (VN_IS(nodep, AssignDly)) { } else if (VN_IS(nodep, AssignDly)) {
@ -970,6 +974,7 @@ private:
if (jumpingOver(nodep)) return; if (jumpingOver(nodep)) return;
if (!optimizable()) return; // Accelerate if (!optimizable()) return; // Accelerate
UINFO(5, " FUNCREF " << nodep << endl); UINFO(5, " FUNCREF " << nodep << endl);
checkNodeInfo(nodep);
if (!m_params) { if (!m_params) {
badNodeType(nodep); badNodeType(nodep);
return; return;
@ -1053,6 +1058,7 @@ private:
virtual void visit(AstSFormatF* nodep) override { virtual void visit(AstSFormatF* nodep) override {
if (jumpingOver(nodep)) return; if (jumpingOver(nodep)) return;
if (!optimizable()) return; // Accelerate if (!optimizable()) return; // Accelerate
checkNodeInfo(nodep);
iterateChildren(nodep); iterateChildren(nodep);
if (m_params) { if (m_params) {
AstNode* nextArgp = nodep->exprsp(); AstNode* nextArgp = nodep->exprsp();
@ -1106,6 +1112,9 @@ private:
virtual void visit(AstDisplay* nodep) override { virtual void visit(AstDisplay* nodep) override {
if (jumpingOver(nodep)) return; if (jumpingOver(nodep)) return;
if (!optimizable()) return; // Accelerate if (!optimizable()) return; // Accelerate
// We ignore isPredictOptimizable as $display is often in constant
// functions and we want them to work if used with parameters
checkNodeInfo(nodep, /*display:*/ true);
iterateChildren(nodep); iterateChildren(nodep);
if (m_params) { if (m_params) {
AstConst* const textp = fetchConst(nodep->fmtp()); AstConst* const textp = fetchConst(nodep->fmtp());
@ -1155,6 +1164,7 @@ public:
m_anyAssignComb = false; m_anyAssignComb = false;
m_anyAssignDly = false; m_anyAssignDly = false;
m_inDlyAssign = false; m_inDlyAssign = false;
m_isOutputter = false;
m_instrCount = 0; m_instrCount = 0;
m_dataCount = 0; m_dataCount = 0;
m_jumpp = nullptr; m_jumpp = nullptr;

View File

@ -225,6 +225,9 @@ private:
if (!m_outWidthBytes || !m_inWidthBits) { if (!m_outWidthBytes || !m_inWidthBits) {
chkvis.clearOptimizable(nodep, "Table has no outputs"); chkvis.clearOptimizable(nodep, "Table has no outputs");
} }
if (chkvis.isOutputter()) {
chkvis.clearOptimizable(nodep, "Table creates display output");
}
UINFO(4, " Test: Opt=" << (chkvis.optimizable() ? "OK" : "NO") << ", Instrs=" UINFO(4, " Test: Opt=" << (chkvis.optimizable() ? "OK" : "NO") << ", Instrs="
<< chkvis.instrCount() << " Data=" << chkvis.dataCount() << chkvis.instrCount() << " Data=" << chkvis.dataCount()
<< " in width (bits)=" << m_inWidthBits << " out width (bytes)=" << " in width (bits)=" << m_inWidthBits << " out width (bytes)="

View File

@ -0,0 +1,12 @@
Clocked
Clocked
Clocked
Clocked
Clocked
Clocked
Clocked
Clocked
Clocked
Clocked
Clocked
*-* All Finished *-*

View File

@ -0,0 +1,23 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
verilator_flags2 => ["--stats"],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,44 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Outputs
test,
// Inputs
clk
);
input clk;
output reg [5:0] test;
parameter STATE1 = 6'b000001;
parameter STATE2 = 6'b000010;
parameter STATE3 = 6'b000100;
parameter STATE4 = 6'b001000;
parameter STATE5 = 6'b010000;
parameter STATE6 = 6'b100000;
always @(posedge clk) begin
$display("Clocked");
case (test)
STATE1: test <= STATE2;
STATE2: test <= STATE3;
STATE3: test <= STATE4;
STATE4: test <= STATE5;
STATE5: test <= STATE6;
default: test <= STATE1;
endcase
end
int cyc;
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule