Support `--top` specifying `config` name (#6710)

This commit is contained in:
Dan Ruelas-Petrisko 2025-11-19 17:23:02 -08:00 committed by GitHub
parent 00988aed70
commit 7edf6d4749
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 139 additions and 123 deletions

View File

@ -38,7 +38,7 @@ Chuxuan Wang
Chykon
Congcong Cai
Conor McCullough
Dan Petrisko
Dan Ruelas-Petrisko
Daniel Bates
Danny Oler
Dave Sargeant

View File

@ -821,16 +821,20 @@ class AstConfig final : public AstNode {
// Parents: NETLIST
// @astgen op1 := designp : List[AstConfigCell]
// @astgen op2 := itemsp : List[AstNode]
std::string m_name; // Config block name
std::string m_libname; // Config library, or ""
std::string m_configname; // Config name within library
public:
AstConfig(FileLine* fl, const std::string& name, AstNode* itemsp)
AstConfig(FileLine* fl, const std::string& libname, const std::string& cellname)
: ASTGEN_SUPER_Config(fl)
, m_name{name} {
addItemsp(itemsp);
}
, m_libname{libname}
, m_configname{cellname} {}
ASTGEN_MEMBERS_AstConfig;
std::string name() const override VL_MT_STABLE { return m_name; }
std::string name() const override VL_MT_STABLE { return m_libname + "." + m_configname; }
std::string libname() const VL_MT_STABLE { return m_libname; }
std::string configname() const VL_MT_STABLE { return m_configname; }
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
};
class AstConfigCell final : public AstNode {
// Parents: CONFIGRULE

View File

@ -1858,6 +1858,16 @@ void AstClocking::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isGlobal);
dumpJsonGen(str);
}
void AstConfig::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " configname=" << configname();
if (libname() != "work") str << " libname=" << libname();
}
void AstConfig::dumpJson(std::ostream& str) const {
dumpJsonStrFunc(str, configname);
if (libname() != "work") dumpJsonStr(str, "libname=", libname());
dumpJsonGen(str);
}
void AstConfigRule::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isCell()) str << " [CELL]";

View File

