Support 'real' numbers and related functions.
This commit is contained in:
parent
d5478e6e08
commit
55906486d8
2
Changes
2
Changes
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 \
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
283
src/V3AstNodes.h
283
src/V3AstNodes.h
|
|
@ -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); }
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)");
|
||||||
|
|
|
||||||
|
|
@ -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 ");
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
451
src/V3Signed.cpp
451
src/V3Signed.cpp
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
1048
src/V3Width.cpp
1048
src/V3Width.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue