parent
66b3790444
commit
394d9cf168
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ set(COMMON_SOURCES
|
|||
V3Inst.cpp
|
||||
V3InstrCount.cpp
|
||||
V3Interface.cpp
|
||||
V3LibMap.cpp
|
||||
V3Life.cpp
|
||||
V3LifePost.cpp
|
||||
V3LinkCells.cpp
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3Inst.o \
|
||||
V3InstrCount.o \
|
||||
V3Interface.o \
|
||||
V3LibMap.o \
|
||||
V3Life.o \
|
||||
V3LifePost.o \
|
||||
V3LinkCells.o \
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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: ");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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}; }
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue