diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c3b9f3e2..acc2eaf18 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -84,6 +84,7 @@ set(HEADERS V3DfgPeepholePatterns.h V3DfgVertices.h V3DiagSarif.h + V3DumpSignals.h V3DupFinder.h V3EmitC.h V3EmitCBase.h @@ -251,6 +252,7 @@ set(COMMON_SOURCES V3DfgRegularize.cpp V3DfgSynthesize.cpp V3DiagSarif.cpp + V3DumpSignals.cpp V3DupFinder.cpp V3EmitCBase.cpp V3EmitCConstPool.cpp diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 16725d2fd..939aee11b 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -269,6 +269,7 @@ RAW_OBJS_PCH_ASTNOMT = \ V3DfgRegularize.o \ V3DfgSynthesize.o \ V3DiagSarif.o \ + V3DumpSignals.o \ V3DupFinder.o \ V3EmitCMain.o \ V3EmitCMake.o \ diff --git a/src/V3DumpSignals.cpp b/src/V3DumpSignals.cpp new file mode 100644 index 000000000..bb792719b --- /dev/null +++ b/src/V3DumpSignals.cpp @@ -0,0 +1,117 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: +// +// 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 +// +//************************************************************************* +// +//************************************************************************* + +#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT + +#include "V3DumpSignals.h" + +#include "V3Global.h" + +#include +#include +#include + +VL_DEFINE_DEBUG_FUNCTIONS; +V3Global v3global; + +class DumpSignals final : public VNVisitor { + bool m_firstModuleNode = true; + bool m_foundCell = false; + string m_currHier; + std::ofstream m_signalFile; + + // Methods + void processVar(AstVar* varp) { + if (varp->basicp() && varp->basicp()->name() != "") { + bool hasRangep = varp->basicp()->rangep() != nullptr; + bool isSized = varp->basicp()->widthSized(); + if (hasRangep) { + std::string varHier = m_currHier + varp->name() + " : Type[" + varp->basicp()->name() + "] Width[" + std::to_string(varp->basicp()->rangep()->elementsConst()) + "]"; + m_signalFile << varHier << "\n"; + } else { + if (varp->basicp()->implicit()){ + // Since Var is implicit set the width to 1 like in V3Width.cpp in the AstVar visitor + std::string varHier = m_currHier + varp->name() + " : Type[" + varp->basicp()->name() + "] Width[" + std::to_string(1) + "]"; + m_signalFile << varHier << "\n"; + } else { + std::string varHier = m_currHier + varp->name() + " : Type[" + varp->basicp()->name() + "] Width[" + std::to_string(varp->basicp()->width()) + "]"; + m_signalFile << varHier << "\n"; + } + } + } + } + + void processChildrenNode(AstNode* nodep) { + for (AstNode* n = nodep->op2p(); n; n = n->nextp()) { + if (VN_IS(n, Var)) { + AstVar* varp = VN_AS(n, Var); + if (!varp->isParam() && !varp->isGenVar() && !varp->isIfaceRef() && !varp->isIfaceParent()) { + processVar(varp); + } + } else if (VN_IS(n, Cell)) { + if (VN_IS(VN_AS(n, Cell)->modp(), Module)) { + m_foundCell = true; + std::string oldHier = m_currHier; + m_currHier += n->name() + "."; + diveIntoCellModp(VN_AS(n, Cell)->modp()); + m_currHier = oldHier; + } + } + } + } + + void diveIntoCellModp(AstNodeModule* modp) { + processChildrenNode(modp); + } + + // VISITORS + void visit(AstModule* nodep) override { + if (m_firstModuleNode) { + m_currHier = nodep->name() + "."; + processChildrenNode(nodep); + m_firstModuleNode = false; + } + } + + //----------------- + void visit(AstNode* nodep) override { + iterateChildren(nodep); + } + +public: + explicit DumpSignals(AstNetlist* nodep) { + std::string filePath = v3global.opt.hierTopDataDir() + "/signalDump.log"; + m_signalFile.open(filePath); + iterate(nodep); + } + + ~DumpSignals() override { + if (m_signalFile.is_open()) { + m_signalFile.close(); + } + } +}; + +//################################################################################## +// DumpSignals class functions + +void V3DumpSignals::dumpSignals(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + { DumpSignals{nodep}; } + V3Global::dumpCheckGlobalTree("dumpSignals", 0, dumpTreeEitherLevel() >= 3); +} diff --git a/src/V3DumpSignals.h b/src/V3DumpSignals.h new file mode 100644 index 000000000..baf24f06c --- /dev/null +++ b/src/V3DumpSignals.h @@ -0,0 +1,32 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: +// +// 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_V3DUMPSIGNALS_H_ +#define VERILATOR_V3DUMPSIGNALS_H_ + +#include "config_build.h" +#include "verilatedos.h" + +class AstNetlist; + +//========================================================================= + +class V3DumpSignals final { +public: + static void dumpSignals(AstNetlist* nodep) VL_MT_DISABLED; +}; + +#endif // Guard diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 21429c9ab..78310680c 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1947,6 +1947,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, }); DECL_OPTION("-instrument", OnOff, &m_instrument); + DECL_OPTION("-dump-signals", OnOff, &m_dumpSignals); parser.finalize(); diff --git a/src/V3Options.h b/src/V3Options.h index dbafb4a52..39ac5fa85 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -250,6 +250,7 @@ private: bool m_decorationNodes = false; // main switch: --decoration=nodes bool m_diagnosticsSarif = false; // main switch: --diagnostics-sarif bool m_dpiHdrOnly = false; // main switch: --dpi-hdr-only + bool m_dumpSignals = false; // main switch: --dump-signals bool m_emitAccessors = false; // main switch: --emit-accessors bool m_exe = false; // main switch: --exe bool m_flatten = false; // main switch: --flatten @@ -529,6 +530,7 @@ public: bool diagnosticsSarif() const VL_MT_SAFE { return m_diagnosticsSarif; } bool dpiHdrOnly() const { return m_dpiHdrOnly; } bool dumpDefines() const { return m_dumpLevel.count("defines") && m_dumpLevel.at("defines"); } + bool dumpSignals() const { return m_dumpSignals; } bool dumpTreeDot() const { return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot"); } diff --git a/src/Verilator.cpp b/src/Verilator.cpp index ad17ed494..de0b3f2a1 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -45,6 +45,7 @@ #include "V3Descope.h" #include "V3DfgOptimizer.h" #include "V3DiagSarif.h" +#include "V3DumpSignals.h" #include "V3EmitC.h" #include "V3EmitCMain.h" #include "V3EmitCMake.h" @@ -153,6 +154,10 @@ static void process() { v3Global.vlExit(0); } + if (v3Global.opt.dumpSignals()) { + V3DumpSignals::dumpSignals(v3Global.rootp()); + } + // Instrument Design with the configurations given in .vlt file if (v3Global.opt.instrument()) { v3Global.dpi(true);