Optimize labels as final `if` block statements (#5744).
This commit is contained in:
parent
694f2ff7c7
commit
05c7a3b90b
1
Changes
1
Changes
|
|
@ -25,6 +25,7 @@ Verilator 5.033 devel
|
||||||
* Improve hierarchical DPI wrapper scheduling performance (#2583) (#5734). [Bartłomiej Chmiel, Antmicro Ltd.]
|
* Improve hierarchical DPI wrapper scheduling performance (#2583) (#5734). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
* Improve VPI write errors (#5712). [Andrew Nolte]
|
* Improve VPI write errors (#5712). [Andrew Nolte]
|
||||||
* Improve `resetall support (#5728) (#5730). [Ethan Sifferman]
|
* Improve `resetall support (#5728) (#5730). [Ethan Sifferman]
|
||||||
|
* Optimize labels as final `if` block statements (#5744).
|
||||||
* Fix error message when call task as a function (#3089). [Matthew Ballance]
|
* Fix error message when call task as a function (#3089). [Matthew Ballance]
|
||||||
* Fix VPI iteration over hierarchy (#5314) (#5731). [Natan Kreimer]
|
* Fix VPI iteration over hierarchy (#5314) (#5731). [Natan Kreimer]
|
||||||
* Fix constrained random for > 64-bit associative arrays (#5670) (#5682). [Yilou Wang]
|
* Fix constrained random for > 64-bit associative arrays (#5670) (#5682). [Yilou Wang]
|
||||||
|
|
|
||||||
|
|
@ -2266,6 +2266,19 @@ class ConstVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool replaceJumpGoNext(AstJumpGo* nodep, AstNode* abovep) {
|
||||||
|
// If JumpGo has an upper JumpBlock that is to same label, then
|
||||||
|
// code will by normal sequential operation do the JUMPGO and it
|
||||||
|
// can be removed.
|
||||||
|
if (nodep->nextp()) return false; // Label jumps other statements
|
||||||
|
AstJumpBlock* const aboveBlockp = VN_CAST(abovep, JumpBlock);
|
||||||
|
if (!aboveBlockp) return false;
|
||||||
|
if (aboveBlockp != nodep->labelp()->blockp()) return false;
|
||||||
|
if (aboveBlockp->endStmtsp() != nodep->labelp()) return false;
|
||||||
|
UINFO(4, "JUMPGO => last remove " << nodep << endl);
|
||||||
|
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Boolean replacements
|
// Boolean replacements
|
||||||
bool operandBoolShift(const AstNode* nodep) {
|
bool operandBoolShift(const AstNode* nodep) {
|
||||||
|
|
@ -3158,8 +3171,9 @@ class ConstVisitor final : public VNVisitor {
|
||||||
nodep->condp(new AstLogAnd{lowerIfp->fileline(), condp, lowerCondp});
|
nodep->condp(new AstLogAnd{lowerIfp->fileline(), condp, lowerCondp});
|
||||||
lowerIfp->replaceWith(lowerThensp);
|
lowerIfp->replaceWith(lowerThensp);
|
||||||
VL_DO_DANGLING(pushDeletep(lowerIfp), lowerIfp);
|
VL_DO_DANGLING(pushDeletep(lowerIfp), lowerIfp);
|
||||||
} else if (operandBoolShift(nodep->condp())) {
|
} else {
|
||||||
replaceBoolShift(nodep->condp());
|
// Optimizations that don't reform the IF itself
|
||||||
|
if (operandBoolShift(nodep->condp())) replaceBoolShift(nodep->condp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3390,14 +3404,14 @@ class ConstVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
// If last statement in a jump label we have JumpLabel(...., JumpGo)
|
// If last statement in a jump label we have JumpLabel(...., JumpGo)
|
||||||
// Often caused by "return" in a Verilog function. The Go is pointless, remove.
|
// Often caused by "return" in a Verilog function. The Go is pointless, remove.
|
||||||
|
if (replaceJumpGoNext(nodep, nodep->abovep())) return;
|
||||||
|
// Also optimize If with a then or else's final statement being this JumpGo
|
||||||
|
// We only do single ifs... Ideally we'd look at control flow and delete any
|
||||||
|
// Jumps where any following control flow point is the label
|
||||||
if (!nodep->nextp()) {
|
if (!nodep->nextp()) {
|
||||||
if (AstJumpBlock* const aboveBlockp = VN_CAST(nodep->abovep(), JumpBlock)) {
|
if (AstNodeIf* const aboveIfp = VN_CAST(nodep->abovep(), NodeIf)) {
|
||||||
if (aboveBlockp == nodep->labelp()->blockp()) {
|
if (!aboveIfp->nextp()) {
|
||||||
if (aboveBlockp->endStmtsp() == nodep->labelp()) {
|
if (replaceJumpGoNext(nodep, aboveIfp->abovep())) return;
|
||||||
UINFO(4, "JUMPGO => last remove " << nodep << endl);
|
|
||||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2025 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=['--stats'])
|
||||||
|
|
||||||
|
test.file_grep(test.stats, r'Node count, JUMPGO + 3 *$')
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class uvm_object;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class uvm_callback;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class uvm_callbacks #(type T=uvm_object, type CB=uvm_callback);
|
||||||
|
bit m_registered = 1;
|
||||||
|
virtual function bit m_is_registered(uvm_object obj, uvm_callback cb);
|
||||||
|
if (m_is_for_me(cb) && m_am_i_a(obj)) begin
|
||||||
|
return m_registered;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
virtual function bit m_is_for_me(uvm_callback cb);
|
||||||
|
CB this_cb;
|
||||||
|
// verilator lint_off WIDTHTRUNC
|
||||||
|
return ($cast(this_cb, cb));
|
||||||
|
// verilator lint_on WIDTHTRUNC
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
virtual function bit m_am_i_a(uvm_object obj);
|
||||||
|
T this_t;
|
||||||
|
// verilator lint_off WIDTHTRUNC
|
||||||
|
return ($cast(this_t, obj));
|
||||||
|
// verilator lint_on WIDTHTRUNC
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class my_object extends uvm_object;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class my_callback extends uvm_callback;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class other_object extends uvm_object;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
my_object obj;
|
||||||
|
other_object oobj;
|
||||||
|
my_callback cb;
|
||||||
|
uvm_callbacks#(my_object, my_callback) ucs;
|
||||||
|
bit i;
|
||||||
|
|
||||||
|
obj = new;
|
||||||
|
oobj = new;
|
||||||
|
cb = new;
|
||||||
|
ucs = new;
|
||||||
|
|
||||||
|
i = ucs.m_is_registered(obj, cb);
|
||||||
|
if (i !== 1) $stop;
|
||||||
|
i = ucs.m_is_registered(oobj, cb);
|
||||||
|
if (i !== 0) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue