diff --git a/src/V3Ast.h b/src/V3Ast.h index 7a10bc232..9dd499dfd 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -209,7 +209,7 @@ class AstBasicDTypeKwd { public: enum en { BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT, - REAL, REALTIME, SHORTINT, SHORTREAL, TIME, + REAL, SHORTINT, SHORTREAL, TIME, // Closer to a class type, but limited usage STRING, // Internal types for mid-steps @@ -221,7 +221,7 @@ public: const char* ascii() const { static const char* names[] = { "bit", "byte", "chandle", "int", "integer", "logic", "longint", - "real", "realtime", "shortint", "shortreal", "time", + "real", "shortint", "shortreal", "time", "string", "VerilatedScope*", "char*", "LOGIC_IMPLICIT" @@ -231,7 +231,7 @@ public: const char* dpiType() const { static const char* names[] = { "unsigned char", "char", "void*", "int", "int", "svLogic", "long long", - "double", "double", "short int", "float", "long long", + "double", "short int", "float", "long long", "const char*", "dpiScope", "const char*", "" @@ -251,6 +251,8 @@ public: case INTEGER: return 32; case LOGIC: return 1; case LONGINT: return 64; + case REAL: return 64; + case SHORTREAL: return 32; case SHORTINT: return 16; case TIME: return 64; case STRING: return 64; // Just the pointer, for today @@ -265,7 +267,7 @@ public: } bool isZeroInit() const { // Otherwise initializes to X return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT - || m_e==STRING); + || m_e==STRING || m_e==REAL || m_e==SHORTREAL); } bool isSloppy() const { // Don't be as anal about width warnings return !(m_e==LOGIC || m_e==BIT); @@ -274,10 +276,13 @@ public: return (m_e==LOGIC || m_e==BIT); } bool isDpiUnsupported() const { - return (m_e==LOGIC || m_e==TIME || m_e==REALTIME); + return (m_e==LOGIC || m_e==TIME); } bool isOpaque() const { // IE not a simple number we can bit optimize - return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR); + return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==REAL || m_e==SHORTREAL); + } + bool isReal() const { + return (m_e==REAL); } }; inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 19ca280d9..3a133e3d6 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const { arg += "const char*"; } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) { arg += "const VerilatedScope*"; + } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::REAL) { + arg += "double"; + } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SHORTREAL) { + arg += "float"; } else if (strtype) { if (isInOnly()) arg += "const "; arg += "string"; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index d160d3857..179aa09a5 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1519,7 +1519,7 @@ private: if (!inPct && ch=='%') { inPct = true; fmt = ch; - } else if (inPct && isdigit(ch)) { + } else if (inPct && (isdigit(ch) || ch=='.')) { fmt += ch; } else if (inPct) { inPct = false; diff --git a/src/V3Signed.cpp b/src/V3Signed.cpp index 51469ae40..9563c6d77 100644 --- a/src/V3Signed.cpp +++ b/src/V3Signed.cpp @@ -48,7 +48,6 @@ class SignedVisitor : public AstNVisitor { private: // NODE STATE/TYPES // STATE - int m_taskDepth; // Recursion check bool m_paramsOnly; // Computing parameter value; limit operation // METHODS - special type detection @@ -62,8 +61,8 @@ private: // VISITORS //======== // Signed: Output explicit by user, Lhs either - virtual void visit(AstSigned* nodep, AstNUser*) { signed_Os_Ix(nodep); } virtual void visit(AstUnsigned* nodep, AstNUser*) { signed_Ou_Ix(nodep); } + virtual void visit(AstSigned* nodep, AstNUser*) { signed_Os_Ix(nodep); } //======== // Signed: Output unsigned, Operands either @@ -291,6 +290,18 @@ private: // ShiftRS converts to ShiftR, but not vice-versa virtual void visit(AstShiftRS* nodep, AstNUser*) { checkReplace_Olhs(nodep); } + // VISITORS - defaults + virtual void visit(AstNodeMath* nodep, AstNUser*) { + nodep->v3fatalSrc("Visit function missing? Signedness unknown for this node: "<iterateChildren(*this); + } + virtual void visit(AstNode* nodep, AstNUser*) { + nodep->iterateChildren(*this); + } + + //======= + // Lower level functions + void checkReplace_Ou_FlavLhsAndRhs(AstNodeBiop* nodep) { // For compares, the output of the comparison is unsigned. // However, we need the appropriate type of compare selected by RHS & LHS @@ -336,15 +347,6 @@ private: } } - // VISITORS - defaults - virtual void visit(AstNodeMath* nodep, AstNUser*) { - nodep->v3fatalSrc("Visit function missing? Signedness unknown for this node: "<iterateChildren(*this); - } - virtual void visit(AstNode* nodep, AstNUser*) { - nodep->iterateChildren(*this); - } - // COMMON SCHEMES // Signed: Output signed, Lhs/Rhs/etc either void signed_Os_Ix(AstNode* nodep) { @@ -392,7 +394,6 @@ public: // CONSTRUCTORS SignedVisitor(bool paramsOnly) { m_paramsOnly = paramsOnly; - m_taskDepth = 0; } virtual ~SignedVisitor() {} AstNode* mainAcceptEdit(AstNode* nodep) { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 1f21e776d..3e7cf6acc 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -173,6 +173,14 @@ private: virtual void visit(AstShiftR* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } virtual void visit(AstShiftRS* nodep, AstNUser* vup) { width_Olhs_L_R32(nodep,vup); } + // Widths: Fixed + void width_Ofixed_L(AstNodeUniop* nodep, AstNUser* vup, int width); + + // Widths: Constant, terminal + virtual void visit(AstTime* nodep, AstNUser*) { nodep->width(64,64); } + virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { nodep->width(32,32); } + virtual void visit(AstScopeName* nodep, AstNUser* vup) { nodep->width(64,1); } // A pointer, but not that it matters + // Special cases. So many.... virtual void visit(AstNodeCond* nodep, AstNUser* vup) { // op=cond?expr1:expr2 is a Good large example of the propagation mess @@ -431,9 +439,6 @@ private: nodep->width(32,32); // Says the spec } } - virtual void visit(AstTime* nodep, AstNUser*) { - nodep->width(64,64); - } virtual void visit(AstUCFunc* nodep, AstNUser* vup) { // Give it the size the user wants. if (vup && vup->c()->prelim()) { @@ -470,9 +475,6 @@ private: virtual void visit(AstText* nodep, AstNUser* vup) { // Only used in CStmts which don't care.... } - virtual void visit(AstScopeName* nodep, AstNUser* vup) { - nodep->width(64,1); // A pointer, but not that it matters - } virtual void visit(AstArrayDType* nodep, AstNUser* vup) { // Lower datatype determines the width nodep->dtypep()->iterateAndNext(*this,vup); @@ -829,9 +831,6 @@ private: nodep->lsbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->msbp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); } - virtual void visit(AstTestPlusArgs* nodep, AstNUser* vup) { - nodep->width(32,32); - } virtual void visit(AstValuePlusArgs* nodep, AstNUser* vup) { nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->width(32,32); @@ -1305,6 +1304,15 @@ void WidthVisitor::width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup) { } } +void WidthVisitor::width_Ofixed_L(AstNodeUniop* nodep, AstNUser* vup, int width) { + // Widths: out width = specified width + if (nodep->op2p()) nodep->v3fatalSrc("For unary ops only!"); + if (vup->c()->prelim()) { + nodep->op1p()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + } + nodep->width(width,width); +} + void WidthVisitor::width_Olhs_L(AstNodeUniop* nodep, AstNUser* vup) { // Widths: out width = lhs width // "Interim results shall take the max of operands, including LHS of assignments"