Fixes# 7901 Signed-off-by: Artur Bieniek <abieniek@antmicro.com>
This commit is contained in:
parent
b211af9d24
commit
feb2fe0d94
|
|
@ -679,8 +679,9 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) {
|
||||||
// the port variable. The constant can still be inlined, in which case
|
// the port variable. The constant can still be inlined, in which case
|
||||||
// this is needed for tracing the inlined port variable.
|
// this is needed for tracing the inlined port variable.
|
||||||
if (AstConst* const pinp = VN_CAST(pinExprp, Const)) {
|
if (AstConst* const pinp = VN_CAST(pinExprp, Const)) {
|
||||||
AstAssignW* const ap
|
AstVarRef* const lhsp = portRef(VAccess::WRITE);
|
||||||
= new AstAssignW{flp, portRef(VAccess::WRITE), pinp->cloneTree(false)};
|
lhsp->varp()->isContinuously(true);
|
||||||
|
AstAssignW* const ap = new AstAssignW{flp, lhsp, pinp->cloneTree(false)};
|
||||||
modp->addStmtsp(new AstAlways{ap});
|
modp->addStmtsp(new AstAlways{ap});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -732,12 +733,14 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) {
|
||||||
// Otherwise create the continuous assignment between the port var and the pin expression
|
// Otherwise create the continuous assignment between the port var and the pin expression
|
||||||
UINFO(6, "Not inlining port variable: " << nodep);
|
UINFO(6, "Not inlining port variable: " << nodep);
|
||||||
if (nodep->direction() == VDirection::INPUT) {
|
if (nodep->direction() == VDirection::INPUT) {
|
||||||
AstAssignW* const ap
|
AstVarRef* const lhsp = portRef(VAccess::WRITE);
|
||||||
= new AstAssignW{flp, portRef(VAccess::WRITE), pinRefAsExpr(VAccess::READ)};
|
lhsp->varp()->isContinuously(true);
|
||||||
|
AstAssignW* const ap = new AstAssignW{flp, lhsp, pinRefAsExpr(VAccess::READ)};
|
||||||
modp->addStmtsp(new AstAlways{ap});
|
modp->addStmtsp(new AstAlways{ap});
|
||||||
} else if (nodep->direction() == VDirection::OUTPUT) {
|
} else if (nodep->direction() == VDirection::OUTPUT) {
|
||||||
AstAssignW* const ap
|
AstNodeVarRef* const lhsp = VN_AS(pinRefAsExpr(VAccess::WRITE), NodeVarRef);
|
||||||
= new AstAssignW{flp, pinRefAsExpr(VAccess::WRITE), portRef(VAccess::READ)};
|
lhsp->varp()->isContinuously(true);
|
||||||
|
AstAssignW* const ap = new AstAssignW{flp, lhsp, portRef(VAccess::READ)};
|
||||||
modp->addStmtsp(new AstAlways{ap});
|
modp->addStmtsp(new AstAlways{ap});
|
||||||
} else {
|
} else {
|
||||||
pinExprp->v3fatalSrc("V3Tristate left INOUT port");
|
pinExprp->v3fatalSrc("V3Tristate left INOUT port");
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,12 @@
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
|
static void markContinuousLhs(AstNode* const nodep) {
|
||||||
|
nodep->foreach([](AstNodeVarRef* refp) {
|
||||||
|
if (refp->access().isWriteOrRW()) refp->varp()->isContinuously(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Inst state, as a visitor of each AstNode
|
// Inst state, as a visitor of each AstNode
|
||||||
|
|
||||||
|
|
@ -73,16 +79,17 @@ class InstVisitor final : public VNVisitor {
|
||||||
} else if (nodep->modVarp()->isWritable()) {
|
} else if (nodep->modVarp()->isWritable()) {
|
||||||
AstNodeExpr* const rhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
AstNodeExpr* const rhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
||||||
m_cellp->name(), VAccess::READ};
|
m_cellp->name(), VAccess::READ};
|
||||||
|
markContinuousLhs(exprp);
|
||||||
AstAssignW* const assp = new AstAssignW{exprp->fileline(), exprp, rhsp};
|
AstAssignW* const assp = new AstAssignW{exprp->fileline(), exprp, rhsp};
|
||||||
m_cellp->addNextHere(new AstAlways{assp});
|
m_cellp->addNextHere(new AstAlways{assp});
|
||||||
} else if (nodep->modVarp()->isNonOutput()) {
|
} else if (nodep->modVarp()->isNonOutput()) {
|
||||||
// Don't bother moving constants now,
|
// Don't bother moving constants now,
|
||||||
// we'll be pushing the const down to the cell soon enough.
|
// we'll be pushing the const down to the cell soon enough.
|
||||||
AstAssignW* const assp
|
AstVarXRef* const lhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
||||||
= new AstAssignW{exprp->fileline(),
|
m_cellp->name(), VAccess::WRITE};
|
||||||
new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
|
||||||
m_cellp->name(), VAccess::WRITE},
|
markContinuousLhs(lhsp);
|
||||||
exprp};
|
AstAssignW* const assp = new AstAssignW{exprp->fileline(), lhsp, exprp};
|
||||||
m_cellp->addNextHere(new AstAlways{assp});
|
m_cellp->addNextHere(new AstAlways{assp});
|
||||||
UINFOTREE(9, assp, "", "_new");
|
UINFOTREE(9, assp, "", "_new");
|
||||||
} else if (nodep->modVarp()->isIfaceRef()
|
} else if (nodep->modVarp()->isIfaceRef()
|
||||||
|
|
@ -903,9 +910,11 @@ public:
|
||||||
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
|
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
|
||||||
pinp->exprp(new AstVarRef{newvarp->fileline(), newvarp, VAccess::WRITE});
|
pinp->exprp(new AstVarRef{newvarp->fileline(), newvarp, VAccess::WRITE});
|
||||||
AstNodeExpr* const rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
|
AstNodeExpr* const rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
|
||||||
|
markContinuousLhs(pinexprp);
|
||||||
assignp = new AstAssignW{pinp->fileline(), pinexprp, rhsSelp};
|
assignp = new AstAssignW{pinp->fileline(), pinexprp, rhsSelp};
|
||||||
} else {
|
} else {
|
||||||
// V3 width should have range/extended to make the widths correct
|
// V3 width should have range/extended to make the widths correct
|
||||||
|
newvarp->isContinuously(true);
|
||||||
assignp = new AstAssignW{pinp->fileline(),
|
assignp = new AstAssignW{pinp->fileline(),
|
||||||
new AstVarRef{pinp->fileline(), newvarp, VAccess::WRITE},
|
new AstVarRef{pinp->fileline(), newvarp, VAccess::WRITE},
|
||||||
pinexprp};
|
pinexprp};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--binary --flatten"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain
|
||||||
|
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
// verilog_format: off
|
||||||
|
`define stop $stop
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||||
|
// verilog_format: on
|
||||||
|
|
||||||
|
module t;
|
||||||
|
logic [31:0] b = 0;
|
||||||
|
logic [31:0] d = 32'h1111_2222;
|
||||||
|
wire [31:0] e;
|
||||||
|
wire [7:0] f;
|
||||||
|
wire [31:0] g;
|
||||||
|
logic [4:0] idx = 0;
|
||||||
|
sub s(b);
|
||||||
|
sub8 s_sel(d[7:0]);
|
||||||
|
sub8 s_const(8'h7c);
|
||||||
|
subout s_out(e[idx+:8]);
|
||||||
|
subout s_out_simple(f);
|
||||||
|
subout s_out_slice(g[15:8]);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
#1;
|
||||||
|
|
||||||
|
force s.c = 2;
|
||||||
|
`checkh(s.c, 2);
|
||||||
|
release s.c;
|
||||||
|
`checkh(s.c, 0);
|
||||||
|
|
||||||
|
`checkh(s_sel.c, 8'h22);
|
||||||
|
force s_sel.c = 8'h33;
|
||||||
|
`checkh(s_sel.c, 8'h33);
|
||||||
|
release s_sel.c;
|
||||||
|
`checkh(s_sel.c, 8'h22);
|
||||||
|
|
||||||
|
`checkh(s_const.c, 8'h7c);
|
||||||
|
force s_const.c = 8'ha5;
|
||||||
|
`checkh(s_const.c, 8'ha5);
|
||||||
|
release s_const.c;
|
||||||
|
`checkh(s_const.c, 8'h7c);
|
||||||
|
|
||||||
|
`checkh(s_out_simple.c, 8'h5a);
|
||||||
|
force s_out_simple.c = 8'hc3;
|
||||||
|
`checkh(s_out_simple.c, 8'hc3);
|
||||||
|
release s_out_simple.c;
|
||||||
|
`checkh(s_out_simple.c, 8'h5a);
|
||||||
|
|
||||||
|
`checkh(f, 8'h5a);
|
||||||
|
force f = 8'ha5;
|
||||||
|
`checkh(f, 8'ha5);
|
||||||
|
release f;
|
||||||
|
`checkh(f, 8'h5a);
|
||||||
|
|
||||||
|
`checkh(g[15:8], 8'h5a);
|
||||||
|
force g[15:8] = 8'ha5;
|
||||||
|
`checkh(g[15:8], 8'ha5);
|
||||||
|
release g[15:8];
|
||||||
|
`checkh(g[15:8], 8'h5a);
|
||||||
|
|
||||||
|
force d = 32'h1234_5678;
|
||||||
|
`checkh(d, 32'h1234_5678);
|
||||||
|
release d;
|
||||||
|
`checkh(d, 32'h1234_5678);
|
||||||
|
|
||||||
|
idx = 5'd4;
|
||||||
|
force idx = 5'd8;
|
||||||
|
`checkh(idx, 5'd8);
|
||||||
|
release idx;
|
||||||
|
`checkh(idx, 5'd8);
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub(input logic [31:0] c);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub8(input logic [7:0] c);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module subout(output logic [7:0] c);
|
||||||
|
assign c = 8'h5a;
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
test.top_filename = "t_force_immediate_release_port_net.v"
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=["--binary -fno-inline"])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
Loading…
Reference in New Issue