Support 'real' numbers and related functions.

This commit is contained in:
Wilson Snyder 2011-07-24 15:01:51 -04:00
parent d5478e6e08
commit 55906486d8
31 changed files with 1502 additions and 807 deletions

View File

@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.814**** * Verilator 3.814****
** Support 'real' numbers and related functions.
*** Support 'const' variables in limited cases; similar to enums. [Alex Solomatnikov] *** Support 'const' variables in limited cases; similar to enums. [Alex Solomatnikov]
*** Support disable for loop escapes. *** Support disable for loop escapes.

View File

@ -930,8 +930,8 @@ Enables the specified warning message.
Enable all lint related warning messages (note by default they are already Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX "-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED -Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
-Wwarn-WIDTH". -Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style =item -Wwarn-style
@ -2096,7 +2096,7 @@ that Verilator will print a list of known scopes to help your debugging.
=head2 Floating Point =head2 Floating Point
Floating Point numbers are not synthesizable, and so not supported. Floating Point (real) numbers are supported.
=head2 Latches =head2 Latches
@ -2336,10 +2336,6 @@ Read memory commands should work properly. Note Verilator and the Verilog
specification does not include support for readmem to multi-dimensional specification does not include support for readmem to multi-dimensional
arrays. arrays.
=item $realtime
Treated as $time.
=item $test$plusargs, $value$plusargs =item $test$plusargs, $value$plusargs
Supported, but the instantiating C++/SystemC testbench must call Supported, but the instantiating C++/SystemC testbench must call
@ -2619,6 +2615,11 @@ not really needed. The best solution is to insure that each module is in a
unique file by the same name. Otherwise, make sure all library files are unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y. read in as libraries with -v, instead of automatically with -y.
=item REALCVT
Warns that a real number is being implicitly rounded to an integer, with
possible loss of precision.
=item REDEFMACRO =item REDEFMACRO
Warns that you have redefined the same macro with a different value, for Warns that you have redefined the same macro with a different value, for

View File

@ -209,7 +209,6 @@ RAW_OBJS = \
V3PreShell.o \ V3PreShell.o \
V3Premit.o \ V3Premit.o \
V3Scope.o \ V3Scope.o \
V3Signed.o \
V3Slice.o \ V3Slice.o \
V3Split.o \ V3Split.o \
V3SplitAs.o \ V3SplitAs.o \

View File

@ -817,6 +817,8 @@ public:
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
@ -1323,7 +1325,6 @@ private:
string m_name; // Name of task string m_name; // Name of task
string m_cname; // Name of task if DPI import string m_cname; // Name of task if DPI import
bool m_taskPublic:1; // Public task bool m_taskPublic:1; // Public task
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_attrIsolateAssign:1;// User isolate_assignments attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_prototype:1; // Just a prototype bool m_prototype:1; // Just a prototype
bool m_dpiExport:1; // DPI exported bool m_dpiExport:1; // DPI exported
@ -1334,7 +1335,7 @@ private:
public: public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp) AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline) : AstNode(fileline)
, m_name(name), m_taskPublic(false), m_didSigning(false) , m_name(name), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false) , m_attrIsolateAssign(false), m_prototype(false)
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false) , m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
, m_dpiTask(false), m_pure(false) { , m_dpiTask(false), m_pure(false) {
@ -1361,8 +1362,6 @@ public:
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; } void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; } bool taskPublic() const { return m_taskPublic; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; } bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; } void prototype(bool flag) { m_prototype = flag; }

View File

@ -503,6 +503,7 @@ void AstNode::dump(ostream& os) {
<<((editCount()>=editCountLast())?"#>":">") <<((editCount()>=editCountLast())?"#>":">")
<<" {"<<dec<<fileline()->lineno()<<"}" <<" {"<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"") <<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width(); <<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) os<<"/"<<widthMin(); if (!widthSized()) os<<"/"<<widthMin();
if (name()!="") os<<" "<<AstNode::quoteName(name()); if (name()!="") os<<" "<<AstNode::quoteName(name());

View File

@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
private: private:
V3Number m_num; // Constant value V3Number m_num; // Constant value
public: public:
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, const V3Number& num) AstConst(FileLine* fl, const V3Number& num)
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(num) { ,m_num(num) {
width(m_num.width(), m_num.sized()?0:m_num.minWidth()); width(m_num.width(), m_num.sized()?0:m_num.minWidth());
isSigned(m_num.isSigned()); numeric(m_num.isDouble() ? AstNumeric::DOUBLE
: m_num.isSigned() ? AstNumeric::SIGNED
: AstNumeric::UNSIGNED);
} }
AstConst(FileLine* fl, uint32_t num) AstConst(FileLine* fl, uint32_t num)
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); } ,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); }
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); } ,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); }
class RealDouble {}; // for creator type-overload selection
AstConst(FileLine* fl, RealDouble, double num)
:AstNodeMath(fl)
,m_num(V3Number(fl,64)) { m_num.setDouble(num); numeric(AstNumeric::DOUBLE); }
class LogicFalse {}; class LogicFalse {};
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1 AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
:AstNodeMath(fl) :AstNodeMath(fl)
@ -258,7 +264,8 @@ private:
m_keyword = AstBasicDTypeKwd::LOGIC; m_keyword = AstBasicDTypeKwd::LOGIC;
} }
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED; if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
setSignedState(signst); if (keyword().isDouble()) numeric(AstNumeric::DOUBLE);
else setSignedState(signst);
if (!rangep) { // Set based on keyword properties if (!rangep) { // Set based on keyword properties
// V3Width will pull from this width // V3Width will pull from this width
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0); if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
@ -278,7 +285,8 @@ public:
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
void rangep(AstRange* nodep) { setNOp1p(nodep); } void rangep(AstRange* nodep) { setNOp1p(nodep); }
void setSignedState(AstSignedState signst) { void setSignedState(AstSignedState signst) {
if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED); if (signst==signedst_UNSIGNED) numeric(AstNumeric::UNSIGNED);
else if (signst==signedst_SIGNED) numeric(AstNumeric::SIGNED);
} }
// METHODS // METHODS
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
@ -581,8 +589,6 @@ private:
bool m_attrClockEn:1;// User clock enable attribute bool m_attrClockEn:1;// User clock enable attribute
bool m_attrIsolateAssign:1;// User isolate_assignments attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_attrSFormat:1;// User sformat attribute bool m_attrSFormat:1;// User sformat attribute
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_didWidth:1; // V3Width completed; can skip iteration
bool m_fileDescr:1; // File descriptor bool m_fileDescr:1; // File descriptor
bool m_isConst:1; // Table contains constant data bool m_isConst:1; // Table contains constant data
bool m_isStatic:1; // Static variable bool m_isStatic:1; // Static variable
@ -596,7 +602,6 @@ private:
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false; m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
m_funcLocal=false; m_funcReturn=false; m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false; m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false;
m_didSigning=false; m_didWidth=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false; m_fileDescr=false; m_isConst=false; m_isStatic=false;
m_trace=false; m_trace=false;
} }
@ -607,6 +612,7 @@ public:
init(); init();
combineType(type); setOp1p(dtypep); combineType(type); setOp1p(dtypep);
if (dtypep && dtypep->basicp()) { if (dtypep && dtypep->basicp()) {
numericFrom(dtypep);
width(dtypep->basicp()->width(), 0); width(dtypep->basicp()->width(), 0);
} else width(1, 0); } else width(1, 0);
} }
@ -626,6 +632,7 @@ public:
if (examplep->dtypep()) { if (examplep->dtypep()) {
setOp1p(examplep->dtypep()->cloneTree(true)); setOp1p(examplep->dtypep()->cloneTree(true));
} }
numericFrom(examplep);
width(examplep->width(), examplep->widthMin()); width(examplep->width(), examplep->widthMin());
} }
ASTNODE_NODE_FUNCS(Var, VAR) ASTNODE_NODE_FUNCS(Var, VAR)
@ -659,10 +666,6 @@ public:
void attrScClocked(bool flag) { m_scClocked = flag; } void attrScClocked(bool flag) { m_scClocked = flag; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
void attrSFormat(bool flag) { m_attrSFormat = flag; } void attrSFormat(bool flag) { m_attrSFormat = flag; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void usedClock(bool flag) { m_usedClock = flag; } void usedClock(bool flag) { m_usedClock = flag; }
void usedParam(bool flag) { m_usedParam = flag; } void usedParam(bool flag) { m_usedParam = flag; }
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; } void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
@ -1454,6 +1457,15 @@ struct AstCondBound : public AstNodeCond {
ASTNODE_NODE_FUNCS(CondBound, CONDBOUND) ASTNODE_NODE_FUNCS(CondBound, CONDBOUND)
}; };
struct AstCondD : public AstNodeCond {
// Conditional ?: statement, double rhs/lhs/out
// Parents: MATH
// Children: MATH
AstCondD(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeCond(fl, condp, expr1p, expr2p) { numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(CondD, CONDD)
};
struct AstCoverDecl : public AstNodeStmt { struct AstCoverDecl : public AstNodeStmt {
// Coverage analysis point declaration // Coverage analysis point declaration
// Parents: {statement list} // Parents: {statement list}
@ -2447,6 +2459,20 @@ struct AstTime : public AstNodeTermop {
virtual bool same(AstNode* samep) const { return true; } virtual bool same(AstNode* samep) const { return true; }
}; };
struct AstTimeD : public AstNodeTermop {
AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(TimeD, TIMED)
virtual string emitVerilog() { return "%f$realtime"; }
virtual string emitC() { return "VL_TIME_D()"; }
virtual bool cleanOut() { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual int instrCount() const { return instrCountTime(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
};
struct AstUCFunc : public AstNodeMath { struct AstUCFunc : public AstNodeMath {
// User's $c function // User's $c function
// Perhaps this should be a AstNodeListop; but there's only one list math right now // Perhaps this should be a AstNodeListop; but there's only one list math right now
@ -2482,9 +2508,22 @@ struct AstNegate : public AstNodeUniop {
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersLhs() {return true;}
}; };
struct AstNegateD : public AstNodeUniop {
AstNegateD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(NegateD, NEGATED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); }
virtual string emitVerilog() { return "%f(- %l)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstRedAnd : public AstNodeUniop { struct AstRedAnd : public AstNodeUniop {
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedAnd, REDAND) ASTNODE_NODE_FUNCS(RedAnd, REDAND)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
virtual string emitVerilog() { return "%f(& %l)"; } virtual string emitVerilog() { return "%f(& %l)"; }
@ -2494,7 +2533,7 @@ struct AstRedAnd : public AstNodeUniop {
}; };
struct AstRedOr : public AstNodeUniop { struct AstRedOr : public AstNodeUniop {
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedOr, REDOR) ASTNODE_NODE_FUNCS(RedOr, REDOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
virtual string emitVerilog() { return "%f(| %l)"; } virtual string emitVerilog() { return "%f(| %l)"; }
@ -2504,7 +2543,7 @@ struct AstRedOr : public AstNodeUniop {
}; };
struct AstRedXor : public AstNodeUniop { struct AstRedXor : public AstNodeUniop {
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXor, REDXOR) ASTNODE_NODE_FUNCS(RedXor, REDXOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
virtual string emitVerilog() { return "%f(^ %l)"; } virtual string emitVerilog() { return "%f(^ %l)"; }
@ -2518,7 +2557,7 @@ struct AstRedXor : public AstNodeUniop {
struct AstRedXnor : public AstNodeUniop { struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const. // AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR) ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
virtual string emitVerilog() { return "%f(~^ %l)"; } virtual string emitVerilog() { return "%f(~^ %l)"; }
@ -2576,7 +2615,7 @@ struct AstExtendS : public AstNodeUniop {
struct AstSigned : public AstNodeUniop { struct AstSigned : public AstNodeUniop {
// $signed(lhs) // $signed(lhs)
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(true); numeric(AstNumeric::SIGNED);
} }
ASTNODE_NODE_FUNCS(Signed, SIGNED) ASTNODE_NODE_FUNCS(Signed, SIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@ -2589,7 +2628,7 @@ struct AstSigned : public AstNodeUniop {
struct AstUnsigned : public AstNodeUniop { struct AstUnsigned : public AstNodeUniop {
// $unsigned(lhs) // $unsigned(lhs)
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(false); numeric(AstNumeric::UNSIGNED);
} }
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED) ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@ -2599,6 +2638,63 @@ struct AstUnsigned : public AstNodeUniop {
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
virtual int instrCount() const { return 0; } virtual int instrCount() const { return 0; }
}; };
struct AstRToIS : public AstNodeUniop {
// $rtoi(lhs)
AstRToIS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
ASTNODE_NODE_FUNCS(RToIS, RTOIS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); }
virtual string emitVerilog() { return "%f$rtoi(%l)"; }
virtual string emitC() { return "VL_RTOI_I_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstRToIRoundS : public AstNodeUniop {
AstRToIRoundS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
ASTNODE_NODE_FUNCS(RToIRoundS, RTOIROUNDS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); }
virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; }
virtual string emitC() { return "VL_RTOIROUND_I_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstIToRD : public AstNodeUniop {
AstIToRD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(IToRD, ITORD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
virtual string emitVerilog() { return "%f$itor(%l)"; }
virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstRealToBits : public AstNodeUniop {
AstRealToBits(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(64,64); }
ASTNODE_NODE_FUNCS(RealToBits, REALTOBITS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); }
virtual string emitVerilog() { return "%f$realtobits(%l)"; }
virtual string emitC() { return "VL_CVT_Q_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstBitsToRealD : public AstNodeUniop {
AstBitsToRealD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(BitsToRealD, BITSTOREALD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); }
virtual string emitVerilog() { return "%f$bitstoreal(%l)"; }
virtual string emitC() { return "VL_CVT_D_Q(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstCLog2 : public AstNodeUniop { struct AstCLog2 : public AstNodeUniop {
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {} AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CLog2, CLOG2) ASTNODE_NODE_FUNCS(CLog2, CLOG2)
@ -2851,6 +2947,20 @@ struct AstEq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstEqD : public AstNodeBiCom {
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(EqD, EQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstNeq : public AstNodeBiCom { struct AstNeq : public AstNodeBiCom {
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) { AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@ -2863,6 +2973,20 @@ struct AstNeq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstNeqD : public AstNodeBiCom {
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(NeqD, NEQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLt : public AstNodeBiop { struct AstLt : public AstNodeBiop {
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@ -2875,6 +2999,20 @@ struct AstLt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstLtD : public AstNodeBiop {
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(LtD, LTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "<"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLtS : public AstNodeBiop { struct AstLtS : public AstNodeBiop {
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@ -2900,6 +3038,20 @@ struct AstGt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstGtD : public AstNodeBiop {
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(GtD, GTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return ">"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstGtS : public AstNodeBiop { struct AstGtS : public AstNodeBiop {
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@ -2925,6 +3077,20 @@ struct AstGte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstGteD : public AstNodeBiop {
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(GteD, GTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return ">="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstGteS : public AstNodeBiop { struct AstGteS : public AstNodeBiop {
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@ -2950,6 +3116,20 @@ struct AstLte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstLteD : public AstNodeBiop {
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(LteD, LTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "<="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLteS : public AstNodeBiop { struct AstLteS : public AstNodeBiop {
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@ -3018,6 +3198,20 @@ struct AstAdd : public AstNodeBiComAsv {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
}; };
struct AstAddD : public AstNodeBiComAsv {
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(AddD, ADDD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "+"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstSub : public AstNodeBiop { struct AstSub : public AstNodeBiop {
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@ -3030,6 +3224,20 @@ struct AstSub : public AstNodeBiop {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
}; };
struct AstSubD : public AstNodeBiop {
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(SubD, SUBD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstMul : public AstNodeBiComAsv { struct AstMul : public AstNodeBiComAsv {
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) { AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@ -3043,6 +3251,20 @@ struct AstMul : public AstNodeBiComAsv {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); } virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
}; };
struct AstMulD : public AstNodeBiComAsv {
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(MulD, MULD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "*"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstMulS : public AstNodeBiComAsv { struct AstMulS : public AstNodeBiComAsv {
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) { AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@ -3069,6 +3291,20 @@ struct AstDiv : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } virtual int instrCount() const { return widthInstrs()*instrCountDiv(); }
}; };
struct AstDivD : public AstNodeBiop {
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(DivD, DIVD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "/"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleDiv(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstDivS : public AstNodeBiop { struct AstDivS : public AstNodeBiop {
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@ -3119,6 +3355,19 @@ struct AstPow : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); } virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
}; };
struct AstPowD : public AstNodeBiop {
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(PowD, POWD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "pow(%li,%ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleDiv(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstPowS : public AstNodeBiop { struct AstPowS : public AstNodeBiop {
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }

View File

@ -148,17 +148,19 @@ private:
bool isCaseTreeFast(AstCase* nodep) { bool isCaseTreeFast(AstCase* nodep) {
int width = 0; int width = 0;
bool opaque = false;
m_caseItems = 0; m_caseItems = 0;
m_caseNoOverlapsAllCovered = true; m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width(); if (icondp->width() > width) width = icondp->width();
if (icondp->isDouble()) opaque = true;
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++; m_caseItems++;
} }
} }
m_caseWidth = width; m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH) { if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
m_caseNoOverlapsAllCovered = false; m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis return false; // Too wide for analysis
} }
@ -348,7 +350,9 @@ private:
and1p = cexprp->cloneTree(false); and1p = cexprp->cloneTree(false);
and2p = icondp; and2p = icondp;
} }
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p); AstNodeBiop* condp = (and1p->isDouble()
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
if (!ifexprp) { if (!ifexprp) {
ifexprp = condp; ifexprp = condp;
} else { } else {

View File

@ -37,7 +37,6 @@
#include "V3Const.h" #include "V3Const.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h"
#include "V3Simulate.h" #include "V3Simulate.h"
//###################################################################### //######################################################################
@ -1783,17 +1782,23 @@ private:
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)"); TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");

View File

@ -545,6 +545,8 @@ public:
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word))); ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
} }
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0))); ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
} else if (nodep->isDouble()) {
ofp()->printf("%g", nodep->num().toDouble());
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
vluint64_t num = nodep->toUQuad(); vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num); if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
@ -2013,7 +2015,9 @@ class EmitCTrace : EmitCStmts {
return varp->isSc() && varp->isScBv(); return varp->isSc() && varp->isScBv();
} }
void emitTraceInitOne(AstTraceDecl* nodep) { void emitTraceInitOne(AstTraceDecl* nodep) {
if (nodep->isWide()) { if (nodep->isDouble()) {
puts("vcdp->declDouble");
} else if (nodep->isWide()) {
puts("vcdp->declArray"); puts("vcdp->declArray");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->declQuad "); puts("vcdp->declQuad ");
@ -2042,7 +2046,9 @@ class EmitCTrace : EmitCStmts {
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB) || m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
? "full":"chg"); ? "full":"chg");
if (nodep->isWide() || emitTraceIsScBv(nodep)) { if (nodep->isDouble()) {
puts("vcdp->"+full+"Double");
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
puts("vcdp->"+full+"Array"); puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad "); puts("vcdp->"+full+"Quad ");

View File

@ -73,6 +73,7 @@ public:
LITENDIAN, // Little bit endian vector LITENDIAN, // Little bit endian vector
MODDUP, // Duplicate module MODDUP, // Duplicate module
MULTIDRIVEN, // Driven from multiple blocks MULTIDRIVEN, // Driven from multiple blocks
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro REDEFMACRO, // Redefining existing define macro
STMTDLY, // Delayed statement STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word SYMRSVDWORD, // Symbol is Reserved Word
@ -111,7 +112,7 @@ public:
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH", "IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"LITENDIAN", "MODDUP", "LITENDIAN", "MODDUP",
"MULTIDRIVEN", "MULTIDRIVEN",
"REDEFMACRO", "REALCVT", "REDEFMACRO",
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT", "VARHIDDEN", "WIDTH", "WIDTHCONCAT",
@ -135,6 +136,7 @@ public:
|| m_e==CMPCONST || m_e==CMPCONST
|| m_e==IMPLICIT || m_e==IMPLICIT
|| m_e==LITENDIAN || m_e==LITENDIAN
|| m_e==REALCVT
|| m_e==UNSIGNED || m_e==UNSIGNED
|| m_e==WIDTH); } || m_e==WIDTH); }
// Warnings that are style only // Warnings that are style only

View File

@ -428,7 +428,7 @@ private:
if (dtypep) dtypep->unlinkFrBack(); if (dtypep) dtypep->unlinkFrBack();
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC); else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep); AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep);
newvarp->isSigned(nodep->isSigned()); if (nodep->isSigned()) newvarp->numeric(AstNumeric::SIGNED);
newvarp->funcReturn(true); newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); newvarp->attrIsolateAssign(nodep->attrIsolateAssign());

View File

@ -135,8 +135,8 @@ private:
// Spec says value is integral, if negative is ignored // Spec says value is integral, if negative is ignored
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
AstLogicPacked(), 32); AstLogicPacked(), 32);
varp->isSigned(true); varp->numeric(AstNumeric::SIGNED);
varp->dtypep()->isSigned(true); varp->dtypep()->numeric(AstNumeric::SIGNED);
varp->usedLoopIdx(true); varp->usedLoopIdx(true);
m_modp->addStmtp(varp); m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
@ -144,7 +144,7 @@ private:
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1))); new AstConst(nodep->fileline(), 1)));
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->isSigned(true); AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->numeric(AstNumeric::SIGNED);
AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
zerosp); zerosp);
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext(); AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();

View File

@ -1,451 +0,0 @@
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 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.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// Signedness depends on:
// Decimal numbers are signed
// Based numbers are unsigned unless 's' prefix
// Comparison results are unsigned
// Bit&Part selects are unsigned, even if whole
// Concatenates are unsigned
// Ignore signedness of self-determined:
// shift rhs, ** rhs, x?: lhs, concat and replicate members
// Else, if any operand unsigned, output unsigned
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
#include "V3Global.h"
#include "V3Signed.h"
#include "V3Ast.h"
//######################################################################
// Signed class functions
class SignedVisitor : public AstNVisitor {
private:
// NODE STATE/TYPES
// STATE
bool m_paramsOnly; // Computing parameter value; limit operation
// METHODS - special type detection
bool backRequiresUnsigned(AstNode* nodep) {
// The spec doesn't state this, but if you have an array select where the selection
// index is NOT wide enough, you do not sign extend, but always zero extend.
return (nodep->castArraySel()
|| nodep->castSel());
}
// VISITORS
//========
// Signed: Output explicit by user, Lhs either
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
virtual void visit(AstSel* nodep, AstNUser*) { signed_Ou_Ix(nodep); } //See backRequiresUnsigned
virtual void visit(AstAttrOf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCountOnes* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCLog2* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstPslBool* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTime* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstRedAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedXnor* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstRedXor* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstIsUnknown* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot0* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFEof* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetC* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstSScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRange* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... One presumes these are unsigned out, though the spec doesn't say
virtual void visit(AstLogNot* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIff* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstBufIf1* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These shouldn't matter, just make unsigned
virtual void visit(AstScopeName* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstText* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstUCFunc* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These comparisons don't care about inbound types
// ... (Though they should match. We don't check.)
virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqWild* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
// ... Opaque returns, so arbitrary
virtual void visit(AstCvtPackString* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//========
// Signed: Output signed
virtual void visit(AstRand* nodep, AstNUser*) { signed_Os_Ix(nodep); }
//=======
// Signed: Output signed iff LHS signed; unary operator
virtual void visit(AstNot* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstNegate* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftL* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftR* nodep, AstNUser*) { signed_Olhs(nodep); }
// Signed: Output signed iff LHS signed; binary operator
// Note by contrast, bit extract selects are unsigned
virtual void visit(AstArraySel* nodep, AstNUser*) { signed_Olhs(nodep); } //See backRequiresUnsigned
//=======
// Signed: Output signed iff LHS & RHS signed; binary operator
virtual void visit(AstAnd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstOr* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXnor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstSub* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstAdd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
//=======
// Signed: Output signed iff RHS & THS signed
virtual void visit(AstNodeCond* nodep, AstNUser*) { signed_OrhsAndThs(nodep); }
//=======
// These have proper signedness set when they were created.
virtual void visit(AstReturn* nodep, AstNUser*) { nodep->iterateChildren(*this); }
virtual void visit(AstNodeDType* nodep, AstNUser*) { nodep->iterateChildren(*this); }
// Inherit from others
virtual void visit(AstVar* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
nodep->numericFrom(nodep->dtypep());
}
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->varp()->iterate(*this);
nodep->numericFrom(nodep->varp());
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->itemp()->iterate(*this);
nodep->numericFrom(nodep->itemp());
}
virtual void visit(AstCast* nodep, AstNUser*) {
nodep->lhsp()->iterate(*this);
nodep->dtypep()->iterate(*this);
nodep->numericFrom(nodep->dtypep());
}
virtual void visit(AstConst* nodep, AstNUser*) {
// The node got setup with the signed state of the node.
// However a later operation may have changed the node->signed w/o changing
// the number's sign. So we don't: nodep->isSigned(nodep->num().isSigned());
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
if (nodep->fvarp()) {
nodep->numericFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep()
}
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->taskp()) nodep->taskp()->iterate(*this);
nodep->numericFrom(nodep->taskp());
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->defp()) nodep->defp()->iterate(*this);
nodep->numericFrom(nodep->skipRefp());
}
virtual void visit(AstNodeIf* nodep, AstNUser*) {
if (!nodep->castGenIf()) { // for m_paramsOnly
nodep->ifsp()->iterateAndNext(*this);
nodep->elsesp()->iterateAndNext(*this);
}
nodep->condp()->iterateAndNext(*this);
}
virtual void visit(AstPin* nodep, AstNUser*) {
// Same as above taskref argument.
nodep->iterateChildren(*this);
}
// VISITORS - Special
virtual void visit(AstSFormatF* nodep, AstNUser*) {
nodep->iterateChildren(*this);
//
UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
} else if (inPct && isdigit(ch)) {
} else if (tolower(inPct)) {
inPct = false;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
case 'd': { // Convert decimal to either 'd' or 'u'
if (argp && argp->isSigned()) { // Convert it
ch = '~';
}
if (argp) argp=argp->nextp();
break;
}
default: // Most operators, just move to next argument
if (argp) argp=argp->nextp();
break;
} // switch
}
dispout += ch;
}
nodep->text(dispout);
UINFO(9," Display out "<<nodep->text()<<endl);
}
// VISITORS - These need to be changed to different op types
// Uniop
virtual void visit(AstExtend* nodep, AstNUser*) {
signed_Olhs(nodep);
if (nodep->isSigned() && !backRequiresUnsigned(nodep->backp())) {
replaceWithSignedVersion(nodep, new AstExtendS (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstExtendS* nodep, AstNUser*) {
signed_Olhs(nodep);
if (!(nodep->isSigned() && !backRequiresUnsigned(nodep->backp()))) {
replaceWithSignedVersion(nodep, new AstExtend (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
// Biop
virtual void visit(AstPow* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPowS (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstPowS* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (!nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPow (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
// These have different node types, as they operate differently
// Must add to case statement below,
virtual void visit(AstGt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
// Need replacements; output matches input sign
virtual void visit(AstDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMul* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMulS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
// 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: "<<nodep);
nodep->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
signed_Ou_Ix(nodep);
checkReplace(nodep, nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
void checkReplace_Olhs(AstNodeBiop* nodep) {
signed_Olhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace_OlhsAndRhs(AstNodeBiop* nodep) {
signed_OlhsAndRhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace(AstNodeBiop* nodep, bool signedFlavorNeeded) {
if (signedFlavorNeeded != nodep->signedFlavor()) {
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp = NULL;
// Given a signed/unsigned node type, create the opposite type
switch (nodep->type()) {
case AstType::atGT: newp = new AstGtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTS: newp = new AstGt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTE: newp = new AstGteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTES: newp = new AstGte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLT: newp = new AstLtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTS: newp = new AstLt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTE: newp = new AstLteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTES: newp = new AstLte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIV: newp = new AstDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIVS: newp = new AstDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIV: newp = new AstModDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIVS: newp = new AstModDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMUL: newp = new AstMulS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMULS: newp = new AstMul (nodep->fileline(), lhsp, rhsp); break;
case AstType::atSHIFTRS: newp = new AstShiftR (nodep->fileline(), lhsp, rhsp); break;
default:
nodep->v3fatalSrc("Node needs sign change, but bad case: "<<nodep<<endl);
break;
}
replaceWithSignedVersion(nodep,newp);
}
}
// COMMON SCHEMES
// Signed: Output signed, Lhs/Rhs/etc either
void signed_Os_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(true);
}
// Signed: Output unsigned, Lhs/Rhs/etx either
void signed_Ou_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(false);
}
// Signed: Output signed iff LHS signed; unary operator
void signed_Olhs(AstNodeUniop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; binary operator
void signed_Olhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; select operator
void signed_Olhs(AstSel* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->fromp()->isSigned());
}
// Signed: Output signed iff LHS & RHS signed; binary operator
void signed_OlhsAndRhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
// Signed: Output signed iff RHS & THS signed
void signed_OrhsAndThs(AstNodeTriop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->rhsp()->isSigned() && nodep->thsp()->isSigned());
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedVisitor(bool paramsOnly) {
m_paramsOnly = paramsOnly;
}
virtual ~SignedVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Signed class functions
/// Remove all $signed, $unsigned, we're done with them.
class SignedRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedRemoveVisitor() {}
virtual ~SignedRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Top Signed class
void V3Signed::signedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
(void)signedParamsEdit(nodep);
}
AstNode* V3Signed::signedParamsEdit(AstNode* nodep) {
// Only called from V3Width::widthParamsEdit
UINFO(4,__FUNCTION__<<": "<<endl);
SignedVisitor visitor (true);
nodep = visitor.mainAcceptEdit(nodep);
SignedRemoveVisitor rvisitor;
nodep = rvisitor.mainAcceptEdit(nodep);
return nodep;
}

View File

@ -1,40 +0,0 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 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.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3SIGNED_H_
#define _V3SIGNED_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3Signed {
public:
static void signedAll(AstNetlist* nodep);
protected:
friend class V3Width; // Use widthParamsEdit instead of signedParamsEdit
static AstNode* signedParamsEdit(AstNode* nodep); // May replace nodep
};
#endif // Guard

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,37 @@
//###################################################################### //######################################################################
/// Remove all $signed, $unsigned, we're done with them.
class WidthRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
WidthRemoveVisitor() {}
virtual ~WidthRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
class WidthCommitVisitor : public AstNVisitor { class WidthCommitVisitor : public AstNVisitor {
// Now that all widthing is complete, // Now that all widthing is complete,
// Copy all width() to widthMin(). V3Const expects this // Copy all width() to widthMin(). V3Const expects this

View File

@ -74,7 +74,6 @@
#include "V3PreShell.h" #include "V3PreShell.h"
#include "V3Premit.h" #include "V3Premit.h"
#include "V3Scope.h" #include "V3Scope.h"
#include "V3Signed.h"
#include "V3Slice.h" #include "V3Slice.h"
#include "V3Split.h" #include "V3Split.h"
#include "V3SplitAs.h" #include "V3SplitAs.h"
@ -168,9 +167,6 @@ void process () {
V3Width::width(v3Global.rootp()); V3Width::width(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree")); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree"));
// Compute signed/unsigned
V3Signed::signedAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("signed.tree"));
V3Error::abortIfErrors(); V3Error::abortIfErrors();
// Commit to the widths we've chosen; Make widthMin==width // Commit to the widths we've chosen; Make widthMin==width

View File

@ -174,6 +174,7 @@ word [a-zA-Z0-9_]+
/* Extensions to Verilog set, some specified by PSL */ /* Extensions to Verilog set, some specified by PSL */
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/ "$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
/* System Tasks */ /* System Tasks */
"$bitstoreal" { FL; return yD_BITSTOREAL; }
"$display" { FL; return yD_DISPLAY; } "$display" { FL; return yD_DISPLAY; }
"$fclose" { FL; return yD_FCLOSE; } "$fclose" { FL; return yD_FCLOSE; }
"$fdisplay" { FL; return yD_FDISPLAY; } "$fdisplay" { FL; return yD_FDISPLAY; }
@ -187,15 +188,18 @@ word [a-zA-Z0-9_]+
"$fullskew" { FL; return yaTIMINGSPEC; } "$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; } "$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; } "$hold" { FL; return yaTIMINGSPEC; }
"$itor" { FL; return yD_ITOR; }
"$nochange" { FL; return yaTIMINGSPEC; } "$nochange" { FL; return yaTIMINGSPEC; }
"$period" { FL; return yaTIMINGSPEC; } "$period" { FL; return yaTIMINGSPEC; }
"$random" { FL; return yD_RANDOM; } "$random" { FL; return yD_RANDOM; }
"$readmemb" { FL; return yD_READMEMB; } "$readmemb" { FL; return yD_READMEMB; }
"$readmemh" { FL; return yD_READMEMH; } "$readmemh" { FL; return yD_READMEMH; }
"$realtime" { FL; return yD_TIME; } "$realtime" { FL; return yD_REALTIME; }
"$realtobits" { FL; return yD_REALTOBITS; }
"$recovery" { FL; return yaTIMINGSPEC; } "$recovery" { FL; return yaTIMINGSPEC; }
"$recrem" { FL; return yaTIMINGSPEC; } "$recrem" { FL; return yaTIMINGSPEC; }
"$removal" { FL; return yaTIMINGSPEC; } "$removal" { FL; return yaTIMINGSPEC; }
"$rtoi" { FL; return yD_RTOI; }
"$setup" { FL; return yaTIMINGSPEC; } "$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yaTIMINGSPEC; } "$setuphold" { FL; return yaTIMINGSPEC; }
"$sformat" { FL; return yD_SFORMAT; } "$sformat" { FL; return yD_SFORMAT; }
@ -261,6 +265,8 @@ word [a-zA-Z0-9_]+
"pulldown" { FL; return yPULLDOWN; } "pulldown" { FL; return yPULLDOWN; }
"pullup" { FL; return yPULLUP; } "pullup" { FL; return yPULLUP; }
"rcmos" { FL; return yRCMOS; } "rcmos" { FL; return yRCMOS; }
"real" { FL; return yREAL; }
"realtime" { FL; return yREALTIME; }
"reg" { FL; return yREG; } "reg" { FL; return yREG; }
"repeat" { FL; return yREPEAT; } "repeat" { FL; return yREPEAT; }
"rnmos" { FL; return yRNMOS; } "rnmos" { FL; return yRNMOS; }
@ -310,8 +316,6 @@ word [a-zA-Z0-9_]+
"medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"real" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"realtime" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
@ -950,12 +954,13 @@ word [a-zA-Z0-9_]+
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; } int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
double V3ParseImp::parseDouble(const char* textp, size_t length) { double V3ParseImp::parseDouble(const char* textp, size_t length) {
char* strgp = new char[strlen(textp)+1]; char* strgp = new char[length+1];
char* dp=strgp; char* dp=strgp;
for (const char* sp=textp; sp<(textp+length);) { for (const char* sp=textp; sp<(textp+length);) {
if (*sp != '_') *dp++ = *sp++; if (*sp != '_') *dp++ = *sp++;
else sp++; else sp++;
} }
*dp++ = '\0';
char* endp = strgp; char* endp = strgp;
double d = strtod(strgp, &endp); double d = strtod(strgp, &endp);
if ((endp-strgp) != length) { yyerrorf("Syntax error parsing real: %s",strgp); } if ((endp-strgp) != length) { yyerrorf("Syntax error parsing real: %s",strgp); }

View File

@ -342,6 +342,8 @@ class AstSenTree;
%token<fl> yPULLUP "pullup" %token<fl> yPULLUP "pullup"
%token<fl> yPURE "pure" %token<fl> yPURE "pure"
%token<fl> yRCMOS "rcmos" %token<fl> yRCMOS "rcmos"
%token<fl> yREAL "real"
%token<fl> yREALTIME "realtime"
%token<fl> yREG "reg" %token<fl> yREG "reg"
%token<fl> yREPEAT "repeat" %token<fl> yREPEAT "repeat"
%token<fl> yRETURN "return" %token<fl> yRETURN "return"
@ -382,6 +384,7 @@ class AstSenTree;
%token<fl> yXOR "xor" %token<fl> yXOR "xor"
%token<fl> yD_BITS "$bits" %token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_C "$c" %token<fl> yD_C "$c"
%token<fl> yD_CLOG2 "$clog2" %token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COUNTONES "$countones" %token<fl> yD_COUNTONES "$countones"
@ -400,11 +403,15 @@ class AstSenTree;
%token<fl> yD_FWRITE "$fwrite" %token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_INFO "$info" %token<fl> yD_INFO "$info"
%token<fl> yD_ISUNKNOWN "$isunknown" %token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_ONEHOT "$onehot" %token<fl> yD_ONEHOT "$onehot"
%token<fl> yD_ONEHOT0 "$onehot0" %token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_RANDOM "$random" %token<fl> yD_RANDOM "$random"
%token<fl> yD_READMEMB "$readmemb" %token<fl> yD_READMEMB "$readmemb"
%token<fl> yD_READMEMH "$readmemh" %token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SFORMAT "$sformat" %token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SIGNED "$signed" %token<fl> yD_SIGNED "$signed"
%token<fl> yD_SSCANF "$sscanf" %token<fl> yD_SSCANF "$sscanf"
@ -1067,6 +1074,12 @@ integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg | yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg
; ;
non_integer_type<bdtypep>: // ==IEEE: non_integer_type
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
;
signingE<signstate>: // IEEE: signing - plus empty signingE<signstate>: // IEEE: signing - plus empty
/*empty*/ { $$ = signedst_NOP; } /*empty*/ { $$ = signedst_NOP; }
| signing { $$ = $1; } | signing { $$ = $1; }
@ -1097,7 +1110,7 @@ simple_type<dtypep>: // ==IEEE: simple_type
// // IEEE: integer_type // // IEEE: integer_type
integer_atom_type { $$ = $1; } integer_atom_type { $$ = $1; }
| integer_vector_type { $$ = $1; } | integer_vector_type { $$ = $1; }
//UNSUP non_integer_type { $$ = $1; } | non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier // // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE) // // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; } | ps_type { $$ = $1; }
@ -1120,7 +1133,7 @@ data_type<dtypep>: // ==IEEE: data_type
data_typeBasic<dtypep>: // IEEE: part of data_type data_typeBasic<dtypep>: // IEEE: part of data_type
integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); } integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); }
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; } | integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
//UNSUP non_integer_type { UNSUP } | non_integer_type { $$ = $1; }
; ;
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
@ -1527,8 +1540,7 @@ delay_value: // ==IEEE:delay_value
delayExpr: delayExpr:
expr { } expr { }
// // Verilator doesn't support yaFLOATNUM/yaTIMENUM, so not in expr // // Verilator doesn't support yaTIMENUM, so not in expr
| yaFLOATNUM { }
| yaTIMENUM { } | yaTIMENUM { }
; ;
@ -1713,8 +1725,6 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); } | expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
//UNSUP expr ':' expr { } //UNSUP expr ':' expr { }
//UNSUP expr ':' expr ':' expr { } //UNSUP expr ':' expr ':' expr { }
// // Floatnum should only occur with UDPs, but since ports aren't floats, it's legal to round always
| yaFLOATNUM { $$ = new AstPin($<fl>1,PINNUMINC(),"",new AstConst($<fl>1,AstConst::Unsized32(),(int)(($1<0)?($1-0.5):($1+0.5)))); }
; ;
//************************************************ //************************************************
@ -2144,6 +2154,7 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
// //
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); } | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); } | yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); } | yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
@ -2153,10 +2164,14 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); } | yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); } | yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); } | yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
| yD_RANDOM parenE { $$ = new AstRand($1); } | yD_RANDOM parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug //| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); } | yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
@ -2455,7 +2470,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// //
// // IEEE: primary_literal (minus string, which is handled specially) // // IEEE: primary_literal (minus string, which is handled specially)
| yaINTNUM { $$ = new AstConst($<fl>1,*$1); } | yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
//UNSUP yaFLOATNUM { UNSUP } | yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
//UNSUP yaTIMENUM { UNSUP } //UNSUP yaTIMENUM { UNSUP }
| strAsInt~noStr__IGNORE~ { $$ = $1; } | strAsInt~noStr__IGNORE~ { $$ = $1; }
// //

View File

@ -0,0 +1,39 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
compile (
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
'),
);
ok(1);
1;

View File

@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2003 by Wilson Snyder.
module t;
real n0; initial n0 = 0.0;
real n1; initial n1 = 1.0;
real n2; initial n2 = 0.1;
real n3; initial n3 = 1.2345e-15;
real n4; initial n4 = 2.579e+15;
initial begin
// Display formatting
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n0,n0,n0,n0);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n1,n1,n1,n1);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n2,n2,n2,n2);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n3,n3,n3,n3);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n4,n4,n4,n4);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
top_filename("t/t_display_real.v");
compile (
v_flags2 => [$Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
'),
);
ok(1);
1;

View File

@ -39,9 +39,7 @@ module t ();
import "DPI-C" pure function longint dpii_f_longint (input longint i); import "DPI-C" pure function longint dpii_f_longint (input longint i);
import "DPI-C" pure function chandle dpii_f_chandle (input chandle i); import "DPI-C" pure function chandle dpii_f_chandle (input chandle i);
import "DPI-C" pure function string dpii_f_string (input string i); import "DPI-C" pure function string dpii_f_string (input string i);
`ifndef VERILATOR
import "DPI-C" pure function real dpii_f_real (input real i); import "DPI-C" pure function real dpii_f_real (input real i);
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
import "DPI-C" pure function shortreal dpii_f_shortreal(input shortreal i); import "DPI-C" pure function shortreal dpii_f_shortreal(input shortreal i);
`endif `endif
@ -53,9 +51,7 @@ module t ();
import "DPI-C" pure function void dpii_v_longint (input longint i, output longint o); import "DPI-C" pure function void dpii_v_longint (input longint i, output longint o);
import "DPI-C" pure function void dpii_v_chandle (input chandle i, output chandle o); import "DPI-C" pure function void dpii_v_chandle (input chandle i, output chandle o);
import "DPI-C" pure function void dpii_v_string (input string i, output string o); import "DPI-C" pure function void dpii_v_string (input string i, output string o);
`ifndef VERILATOR
import "DPI-C" pure function void dpii_v_real (input real i, output real o); import "DPI-C" pure function void dpii_v_real (input real i, output real o);
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o); import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o);
`endif `endif
@ -93,9 +89,7 @@ module t ();
longint i_l, o_l; longint i_l, o_l;
chandle i_c, o_c; chandle i_c, o_c;
string i_n, o_n; string i_n, o_n;
`ifndef VERILATOR
real i_d, o_d; real i_d, o_d;
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
shortreal i_f, o_f; shortreal i_f, o_f;
`endif `endif
@ -122,6 +116,10 @@ module t ();
i_y = {1'b1,wide[8-2:0]}; i_y = {1'b1,wide[8-2:0]};
i_s = {1'b1,wide[16-2:0]}; i_s = {1'b1,wide[16-2:0]};
i_l = {1'b1,wide[64-2:0]}; i_l = {1'b1,wide[64-2:0]};
i_d = 32.1;
`ifndef NO_SHORTREAL
i_f = 30.2;
`endif
if (dpii_f_bit (i_b) !== ~i_b) $stop; if (dpii_f_bit (i_b) !== ~i_b) $stop;
if (dpii_f_bit8 (i_b8) !== ~i_b8) $stop; if (dpii_f_bit8 (i_b8) !== ~i_b8) $stop;
@ -145,9 +143,7 @@ module t ();
if (dpii_f_longint (i_l) !== ~i_l) $stop; if (dpii_f_longint (i_l) !== ~i_l) $stop;
if (dpii_f_chandle (i_c) !== i_c) $stop; if (dpii_f_chandle (i_c) !== i_c) $stop;
if (dpii_f_string (i_n) != i_n) $stop; if (dpii_f_string (i_n) != i_n) $stop;
`ifndef VERILATOR
if (dpii_f_real (i_d) != i_d+1.5) $stop; if (dpii_f_real (i_d) != i_d+1.5) $stop;
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
if (dpii_f_shortreal(i_f) != i_f+1.5) $stop; if (dpii_f_shortreal(i_f) != i_f+1.5) $stop;
`endif `endif
@ -159,9 +155,7 @@ module t ();
dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop; dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop;
dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop; dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop;
dpii_v_string (i_n,o_n); if (o_n != i_n) $stop; dpii_v_string (i_n,o_n); if (o_n != i_n) $stop;
`ifndef VERILATOR
dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop; dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop;
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop; dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop;
`endif `endif

View File

@ -13,8 +13,6 @@ compile (
expect=> expect=>
q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add' q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add' %Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add' %Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x' %Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x' %Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'

View File

@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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.
compile (
make_top_shell => 0,
make_main => 0,
v_flags2 => ["--lint-only -Wwarn-REALCVT"],
verilator_make_gcc => 0,
fails=>1,
expect=>
'%Warning-REALCVT: t/t_lint_realcvt_bad.v:\d+: Implicit conversion of real to integer
%Warning-REALCVT: Use .* to disable this message.
%Error: Exiting due to.*',
) if $Self->{v3};
ok(1);
1;

View File

@ -0,0 +1,11 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module sub;
integer i;
initial begin
i = 23.2;
end
endmodule

18
test_regress/t/t_math_real.pl Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,136 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2011 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.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer i;
reg [63:0] b;
real r, r2;
integer cyc=0;
realtime uninit;
initial if (uninit != 0.0) $stop;
initial begin
// rtoi truncates
if ($rtoi(36.7) != 36) $stop;
if ($rtoi(36.5) != 36) $stop;
if ($rtoi(36.4) != 36) $stop;
// casting rounds
if ((integer '(36.7)) != 37) $stop;
if ((integer '(36.5)) != 37) $stop;
if ((integer '(36.4)) != 36) $stop;
// assignment rounds
// verilator lint_off REALCVT
i = 36.7; if (i != 37) $stop;
i = 36.5; if (i != 37) $stop;
i = 36.4; if (i != 36) $stop;
r = 10'd38; if (r!=38.0) $stop;
// verilator lint_on REALCVT
// operators
if ((-(1.5)) != -1.5) $stop;
if ((+(1.5)) != 1.5) $stop;
if (((1.5)+(1.25)) != 2.75) $stop;
if (((1.5)-(1.25)) != 0.25) $stop;
if (((1.5)*(1.25)) != 1.875) $stop;
if (((1.5)/(1.25)) != 1.2) $stop;
//
if (((1.5)==(2)) != 1'b0) $stop; // note 2 becomes real 2.0
if (((1.5)!=(2)) != 1'b1) $stop;
if (((1.5)> (2)) != 1'b0) $stop;
if (((1.5)>=(2)) != 1'b0) $stop;
if (((1.5)< (2)) != 1'b1) $stop;
if (((1.5)<=(2)) != 1'b1) $stop;
if (((1.5)==(1.5)) != 1'b1) $stop;
if (((1.5)!=(1.5)) != 1'b0) $stop;
if (((1.5)> (1.5)) != 1'b0) $stop;
if (((1.5)>=(1.5)) != 1'b1) $stop;
if (((1.5)< (1.5)) != 1'b0) $stop;
if (((1.5)<=(1.5)) != 1'b1) $stop;
if (((1.6)==(1.5)) != 1'b0) $stop;
if (((1.6)!=(1.5)) != 1'b1) $stop;
if (((1.6)> (1.5)) != 1'b1) $stop;
if (((1.6)>=(1.5)) != 1'b1) $stop;
if (((1.6)< (1.5)) != 1'b0) $stop;
if (((1.6)<=(1.5)) != 1'b0) $stop;
//
if (((0.0)?(2.0):(1.1)) != 1.1) $stop;
if (((1.5)?(2.0):(1.1)) != 2.0) $stop;
//
if (!1.7) $stop;
if (!(!0.0)) $stop;
if (1.8 && 0.0) $stop;
if (!(1.8 || 0.0)) $stop;
//
i=0;
for (r=1.0; r<2.0; r=r+0.1) i++;
if (i!=10) $stop;
end
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
`endif
cyc <= cyc + 1;
if (cyc==0) begin
// Setup
end
else if (cyc<90) begin
if ($time != {32'h0, $rtoi($realtime)}) $stop;
if ($itor(cyc) != cyc) $stop;
//Unsup: if ((real `($time)) != $realtime) $stop;
r = $itor(cyc*2);
i = $rtoi(r);
if (i!=cyc*2) $stop;
//
r = $itor(cyc)/1.5;
b = $realtobits(r);
r2 = $bitstoreal(b);
if (r != r2) $stop;
//
// Trust the integer math as a comparison
r = $itor(cyc);
if ($rtoi(-r) != -cyc) $stop;
if ($rtoi(+r) != cyc) $stop;
if ($rtoi(r+2.0) != (cyc+2)) $stop;
if ($rtoi(r-2.0) != (cyc-2)) $stop;
if ($rtoi(r*2.0) != (cyc*2)) $stop;
if ($rtoi(r/2.0) != (cyc/2)) $stop;
r2 = (2.0/(r-60)); // When zero, result indeterminate, but no crash
//
r2 = $itor(cyc);
case (r)
(r2-1.0): $stop;
r2: ;
default: $stop;
endcase
//
r = $itor(cyc);
if ((r==50.0) != (cyc==50)) $stop;
if ((r!=50.0) != (cyc!=50)) $stop;
if ((r> 50.0) != (cyc> 50)) $stop;
if ((r>=50.0) != (cyc>=50)) $stop;
if ((r< 50.0) != (cyc< 50)) $stop;
if ((r<=50.0) != (cyc<=50)) $stop;
//
if ($rtoi((r-50.0) ? 10.0 : 20.0)
!= (((cyc-50)!=0) ? 10 : 20)) $stop;
//
if ((!(r-50.0)) != (!((cyc-50) != 0))) $stop;
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -16,6 +16,8 @@ module t;
reg [48*8:1] str; reg [48*8:1] str;
reg [48*8:1] str2; reg [48*8:1] str2;
real r;
initial begin initial begin
n = 4'b1100; n = 4'b1100;
q = 64'h1234_5678_abcd_0123; q = 64'h1234_5678_abcd_0123;
@ -29,6 +31,15 @@ module t;
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif `ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
if (str2 !== "n=1100 q= 2623536935500120647 w=hello-there12345") $stop; if (str2 !== "n=1100 q= 2623536935500120647 w=hello-there12345") $stop;
$swrite(str2, "e=%e", r);
$swrite(str2, "e=%f", r);
$swrite(str2, "e=%g", r);
r = 0.01;
$swrite(str2, "e=%e f=%f g=%g", r, r, r);
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
if (str2 !== "e=1.000000e-02 f=0.010000 g=0.01") $stop;
$swrite(str2, "mod=%m"); $swrite(str2, "mod=%m");
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif `ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
`ifdef verilator `ifdef verilator

View File

@ -15,12 +15,14 @@ module t (/*AUTOARG*/
integer b_trace_off; integer b_trace_off;
// verilator tracing_on // verilator tracing_on
integer c_trace_on; integer c_trace_on;
real r;
always @ (posedge clk) begin always @ (posedge clk) begin
if (cyc!=0) begin if (cyc!=0) begin
cyc <= cyc + 1; cyc <= cyc + 1;
b_trace_off <= cyc; b_trace_off <= cyc;
c_trace_on <= b_trace_off; c_trace_on <= b_trace_off;
r <= r + 0.1;
if (cyc==4) begin if (cyc==4) begin
if (c_trace_on != 2) $stop; if (c_trace_on != 2) $stop;
end end

View File

@ -25,8 +25,8 @@ module t (/*AUTOARG*/);
// IEEE: non_integer_type // IEEE: non_integer_type
//UNSUP shortreal d_shortreal; //UNSUP shortreal d_shortreal;
//UNSUP real d_real; real d_real;
//UNSUP realtime d_realtime; realtime d_realtime;
// Declarations using var // Declarations using var
var byte v_b; var byte v_b;