Support `-libmap` (#5891 partial) (#6764)

This commit is contained in:
Dan Ruelas-Petrisko 2025-12-16 08:21:46 -08:00 committed by GitHub
parent 66b3790444
commit 394d9cf168
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 454 additions and 101 deletions

View File

@ -419,6 +419,7 @@ detailed descriptions of these arguments.
--l2-name <value> Verilog scope name of the top module
--language <lang> Default language standard to parse
-LDFLAGS <flags> Linker pre-object arguments for makefile
-libmap Specify library mapping file
--lib-create <name> Create a DPI library
+libext+<ext>+[ext]... Extensions for finding modules
+librescan Ignored for compatibility

View File

@ -989,6 +989,11 @@ Summary:
"+libext+" is relatively standard across Verilog tools. Defaults to
".v+.sv".
.. option:: -libmap <lib.map>
Specifies library mapping file to sort modules into libraries. This can be
overridden by :vltopt:`-work`.
.. option:: +librescan
Ignored for compatibility with other simulators.

View File

@ -80,7 +80,8 @@ Verilator first reads all files provided on the command line and
:vlopt:`-f` files, and parses all modules within. Each module is assigned
to the most recent library specified with :vlopt:`-work`, thus `-work liba
a.v -work libb b.v` will assign modules in `a.v` to `liba` and modules in
`b.v` to `libb`.
`b.v` to `libb`. In the absence of a `-work` mapping, each module is optionally
assigned to a library based on mappings provided by :vlopt:`-libmap`.
If a module is not defined from a file on the command-line, Verilator
attempts to find a filename constructed from the module name using

View File

@ -290,6 +290,7 @@ set(COMMON_SOURCES
V3Inst.cpp
V3InstrCount.cpp
V3Interface.cpp
V3LibMap.cpp
V3Life.cpp
V3LifePost.cpp
V3LinkCells.cpp

View File

@ -287,6 +287,7 @@ RAW_OBJS_PCH_ASTNOMT = \
V3Inst.o \
V3InstrCount.o \
V3Interface.o \
V3LibMap.o \
V3Life.o \
V3LifePost.o \
V3LinkCells.o \

View File

@ -1125,6 +1125,23 @@ public:
string name() const override VL_MT_STABLE { return m_name; }
ASTGEN_MEMBERS_AstIntfRef;
};
class AstLibrary final : public AstNode {
// Parents: NETLIST
// Library declaration from lib.map file
// @astgen op1 := filesp : List[AstNodeExpr]
// @astgen op2 := incdirsp : List[AstNodeExpr]
std::string m_name; // Library name
public:
AstLibrary(FileLine* fl, const std::string& name, AstNodeExpr* filesp, AstNodeExpr* incdirsp)
: ASTGEN_SUPER_Library(fl)
, m_name{name} {
addFilesp(filesp);
addIncdirsp(incdirsp);
}
ASTGEN_MEMBERS_AstLibrary;
std::string name() const override VL_MT_STABLE { return m_name; }
};
class AstModport final : public AstNode {
// A modport in an interface
// @astgen op1 := varsp : List[AstNode]

View File

@ -22,8 +22,10 @@
#include "V3Error.h"
#include "V3File.h"
#include "V3HierBlock.h"
#include "V3LibMap.h"
#include "V3LinkCells.h"
#include "V3Parse.h"
#include "V3ParseImp.h"
#include "V3PreShell.h"
#include "V3Stats.h"
#include "V3ThreadPool.h"
@ -51,12 +53,14 @@ extern "C" const char* __asan_default_options() {
void V3Global::boot() {
UASSERT(!m_rootp, "call once");
m_rootp = new AstNetlist;
m_libMapp = new V3LibMap;
}
void V3Global::shutdown() {
V3PreShell::shutdown();
VL_DO_CLEAR(delete m_hierGraphp, m_hierGraphp = nullptr); // delete nullptr is safe
VL_DO_CLEAR(delete m_threadPoolp, m_threadPoolp = nullptr); // delete nullptr is safe
VL_DO_CLEAR(delete m_libMapp, m_libMapp = nullptr); // delete nullptr is safe
#ifdef VL_LEAK_CHECKS
if (m_rootp) VL_DO_CLEAR(m_rootp->deleteTree(), m_rootp = nullptr);
#endif
@ -84,26 +88,39 @@ void V3Global::readFiles() {
if (v3Global.opt.stdWaiver()) {
parser.parseFile(
new FileLine{V3Options::getStdWaiverPath()}, V3Options::getStdWaiverPath(), false,
"work", "Cannot find verilated_std_waiver.vlt containing built-in lint waivers: ");
false, "work",
"Cannot find verilated_std_waiver.vlt containing built-in lint waivers: ");
}
// Read .vlt files
for (const VFileLibName& filelib : v3Global.opt.vltFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
false, filelib.libname(), "Cannot find file containing .vlt file: ");
false, false, filelib.libname(),
"Cannot find file containing .vlt file: ");
}
// Parse the std package
if (v3Global.opt.stdPackage()) {
parser.parseFile(
new FileLine{V3Options::getStdPackagePath()}, V3Options::getStdPackagePath(),
false, "work",
false, false, "work",
"Cannot find verilated_std.sv containing built-in std:: definitions: ");
}
// Parse libmap files
for (const string& filename : v3Global.opt.libmapFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filename, false, true,
"work", "Cannot find file containing libmap definitions: ");
}
// Create library mapping
V3LibMap::map(v3Global.rootp());
// Read top module
for (const auto& filelib : v3Global.opt.vFiles()) {
const string& libname = filelib.libname() == "work"
? v3Global.libMapp()->matchMapping(filelib.filename())
: filelib.libname();
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
false, filelib.libname(), "Cannot find file containing module: ");
false, false, libname, "Cannot find file containing module: ");
}
// Read libraries
@ -111,14 +128,14 @@ void V3Global::readFiles() {
// this needs to be done after the top file is read
for (const auto& filelib : v3Global.opt.libraryFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
true, filelib.libname(),
true, false, filelib.libname(),
"Cannot find file containing library module: ");
}
// Read hierarchical type parameter file
for (const auto& filelib : v3Global.opt.hierParamFile()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
false, filelib.libname(),
false, false, filelib.libname(),
"Cannot open file containing hierarchical parameter declarations: ");
}
}

