Fix tristate lowering for interface inout ports (#7134 repair) (#7708) (#7710)

Fixes #7708.
This commit is contained in:
Nick Brereton 2026-06-03 19:51:49 -04:00 committed by GitHub
parent 7bd41bfbb9
commit 4d5393c191
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 83 additions and 2 deletions

View File

@ -739,7 +739,7 @@ class TristateVisitor final : public TristateBaseVisitor {
// Check if the var is owned by a different module (cross-module reference). // Check if the var is owned by a different module (cross-module reference).
// For interface vars this is expected; for regular modules it's unsupported. // For interface vars this is expected; for regular modules it's unsupported.
AstNodeModule* const ownerModp = findParentModule(invarp); AstNodeModule* const ownerModp = findParentModule(invarp);
const bool isCrossModule = ownerModp && ownerModp != nodep && !invarp->isIO(); const bool isCrossModule = ownerModp && ownerModp != nodep;
const bool isIfaceTri = isCrossModule && VN_IS(ownerModp, Iface); const bool isIfaceTri = isCrossModule && VN_IS(ownerModp, Iface);
if (isCrossModule && !isIfaceTri) { if (isCrossModule && !isIfaceTri) {
@ -778,7 +778,7 @@ class TristateVisitor final : public TristateBaseVisitor {
kv.second.inlinedDots, kv.second.inlinedDots,
findModportForDotted(nodep, kv.first)); findModportForDotted(nodep, kv.first));
} }
} else if (VN_IS(nodep, Iface)) { } else if (VN_IS(nodep, Iface) && !invarp->isIO()) {
// Local driver in an interface module - use contribution mechanism // Local driver in an interface module - use contribution mechanism
// so it can be combined with any external drivers later // so it can be combined with any external drivers later
insertTristatesSignal(nodep, invarp, refsp, true, "", "", nullptr); insertTristatesSignal(nodep, invarp, refsp, true, "", "", nullptr);

View File

@ -0,0 +1,16 @@
#!/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('vlt')
test.compile()
test.passes()

View File

@ -0,0 +1,65 @@
// DESCRIPTION: Verilator: Interface inout port driven locally and externally
//
// 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
interface zest_if_local (
inout [0:0] U27
);
assign U27[0] = 1'b1;
endinterface
interface zest_if_ext (
inout [0:0] U28
);
endinterface
module ext_drv (
zest_if_ext zif,
input drive_en
);
assign zif.U28[0] = drive_en ? 1'b1 : 1'bz;
endmodule
interface zest_if_ext_mp (
inout [0:0] U29
);
modport drv(inout U29);
endinterface
module ext_drv_mp (
zest_if_ext_mp.drv zif,
input drive_en
);
assign zif.U29[0] = drive_en ? 1'b0 : 1'bz;
endmodule
module t (
inout [0:0] bus_local,
inout [0:0] bus_ext,
inout [0:0] bus_ext_mp,
input drive_en
);
zest_if_local zif_local (
.U27(bus_local)
);
zest_if_ext zif_ext (
.U28(bus_ext)
);
ext_drv u_ext_drv (
.zif(zif_ext),
.drive_en(drive_en)
);
zest_if_ext_mp zif_ext_mp (
.U29(bus_ext_mp)
);
ext_drv_mp u_ext_drv_mp (
.zif(zif_ext_mp),
.drive_en(drive_en)
);
endmodule