From 8c705ee145c37f646a513b4e1a234c37d3f44108 Mon Sep 17 00:00:00 2001 From: Dan Petrisko Date: Wed, 7 Jul 2021 12:00:29 -0700 Subject: [PATCH] Support middle-of-design nested topmodules (#3026) --- src/V3LinkCells.cpp | 21 ++------- test_regress/t/t_flag_topmod2_bad.out | 2 - test_regress/t/t_flag_topmod2_bad.v | 32 -------------- ...flag_topmod2_bad.pl => t_mod_topmodule.pl} | 14 +++--- test_regress/t/t_mod_topmodule.v | 34 +++++++++++++++ test_regress/t/t_mod_topmodule_nest.pl | 22 ++++++++++ test_regress/t/t_mod_topmodule_nest.v | 43 +++++++++++++++++++ 7 files changed, 111 insertions(+), 57 deletions(-) delete mode 100644 test_regress/t/t_flag_topmod2_bad.out delete mode 100644 test_regress/t/t_flag_topmod2_bad.v rename test_regress/t/{t_flag_topmod2_bad.pl => t_mod_topmodule.pl} (68%) create mode 100644 test_regress/t/t_mod_topmodule.v create mode 100755 test_regress/t/t_mod_topmodule_nest.pl create mode 100644 test_regress/t/t_mod_topmodule_nest.v diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index ef6804da0..0713c4d70 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -173,19 +173,6 @@ private: // +1 so we leave level 1 for the new wrapper we'll make in a moment AstNodeModule* modp = vvertexp->modp(); modp->level(vvertexp->rank() + 1); - if (vvertexp == m_topVertexp && modp->level() != 2) { - AstNodeModule* abovep = nullptr; - if (V3GraphEdge* edgep = vvertexp->inBeginp()) { - if (LinkCellsVertex* eFromVertexp - = dynamic_cast(edgep->fromp())) { - abovep = eFromVertexp->modp(); - } - } - v3error("Specified --top-module '" - << v3Global.opt.topModule() - << "' isn't at the top level, it's under another instance '" - << (abovep ? abovep->prettyName() : "UNKNOWN") << "'"); - } } } if (v3Global.opt.topModule() != "" && !m_topVertexp) { @@ -291,12 +278,12 @@ private: // m_mod, if 0 never did it, if !=, it is an unprocessed clone const bool cloned = (nodep->user1p() && nodep->user1p() != m_modp); if (nodep->user1p() == m_modp) return; // AstBind and AstNodeModule may call a cell twice - if (v3Global.opt.hierChild() && nodep->modName() == m_origTopModuleName) { - if (nodep->modName() == m_modp->origName()) { - // Only the root of the recursive instantiation can be a hierarhcical block. + if (nodep->modName() == m_origTopModuleName) { + if (v3Global.opt.hierChild() && nodep->modName() == m_modp->origName()) { + // Only the root of the recursive instantiation can be a hierarchical block. nodep->modName(m_modp->name()); } else { - // In hierarchical mode, non-top module can be the top module of this run + // non-top module will be the top module of this run VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); return; } diff --git a/test_regress/t/t_flag_topmod2_bad.out b/test_regress/t/t_flag_topmod2_bad.out deleted file mode 100644 index a3680a2c6..000000000 --- a/test_regress/t/t_flag_topmod2_bad.out +++ /dev/null @@ -1,2 +0,0 @@ -%Error: Specified --top-module 'a' isn't at the top level, it's under another instance 'a_top' -%Error: Exiting due to diff --git a/test_regress/t/t_flag_topmod2_bad.v b/test_regress/t/t_flag_topmod2_bad.v deleted file mode 100644 index 3d19fd0f5..000000000 --- a/test_regress/t/t_flag_topmod2_bad.v +++ /dev/null @@ -1,32 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain, for -// any use, without warranty, 2008 by Wilson Snyder. -// SPDX-License-Identifier: CC0-1.0 - -module a_top; - a a (); - initial begin - $write("Bad top modules\n"); - $stop; - end -endmodule - -module a; - b b (); - c c (); - d d (); -endmodule - -module b; -endmodule - -module c; -endmodule - -module d; - initial begin - $write("*-* All Finished *-*\n"); - $finish; - end -endmodule diff --git a/test_regress/t/t_flag_topmod2_bad.pl b/test_regress/t/t_mod_topmodule.pl similarity index 68% rename from test_regress/t/t_flag_topmod2_bad.pl rename to test_regress/t/t_mod_topmodule.pl index 8835ebd9c..914a14238 100755 --- a/test_regress/t/t_flag_topmod2_bad.pl +++ b/test_regress/t/t_mod_topmodule.pl @@ -2,18 +2,20 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } # DESCRIPTION: Verilator: Verilog Test driver/expect definition # -# Copyright 2008 by Wilson Snyder. This program is free software; you +# Copyright 2021 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); +scenarios(simulator => 1); -lint( - v_flags2 => ["--top-module a "], - fails => 1, - expect_filename => $Self->{golden_filename}, +compile( + verilator_flags2 => ["--top-module top"] + ); + +execute( + check_finished => 1, ); ok(1); diff --git a/test_regress/t/t_mod_topmodule.v b/test_regress/t/t_mod_topmodule.v new file mode 100644 index 000000000..05d4c3ffa --- /dev/null +++ b/test_regress/t/t_mod_topmodule.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This test verifies that a top-module can be specified which +// is instantiated beneath another module in the compiled source +// code. +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2021 by Dan Petrisko +// SPDX-License-Identifier: CC0-1.0 + +module top(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + always_ff @(posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish(); + end + +endmodule + +module faketop(/*AUTOARG*/ + ); + + top top(); + + // Stop immediately if this module is instantiated + initial begin + $stop(); + end + +endmodule diff --git a/test_regress/t/t_mod_topmodule_nest.pl b/test_regress/t/t_mod_topmodule_nest.pl new file mode 100755 index 000000000..914a14238 --- /dev/null +++ b/test_regress/t/t_mod_topmodule_nest.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2021 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( + verilator_flags2 => ["--top-module top"] + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_mod_topmodule_nest.v b/test_regress/t/t_mod_topmodule_nest.v new file mode 100644 index 000000000..53c8c41d7 --- /dev/null +++ b/test_regress/t/t_mod_topmodule_nest.v @@ -0,0 +1,43 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This test verifies that a top-module can be specified which +// is instantiated beneath another module in the compiled source +// code, even when that top-module has a module both above and beside +// it in the hierarchy. +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2021 by Dan Petrisko. +// SPDX-License-Identifier: CC0-1.0 + +module top(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + always_ff @(posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish(); + end + + under under(); + +endmodule + +module under(/*AUTOARG*/ + ); + +endmodule + +module faketop(/*AUTOARG*/ + ); + + under under(); + top top(); + + // Stop immediately if this module is instantiated + initial begin + $stop(); + end + +endmodule