Make emitVarDecl and emitModCUse reusable via V3EmitCBase.

Moved these 2 function into V3EmitCBase so we can reuse them later.
emitVarDecl required minor alteration to move building of m_ctorVarsVec
back into V3EmitC (which is now done in V3EmitC::emitSortedVarList).
No functional change intended.
This commit is contained in:
Geza Lore 2021-06-24 17:08:07 +01:00
parent 5250408019
commit bbbee8b89e
3 changed files with 104 additions and 98 deletions

View File

@ -23,7 +23,6 @@
#include "V3EmitCBase.h"
#include "V3Number.h"
#include "V3PartitionGraph.h"
#include "V3Task.h"
#include "V3TSP.h"
#include <algorithm>
@ -80,7 +79,6 @@ public:
void displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const string& vfmt, bool ignore,
char fmtLetter);
void emitVarDecl(const AstVar* nodep, const string& prefixIfImp);
enum EisWhich : uint8_t {
EVL_CLASS_IO,
EVL_CLASS_SIG,
@ -116,14 +114,6 @@ public:
void emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, AstNode* rhsp,
AstNode* thsp);
void emitDeclArrayBrackets(const AstVar* nodep) {
// This isn't very robust and may need cleanup for other data types
for (const AstUnpackArrayDType* arrayp
= VN_CAST_CONST(nodep->dtypeSkipRefp(), UnpackArrayDType);
arrayp; arrayp = VN_CAST_CONST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
puts("[" + cvtToStr(arrayp->elementsConst()) + "]");
}
}
void emitTypedefs(AstNode* firstp) {
bool first = true;
for (AstNode* loopp = firstp; loopp; loopp = loopp->nextp()) {
@ -1742,24 +1732,6 @@ class EmitCImp final : EmitCStmts {
// METHODS
// Low level
void emitModCUse(AstNodeModule* modp, VUseType useType) {
string nl;
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
if (AstCUse* usep = VN_CAST(itemp, CUse)) {
if (usep->useType() == useType) {
if (usep->useType().isInclude()) {
puts("#include \"" + prefixNameProtect(usep) + ".h\"\n");
}
if (usep->useType().isFwdClass()) {
puts("class " + prefixNameProtect(usep) + ";\n");
}
nl = "\n";
}
}
}
puts(nl);
}
void emitVarReset(AstVar* varp) {
AstNodeDType* const dtypep = varp->dtypep()->skipRefp();
const string varNameProtected
@ -1906,75 +1878,6 @@ public:
//######################################################################
// Internal EmitCStmts
void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
AstBasicDType* basicp = nodep->basicp();
if (nodep->isIO() && nodep->isSc()) {
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
m_ctorVarsVec.push_back(nodep);
if (nodep->attrScClocked() && nodep->isReadOnly()) {
puts("sc_in_clk ");
} else {
if (nodep->isInoutish()) {
puts("sc_inout<");
} else if (nodep->isWritable()) {
puts("sc_out<");
} else if (nodep->isNonOutput()) {
puts("sc_in<");
} else {
nodep->v3fatalSrc("Unknown type");
}
puts(nodep->scType());
puts("> ");
}
puts(nodep->nameProtect());
emitDeclArrayBrackets(nodep);
puts(";\n");
} else if (nodep->isIO() && basicp && !basicp->isOpaque()) {
if (nodep->isInoutish()) {
puts("VL_INOUT");
} else if (nodep->isWritable()) {
puts("VL_OUT");
} else if (nodep->isNonOutput()) {
puts("VL_IN");
} else {
nodep->v3fatalSrc("Unknown type");
}
if (nodep->isQuad()) {
puts("64");
} else if (nodep->widthMin() <= 8) {
puts("8");
} else if (nodep->widthMin() <= 16) {
puts("16");
} else if (nodep->isWide()) {
puts("W");
}
puts("(" + nodep->nameProtect());
emitDeclArrayBrackets(nodep);
// If it's a packed struct/array then nodep->width is the whole
// thing, msb/lsb is just lowest dimension
puts("," + cvtToStr(basicp->lo() + nodep->width() - 1) + "," + cvtToStr(basicp->lo()));
if (nodep->isWide()) puts("," + cvtToStr(nodep->widthWords()));
puts(");\n");
} else {
if (basicp && basicp->keyword().isMTaskState()) { m_ctorVarsVec.push_back(nodep); }
// strings and other fundamental c types
if (nodep->isFuncLocal() && nodep->isString()) {
const string name = nodep->name();
const string suffix = V3Task::dpiTemporaryVarSuffix();
// string temporary variable for DPI-C needs to be static because c_str() will be
// passed to C code and the lifetime of the variable must be long enough. See also
// Issue 2622.
const bool beStatic = name.size() >= suffix.size()
&& name.substr(name.size() - suffix.size()) == suffix;
if (beStatic) puts("static VL_THREAD_LOCAL ");
}
puts(nodep->vlArgType(true, false, false, prefixIfImp));
puts(";\n");
}
}
void EmitCStmts::emitCtorSep(bool* firstp) {
if (*firstp) {
puts(" : ");
@ -3084,7 +2987,12 @@ void EmitCStmts::emitSortedVarList(const VarVec& anons, const VarVec& nonanons,
}
}
// Output nonanons
for (const AstVar* varp : nonanons) { emitVarDecl(varp, prefixIfImp); }
for (const AstVar* varp : nonanons) {
if (varp->isIO() && varp->isSc()) { m_ctorVarsVec.push_back(varp); }
AstBasicDType* const basicp = varp->basicp();
if (basicp && basicp->keyword().isMTaskState()) { m_ctorVarsVec.push_back(varp); }
emitVarDecl(varp, prefixIfImp);
}
}
void EmitCImp::emitThreadingState() {

View File

@ -18,6 +18,7 @@
#include "verilatedos.h"
#include "V3EmitCBase.h"
#include "V3Task.h"
//######################################################################
// EmitCBaseVisitor implementation
@ -106,3 +107,98 @@ void EmitCBaseVisitor::emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule*
puts(";\n");
if (!funcp->ifdef().empty()) puts("#endif // " + funcp->ifdef() + "\n");
}
void EmitCBaseVisitor::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
const AstBasicDType* const basicp = nodep->basicp();
const auto emitDeclArrayBrackets = [this](const AstVar* nodep) -> void {
// This isn't very robust and may need cleanup for other data types
for (const AstUnpackArrayDType* arrayp
= VN_CAST_CONST(nodep->dtypeSkipRefp(), UnpackArrayDType);
arrayp; arrayp = VN_CAST_CONST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
puts("[" + cvtToStr(arrayp->elementsConst()) + "]");
}
};
if (nodep->isIO() && nodep->isSc()) {
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
if (nodep->attrScClocked() && nodep->isReadOnly()) {
puts("sc_in_clk ");
} else {
if (nodep->isInoutish()) {
puts("sc_inout<");
} else if (nodep->isWritable()) {
puts("sc_out<");
} else if (nodep->isNonOutput()) {
puts("sc_in<");
} else {
nodep->v3fatalSrc("Unknown type");
}
puts(nodep->scType());
puts("> ");
}
puts(nodep->nameProtect());
emitDeclArrayBrackets(nodep);
puts(";\n");
} else if (nodep->isIO() && basicp && !basicp->isOpaque()) {
if (nodep->isInoutish()) {
puts("VL_INOUT");
} else if (nodep->isWritable()) {
puts("VL_OUT");
} else if (nodep->isNonOutput()) {
puts("VL_IN");
} else {
nodep->v3fatalSrc("Unknown type");
}
if (nodep->isQuad()) {
puts("64");
} else if (nodep->widthMin() <= 8) {
puts("8");
} else if (nodep->widthMin() <= 16) {
puts("16");
} else if (nodep->isWide()) {
puts("W");
}
puts("(" + nodep->nameProtect());
emitDeclArrayBrackets(nodep);
// If it's a packed struct/array then nodep->width is the whole
// thing, msb/lsb is just lowest dimension
puts("," + cvtToStr(basicp->lo() + nodep->width() - 1) + "," + cvtToStr(basicp->lo()));
if (nodep->isWide()) puts("," + cvtToStr(nodep->widthWords()));
puts(");\n");
} else {
// strings and other fundamental c types
if (nodep->isFuncLocal() && nodep->isString()) {
const string name = nodep->name();
const string suffix = V3Task::dpiTemporaryVarSuffix();
// string temporary variable for DPI-C needs to be static because c_str() will be
// passed to C code and the lifetime of the variable must be long enough. See also
// Issue 2622.
const bool beStatic = name.size() >= suffix.size()
&& name.substr(name.size() - suffix.size()) == suffix;
if (beStatic) puts("static VL_THREAD_LOCAL ");
}
puts(nodep->vlArgType(true, false, false, prefixIfImp));
puts(";\n");
}
}
void EmitCBaseVisitor::emitModCUse(AstNodeModule* modp, VUseType useType) {
string nl;
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
if (AstCUse* usep = VN_CAST(itemp, CUse)) {
if (usep->useType() == useType) {
if (usep->useType().isInclude()) {
puts("#include \"" + prefixNameProtect(usep) + ".h\"\n");
}
if (usep->useType().isFwdClass()) {
puts("class " + prefixNameProtect(usep) + ";\n");
}
nl = "\n";
}
}
}
puts(nl);
}

View File

@ -83,6 +83,8 @@ public:
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);
void emitVarDecl(const AstVar* nodep, const string& prefixIfImp);
void emitModCUse(AstNodeModule* modp, VUseType useType);
// CONSTRUCTORS
EmitCBaseVisitor() = default;