Fix forced assignments that override non-continuous assignments (#4183) (#4192)

Only assign forced value on release if it was forced in the first place.
This commit is contained in:
Krzysztof Bieganski 2023-05-12 12:57:12 +02:00 committed by GitHub
parent 0198a3fc52
commit 4835ed6967
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 6 deletions

View File

@ -253,16 +253,33 @@ class ForceConvertVisitor final : public VNVisitor {
resetRdp->rhsp()->foreach([this](AstNodeVarRef* refp) {
if (refp->access() != VAccess::WRITE) return;
AstVarScope* const vscp = refp->varScopep();
AstVarScope* const newVscp
= vscp->varp()->isContinuously() ? vscp : getForceComponents(vscp).m_valVscp;
AstVarRef* const newpRefp = new AstVarRef{refp->fileline(), newVscp, VAccess::READ};
FileLine* const flp = new FileLine{refp->fileline()};
AstVarRef* const newpRefp = new AstVarRef{refp->fileline(), vscp, VAccess::READ};
newpRefp->user2(1); // Don't replace this read ref with the read signal
refp->replaceWith(newpRefp);
if (vscp->varp()->isContinuously()) {
refp->replaceWith(newpRefp);
} else if (isRangedDType(vscp)) {
refp->replaceWith(new AstOr{
flp,
new AstAnd{
flp, new AstVarRef{flp, getForceComponents(vscp).m_enVscp, VAccess::READ},
new AstVarRef{flp, getForceComponents(vscp).m_valVscp, VAccess::READ}},
new AstAnd{
flp,
new AstNot{flp, new AstVarRef{flp, getForceComponents(vscp).m_enVscp,
VAccess::READ}},
newpRefp}});
} else {
refp->replaceWith(new AstCond{
flp, new AstVarRef{flp, getForceComponents(vscp).m_enVscp, VAccess::READ},
new AstVarRef{flp, getForceComponents(vscp).m_valVscp, VAccess::READ},
newpRefp});
}
VL_DO_DANGLING(refp->deleteTree(), refp);
});
resetEnp->addNext(resetRdp);
relinker.relink(resetEnp);
resetRdp->addNext(resetEnp);
relinker.relink(resetRdp);
}
void visit(AstVarScope* nodep) override {

View File

@ -0,0 +1,21 @@
#!/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 Antmicro Ltd. 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(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,51 @@
// 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
// verilator lint_off MULTIDRIVEN
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
logic [31:0] lhs1, lhs2, rhs;
logic cond = 0;
always_comb lhs1 = rhs;
assign lhs2 = rhs;
always @(posedge clk) rhs = '1;
always @(negedge clk) begin
if (cond) begin
force lhs1 = 'hdeadbeef;
force lhs2 = 'hfeedface;
end
else begin
release lhs1;
release lhs2;
end
end
int cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 0) cond <= 1;
if (cyc == 3) cond <= 0;
if (cyc > 1 && cyc < 4) begin
if (lhs1 != 'hdeadbeef) $stop;
if (lhs2 != 'hfeedface) $stop;
end
if (cyc > 4 && cyc < 8) begin
if (lhs1 != '1) $stop;
if (lhs2 != '1) $stop;
end
if (cyc >= 8) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule