Fix nested assignments on the LHS (#4435)

This commit is contained in:
Ryszard Rozak 2023-08-23 12:08:22 +02:00 committed by GitHub
parent 967a8530dd
commit 90079c2974
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 15 deletions

View File

@ -415,25 +415,19 @@ private:
// METHODS
// Find net delay on the LHS of an assignment
AstDelay* getLhsNetDelay(AstNodeAssign* nodep) const {
bool foundWrite = false;
AstDelay* delayp = nullptr;
nodep->lhsp()->foreach([&](const AstNodeVarRef* const refp) {
if (!refp->access().isWriteOrRW()) return;
UASSERT_OBJ(!foundWrite, nodep, "Should only be one variable written to on the LHS");
foundWrite = true;
if (refp->varp()->delayp()) {
delayp = refp->varp()->delayp();
delayp->unlinkFrBack();
}
});
return delayp;
AstDelay* getLhsNetDelayRecurse(const AstNodeExpr* const nodep) const {
if (const AstNodeVarRef* const refp = VN_CAST(nodep, NodeVarRef)) {
if (refp->varp()->delayp()) return refp->varp()->delayp()->unlinkFrBack();
} else if (const AstSel* const selp = VN_CAST(nodep, Sel)) {
return getLhsNetDelayRecurse(selp->fromp());
}
return nullptr;
}
// Transform an assignment with an intra timing control into a timing control with the
// assignment under it
AstNode* factorOutTimingControl(AstNodeAssign* nodep) const {
AstNode* stmtp = nodep;
AstDelay* delayp = getLhsNetDelay(nodep);
AstDelay* delayp = getLhsNetDelayRecurse(nodep->lhsp());
FileLine* const flp = nodep->fileline();
AstNode* const controlp = nodep->timingControlp();
if (controlp) {
@ -955,7 +949,7 @@ private:
replaceWithIntermediate(nodep->rhsp(), m_intraValueNames.get(nodep));
}
void visit(AstAssignW* nodep) override {
AstDelay* const netDelayp = getLhsNetDelay(nodep);
AstDelay* const netDelayp = getLhsNetDelayRecurse(nodep->lhsp());
if (!netDelayp && !nodep->timingControlp()) return;
// This assignment will be converted to an always. In some cases this may generate an
// UNOPTFLAT, e.g.: assign #1 clk = ~clk. We create a temp var for the LHS of this

View File

@ -0,0 +1,25 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2023 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);
top_filename("t/t_net_delay.v");
compile(
timing_loop => 1,
verilator_flags2 => ["--timing"],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,31 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
class uvm_object_wrapper;
function string get_type_name;
return "abcd";
endfunction
endclass
class uvm_default_factory;
int m_type_names[string];
virtual function int register;
uvm_object_wrapper obj;
string name;
m_type_names[(name = obj.get_type_name())] = 1;
return m_type_names[name];
endfunction
endclass
module t;
initial begin
uvm_default_factory u = new;
if (u.register() != 1) $stop;
#1; // Needed only visit assignments in V3Timing
$write("*-* All Finished *-*\n");
$finish;
end
endmodule