View File

@ -38,6 +38,7 @@
class AstNetlist;
class V3HierGraph;
class V3LibMap;
class V3ThreadPool;
//======================================================================
@ -103,6 +104,8 @@ class V3Global final {
V3HierGraph* m_hierGraphp = nullptr;
// Thread Pool, nullptr unless 'verilatedJobs' is known, set via threadPoolp(V3ThreadPool*)
V3ThreadPool* m_threadPoolp = nullptr;
// Library Mapping, nullptr unless --libmap is used
V3LibMap* m_libMapp = nullptr;
VWidthMinUsage m_widthMinUsage
= VWidthMinUsage::LINT_WIDTH; // What AstNode::widthMin() is used for
@ -152,6 +155,7 @@ public:
// ACCESSORS (general)
AstNetlist* rootp() const VL_MT_SAFE { return m_rootp; }
V3LibMap* libMapp() const VL_PURE { return m_libMapp; }
V3ThreadPool* threadPoolp() const VL_PURE { return m_threadPoolp; }
void threadPoolp(V3ThreadPool* threadPoolp) {
UASSERT(!m_threadPoolp, "attempted to create multiple threadPool singletons");

107
src/V3LibMap.cpp Normal file
View File

@ -0,0 +1,107 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Resolve module/signal name references
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-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
//
//*************************************************************************
// Visitor to build library mapping patterns from --libmap files, which may
// be overridden on command line with --work. Patterns are relative to
// libmap file location.
//*************************************************************************
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
#include "V3LibMap.h"
#include "V3Graph.h"
#include "V3Options.h"
#include "V3Os.h"
#include "V3Parse.h"
#include "V3SymTable.h"
#include <unordered_set>
#include <vector>
VL_DEFINE_DEBUG_FUNCTIONS;
class LibMapVisitor final : public VNVisitor {
// STATE
string m_lib; // Library currently being mapped
string m_rel; // Relative path of current libmap file
// VISITORS
void visit(AstParseRef* nodep) override {
if (!m_lib.empty()) {
const string& pattern = nodep->name();
v3Global.libMapp()->addPattern(pattern, m_lib, m_rel);
}
}
void visit(AstLibrary* nodep) override {
VL_RESTORER(m_lib);
VL_RESTORER(m_rel);
m_lib = nodep->name();
m_rel = V3Os::filenameDir(nodep->fileline()->filename());
iterateChildren(nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
void visit(AstNode* nodep) override { iterateChildren(nodep); }
public:
// CONSTRUCTORS
LibMapVisitor(AstNetlist* nodep) { iterate(nodep); }
};
//######################################################################
// LibMap class functions
string V3LibMap::matchMapping(const string& filename) {
// Check explicit mappings first
for (const auto& mapping : m_explicitMappings) {
const string& filepath = V3Os::filenameRelativePath(filename, mapping.base());
if (VString::wildmatch(filepath, mapping.pattern())) { return mapping.libname(); }
}
// Then check wildcard mappings
for (const auto& mapping : m_wildcardMappings) {
const string& filepath = V3Os::filenameRelativePath(filename, mapping.base());
if (VString::wildmatch(filepath, mapping.pattern())) { return mapping.libname(); }
}
// Then check directory mappings
for (const auto& mapping : m_directoryMappings) {
const string& filepath = V3Os::filenameRelativePath(filename, mapping.base());
const string& dirpart = V3Os::filenameDir(filepath);
if (VString::wildmatch(dirpart, mapping.pattern())) { return mapping.libname(); }
}
return "work";
}
void V3LibMap::addPattern(const string& pattern, const string& libname, const string& base) {
UINFO(4, __FUNCTION__ << ": pattern '" << pattern << "' => library '" << libname << "'");
bool isIncDir = pattern.back() == '/';
const string& nondir = V3Os::filenameNonDir(pattern);
const string& cleanPattern = V3Os::filenameCleanup(pattern);
if (isIncDir) {
m_directoryMappings.push_back({cleanPattern, libname, base});
} else if (nondir.find('*') != string::npos || nondir.find('?') != string::npos) {
m_wildcardMappings.push_back({cleanPattern, libname, base});
} else {
m_explicitMappings.push_back({cleanPattern, libname, base});
}
}
void V3LibMap::map(AstNetlist* nodep) {
UINFO(4, __FUNCTION__ << ": ");
{ LibMapVisitor{nodep}; }
}

67
src/V3LibMap.h Normal file
View File

@ -0,0 +1,67 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Link modules/signals together
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-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
//
//*************************************************************************
#ifndef VERILATOR_V3LIBMAP_H_
#define VERILATOR_V3LIBMAP_H_
#include "config_build.h"
#include "verilatedos.h"
#include <vector>
class AstNetlist;
class VInFilter;
class V3ParseSym;
//============================================================================
// State to pass between config parsing and cell linking visitors.
class LibMapping final {
const string m_pattern; // Pattern to match
const string m_libname; // Library name
const string m_base; // Relative path of the libmap file
public:
LibMapping(const string& pattern_, const string& libname_, const string& base_)
: m_pattern{pattern_}
, m_libname{libname_}
, m_base{base_} {}
string pattern() const { return m_pattern; }
string libname() const { return m_libname; }
string base() const { return m_base; }
};
class V3LibMap final {
private:
// STATE
// 33.3.1.1 File path resolution
// If a file name potentially matches multiple file path specifications, the path
// specifications shall be resolved in the following order: a) File path specifications that
// end with an explicit file name b) File path specifications that end with a wildcarded file
// name c) File path specifications that end with a directory name
std::vector<LibMapping> m_explicitMappings;
std::vector<LibMapping> m_wildcardMappings;
std::vector<LibMapping> m_directoryMappings;
// METHODS
public:
string matchMapping(const string& filename);
void addPattern(const string& pattern, const string& libname, const string& base);
static void map(AstNetlist* nodep) VL_MT_DISABLED;
};
#endif // Guard

View File

@ -310,7 +310,7 @@ class LinkCellsVisitor final : public VNVisitor {
const string prettyName = AstNode::prettyName(modName);
V3Parse parser{v3Global.rootp(), m_filterp};
// true below -> other simulators treat modules in link-found files as library cells
parser.parseFile(nodep->fileline(), prettyName, true, m_modp->libname(), "");
parser.parseFile(nodep->fileline(), prettyName, true, false, m_modp->libname(), "");
V3Error::abortIfErrors();
// We've read new modules, grab new pointers to their names
readModNames();

View File

@ -364,6 +364,7 @@ void V3Options::checkParameters() {
void V3Options::addCppFile(const string& filename) { m_cppFiles.insert(filename); }
void V3Options::addCFlags(const string& filename) { m_cFlags.push_back(filename); }
void V3Options::addLibMapFile(const string& filename) { m_libmapFiles.insert(filename); }
void V3Options::addCompilerIncludes(const string& filename) {
m_compilerIncludes.insert(filename);
}
@ -1559,6 +1560,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
};
DECL_OPTION("-default-language", CbVal, setLang).notForRerun();
DECL_OPTION("-language", CbVal, setLang).notForRerun();
DECL_OPTION("-libmap", CbVal, [this](const char* valp) { addLibMapFile(valp); });
DECL_OPTION("-lib-create", CbVal, [this, fl](const char* valp) {
validateIdentifier(fl, valp, "--lib-create");
m_libCreate = valp;

View File

@ -207,6 +207,7 @@ private:
VFileLibSet m_libraryFiles; // argument: Verilog -v files
VFileLibList m_vFiles; // argument: Verilog files to read
VFileLibSet m_vltFiles; // argument: Verilator config files to read
VStringSet m_libmapFiles; // argument: --libmap files to read
VStringList m_forceIncs; // argument: -FI
DebugLevelMap m_debugLevel; // argument: --debugi-<srcfile/tag> <level>
DebugLevelMap m_dumpLevel; // argument: --dumpi-<srcfile/tag> <level>
@ -469,6 +470,7 @@ public:
void addCompilerIncludes(const string& filename);
void addLdLibs(const string& filename);
void addMakeFlags(const string& filename);
void addLibMapFile(const string& filename);
void addLibraryFile(const string& filename, const string& libname);
void addVFile(const string& filename, const string& libname);
void addVltFile(const string& filename, const string& libname);
@ -679,6 +681,7 @@ public:
const VStringList& ldLibs() const { return m_ldLibs; }
const VStringList& makeFlags() const { return m_makeFlags; }
const VFileLibSet& libraryFiles() const { return m_libraryFiles; }
const VStringSet& libmapFiles() const { return m_libmapFiles; }
const VFileLibList& vFiles() const { return m_vFiles; }
const VFileLibSet& vltFiles() const { return m_vltFiles; }
const VStringList& forceIncs() const { return m_forceIncs; }

View File

@ -42,7 +42,7 @@ public:
// METHODS
// Preprocess and read the Verilog file specified into the netlist database
void parseFile(FileLine* fileline, const string& modname, bool inLibrary,
void parseFile(FileLine* fileline, const string& modname, bool inLibrary, bool inLibMap,
const string& libname, const string& errmsg) VL_MT_DISABLED;
// Push preprocessed text to the lexer

View File

@ -293,16 +293,18 @@ void V3ParseImp::preprocDumps(std::ostream& os, bool forInputs) {
}
void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
const string& libname,
bool inLibMap, const string& libname,
const string& errmsg) { // "" for no error, make fake node
const string nondirname = V3Os::filenameNonDir(modfilename);
const string modname = V3Os::filenameNonDirExt(modfilename);
UINFO(2, __FUNCTION__ << ": " << modname << (inLibrary ? " [LIB]" : ""));
UINFO(2, __FUNCTION__ << ": " << modname << (inLibrary ? " [LIB]" : "")
<< (inLibMap ? " [LIBMAP]" : ""));
m_lexFileline = new FileLine{fileline};
m_lexFileline->newContent();
m_bisonLastFileline = m_lexFileline;
m_inLibrary = inLibrary;
m_inLibMap = inLibMap;
m_libname = libname;
// Preprocess into m_ppBuffer
@ -823,9 +825,9 @@ V3Parse::V3Parse(AstNetlist* rootp, VInFilter* filterp) {
V3Parse::~V3Parse() { //
VL_DO_CLEAR(delete m_impp, m_impp = nullptr);
}
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary,
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary, bool inLibMap,
const string& libname, const string& errmsg) {
m_impp->parseFile(fileline, modname, inLibrary, libname, errmsg);
m_impp->parseFile(fileline, modname, inLibrary, inLibMap, libname, errmsg);
}
void V3Parse::ppPushText(V3ParseImp* impp, const string& text) {
if (text != "") impp->ppPushText(text);

View File

@ -151,6 +151,7 @@ class V3ParseImp final {
FileLine* m_bisonLastFileline = nullptr; // Filename/linenumber of last token
bool m_inLibrary = false; // Currently reading a library vs. regular file
bool m_inLibMap = false; // Currently reading a libmap file
string m_libname; // Config library name (or --work)
int m_lexKwdDepth = 0; // Inside a `begin_keywords
int m_lexKwdLast; // Last LEX state in `begin_keywords
@ -264,6 +265,7 @@ public:
// Return next token, for bison, since bison isn't class based, use a global THIS
AstNetlist* rootp() const { return m_rootp; }
bool inLibMap() const { return m_inLibMap; }
bool inLibrary() const { return m_inLibrary; }
string libname() const { return m_libname; }
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
@ -299,7 +301,7 @@ public:
// Preprocess and read the Verilog file specified into the netlist database
int tokenToBison() VL_MT_DISABLED; // Pass token to bison
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary, bool inLibMap,
const string& libname, const string& errmsg) VL_MT_DISABLED;
void dumpInputsFile() VL_MT_DISABLED;
void dumpTokensAhead(int line) VL_MT_DISABLED;

View File

@ -84,6 +84,7 @@ static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t, l)
%x QQQMODE
%x STRIFY
%x STRMODE
%x LIBMODE
/* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */
@ -119,6 +120,8 @@ bom [\357\273\277]
<INITIAL>"`ifdef" { FL_FWDC; return VP_IFDEF; }
<INITIAL>"`ifndef" { FL_FWDC; return VP_IFNDEF; }
<INITIAL>"`include" { FL_FWDC; return VP_INCLUDE; }
<INITIAL>"include" { FL_FWDC; yy_push_state(LIBMODE); return VP_TEXT; }
<INITIAL>"library" { FL_FWDC; yy_push_state(LIBMODE); return VP_TEXT; }
<INITIAL>"`undef" { FL_FWDC; return VP_UNDEF; }
<INITIAL>"`undefineall" { FL_FWDC; return VP_UNDEFINEALL; }
<INITIAL>"`error" { FL_FWDC; if (!pedantic()) return VP_ERROR; else return VP_DEFREF; }
@ -319,6 +322,14 @@ bom [\357\273\277]
<INCMODE>[\\]. { yymore(); }
<INCMODE>[\>] { FL_FWDC; yy_pop_state(); return VP_STRING; }
/* Library/config file paths */
<LIBMODE>{crnl} { FL_FWDC; linenoInc(); yytext=(char*)"\n"; yyleng=1; return VP_WHITE; }
<LIBMODE>{wsn}+ { FL_FWDC; return VP_WHITE; }
<LIBMODE>{quote} { yy_push_state(STRMODE); yymore(); }
<LIBMODE>"//" { yy_push_state(CMTONEM); yymore(); }
<LIBMODE>";" { FL_FWDC; yy_pop_state(); return VP_TEXT; }
<LIBMODE>. { FL_FWDC; return VP_TEXT; }
/* Reading definition formal parenthesis (or not) to begin formal arguments */
/* Note '(' must IMMEDIATELY follow definition name */
<DEFFPAR>[(] { FL_FWDC; appendDefValue("(", 1); LEXP->m_formalLevel=1;

View File

@ -65,6 +65,7 @@
#include "V3Inline.h"
#include "V3Inst.h"
#include "V3Interface.h"
#include "V3LibMap.h"
#include "V3Life.h"
#include "V3LifePost.h"
#include "V3LinkDot.h"

View File

@ -54,6 +54,12 @@
yylval.strp = PARSEP->newString(AstNode::encodeName(str)); \
} while (false)
#define STR_FILEPATH \
do { \
const string str(yytext, yyleng); \
yylval.strp = PARSEP->newString(str); \
} while (false)
#define ERROR_RSVD_WORD(language) \
do { \
yylval.fl->v3warn(E_UNSUPPORTED, "Unsupported: " << language \
@ -88,6 +94,7 @@ static double lexParseDouble(FileLine* fl, const char* textp, size_t length) {
%s ATTRMODE QQQ STRING TABLE EDGEDESC
%s VA5 SAX VLT
%s SYSCHDR SYSCHDRP SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
%x FILEPATH
ws [ \t\f\r]+
wsnr [ \t\f]+
@ -106,6 +113,17 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
<INITIAL>.|\n { BEGIN STATE_VERILOG_RECENT; yyless(0); }
/************************************************************************/
/* File paths */
<FILEPATH>{
{ws} { FL_FWD; FL_BRK; }
{crnl} { FL_FWD; FL_BRK; }
"-incdir" { FL; return yINCDIR; }
";" { yy_pop_state(); return ';'; }
"," { FL; return ','; }
[^ \t\n\r;,"]+ { FL; STR_FILEPATH; return yaSTRING; }
}
/************************************************************************/
/* Verilator control files */
<VLT>{
@ -461,15 +479,22 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"config" { FL; return yCONFIG; }
"design" { FL; return yDESIGN; }
"endconfig" { FL; return yENDCONFIG; }
"incdir" { FL; ERROR_RSVD_WORD("IEEE 1800-2001-config lib.map"); FL_BRK; }
"include" { FL; yylval.fl->v3warn(E_UNSUPPORTED, "Unsupported: IEEE 1800-2001-config lib.map"
" reserved word not implemented: 'include'\n"
<< yylval.fl->warnMore() << "... Suggest unless in a lib.map file,"
" want `include instead");
FL_BRK; }
"incdir" { FL; yy_push_state(FILEPATH); return yINCDIR; }
"include" { FL;
if (PARSEP->inLibMap()) {
yy_push_state(FILEPATH);
return yINCLUDE;
} else {
yylval.fl->v3warn(E_UNSUPPORTED, "Unsupported: IEEE 1800-2001-config lib.map"
" reserved word not implemented: 'include'\n"
<< yylval.fl->warnMore() << "... Suggest unless in a lib.map file,"
" want `include instead");
FL_BRK;
}
}
"instance" { FL; return yINSTANCE; }
"liblist" { FL; return yLIBLIST; }
"library" { FL; ERROR_RSVD_WORD("IEEE 1800-2001-config lib.map"); FL_BRK; }
"library" { FL; yy_push_state(FILEPATH); return yLIBRARY; }
"use" { FL; return yUSE; }
}

View File

@ -433,6 +433,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yIMPLEMENTS "implements"
%token<fl> yIMPLIES "implies"
%token<fl> yIMPORT "import"
%token<fl> yINCDIR "incdir"
%token<fl> yINCLUDE "include"
%token<fl> yINITIAL "initial"
%token<fl> yINOUT "inout"
%token<fl> yINPUT "input"
@ -448,6 +450,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yJOIN_NONE "join_none"
%token<fl> yLET "let"
%token<fl> yLIBLIST "liblist"
%token<fl> yLIBRARY "library"
%token<fl> yLOCALPARAM "localparam"
%token<fl> yLOCAL__COLONCOLON "local-then-::"
%token<fl> yLOCAL__ETC "local"
@ -1028,6 +1031,9 @@ descriptionList: // IEEE: part of source_text
description: // ==IEEE: description
module_declaration { }
// // udp_declaration moved into module_declaration
// // library_declaration and include_statement moved from library_description
| library_declaration { PARSEP->rootp()->addMiscsp($1); }
| include_statement { }
| interface_declaration { }
| program_declaration { }
| package_declaration { }
@ -7999,33 +8005,26 @@ colonConfigE<cbool>: // IEEE: [ ':' yCONFIG]
//**********************************************************************
// Config - lib.map
//
// TODO when implement this support, add -libmap option which takes multiple files.
//UNSUP library_text: // == IEEE: library_text (note is top-level entry point)
//UNSUP library_description { }
//UNSUP | library_text library_description { }
//UNSUP ;
//UNSUP library_description: // == IEEE: library_description
//UNSUP // // IEEE: library_declaration
//UNSUP yLIBRARY idAny/*library_identifier*/ file_path_specList ';'
//UNSUP { BBUNSUP($<fl>1, "Unsupported: config lib.map library"); }
//UNSUP yLIBRARY idAny/*library_identifier*/ file_path_specList '-' yINCDIR file_path_specList ';'
//UNSUP { BBUNSUP($<fl>1, "Unsupported: config lib.map library"); }
//UNSUP // // IEEE: include_statement
//UNSUP | yINCLUDE file_path_spec ';' { BBUNSUP($<fl>1, "Unsupported: config include"); }
//UNSUP | config_declaration { }
//UNSUP | ';' { }
//UNSUP ;
//UNSUP file_path_specList: // IEEE: file_path_spec { ',' file_path_spec }
//UNSUP file_path_spec { }
//UNSUP | file_path_specList ',' file_path_spec { }
//UNSUP ;
//UNSUP file_path_spec: // IEEE: file_path_spec
//UNSUP Needs to be lexer rule, Note '/' '*' must not be a comment.
//UNSUP ;
library_declaration<nodep>: // IEEE: library_declaration
yLIBRARY yaSTRING file_path_specList incdirE ';'
{ $$ = new AstLibrary{$<fl>1, *$2, $3, $4}; }
;
incdirE<nodeExprp>: // IEEE: [ '-' yINCDIR file_path_specList ';']
/* empty */ { $$ = nullptr; }
// https://accellera.mantishub.io/view.php?id=1166
| yINCDIR file_path_specList { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: config incdir"); }
;
include_statement<nodep>: // IEEE: include_statement
yINCLUDE file_path_spec ';' { $$ = nullptr; BBUNSUP($<fl>1, "Unsupported: config include"); }
;
file_path_specList<nodeExprp>: // IEEE: file_path_spec { ',' file_path_spec }
file_path_spec { $$ = $1; }
| file_path_specList ',' file_path_spec { $$ = addNextNull($1, $3); }
;
file_path_spec<nodeExprp>: // IEEE: file_path_spec
yaSTRING { $$ = new AstParseRef{$<fl>1, *$1}; }
;
//**********************************************************************
// VLT Files

View File

@ -1,31 +1,7 @@
%Error-UNSUPPORTED: t/t_config_libmap.map:9:1: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'include'
: ... Suggest unless in a lib.map file, want `include instead
9 | include ./t_config_libmap_inc.map
| ^~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: t/t_config_libmap.map:9:9: syntax error, unexpected '.'
9 | include ./t_config_libmap_inc.map
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error-UNSUPPORTED: t/t_config_libmap.map:11:1: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'library'
11 | library rtllib *.v;
| ^~~~~~~
%Error-UNSUPPORTED: t/t_config_libmap.map:12:1: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'library'
12 | library rtllib2 *.v, *.sv;
| ^~~~~~~
%Error-UNSUPPORTED: t/t_config_libmap.map:13:1: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'library'
13 | library rtllib3 *.v -incdir *.vh;
| ^~~~~~~
%Error-UNSUPPORTED: t/t_config_libmap.map:13:22: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'incdir'
13 | library rtllib3 *.v -incdir *.vh;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_libmap.map:14:1: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'library'
14 | library rtllib4 *.v -incdir *.vh, *.svh;
| ^~~~~~~
%Error-UNSUPPORTED: t/t_config_libmap.map:14:22: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'incdir'
14 | library rtllib4 *.v -incdir *.vh, *.svh;
| ^~~~~~
%Error-UNSUPPORTED: t/t_config_libmap.map:17:1: Unsupported: IEEE 1800-2001-config lib.map reserved word not implemented: 'library'
17 | library gatelib .
| ^~~~~~~
%Error: Exiting due to
*-* All Finished *-*
m1 %m=top.t.u_1 %l=rtllib.m1
m2 %m=top.t.u_2 %l=rtllib.m2
m3 %m=top.t.u_3 %l=gatelib.m3
m5 %m=top.t.u_5 %l=rtllib5.m5
other %m=top.t.u_o %l=rtllib2.other
x4 %m=top.t.u_4 %l=work.x4

View File

@ -9,10 +9,17 @@
import vltest_bootstrap
test.scenarios('linter')
test.scenarios('simulator')
test.lint(verilator_flags2=["t/" + test.name + ".map"],
fails=test.vlt_all,
expect_filename=test.golden_filename)
test.compile(verilator_flags2=[
"-libmap t/t_config_libmap/lib.map", "t/t_config_libmap/m1.v", "t/t_config_libmap/m2.sv",
"t/t_config_libmap/m3.vg", "t/t_config_libmap/m5.v", "t/t_config_libmap/x4.v",
"t/t_config_libmap/sub/other.sv", "--top-module cfg"
])
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()

View File

@ -5,8 +5,15 @@
// SPDX-License-Identifier: CC0-1.0
module t;
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
m1 u_1();
m2 u_2();
m3 u_3();
x4 u_4();
m5 u_5();
other u_o();
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -6,12 +6,10 @@
// SPDX-License-Identifier: CC0-1.0
// lib.map file:
include ./t_config_libmap_inc.map
library rtllib *.v;
library rtllib2 *.v, *.sv;
library rtllib3 *.v -incdir *.vh;
library rtllib4 *.v -incdir *.vh, *.svh;
library rtllib m?.v, m*.sv; // wildcard match (?, *)
library rtllib2 sub/; // include directory match
library rtllib5 m5.v; // explicit match
// Note this does not start a comment
library gatelib ./*.vg;

View File

@ -0,0 +1,9 @@
// 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 m1;
initial $display("m1 %%m=%m %%l=%l");
endmodule

View File

@ -0,0 +1,9 @@
// 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 m2;
initial $display("m2 %%m=%m %%l=%l");
endmodule

View File

@ -0,0 +1,9 @@
// 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 m3;
initial $display("m3 %%m=%m %%l=%l");
endmodule

View File

@ -0,0 +1,9 @@
// 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 m5;
initial $display("m5 %%m=%m %%l=%l");
endmodule

View File

@ -0,0 +1,9 @@
// 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 other;
initial $display("other %%m=%m %%l=%l");
endmodule

View File

@ -0,0 +1,9 @@
// 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 x4;
initial $display("x4 %%m=%m %%l=%l");
endmodule

View File

@ -6,13 +6,8 @@
// SPDX-License-Identifier: CC0-1.0
// lib.map file:
include ./t_config_libmap_inc.map
include ./t_config_libmap/lib.map;
library rtllib *.v;
library rtllib2 *.v, *.sv;
library rtllib3 *.v -incdir *.vh;
library rtllib4 *.v -incdir *.vh, *.svh;
config cfg;
design t;
endconfig
library rtllib1 somepath -incdir somedir;
library rtllib2 somewild*;
library rtllib3 someexplicit;

View File

@ -0,0 +1,8 @@
%Error-UNSUPPORTED: t/t_config_libmap_inc.map:9:1: Unsupported: config include
9 | include ./t_config_libmap/lib.map;
| ^~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_config_libmap_inc.map:11:26: Unsupported: config incdir
11 | library rtllib1 somepath -incdir somedir;
| ^~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/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.scenarios('linter')
test.lint(verilator_flags2=["--lint-only", "-libmap t/t_config_libmap_inc.map"],
fails=test.vlt_all,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,12 @@
// 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;
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,10 @@
// -*- Verilog -*-
// 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
// lib.map file:
library nonelib none.sv, none*.sv, none/; // no matches

View File

@ -12,7 +12,8 @@ import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=[
'--binary', '--work liba', 't/t_config_work__liba.v', '--work libb', 't/t_config_work__libb.v'
'--binary', '--work liba', 't/t_config_work__liba.v', '--work libb', 't/t_config_work__libb.v',
'-libmap t_config_work.map'
])
test.execute()