mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Remove obsolete DepSet from output file names (#6564)
This commit is contained in:
+39
-186
@@ -27,128 +27,6 @@
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Visitor that gathers the headers required by an AstCFunc
|
||||
|
||||
class EmitCGatherDependencies final : VNVisitorConst {
|
||||
// Ordered set, as it is used as a key in another map.
|
||||
std::set<string> m_dependencies; // Header names to be included in output C++ file
|
||||
|
||||
// METHODS
|
||||
void addSymsDependency() { m_dependencies.insert(EmitCUtil::symClassName()); }
|
||||
void addModDependency(const AstNodeModule* modp) {
|
||||
if (const AstClass* const classp = VN_CAST(modp, Class)) {
|
||||
m_dependencies.insert(EmitCUtil::prefixNameProtect(classp->classOrPackagep()));
|
||||
} else {
|
||||
m_dependencies.insert(EmitCUtil::prefixNameProtect(modp));
|
||||
}
|
||||
}
|
||||
void addDTypeDependency(const AstNodeDType* nodep) {
|
||||
if (const AstClassRefDType* const dtypep = VN_CAST(nodep, ClassRefDType)) {
|
||||
m_dependencies.insert(
|
||||
EmitCUtil::prefixNameProtect(dtypep->classp()->classOrPackagep()));
|
||||
} else if (const AstNodeUOrStructDType* const dtypep
|
||||
= VN_CAST(nodep, NodeUOrStructDType)) {
|
||||
if (!dtypep->packed()) {
|
||||
UASSERT_OBJ(dtypep->classOrPackagep(), nodep, "Unlinked struct package");
|
||||
m_dependencies.insert(EmitCUtil::prefixNameProtect(dtypep->classOrPackagep()));
|
||||
}
|
||||
}
|
||||
}
|
||||
void addSelfDependency(VSelfPointerText selfPointer, AstNode* nodep) {
|
||||
if (selfPointer.isEmpty()) {
|
||||
// No self pointer (e.g.: function locals, const pool values, loose static methods),
|
||||
// so no dependency
|
||||
} else if (selfPointer.hasThis()) {
|
||||
// Dereferencing 'this', we need the definition of this module, which is also the
|
||||
// module that contains the variable.
|
||||
addModDependency(EmitCParentModule::get(nodep));
|
||||
} else {
|
||||
// Must be an absolute reference
|
||||
UASSERT_OBJ(selfPointer.isVlSym(), nodep,
|
||||
"Unknown self pointer: '" << selfPointer.asString() << "'");
|
||||
// Dereferencing vlSymsp, so we need it's definition...
|
||||
addSymsDependency();
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
void visit(AstCCall* nodep) override {
|
||||
addSelfDependency(nodep->selfPointer(), nodep->funcp());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstCNew* nodep) override {
|
||||
addSymsDependency();
|
||||
addDTypeDependency(nodep->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstCMethodCall* nodep) override {
|
||||
addDTypeDependency(nodep->fromp()->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstNewCopy* nodep) override {
|
||||
addSymsDependency();
|
||||
addDTypeDependency(nodep->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
addDTypeDependency(nodep->fromp()->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstStructSel* nodep) override {
|
||||
addDTypeDependency(nodep->fromp()->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
addSelfDependency(nodep->selfPointer(), nodep->varp());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstNodeCoverDecl* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstCoverInc* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstDumpCtl* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstScopeName* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstPrintTimeScale* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstTimeFormat* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstNodeSimpleText* nodep) override {
|
||||
if (nodep->text().find("vlSymsp") != string::npos) addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
||||
// CONSTRUCTOR
|
||||
explicit EmitCGatherDependencies(AstCFunc* cfuncp) {
|
||||
// Strictly speaking, for loose methods, we could get away with just a forward
|
||||
// declaration of the receiver class, but their body very likely includes at least one
|
||||
// relative reference, so we are probably not loosing much.
|
||||
addModDependency(EmitCParentModule::get(cfuncp));
|
||||
iterateConst(cfuncp);
|
||||
}
|
||||
|
||||
public:
|
||||
static const std::set<std::string> gather(AstCFunc* cfuncp) VL_MT_STABLE {
|
||||
const EmitCGatherDependencies visitor{cfuncp};
|
||||
return std::move(visitor.m_dependencies);
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Internal EmitC implementation
|
||||
|
||||
@@ -156,49 +34,41 @@ class EmitCImp final : EmitCFunc {
|
||||
// MEMBERS
|
||||
const AstNodeModule* const m_fileModp; // Files names/headers constructed using this module
|
||||
const bool m_slow; // Creating __Slow file
|
||||
const std::set<string>* m_requiredHeadersp; // Header files required by output file
|
||||
std::string m_subFileName; // substring added to output filenames
|
||||
V3UniqueNames m_uniqueNames; // For generating unique file names
|
||||
size_t m_nSplitFiles = 0; // Sequence number for file splitting
|
||||
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
|
||||
|
||||
// METHODS
|
||||
void openNextOutputFile(const std::set<string>& headers, const string& subFileName) {
|
||||
void openNextOutputFile(bool canBeSplit) {
|
||||
UASSERT(!ofp(), "Output file already open");
|
||||
|
||||
splitSizeReset(); // Reset file size tracking
|
||||
m_lazyDecls.reset(); // Need to emit new lazy declarations
|
||||
|
||||
AstCFile* filep = nullptr;
|
||||
V3OutCFile* ofilep = nullptr;
|
||||
if (v3Global.opt.lintOnly()) {
|
||||
// Unfortunately we have some lint checks here, so we can't just skip processing.
|
||||
// We should move them to a different stage.
|
||||
const string filename = VL_DEV_NULL;
|
||||
AstCFile* const filep = createCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
m_cfilesr.push_back(filep);
|
||||
V3OutCFile* const ofilep = new V3OutCFile{filename};
|
||||
setOutputFile(ofilep, filep);
|
||||
const std::string filename = VL_DEV_NULL;
|
||||
filep = createCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
ofilep = new V3OutCFile{filename};
|
||||
} else {
|
||||
string filename
|
||||
= v3Global.opt.makeDir() + "/" + EmitCUtil::prefixNameProtect(m_fileModp);
|
||||
if (!subFileName.empty()) {
|
||||
filename += "__" + subFileName;
|
||||
filename = m_uniqueNames.get(filename);
|
||||
}
|
||||
std::string filename = v3Global.opt.makeDir();
|
||||
filename += "/" + EmitCUtil::prefixNameProtect(m_fileModp);
|
||||
if (canBeSplit) filename += "__" + std::to_string(m_nSplitFiles++);
|
||||
if (m_slow) filename += "__Slow";
|
||||
filename += ".cpp";
|
||||
AstCFile* const filep = createCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
m_cfilesr.push_back(filep);
|
||||
V3OutCFile* const ofilep
|
||||
= v3Global.opt.systemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
|
||||
setOutputFile(ofilep, filep);
|
||||
filep = createCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
ofilep = v3Global.opt.systemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
|
||||
}
|
||||
m_cfilesr.push_back(filep);
|
||||
setOutputFile(ofilep, filep);
|
||||
|
||||
putsHeader();
|
||||
puts("// DESCRIPTION: Verilator output: Design implementation internals\n");
|
||||
puts("// See " + EmitCUtil::topClassName() + ".h for the primary calling header\n");
|
||||
|
||||
puts("\n");
|
||||
puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
|
||||
for (const string& name : headers) puts("#include \"" + name + ".h\"\n");
|
||||
|
||||
emitSystemCSection(m_modp, VSystemCSectionType::IMP_HDR);
|
||||
}
|
||||
@@ -305,7 +175,6 @@ class EmitCImp final : EmitCFunc {
|
||||
puts(modName + "__" + protect("_configure_coverage") + "(this, first);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
void emitCoverageImp() {
|
||||
// Rather than putting out VL_COVER_INSERT calls directly, we do it via this
|
||||
@@ -341,7 +210,6 @@ class EmitCImp final : EmitCFunc {
|
||||
puts(" \"comment\",commentp,");
|
||||
puts(" (linescovp[0] ? \"linescov\" : \"\"), linescovp);\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
if (v3Global.opt.coverageToggle()) {
|
||||
puts("\n// Toggle Coverage\n");
|
||||
@@ -386,7 +254,6 @@ class EmitCImp final : EmitCFunc {
|
||||
puts("}\n");
|
||||
puts("}\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
}
|
||||
void emitDestructorImp(const AstNodeModule* modp) {
|
||||
@@ -395,7 +262,6 @@ class EmitCImp final : EmitCFunc {
|
||||
+ "() {\n");
|
||||
emitSystemCSection(modp, VSystemCSectionType::DTOR);
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
void emitSavableImp(const AstNodeModule* modp) {
|
||||
if (v3Global.opt.savable()) {
|
||||
@@ -519,11 +385,7 @@ class EmitCImp final : EmitCFunc {
|
||||
= VN_IS(modp, ClassPackage) ? VN_AS(modp, ClassPackage)->classp() : nullptr;
|
||||
|
||||
if (hasCommonImp(modp) || hasCommonImp(classp)) {
|
||||
std::set<string> headers;
|
||||
headers.insert(EmitCUtil::prefixNameProtect(m_fileModp));
|
||||
headers.insert(EmitCUtil::symClassName());
|
||||
|
||||
openNextOutputFile(headers, "");
|
||||
openNextOutputFile(/* canBeSplit: */ false);
|
||||
|
||||
doCommonImp(modp);
|
||||
if (classp) {
|
||||
@@ -536,22 +398,19 @@ class EmitCImp final : EmitCFunc {
|
||||
}
|
||||
}
|
||||
void emitCFuncImp(const AstNodeModule* modp) {
|
||||
// Partition functions based on which module definitions they require, by building a
|
||||
// map from "AstNodeModules whose definitions are required" -> "functions that need
|
||||
// them"
|
||||
std::map<const std::set<string>, std::vector<AstCFunc*>> depSet2funcps;
|
||||
// Functions to be emitted here
|
||||
std::vector<AstCFunc*> funcps;
|
||||
|
||||
const auto gather = [this, &depSet2funcps](const AstNodeModule* modp) {
|
||||
const auto gather = [this, &funcps](const AstNodeModule* modp) {
|
||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstCFunc* const funcp = VN_CAST(nodep, CFunc)) {
|
||||
// TRACE_* and DPI handled elsewhere
|
||||
if (funcp->isTrace()) continue;
|
||||
if (funcp->dpiImportPrototype()) continue;
|
||||
if (funcp->dpiExportDispatcher()) continue;
|
||||
if (funcp->slow() != m_slow) continue;
|
||||
const auto& depSet = EmitCGatherDependencies::gather(funcp);
|
||||
depSet2funcps[depSet].push_back(funcp);
|
||||
}
|
||||
AstCFunc* const funcp = VN_CAST(nodep, CFunc);
|
||||
if (!funcp) continue;
|
||||
// TRACE_* and DPI handled elsewhere
|
||||
if (funcp->isTrace()) continue;
|
||||
if (funcp->dpiImportPrototype()) continue;
|
||||
if (funcp->dpiExportDispatcher()) continue;
|
||||
if (funcp->slow() != m_slow) continue;
|
||||
funcps.push_back(funcp);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -562,25 +421,19 @@ class EmitCImp final : EmitCFunc {
|
||||
gather(packagep->classp());
|
||||
}
|
||||
|
||||
// Emit all functions in each dependency set into separate files
|
||||
for (const auto& pair : depSet2funcps) {
|
||||
m_requiredHeadersp = &pair.first;
|
||||
// Compute the hash of the dependencies, so we can add it to the filenames to
|
||||
// disambiguate them
|
||||
V3Hash hash;
|
||||
for (const string& name : *m_requiredHeadersp) hash += name;
|
||||
m_subFileName = "DepSet_" + hash.toString();
|
||||
// Open output file
|
||||
openNextOutputFile(*m_requiredHeadersp, m_subFileName);
|
||||
// Emit functions in this dependency set
|
||||
for (AstCFunc* const funcp : pair.second) {
|
||||
VL_RESTORER(m_modp);
|
||||
m_modp = EmitCParentModule::get(funcp);
|
||||
iterateConst(funcp);
|
||||
}
|
||||
// Close output file
|
||||
closeOutputFile();
|
||||
// Do not create empty files
|
||||
if (funcps.empty()) return;
|
||||
|
||||
// Open output file
|
||||
openNextOutputFile(/* canBeSplit: */ true);
|
||||
// Emit all functions
|
||||
for (AstCFunc* const funcp : funcps) {
|
||||
VL_RESTORER(m_modp);
|
||||
m_modp = EmitCParentModule::get(funcp);
|
||||
iterateConst(funcp);
|
||||
}
|
||||
// Close output file
|
||||
closeOutputFile();
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
@@ -591,7 +444,7 @@ class EmitCImp final : EmitCFunc {
|
||||
// Close old file
|
||||
closeOutputFile();
|
||||
// Open a new file
|
||||
openNextOutputFile(*m_requiredHeadersp, m_subFileName);
|
||||
openNextOutputFile(/* canBeSplit: */ true);
|
||||
}
|
||||
|
||||
EmitCFunc::visit(nodep);
|
||||
|
||||
Reference in New Issue
Block a user