@ -91,6 +91,59 @@ void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFunc
//######################################################################
// Link state, as a visitor of each AstNode
// State to pass between config parsing and cell linking visitors.
struct LinkCellsState final {
// Set of possible top module names from command line and configs
std::unordered_set<std::string> m_topModuleNames;
};
class LinkConfigsVisitor final : public VNVisitor {
// STATE
LinkCellsState& m_state; // Context for linking cells
// VISITORS
void visit(AstConfig* nodep) override {
const string fullTopName = v3Global.opt.work() + '.' + v3Global.opt.topModule();
const bool topMatch = (fullTopName == nodep->name());
if (topMatch) {
m_state.m_topModuleNames.erase(fullTopName);
for (AstConfigCell* cellp = nodep->designp(); cellp;
cellp = VN_AS(cellp->nextp(), ConfigCell)) {
m_state.m_topModuleNames.insert(cellp->name());
}
}
// We don't do iterateChildren here because we want to skip designp
iterateAndNextNull(nodep->itemsp());
}
void visit(AstConfigCell* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config cell");
iterateChildren(nodep);
}
void visit(AstConfigRule* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config rule");
iterateChildren(nodep);
}
void visit(AstConfigUse* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config use");
iterateChildren(nodep);
}
void visit(AstNode* nodep) override { iterateChildren(nodep); }
public:
// CONSTRUCTORS
LinkConfigsVisitor(AstNetlist* nodep, LinkCellsState& state)
: m_state{state} {
// Initialize top module from command line option
if (!m_state.m_topModuleNames.size() && !v3Global.opt.topModule().empty()) {
const string fullTopName = v3Global.opt.work() + '.' + v3Global.opt.topModule();
m_state.m_topModuleNames.insert(fullTopName);
}
iterate(nodep);
}
};
class LinkCellsVisitor final : public VNVisitor {
// NODE STATE
// Entire netlist:
@ -105,6 +158,7 @@ class LinkCellsVisitor final : public VNVisitor {
// STATE
VInFilter* const m_filterp; // Parser filter
LinkCellsState& m_state; // State for linking cells
// Below state needs to be preserved between each module call.
AstNodeModule* m_modp = nullptr; // Current module
@ -245,7 +299,8 @@ class LinkCellsVisitor final : public VNVisitor {
if (VN_IS(nodep, Iface) || VN_IS(nodep, Package)) {
nodep->inLibrary(true); // Interfaces can't be at top, unless asked
}
const bool topMatch = (v3Global.opt.topModule() == nodep->prettyName());
const string fullName = nodep->libname() + "." + nodep->name();
const bool topMatch = (m_state.m_topModuleNames.count(fullName) > 0);
if (topMatch) {
m_topVertexp = vertex(nodep);
UINFO(2, "Link --top-module: " << nodep);
@ -603,23 +658,6 @@ class LinkCellsVisitor final : public VNVisitor {
iterateAndNextNull(nodep->attrsp());
}
void visit(AstConfig* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config");
iterateChildren(nodep);
}
void visit(AstConfigCell* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config cell");
iterateChildren(nodep);
}
void visit(AstConfigRule* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config rule");
iterateChildren(nodep);
}
void visit(AstConfigUse* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: config use");
iterateChildren(nodep);
}
void visit(AstNode* nodep) override { iterateChildren(nodep); }
// METHODS
@ -676,8 +714,9 @@ class LinkCellsVisitor final : public VNVisitor {
public:
// CONSTRUCTORS
LinkCellsVisitor(AstNetlist* nodep, VInFilter* filterp)
LinkCellsVisitor(AstNetlist* nodep, VInFilter* filterp, LinkCellsState& state)
: m_filterp{filterp}
, m_state{state}
, m_mods{nodep} {
if (v3Global.opt.hierChild()) {
const V3HierBlockOptSet& hierBlocks = v3Global.opt.hierBlocks();
@ -704,5 +743,8 @@ public:
void V3LinkCells::link(AstNetlist* nodep, VInFilter* filterp) {
UINFO(4, __FUNCTION__ << ": ");
{ LinkCellsVisitor{nodep, filterp}; }
// Configs must be parsed first because they determine the library search order for linking
LinkCellsState state;
{ LinkConfigsVisitor{nodep, state}; }
{ LinkCellsVisitor{nodep, filterp, state}; }
}

View File

@ -7783,8 +7783,9 @@ config_declaration: // == IEEE: config_declaration
yCONFIG idAny/*config_identifier*/ ';'
/*cont*/ configParameterListE design_statement config_rule_statementListE
/*cont*/ yENDCONFIG endLabelE
{ AstConfig* const newp = new AstConfig{$1, *$2, $4};
newp->addItemsp($5);
{ AstConfig* const newp = new AstConfig{$1, PARSEP->libname(), *$2};
newp->addDesignp($5);
newp->addItemsp($4);
newp->addItemsp($6);
GRAMMARP->endLabel($<fl>7, *$2, $8);
PARSEP->rootp()->addMiscsp(newp); }
@ -7805,7 +7806,7 @@ configParameter<nodep>: // IEEE: part of config_declaration
{ $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: config localparam declaration"); DEL($1); }
;
design_statement<nodep>: // == IEEE: design_statement
design_statement<configCellp>: // == IEEE: design_statement
yDESIGN configCellList ';' { $$ = $2; }
;
@ -7816,7 +7817,7 @@ configCellList<configCellp>: // IEEE: part of design_statement
configCell<configCellp>: // IEEE: part of design_statement, part of cell_clause
idAny/*cell_identifier*/
{ $$ = new AstConfigCell{$<fl>1, "", *$1}; }
{ $$ = new AstConfigCell{$<fl>1, PARSEP->libname(), *$1}; }
| idAny/*library_identifier*/ '.' idAny/*cell_identifier*/
{ $$ = new AstConfigCell{$<fl>1, *$1, *$3}; }
;

View File

@ -1,34 +1,16 @@
%Error-UNSUPPORTED: t/t_config_hier.v:34:1: Unsupported: config
34 | config cfg21;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_hier.v:35:10: Unsupported: config cell
35 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_hier.v:36:3: Unsupported: config rule
36 | instance t.u_1 use work.cfg2 :config;
| ^~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_hier.v:36:18: Unsupported: config use
36 | instance t.u_1 use work.cfg2 :config;
| ^~~
%Error-UNSUPPORTED: t/t_config_hier.v:39:1: Unsupported: config
39 | config cfg22;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:40:10: Unsupported: config cell
40 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_hier.v:41:3: Unsupported: config rule
41 | instance t.u_1 use cfg2 :config;
| ^~~~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:41:18: Unsupported: config use
41 | instance t.u_1 use cfg2 :config;
| ^~~
%Error-UNSUPPORTED: t/t_config_hier.v:44:1: Unsupported: config
44 | config cfg31;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:45:10: Unsupported: config cell
45 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_hier.v:46:3: Unsupported: config rule
46 | cell work.m1 use work.cfg2 :config;
| ^~~~
@ -38,12 +20,6 @@
%Error-UNSUPPORTED: t/t_config_hier.v:46:16: Unsupported: config use
46 | cell work.m1 use work.cfg2 :config;
| ^~~
%Error-UNSUPPORTED: t/t_config_hier.v:49:1: Unsupported: config
49 | config cfg32;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:50:10: Unsupported: config cell
50 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_hier.v:51:3: Unsupported: config rule
51 | cell m1 use cfg2 :config;
| ^~~~
@ -53,12 +29,6 @@
%Error-UNSUPPORTED: t/t_config_hier.v:51:11: Unsupported: config use
51 | cell m1 use cfg2 :config;
| ^~~
%Error-UNSUPPORTED: t/t_config_hier.v:54:1: Unsupported: config
54 | config cfg41;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:55:10: Unsupported: config cell
55 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_hier.v:56:3: Unsupported: config rule
56 | cell work.m1 use work.cfg2;
| ^~~~
@ -68,18 +38,10 @@
%Error-UNSUPPORTED: t/t_config_hier.v:56:16: Unsupported: config use
56 | cell work.m1 use work.cfg2;
| ^~~
%Error-UNSUPPORTED: t/t_config_hier.v:60:1: Unsupported: config
60 | config cfg2;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:61:10: Unsupported: config cell
61 | design c2_b;
| ^~~~
%Error-UNSUPPORTED: t/t_config_hier.v:62:3: Unsupported: config rule
62 | instance u_bb use work.c2_bb;
| ^~~~~~~~
%Error-UNSUPPORTED: t/t_config_hier.v:62:17: Unsupported: config use
62 | instance u_bb use work.c2_bb;
| ^~~
%Error: Specified --top-module 'cfg21' was not found in design.
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=['--binary', '--top cfg1'])
test.execute()
test.file_grep(test.run_log_filename, r"In 'm1'")
test.file_grep(test.run_log_filename, r"In 'm2'")
test.passes()

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// verilator lint_off MULTITOP
module m1;
initial $display("In '%m'");
endmodule
module m2;
initial $display("In '%m'");
endmodule
config cfg1;
design m1 m2;
endconfig : cfg1 // Test end label
// verilator lint_on MULTITOP

View File

@ -1,13 +1,7 @@
%Error-UNSUPPORTED: t/t_config_rules.v:24:1: Unsupported: config
24 | config cfg;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_rules.v:25:10: Unsupported: config cell
25 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_rules.v:28:3: Unsupported: config rule
28 | default liblist;
| ^~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_rules.v:29:3: Unsupported: config rule
29 | default liblist liba libb;
| ^~~~~~~
@ -74,6 +68,4 @@
%Error-UNSUPPORTED: t/t_config_rules.v:48:17: Unsupported: config use
48 | cell work.m43 use work.m43alt;
| ^~~
%Error: Specified --top-module 'cfg' was not found in design.
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -1,22 +0,0 @@
%Error-UNSUPPORTED: t/t_config_top.v:20:1: Unsupported: config
20 | config cfg1;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_top.v:21:10: Unsupported: config cell
21 | design m1;
| ^~
%Error-UNSUPPORTED: t/t_config_top.v:25:1: Unsupported: config
25 | config cfg2;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_top.v:26:10: Unsupported: config cell
26 | design m2;
| ^~
%Error-UNSUPPORTED: t/t_config_top.v:29:1: Unsupported: config
29 | config cfg3;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_top.v:30:10: Unsupported: config cell
30 | design work.m3;
| ^~~~
%Error: Specified --top-module 'cfg2' was not found in design.
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -11,6 +11,8 @@ import vltest_bootstrap
test.scenarios('simulator')
test.lint(verilator_flags2=["--top cfg2"], fails=True, expect_filename=test.golden_filename)
test.compile(verilator_flags2=['--binary', '--top cfg2'])
test.execute()
test.passes()

View File

@ -1,13 +0,0 @@
%Error-UNSUPPORTED: t/t_config_top2.v:21:1: Unsupported: config
21 | config cfg12;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_top2.v:22:10: Unsupported: config cell
22 | design work.m1 m2;
| ^~~~
%Error-UNSUPPORTED: t/t_config_top2.v:22:18: Unsupported: config cell
22 | design work.m1 m2;
| ^~
%Error: Specified --top-module 'cfg2' was not found in design.
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -11,6 +11,8 @@ import vltest_bootstrap
test.scenarios('simulator')
test.lint(verilator_flags2=["--top cfg2"], fails=True, expect_filename=test.golden_filename)
test.compile(verilator_flags2=['--binary', '--top cfg12'])
test.execute()
test.passes()

View File

@ -4,6 +4,7 @@
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// verilator lint_off MULTITOP
module m1;
initial begin
m2.fin;
@ -21,3 +22,4 @@ endmodule
config cfg12;
design work.m1 m2; // Test both modules listed, library.cell, and cell w/o library
endconfig
// verilator lint_on MULTITOP

View File

@ -1,13 +1,7 @@
%Error-UNSUPPORTED: t/t_config_unsup.v:24:1: Unsupported: config
24 | config cfg;
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_unsup.v:25:10: Unsupported: config cell
25 | design t;
| ^
%Error-UNSUPPORTED: t/t_config_unsup.v:28:3: Unsupported: config rule
28 | default liblist;
| ^~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_unsup.v:29:3: Unsupported: config rule
29 | default liblist liba libb;
| ^~~~~~~