mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Restrict VL_RESTORER to be usable only with trivially copyable types. Introduce VL_RESTORER_COPY and VL_RESTORER_CLEAR, which are more efficient versions usable for non trivially copyable types. VL_RESTORER_COPY semantically behaves the same as VL_RESTORER, but only does one copy at initialization, and on scope exit restores via a move. VL_RESTORER_CLEAR swaps the variable with an new one constructed via the no-args constructor (e.g. empty collection), which does not require any copying at any point. Static assertions enforce picking one of the new flavours when copying might be expensive.
108 lines
3.9 KiB
C++
108 lines
3.9 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Resolve module/signal name references
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
//*************************************************************************
|
|
//
|
|
// 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-FileCopyrightText: 2003-2026 Wilson Snyder
|
|
// 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_CLEAR(m_lib);
|
|
VL_RESTORER_CLEAR(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
|
|
explicit 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 << "'");
|
|
|
|
const 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}; }
|
|
}
|