Internals: Refactor file handling in EmitC* (#6667)
Combined the 3 various APIs used in EmitC* passes to handle file opening/splitting into a single one. This removes a lot of copy paste and makes everything consistent. All C++ file handling goes through `EmitCBaseVisitor` using the `openNewOutputHeaderFile`, `openNewOutputSourceFile` and `closOutputFile` methods. To emit a new kind of file, always derive a new class from `EmitCBaseVisitor`, and use the above APIs, they will take care of everything else in a consistent matter. Subsequently also removed V3OutSCFile, and instead included verilated_sc.h (which included the systemc header itself) in the two files that need it (the primary model header, and the root module header). Functional changes: - The PCH header did not use to have a corresponding AstCFile. Now it does, though this makes no difference in the output - All 'slow' sources now have '__Slow' in the name automatically (the only one missing was for the ConstPool files) Rest of the output is identical except for the header line now being present in all generated C++ files.
This commit is contained in:
parent
aaafa6e8df
commit
f4086496cb
|
|
@ -92,21 +92,6 @@ string EmitCBaseVisitorConst::funcNameProtect(const AstCFunc* nodep, const AstNo
|
|||
return name;
|
||||
}
|
||||
|
||||
AstCFile* EmitCBaseVisitorConst::newCFile(const string& filename, bool slow, bool source) {
|
||||
AstCFile* const cfilep = createCFile(filename, slow, source);
|
||||
v3Global.rootp()->addFilesp(cfilep);
|
||||
return cfilep;
|
||||
}
|
||||
|
||||
AstCFile* EmitCBaseVisitorConst::createCFile(const string& filename, bool slow,
|
||||
bool source) VL_MT_SAFE {
|
||||
AstCFile* const cfilep = new AstCFile{v3Global.rootp()->fileline(), filename};
|
||||
cfilep->slow(slow);
|
||||
cfilep->source(source);
|
||||
if (source) V3Stats::addStatSum(V3Stats::STAT_CPP_FILES, 1);
|
||||
return cfilep;
|
||||
}
|
||||
|
||||
string EmitCBaseVisitorConst::cFuncArgs(const AstCFunc* nodep) {
|
||||
// Return argument list for given C function
|
||||
string args;
|
||||
|
|
|
|||
|
|
@ -85,40 +85,89 @@ public:
|
|||
// Base Visitor class -- holds output file pointer
|
||||
|
||||
class EmitCBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
public:
|
||||
// STATE
|
||||
V3OutCFile* m_ofp = nullptr;
|
||||
AstCFile* m_outFileNodep = nullptr;
|
||||
int m_splitSize = 0; // # of cfunc nodes placed into output file
|
||||
V3OutCFile* m_ofp = nullptr; // File handle to emit to
|
||||
AstCFile* m_cfilep = nullptr; // Current AstCFile being emitted
|
||||
std::vector<AstCFile*> m_newCfileps; // AstCFiles created
|
||||
size_t m_splitSize = 0; // Complexity of this file
|
||||
const size_t m_splitLimit = v3Global.opt.outputSplit()
|
||||
? static_cast<size_t>(v3Global.opt.outputSplit())
|
||||
: std::numeric_limits<size_t>::max();
|
||||
|
||||
// METHODS
|
||||
|
||||
// Create new AstCFile and open it for writing
|
||||
void openNewOutputFile(const std::string& baseName, bool slow, bool support, bool source,
|
||||
const char* const descriptionp) {
|
||||
std::string fileName = v3Global.opt.makeDir() + "/" + baseName;
|
||||
if (source) {
|
||||
if (slow) fileName += "__Slow";
|
||||
fileName += ".cpp";
|
||||
} else {
|
||||
fileName += ".h";
|
||||
}
|
||||
AstCFile* const cfilep = new AstCFile{v3Global.rootp()->fileline(), fileName};
|
||||
cfilep->slow(slow);
|
||||
cfilep->source(source);
|
||||
cfilep->support(support);
|
||||
m_newCfileps.emplace_back(cfilep);
|
||||
openOutputFile(cfilep, descriptionp);
|
||||
}
|
||||
|
||||
public:
|
||||
// Create new source AstCFile and open it for writing
|
||||
void openNewOutputSourceFile(const std::string& baseName, bool slow, bool support,
|
||||
const char* descriptionp) {
|
||||
V3Stats::addStatSum(V3Stats::STAT_CPP_FILES, 1);
|
||||
openNewOutputFile(baseName, slow, support, true, descriptionp);
|
||||
}
|
||||
|
||||
// Create new header AstCFile and open it for writing
|
||||
void openNewOutputHeaderFile(const std::string& baseName, const char* descriptionp) {
|
||||
openNewOutputFile(baseName, false, false, false, descriptionp);
|
||||
}
|
||||
|
||||
// Open exisitng AstCFile for writing
|
||||
void openOutputFile(AstCFile* cfilep, const char* descriptionp) {
|
||||
UASSERT(!m_ofp, "Output file is already open");
|
||||
m_cfilep = cfilep;
|
||||
m_splitSize = 0;
|
||||
if (v3Global.opt.lintOnly()) {
|
||||
// Unfortunately we have some lint checks in EmitCImp, so we can't
|
||||
// just skip processing. TODO: Move them to an earlier stage.
|
||||
m_ofp = new V3OutCFile{VL_DEV_NULL};
|
||||
return;
|
||||
}
|
||||
m_ofp = new V3OutCFile{cfilep->name()};
|
||||
putsHeader();
|
||||
// Emit description
|
||||
m_ofp->putsNoTracking("// DESCR" /* keep this comment */ "IPTION: Verilator output: ");
|
||||
m_ofp->putsNoTracking(descriptionp);
|
||||
m_ofp->putsNoTracking("\n");
|
||||
}
|
||||
|
||||
// Close current output file. Sets ofp() and outFileNodep() to nullptr.
|
||||
void closeOutputFile() {
|
||||
UASSERT(m_ofp, "No currently open output file");
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
m_cfilep->complexityScore(m_splitSize);
|
||||
m_cfilep = nullptr;
|
||||
}
|
||||
|
||||
std::vector<AstCFile*> getAndClearCfileps() {
|
||||
UASSERT(!m_ofp, "Output file is open");
|
||||
return std::move(m_newCfileps);
|
||||
}
|
||||
|
||||
void splitSizeInc(size_t count) { m_splitSize += count; }
|
||||
void splitSizeInc(const AstNode* nodep) {
|
||||
splitSizeInc(static_cast<size_t>(nodep->nodeCount()));
|
||||
}
|
||||
bool splitNeeded(size_t splitLimit) const { return m_splitSize >= splitLimit; }
|
||||
bool splitNeeded() const { return splitNeeded(m_splitLimit); }
|
||||
|
||||
// Returns pointer to current output file object.
|
||||
V3OutCFile* ofp() const VL_MT_SAFE { return m_ofp; }
|
||||
// Returns pointer to the AST node that represents the output file (`ofp()`)
|
||||
AstCFile* outFileNodep() const VL_MT_SAFE { return m_outFileNodep; }
|
||||
|
||||
// Sets ofp() and outFileNodep() to the given pointers, without closing a file these pointers
|
||||
// currently point to.
|
||||
void setOutputFile(V3OutCFile* ofp, AstCFile* nodep) {
|
||||
// cppcheck-suppress danglingLifetime // ofp is often on stack in caller, it's fine.
|
||||
m_ofp = ofp;
|
||||
m_outFileNodep = nodep;
|
||||
}
|
||||
|
||||
// Sets ofp() and outFileNodep() to null, without closing a file these pointers currently point
|
||||
// to. NOTE: Dummy nullptr argument is taken to make function calls more explicit.
|
||||
void setOutputFile(std::nullptr_t nullp) {
|
||||
UASSERT(nullp == nullptr, "Expected nullptr as the argument");
|
||||
m_ofp = nullp;
|
||||
m_outFileNodep = nullp;
|
||||
}
|
||||
|
||||
// Closes current output file. Sets ofp() and outFileNodep() to nullptr.
|
||||
void closeOutputFile() {
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
m_outFileNodep->complexityScore(m_splitSize);
|
||||
m_outFileNodep = nullptr;
|
||||
}
|
||||
|
||||
void puts(const string& str) { ofp()->puts(str); }
|
||||
void putns(const AstNode* nodep, const string& str) { ofp()->putns(nodep, str); }
|
||||
|
|
@ -133,8 +182,6 @@ public:
|
|||
bool optSystemC() { return v3Global.opt.systemC(); }
|
||||
static string protect(const string& name) VL_MT_SAFE { return VIdProtect::protect(name); }
|
||||
static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp = nullptr);
|
||||
static AstCFile* newCFile(const string& filename, bool slow, bool source);
|
||||
static AstCFile* createCFile(const string& filename, bool slow, bool source) VL_MT_SAFE;
|
||||
string cFuncArgs(const AstCFunc* nodep);
|
||||
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
|
||||
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
|
||||
|
|
@ -163,7 +210,11 @@ public:
|
|||
|
||||
// CONSTRUCTORS
|
||||
EmitCBaseVisitorConst() = default;
|
||||
~EmitCBaseVisitorConst() override = default;
|
||||
~EmitCBaseVisitorConst() override {
|
||||
UASSERT(!m_ofp, "Did not close output file");
|
||||
// Add files cerated to the netlist (unless retrieved before destruction)
|
||||
for (AstCFile* const cfilep : m_newCfileps) v3Global.rootp()->addFilesp(cfilep);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "V3EmitCConstInit.h"
|
||||
#include "V3File.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
|
|
@ -34,40 +35,15 @@ class EmitCConstPool final : public EmitCConstInit {
|
|||
using OutCFilePair = std::pair<V3OutCFile*, AstCFile*>;
|
||||
|
||||
// MEMBERS
|
||||
uint32_t m_outFileCount = 0;
|
||||
int m_outFileSize = 0;
|
||||
VDouble0 m_tablesEmitted;
|
||||
VDouble0 m_constsEmitted;
|
||||
V3UniqueNames m_uniqueNames; // Generates unique file names
|
||||
const std::string m_fileBaseName = EmitCUtil::topClassName() + "__ConstPool";
|
||||
|
||||
// METHODS
|
||||
|
||||
OutCFilePair newOutCFile() const {
|
||||
const string fileName = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName()
|
||||
+ "__ConstPool_" + cvtToStr(m_outFileCount) + ".cpp";
|
||||
AstCFile* const cfilep = newCFile(fileName, /* slow: */ true, /* source: */ true);
|
||||
V3OutCFile* const ofp = new V3OutCFile{fileName};
|
||||
ofp->putsHeader();
|
||||
ofp->puts("// DESCRIPTION: Verilator output: Constant pool\n");
|
||||
ofp->puts("//\n");
|
||||
ofp->puts("\n");
|
||||
ofp->puts("#include \"verilated.h\"\n");
|
||||
return {ofp, cfilep};
|
||||
}
|
||||
|
||||
void maybeSplitCFile() {
|
||||
if (v3Global.opt.outputSplit() && m_outFileSize < v3Global.opt.outputSplit()) return;
|
||||
// Splitting file, so using parallel build.
|
||||
v3Global.useParallelBuild(true);
|
||||
// Close current file
|
||||
closeOutputFile();
|
||||
// Open next file
|
||||
m_outFileSize = 0;
|
||||
++m_outFileCount;
|
||||
const OutCFilePair outFileAndNodePair = newOutCFile();
|
||||
setOutputFile(outFileAndNodePair.first, outFileAndNodePair.second);
|
||||
}
|
||||
|
||||
void emitVars(const AstConstPool* poolp) {
|
||||
UASSERT(!ofp(), "Output file should not be open");
|
||||
|
||||
std::vector<const AstVar*> varps;
|
||||
for (AstNode* nodep = poolp->modp()->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (const AstVar* const varp = VN_CAST(nodep, Var)) varps.push_back(varp);
|
||||
|
|
@ -79,12 +55,22 @@ class EmitCConstPool final : public EmitCConstInit {
|
|||
return ap->name() < bp->name();
|
||||
});
|
||||
|
||||
const OutCFilePair outFileAndNodePair = newOutCFile();
|
||||
setOutputFile(outFileAndNodePair.first, outFileAndNodePair.second);
|
||||
|
||||
for (const AstVar* varp : varps) {
|
||||
maybeSplitCFile();
|
||||
const string nameProtect
|
||||
if (splitNeeded()) {
|
||||
// Splitting file, so using parallel build.
|
||||
v3Global.useParallelBuild(true);
|
||||
// Close old file
|
||||
closeOutputFile();
|
||||
}
|
||||
|
||||
if (!ofp()) {
|
||||
openNewOutputSourceFile(m_uniqueNames.get(m_fileBaseName), true, false,
|
||||
"Constant pool");
|
||||
puts("\n");
|
||||
puts("#include \"verilated.h\"\n");
|
||||
}
|
||||
|
||||
const std::string nameProtect
|
||||
= EmitCUtil::topClassName() + "__ConstPool__" + varp->nameProtect();
|
||||
puts("\n");
|
||||
putns(varp, "extern const ");
|
||||
|
|
@ -101,12 +87,18 @@ class EmitCConstPool final : public EmitCConstInit {
|
|||
}
|
||||
}
|
||||
|
||||
closeOutputFile();
|
||||
if (ofp()) closeOutputFile();
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
void visit(AstConst* nodep) override {
|
||||
m_outFileSize += nodep->num().isString() ? 10 : nodep->isWide() ? nodep->widthWords() : 1;
|
||||
if (nodep->num().isString()) {
|
||||
splitSizeInc(AstNode::INSTR_COUNT_STR);
|
||||
} else if (nodep->isWide()) {
|
||||
splitSizeInc(nodep->widthWords());
|
||||
} else {
|
||||
splitSizeInc(1);
|
||||
}
|
||||
EmitCConstInit::visit(nodep);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class EmitCFunc VL_NOT_FINAL : public EmitCConstInit {
|
|||
} m_emitDispState;
|
||||
|
||||
protected:
|
||||
EmitCLazyDecls m_lazyDecls; // Visitor for emitting lazy declarations
|
||||
EmitCLazyDecls m_lazyDecls{*this}; // Visitor for emitting lazy declarations
|
||||
bool m_useSelfForThis = false; // Replace "this" with "vlSelf"
|
||||
bool m_usevlSelfRef = false; // Use vlSelfRef reference instead of vlSelf pointer
|
||||
const AstNodeModule* m_modp = nullptr; // Current module being emitted
|
||||
|
|
@ -169,16 +169,6 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
|
||||
// ACCESSORS
|
||||
void splitSizeInc(int count) { m_splitSize += count; }
|
||||
void splitSizeInc(const AstNode* nodep) { splitSizeInc(nodep->nodeCount()); }
|
||||
void splitSizeReset() { m_splitSize = 0; }
|
||||
bool splitNeeded() const {
|
||||
return v3Global.opt.outputSplit() && m_splitSize >= v3Global.opt.outputSplit();
|
||||
}
|
||||
|
||||
// METHODS
|
||||
void displayNode(AstNode* nodep, AstScopeName* scopenamep, const string& vformat,
|
||||
AstNode* exprsp, bool isScan);
|
||||
|
|
@ -1730,13 +1720,8 @@ public:
|
|||
}
|
||||
} // LCOV_EXCL_STOP
|
||||
|
||||
EmitCFunc()
|
||||
: m_lazyDecls{*this} {}
|
||||
EmitCFunc(AstNode* nodep, V3OutCFile* ofp, AstCFile* cfilep)
|
||||
: EmitCFunc{} {
|
||||
setOutputFile(ofp, cfilep);
|
||||
iterateConst(nodep);
|
||||
}
|
||||
protected:
|
||||
EmitCFunc() = default;
|
||||
~EmitCFunc() override = default;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -635,16 +635,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
UINFO(5, " Emitting header for " << EmitCUtil::prefixNameProtect(modp));
|
||||
|
||||
// Open output file
|
||||
const string filename
|
||||
= v3Global.opt.makeDir() + "/" + EmitCUtil::prefixNameProtect(modp) + ".h";
|
||||
AstCFile* const cfilep = newCFile(filename, /* slow: */ false, /* source: */ false);
|
||||
V3OutCFile* const ofilep
|
||||
= v3Global.opt.systemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
|
||||
|
||||
setOutputFile(ofilep, cfilep);
|
||||
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCRIPTION: Verilator output: Design internal header\n");
|
||||
openNewOutputHeaderFile(EmitCUtil::prefixNameProtect(modp), "Design internal header");
|
||||
puts("// See " + EmitCUtil::topClassName() + ".h for the primary calling header\n");
|
||||
|
||||
ofp()->putsGuard();
|
||||
|
|
@ -653,6 +644,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
puts("\n");
|
||||
ofp()->putsIntTopInclude();
|
||||
puts("#include \"verilated.h\"\n");
|
||||
if (modp->isTop() && optSystemC()) puts("#include \"verilated_sc.h\"\n");
|
||||
if (v3Global.opt.mtasks()) puts("#include \"verilated_threads.h\"\n");
|
||||
if (v3Global.opt.savable()) puts("#include \"verilated_save.h\"\n");
|
||||
if (v3Global.opt.coverage()) puts("#include \"verilated_cov.h\"\n");
|
||||
|
|
|
|||
|
|
@ -30,47 +30,23 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
|||
//######################################################################
|
||||
// Internal EmitC implementation
|
||||
|
||||
class EmitCImp final : EmitCFunc {
|
||||
class EmitCImp final : public EmitCFunc {
|
||||
// MEMBERS
|
||||
const AstNodeModule* const m_fileModp; // Files names/headers constructed using this module
|
||||
// Base module (For non-classes, same as m_modp. For classes, it's the ClassPackage.)
|
||||
const AstNodeModule* const m_fileModp;
|
||||
const bool m_slow; // Creating __Slow file
|
||||
size_t m_nSplitFiles = 0; // Sequence number for file splitting
|
||||
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
|
||||
V3UniqueNames m_uniqueNames; // Generates unique file names
|
||||
const std::string m_fileBaseName = EmitCUtil::prefixNameProtect(m_fileModp);
|
||||
|
||||
// METHODS
|
||||
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 std::string filename = VL_DEV_NULL;
|
||||
filep = createCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
ofilep = new V3OutCFile{filename};
|
||||
} else {
|
||||
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";
|
||||
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");
|
||||
void openNextOutputFile(const std::string& fileName) {
|
||||
openNewOutputSourceFile(fileName, m_slow, false, "Design implementation internals");
|
||||
puts("// See " + EmitCUtil::topClassName() + ".h for the primary calling header\n");
|
||||
puts("\n");
|
||||
puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
|
||||
|
||||
emitSystemCSection(m_modp, VSystemCSectionType::IMP_HDR);
|
||||
emitSystemCSection(m_fileModp, VSystemCSectionType::IMP_HDR);
|
||||
// Need to emit new lazy declarations
|
||||
m_lazyDecls.reset();
|
||||
}
|
||||
|
||||
void emitStaticVarDefns(const AstNodeModule* modp) {
|
||||
|
|
@ -402,7 +378,7 @@ class EmitCImp final : EmitCFunc {
|
|||
= VN_IS(modp, ClassPackage) ? VN_AS(modp, ClassPackage)->classp() : nullptr;
|
||||
|
||||
if (hasCommonImp(modp) || hasCommonImp(classp)) {
|
||||
openNextOutputFile(/* canBeSplit: */ false);
|
||||
openNextOutputFile(m_fileBaseName);
|
||||
|
||||
doCommonImp(modp);
|
||||
if (classp) {
|
||||
|
|
@ -442,7 +418,7 @@ class EmitCImp final : EmitCFunc {
|
|||
if (funcps.empty()) return;
|
||||
|
||||
// Open output file
|
||||
openNextOutputFile(/* canBeSplit: */ true);
|
||||
openNextOutputFile(m_uniqueNames.get(m_fileBaseName));
|
||||
// Emit all functions
|
||||
for (AstCFunc* const funcp : funcps) {
|
||||
VL_RESTORER(m_modp);
|
||||
|
|
@ -461,16 +437,15 @@ class EmitCImp final : EmitCFunc {
|
|||
// Close old file
|
||||
closeOutputFile();
|
||||
// Open a new file
|
||||
openNextOutputFile(/* canBeSplit: */ true);
|
||||
openNextOutputFile(m_uniqueNames.get(m_fileBaseName));
|
||||
}
|
||||
|
||||
EmitCFunc::visit(nodep);
|
||||
}
|
||||
|
||||
explicit EmitCImp(const AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr)
|
||||
explicit EmitCImp(const AstNodeModule* modp, bool slow)
|
||||
: m_fileModp{modp}
|
||||
, m_slow{slow}
|
||||
, m_cfilesr{cfilesr} {
|
||||
, m_slow{slow} {
|
||||
UINFO(5, " Emitting implementation of " << EmitCUtil::prefixNameProtect(modp));
|
||||
|
||||
m_modp = modp;
|
||||
|
|
@ -489,121 +464,142 @@ class EmitCImp final : EmitCFunc {
|
|||
~EmitCImp() override = default;
|
||||
|
||||
public:
|
||||
static void main(const AstNodeModule* modp, bool slow,
|
||||
std::deque<AstCFile*>& cfilesr) VL_MT_STABLE {
|
||||
EmitCImp{modp, slow, cfilesr};
|
||||
static std::vector<AstCFile*> main(const AstNodeModule* modp, bool slow) VL_MT_STABLE {
|
||||
EmitCImp emitCImp{modp, slow};
|
||||
return emitCImp.getAndClearCfileps();
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Tracing routines
|
||||
|
||||
class EmitCTrace final : EmitCFunc {
|
||||
// Trace type descriptors go in a different file as it needs to be written in
|
||||
// parallel with the actual trace function source files
|
||||
class EmitCTraceTypes final : public EmitCFunc {
|
||||
// NODE STATE/TYPES
|
||||
// None allowed to support threaded emitting
|
||||
|
||||
// STATE
|
||||
int m_enumNum = 0; // Enumeration number (whole netlist)
|
||||
std::unordered_map<AstNode*, int> m_enumNumMap; // EnumDType to enumeration number
|
||||
int m_traceTypeSubs = 0; // Number of trace type declaration sub-functions
|
||||
V3UniqueNames m_uniqueNames; // Generates unique file names
|
||||
const std::string m_fileBaseName = EmitCUtil::topClassName() + "_" + protect("_TraceDecls");
|
||||
// This one uses CSplitTrace for file splitting, which is incorrect but historically accurates
|
||||
const size_t m_splitLimit = v3Global.opt.outputSplitCTrace()
|
||||
? static_cast<size_t>(v3Global.opt.outputSplitCTrace())
|
||||
: std::numeric_limits<size_t>::max();
|
||||
|
||||
void openNextOutputFile() {
|
||||
openNewOutputSourceFile(m_uniqueNames.get(m_fileBaseName), true, true,
|
||||
"Tracing declarations");
|
||||
puts("\n");
|
||||
for (const std::string& base : v3Global.opt.traceSourceLangs()) {
|
||||
puts("#include \"" + base + ".h\"\n");
|
||||
}
|
||||
puts("\n");
|
||||
puts("\nvoid " + EmitCUtil::prefixNameProtect(m_modp) + "__"
|
||||
+ protect("traceDeclTypesSub" + std::to_string(m_traceTypeSubs++)) + "("
|
||||
+ v3Global.opt.traceClassBase() + "* tracep) {\n");
|
||||
}
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
int getEnumMapNum(AstEnumDType* nodep) {
|
||||
int& enumNumr = m_enumNumMap[nodep];
|
||||
if (!enumNumr) {
|
||||
if (splitNeeded(m_splitLimit)) {
|
||||
// Splitting file, so using parallel build.
|
||||
v3Global.useParallelBuild(true);
|
||||
puts("}\n");
|
||||
closeOutputFile();
|
||||
openNextOutputFile();
|
||||
}
|
||||
|
||||
enumNumr = ++m_enumNum;
|
||||
int nvals = 0;
|
||||
puts("{\n");
|
||||
putns(nodep, "const char* " + protect("__VenumItemNames") + "[]\n");
|
||||
puts("= {");
|
||||
for (AstEnumItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), EnumItem)) {
|
||||
if (++nvals > 1) puts(", ");
|
||||
putbs("\"" + itemp->prettyName() + "\"");
|
||||
}
|
||||
puts("};\n");
|
||||
nvals = 0;
|
||||
puts("const char* " + protect("__VenumItemValues") + "[]\n");
|
||||
puts("= {");
|
||||
for (AstEnumItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), EnumItem)) {
|
||||
AstConst* const constp = VN_AS(itemp->valuep(), Const);
|
||||
if (++nvals > 1) puts(", ");
|
||||
putbs("\"" + constp->num().displayed(nodep, "%0b") + "\"");
|
||||
}
|
||||
puts("};\n");
|
||||
puts("tracep->declDTypeEnum(" + std::to_string(enumNumr) + ", \"" + nodep->prettyName()
|
||||
+ "\", " + std::to_string(nvals) + ", " + std::to_string(nodep->widthMin()) + ", "
|
||||
+ protect("__VenumItemNames") + ", " + protect("__VenumItemValues") + ");\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(AstNode::INSTR_COUNT_CALL);
|
||||
}
|
||||
return enumNumr;
|
||||
}
|
||||
|
||||
// Close output file
|
||||
void finalize() {
|
||||
// Close function definition
|
||||
puts("}\n");
|
||||
|
||||
const std::string modName = EmitCUtil::prefixNameProtect(m_modp);
|
||||
const std::string args = v3Global.opt.traceClassBase() + "* tracep";
|
||||
|
||||
// Forward declarations for subs in other files
|
||||
for (int i = 0; i < m_traceTypeSubs - 1; ++i) {
|
||||
puts("void " + modName + "__" + protect("traceDeclTypesSub" + std::to_string(i)) + "("
|
||||
+ args + ");\n");
|
||||
}
|
||||
|
||||
// Create top level trace_decl_types function and call each sub-function
|
||||
puts("\nvoid " + modName + "__" + protect("trace_decl_types") + "(" + args + ") {\n");
|
||||
for (int i = 0; i < m_traceTypeSubs; ++i) {
|
||||
puts(modName + "__" + protect("traceDeclTypesSub" + std::to_string(i))
|
||||
+ "(tracep);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
|
||||
closeOutputFile();
|
||||
}
|
||||
|
||||
EmitCTraceTypes() {
|
||||
m_modp = v3Global.rootp()->topModulep();
|
||||
openNextOutputFile();
|
||||
}
|
||||
~EmitCTraceTypes() override = default;
|
||||
};
|
||||
|
||||
class EmitCTrace final : public EmitCFunc {
|
||||
// NODE STATE/TYPES
|
||||
// None allowed to support threaded emitting
|
||||
|
||||
// MEMBERS
|
||||
const bool m_slow; // Making slow file
|
||||
int m_enumNum = 0; // Enumeration number (whole netlist)
|
||||
V3UniqueNames m_uniqueNames; // For generating unique file names
|
||||
std::unordered_map<AstNode*, int> m_enumNumMap; // EnumDType to enumeration number
|
||||
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
|
||||
V3OutCFile* m_typesFp = nullptr; // File for type declarations
|
||||
int m_traceTypeSubs = 0; // Number of trace type declaration sub-functions
|
||||
int m_typeSplitSize = 0; // # of cfunc nodes placed into output file
|
||||
const std::unique_ptr<EmitCTraceTypes> m_emitTypesp{m_slow ? new EmitCTraceTypes{} : nullptr};
|
||||
V3UniqueNames m_uniqueNames; // Generates unique file names
|
||||
const std::string m_fileBaseName = EmitCUtil::topClassName() + "_" + protect("_Trace");
|
||||
|
||||
// METHODS
|
||||
void openNextOutputFile() {
|
||||
UASSERT(!ofp(), "Output file already open");
|
||||
|
||||
splitSizeReset(); // Reset file size tracking
|
||||
m_lazyDecls.reset(); // Need to emit new lazy declarations
|
||||
|
||||
string filename
|
||||
= (v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "_" + protect("_Trace"));
|
||||
filename = m_uniqueNames.get(filename);
|
||||
if (m_slow) filename += "__Slow";
|
||||
filename += ".cpp";
|
||||
|
||||
AstCFile* const cfilep = createCFile(filename, m_slow, true /*source*/);
|
||||
cfilep->support(true);
|
||||
m_cfilesr.push_back(cfilep);
|
||||
|
||||
V3OutCFile* const ofilep
|
||||
= optSystemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
|
||||
setOutputFile(ofilep, cfilep);
|
||||
|
||||
putsHeader();
|
||||
puts("// DESCR"
|
||||
"IPTION: Verilator output: Tracing implementation internals\n");
|
||||
|
||||
// Includes
|
||||
for (const string& base : v3Global.opt.traceSourceLangs())
|
||||
openNewOutputSourceFile(m_uniqueNames.get(m_fileBaseName), m_slow, true,
|
||||
"Tracing implementation internals");
|
||||
puts("\n");
|
||||
for (const std::string& base : v3Global.opt.traceSourceLangs()) {
|
||||
puts("#include \"" + base + ".h\"\n");
|
||||
}
|
||||
puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
V3OutCFile* typesFp() const VL_MT_SAFE { return m_typesFp; }
|
||||
|
||||
void openNextTypesFile() {
|
||||
UASSERT(!m_typesFp, "Declarations output file already open");
|
||||
|
||||
string filename = (v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "_"
|
||||
+ protect("_TraceDecls"));
|
||||
filename = m_uniqueNames.get(filename);
|
||||
filename += "__Slow.cpp";
|
||||
|
||||
AstCFile* const cfilep = createCFile(filename, m_slow, true /*source*/);
|
||||
cfilep->support(true);
|
||||
m_cfilesr.push_back(cfilep);
|
||||
|
||||
if (optSystemC()) {
|
||||
m_typesFp = new V3OutScFile{filename};
|
||||
} else {
|
||||
m_typesFp = new V3OutCFile{filename};
|
||||
}
|
||||
typesFp()->putsHeader();
|
||||
typesFp()->puts("// DESCR"
|
||||
"IPTION: Verilator output: Tracing declarations\n");
|
||||
|
||||
// Includes
|
||||
for (const string& base : v3Global.opt.traceSourceLangs())
|
||||
typesFp()->puts("#include \"" + base + ".h\"\n");
|
||||
typesFp()->puts("\n");
|
||||
|
||||
typesFp()->puts("\nvoid " + EmitCUtil::prefixNameProtect(m_modp) + "__"
|
||||
+ protect("traceDeclTypesSub" + cvtToStr(m_traceTypeSubs++)) + "("
|
||||
+ v3Global.opt.traceClassBase() + "* tracep) {\n");
|
||||
}
|
||||
|
||||
void closeTypesFile() {
|
||||
typesFp()->puts("}\n");
|
||||
VL_DO_CLEAR(delete m_typesFp, m_typesFp = nullptr);
|
||||
}
|
||||
|
||||
void callTypeSubs() {
|
||||
typesFp()->puts("}\n");
|
||||
|
||||
// Forward declarations for subs in other files
|
||||
for (int i = 0; i < m_traceTypeSubs - 1; ++i) {
|
||||
typesFp()->puts("void " + EmitCUtil::prefixNameProtect(m_modp) + "__"
|
||||
+ protect("traceDeclTypesSub" + cvtToStr(i)) + "("
|
||||
+ v3Global.opt.traceClassBase() + "* tracep);\n");
|
||||
}
|
||||
|
||||
typesFp()->puts("\nvoid " + EmitCUtil::prefixNameProtect(m_modp) + "__"
|
||||
+ protect("trace_decl_types") + "(" + v3Global.opt.traceClassBase()
|
||||
+ "* tracep) {\n");
|
||||
for (int i = 0; i < m_traceTypeSubs; ++i) {
|
||||
typesFp()->puts(EmitCUtil::prefixNameProtect(m_modp) + "__"
|
||||
+ protect("traceDeclTypesSub" + cvtToStr(i)) + "(tracep);\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool typesSplitNeeded() {
|
||||
return v3Global.opt.outputSplitCTrace()
|
||||
&& m_typeSplitSize >= v3Global.opt.outputSplitCTrace();
|
||||
// Need to emit new lazy declarations
|
||||
m_lazyDecls.reset();
|
||||
}
|
||||
|
||||
bool emitTraceIsScBv(const AstTraceInc* nodep) {
|
||||
|
|
@ -693,54 +689,13 @@ class EmitCTrace final : EmitCFunc {
|
|||
puts(");");
|
||||
}
|
||||
|
||||
int getEnumMapNum(AstEnumDType* nodep) {
|
||||
int enumNum = m_enumNumMap[nodep];
|
||||
if (!enumNum) {
|
||||
if (typesSplitNeeded()) {
|
||||
// Splitting file, so using parallel build.
|
||||
v3Global.useParallelBuild(true);
|
||||
closeTypesFile();
|
||||
openNextTypesFile();
|
||||
}
|
||||
enumNum = ++m_enumNum;
|
||||
m_enumNumMap[nodep] = enumNum;
|
||||
int nvals = 0;
|
||||
typesFp()->puts("{\n");
|
||||
typesFp()->putns(nodep, "const char* " + protect("__VenumItemNames") + "[]\n");
|
||||
typesFp()->puts("= {");
|
||||
for (AstEnumItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), EnumItem)) {
|
||||
if (++nvals > 1) typesFp()->puts(", ");
|
||||
typesFp()->putbs("\"" + itemp->prettyName() + "\"");
|
||||
}
|
||||
typesFp()->puts("};\n");
|
||||
nvals = 0;
|
||||
typesFp()->puts("const char* " + protect("__VenumItemValues") + "[]\n");
|
||||
typesFp()->puts("= {");
|
||||
for (AstEnumItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), EnumItem)) {
|
||||
AstConst* const constp = VN_AS(itemp->valuep(), Const);
|
||||
if (++nvals > 1) typesFp()->puts(", ");
|
||||
typesFp()->putbs("\"" + constp->num().displayed(nodep, "%0b") + "\"");
|
||||
}
|
||||
typesFp()->puts("};\n");
|
||||
typesFp()->puts("tracep->declDTypeEnum(" + cvtToStr(enumNum) + ", \""
|
||||
+ nodep->prettyName() + "\", " + cvtToStr(nvals) + ", "
|
||||
+ cvtToStr(nodep->widthMin()) + ", " + protect("__VenumItemNames")
|
||||
+ ", " + protect("__VenumItemValues") + ");\n");
|
||||
typesFp()->puts("}\n");
|
||||
m_typeSplitSize += 3;
|
||||
}
|
||||
return enumNum;
|
||||
}
|
||||
|
||||
int emitTraceDeclDType(AstNodeDType* nodep) {
|
||||
// Return enum number or -1 for none
|
||||
if (v3Global.opt.traceEnabledFst()) {
|
||||
// Skip over refs-to-refs, but stop before final ref so can get data type name
|
||||
// Alternatively back in V3Width we could push enum names from upper typedefs
|
||||
if (AstEnumDType* const enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) {
|
||||
return getEnumMapNum(enump);
|
||||
return m_emitTypesp->getEnumMapNum(enump);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
|
@ -873,29 +828,49 @@ class EmitCTrace final : EmitCFunc {
|
|||
}
|
||||
}
|
||||
|
||||
explicit EmitCTrace(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr)
|
||||
: m_slow{slow}
|
||||
, m_cfilesr{cfilesr} {
|
||||
m_modp = modp;
|
||||
explicit EmitCTrace(bool slow)
|
||||
: m_slow{slow} {
|
||||
m_modp = v3Global.rootp()->topModulep();
|
||||
// Open output file
|
||||
openNextOutputFile();
|
||||
if (m_slow) openNextTypesFile();
|
||||
// Emit functions
|
||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstCFunc* const funcp = VN_CAST(nodep, CFunc)) iterateConst(funcp);
|
||||
}
|
||||
// Close output file
|
||||
closeOutputFile();
|
||||
if (m_slow) {
|
||||
callTypeSubs();
|
||||
closeTypesFile();
|
||||
}
|
||||
if (m_slow) m_emitTypesp->finalize();
|
||||
}
|
||||
~EmitCTrace() override = default;
|
||||
|
||||
public:
|
||||
static void main(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr) VL_MT_STABLE {
|
||||
EmitCTrace{modp, slow, cfilesr};
|
||||
static std::vector<AstCFile*> main(bool slow) VL_MT_STABLE {
|
||||
EmitCTrace emitCTrace{slow};
|
||||
std::vector<AstCFile*> cfileps = emitCTrace.getAndClearCfileps();
|
||||
if (slow) {
|
||||
for (AstCFile* const cfilep : emitCTrace.m_emitTypesp->getAndClearCfileps()) {
|
||||
cfileps.emplace_back(cfilep);
|
||||
}
|
||||
}
|
||||
return cfileps;
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Existing AstCFile emitter
|
||||
|
||||
class EmitCFile final : public EmitCFunc {
|
||||
explicit EmitCFile(AstCFile* cfilep) {
|
||||
openOutputFile(cfilep, "Generated C++");
|
||||
iterateConst(cfilep->tblockp());
|
||||
closeOutputFile();
|
||||
}
|
||||
~EmitCFile() override = default;
|
||||
|
||||
public:
|
||||
static void main(AstCFile* cfilep) VL_MT_STABLE {
|
||||
if (!cfilep->tblockp()) return;
|
||||
EmitCFile{cfilep};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -904,42 +879,37 @@ public:
|
|||
|
||||
void V3EmitC::emitcImp() {
|
||||
UINFO(2, __FUNCTION__ << ":");
|
||||
// Make parent module pointers available.
|
||||
const EmitCParentModule emitCParentModule;
|
||||
std::list<std::deque<AstCFile*>> cfiles;
|
||||
V3ThreadScope threadScope;
|
||||
std::list<std::vector<AstCFile*>> cfiles;
|
||||
{
|
||||
// Make parent module pointers available.
|
||||
const EmitCParentModule emitCParentModule;
|
||||
V3ThreadScope threadScope;
|
||||
|
||||
// Process each module in turn
|
||||
for (const AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) {
|
||||
if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage
|
||||
const AstNodeModule* const modp = VN_AS(nodep, NodeModule);
|
||||
cfiles.emplace_back();
|
||||
auto& slowCfilesr = cfiles.back();
|
||||
threadScope.enqueue(
|
||||
[modp, &slowCfilesr] { EmitCImp::main(modp, /* slow: */ true, slowCfilesr); });
|
||||
cfiles.emplace_back();
|
||||
auto& fastCfilesr = cfiles.back();
|
||||
threadScope.enqueue(
|
||||
[modp, &fastCfilesr] { EmitCImp::main(modp, /* slow: */ false, fastCfilesr); });
|
||||
}
|
||||
// Process each module in turn
|
||||
for (const AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) {
|
||||
if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage
|
||||
const AstNodeModule* const modp = VN_AS(nodep, NodeModule);
|
||||
cfiles.emplace_back();
|
||||
std::vector<AstCFile*>& slow = cfiles.back();
|
||||
threadScope.enqueue([modp, &slow] { slow = EmitCImp::main(modp, /* slow: */ true); });
|
||||
cfiles.emplace_back();
|
||||
std::vector<AstCFile*>& fast = cfiles.back();
|
||||
threadScope.enqueue([modp, &fast] { fast = EmitCImp::main(modp, /* slow: */ false); });
|
||||
}
|
||||
|
||||
// Emit trace routines (currently they can only exist in the top module)
|
||||
if (v3Global.opt.trace() && !v3Global.opt.lintOnly()) {
|
||||
cfiles.emplace_back();
|
||||
auto& slowCfilesr = cfiles.back();
|
||||
threadScope.enqueue([&slowCfilesr] {
|
||||
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true, slowCfilesr);
|
||||
});
|
||||
cfiles.emplace_back();
|
||||
auto& fastCfilesr = cfiles.back();
|
||||
threadScope.enqueue([&fastCfilesr] {
|
||||
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false, fastCfilesr);
|
||||
});
|
||||
// Emit trace routines (currently they can only exist in the top module)
|
||||
if (v3Global.opt.trace() && !v3Global.opt.lintOnly()) {
|
||||
cfiles.emplace_back();
|
||||
std::vector<AstCFile*>& slow = cfiles.back();
|
||||
threadScope.enqueue([&slow] { slow = EmitCTrace::main(/* slow: */ true); });
|
||||
cfiles.emplace_back();
|
||||
std::vector<AstCFile*>& fast = cfiles.back();
|
||||
threadScope.enqueue([&fast] { fast = EmitCTrace::main(/* slow: */ false); });
|
||||
}
|
||||
}
|
||||
// Wait for futures
|
||||
threadScope.wait();
|
||||
for (const auto& collr : cfiles) {
|
||||
for (const auto cfilep : collr) v3Global.rootp()->addFilesp(cfilep);
|
||||
// Add files to netlist
|
||||
for (const std::vector<AstCFile*>& cfileps : cfiles) {
|
||||
for (AstCFile* const cfilep : cfileps) v3Global.rootp()->addFilesp(cfilep);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -947,12 +917,6 @@ void V3EmitC::emitcFiles() {
|
|||
UINFO(2, __FUNCTION__ << ":");
|
||||
for (AstNodeFile *filep = v3Global.rootp()->filesp(), *nextp; filep; filep = nextp) {
|
||||
nextp = VN_AS(filep->nextp(), NodeFile);
|
||||
AstCFile* const cfilep = VN_CAST(filep, CFile);
|
||||
if (cfilep && cfilep->tblockp()) {
|
||||
V3OutCFile of{cfilep->name()};
|
||||
of.puts("// DESCR"
|
||||
"IPTION: Verilator generated C++\n");
|
||||
EmitCFunc{cfilep->tblockp(), &of, cfilep};
|
||||
}
|
||||
if (AstCFile* const cfilep = VN_CAST(filep, CFile)) EmitCFile::main(cfilep);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,12 +41,6 @@ public:
|
|||
private:
|
||||
// MAIN METHOD
|
||||
void emitInt() {
|
||||
const string filename
|
||||
= v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "__main.cpp";
|
||||
AstCFile* const cfilep = newCFile(filename, false /*slow*/, true /*source*/);
|
||||
V3OutCFile cf{filename};
|
||||
setOutputFile(&cf, cfilep);
|
||||
|
||||
// Not defining main_time/vl_time_stamp, so
|
||||
v3Global.opt.addCFlags("-DVL_TIME_CONTEXT"); // On MSVC++ anyways
|
||||
|
||||
|
|
@ -54,11 +48,12 @@ private:
|
|||
string topName = v3Global.opt.mainTopName();
|
||||
if (topName == "-") topName = "";
|
||||
|
||||
// Heavily commented output, as users are likely to look at or copy this code
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCRIPTION: main() calling loop, created with Verilator --main\n");
|
||||
openNewOutputSourceFile(EmitCUtil::topClassName() + "__main", false, false,
|
||||
"main() simulation loop, created with --main");
|
||||
puts("\n");
|
||||
|
||||
// Heavily commented output, as users are likely to look at or copy this code
|
||||
|
||||
puts("#include \"verilated.h\"\n");
|
||||
puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
|
||||
|
||||
|
|
@ -116,7 +111,7 @@ private:
|
|||
puts("return 0;\n");
|
||||
puts("}\n");
|
||||
|
||||
setOutputFile(nullptr);
|
||||
closeOutputFile();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,15 +53,7 @@ class EmitCModel final : public EmitCFunc {
|
|||
}
|
||||
|
||||
void emitHeader(AstNodeModule* modp) {
|
||||
UASSERT(!ofp(), "Output file should not be open");
|
||||
|
||||
const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + ".h";
|
||||
setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename}
|
||||
: new V3OutCFile{filename},
|
||||
newCFile(filename, /* slow: */ false, /* source: */ false));
|
||||
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCRIPTION: Verilator output: Primary model header\n");
|
||||
openNewOutputHeaderFile(EmitCUtil::topClassName(), "Primary model header");
|
||||
puts("//\n");
|
||||
puts("// This header should be included by all source files instantiating the design.\n");
|
||||
puts("// The class here is then constructed to instantiate the design.\n");
|
||||
|
|
@ -72,7 +64,9 @@ class EmitCModel final : public EmitCFunc {
|
|||
// Include files
|
||||
puts("\n");
|
||||
ofp()->putsIntTopInclude();
|
||||
|
||||
puts("#include \"verilated.h\"\n");
|
||||
if (v3Global.opt.systemC()) puts("#include \"verilated_sc.h\"\n");
|
||||
if (v3Global.opt.mtasks()) puts("#include \"verilated_threads.h\"\n");
|
||||
if (v3Global.opt.savable()) puts("#include \"verilated_save.h\"\n");
|
||||
if (v3Global.opt.coverage()) puts("#include \"verilated_cov.h\"\n");
|
||||
|
|
@ -614,17 +608,8 @@ class EmitCModel final : public EmitCFunc {
|
|||
}
|
||||
|
||||
void emitImplementation(AstNodeModule* modp) {
|
||||
UASSERT(!ofp(), "Output file should not be open");
|
||||
|
||||
const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + ".cpp";
|
||||
setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename}
|
||||
: new V3OutCFile{filename},
|
||||
newCFile(filename, /* slow: */ false, /* source: */ true));
|
||||
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCRIPTION: Verilator output: "
|
||||
"Model implementation (design independent parts)\n");
|
||||
|
||||
openNewOutputSourceFile(EmitCUtil::topClassName(), false, false,
|
||||
"Model implementation (design independent parts)");
|
||||
puts("\n");
|
||||
puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
|
||||
for (const string& base : v3Global.opt.traceSourceLangs())
|
||||
|
|
@ -643,6 +628,10 @@ class EmitCModel final : public EmitCFunc {
|
|||
void emitDpiExportDispatchers(AstNodeModule* modp) {
|
||||
UASSERT(!ofp(), "Output file should not be open");
|
||||
|
||||
// File name utils
|
||||
V3UniqueNames uniqueNames;
|
||||
const std::string fileBaseName = EmitCUtil::topClassName() + "__Dpi_Export";
|
||||
|
||||
// Emit DPI Export dispatchers
|
||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
AstCFunc* const funcp = VN_CAST(nodep, CFunc);
|
||||
|
|
@ -656,23 +645,14 @@ class EmitCModel final : public EmitCFunc {
|
|||
}
|
||||
|
||||
if (!ofp()) {
|
||||
string filename
|
||||
= v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "__Dpi_Export";
|
||||
filename = m_uniqueNames.get(filename);
|
||||
filename += ".cpp";
|
||||
setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename}
|
||||
: new V3OutCFile{filename},
|
||||
newCFile(filename, /* slow: */ false, /* source: */ true));
|
||||
splitSizeReset(); // Reset file size tracking
|
||||
m_lazyDecls.reset();
|
||||
ofp()->putsHeader();
|
||||
puts(
|
||||
"// DESCRIPTION: Verilator output: Implementation of DPI export functions.\n");
|
||||
puts("//\n");
|
||||
openNewOutputSourceFile(uniqueNames.get(fileBaseName), false, false,
|
||||
"Implementation of DPI export functions.");
|
||||
puts("\n");
|
||||
puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
|
||||
puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
|
||||
puts("#include \"verilated_dpi.h\"\n");
|
||||
puts("\n");
|
||||
m_lazyDecls.reset();
|
||||
}
|
||||
|
||||
iterateConst(funcp);
|
||||
|
|
|
|||
|
|
@ -23,48 +23,49 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
|||
//######################################################################
|
||||
// Precompiled header emitter
|
||||
|
||||
class EmitCPch final {
|
||||
class EmitCPch final : public EmitCBaseVisitorConst {
|
||||
public:
|
||||
// METHODS
|
||||
|
||||
void emitPch() {
|
||||
// Generate the makefile
|
||||
V3OutCFile of{v3Global.opt.makeDir() + "/" + EmitCUtil::pchClassName() + ".h"};
|
||||
of.putsHeader();
|
||||
of.puts("// DESCRIPTION: Verilator output: Precompiled header\n");
|
||||
of.puts("//\n");
|
||||
of.puts("// Internal details; most user sources do not need this header,\n");
|
||||
of.puts("// unless using verilator public meta comments.\n");
|
||||
of.puts("// Suggest use " + EmitCUtil::topClassName() + ".h instead.\n");
|
||||
of.puts("\n");
|
||||
openNewOutputHeaderFile(EmitCUtil::pchClassName(), "Precompiled header");
|
||||
puts("//\n");
|
||||
puts("// Internal details; most user sources do not need this header,\n");
|
||||
puts("// unless using verilator public meta comments.\n");
|
||||
puts("// Suggest use " + EmitCUtil::topClassName() + ".h instead.\n");
|
||||
|
||||
of.putsGuard();
|
||||
ofp()->putsGuard();
|
||||
|
||||
of.puts("\n");
|
||||
of.puts("// GCC and Clang only will precompile headers (PCH) for the first header.\n");
|
||||
of.puts("// So, make sure this is the one and only PCH.\n");
|
||||
of.puts("// If multiple module's includes are needed, use individual includes.\n");
|
||||
of.puts("#ifdef VL_PCH_INCLUDED\n");
|
||||
of.puts("# error \"Including multiple precompiled header files\"\n");
|
||||
of.puts("#endif\n");
|
||||
of.puts("#define VL_PCH_INCLUDED\n");
|
||||
puts("\n");
|
||||
puts("// GCC and Clang only will precompile headers (PCH) for the first header.\n");
|
||||
puts("// So, make sure this is the one and only PCH.\n");
|
||||
puts("// If multiple module's includes are needed, use individual includes.\n");
|
||||
puts("#ifdef VL_PCH_INCLUDED\n");
|
||||
puts("# error \"Including multiple precompiled header files\"\n");
|
||||
puts("#endif\n");
|
||||
puts("#define VL_PCH_INCLUDED\n");
|
||||
|
||||
of.puts("\n");
|
||||
of.puts("\n#include \"verilated.h\"\n");
|
||||
if (v3Global.dpi()) of.puts("#include \"verilated_dpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("\n#include \"verilated.h\"\n");
|
||||
if (v3Global.dpi()) puts("#include \"verilated_dpi.h\"\n");
|
||||
|
||||
of.puts("\n");
|
||||
of.puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
|
||||
of.puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
|
||||
puts("\n");
|
||||
puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
|
||||
puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
|
||||
|
||||
of.puts("\n// Additional include files added using '--compiler-include'\n");
|
||||
puts("\n// Additional include files added using '--compiler-include'\n");
|
||||
for (const string& filename : v3Global.opt.compilerIncludes()) {
|
||||
of.puts("#include \"" + filename + "\"\n");
|
||||
puts("#include \"" + filename + "\"\n");
|
||||
}
|
||||
|
||||
of.putsEndGuard();
|
||||
ofp()->putsEndGuard();
|
||||
|
||||
closeOutputFile();
|
||||
}
|
||||
|
||||
// VISITOR
|
||||
void visit(AstNode* nodep) { nodep->v3fatalSrc("Unused"); }
|
||||
|
||||
public:
|
||||
explicit EmitCPch() { emitPch(); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,16 +103,8 @@ class EmitCSyms final : EmitCBaseVisitorConst {
|
|||
const bool m_dpiHdrOnly; // Only emit the DPI header
|
||||
std::vector<std::string> m_splitFuncNames; // Split file names
|
||||
VDouble0 m_statVarScopeBytes; // Statistic tracking
|
||||
const std::string m_symsFileBase = v3Global.opt.makeDir() + "/" + symClassName();
|
||||
|
||||
// METHODS
|
||||
void openOutputFile(const std::string fileName) {
|
||||
V3OutCFile* const fp = optSystemC() ? new V3OutScFile{fileName} : new V3OutCFile{fileName};
|
||||
AstCFile* const cfilep = newCFile(fileName, true /*slow*/, true /*source*/);
|
||||
cfilep->support(true);
|
||||
setOutputFile(fp, cfilep);
|
||||
}
|
||||
|
||||
void emitSymHdr();
|
||||
void emitSymImpPreamble();
|
||||
void emitScopeHier(std::vector<std::string>& stmts, bool destroy);
|
||||
|
|
@ -415,14 +407,7 @@ public:
|
|||
|
||||
void EmitCSyms::emitSymHdr() {
|
||||
UINFO(6, __FUNCTION__ << ": ");
|
||||
const std::string filename = m_symsFileBase + ".h";
|
||||
AstCFile* const cfilep = newCFile(filename, true /*slow*/, false /*source*/);
|
||||
V3OutCFile* const ofilep = optSystemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
|
||||
setOutputFile(ofilep, cfilep);
|
||||
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCR"
|
||||
"IPTION: Verilator output: Symbol table internal header\n");
|
||||
openNewOutputHeaderFile(symClassName(), "Symbol table internal header");
|
||||
puts("//\n");
|
||||
puts("// Internal details; most calling programs do not need this header,\n");
|
||||
puts("// unless using verilator public meta comments.\n");
|
||||
|
|
@ -596,9 +581,6 @@ void EmitCSyms::emitSymHdr() {
|
|||
}
|
||||
|
||||
void EmitCSyms::emitSymImpPreamble() {
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCR"
|
||||
"IPTION: Verilator output: Symbol table implementation internals\n");
|
||||
puts("\n");
|
||||
|
||||
// Includes
|
||||
|
|
@ -883,7 +865,6 @@ std::vector<std::string> EmitCSyms::getSymDtorStmts() {
|
|||
|
||||
void EmitCSyms::emitSplit(std::vector<std::string>& stmts, const std::string name,
|
||||
size_t maxCost) {
|
||||
const std::string baseName = m_symsFileBase + "__" + name;
|
||||
size_t nSubFunctions = 0;
|
||||
// Reduce into a balanced tree of sub-function calls until we end up with a single statement
|
||||
while (stmts.size() > 1) {
|
||||
|
|
@ -905,7 +886,7 @@ void EmitCSyms::emitSplit(std::vector<std::string>& stmts, const std::string nam
|
|||
const std::string funcName = symClassName() + "__" + name + "__" + nStr;
|
||||
m_splitFuncNames.emplace_back(funcName);
|
||||
// Open split file
|
||||
openOutputFile(baseName + "__" + nStr + "__Slow.cpp");
|
||||
openNewOutputSourceFile(funcName, true, true, "Symbol table implementation internals");
|
||||
// Emit header
|
||||
emitSymImpPreamble();
|
||||
// Open sub-function definition in the split file
|
||||
|
|
@ -913,9 +894,9 @@ void EmitCSyms::emitSplit(std::vector<std::string>& stmts, const std::string nam
|
|||
|
||||
// Emit statements
|
||||
for (size_t j = splitStart; j < splitEnd; ++j) {
|
||||
m_ofp->putsNoTracking(" ");
|
||||
m_ofp->putsNoTracking(stmts[j]);
|
||||
m_ofp->putsNoTracking("\n");
|
||||
ofp()->putsNoTracking(" ");
|
||||
ofp()->putsNoTracking(stmts[j]);
|
||||
ofp()->putsNoTracking("\n");
|
||||
}
|
||||
|
||||
// Close sub-function
|
||||
|
|
@ -961,7 +942,7 @@ void EmitCSyms::emitSymImp(AstNetlist* netlistp) {
|
|||
}
|
||||
}
|
||||
|
||||
openOutputFile(m_symsFileBase + "__Slow.cpp");
|
||||
openNewOutputSourceFile(symClassName(), true, true, "Symbol table implementation internals");
|
||||
emitSymImpPreamble();
|
||||
|
||||
// Constructor
|
||||
|
|
@ -988,18 +969,18 @@ void EmitCSyms::emitSymImp(AstNetlist* netlistp) {
|
|||
}
|
||||
puts("{\n");
|
||||
for (const std::string& stmt : ctorStmts) {
|
||||
m_ofp->putsNoTracking(" ");
|
||||
m_ofp->putsNoTracking(stmt);
|
||||
m_ofp->putsNoTracking("\n");
|
||||
ofp()->putsNoTracking(" ");
|
||||
ofp()->putsNoTracking(stmt);
|
||||
ofp()->putsNoTracking("\n");
|
||||
}
|
||||
puts("}\n");
|
||||
|
||||
// Destructor
|
||||
puts("\n" + symClassName() + "::~" + symClassName() + "() {\n");
|
||||
for (const std::string& stmt : dtorStmts) {
|
||||
m_ofp->putsNoTracking(" ");
|
||||
m_ofp->putsNoTracking(stmt);
|
||||
m_ofp->putsNoTracking("\n");
|
||||
ofp()->putsNoTracking(" ");
|
||||
ofp()->putsNoTracking(stmt);
|
||||
ofp()->putsNoTracking("\n");
|
||||
}
|
||||
puts("}\n");
|
||||
|
||||
|
|
@ -1058,15 +1039,9 @@ void EmitCSyms::emitSymImp(AstNetlist* netlistp) {
|
|||
|
||||
void EmitCSyms::emitDpiHdr() {
|
||||
UINFO(6, __FUNCTION__ << ": ");
|
||||
const std::string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi.h";
|
||||
AstCFile* const cfilep = newCFile(filename, false /*slow*/, false /*source*/);
|
||||
cfilep->support(true);
|
||||
V3OutCFile hf{filename};
|
||||
setOutputFile(&hf, cfilep);
|
||||
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCR"
|
||||
"IPTION: Verilator output: Prototypes for DPI import and export functions.\n");
|
||||
openNewOutputHeaderFile(topClassName() + "__Dpi",
|
||||
"Prototypes for DPI import and export functions.");
|
||||
puts("//\n");
|
||||
puts("// Verilator includes this file in all generated .cpp files that use DPI functions.\n");
|
||||
puts("// Manually include this file where DPI .c import functions are declared to ensure\n");
|
||||
|
|
@ -1105,22 +1080,16 @@ void EmitCSyms::emitDpiHdr() {
|
|||
puts("#endif\n");
|
||||
|
||||
ofp()->putsEndGuard();
|
||||
setOutputFile(nullptr);
|
||||
|
||||
closeOutputFile();
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
void EmitCSyms::emitDpiImp() {
|
||||
UINFO(6, __FUNCTION__ << ": ");
|
||||
const std::string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi.cpp";
|
||||
AstCFile* const cfilep = newCFile(filename, false /*slow*/, true /*source*/);
|
||||
cfilep->support(true);
|
||||
V3OutCFile hf(filename);
|
||||
setOutputFile(&hf, cfilep);
|
||||
|
||||
ofp()->putsHeader();
|
||||
puts("// DESCR"
|
||||
"IPTION: Verilator output: Implementation of DPI export functions.\n");
|
||||
openNewOutputSourceFile(topClassName() + "__Dpi", false, true,
|
||||
"Implementation of DPI export functions");
|
||||
puts("//\n");
|
||||
puts("// Verilator compiles this file in when DPI functions are used.\n");
|
||||
puts("// If you have multiple Verilated designs with the same DPI exported\n");
|
||||
|
|
@ -1164,7 +1133,7 @@ void EmitCSyms::emitDpiImp() {
|
|||
puts("#endif\n");
|
||||
puts("\n");
|
||||
}
|
||||
setOutputFile(nullptr);
|
||||
closeOutputFile();
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
13
src/V3File.h
13
src/V3File.h
|
|
@ -400,19 +400,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class V3OutScFile final : public V3OutCFile {
|
||||
public:
|
||||
explicit V3OutScFile(const string& filename)
|
||||
: V3OutCFile{filename} {}
|
||||
~V3OutScFile() override = default;
|
||||
void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
void putsIntTopInclude() override {
|
||||
putsForceIncs();
|
||||
puts("#include \"systemc\"\n");
|
||||
puts("#include \"verilated_sc.h\"\n");
|
||||
}
|
||||
};
|
||||
|
||||
class V3OutVFile final : public V3OutCFile {
|
||||
public:
|
||||
explicit V3OutVFile(const string& filename)
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_clas
|
|||
test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_classes_2")
|
||||
|
||||
# Check combine count
|
||||
test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (271 if test.vltmt else 254))
|
||||
test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (272 if test.vltmt else 255))
|
||||
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_FAST + (\d+)', 2)
|
||||
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_SLOW + (\d+)', 2)
|
||||
|
||||
|
|
|
|||
|
|
@ -2924,69 +2924,70 @@
|
|||
],
|
||||
"filesp": [
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms__Slow.cpp","addr":"(ZQB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms.h","addr":"(ARB)","loc":"a,0:0,0:0","source":false,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms.h","addr":"(ARB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.h","addr":"(BRB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.cpp","addr":"(CRB)","loc":"a,0:0,0:0","source":true,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root.h","addr":"(DRB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit.h","addr":"(ERB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__Slow.cpp","addr":"(FRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0__Slow.cpp","addr":"(GRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0.cpp","addr":"(HRB)","loc":"a,0:0,0:0","source":true,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__Slow.cpp","addr":"(IRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__0__Slow.cpp","addr":"(JRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__pch.h","addr":"(DRB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root.h","addr":"(ERB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit.h","addr":"(FRB)","loc":"a,0:0,0:0","source":false,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__Slow.cpp","addr":"(GRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0__Slow.cpp","addr":"(HRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0.cpp","addr":"(IRB)","loc":"a,0:0,0:0","source":true,"slow":false,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__Slow.cpp","addr":"(JRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
|
||||
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__0__Slow.cpp","addr":"(KRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}
|
||||
],
|
||||
"miscsp": [
|
||||
{"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(AB)",
|
||||
"typesp": [
|
||||
{"type":"BASICDTYPE","name":"logic","addr":"(K)","loc":"d,33:24,33:27","dtypep":"(K)","keyword":"logic","generic":true,"rangep": []},
|
||||
{"type":"BASICDTYPE","name":"logic","addr":"(EC)","loc":"d,53:16,53:17","dtypep":"(EC)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
|
||||
{"type":"BASICDTYPE","name":"logic","addr":"(KRB)","loc":"d,17:17,17:18","dtypep":"(KRB)","keyword":"logic","range":"3:0","generic":true,"rangep": []},
|
||||
{"type":"ENUMDTYPE","name":"t.my_t","addr":"(LRB)","loc":"d,17:12,17:16","dtypep":"(LRB)","enum":true,"generic":false,"refDTypep":"(KRB)","childDTypep": [],
|
||||
{"type":"BASICDTYPE","name":"logic","addr":"(LRB)","loc":"d,17:17,17:18","dtypep":"(LRB)","keyword":"logic","range":"3:0","generic":true,"rangep": []},
|
||||
{"type":"ENUMDTYPE","name":"t.my_t","addr":"(MRB)","loc":"d,17:12,17:16","dtypep":"(MRB)","enum":true,"generic":false,"refDTypep":"(LRB)","childDTypep": [],
|
||||
"itemsp": [
|
||||
{"type":"ENUMITEM","name":"E01","addr":"(MRB)","loc":"d,18:24,18:27","dtypep":"(RB)","rangep": [],
|
||||
{"type":"ENUMITEM","name":"E01","addr":"(NRB)","loc":"d,18:24,18:27","dtypep":"(RB)","rangep": [],
|
||||
"valuep": [
|
||||
{"type":"CONST","name":"4'h1","addr":"(NRB)","loc":"d,18:30,18:31","dtypep":"(RB)"}
|
||||
{"type":"CONST","name":"4'h1","addr":"(ORB)","loc":"d,18:30,18:31","dtypep":"(RB)"}
|
||||
]},
|
||||
{"type":"ENUMITEM","name":"E03","addr":"(ORB)","loc":"d,19:24,19:27","dtypep":"(RB)","rangep": [],
|
||||
{"type":"ENUMITEM","name":"E03","addr":"(PRB)","loc":"d,19:24,19:27","dtypep":"(RB)","rangep": [],
|
||||
"valuep": [
|
||||
{"type":"CONST","name":"4'h3","addr":"(PRB)","loc":"d,19:30,19:31","dtypep":"(RB)"}
|
||||
{"type":"CONST","name":"4'h3","addr":"(QRB)","loc":"d,19:30,19:31","dtypep":"(RB)"}
|
||||
]},
|
||||
{"type":"ENUMITEM","name":"E04","addr":"(QRB)","loc":"d,20:24,20:27","dtypep":"(RB)","rangep": [],
|
||||
{"type":"ENUMITEM","name":"E04","addr":"(RRB)","loc":"d,20:24,20:27","dtypep":"(RB)","rangep": [],
|
||||
"valuep": [
|
||||
{"type":"CONST","name":"4'h4","addr":"(RRB)","loc":"d,20:30,20:31","dtypep":"(RB)"}
|
||||
{"type":"CONST","name":"4'h4","addr":"(SRB)","loc":"d,20:30,20:31","dtypep":"(RB)"}
|
||||
]}
|
||||
]},
|
||||
{"type":"BASICDTYPE","name":"integer","addr":"(P)","loc":"d,23:4,23:11","dtypep":"(P)","keyword":"integer","range":"31:0","generic":true,"rangep": []},
|
||||
{"type":"REFDTYPE","name":"my_t","addr":"(M)","loc":"d,24:4,24:8","dtypep":"(LRB)","generic":false,"typedefp":"UNLINKED","refDTypep":"(LRB)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []},
|
||||
{"type":"REFDTYPE","name":"my_t","addr":"(M)","loc":"d,24:4,24:8","dtypep":"(MRB)","generic":false,"typedefp":"UNLINKED","refDTypep":"(MRB)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []},
|
||||
{"type":"BASICDTYPE","name":"string","addr":"(PB)","loc":"d,28:4,28:10","dtypep":"(PB)","keyword":"string","generic":true,"rangep": []},
|
||||
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(ZB)","loc":"d,17:12,17:16","dtypep":"(ZB)","isCompound":false,"declRange":"[7:0]","generic":false,"refDTypep":"(LRB)","childDTypep": [],
|
||||
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(ZB)","loc":"d,17:12,17:16","dtypep":"(ZB)","isCompound":false,"declRange":"[7:0]","generic":false,"refDTypep":"(MRB)","childDTypep": [],
|
||||
"rangep": [
|
||||
{"type":"RANGE","name":"","addr":"(SRB)","loc":"d,17:12,17:16","ascending":false,"fromBracket":false,
|
||||
{"type":"RANGE","name":"","addr":"(TRB)","loc":"d,17:12,17:16","ascending":false,"fromBracket":false,
|
||||
"leftp": [
|
||||
{"type":"CONST","name":"32'h7","addr":"(TRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h7","addr":"(URB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
],
|
||||
"rightp": [
|
||||
{"type":"CONST","name":"32'h0","addr":"(URB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h0","addr":"(VRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
]}
|
||||
]},
|
||||
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(TI)","loc":"d,17:12,17:16","dtypep":"(TI)","isCompound":false,"declRange":"[7:0]","generic":false,"refDTypep":"(LRB)","childDTypep": [],
|
||||
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(TI)","loc":"d,17:12,17:16","dtypep":"(TI)","isCompound":false,"declRange":"[7:0]","generic":false,"refDTypep":"(MRB)","childDTypep": [],
|
||||
"rangep": [
|
||||
{"type":"RANGE","name":"","addr":"(VRB)","loc":"d,17:12,17:16","ascending":false,"fromBracket":false,
|
||||
{"type":"RANGE","name":"","addr":"(WRB)","loc":"d,17:12,17:16","ascending":false,"fromBracket":false,
|
||||
"leftp": [
|
||||
{"type":"CONST","name":"32'h7","addr":"(WRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h7","addr":"(XRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
],
|
||||
"rightp": [
|
||||
{"type":"CONST","name":"32'h0","addr":"(XRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h0","addr":"(YRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
]}
|
||||
]},
|
||||
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(FM)","loc":"d,17:12,17:16","dtypep":"(FM)","isCompound":true,"declRange":"[7:0]","generic":false,"refDTypep":"(PB)","childDTypep": [],
|
||||
"rangep": [
|
||||
{"type":"RANGE","name":"","addr":"(YRB)","loc":"d,17:12,17:16","ascending":false,"fromBracket":false,
|
||||
{"type":"RANGE","name":"","addr":"(ZRB)","loc":"d,17:12,17:16","ascending":false,"fromBracket":false,
|
||||
"leftp": [
|
||||
{"type":"CONST","name":"32'h7","addr":"(ZRB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h7","addr":"(ASB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
],
|
||||
"rightp": [
|
||||
{"type":"CONST","name":"32'h0","addr":"(ASB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h0","addr":"(BSB)","loc":"d,17:12,17:16","dtypep":"(EC)"}
|
||||
]}
|
||||
]},
|
||||
{"type":"BASICDTYPE","name":"logic","addr":"(IB)","loc":"d,23:23,23:24","dtypep":"(IB)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
|
||||
|
|
@ -2994,12 +2995,12 @@
|
|||
{"type":"BASICDTYPE","name":"bit","addr":"(EN)","loc":"a,0:0,0:0","dtypep":"(EN)","keyword":"bit","range":"63:0","generic":true,"rangep": []},
|
||||
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(T)","loc":"d,11:8,11:9","dtypep":"(T)","isCompound":false,"declRange":"[0:0]","generic":false,"refDTypep":"(EN)","childDTypep": [],
|
||||
"rangep": [
|
||||
{"type":"RANGE","name":"","addr":"(BSB)","loc":"d,11:8,11:9","ascending":false,"fromBracket":false,
|
||||
{"type":"RANGE","name":"","addr":"(CSB)","loc":"d,11:8,11:9","ascending":false,"fromBracket":false,
|
||||
"leftp": [
|
||||
{"type":"CONST","name":"32'h0","addr":"(CSB)","loc":"d,11:8,11:9","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h0","addr":"(DSB)","loc":"d,11:8,11:9","dtypep":"(EC)"}
|
||||
],
|
||||
"rightp": [
|
||||
{"type":"CONST","name":"32'h0","addr":"(DSB)","loc":"d,11:8,11:9","dtypep":"(EC)"}
|
||||
{"type":"CONST","name":"32'h0","addr":"(ESB)","loc":"d,11:8,11:9","dtypep":"(EC)"}
|
||||
]}
|
||||
]},
|
||||
{"type":"BASICDTYPE","name":"IData","addr":"(LP)","loc":"a,0:0,0:0","dtypep":"(LP)","keyword":"IData","range":"31:0","generic":true,"rangep": []},
|
||||
|
|
@ -3013,9 +3014,9 @@
|
|||
]},
|
||||
{"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0",
|
||||
"modulep": [
|
||||
{"type":"MODULE","name":"@CONST-POOL@","addr":"(ESB)","loc":"a,0:0,0:0","isChecker":false,"isProgram":false,"hasGenericIface":false,"origName":"@CONST-POOL@","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"NONE","inlinesp": [],
|
||||
{"type":"MODULE","name":"@CONST-POOL@","addr":"(FSB)","loc":"a,0:0,0:0","isChecker":false,"isProgram":false,"hasGenericIface":false,"origName":"@CONST-POOL@","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"NONE","inlinesp": [],
|
||||
"stmtsp": [
|
||||
{"type":"SCOPE","name":"TOP","addr":"(FSB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(ESB)","varsp": [],"blocksp": [],"inlinesp": []}
|
||||
{"type":"SCOPE","name":"TOP","addr":"(GSB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(FSB)","varsp": [],"blocksp": [],"inlinesp": []}
|
||||
]}
|
||||
]}
|
||||
]}
|
||||
|
|
|
|||
|
|
@ -1786,6 +1786,7 @@
|
|||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck__Syms.h"/>
|
||||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck.h"/>
|
||||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck.cpp"/>
|
||||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck__pch.h"/>
|
||||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck_$root.h"/>
|
||||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck_$unit.h"/>
|
||||
<cfile loc="a,0,0,0,0" name="obj_vlt/t_xml_debugcheck/Vt_xml_debugcheck_$root__Slow.cpp"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue