Rework variable emit to prep for other data types.

This commit is contained in:
Wilson Snyder 2019-11-12 21:52:25 -05:00
parent 77e30d4920
commit 21a380def0
4 changed files with 112 additions and 128 deletions

View File

@ -221,13 +221,6 @@ public:
//=========================================================================
// Declare nets
#ifndef VL_ST_SIG
# define VL_ST_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits
# define VL_ST_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits
# define VL_ST_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits
# define VL_ST_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits
# define VL_ST_SIGW(name,msb,lsb,words) WData name[words] ///< Declare signal, 65+ bits
#endif
#ifndef VL_SIG
# define VL_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits
# define VL_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits

View File

@ -226,72 +226,92 @@ string AstVar::verilogKwd() const {
}
}
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
class AstVar::VlArgTypeRecurseInfo {
public:
bool m_named;
bool m_forFunc;
bool m_mayParen;
string m_namespc;
string paren(const string& s) {
if (m_mayParen) { m_mayParen = false; return " ("+s+")"; }
else return s;
}
};
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc) const {
UASSERT_OBJ(!forReturn, this,
"Internal data is never passed as return, but as first argument");
string otype;
AstBasicDType* bdtypep = basicp();
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
otype += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
otype += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "float";
} else if (strtype) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "std::string";
} else if (widthMin() <= 8) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "CData";
} else if (widthMin() <= 16) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "SData";
} else if (widthMin() <= VL_WORDSIZE) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "IData";
} else if (isQuad()) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "QData";
} else if (isWide()) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "WData"; // []'s added later
}
VlArgTypeRecurseInfo info;
info.m_named = named;
info.m_forFunc = forFunc;
info.m_mayParen = false;
info.m_namespc = namespc;
bool mayparen = false; // Need paren, to handle building "(& name)[2]"
string oname;
if (isDpiOpenArray()
|| (isWide() && !strtype)
|| (forFunc && (isWritable()
|| direction()==VDirection::REF
|| direction()==VDirection::CONSTREF
|| (strtype && isNonOutput())))) {
oname += "&";
mayparen = true;
}
if (named) oname += " "+VIdProtect::protectIf(name(), protect());
string ostatic;
if (isStatic() && info.m_namespc.empty()) ostatic = "static ";
return ostatic + vlArgTypeRecurse(dtypep(), &info, "");
}
string oarray;
if (isDpiOpenArray() || direction().isRefOrConstRef()) {
for (AstNodeDType* dtp=dtypep(); dtp; ) {
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstUnpackArrayDType* adtypep = VN_CAST(dtp, UnpackArrayDType)) {
if (mayparen) { oname = " ("+oname+")"; mayparen = false; }
oarray += "["+cvtToStr(adtypep->declRange().elements())+"]";
dtp = adtypep->subDTypep();
} else break;
string AstVar::vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* infop,
const string& inarray) const {
dtypep = dtypep->skipRefp();
if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
string oarray = "["+cvtToStr(adtypep->declRange().elements())+"]";
return vlArgTypeRecurse(adtypep->subDTypep(), infop, inarray+oarray);
} else if (AstBasicDType* bdtypep = basicp()) {
string otype;
string oarray = inarray;
bool strtype = bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::STRING;
string bitvec;
if (bdtypep && !bdtypep->isOpaque() && !v3Global.opt.protectIds()) {
bitvec = ("/*"+cvtToStr(bdtypep->lsb()+bdtypep->width()-1)
+":"+cvtToStr(bdtypep->lsb())+"*/");
}
if ((infop->m_forFunc && isReadOnly())
|| bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR
|| bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) otype += "const ";
if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) {
otype += "char*";
} else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) {
otype += "VerilatedScope*";
} else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) {
otype += "double";
} else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) {
otype += "float";
} else if (strtype) {
otype += "std::string";
} else if (widthMin() <= 8) {
otype += "CData"+bitvec;
} else if (widthMin() <= 16) {
otype += "SData"+bitvec;
} else if (widthMin() <= VL_WORDSIZE) {
otype += "IData"+bitvec;
} else if (isQuad()) {
otype += "QData"+bitvec;
} else if (isWide()) {
otype += "WData"+bitvec; // []'s added later
oarray += "["+cvtToStr(widthWords())+"]";
}
string oname;
if (isDpiOpenArray()
|| (infop->m_forFunc && (isWritable()
|| direction() == VDirection::REF
|| direction() == VDirection::CONSTREF
|| (strtype && isNonOutput())))) {
oname += "&";
infop->m_mayParen = true;
}
if (infop->m_named) {
oname += " ";
if (!infop->m_namespc.empty()) oname += infop->m_namespc+"::";
oname += VIdProtect::protectIf(name(), protect());
}
if (!oarray.empty()) oname = infop->paren(oname);
return otype+oname+oarray;
} else {
v3fatalSrc("Unknown data type in var type emitter: "<<dtypep->prettyName());
}
if (isWide() && !strtype) {
if (mayparen) { oname = " ("+oname+")"; mayparen = false; }
oarray += "["+cvtToStr(widthWords())+"]";
}
if (mayparen) { }
return otype+oname+oarray;
}
string AstVar::vlEnumType() const {

View File

@ -1271,7 +1271,7 @@ public:
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
// Return Verilator internal type for argument: CData, SData, IData, WData
string vlArgType(bool named, bool forReturn, bool forFunc) const;
string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc="") const;
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
string vlPropInit() const; // Return VerilatorVarProps initializer
@ -1410,6 +1410,10 @@ public:
void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); }
const MTaskIdSet& mtaskIds() const { return m_mtaskIds; }
string mtasksString() const;
private:
class VlArgTypeRecurseInfo;
string vlArgTypeRecurse(AstNodeDType* dtypep, VlArgTypeRecurseInfo* infop,
const string& oarray) const;
};
class AstDefParam : public AstNode {

View File

@ -1303,71 +1303,34 @@ public:
void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
AstBasicDType* basicp = nodep->basicp();
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
if (nodep->isIO()) {
if (nodep->isSc()) {
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 (basicp && basicp->isOpaque()) {
// strings and other fundamental c types; no VL_ macro can be used
puts(nodep->vlArgType(true, false, false));
emitDeclArrayBrackets(nodep);
puts(";\n");
} else { // C++ signals
if (nodep->isInoutish()) puts("VL_INOUT");
else if (nodep->isWritable()) puts("VL_OUT");
else if (nodep->isNonOutput()) puts("VL_IN");
if (nodep->isIO() && nodep->isSc()) {
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");
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->lsb()+nodep->width()-1)
+","+cvtToStr(basicp->lsb()));
if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords()));
puts(");\n");
puts(nodep->scType());
puts("> ");
}
} else if (basicp && basicp->isOpaque()) {
// strings and other fundamental c types
puts(nodep->vlArgType(true, false, false));
puts(nodep->nameProtect());
emitDeclArrayBrackets(nodep);
puts(";\n");
} else {
// Arrays need a small alignment, but may need different padding after.
// For example three VL_SIG8's needs alignment 1 but size 3.
if (nodep->isStatic() && prefixIfImp=="") puts("static ");
if (nodep->isStatic()) puts("VL_ST_"); else puts("VL_");
if (nodep->widthMin() <= 8) {
puts("SIG8(");
} else if (nodep->widthMin() <= 16) {
puts("SIG16(");
} else if (nodep->isQuad()) {
puts("SIG64(");
} else if (!nodep->isWide()) {
puts("SIG(");
} else {
puts("SIGW(");
}
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
puts(nodep->nameProtect());
} 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
@ -1375,6 +1338,10 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
+","+cvtToStr(basicp->lsb()));
if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords()));
puts(");\n");
} else {
// strings and other fundamental c types
puts(nodep->vlArgType(true, false, false, prefixIfImp));
puts(";\n");
}
}