Fix immediate release in submodules, set isContinuously correctly.
Signed-off-by: Artur Bieniek <abieniek@antmicro.com>
This commit is contained in:
parent
93d0443998
commit
accd1a44c8
|
|
@ -679,8 +679,9 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) {
|
|||
// the port variable. The constant can still be inlined, in which case
|
||||
// this is needed for tracing the inlined port variable.
|
||||
if (AstConst* const pinp = VN_CAST(pinExprp, Const)) {
|
||||
AstAssignW* const ap
|
||||
= new AstAssignW{flp, portRef(VAccess::WRITE), pinp->cloneTree(false)};
|
||||
AstVarRef* const lhsp = portRef(VAccess::WRITE);
|
||||
lhsp->varp()->isContinuously(true);
|
||||
AstAssignW* const ap = new AstAssignW{flp, lhsp, pinp->cloneTree(false)};
|
||||
modp->addStmtsp(new AstAlways{ap});
|
||||
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
|
||||
UINFO(6, "Not inlining port variable: " << nodep);
|
||||
if (nodep->direction() == VDirection::INPUT) {
|
||||
AstAssignW* const ap
|
||||
= new AstAssignW{flp, portRef(VAccess::WRITE), pinRefAsExpr(VAccess::READ)};
|
||||
AstVarRef* const lhsp = portRef(VAccess::WRITE);
|
||||
lhsp->varp()->isContinuously(true);
|
||||
AstAssignW* const ap = new AstAssignW{flp, lhsp, pinRefAsExpr(VAccess::READ)};
|
||||
modp->addStmtsp(new AstAlways{ap});
|
||||
} else if (nodep->direction() == VDirection::OUTPUT) {
|
||||
AstAssignW* const ap
|
||||
= new AstAssignW{flp, pinRefAsExpr(VAccess::WRITE), portRef(VAccess::READ)};
|
||||
AstNodeVarRef* const lhsp = VN_AS(pinRefAsExpr(VAccess::WRITE), NodeVarRef);
|
||||
lhsp->varp()->isContinuously(true);
|
||||
AstAssignW* const ap = new AstAssignW{flp, lhsp, portRef(VAccess::READ)};
|
||||
modp->addStmtsp(new AstAlways{ap});
|
||||
} else {
|
||||
pinExprp->v3fatalSrc("V3Tristate left INOUT port");
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@
|
|||
|
||||
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
|
||||
|
||||
|
|
@ -73,16 +79,17 @@ class InstVisitor final : public VNVisitor {
|
|||
} else if (nodep->modVarp()->isWritable()) {
|
||||
AstNodeExpr* const rhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
||||
m_cellp->name(), VAccess::READ};
|
||||
markContinuousLhs(exprp);
|
||||
AstAssignW* const assp = new AstAssignW{exprp->fileline(), exprp, rhsp};
|
||||
m_cellp->addNextHere(new AstAlways{assp});
|
||||
} else if (nodep->modVarp()->isNonOutput()) {
|
||||
// Don't bother moving constants now,
|
||||
// we'll be pushing the const down to the cell soon enough.
|
||||
AstAssignW* const assp
|
||||
= new AstAssignW{exprp->fileline(),
|
||||
new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
||||
m_cellp->name(), VAccess::WRITE},
|
||||
exprp};
|
||||
AstVarXRef* const lhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(),
|
||||
m_cellp->name(), VAccess::WRITE};
|
||||
|
||||
markContinuousLhs(lhsp);
|
||||
AstAssignW* const assp = new AstAssignW{exprp->fileline(), lhsp, exprp};
|
||||
m_cellp->addNextHere(new AstAlways{assp});
|
||||
UINFOTREE(9, assp, "", "_new");
|
||||
} else if (nodep->modVarp()->isIfaceRef()
|
||||
|
|
@ -903,9 +910,11 @@ public:
|
|||
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
|
||||
pinp->exprp(new AstVarRef{newvarp->fileline(), newvarp, VAccess::WRITE});
|
||||
AstNodeExpr* const rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
|
||||
markContinuousLhs(pinexprp);
|
||||
assignp = new AstAssignW{pinp->fileline(), pinexprp, rhsSelp};
|
||||
} else {
|
||||
// V3 width should have range/extended to make the widths correct
|
||||
newvarp->isContinuously(true);
|
||||
assignp = new AstAssignW{pinp->fileline(),
|
||||
new AstVarRef{pinp->fileline(), newvarp, VAccess::WRITE},
|
||||
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