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 VPI write errors (#5712). [Andrew Nolte]
|
||||
* 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 VPI iteration over hierarchy (#5314) (#5731). [Natan Kreimer]
|
||||
* Fix constrained random for > 64-bit associative arrays (#5670) (#5682). [Yilou Wang]
|
||||
|
|
|
@ -2266,6 +2266,19 @@ class ConstVisitor final : public VNVisitor {
|
|||
}
|
||||
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
|
||||
bool operandBoolShift(const AstNode* nodep) {
|
||||
|
@ -3158,8 +3171,9 @@ class ConstVisitor final : public VNVisitor {
|
|||
nodep->condp(new AstLogAnd{lowerIfp->fileline(), condp, lowerCondp});
|
||||
lowerIfp->replaceWith(lowerThensp);
|
||||
VL_DO_DANGLING(pushDeletep(lowerIfp), lowerIfp);
|
||||
} else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
} else {
|
||||
// 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)
|
||||
// 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 (AstJumpBlock* const aboveBlockp = VN_CAST(nodep->abovep(), JumpBlock)) {
|
||||
if (aboveBlockp == nodep->labelp()->blockp()) {
|
||||
if (aboveBlockp->endStmtsp() == nodep->labelp()) {
|
||||
UINFO(4, "JUMPGO => last remove " << nodep << endl);
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
return;
|
||||
}
|
||||
if (AstNodeIf* const aboveIfp = VN_CAST(nodep->abovep(), NodeIf)) {
|
||||
if (!aboveIfp->nextp()) {
|
||||
if (replaceJumpGoNext(nodep, aboveIfp->abovep())) 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