mirror of
https://github.com/verilator/verilator.git
synced 2025-02-02 03:34:05 +00:00
900c023bb5
The main goal of this patch is to enable splitting the full and incremental tracing functions into multiple functions, which can then be run in parallel at a later stage. It also simplifies further experimentation as all of the interesting trace code construction now happens in V3Trace. No functional change is intended by this patch, but there are some implementation changes in the generated code. Highlights: - Pass symbol table directly to trace callbacks for simplicity. - A new traceRegister function is generated which adds each trace function as an individual callback, which means we can have multiple callbacks for each trace function type. - A new traceCleanup function is generated which clears the activity flags, as the trace callbacks might be implemented as multiple functions. - Re-worked sub-function handling so there is no separate sub-function for each trace activity class. Sub-functions are generate when required by splitting. - traceFull/traceChg are now created in V3Trace rather than V3TraceDecl, this requires carrying the trace value tree in TraceDecl until it reaches V3Trace where the TraceInc nodes are created (previously a TraceInc was also created in V3TraceDecl which carries the value).
140 lines
5.0 KiB
C++
140 lines
5.0 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
//*************************************************************************
|
|
//
|
|
// Copyright 2003-2020 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 _V3EMITCBASE_H_
|
|
#define _V3EMITCBASE_H_ 1
|
|
|
|
#include "config_build.h"
|
|
#include "verilatedos.h"
|
|
|
|
#include "V3Global.h"
|
|
#include "V3File.h"
|
|
#include "V3Ast.h"
|
|
|
|
#include <cstdarg>
|
|
#include <cmath>
|
|
|
|
//######################################################################
|
|
// Base Visitor class -- holds output file pointer
|
|
|
|
class EmitCBaseVisitor : public AstNVisitor {
|
|
public:
|
|
// STATE
|
|
V3OutCFile* m_ofp;
|
|
bool m_trackText; // Always track AstText nodes
|
|
// METHODS
|
|
V3OutCFile* ofp() const { return m_ofp; }
|
|
void puts(const string& str) { ofp()->puts(str); }
|
|
void putbs(const string& str) { ofp()->putbs(str); }
|
|
void putsDecoration(const string& str) {
|
|
if (v3Global.opt.decoration()) puts(str);
|
|
}
|
|
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
|
bool optSystemC() { return v3Global.opt.systemC(); }
|
|
static string protect(const string& name) { return VIdProtect::protectIf(name, true); }
|
|
static string protectIf(const string& name, bool doIt) {
|
|
return VIdProtect::protectIf(name, doIt);
|
|
}
|
|
static string protectWordsIf(const string& name, bool doIt) {
|
|
return VIdProtect::protectWordsIf(name, doIt);
|
|
}
|
|
static string ifNoProtect(const string& in) { return v3Global.opt.protectIds() ? "" : in; }
|
|
static string symClassName() { return v3Global.opt.prefix() + "_" + protect("_Syms"); }
|
|
static string symClassVar() { return symClassName() + "* __restrict vlSymsp"; }
|
|
static string symTopAssign() {
|
|
return v3Global.opt.prefix() + "* const __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;";
|
|
}
|
|
static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp) {
|
|
if (nodep->isConstructor()) {
|
|
return prefixNameProtect(modp);
|
|
} else if (nodep->isDestructor()) {
|
|
return string("~") + prefixNameProtect(modp);
|
|
} else {
|
|
return nodep->nameProtect();
|
|
}
|
|
}
|
|
static string prefixNameProtect(const AstNode* nodep) { // C++ name with prefix
|
|
const AstNodeModule* modp = VN_CAST_CONST(nodep, NodeModule);
|
|
if (modp && modp->isTop()) {
|
|
return v3Global.opt.prefix();
|
|
} else {
|
|
return v3Global.opt.modPrefix() + "_" + protect(nodep->name());
|
|
}
|
|
}
|
|
static string topClassName() { // Return name of top wrapper module
|
|
return v3Global.opt.prefix();
|
|
}
|
|
static AstCFile* newCFile(const string& filename, bool slow, bool source) {
|
|
AstCFile* cfilep = new AstCFile(v3Global.rootp()->fileline(), filename);
|
|
cfilep->slow(slow);
|
|
cfilep->source(source);
|
|
v3Global.rootp()->addFilesp(cfilep);
|
|
return cfilep;
|
|
}
|
|
string cFuncArgs(const AstCFunc* nodep) {
|
|
// Return argument list for given C function
|
|
string args = nodep->argTypes();
|
|
// Might be a user function with argument list.
|
|
for (const AstNode* stmtp = nodep->argsp(); stmtp; stmtp = stmtp->nextp()) {
|
|
if (const AstVar* portp = VN_CAST_CONST(stmtp, Var)) {
|
|
if (portp->isIO() && !portp->isFuncReturn()) {
|
|
if (args != "") args += ", ";
|
|
if (nodep->dpiImport() || nodep->dpiExportWrapper()) {
|
|
args += portp->dpiArgType(true, false);
|
|
} else if (nodep->funcPublic()) {
|
|
args += portp->cPubArgType(true, false);
|
|
} else {
|
|
args += portp->vlArgType(true, false, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return args;
|
|
}
|
|
|
|
// CONSTRUCTORS
|
|
EmitCBaseVisitor() {
|
|
m_ofp = NULL;
|
|
m_trackText = false;
|
|
}
|
|
virtual ~EmitCBaseVisitor() {}
|
|
};
|
|
|
|
//######################################################################
|
|
// Count operations under the given node, as a visitor of each AstNode
|
|
|
|
class EmitCBaseCounterVisitor : public AstNVisitor {
|
|
private:
|
|
// MEMBERS
|
|
int m_count; // Number of statements
|
|
// VISITORS
|
|
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
|
m_count++;
|
|
iterateChildren(nodep);
|
|
}
|
|
|
|
public:
|
|
// CONSTRUCTORS
|
|
explicit EmitCBaseCounterVisitor(AstNode* nodep) {
|
|
m_count = 0;
|
|
iterate(nodep);
|
|
}
|
|
virtual ~EmitCBaseCounterVisitor() {}
|
|
int count() const { return m_count; }
|
|
};
|
|
|
|
#endif // guard
|