Support `--top` specifying `config` name (#6710)
This commit is contained in:
parent
00988aed70
commit
7edf6d4749
|
|
@ -38,7 +38,7 @@ Chuxuan Wang
|
|||
Chykon
|
||||
Congcong Cai
|
||||
Conor McCullough
|
||||
Dan Petrisko
|
||||
Dan Ruelas-Petrisko
|
||||
Daniel Bates
|
||||
Danny Oler
|
||||
Dave Sargeant
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]";
|
||||
|
|
|
|||
|
|
@ -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}; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}; }
|
||||
;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
| ^~~~~~~
|
||||
|
|
|
|||
Loading…
Reference in New Issue