From 9346b98cb6df016c741937cb59c513383b0b0aa3 Mon Sep 17 00:00:00 2001 From: Dan Ruelas-Petrisko Date: Sat, 22 Nov 2025 17:17:17 -0800 Subject: [PATCH] Support `config` cell clauses (#6717) --- src/V3LinkCells.cpp | 57 ++++++++++++++++++++++------- test_regress/t/t_config_hier.out | 42 ++------------------- test_regress/t/t_config_liblist.out | 5 +++ test_regress/t/t_config_liblist.py | 24 ++++++++++++ test_regress/t/t_config_liblist.v | 19 ++++++++++ test_regress/t/t_config_rules.out | 55 ++++------------------------ test_regress/t/t_config_unsup.out | 55 ++++------------------------ 7 files changed, 110 insertions(+), 147 deletions(-) create mode 100644 test_regress/t/t_config_liblist.out create mode 100755 test_regress/t/t_config_liblist.py create mode 100644 test_regress/t/t_config_liblist.v diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 9e42b80c4..ef385919a 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -96,7 +96,11 @@ struct LinkCellsState final { // Set of possible top module names from command line and configs std::unordered_set m_topModuleNames; // Default library lists to search - std::vector m_liblist; + std::vector m_liblistDefault; + // Library lists for specific cells + std::unordered_map> m_liblistCell; + // Use list for specific cells (libname, cellname) + std::unordered_map>> m_uselistCell; }; class LinkConfigsVisitor final : public VNVisitor { @@ -119,23 +123,31 @@ class LinkConfigsVisitor final : public VNVisitor { VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } - void visit(AstConfigCell* nodep) override { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: config cell"); - iterateChildren(nodep); - } void visit(AstConfigRule* nodep) override { if (!nodep->cellp()) { for (AstNode* usep = nodep->usep(); usep; usep = usep->nextp()) { - m_state.m_liblist.push_back(usep->name()); + m_state.m_liblistDefault.push_back(usep->name()); + } + } else if (nodep->isCell()) { + string cellName = nodep->cellp()->name(); + if (VN_IS(nodep->usep(),ParseRef)) { + m_state.m_liblistCell[cellName] = std::vector{}; + for (AstParseRef* usep = VN_AS(nodep->usep(), ParseRef); usep; usep = VN_AS(usep->nextp(), ParseRef)) { + m_state.m_liblistCell[cellName].push_back(usep->name()); + } + } else { + m_state.m_uselistCell[cellName] = std::vector>{}; + for (AstConfigUse* usep = VN_AS(nodep->usep(), ConfigUse); usep; usep = VN_AS(usep->nextp(), ConfigUse)) { + m_state.m_uselistCell[cellName].push_back(std::pair{usep->libname(), usep->cellname()}); + } } } else { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: config cell rule"); + if (VN_IS(nodep->usep(),ParseRef)) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: config inst liblist rule"); + } else { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: config inst use rule"); + } } - iterateChildren(nodep); - } - void visit(AstConfigUse* nodep) override { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: config use"); - iterateChildren(nodep); } void visit(AstNode* nodep) override { iterateChildren(nodep); } @@ -206,9 +218,26 @@ class LinkCellsVisitor final : public VNVisitor { } AstNodeModule* findModuleSym(const string& modName, const string& libname) { // Given module and library to start search in, resolve using config library choices - // First search IEEE config library list AstNodeModule* foundp; - for (auto const& l : m_state.m_liblist) { + string fullName = libname + "." + modName; + // First search cell-specific use list + const auto itCellUseList = m_state.m_uselistCell.find(fullName); + if (itCellUseList != m_state.m_uselistCell.end()) { + for (auto const& u : itCellUseList->second) { + foundp = findModuleLibSym(u.second, u.first); + if (foundp) return foundp; + } + } + // Then search cell-specific library list + const auto itCellLibList = m_state.m_liblistCell.find(fullName); + if (itCellLibList != m_state.m_liblistCell.end()) { + for (auto const& l : itCellLibList->second) { + foundp = findModuleLibSym(modName, l); + if (foundp) return foundp; + } + } + // Then search IEEE config default liblist + for (auto const& l : m_state.m_liblistDefault) { foundp = findModuleLibSym(modName, l); if (foundp) return foundp; } diff --git a/test_regress/t/t_config_hier.out b/test_regress/t/t_config_hier.out index f7dd707b9..68c76c0c4 100644 --- a/test_regress/t/t_config_hier.out +++ b/test_regress/t/t_config_hier.out @@ -1,47 +1,11 @@ -%Error-UNSUPPORTED: t/t_config_hier.v:36:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_hier.v:36:3: Unsupported: config inst use 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:41:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_hier.v:41:3: Unsupported: config inst use 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:46:3: Unsupported: config cell rule - 46 | cell work.m1 use work.cfg2 :config; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_hier.v:46:8: Unsupported: config cell - 46 | cell work.m1 use work.cfg2 :config; - | ^~~~ -%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:51:3: Unsupported: config cell rule - 51 | cell m1 use cfg2 :config; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_hier.v:51:8: Unsupported: config cell - 51 | cell m1 use cfg2 :config; - | ^~ -%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:56:3: Unsupported: config cell rule - 56 | cell work.m1 use work.cfg2; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_hier.v:56:8: Unsupported: config cell - 56 | cell work.m1 use work.cfg2; - | ^~~~ -%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:62:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_hier.v:62:3: Unsupported: config inst use 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: Exiting due to diff --git a/test_regress/t/t_config_liblist.out b/test_regress/t/t_config_liblist.out new file mode 100644 index 000000000..0df8def65 --- /dev/null +++ b/test_regress/t/t_config_liblist.out @@ -0,0 +1,5 @@ +*-* All Finished *-* +liba:m1 %m=t.u_1 %l=liba.m1 +liba:m3 %m=t.u_2.u_23 %l=liba.m3 +libb:m2 %m=t.u_2 %l=libb.m2 +libb:m3 %m=t.u_1.u_13 %l=libb.m3 diff --git a/test_regress/t/t_config_liblist.py b/test_regress/t/t_config_liblist.py new file mode 100755 index 000000000..628079b8b --- /dev/null +++ b/test_regress/t/t_config_liblist.py @@ -0,0 +1,24 @@ +#!/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', '--work liba', 't/t_config_work__liba.v', '--work libb', + 't/t_config_work__libb.v' +]) + +test.execute() + +# Sort so that 'initial' scheduling order is not relevant +test.files_identical_sorted(test.run_log_filename, test.golden_filename, is_logfile=True) + +test.passes() diff --git a/test_regress/t/t_config_liblist.v b/test_regress/t/t_config_liblist.v new file mode 100644 index 000000000..3d131145a --- /dev/null +++ b/test_regress/t/t_config_liblist.v @@ -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 + +module t; + // Test config allows selecting two different libraries for these instances + m1 u_1(); + m2 u_2(); + final $write("*-* All Finished *-*\n"); +endmodule + +config cfg1; + design t; + // Use libb's version of m3 for m1 and liba's version of m3 for m2 + cell liba.m3 liblist libb; + cell libb.m3 use liba.m3; +endconfig diff --git a/test_regress/t/t_config_rules.out b/test_regress/t/t_config_rules.out index a23367a98..a8fab7a2c 100644 --- a/test_regress/t/t_config_rules.out +++ b/test_regress/t/t_config_rules.out @@ -1,65 +1,26 @@ -%Error-UNSUPPORTED: t/t_config_rules.v:33:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:33:3: Unsupported: config inst use rule 33 | instance t.m20 liblist; | ^~~~~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_config_rules.v:34:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:34:3: Unsupported: config inst liblist rule 34 | instance t.m21 liblist libc; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:35:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:35:3: Unsupported: config inst liblist rule 35 | instance t.m22 liblist libc libd; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:36:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:36:3: Unsupported: config inst liblist rule 36 | instance t.m23 liblist libc libd; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:37:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:37:3: Unsupported: config inst liblist rule 37 | instance t.m24 liblist libc libd; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:40:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:40:3: Unsupported: config inst use rule 40 | instance t.m30 use cell_identifier; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:40:18: Unsupported: config use - 40 | instance t.m30 use cell_identifier; - | ^~~ -%Error-UNSUPPORTED: t/t_config_rules.v:41:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:41:3: Unsupported: config inst use rule 41 | instance t.m31 use lib_id.cell_id; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:41:18: Unsupported: config use - 41 | instance t.m31 use lib_id.cell_id; - | ^~~ -%Error-UNSUPPORTED: t/t_config_rules.v:42:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_rules.v:42:3: Unsupported: config inst use rule 42 | instance t.m32 use #(); | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:42:18: Unsupported: config use - 42 | instance t.m32 use #(); - | ^~~ -%Error-UNSUPPORTED: t/t_config_rules.v:45:3: Unsupported: config cell rule - 45 | cell m40 liblist libc libd; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:45:8: Unsupported: config cell - 45 | cell m40 liblist libc libd; - | ^~~ -%Error-UNSUPPORTED: t/t_config_rules.v:46:3: Unsupported: config cell rule - 46 | cell work.m41 liblist libc libd; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:46:8: Unsupported: config cell - 46 | cell work.m41 liblist libc libd; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:47:3: Unsupported: config cell rule - 47 | cell m42 use m42alt; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:47:8: Unsupported: config cell - 47 | cell m42 use m42alt; - | ^~~ -%Error-UNSUPPORTED: t/t_config_rules.v:47:12: Unsupported: config use - 47 | cell m42 use m42alt; - | ^~~ -%Error-UNSUPPORTED: t/t_config_rules.v:48:3: Unsupported: config cell rule - 48 | cell work.m43 use work.m43alt; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:48:8: Unsupported: config cell - 48 | cell work.m43 use work.m43alt; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_rules.v:48:17: Unsupported: config use - 48 | cell work.m43 use work.m43alt; - | ^~~ %Error: Exiting due to diff --git a/test_regress/t/t_config_unsup.out b/test_regress/t/t_config_unsup.out index bcce01176..ac5ece905 100644 --- a/test_regress/t/t_config_unsup.out +++ b/test_regress/t/t_config_unsup.out @@ -1,65 +1,26 @@ -%Error-UNSUPPORTED: t/t_config_unsup.v:32:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:32:3: Unsupported: config inst use rule 32 | instance t.m20 liblist; | ^~~~~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_config_unsup.v:33:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:33:3: Unsupported: config inst liblist rule 33 | instance t.m21 liblist libc; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:34:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:34:3: Unsupported: config inst liblist rule 34 | instance t.m22 liblist libc libd; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:35:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:35:3: Unsupported: config inst liblist rule 35 | instance t.m23 liblist libc libd; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:36:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:36:3: Unsupported: config inst liblist rule 36 | instance t.m24 liblist libc libd; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:39:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:39:3: Unsupported: config inst use rule 39 | instance t.m30 use cell_identifier; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:39:18: Unsupported: config use - 39 | instance t.m30 use cell_identifier; - | ^~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:40:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:40:3: Unsupported: config inst use rule 40 | instance t.m31 use lib_id.cell_id; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:40:18: Unsupported: config use - 40 | instance t.m31 use lib_id.cell_id; - | ^~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:41:3: Unsupported: config cell rule +%Error-UNSUPPORTED: t/t_config_unsup.v:41:3: Unsupported: config inst use rule 41 | instance t.m32 use #(); | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:41:18: Unsupported: config use - 41 | instance t.m32 use #(); - | ^~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:44:3: Unsupported: config cell rule - 44 | cell m40 liblist libc libd; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:44:8: Unsupported: config cell - 44 | cell m40 liblist libc libd; - | ^~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:45:3: Unsupported: config cell rule - 45 | cell work.m41 liblist libc libd; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:45:8: Unsupported: config cell - 45 | cell work.m41 liblist libc libd; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:46:3: Unsupported: config cell rule - 46 | cell m42 use m42alt; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:46:8: Unsupported: config cell - 46 | cell m42 use m42alt; - | ^~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:46:12: Unsupported: config use - 46 | cell m42 use m42alt; - | ^~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:47:3: Unsupported: config cell rule - 47 | cell work.m43 use work.m43alt; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:47:8: Unsupported: config cell - 47 | cell work.m43 use work.m43alt; - | ^~~~ -%Error-UNSUPPORTED: t/t_config_unsup.v:47:17: Unsupported: config use - 47 | cell work.m43 use work.m43alt; - | ^~~ %Error: Exiting due to