mirror of
https://github.com/verilator/verilator.git
synced 2025-04-04 19:52:39 +00:00
parent
72845167e6
commit
a8b5738b44
@ -406,6 +406,7 @@ detailed descriptions of these arguments.
|
||||
--output-split-ctrace <statements> Split tracing functions
|
||||
-P Disable line numbers and blanks with -E
|
||||
--pins-bv <bits> Specify types for top-level ports
|
||||
--pins-inout-enables Specify that __en and __out signals be created for inouts
|
||||
--pins-sc-biguint Specify types for top-level ports
|
||||
--pins-sc-uint Specify types for top-level ports
|
||||
--pins-uint8 Specify types for top-level ports
|
||||
|
@ -985,6 +985,13 @@ Summary:
|
||||
:option:`/*verilator&32;sc_bv*/` metacomment to select specific ports to
|
||||
be sc_bv.
|
||||
|
||||
.. option:: --pins-inout-enables
|
||||
|
||||
Specifies that the __en and __out outputs will always be created for
|
||||
inouts in the top-level module. The __en variable has a one in a bit
|
||||
position to indicate the corresponding bit of the __out variable has
|
||||
a value being driven from within the Verilated model.
|
||||
|
||||
.. option:: --pins-sc-uint
|
||||
|
||||
Specifies SystemC inputs/outputs greater than 2 bits wide should use
|
||||
|
@ -1388,6 +1388,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
||||
m_pinsScBigUint = flag;
|
||||
m_pinsBv = 513;
|
||||
});
|
||||
DECL_OPTION("-pins-inout-enables", OnOff, &m_pinsInoutEnables);
|
||||
DECL_OPTION("-pins-uint8", OnOff, &m_pinsUint8);
|
||||
DECL_OPTION("-pipe-filter", Set, &m_pipeFilter);
|
||||
DECL_OPTION("-pp-comments", OnOff, &m_ppComments);
|
||||
|
@ -258,6 +258,7 @@ private:
|
||||
bool m_main = false; // main switch: --main
|
||||
bool m_outFormatOk = false; // main switch: --cc, --sc or --sp was specified
|
||||
bool m_pedantic = false; // main switch: --Wpedantic
|
||||
bool m_pinsInoutEnables = false;// main switch: --pins-inout-enables
|
||||
bool m_pinsScUint = false; // main switch: --pins-sc-uint
|
||||
bool m_pinsScBigUint = false; // main switch: --pins-sc-biguint
|
||||
bool m_pinsUint8 = false; // main switch: --pins-uint8
|
||||
@ -509,6 +510,7 @@ public:
|
||||
bool outFormatOk() const { return m_outFormatOk; }
|
||||
bool keepTempFiles() const { return (V3Error::debugDefault() != 0); }
|
||||
bool pedantic() const { return m_pedantic; }
|
||||
bool pinsInoutEnables() const { return m_pinsInoutEnables; }
|
||||
bool pinsScUint() const { return m_pinsScUint; }
|
||||
bool pinsScBigUint() const { return m_pinsScBigUint; }
|
||||
bool pinsUint8() const { return m_pinsUint8; }
|
||||
|
@ -483,11 +483,12 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
// Otherwise return the previous output enable
|
||||
return VN_AS(nodep->user1p(), NodeExpr);
|
||||
}
|
||||
AstVar* getCreateEnVarp(AstVar* invarp) {
|
||||
AstVar* getCreateEnVarp(AstVar* invarp, bool isTop) {
|
||||
// Return the master __en for the specified input variable
|
||||
if (!invarp->user1p()) {
|
||||
AstVar* const newp = new AstVar{invarp->fileline(), VVarType::MODULETEMP,
|
||||
invarp->name() + "__en", invarp};
|
||||
AstVar* const newp
|
||||
= new AstVar{invarp->fileline(), isTop ? VVarType::PORT : VVarType::MODULETEMP,
|
||||
invarp->name() + "__en", invarp};
|
||||
UINFO(9, " newenv " << newp << endl);
|
||||
modAddStmtp(invarp, newp);
|
||||
invarp->user1p(newp); // find envar given invarp
|
||||
@ -504,7 +505,7 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
}
|
||||
AstNodeExpr* getEnExprBasedOnOriginalp(AstNodeExpr* const nodep) {
|
||||
if (AstVarRef* const varrefp = VN_CAST(nodep, VarRef)) {
|
||||
return new AstVarRef{varrefp->fileline(), getCreateEnVarp(varrefp->varp()),
|
||||
return new AstVarRef{varrefp->fileline(), getCreateEnVarp(varrefp->varp(), false),
|
||||
VAccess::READ};
|
||||
} else if (AstConst* const constp = VN_CAST(nodep, Const)) {
|
||||
return getNonZConstp(constp);
|
||||
@ -535,11 +536,12 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
AstVar* getCreateOutVarp(AstVar* invarp) {
|
||||
AstVar* getCreateOutVarp(AstVar* invarp, bool isTop) {
|
||||
// Return the master __out for the specified input variable
|
||||
if (!m_varAux(invarp).outVarp) {
|
||||
AstVar* const newp = new AstVar{invarp->fileline(), VVarType::MODULETEMP,
|
||||
invarp->name() + "__out", invarp};
|
||||
AstVar* const newp
|
||||
= new AstVar{invarp->fileline(), isTop ? VVarType::PORT : VVarType::MODULETEMP,
|
||||
invarp->name() + "__out", invarp};
|
||||
UINFO(9, " newout " << newp << endl);
|
||||
modAddStmtp(invarp, newp);
|
||||
m_varAux(invarp).outVarp = newp; // find outvar given invarp
|
||||
@ -714,20 +716,27 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
// original port gets converted to an input. Don't tristate expand
|
||||
// if this is the top level so that we can force the final
|
||||
// tristate resolution at the top.
|
||||
// Or if this is a top-level inout, do tristate expand if requested
|
||||
// by pinsInoutEnables(). The resolution will be done outside of
|
||||
// verilator.
|
||||
AstVar* envarp = nullptr;
|
||||
AstVar* outvarp = nullptr; // __out
|
||||
AstVar* lhsp = invarp; // Variable to assign drive-value to (<in> or __out)
|
||||
if (!nodep->isTop() && invarp->isIO()) {
|
||||
bool isTopInout
|
||||
= (invarp->direction() == VDirection::INOUT) && invarp->isIO() && nodep->isTop();
|
||||
if ((v3Global.opt.pinsInoutEnables() && isTopInout)
|
||||
|| ((!nodep->isTop()) && invarp->isIO())) {
|
||||
// This var becomes an input
|
||||
invarp->varType2In(); // convert existing port to type input
|
||||
// Create an output port (__out)
|
||||
outvarp = getCreateOutVarp(invarp);
|
||||
outvarp = getCreateOutVarp(invarp, isTopInout);
|
||||
outvarp->varType2Out();
|
||||
lhsp = outvarp; // Must assign to __out, not to normal input signal
|
||||
UINFO(9, " TRISTATE propagates up with " << lhsp << endl);
|
||||
// Create an output enable port (__en)
|
||||
// May already be created if have foo === 1'bz somewhere
|
||||
envarp = getCreateEnVarp(invarp); // direction will be sen in visit(AstPin*)
|
||||
envarp
|
||||
= getCreateEnVarp(invarp, isTopInout); // direction will be sen in visit(AstPin*)
|
||||
//
|
||||
outvarp->user1p(envarp);
|
||||
m_varAux(outvarp).pullp = m_varAux(invarp).pullp; // AstPull* propagation
|
||||
@ -821,6 +830,18 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
assp->user2(U2_BOTH); // Don't process further; already resolved
|
||||
if (debug() >= 9) assp->dumpTree("- lhsp-eqn: ");
|
||||
nodep->addStmtsp(assp);
|
||||
|
||||
// If this is a top-level inout, make sure that the INOUT pins get __en and __out
|
||||
if (v3Global.opt.pinsInoutEnables() && isTopInout) {
|
||||
if (envarp) {
|
||||
envarp->primaryIO(true);
|
||||
envarp->direction(VDirection::OUTPUT);
|
||||
}
|
||||
if (outvarp) {
|
||||
outvarp->primaryIO(true);
|
||||
outvarp->direction(VDirection::OUTPUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isOnlyAssignmentIsToLhsVar(AstAssignW* const nodep) {
|
||||
@ -1390,7 +1411,7 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
<< nodep->prettyTypeName());
|
||||
return;
|
||||
}
|
||||
AstVar* const envarp = getCreateEnVarp(varrefp->varp());
|
||||
AstVar* const envarp = getCreateEnVarp(varrefp->varp(), false);
|
||||
// If any drops, we need to add in the count of Zs (from __en)
|
||||
UINFO(4, " COUNTBITS('z)-> " << nodep << endl);
|
||||
VNRelinker relinkHandle;
|
||||
@ -1688,7 +1709,7 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
&& m_tgraph.feedsTri(nodep)) {
|
||||
// Then propagate the enable from the original variable
|
||||
UINFO(9, " Ref-to-tri " << nodep << endl);
|
||||
AstVar* const enVarp = getCreateEnVarp(nodep->varp());
|
||||
AstVar* const enVarp = getCreateEnVarp(nodep->varp(), false);
|
||||
nodep->user1p(new AstVarRef{nodep->fileline(), enVarp, VAccess::READ});
|
||||
}
|
||||
(void)m_alhs; // NOP; user1() already passed down from assignment
|
||||
|
28
test_regress/t/t_tri_gate_bufif0_pins_inout.pl
Executable file
28
test_regress/t/t_tri_gate_bufif0_pins_inout.pl
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_BUFIF0',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_BUFIF0',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
29
test_regress/t/t_tri_gate_bufif1_pins_inout.pl
Executable file
29
test_regress/t/t_tri_gate_bufif1_pins_inout.pl
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env perl
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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
|
||||
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
|
||||
scenarios(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_BUFIF1',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_BUFIF1',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_tri_gate_cond_pins_inout.pl
Executable file
28
test_regress/t/t_tri_gate_cond_pins_inout.pl
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_COND',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_COND',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_tri_gate_nmos_pins_inout.pl
Executable file
28
test_regress/t/t_tri_gate_nmos_pins_inout.pl
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_NMOS',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_NMOS',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_tri_gate_notif0_pins_inout.pl
Executable file
28
test_regress/t/t_tri_gate_notif0_pins_inout.pl
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_NOTIF0',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_NOTIF0',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_tri_gate_notif1_pins_inout.pl
Executable file
28
test_regress/t/t_tri_gate_notif1_pins_inout.pl
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_NOTIF1',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_NOTIF1',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_tri_gate_pmos_pins_inout.pl
Executable file
28
test_regress/t/t_tri_gate_pmos_pins_inout.pl
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_gate.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
v_flags2 => ['+define+T_PMOS',],
|
||||
make_flags => 'CPPFLAGS_ADD=-DT_PMOS',
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_gate.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
26
test_regress/t/t_tri_inout_pins_inout.pl
Executable file
26
test_regress/t/t_tri_inout_pins_inout.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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
|
||||
|
||||
top_filename("t/t_tri_inout.v");
|
||||
|
||||
scenarios(vlt_all => 1);
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_inout.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
24
test_regress/t/t_tri_no_top.pl
Executable file
24
test_regress/t/t_tri_no_top.pl
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 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);
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe --pins-inout-enables --timing --main", "$Self->{t_dir}/t_tri_top_en_out.v"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
66
test_regress/t/t_tri_no_top.v
Normal file
66
test_regress/t/t_tri_no_top.v
Normal file
@ -0,0 +1,66 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Paul Wright.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// The module t_tri_top_en_out is used to test that we can
|
||||
// force verilator to include __en and __out variables for
|
||||
// inouts. This test checks that the tests within that module
|
||||
// pass. They should pass regardless of the presence of C or
|
||||
// SystemVerilog in the level above.
|
||||
|
||||
module
|
||||
t_tri_no_top
|
||||
();
|
||||
|
||||
timeunit 1ns;
|
||||
timeprecision 1ps;
|
||||
|
||||
wire single_bit_io;
|
||||
|
||||
wire bidir_single_bit_io;
|
||||
|
||||
wire [63:0] bus_64_io;
|
||||
|
||||
wire [63:0] bidir_bus_64_io;
|
||||
|
||||
wire [127:0] bus_128_io;
|
||||
|
||||
wire [127:0] bidir_bus_128_io;
|
||||
|
||||
reg [3:0] drv_en;
|
||||
|
||||
reg test_en;
|
||||
|
||||
wire loop_done;
|
||||
|
||||
wire sub_io;
|
||||
|
||||
t_tri_top_en_out
|
||||
t_tri_top_en_out
|
||||
(.*);
|
||||
|
||||
initial
|
||||
begin
|
||||
test_en = 1'b1;
|
||||
drv_en = 4'd0;
|
||||
|
||||
forever
|
||||
begin
|
||||
@(loop_done);
|
||||
if (loop_done === 1'b1)
|
||||
begin
|
||||
if (drv_en == 4'hf)
|
||||
begin
|
||||
test_en = 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
drv_en++;
|
||||
end
|
||||
end
|
||||
end
|
||||
end // initial begin
|
||||
|
||||
endmodule // top
|
26
test_regress/t/t_tri_pullup_pins_inout.pl
Executable file
26
test_regress/t/t_tri_pullup_pins_inout.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_pullup.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_pullup.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
26
test_regress/t/t_tri_select_pins_inout.pl
Executable file
26
test_regress/t/t_tri_select_pins_inout.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 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(vlt_all => 1);
|
||||
|
||||
top_filename("t/t_tri_select.v");
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe --pins-inout-enables $Self->{t_dir}/t_tri_select.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
24
test_regress/t/t_tri_struct_pins_inout.pl
Executable file
24
test_regress/t/t_tri_struct_pins_inout.pl
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 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_st => 1);
|
||||
|
||||
top_filename("t/t_tri_struct.v");
|
||||
|
||||
compile(
|
||||
verilator_flags2 => ['--exe --pins-inout-enables --main --timing'],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
168
test_regress/t/t_tri_top_en_out.cpp
Normal file
168
test_regress/t/t_tri_top_en_out.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module, C driver code
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Paul Wright.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
#include "verilated.h"
|
||||
|
||||
#include "TestCheck.h"
|
||||
#include "Vt_tri_top_en_out.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
int main(int argc, char** argv, char**) {
|
||||
int errors;
|
||||
// Setup context, defaults, and parse command line
|
||||
Verilated::debug(0);
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
contextp->commandArgs(argc, argv);
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating
|
||||
const std::unique_ptr<Vt_tri_top_en_out> topp{new Vt_tri_top_en_out{contextp.get()}};
|
||||
|
||||
// Initial input
|
||||
topp->drv_en = 0;
|
||||
topp->single_bit_io = rand() & 1;
|
||||
topp->bidir_single_bit_io = rand() & 1;
|
||||
topp->bus_64_io = 0;
|
||||
topp->bidir_bus_64_io = rand() & 0xffffffffffffffff;
|
||||
topp->bus_128_io[0] = 0;
|
||||
topp->bus_128_io[1] = 0;
|
||||
topp->bus_128_io[2] = 0;
|
||||
topp->bus_128_io[3] = 0;
|
||||
topp->bidir_bus_128_io[0] = rand() & 0xffffffff;
|
||||
topp->bidir_bus_128_io[1] = rand() & 0xffffffff;
|
||||
topp->bidir_bus_128_io[2] = rand() & 0xffffffff;
|
||||
topp->bidir_bus_128_io[3] = rand() & 0xffffffff;
|
||||
topp->sub_io = rand() & 1;
|
||||
topp->test_en = 1;
|
||||
|
||||
errors = 0;
|
||||
|
||||
// Simulate until $finish
|
||||
while (!contextp->gotFinish()) {
|
||||
// Evaluate model
|
||||
topp->eval();
|
||||
|
||||
// Advance time (to scheduled events)
|
||||
if (!topp->eventsPending()) break;
|
||||
contextp->time(topp->nextTimeSlot());
|
||||
|
||||
// We want to check that the __en and __out signals can be accessed
|
||||
printf("Info:(cpp): drv_en = %x\n", topp->drv_en);
|
||||
printf("Info:(cpp): bidir_single_bit_io__en = %x\n", topp->bidir_single_bit_io__en);
|
||||
printf("Info:(cpp): bidir_bus_64_io__en = %x\n", (unsigned int)topp->bidir_bus_64_io__en);
|
||||
printf("Info:(cpp): bidir_bus_128_io__en = %x,%x,%x,%x\n", topp->bidir_bus_128_io__en[3],
|
||||
topp->bidir_bus_128_io__en[2], topp->bidir_bus_128_io__en[1],
|
||||
topp->bidir_bus_128_io__en[0]);
|
||||
printf("Info:(cpp): sub_io__en = %x\n", topp->sub_io__en);
|
||||
printf("Info:(cpp): bidir_single_bit_io = %x\n", topp->bidir_single_bit_io__out);
|
||||
printf("Info:(cpp): bidir_bus_64_io = %x\n", (unsigned int)topp->bidir_bus_64_io__out);
|
||||
printf("Info:(cpp): bidir_bus_128_io = %x,%x,%x,%x\n", topp->bidir_bus_128_io__out[3],
|
||||
topp->bidir_bus_128_io__out[2], topp->bidir_bus_128_io__out[1],
|
||||
topp->bidir_bus_128_io__out[0]);
|
||||
printf("Info:(cpp): sub_io = %x\n", topp->sub_io__out);
|
||||
|
||||
// Loop back if verilog is driving
|
||||
// Verilator will not do this for itself
|
||||
// We must implement the top-level resolution
|
||||
if (topp->sub_io__en) { topp->sub_io = topp->sub_io__out; }
|
||||
if (topp->bidir_single_bit_io__en) {
|
||||
topp->bidir_single_bit_io = topp->bidir_single_bit_io__out;
|
||||
}
|
||||
// For bus signals, overwrite the bits which are driven by verilog, preserve the others
|
||||
if (topp->bidir_bus_64_io__en) {
|
||||
topp->bidir_bus_64_io = ((~topp->bidir_bus_64_io__en) & topp->bidir_bus_64_io)
|
||||
| (topp->bidir_bus_64_io__en & topp->bidir_bus_64_io__out);
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (topp->bidir_bus_128_io__en[i]) {
|
||||
topp->bidir_bus_128_io[i]
|
||||
= ((~topp->bidir_bus_128_io__en[i]) & topp->bidir_bus_128_io[i])
|
||||
| (topp->bidir_bus_128_io__en[i] & topp->bidir_bus_128_io__out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Has the verilog code finished a test loop?
|
||||
if (topp->loop_done == 1) {
|
||||
|
||||
// Check the expected __en output
|
||||
|
||||
if (topp->drv_en & 0x1) {
|
||||
TEST_CHECK_EQ(uint64_t(topp->sub_io__en), 1);
|
||||
TEST_CHECK_EQ(uint64_t(topp->bidir_single_bit_io__en), 1);
|
||||
} else {
|
||||
TEST_CHECK_EQ(uint64_t(topp->sub_io__en), 0);
|
||||
TEST_CHECK_EQ(uint64_t(topp->bidir_single_bit_io__en), 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// __en enabled?
|
||||
if ((topp->drv_en & (1 << i)) != 0) {
|
||||
TEST_CHECK_EQ(uint64_t(topp->bidir_bus_64_io__en >> (i * 16) & 0xffff),
|
||||
0xffff);
|
||||
TEST_CHECK_EQ(uint64_t(topp->bidir_bus_128_io__en[i]), 0xffffffff);
|
||||
}
|
||||
// __en not enabled
|
||||
else {
|
||||
TEST_CHECK_EQ(uint64_t(topp->bidir_bus_64_io__en >> (i * 16) & 0xffff),
|
||||
0x0000);
|
||||
TEST_CHECK_EQ(uint64_t(topp->bidir_bus_128_io__en[i]), 0x00000000);
|
||||
}
|
||||
} // for
|
||||
if (topp->drv_en == 15) {
|
||||
topp->test_en = 0;
|
||||
} else {
|
||||
topp->drv_en++;
|
||||
|
||||
// Drive the bits verilog shouldn't be driving
|
||||
if (topp->drv_en & 1) {
|
||||
topp->single_bit_io = rand() & 1;
|
||||
topp->bidir_single_bit_io = rand() & 1;
|
||||
topp->sub_io = rand() & 1;
|
||||
topp->bidir_bus_64_io
|
||||
= ((rand() & 0xffff) << 0) | (topp->bidir_bus_64_io & 0xffffffffffff0000);
|
||||
topp->bidir_bus_128_io[0] = rand() & 0xffffffff;
|
||||
} else {
|
||||
topp->single_bit_io = 0;
|
||||
topp->bidir_single_bit_io = 0;
|
||||
topp->sub_io = 0;
|
||||
topp->bidir_bus_64_io = (topp->bidir_bus_64_io & 0xffffffffffff0000);
|
||||
topp->bidir_bus_128_io[0] = 0;
|
||||
}
|
||||
if (topp->drv_en & 2) {
|
||||
topp->bidir_bus_64_io
|
||||
= ((rand() & 0xffff) << 16) | (topp->bidir_bus_64_io & 0xffffffff0000ffff);
|
||||
topp->bidir_bus_128_io[1] = rand() & 0xffffffff;
|
||||
} else {
|
||||
topp->bidir_bus_64_io = (topp->bidir_bus_64_io & 0xffffffff0000ffff);
|
||||
topp->bidir_bus_128_io[1] = 0;
|
||||
}
|
||||
if (topp->drv_en & 4) {
|
||||
topp->bidir_bus_64_io = (((uint64_t)(rand() & 0xffff)) << 32)
|
||||
| (topp->bidir_bus_64_io & 0xffff0000ffffffff);
|
||||
topp->bidir_bus_128_io[2] = rand() & 0xffffffff;
|
||||
} else {
|
||||
topp->bidir_bus_64_io = (topp->bidir_bus_64_io & 0xffff0000ffffffff);
|
||||
topp->bidir_bus_128_io[2] = 0;
|
||||
}
|
||||
if (topp->drv_en & 8) {
|
||||
topp->bidir_bus_64_io = (((uint64_t)(rand() & 0xffff)) << 48)
|
||||
| (topp->bidir_bus_64_io & 0x0000ffffffffffff);
|
||||
topp->bidir_bus_128_io[3] = rand() & 0xffffffff;
|
||||
} else {
|
||||
topp->bidir_bus_64_io = (topp->bidir_bus_64_io & 0x0000ffffffffffff);
|
||||
topp->bidir_bus_128_io[3] = 0;
|
||||
}
|
||||
}
|
||||
// Invert the input side
|
||||
topp->bidir_single_bit_io = (~topp->bidir_single_bit_io) & 0x1;
|
||||
topp->bidir_bus_64_io = ~topp->bidir_bus_64_io;
|
||||
for (int i = 0; i < 4; i++) { topp->bidir_bus_128_io[i] = ~topp->bidir_bus_128_io[i]; }
|
||||
} // if (loop_done)
|
||||
if (errors != 0) break;
|
||||
}
|
||||
// Final model cleanup
|
||||
topp->final();
|
||||
return 0;
|
||||
}
|
23
test_regress/t/t_tri_top_en_out.pl
Executable file
23
test_regress/t/t_tri_top_en_out.pl
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 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(vlt => 1);
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_flags2 => ["--exe --timing --pins-inout-enables", "$Self->{t_dir}/$Self->{name}.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
ok(1);
|
||||
1;
|
221
test_regress/t/t_tri_top_en_out.v
Normal file
221
test_regress/t/t_tri_top_en_out.v
Normal file
@ -0,0 +1,221 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Paul Wright.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// A submodule to ensure that __en and __out propagate upwards
|
||||
module
|
||||
t_sub_io
|
||||
(
|
||||
inout my_io,
|
||||
input drv_en,
|
||||
input op_val
|
||||
);
|
||||
|
||||
timeunit 1ns;
|
||||
timeprecision 1ps;
|
||||
|
||||
assign my_io = drv_en ? op_val : 1'bz;
|
||||
|
||||
endmodule
|
||||
|
||||
`ifndef T_TRI_TOP_NAME
|
||||
`define T_TRI_TOP_NAME t_tri_top_en_out
|
||||
`endif
|
||||
|
||||
// The top module
|
||||
// __en and __out should be added for the inout ports
|
||||
module
|
||||
`T_TRI_TOP_NAME
|
||||
(
|
||||
inout single_bit_io,
|
||||
inout bidir_single_bit_io,
|
||||
inout [63:0] bus_64_io,
|
||||
inout [63:0] bidir_bus_64_io,
|
||||
inout [127:0] bus_128_io,
|
||||
inout [127:0] bidir_bus_128_io,
|
||||
input [3:0] drv_en,
|
||||
input test_en,
|
||||
output logic loop_done,
|
||||
inout sub_io
|
||||
);
|
||||
|
||||
timeunit 1ns;
|
||||
timeprecision 1ps;
|
||||
|
||||
bit rand_bit;
|
||||
|
||||
assign single_bit_io = 1'bz;
|
||||
assign bidir_single_bit_io = drv_en[0] ? rand_bit : 1'bz;
|
||||
assign bus_64_io = {64{1'bz}};
|
||||
|
||||
assign bidir_bus_64_io[15:0] = drv_en[0] ? {16{rand_bit}} : {16{1'bz}};
|
||||
assign bidir_bus_64_io[31:16] = drv_en[1] ? {16{rand_bit}} : {16{1'bz}};
|
||||
assign bidir_bus_64_io[47:32] = drv_en[2] ? {16{rand_bit}} : {16{1'bz}};
|
||||
assign bidir_bus_64_io[63:48] = drv_en[3] ? {16{rand_bit}} : {16{1'bz}};
|
||||
|
||||
assign bus_128_io = {128{1'bz}};
|
||||
|
||||
assign bidir_bus_128_io[31:0] = drv_en[0] ? {32{rand_bit}} : {32{1'bz}};
|
||||
assign bidir_bus_128_io[63:32] = drv_en[1] ? {32{rand_bit}} : {32{1'bz}};
|
||||
assign bidir_bus_128_io[95:64] = drv_en[2] ? {32{rand_bit}} : {32{1'bz}};
|
||||
assign bidir_bus_128_io[127:96] = drv_en[3] ? {32{rand_bit}} : {32{1'bz}};
|
||||
|
||||
int loop_cnt;
|
||||
int error_cnt;
|
||||
|
||||
initial begin : init_error
|
||||
error_cnt = 'd0;
|
||||
end
|
||||
|
||||
initial begin : test_and_loop
|
||||
loop_cnt = 0;
|
||||
#(1ps);
|
||||
while (test_en == 1) begin
|
||||
loop_done = 0;
|
||||
rand_bit = (($urandom_range(1,0) & 'd1) == 'd1);
|
||||
chk_sigs;
|
||||
#(1ns) $display("Info:(v): 1ns");
|
||||
rand_bit = ~rand_bit;
|
||||
chk_sigs;
|
||||
#(1ns) $display("Info:(v): 2ns");
|
||||
rand_bit = ~rand_bit;
|
||||
chk_sigs;
|
||||
#(1ns);
|
||||
loop_done = 1;
|
||||
loop_cnt++;
|
||||
#(1ps);
|
||||
end
|
||||
if (error_cnt == 'd0) begin
|
||||
$display("Info:(v): Error count was = %0d", error_cnt);
|
||||
$write("*-* All Finished *-*\n");
|
||||
end
|
||||
else begin
|
||||
$display("Info:(v): Error count was non-zero %0d", error_cnt);
|
||||
end
|
||||
$finish(1);
|
||||
end
|
||||
|
||||
always @(loop_cnt)
|
||||
begin
|
||||
if (loop_cnt > 32) begin
|
||||
$display("%%Error:(v): Excessive loop count");
|
||||
$display("drv_en = %b, test_en = %b", drv_en, test_en);
|
||||
$finish(1);
|
||||
end
|
||||
end
|
||||
|
||||
final begin
|
||||
$display("Info:(v): All done at %t", $time);
|
||||
$display("Info:(v): Error count = %0d", error_cnt);
|
||||
chk_err: assert(error_cnt == 0);
|
||||
end
|
||||
|
||||
wire internal_sub_io;
|
||||
|
||||
logic [15:0] my_64_segment;
|
||||
logic [31:0] my_128_segment;
|
||||
|
||||
task chk_sigs;
|
||||
begin
|
||||
#(1ps);
|
||||
$display("Info:(v): rand_bit = %b", rand_bit);
|
||||
if (|drv_en) begin
|
||||
$display("Info:(v): drv_en = %b", drv_en);
|
||||
$display("Info:(v): bidir_single_bit_io = %b", bidir_single_bit_io);
|
||||
$display("Info:(v): bidir_bus_64_io = %b,%b,%b,%b",
|
||||
bidir_bus_64_io[63:48], bidir_bus_64_io[47:32],
|
||||
bidir_bus_64_io[31:16],bidir_bus_64_io[15:0]);
|
||||
$display("Info:(v): bidir_bus_128_io = %b,%b,%b,%b",
|
||||
bidir_bus_128_io[127:96], bidir_bus_128_io[95:64],
|
||||
bidir_bus_128_io[63:32], bidir_bus_128_io[31:0]);
|
||||
|
||||
for (int i=0;i<4;i++) begin
|
||||
if (drv_en[0]) begin
|
||||
if (bidir_single_bit_io !== rand_bit) begin
|
||||
$display("%%Error:(v): bidir_single_bit_io is wrong (expect %b got %b)",
|
||||
rand_bit, bidir_single_bit_io);
|
||||
error_cnt++;
|
||||
end
|
||||
if (sub_io !== rand_bit) begin
|
||||
$display("%%Error:(v): sub_io is wrong (expect %b, got %b)",
|
||||
rand_bit, sub_io);
|
||||
end
|
||||
end
|
||||
|
||||
if (drv_en[1]) begin
|
||||
if (internal_sub_io !== ~rand_bit) begin
|
||||
$display("%%Error:(v): sub_io is wrong");
|
||||
error_cnt++;
|
||||
end
|
||||
end
|
||||
|
||||
if (drv_en[i]) begin
|
||||
int msb, lsb;
|
||||
msb = ((i+1)*16-1);
|
||||
lsb = i*16;
|
||||
|
||||
case(i)
|
||||
'd0: my_64_segment = bidir_bus_64_io[15:0];
|
||||
'd1: my_64_segment = bidir_bus_64_io[31:16];
|
||||
'd2: my_64_segment = bidir_bus_64_io[47:32];
|
||||
default: my_64_segment = bidir_bus_64_io[63:48];
|
||||
endcase
|
||||
|
||||
case(i)
|
||||
'd0: my_128_segment = bidir_bus_128_io[31:0];
|
||||
'd1: my_128_segment = bidir_bus_128_io[63:32];
|
||||
'd2: my_128_segment = bidir_bus_128_io[95:64];
|
||||
default: my_128_segment = bidir_bus_128_io[127:96];
|
||||
endcase
|
||||
|
||||
if (my_64_segment !== {16{rand_bit}}) begin
|
||||
$display("%%Error:(v): bidir_bus_64_io is wrong");
|
||||
$display("Error:(v): Should be bidir_bus_64_io[%0d:%0d] = %b, was = %b",
|
||||
msb, lsb, {16{rand_bit}}, my_64_segment);
|
||||
error_cnt++;
|
||||
end
|
||||
else begin
|
||||
$display("Info:(v): Pass: bidir_bus_64_io[%0d:%0d] = %b",
|
||||
msb, lsb, {16{rand_bit}});
|
||||
end
|
||||
|
||||
msb = ((i+1)*32-1);
|
||||
lsb = i*32;
|
||||
if (my_128_segment !== {32{rand_bit}}) begin
|
||||
$display("%%Error:(v): bidir_bus_128_io is wrong");
|
||||
$display("Error:(v):Should be bidir_bus_128_io[%0d:%0d] = %b, was = %b",
|
||||
msb, lsb, {32{rand_bit}}, my_128_segment);
|
||||
error_cnt++;
|
||||
end
|
||||
else
|
||||
begin
|
||||
$display("Info:(v): Pass: bidir_bus_128_io[%0d:%0d] = %b",
|
||||
msb, lsb, {32{rand_bit}});
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
// Connects to top level
|
||||
t_sub_io
|
||||
t_sub_io
|
||||
(
|
||||
.my_io (sub_io),
|
||||
.drv_en (drv_en[0]),
|
||||
.op_val (rand_bit)
|
||||
);
|
||||
|
||||
// Does not connect to top-level
|
||||
t_sub_io
|
||||
t_sub_io_internal
|
||||
(
|
||||
.my_io (internal_sub_io),
|
||||
.drv_en (drv_en[1]),
|
||||
.op_val (~rand_bit)
|
||||
);
|
||||
|
||||
endmodule
|
23
test_regress/t/t_tri_top_en_out_bad.pl
Executable file
23
test_regress/t/t_tri_top_en_out_bad.pl
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 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(vlt => 1);
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 1,
|
||||
verilator_make_gmake => 1,
|
||||
verilator_flags2 => ["--exe --pins-inout-enables --no-timing -Wno-STMTDLY"]
|
||||
);
|
||||
file_grep_not("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/internal_sub_io__out/);
|
||||
file_grep_not("$Self->{obj_dir}/$Self->{vm_prefix}.h", qr/internal_sub_io__en/);
|
||||
|
||||
ok(1);
|
||||
1;
|
11
test_regress/t/t_tri_top_en_out_bad.v
Normal file
11
test_regress/t/t_tri_top_en_out_bad.v
Normal file
@ -0,0 +1,11 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Paul Wright.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
//
|
||||
// A submodule to ensure that __en and __out propagate upwards
|
||||
// This version of the test should fail
|
||||
`define T_TRI_TOP_NAME t_tri_top_en_out_bad
|
||||
`define SKIP_TIMING 1
|
||||
`include "t_tri_top_en_out.v"
|
Loading…
Reference in New Issue
Block a user