mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
749ff021b6 | ||
|
|
85c5765c00 | ||
|
|
9e76078939 | ||
|
|
334e0e1ca6 | ||
|
|
dce4519995 | ||
|
|
45bbae80e7 | ||
|
|
d37709a922 | ||
|
|
2560ae9bc1 | ||
|
|
2bdd3ca353 | ||
|
|
8a8aab1aae | ||
|
|
85d790ff79 | ||
|
|
68afc96a9f | ||
|
|
94efaa7675 | ||
|
|
180af74a50 | ||
|
|
88af0d3509 | ||
|
|
97633f7bed | ||
|
|
053e016388 | ||
|
|
2d61e0270e | ||
|
|
3a23afb0bc |
@@ -3,6 +3,29 @@ Revision history for Verilator
|
|||||||
The contributors that suggested a given feature are shown in []. [by ...]
|
The contributors that suggested a given feature are shown in []. [by ...]
|
||||||
indicates the contributor was also the author of the fix; Thanks!
|
indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
|
* Verilator 3.856 2014-03-11
|
||||||
|
|
||||||
|
*** Support case inside, bug708. [Jan Egil Ruud]
|
||||||
|
|
||||||
|
*** Add parameters into trace files, bug706. [Alex Solomatnikov]
|
||||||
|
|
||||||
|
**** Fix parsing "#0 'b0", bug256.
|
||||||
|
|
||||||
|
**** Fix array bound checks on real variables.
|
||||||
|
|
||||||
|
**** Fix --skip-identical mis-detecting on OS-X, bug707.
|
||||||
|
|
||||||
|
**** Fix missing VL_SHIFTRS_IQI with WIDTH warning, bug714. [Fabrizio Ferrandi]
|
||||||
|
|
||||||
|
**** Fix signed shift right optimization, bug715. [Fabrizio Ferrandi]
|
||||||
|
|
||||||
|
**** Fix internal error on "input x =" syntax error, bug716. [Lane Brooks]
|
||||||
|
|
||||||
|
**** Fix slice extraction from packed array, bug717. [Jan Egil Ruud]
|
||||||
|
|
||||||
|
**** Fix inside statement EQWILD error, bug718. [Jan Egil Ruud]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 3.855 2014-01-18
|
* Verilator 3.855 2014-01-18
|
||||||
|
|
||||||
*** Support modport import, bug696. [Jeremy Bennett]
|
*** Support modport import, bug696. [Jeremy Bennett]
|
||||||
|
|||||||
+2
-2
@@ -3543,8 +3543,8 @@ coverage. Both require the SystemPerl package to be installed but do not
|
|||||||
require use of the SystemPerl output mode.
|
require use of the SystemPerl output mode.
|
||||||
|
|
||||||
First, run verilator with the --coverage option. If you're using your own
|
First, run verilator with the --coverage option. If you're using your own
|
||||||
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
|
makefile, compile the model with the GCC flag -DSP_COVERAGE (if using
|
||||||
using Verilator's, it will do this for you.)
|
Verilator's, it will do this for you.)
|
||||||
|
|
||||||
Run your tests in different directories. Each test will create a
|
Run your tests in different directories. Each test will create a
|
||||||
logs/coverage.pl file.
|
logs/coverage.pl file.
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
#AC_INIT([Verilator],[#.### devel])
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
AC_INIT([Verilator],[3.855 2014-01-18])
|
AC_INIT([Verilator],[3.856 2014-03-11])
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||||
|
|
||||||
|
|||||||
+18
-9
@@ -1455,29 +1455,37 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
|
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
|
||||||
static inline IData VL_SHIFTRS_III(int obits, int, int, IData lhs, IData rhs) {
|
static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData rhs) {
|
||||||
// Note the C standard does not specify the >> operator as a arithmetic shift!
|
// Note the C standard does not specify the >> operator as a arithmetic shift!
|
||||||
IData sign = -(lhs >> (obits-1)); // ffff_ffff if negative
|
// IEEE says signed if output signed, but bit position from lbits;
|
||||||
IData signext = ~(VL_MASK_I(obits) >> rhs); // One with bits where we've shifted "past"
|
// must use lbits for sign; lbits might != obits,
|
||||||
|
// an EXTEND(SHIFTRS(...)) can became a SHIFTRS(...) within same 32/64 bit word length
|
||||||
|
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
|
||||||
|
IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past"
|
||||||
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
|
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
|
||||||
}
|
}
|
||||||
static inline QData VL_SHIFTRS_QQI(int obits, int, int, QData lhs, IData rhs) {
|
static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) {
|
||||||
QData sign = -(lhs >> (obits-1));
|
QData sign = -(lhs >> (lbits-1));
|
||||||
QData signext = ~(VL_MASK_Q(obits) >> rhs);
|
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
|
||||||
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) {
|
||||||
|
return (IData)(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
|
||||||
|
}
|
||||||
|
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||||
int word_shift = VL_BITWORD_I(rd);
|
int word_shift = VL_BITWORD_I(rd);
|
||||||
int bit_shift = VL_BITBIT_I(rd);
|
int bit_shift = VL_BITBIT_I(rd);
|
||||||
int lmsw = VL_WORDS_I(obits)-1;
|
int lmsw = VL_WORDS_I(obits)-1;
|
||||||
IData sign = VL_SIGNONES_I(obits,lwp[lmsw]);
|
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
||||||
if ((int)rd >= obits) {
|
if ((int)rd >= obits) { // Shifting past end, sign in all of lbits
|
||||||
for (int i=0; i <= lmsw; i++) owp[i] = sign;
|
for (int i=0; i <= lmsw; i++) owp[i] = sign;
|
||||||
|
owp[lmsw] &= VL_MASK_I(lbits);
|
||||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||||
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
||||||
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
|
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
|
||||||
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
|
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
|
||||||
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
||||||
|
owp[lmsw] &= VL_MASK_I(lbits);
|
||||||
} else {
|
} else {
|
||||||
int loffset = rd & VL_SIZEBITS_I;
|
int loffset = rd & VL_SIZEBITS_I;
|
||||||
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
|
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||||
@@ -1492,6 +1500,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP
|
|||||||
}
|
}
|
||||||
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
|
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
|
||||||
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
|
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
|
||||||
|
owp[lmsw] &= VL_MASK_I(lbits);
|
||||||
}
|
}
|
||||||
return(owp);
|
return(owp);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-8
@@ -496,22 +496,23 @@ public:
|
|||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class AstCaseType {
|
class VCaseType {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
CT_CASE,
|
CT_CASE,
|
||||||
CT_CASEX,
|
CT_CASEX,
|
||||||
CT_CASEZ
|
CT_CASEZ,
|
||||||
|
CT_CASEINSIDE
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstCaseType () : m_e(CT_CASE) {}
|
inline VCaseType () : m_e(CT_CASE) {}
|
||||||
inline AstCaseType (en _e) : m_e(_e) {}
|
inline VCaseType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (VCaseType lhs, VCaseType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (VCaseType lhs, VCaseType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); }
|
inline bool operator== (VCaseType::en lhs, VCaseType rhs) { return (lhs == rhs.m_e); }
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,35 @@ int AstNodeClassDType::widthAlignBytes() const {
|
|||||||
else return 8;
|
else return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstEqD(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstEq(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstGte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstGteD(fl, lhsp, rhsp);
|
||||||
|
} else if (lhsp->isSigned() && rhsp->isSigned()) {
|
||||||
|
return new AstGteS(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstGte(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeBiop* AstLte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
||||||
|
if (lhsp->isDouble() && rhsp->isDouble()) {
|
||||||
|
return new AstLteD(fl, lhsp, rhsp);
|
||||||
|
} else if (lhsp->isSigned() && rhsp->isSigned()) {
|
||||||
|
return new AstLteS(fl, lhsp, rhsp);
|
||||||
|
} else {
|
||||||
|
return new AstLte(fl, lhsp, rhsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AstVar::isSigPublic() const {
|
bool AstVar::isSigPublic() const {
|
||||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-4
@@ -2053,14 +2053,14 @@ struct AstCase : public AstNodeCase {
|
|||||||
// exprp Children: MATHs
|
// exprp Children: MATHs
|
||||||
// casesp Children: CASEITEMs
|
// casesp Children: CASEITEMs
|
||||||
private:
|
private:
|
||||||
AstCaseType m_casex; // 0=case, 1=casex, 2=casez
|
VCaseType m_casex; // 0=case, 1=casex, 2=casez
|
||||||
bool m_fullPragma; // Synthesis full_case
|
bool m_fullPragma; // Synthesis full_case
|
||||||
bool m_parallelPragma; // Synthesis parallel_case
|
bool m_parallelPragma; // Synthesis parallel_case
|
||||||
bool m_uniquePragma; // unique case
|
bool m_uniquePragma; // unique case
|
||||||
bool m_unique0Pragma; // unique0 case
|
bool m_unique0Pragma; // unique0 case
|
||||||
bool m_priorityPragma; // priority case
|
bool m_priorityPragma; // priority case
|
||||||
public:
|
public:
|
||||||
AstCase(FileLine* fileline, AstCaseType casex, AstNode* exprp, AstNode* casesp)
|
AstCase(FileLine* fileline, VCaseType casex, AstNode* exprp, AstNode* casesp)
|
||||||
: AstNodeCase(fileline, exprp, casesp) {
|
: AstNodeCase(fileline, exprp, casesp) {
|
||||||
m_casex=casex;
|
m_casex=casex;
|
||||||
m_fullPragma=false; m_parallelPragma=false;
|
m_fullPragma=false; m_parallelPragma=false;
|
||||||
@@ -2070,8 +2070,11 @@ public:
|
|||||||
virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; }
|
virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; }
|
||||||
virtual bool same(AstNode* samep) const {
|
virtual bool same(AstNode* samep) const {
|
||||||
return m_casex==samep->castCase()->m_casex; }
|
return m_casex==samep->castCase()->m_casex; }
|
||||||
bool casex() const { return m_casex==AstCaseType::CT_CASEX; }
|
bool casex() const { return m_casex==VCaseType::CT_CASEX; }
|
||||||
bool casez() const { return m_casex==AstCaseType::CT_CASEZ; }
|
bool casez() const { return m_casex==VCaseType::CT_CASEZ; }
|
||||||
|
bool caseInside() const { return m_casex==VCaseType::CT_CASEINSIDE; }
|
||||||
|
bool caseSimple() const { return m_casex==VCaseType::CT_CASE; }
|
||||||
|
void caseInsideSet() { m_casex=VCaseType::CT_CASEINSIDE; }
|
||||||
bool fullPragma() const { return m_fullPragma; }
|
bool fullPragma() const { return m_fullPragma; }
|
||||||
void fullPragma(bool flag) { m_fullPragma=flag; }
|
void fullPragma(bool flag) { m_fullPragma=flag; }
|
||||||
bool parallelPragma() const { return m_parallelPragma; }
|
bool parallelPragma() const { return m_parallelPragma; }
|
||||||
@@ -3610,6 +3613,7 @@ struct AstEq : public AstNodeBiCom {
|
|||||||
AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||||
dtypeSetLogicBool(); }
|
dtypeSetLogicBool(); }
|
||||||
ASTNODE_NODE_FUNCS(Eq, EQ)
|
ASTNODE_NODE_FUNCS(Eq, EQ)
|
||||||
|
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEq/AstEqD
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
|
||||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||||
@@ -3740,6 +3744,7 @@ struct AstGte : public AstNodeBiop {
|
|||||||
AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||||
dtypeSetLogicBool(); }
|
dtypeSetLogicBool(); }
|
||||||
ASTNODE_NODE_FUNCS(Gte, GTE)
|
ASTNODE_NODE_FUNCS(Gte, GTE)
|
||||||
|
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstGte/AstGteS/AstGteD
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
|
||||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||||
virtual string emitC() { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
|
virtual string emitC() { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
|
||||||
@@ -3779,6 +3784,7 @@ struct AstLte : public AstNodeBiop {
|
|||||||
AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||||
dtypeSetLogicBool(); }
|
dtypeSetLogicBool(); }
|
||||||
ASTNODE_NODE_FUNCS(Lte, LTE)
|
ASTNODE_NODE_FUNCS(Lte, LTE)
|
||||||
|
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstLte/AstLteS/AstLteD
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
|
||||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||||
virtual string emitC() { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
|
virtual string emitC() { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
|
||||||
@@ -3843,6 +3849,8 @@ struct AstShiftR : public AstNodeBiop {
|
|||||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} // LHS size might be > output size, so don't want to force size
|
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} // LHS size might be > output size, so don't want to force size
|
||||||
};
|
};
|
||||||
struct AstShiftRS : public AstNodeBiop {
|
struct AstShiftRS : public AstNodeBiop {
|
||||||
|
// Shift right with sign extension, >>> operator
|
||||||
|
// Output data type's width determines which bit is used for sign extension
|
||||||
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)
|
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)
|
||||||
: AstNodeBiop(fl, lhsp, rhsp) {
|
: AstNodeBiop(fl, lhsp, rhsp) {
|
||||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
||||||
|
|||||||
+24
-17
@@ -97,7 +97,8 @@ private:
|
|||||||
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
||||||
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
||||||
// Don't sweat it, we already complained about casex in general
|
// Don't sweat it, we already complained about casex in general
|
||||||
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
|
} else if (m_caseExprp->castCase() && (m_caseExprp->castCase()->casez()
|
||||||
|
|| m_caseExprp->castCase()->caseInside())) {
|
||||||
if (nodep->num().isUnknown()) {
|
if (nodep->num().isUnknown()) {
|
||||||
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
||||||
}
|
}
|
||||||
@@ -322,36 +323,42 @@ private:
|
|||||||
icondNextp = icondp->nextp();
|
icondNextp = icondp->nextp();
|
||||||
icondp->unlinkFrBack();
|
icondp->unlinkFrBack();
|
||||||
|
|
||||||
AstNode* and1p;
|
AstNode* condp = NULL; // Default is to use and1p/and2p
|
||||||
AstNode* and2p;
|
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (iconstp && neverItem(nodep, iconstp)) {
|
if (iconstp && neverItem(nodep, iconstp)) {
|
||||||
// X in casez can't ever be executed
|
// X in casez can't ever be executed
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
// For simplicity, make expression that is not equal, and let later
|
// For simplicity, make expression that is not equal, and let later
|
||||||
// optimizations remove it
|
// optimizations remove it
|
||||||
and1p = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
||||||
and2p = new AstConst(itemp->fileline(), AstConst::LogicTrue());
|
} else if (AstInsideRange* irangep = icondp->castInsideRange()) {
|
||||||
|
// Similar logic in V3Width::visit(AstInside)
|
||||||
|
AstNode* ap = AstGte::newTyped(itemp->fileline(),
|
||||||
|
cexprp->cloneTree(false),
|
||||||
|
irangep->lhsp()->unlinkFrBack());
|
||||||
|
AstNode* bp = AstLte::newTyped(itemp->fileline(),
|
||||||
|
cexprp->cloneTree(false),
|
||||||
|
irangep->rhsp()->unlinkFrBack());
|
||||||
|
condp = new AstAnd(itemp->fileline(), ap, bp);
|
||||||
} else if (iconstp && iconstp->num().isFourState()
|
} else if (iconstp && iconstp->num().isFourState()
|
||||||
&& (nodep->casex() || nodep->casez())) {
|
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
nummask.opBitsNonX(iconstp->num());
|
nummask.opBitsNonX(iconstp->num());
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
numval.opBitsOne(iconstp->num());
|
numval.opBitsOne(iconstp->num());
|
||||||
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
and2p = new AstAnd(itemp->fileline(),
|
AstNode* and2p = new AstAnd(itemp->fileline(),
|
||||||
new AstConst(itemp->fileline(), numval),
|
new AstConst(itemp->fileline(), numval),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
|
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
||||||
} else {
|
} else {
|
||||||
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
||||||
and1p = cexprp->cloneTree(false);
|
AstNode* and1p = cexprp->cloneTree(false);
|
||||||
and2p = icondp;
|
AstNode* and2p = icondp;
|
||||||
|
condp = AstEq::newTyped(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 {
|
||||||
@@ -435,7 +442,7 @@ private:
|
|||||||
bool neverItem(AstCase* casep, AstConst* itemp) {
|
bool neverItem(AstCase* casep, AstConst* itemp) {
|
||||||
// Xs in case or casez are impossible due to two state simulations
|
// Xs in case or casez are impossible due to two state simulations
|
||||||
if (casep->casex()) {
|
if (casep->casex()) {
|
||||||
} else if (casep->casez()) {
|
} else if (casep->casez() || casep->caseInside()) {
|
||||||
if (itemp->num().isUnknown()) return true;
|
if (itemp->num().isUnknown()) return true;
|
||||||
} else {
|
} else {
|
||||||
if (itemp->num().isFourState()) return true;
|
if (itemp->num().isFourState()) return true;
|
||||||
|
|||||||
+23
-13
@@ -327,27 +327,27 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool operandBiExtendConst(AstNodeBiop* nodep) {
|
bool operandBiExtendConst(AstNodeBiop* nodep) {
|
||||||
// Loop unrolling likes standalone compares
|
// Loop unrolling favors standalone compares
|
||||||
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
|
// EQ(const{width32}, EXTEND(xx{width3})) -> EQ(const{3}, xx{3})
|
||||||
// Beware that the constant must have zero bits (+ 1 if signed) or compare
|
// Beware that the constant must have zero bits (+ 1 if signed) or compare
|
||||||
// would be incorrect
|
// would be incorrect
|
||||||
AstExtend* extendp = nodep->lhsp()->castExtend();
|
AstExtend* extendp = nodep->rhsp()->castExtend();
|
||||||
if (!extendp) return false;
|
if (!extendp) return false;
|
||||||
AstNode* smallerp = extendp->lhsp();
|
AstNode* smallerp = extendp->lhsp();
|
||||||
int subsize = smallerp->width();
|
int subsize = smallerp->width();
|
||||||
AstConst* constp = nodep->rhsp()->castConst();
|
AstConst* constp = nodep->lhsp()->castConst();
|
||||||
if (!constp) return false;
|
if (!constp) return false;
|
||||||
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
|
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
|
||||||
//
|
//
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
|
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
|
||||||
smallerp->unlinkFrBack();
|
smallerp->unlinkFrBack();
|
||||||
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
|
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
|
||||||
nodep->lhsp(smallerp);
|
nodep->rhsp(smallerp);
|
||||||
|
|
||||||
constp->unlinkFrBack();
|
constp->unlinkFrBack();
|
||||||
V3Number num (constp->fileline(), subsize);
|
V3Number num (constp->fileline(), subsize);
|
||||||
num.opAssign(constp->num());
|
num.opAssign(constp->num());
|
||||||
nodep->rhsp(new AstConst(constp->fileline(), num));
|
nodep->lhsp(new AstConst(constp->fileline(), num));
|
||||||
constp->deleteTree(); constp=NULL;
|
constp->deleteTree(); constp=NULL;
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
||||||
return true;
|
return true;
|
||||||
@@ -538,6 +538,8 @@ private:
|
|||||||
void replaceWChild(AstNode* nodep, AstNode* childp) {
|
void replaceWChild(AstNode* nodep, AstNode* childp) {
|
||||||
// NODE(..., CHILD(...)) -> CHILD(...)
|
// NODE(..., CHILD(...)) -> CHILD(...)
|
||||||
childp->unlinkFrBackWithNext();
|
childp->unlinkFrBackWithNext();
|
||||||
|
// If replacing a SEL for example, the data type comes from the parent (is less wide).
|
||||||
|
// This may adversly affect the operation of the node being replaced.
|
||||||
childp->dtypeFrom(nodep);
|
childp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(childp);
|
nodep->replaceWith(childp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); nodep=NULL;
|
||||||
@@ -1812,6 +1814,14 @@ private:
|
|||||||
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||||
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
||||||
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
||||||
|
TREEOP ("AstLt {!$lhsp.castConst,$rhsp.castConst}", "AstGt {$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstLtS {!$lhsp.castConst,$rhsp.castConst}", "AstGtS {$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstLte {!$lhsp.castConst,$rhsp.castConst}", "AstGte {$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstLteS {!$lhsp.castConst,$rhsp.castConst}", "AstGteS{$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstGt {!$lhsp.castConst,$rhsp.castConst}", "AstLt {$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstGtS {!$lhsp.castConst,$rhsp.castConst}", "AstLtS {$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstGte {!$lhsp.castConst,$rhsp.castConst}", "AstLte {$rhsp,$lhsp}");
|
||||||
|
TREEOP ("AstGteS {!$lhsp.castConst,$rhsp.castConst}", "AstLteS{$rhsp,$lhsp}");
|
||||||
// v--- *1* as These ops are always first, as we warn before replacing
|
// v--- *1* as These ops are always first, as we warn before replacing
|
||||||
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
||||||
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
||||||
@@ -1823,7 +1833,7 @@ private:
|
|||||||
TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)");
|
TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)");
|
||||||
// Two level bubble pushing
|
// Two level bubble pushing
|
||||||
TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==$lhsp->castNot()->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x
|
TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==$lhsp->castNot()->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x
|
||||||
TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x
|
TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->op1p())"); // LOGNOT(LOGNOT(x))->x
|
||||||
TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
@@ -1861,12 +1871,12 @@ private:
|
|||||||
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||||
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
||||||
// Compress out EXTENDs to appease loop unroller
|
// Compress out EXTENDs to appease loop unroller
|
||||||
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
TREEOPV("AstEq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||||
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
TREEOPV("AstNeq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||||
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
TREEOPV("AstGt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||||
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
TREEOPV("AstGte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||||
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
TREEOPV("AstLt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||||
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
TREEOPV("AstLte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||||
// Identical operands on both sides
|
// Identical operands on both sides
|
||||||
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
|
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
|
||||||
// AstAdd->ShiftL(#,1) but uncommon
|
// AstAdd->ShiftL(#,1) but uncommon
|
||||||
|
|||||||
+3
-1
@@ -223,7 +223,9 @@ private:
|
|||||||
bool mightElim(AstVar* nodep) {
|
bool mightElim(AstVar* nodep) {
|
||||||
return (!nodep->isSigPublic() // Can't elim publics!
|
return (!nodep->isSigPublic() // Can't elim publics!
|
||||||
&& !nodep->isIO()
|
&& !nodep->isIO()
|
||||||
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
|
&& (nodep->isTemp()
|
||||||
|
|| (nodep->isParam() && !nodep->isTrace())
|
||||||
|
|| m_elimUserVars)); // Post-Trace can kill most anything
|
||||||
}
|
}
|
||||||
void deadCheckVar() {
|
void deadCheckVar() {
|
||||||
// Delete any unused varscopes
|
// Delete any unused varscopes
|
||||||
|
|||||||
+6
-1
@@ -67,6 +67,7 @@ class V3FileDependImp {
|
|||||||
const string& filename() const { return m_filename; }
|
const string& filename() const { return m_filename; }
|
||||||
bool target() const { return m_target; }
|
bool target() const { return m_target; }
|
||||||
off_t size() const { return m_stat.st_size; }
|
off_t size() const { return m_stat.st_size; }
|
||||||
|
ino_t ino() const { return m_stat.st_ino; }
|
||||||
time_t mtime() const { return m_stat.st_mtime; }
|
time_t mtime() const { return m_stat.st_mtime; }
|
||||||
void loadStats() {
|
void loadStats() {
|
||||||
if (!m_stat.st_mtime) {
|
if (!m_stat.st_mtime) {
|
||||||
@@ -169,10 +170,12 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm
|
|||||||
V3Options::fileNfsFlush(dfp->filename());
|
V3Options::fileNfsFlush(dfp->filename());
|
||||||
dfp->loadStats();
|
dfp->loadStats();
|
||||||
off_t showSize = iter->size();
|
off_t showSize = iter->size();
|
||||||
if (dfp->filename() == filename) showSize=0; // We're writing it, so need to ignore it
|
ino_t showIno = iter->ino();
|
||||||
|
if (dfp->filename() == filename) { showSize=0; showIno=0; } // We're writing it, so need to ignore it
|
||||||
|
|
||||||
*ofp<<(iter->target()?"T":"S")<<" ";
|
*ofp<<(iter->target()?"T":"S")<<" ";
|
||||||
*ofp<<" "<<setw(8)<<showSize;
|
*ofp<<" "<<setw(8)<<showSize;
|
||||||
|
*ofp<<" "<<setw(8)<<showIno;
|
||||||
*ofp<<" "<<setw(11)<<iter->mtime();
|
*ofp<<" "<<setw(11)<<iter->mtime();
|
||||||
*ofp<<" \""<<iter->filename()<<"\"";
|
*ofp<<" \""<<iter->filename()<<"\"";
|
||||||
*ofp<<endl;
|
*ofp<<endl;
|
||||||
@@ -202,6 +205,7 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm
|
|||||||
while (!ifp->eof()) {
|
while (!ifp->eof()) {
|
||||||
char chkDir; *ifp>>chkDir;
|
char chkDir; *ifp>>chkDir;
|
||||||
off_t chkSize; *ifp>>chkSize;
|
off_t chkSize; *ifp>>chkSize;
|
||||||
|
ino_t chkIno; *ifp>>chkIno;
|
||||||
if (ifp->eof()) break; // Needed to read final whitespace before found eof
|
if (ifp->eof()) break; // Needed to read final whitespace before found eof
|
||||||
time_t chkMtime; *ifp>>chkMtime;
|
time_t chkMtime; *ifp>>chkMtime;
|
||||||
char quote; *ifp>>quote;
|
char quote; *ifp>>quote;
|
||||||
@@ -222,6 +226,7 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm
|
|||||||
// we determined the original size. For safety, we know the creation time
|
// we determined the original size. For safety, we know the creation time
|
||||||
// must be within a few second window... call it 20 sec.
|
// must be within a few second window... call it 20 sec.
|
||||||
if (!(chkStat.st_size >= chkSize
|
if (!(chkStat.st_size >= chkSize
|
||||||
|
&& chkStat.st_ino == chkIno
|
||||||
&& chkStat.st_mtime >= chkMtime
|
&& chkStat.st_mtime >= chkMtime
|
||||||
&& chkStat.st_mtime <= (chkMtime + 20))) {
|
&& chkStat.st_mtime <= (chkMtime + 20))) {
|
||||||
UINFO(2," --check-times failed: out-of-date "<<chkFilename
|
UINFO(2," --check-times failed: out-of-date "<<chkFilename
|
||||||
|
|||||||
+1
-1
@@ -504,7 +504,7 @@ private:
|
|||||||
UINFO(6," -to "<<pinNewVarp<<endl);
|
UINFO(6," -to "<<pinNewVarp<<endl);
|
||||||
pinNewVarp->user2p(connectRefp);
|
pinNewVarp->user2p(connectRefp);
|
||||||
// Public output inside the cell must go via an assign rather than alias
|
// Public output inside the cell must go via an assign rather than alias
|
||||||
// Else the public logic will set the alias, loosing the value to be propagated up
|
// Else the public logic will set the alias, losing the value to be propagated up
|
||||||
// (InOnly isn't a problem as the AssignAlias will create the assignment for us)
|
// (InOnly isn't a problem as the AssignAlias will create the assignment for us)
|
||||||
pinNewVarp->user3(pinNewVarp->isSigUserRWPublic() && pinNewVarp->isOutOnly());
|
pinNewVarp->user3(pinNewVarp->isSigUserRWPublic() && pinNewVarp->isOutOnly());
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-1
@@ -61,6 +61,7 @@ private:
|
|||||||
bool m_needStart; // Need start marker on lower AstParse
|
bool m_needStart; // Need start marker on lower AstParse
|
||||||
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
|
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
|
AstNodeFTask* m_ftaskp; // Current task
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
static int debug() {
|
static int debug() {
|
||||||
@@ -85,6 +86,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITs
|
||||||
|
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||||
|
if (!nodep->user1SetOnce()) { // Process only once.
|
||||||
|
cleanFileline(nodep);
|
||||||
|
m_ftaskp = nodep;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
m_ftaskp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||||
if (!nodep->user1SetOnce()) { // Process only once.
|
if (!nodep->user1SetOnce()) { // Process only once.
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
@@ -138,7 +147,11 @@ private:
|
|||||||
// A variable with an = value can be three things:
|
// A variable with an = value can be three things:
|
||||||
FileLine* fl = nodep->valuep()->fileline();
|
FileLine* fl = nodep->valuep()->fileline();
|
||||||
// 1. Parameters and function inputs: It's a default to use if not overridden
|
// 1. Parameters and function inputs: It's a default to use if not overridden
|
||||||
if (nodep->isParam() || nodep->isInOnly()) {
|
if (nodep->isParam() || (m_ftaskp && nodep->isInOnly())) {
|
||||||
|
}
|
||||||
|
else if (!m_ftaskp && nodep->isInOnly()) {
|
||||||
|
nodep->v3error("Unsupported: Default value on module input: "<<nodep->prettyName());
|
||||||
|
nodep->valuep()->unlinkFrBack()->deleteTree();
|
||||||
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
|
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
|
||||||
else if (m_valueModp) {
|
else if (m_valueModp) {
|
||||||
nodep->addNextHere
|
nodep->addNextHere
|
||||||
@@ -313,6 +326,7 @@ public:
|
|||||||
LinkParseVisitor(AstNetlist* rootp) {
|
LinkParseVisitor(AstNetlist* rootp) {
|
||||||
m_varp = NULL;
|
m_varp = NULL;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
m_ftaskp = NULL;
|
||||||
m_inAlways = false;
|
m_inAlways = false;
|
||||||
m_inGenerate = false;
|
m_inGenerate = false;
|
||||||
m_needStart = false;
|
m_needStart = false;
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ class V3ParseImp {
|
|||||||
int m_inBeginKwd; // Inside a `begin_keywords
|
int m_inBeginKwd; // Inside a `begin_keywords
|
||||||
int m_lastVerilogState; // Last LEX state in `begin_keywords
|
int m_lastVerilogState; // Last LEX state in `begin_keywords
|
||||||
|
|
||||||
|
int m_prevLexToken; // previous parsed token (for lexer)
|
||||||
bool m_ahead; // aheadToken is valid
|
bool m_ahead; // aheadToken is valid
|
||||||
int m_aheadToken; // Token we read ahead
|
int m_aheadToken; // Token we read ahead
|
||||||
V3ParseBisonYYSType m_aheadVal; // aheadToken's value
|
V3ParseBisonYYSType m_aheadVal; // aheadToken's value
|
||||||
@@ -193,6 +194,7 @@ public:
|
|||||||
void statePushVlg(); // Parser -> lexer communication
|
void statePushVlg(); // Parser -> lexer communication
|
||||||
void statePop(); // Parser -> lexer communication
|
void statePop(); // Parser -> lexer communication
|
||||||
static int stateVerilogRecent(); // Parser -> lexer communication
|
static int stateVerilogRecent(); // Parser -> lexer communication
|
||||||
|
int prevLexToken() { return m_prevLexToken; } // Parser -> lexer communication
|
||||||
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
|
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
|
||||||
|
|
||||||
//==== Symbol tables
|
//==== Symbol tables
|
||||||
@@ -208,11 +210,13 @@ public:
|
|||||||
m_inLibrary = false;
|
m_inLibrary = false;
|
||||||
m_inBeginKwd = 0;
|
m_inBeginKwd = 0;
|
||||||
m_lastVerilogState = stateVerilogRecent();
|
m_lastVerilogState = stateVerilogRecent();
|
||||||
|
m_prevLexToken = 0;
|
||||||
m_ahead = false;
|
m_ahead = false;
|
||||||
m_aheadToken = 0;
|
m_aheadToken = 0;
|
||||||
}
|
}
|
||||||
~V3ParseImp();
|
~V3ParseImp();
|
||||||
void parserClear();
|
void parserClear();
|
||||||
|
void unputString(const char* textp, size_t length);
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
// Preprocess and read the Verilog file specified into the netlist database
|
// Preprocess and read the Verilog file specified into the netlist database
|
||||||
@@ -223,6 +227,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void lexFile(const string& modname);
|
void lexFile(const string& modname);
|
||||||
|
int yylexReadTok();
|
||||||
int lexToken(); // Internal; called from lexToBison
|
int lexToken(); // Internal; called from lexToBison
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+16
-1
@@ -57,11 +57,26 @@ public:
|
|||||||
void statePop() {
|
void statePop() {
|
||||||
yy_pop_state();
|
yy_pop_state();
|
||||||
}
|
}
|
||||||
|
void unputString(const char* textp, size_t length) {
|
||||||
|
// Add characters to input stream in back-to-front order
|
||||||
|
const char* cp = textp;
|
||||||
|
for (cp += length - 1; length--; cp--) {
|
||||||
|
unput(*cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); }
|
void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); }
|
||||||
void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); }
|
void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); }
|
||||||
void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); }
|
void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); }
|
||||||
int V3ParseImp::yylexThis() { return parsep()->m_lexerp->yylex(); }
|
|
||||||
|
void V3ParseImp::unputString(const char* textp, size_t length) { parsep()->m_lexerp->unputString(textp, length); }
|
||||||
|
|
||||||
|
int V3ParseImp::yylexReadTok() {
|
||||||
|
// Call yylex() remembering last non-whitespace token
|
||||||
|
int token = parsep()->m_lexerp->yylex();
|
||||||
|
m_prevLexToken = token; // Save so can find '#' to parse following number
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Read class functions
|
// Read class functions
|
||||||
|
|||||||
+3
-3
@@ -225,9 +225,9 @@ private:
|
|||||||
constwidthp->dtypeFrom (nodep->rhsp()); // unsigned
|
constwidthp->dtypeFrom (nodep->rhsp()); // unsigned
|
||||||
AstCond* newp =
|
AstCond* newp =
|
||||||
new AstCond (nodep->fileline(),
|
new AstCond (nodep->fileline(),
|
||||||
new AstLte (nodep->fileline(),
|
new AstGte (nodep->fileline(),
|
||||||
nodep->rhsp()->cloneTree(false),
|
constwidthp,
|
||||||
constwidthp),
|
nodep->rhsp()->cloneTree(false)),
|
||||||
nodep,
|
nodep,
|
||||||
constzerop);
|
constzerop);
|
||||||
replaceHandle.relink(newp);
|
replaceHandle.relink(newp);
|
||||||
|
|||||||
+2
-1
@@ -147,7 +147,8 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->varp()->isTemp() && !nodep->varp()->isParam() && !nodep->varp()->isFuncLocal()) {
|
// Avoid updating this if (), instead see varp->isTrace()
|
||||||
|
if (!nodep->varp()->isTemp() && !nodep->varp()->isFuncLocal()) {
|
||||||
UINFO(5, " vsc "<<nodep<<endl);
|
UINFO(5, " vsc "<<nodep<<endl);
|
||||||
AstVar* varp = nodep->varp();
|
AstVar* varp = nodep->varp();
|
||||||
AstScope* scopep = nodep->scopep();
|
AstScope* scopep = nodep->scopep();
|
||||||
|
|||||||
@@ -957,12 +957,26 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void visitEqNeqWild(AstNodeBiop* nodep) {
|
||||||
|
if (!nodep->rhsp()->castConst()) {
|
||||||
|
nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec.
|
||||||
|
// rhs we want to keep X/Z intact, so otherwise ignore
|
||||||
|
}
|
||||||
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
|
if (nodep->lhsp()->user1p()) { nodep->v3error("Unsupported LHS tristate construct: "<<nodep->prettyTypeName()); return; }
|
||||||
|
}
|
||||||
virtual void visit(AstEqCase* nodep, AstNUser*) {
|
virtual void visit(AstEqCase* nodep, AstNUser*) {
|
||||||
visitCaseEq(nodep,false);
|
visitCaseEq(nodep,false);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNeqCase* nodep, AstNUser*) {
|
virtual void visit(AstNeqCase* nodep, AstNUser*) {
|
||||||
visitCaseEq(nodep,true);
|
visitCaseEq(nodep,true);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstEqWild* nodep, AstNUser*) {
|
||||||
|
visitEqNeqWild(nodep);
|
||||||
|
}
|
||||||
|
virtual void visit(AstNeqWild* nodep, AstNUser*) {
|
||||||
|
visitEqNeqWild(nodep);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstPull* nodep, AstNUser*) {
|
virtual void visit(AstPull* nodep, AstNUser*) {
|
||||||
UINFO(9,dbgState()<<nodep<<endl);
|
UINFO(9,dbgState()<<nodep<<endl);
|
||||||
|
|||||||
+9
-9
@@ -126,7 +126,7 @@ private:
|
|||||||
else {
|
else {
|
||||||
string name = ((string)"__Vlvbound"+cvtToStr(m_modp->varNumGetInc()));
|
string name = ((string)"__Vlvbound"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name,
|
AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name,
|
||||||
VFlagLogicPacked(), prep->width());
|
prep->dtypep());
|
||||||
m_modp->addStmtp(varp);
|
m_modp->addStmtp(varp);
|
||||||
|
|
||||||
AstNode* abovep = prep->backp(); // Grab above point before lose it w/ next replace
|
AstNode* abovep = prep->backp(); // Grab above point before lose it w/ next replace
|
||||||
@@ -163,13 +163,13 @@ private:
|
|||||||
m_assignwp = NULL;
|
m_assignwp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
||||||
m_constXCvt = false; // Avoid loosing the X's in casex
|
m_constXCvt = false; // Avoid losing the X's in casex
|
||||||
nodep->condsp()->iterateAndNext(*this);
|
nodep->condsp()->iterateAndNext(*this);
|
||||||
m_constXCvt = true;
|
m_constXCvt = true;
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
||||||
m_constXCvt = false; // Avoid loosing the X's in casex
|
m_constXCvt = false; // Avoid losing the X's in casex
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_constXCvt = true;
|
m_constXCvt = true;
|
||||||
}
|
}
|
||||||
@@ -342,9 +342,9 @@ private:
|
|||||||
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
|
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
|
||||||
|
|
||||||
// See if the condition is constant true
|
// See if the condition is constant true
|
||||||
AstNode* condp = new AstLte (nodep->fileline(),
|
AstNode* condp = new AstGte (nodep->fileline(),
|
||||||
nodep->lsbp()->cloneTree(false),
|
new AstConst(nodep->fileline(), maxlsbnum),
|
||||||
new AstConst(nodep->fileline(), maxlsbnum));
|
nodep->lsbp()->cloneTree(false));
|
||||||
// Note below has null backp(); the Edit function knows how to deal with that.
|
// Note below has null backp(); the Edit function knows how to deal with that.
|
||||||
condp = V3Const::constifyEdit(condp);
|
condp = V3Const::constifyEdit(condp);
|
||||||
if (condp->isOne()) {
|
if (condp->isOne()) {
|
||||||
@@ -400,9 +400,9 @@ private:
|
|||||||
V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), declElements-1);
|
V3Number widthnum (nodep->fileline(), nodep->bitp()->width(), declElements-1);
|
||||||
|
|
||||||
// See if the condition is constant true
|
// See if the condition is constant true
|
||||||
AstNode* condp = new AstLte (nodep->fileline(),
|
AstNode* condp = new AstGte (nodep->fileline(),
|
||||||
nodep->bitp()->cloneTree(false),
|
new AstConst(nodep->fileline(), widthnum),
|
||||||
new AstConst(nodep->fileline(), widthnum));
|
nodep->bitp()->cloneTree(false));
|
||||||
// Note below has null backp(); the Edit function knows how to deal with that.
|
// Note below has null backp(); the Edit function knows how to deal with that.
|
||||||
condp = V3Const::constifyEdit(condp);
|
condp = V3Const::constifyEdit(condp);
|
||||||
if (condp->isOne()) {
|
if (condp->isOne()) {
|
||||||
|
|||||||
+11
-10
@@ -73,6 +73,7 @@ private:
|
|||||||
nodep->v3error("Unsupported: Can't unroll generate for; "<<reason);
|
nodep->v3error("Unsupported: Can't unroll generate for; "<<reason);
|
||||||
}
|
}
|
||||||
UINFO(3," Can't Unroll: "<<reason<<" :"<<nodep<<endl);
|
UINFO(3," Can't Unroll: "<<reason<<" :"<<nodep<<endl);
|
||||||
|
//if (debug()>=9) nodep->dumpTree(cout,"-cant-");
|
||||||
V3Stats::addStatSum(string("Unrolling gave up, ")+reason, 1);
|
V3Stats::addStatSum(string("Unrolling gave up, ")+reason, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -158,20 +159,20 @@ private:
|
|||||||
if (!constIncp) return cantUnroll(nodep, "non-constant increment");
|
if (!constIncp) return cantUnroll(nodep, "non-constant increment");
|
||||||
if (constIncp->isZero()) return cantUnroll(nodep, "zero increment"); // Or we could loop forever below...
|
if (constIncp->isZero()) return cantUnroll(nodep, "zero increment"); // Or we could loop forever below...
|
||||||
|
|
||||||
bool lt = condp->castLt() || condp->castLtS();
|
bool lt = condp->castLt() || condp->castLtS();
|
||||||
bool lte = condp->castLte() || condp->castLteS();
|
bool lte = condp->castLte() || condp->castLteS();
|
||||||
bool gt = condp->castGt() || condp->castGtS();
|
bool gt = condp->castGt() || condp->castGtS();
|
||||||
bool gte = condp->castGte() || condp->castGteS();
|
bool gte = condp->castGte() || condp->castGteS();
|
||||||
if (!lt && !lte && !gt && !gte)
|
if (!lt && !lte && !gt && !gte)
|
||||||
return cantUnroll(nodep, "condition not <= or <");
|
return cantUnroll(nodep, "condition not <= or <");
|
||||||
AstNodeBiop* condBip = condp->castNodeBiop();
|
AstNodeBiop* condBip = condp->castNodeBiop();
|
||||||
if (!condBip->lhsp()->castVarRef())
|
if (!condBip->rhsp()->castVarRef())
|
||||||
return cantUnroll(nodep, "no variable on lhs of condition");
|
return cantUnroll(nodep, "no variable on rhs of condition");
|
||||||
if (condBip->lhsp()->castVarRef()->varp() != m_forVarp
|
if (condBip->rhsp()->castVarRef()->varp() != m_forVarp
|
||||||
|| condBip->lhsp()->castVarRef()->varScopep() != m_forVscp)
|
|| condBip->rhsp()->castVarRef()->varScopep() != m_forVscp)
|
||||||
return cantUnroll(nodep, "different variable in condition");
|
return cantUnroll(nodep, "different variable in condition");
|
||||||
if (m_generate) V3Const::constifyParamsEdit(condBip->rhsp()); // rhsp may change
|
if (m_generate) V3Const::constifyParamsEdit(condBip->lhsp()); // rhsp may change
|
||||||
AstConst* constStopp = condBip->rhsp()->castConst();
|
AstConst* constStopp = condBip->lhsp()->castConst();
|
||||||
if (!constStopp) return cantUnroll(nodep, "non-constant final value");
|
if (!constStopp) return cantUnroll(nodep, "non-constant final value");
|
||||||
UINFO(8, " Stop expr ok: "<<constStopp<<endl);
|
UINFO(8, " Stop expr ok: "<<constStopp<<endl);
|
||||||
//
|
//
|
||||||
@@ -181,7 +182,7 @@ private:
|
|||||||
return cantUnroll(nodep, "init/final/increment too large or four state");
|
return cantUnroll(nodep, "init/final/increment too large or four state");
|
||||||
vlsint32_t valInit = constInitp->num().toSInt();
|
vlsint32_t valInit = constInitp->num().toSInt();
|
||||||
vlsint32_t valStop = constStopp->num().toSInt();
|
vlsint32_t valStop = constStopp->num().toSInt();
|
||||||
if (lte) valStop++; if (gte) valStop--;
|
if (gte) valStop++; if (lte) valStop--; // 23 >= a, handle as if 24 > a
|
||||||
vlsint32_t valInc = constIncp->num().toSInt();
|
vlsint32_t valInc = constIncp->num().toSInt();
|
||||||
if (subtract) valInc = -valInc;
|
if (subtract) valInc = -valInc;
|
||||||
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
|
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
|
||||||
@@ -269,7 +270,7 @@ private:
|
|||||||
UINFO(8," Looping "<<loopValue<<endl);
|
UINFO(8," Looping "<<loopValue<<endl);
|
||||||
// if loopValue<valStop
|
// if loopValue<valStop
|
||||||
V3Number contin (nodep->fileline(), 1);
|
V3Number contin (nodep->fileline(), 1);
|
||||||
cmpInstrp->numberOperate(contin, loopValue, numStop);
|
cmpInstrp->numberOperate(contin, numStop, loopValue);
|
||||||
if (contin.isEqZero()) {
|
if (contin.isEqZero()) {
|
||||||
break; // Done with the loop
|
break; // Done with the loop
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-1
@@ -106,7 +106,7 @@ public:
|
|||||||
char stageAscii() const { return "-PFB"[m_stage]; }
|
char stageAscii() const { return "-PFB"[m_stage]; }
|
||||||
};
|
};
|
||||||
ostream& operator<<(ostream& str, const WidthVP* vup) {
|
ostream& operator<<(ostream& str, const WidthVP* vup) {
|
||||||
str<<" VUP(w="<<vup->width()<<",wm="<<vup->widthMin()<<",s="<<vup->stageAscii()<<")";
|
str<<" VUP(s="<<vup->stageAscii()<<",w="<<vup->width()<<",wm="<<vup->widthMin()<<",dt="<<(void*)vup->dtypep()<<")";
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1050,6 +1050,7 @@ private:
|
|||||||
nextip = itemp->nextp(); // Will be unlinking
|
nextip = itemp->nextp(); // Will be unlinking
|
||||||
AstNode* inewp;
|
AstNode* inewp;
|
||||||
if (AstInsideRange* irangep = itemp->castInsideRange()) {
|
if (AstInsideRange* irangep = itemp->castInsideRange()) {
|
||||||
|
// Similar logic in V3Case
|
||||||
inewp = new AstAnd(itemp->fileline(),
|
inewp = new AstAnd(itemp->fileline(),
|
||||||
new AstGte(itemp->fileline(),
|
new AstGte(itemp->fileline(),
|
||||||
nodep->exprp()->cloneTree(true),
|
nodep->exprp()->cloneTree(true),
|
||||||
|
|||||||
+35
-29
@@ -175,6 +175,22 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeDType* sliceDType(AstPackArrayDType* nodep, int msb, int lsb) {
|
||||||
|
// Return slice needed for msb/lsb, either as original dtype or a new slice dtype
|
||||||
|
if (nodep->declRange().elements() == (msb-lsb+1) // Extracting whole of original array
|
||||||
|
&& nodep->declRange().lo() == lsb) {
|
||||||
|
return nodep;
|
||||||
|
} else {
|
||||||
|
// Need a slice data type, which is an array of the extracted type, but with (presumably) different size
|
||||||
|
VNumRange newRange (msb, lsb, nodep->declRange().littleEndian());
|
||||||
|
AstNodeDType* vardtypep = new AstPackArrayDType(nodep->fileline(),
|
||||||
|
nodep->subDTypep(), // Need to strip off array reference
|
||||||
|
new AstRange(nodep->fileline(), newRange));
|
||||||
|
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||||
|
return vardtypep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
// If adding new visitors, insure V3Width's visit(TYPE) calls into here
|
// If adding new visitors, insure V3Width's visit(TYPE) calls into here
|
||||||
|
|
||||||
@@ -302,18 +318,7 @@ private:
|
|||||||
new AstConst(nodep->fileline(),AstConst::Unsized32(),(msb-lsb+1)*elwidth));
|
new AstConst(nodep->fileline(),AstConst::Unsized32(),(msb-lsb+1)*elwidth));
|
||||||
newp->declRange(fromRange);
|
newp->declRange(fromRange);
|
||||||
newp->declElWidth(elwidth);
|
newp->declElWidth(elwidth);
|
||||||
if (fromRange.elements() == (msb-lsb+1) // Extracting whole of original array
|
newp->dtypeFrom(sliceDType(adtypep, msb, lsb));
|
||||||
&& fromRange.lo() == lsb) {
|
|
||||||
newp->dtypeFrom(adtypep);
|
|
||||||
} else {
|
|
||||||
// Need a slice data type, which is an array of the extracted type, but with (presumably) different size
|
|
||||||
VNumRange newRange (msb, lsb, fromRange.littleEndian());
|
|
||||||
AstNodeDType* vardtypep = new AstPackArrayDType(nodep->fileline(),
|
|
||||||
adtypep->subDTypep(), // Need to strip off array reference
|
|
||||||
new AstRange(nodep->fileline(), newRange));
|
|
||||||
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
|
||||||
newp->dtypeFrom(vardtypep);
|
|
||||||
}
|
|
||||||
//if (debug()>=9) newp->dumpTree(cout,"--EXTBTn: ");
|
//if (debug()>=9) newp->dumpTree(cout,"--EXTBTn: ");
|
||||||
if (newp->widthMin()!=(int)newp->widthConst()) nodep->v3fatalSrc("Width mismatch");
|
if (newp->widthMin()!=(int)newp->widthConst()) nodep->v3fatalSrc("Width mismatch");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
@@ -388,42 +393,43 @@ private:
|
|||||||
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
||||||
VNumRange fromRange = fromdata.m_fromRange;
|
VNumRange fromRange = fromdata.m_fromRange;
|
||||||
if (ddtypep->castBasicDType()
|
if (ddtypep->castBasicDType()
|
||||||
|
|| ddtypep->castPackArrayDType()
|
||||||
|| (ddtypep->castNodeClassDType()
|
|| (ddtypep->castNodeClassDType()
|
||||||
&& ddtypep->castNodeClassDType()->packedUnsup())) {
|
&& ddtypep->castNodeClassDType()->packedUnsup())) {
|
||||||
AstSel* newp = NULL;
|
int elwidth = 1;
|
||||||
|
AstNode* newwidthp = widthp;
|
||||||
|
if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) {
|
||||||
|
elwidth = adtypep->width() / fromRange.elements();
|
||||||
|
newwidthp = new AstConst (nodep->fileline(),AstConst::Unsized32(), width * elwidth);
|
||||||
|
}
|
||||||
|
AstNode* newlsbp = NULL;
|
||||||
if (nodep->castSelPlus()) {
|
if (nodep->castSelPlus()) {
|
||||||
if (fromRange.littleEndian()) {
|
if (fromRange.littleEndian()) {
|
||||||
// SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)
|
// SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)
|
||||||
newp = new AstSel (nodep->fileline(),
|
newlsbp = newSubNeg((fromRange.hi()-width+1), rhsp);
|
||||||
fromp,
|
|
||||||
newSubNeg((fromRange.hi()-width+1), rhsp),
|
|
||||||
widthp);
|
|
||||||
} else {
|
} else {
|
||||||
// SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width)
|
// SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width)
|
||||||
newp = new AstSel (nodep->fileline(),
|
newlsbp = newSubNeg(rhsp, fromRange.lo());
|
||||||
fromp,
|
|
||||||
newSubNeg(rhsp, fromRange.lo()),
|
|
||||||
widthp);
|
|
||||||
}
|
}
|
||||||
} else if (nodep->castSelMinus()) {
|
} else if (nodep->castSelMinus()) {
|
||||||
if (fromRange.littleEndian()) {
|
if (fromRange.littleEndian()) {
|
||||||
// SELMINUS(from,msb,width) -> SEL(from, msb-[bit])
|
// SELMINUS(from,msb,width) -> SEL(from, msb-[bit])
|
||||||
newp = new AstSel (nodep->fileline(),
|
newlsbp = newSubNeg(fromRange.hi(), rhsp);
|
||||||
fromp,
|
|
||||||
newSubNeg(fromRange.hi(), rhsp),
|
|
||||||
widthp);
|
|
||||||
} else {
|
} else {
|
||||||
// SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#)
|
// SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#)
|
||||||
newp = new AstSel (nodep->fileline(),
|
newlsbp = newSubNeg(rhsp, fromRange.lo()+(width-1));
|
||||||
fromp,
|
|
||||||
newSubNeg(rhsp, fromRange.lo()+(width-1)),
|
|
||||||
widthp);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc("Bad Case");
|
nodep->v3fatalSrc("Bad Case");
|
||||||
}
|
}
|
||||||
|
if (elwidth != 1) newlsbp = new AstMul (nodep->fileline(), newlsbp,
|
||||||
|
new AstConst (nodep->fileline(), elwidth));
|
||||||
|
AstSel* newp = new AstSel (nodep->fileline(),
|
||||||
|
fromp, newlsbp, newwidthp);
|
||||||
newp->declRange(fromRange);
|
newp->declRange(fromRange);
|
||||||
|
newp->declElWidth(elwidth);
|
||||||
UINFO(6," new "<<newp<<endl);
|
UINFO(6," new "<<newp<<endl);
|
||||||
|
if (debug()>=9) newp->dumpTree(cout,"--SELNEW: ");
|
||||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
else { // NULL=bad extract, or unknown node type
|
else { // NULL=bad extract, or unknown node type
|
||||||
|
|||||||
+27
-22
@@ -43,7 +43,8 @@ extern void yyerrorf(const char* format, ...);
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
#define NEXTLINE() {PARSEP->linenoInc();}
|
#define NEXTLINE() {PARSEP->linenoInc();}
|
||||||
#define LINECHECK() { const char* cp=yytext; for (int n=yyleng; n; --n) if (cp[n]=='\n') NEXTLINE(); }
|
#define LINECHECKS(textp,len) { const char* cp=textp; for (int n=len; n; --n) if (cp[n]=='\n') NEXTLINE(); }
|
||||||
|
#define LINECHECK() LINECHECKS(yytext,yyleng)
|
||||||
#define CRELINE() (PARSEP->copyOrSameFileLine())
|
#define CRELINE() (PARSEP->copyOrSameFileLine())
|
||||||
|
|
||||||
#define FL { yylval.fl = CRELINE(); }
|
#define FL { yylval.fl = CRELINE(); }
|
||||||
@@ -149,6 +150,13 @@ id [a-zA-Z_][a-zA-Z0-9_$]*
|
|||||||
/* escaped identifier */
|
/* escaped identifier */
|
||||||
escid \\[^ \t\f\r\n]+
|
escid \\[^ \t\f\r\n]+
|
||||||
word [a-zA-Z0-9_]+
|
word [a-zA-Z0-9_]+
|
||||||
|
/* verilog numbers, constructed to not match the ' that begins a '( or '{ */
|
||||||
|
vnum1 [0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]*
|
||||||
|
vnum2 [0-9]*?['']s?[01xXzZ]
|
||||||
|
vnum3 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+
|
||||||
|
vnum4 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]
|
||||||
|
vnum5 [0-9][_0-9]*[ \t\n]*['']s
|
||||||
|
vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@@ -912,24 +920,21 @@ word [a-zA-Z0-9_]+
|
|||||||
}
|
}
|
||||||
\" { yy_push_state(STRING); yymore(); }
|
\" { yy_push_state(STRING); yymore(); }
|
||||||
|
|
||||||
[0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]* {
|
{vnum} {
|
||||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
/* "# 1'b0" is a delay value so must lex as "#" "1" "'b0" */
|
||||||
return yaINTNUM;
|
if (PARSEP->prevLexToken()=='#') {
|
||||||
}
|
int shortlen = 0;
|
||||||
[0-9]*?['']s?[01xXzZ] { /* SystemVerilog */
|
while (isdigit(yytext[shortlen])) shortlen++;
|
||||||
FL; yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
if (shortlen) {
|
||||||
return yaINTNUM;
|
// Push rest for later parse
|
||||||
}
|
PARSEP->unputString(yytext+shortlen, yyleng-shortlen);
|
||||||
/* Note below is constructed to not match the ' that begins a '( or '{ */
|
FL; LINECHECKS(yytext,shortlen);
|
||||||
[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t]*[A-Fa-f0-9xXzZ_?]+ {
|
// Return is stuff before '
|
||||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
yytext[shortlen] = '\0';
|
||||||
return yaINTNUM;
|
yylval.nump = PARSEP->newNumber(yylval.fl, (char*)yytext);
|
||||||
}
|
return yaINTNUM;
|
||||||
[0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH] {
|
}
|
||||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
}
|
||||||
return yaINTNUM;
|
|
||||||
}
|
|
||||||
[0-9][_0-9]*[ \t\n]*['']s {
|
|
||||||
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
FL; LINECHECK(); yylval.nump = PARSEP->newNumber(yylval.fl,(char*)yytext);
|
||||||
return yaINTNUM;
|
return yaINTNUM;
|
||||||
}
|
}
|
||||||
@@ -1106,8 +1111,8 @@ int V3ParseImp::lexToken() {
|
|||||||
yylval = m_aheadVal;
|
yylval = m_aheadVal;
|
||||||
} else {
|
} else {
|
||||||
// Parse new token
|
// Parse new token
|
||||||
token = yylexThis();
|
token = yylexReadTok();
|
||||||
//yylval // Set by yylexThis()
|
//yylval // Set by yylexReadTok()
|
||||||
}
|
}
|
||||||
// If a paren, read another
|
// If a paren, read another
|
||||||
if (token == yCONST__LEX
|
if (token == yCONST__LEX
|
||||||
@@ -1116,7 +1121,7 @@ int V3ParseImp::lexToken() {
|
|||||||
) {
|
) {
|
||||||
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
|
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
|
||||||
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
|
V3ParseBisonYYSType curValue = yylval; // Remember value, as about to read ahead
|
||||||
int nexttok = yylexThis();
|
int nexttok = yylexReadTok();
|
||||||
m_ahead = true;
|
m_ahead = true;
|
||||||
m_aheadToken = nexttok;
|
m_aheadToken = nexttok;
|
||||||
m_aheadVal = yylval;
|
m_aheadVal = yylval;
|
||||||
|
|||||||
+24
-5
@@ -2190,7 +2190,12 @@ statement_item<nodep>: // IEEE: statement_item
|
|||||||
if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true);
|
if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true);
|
||||||
if ($1 == uniq_PRIORITY) $2->priorityPragma(true); }
|
if ($1 == uniq_PRIORITY) $2->priorityPragma(true); }
|
||||||
//UNSUP caseStart caseAttrE yMATCHES case_patternListE yENDCASE { }
|
//UNSUP caseStart caseAttrE yMATCHES case_patternListE yENDCASE { }
|
||||||
//UNSUP caseStart caseAttrE yINSIDE case_insideListE yENDCASE { }
|
| unique_priorityE caseStart caseAttrE yINSIDE case_insideListE yENDCASE { $$ = $2; if ($5) $2->addItemsp($5);
|
||||||
|
if (!$2->caseSimple()) $2->v3error("Illegal to have inside on a casex/casez");
|
||||||
|
$2->caseInsideSet();
|
||||||
|
if ($1 == uniq_UNIQUE) $2->uniquePragma(true);
|
||||||
|
if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true);
|
||||||
|
if ($1 == uniq_PRIORITY) $2->priorityPragma(true); }
|
||||||
//
|
//
|
||||||
// // IEEE: conditional_statement
|
// // IEEE: conditional_statement
|
||||||
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
|
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
|
||||||
@@ -2328,9 +2333,9 @@ unique_priorityE<uniqstate>: // IEEE: unique_priority + empty
|
|||||||
;
|
;
|
||||||
|
|
||||||
caseStart<casep>: // IEEE: part of case_statement
|
caseStart<casep>: // IEEE: part of case_statement
|
||||||
yCASE '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,AstCaseType::CT_CASE,$3,NULL); }
|
yCASE '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASE,$3,NULL); }
|
||||||
| yCASEX '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,AstCaseType::CT_CASEX,$3,NULL); }
|
| yCASEX '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEX,$3,NULL); }
|
||||||
| yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,AstCaseType::CT_CASEZ,$3,NULL); }
|
| yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEZ,$3,NULL); }
|
||||||
;
|
;
|
||||||
|
|
||||||
caseAttrE:
|
caseAttrE:
|
||||||
@@ -2344,6 +2349,11 @@ case_itemListE<caseitemp>: // IEEE: [ { case_item } ]
|
|||||||
| case_itemList { $$ = $1; }
|
| case_itemList { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
case_insideListE<caseitemp>: // IEEE: [ { case_inside_item } ]
|
||||||
|
/* empty */ { $$ = NULL; }
|
||||||
|
| case_inside_itemList { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
case_itemList<caseitemp>: // IEEE: { case_item + ... }
|
case_itemList<caseitemp>: // IEEE: { case_item + ... }
|
||||||
caseCondList ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); }
|
caseCondList ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); }
|
||||||
| yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($2,NULL,$3); }
|
| yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($2,NULL,$3); }
|
||||||
@@ -2353,6 +2363,15 @@ case_itemList<caseitemp>: // IEEE: { case_item + ... }
|
|||||||
| case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
|
| case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
case_inside_itemList<caseitemp>: // IEEE: { case_inside_item + open_range_list ... }
|
||||||
|
open_range_list ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); }
|
||||||
|
| yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($2,NULL,$3); }
|
||||||
|
| yDEFAULT stmtBlock { $$ = new AstCaseItem($1,NULL,$2); }
|
||||||
|
| case_inside_itemList open_range_list ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); }
|
||||||
|
| case_inside_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); }
|
||||||
|
| case_inside_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,NULL,$4)); }
|
||||||
|
;
|
||||||
|
|
||||||
open_range_list<nodep>: // ==IEEE: open_range_list + open_value_range
|
open_range_list<nodep>: // ==IEEE: open_range_list + open_value_range
|
||||||
open_value_range { $$ = $1; }
|
open_value_range { $$ = $1; }
|
||||||
| open_range_list ',' open_value_range { $$ = $1;$1->addNext($3); }
|
| open_range_list ',' open_value_range { $$ = $1;$1->addNext($3); }
|
||||||
@@ -3708,7 +3727,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
|
|||||||
// We need to autosize parameters and integers separately
|
// We need to autosize parameters and integers separately
|
||||||
//
|
//
|
||||||
// Propagate from current module tracing state
|
// Propagate from current module tracing state
|
||||||
if (nodep->isGenVar() || nodep->isParam()) nodep->trace(false);
|
if (nodep->isGenVar()) nodep->trace(false);
|
||||||
else nodep->trace(v3Global.opt.trace() && nodep->fileline()->tracingOn());
|
else nodep->trace(v3Global.opt.trace() && nodep->fileline()->tracingOn());
|
||||||
|
|
||||||
// Remember the last variable created, so we can attach attributes to it in later parsing
|
// Remember the last variable created, so we can attach attributes to it in later parsing
|
||||||
|
|||||||
@@ -1416,6 +1416,11 @@ sub vcd_identical {
|
|||||||
if ($out ne '') {
|
if ($out ne '') {
|
||||||
print $out;
|
print $out;
|
||||||
$self->error("VCD miscompare $fn1 $fn2\n");
|
$self->error("VCD miscompare $fn1 $fn2\n");
|
||||||
|
if ($ENV{HARNESS_UPDATE_GOLDEN}) { # Update golden files with current
|
||||||
|
warn "%Warning: HARNESS_UPDATE_GOLDEN set: cp $fn1 $fn2\n";
|
||||||
|
eval "use File::Copy;";
|
||||||
|
File::Copy::copy($fn1,$fn2);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
// please note it here, otherwise:**
|
// please note it here, otherwise:**
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2013 by ____YOUR_NAME_HERE____.
|
// without warranty, 2014 by ____YOUR_NAME_HERE____.
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|||||||
Executable
+18
@@ -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,82 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2014 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
reg [63:0] crc;
|
||||||
|
reg [63:0] sum;
|
||||||
|
|
||||||
|
logic [2:0] [1:0] in;
|
||||||
|
always @* in = crc[5:0];
|
||||||
|
|
||||||
|
/*AUTOWIRE*/
|
||||||
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||||
|
logic [1:0] [1:0] out; // From test of Test.v
|
||||||
|
// End of automatics
|
||||||
|
|
||||||
|
Test test (/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.out (out/*[1:0][1:0]*/),
|
||||||
|
// Inputs
|
||||||
|
.clk (clk),
|
||||||
|
.in (in/*[2:0][1:0]*/));
|
||||||
|
|
||||||
|
// Aggregate outputs into a single result vector
|
||||||
|
wire [63:0] result = {60'h0, out[1],out[0]};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h5aef0c8d_d70a4497;
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc<10) begin
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
|
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||||
|
// What checksum will we end up with (above print should match)
|
||||||
|
`define EXPECTED_SUM 64'hdc21e42d85441511
|
||||||
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Test (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
out,
|
||||||
|
// Inputs
|
||||||
|
clk, in
|
||||||
|
);
|
||||||
|
|
||||||
|
//bug717
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
input logic [2:0][1:0] in;
|
||||||
|
|
||||||
|
output logic [1:0][1:0] out;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
out <= in[2 -: 2];
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -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,66 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2014 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc; initial cyc=0;
|
||||||
|
reg [63:0] crc;
|
||||||
|
reg [63:0] sum;
|
||||||
|
|
||||||
|
reg out1;
|
||||||
|
reg [4:0] out2;
|
||||||
|
sub sub (.in(crc[23:0]), .out1(out1), .out2(out2));
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
`ifdef TEST_VERBOSE
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x in[3:0]=%x out=%x,%x\n",$time, cyc, crc, sum, crc[3:0], out1,out2);
|
||||||
|
`endif
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {58'h0,out1,out2};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h00000000_00000097;
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
|
`define EXPECTED_SUM 64'h10204fa5567c8a4b
|
||||||
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module sub (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
out1, out2,
|
||||||
|
// Inputs
|
||||||
|
in
|
||||||
|
);
|
||||||
|
|
||||||
|
input [23:0] in;
|
||||||
|
output reg out1;
|
||||||
|
output reg [4:0] out2;
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
case (in[3:0]) inside
|
||||||
|
default: {out1,out2} = {1'b0,5'h0F}; // Note not last item
|
||||||
|
4'h1, 4'h2, 4'h3: {out1,out2} = {1'b1,5'h01};
|
||||||
|
4'h4: {out1,out2} = {1'b1,5'h04};
|
||||||
|
[4'h6:4'h5]: {out1,out2} = {1'b1,5'h05}; // order backwards, will not match
|
||||||
|
4'b100?:/*8,9*/ {out1,out2} = {1'b1,5'h08};
|
||||||
|
[4'hc:4'hf]: {out1,out2} = {1'b1,5'h0C};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -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,83 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2014 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
reg [63:0] crc;
|
||||||
|
reg [63:0] sum;
|
||||||
|
|
||||||
|
wire [4:0] in = crc[4:0];
|
||||||
|
|
||||||
|
/*AUTOWIRE*/
|
||||||
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||||
|
logic out; // From test of Test.v
|
||||||
|
// End of automatics
|
||||||
|
|
||||||
|
Test test (/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.out (out),
|
||||||
|
// Inputs
|
||||||
|
.clk (clk),
|
||||||
|
.in (in[4:0]));
|
||||||
|
|
||||||
|
// Aggregate outputs into a single result vector
|
||||||
|
wire [63:0] result = {63'h0, out};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h5aef0c8d_d70a4497;
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc<10) begin
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
|
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||||
|
// What checksum will we end up with (above print should match)
|
||||||
|
`define EXPECTED_SUM 64'h7a7bd4ee927e7cc3
|
||||||
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Test (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
out,
|
||||||
|
// Inputs
|
||||||
|
clk, in
|
||||||
|
);
|
||||||
|
|
||||||
|
//bug718
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
input logic [4:0] in;
|
||||||
|
|
||||||
|
output logic out;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
out <= in inside {5'b1_1?1?};
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // t
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/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.
|
||||||
|
|
||||||
|
$Self->unsupported("Verilator/commercial slice unsupported, bug711");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2014 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
reg [63:0] crc;
|
||||||
|
reg [63:0] sum;
|
||||||
|
|
||||||
|
// Take CRC data and apply to testblock inputs
|
||||||
|
wire [31:0] in = crc[31:0];
|
||||||
|
|
||||||
|
/*AUTOWIRE*/
|
||||||
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||||
|
wire [15:0] out; // From test of Test.v
|
||||||
|
// End of automatics
|
||||||
|
|
||||||
|
Test test (/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.out (out[15:0]),
|
||||||
|
// Inputs
|
||||||
|
.in (in[31:0]));
|
||||||
|
|
||||||
|
// Aggregate outputs into a single result vector
|
||||||
|
wire [63:0] result = {48'h0, out};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h5aef0c8d_d70a4497;
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc<10) begin
|
||||||
|
sum <= 64'h0;
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||||
|
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||||
|
// What checksum will we end up with (above print should match)
|
||||||
|
`define EXPECTED_SUM 64'h4afe43fb79d7b71e
|
||||||
|
if (sum !== `EXPECTED_SUM) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module callee (input [7:0] port [7:0], output [7:0] o);
|
||||||
|
assign o = ^{port[0], port[1], port[2], port[3],
|
||||||
|
port[4], port[5], port[6], port[7]};
|
||||||
|
endmodule // callee
|
||||||
|
|
||||||
|
module Test (/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
out,
|
||||||
|
// Inputs
|
||||||
|
in
|
||||||
|
);
|
||||||
|
|
||||||
|
input [31:0] in;
|
||||||
|
output reg [15:0] out;
|
||||||
|
|
||||||
|
wire [7:0] port [15:0];
|
||||||
|
wire [7:0] goodport [7:0];
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
port[0][7:0] = in[7:0];
|
||||||
|
port[1][7:0] = in[16:8];
|
||||||
|
port[2] = '0;
|
||||||
|
port[3] = '0;
|
||||||
|
port[4] = '0;
|
||||||
|
port[5] = '0;
|
||||||
|
port[6] = '0;
|
||||||
|
port[7] = '0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
goodport[0][7:0] = in[7:0];
|
||||||
|
goodport[1][7:0] = in[16:8];
|
||||||
|
goodport[2] = '0;
|
||||||
|
goodport[3] = '0;
|
||||||
|
goodport[4] = '0;
|
||||||
|
goodport[5] = '0;
|
||||||
|
goodport[6] = '0;
|
||||||
|
goodport[7] = '0;
|
||||||
|
end
|
||||||
|
|
||||||
|
callee good (.port(goodport), .o(out[7:0]));
|
||||||
|
|
||||||
|
// This is a slice, unsupported by other tools, bug711
|
||||||
|
callee bad (.port(port[7:0]), .o(out[15:8]));
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2008 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.
|
||||||
|
|
||||||
|
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
fails=>1,
|
||||||
|
verilator_make_gcc => 0,
|
||||||
|
make_top_shell => 0,
|
||||||
|
make_main => 0,
|
||||||
|
expect=>
|
||||||
|
'%Error: t/t_lint_input_eq_bad.v:\d+: Unsupported: Default value on module input: i2
|
||||||
|
%Error: Exiting due to.*',
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2010 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t
|
||||||
|
(
|
||||||
|
input wire i,
|
||||||
|
input wire i2 = i // BAD
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+18
@@ -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,20 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2014 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
// verilator lint_off WIDTH
|
||||||
|
reg [6:0] myreg1;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
myreg1 = # 100 7'd0;
|
||||||
|
myreg1 = # 100 'b0; // [#] [100] ['b0]
|
||||||
|
myreg1 = #100'b0; // [#] [100] ['b0]
|
||||||
|
myreg1 = 100'b0;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
$version Generated by VerilatedVcd $end
|
$version Generated by VerilatedVcd $end
|
||||||
$date Sat Dec 14 19:07:34 2013
|
$date Sat Mar 8 15:28:02 2014
|
||||||
$end
|
$end
|
||||||
$timescale 1ns $end
|
$timescale 1ns $end
|
||||||
|
|
||||||
@@ -24,6 +24,12 @@ $timescale 1ns $end
|
|||||||
$var wire 2 $ v_strp [1:0] $end
|
$var wire 2 $ v_strp [1:0] $end
|
||||||
$var wire 4 % v_strp_strp [3:0] $end
|
$var wire 4 % v_strp_strp [3:0] $end
|
||||||
$var wire 2 & v_unip_strp [1:0] $end
|
$var wire 2 & v_unip_strp [1:0] $end
|
||||||
|
$scope module p2 $end
|
||||||
|
$var wire 32 7 P [31:0] $end
|
||||||
|
$upscope $end
|
||||||
|
$scope module p3 $end
|
||||||
|
$var wire 32 8 P [31:0] $end
|
||||||
|
$upscope $end
|
||||||
$scope module unnamedblk1 $end
|
$scope module unnamedblk1 $end
|
||||||
$var wire 32 . b [31:0] $end
|
$var wire 32 . b [31:0] $end
|
||||||
$scope module unnamedblk2 $end
|
$scope module unnamedblk2 $end
|
||||||
@@ -56,6 +62,8 @@ b00000000000000000000000000000000 /
|
|||||||
04
|
04
|
||||||
05
|
05
|
||||||
06
|
06
|
||||||
|
b00000000000000000000000000000010 7
|
||||||
|
b00000000000000000000000000000011 8
|
||||||
#10
|
#10
|
||||||
b00000000000000000000000000000001 #
|
b00000000000000000000000000000001 #
|
||||||
b11 $
|
b11 $
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ module t (clk);
|
|||||||
arru_arrp_t v_arru_arrp;
|
arru_arrp_t v_arru_arrp;
|
||||||
arru_strp_t v_arru_strp;
|
arru_strp_t v_arru_strp;
|
||||||
|
|
||||||
|
p #(.P(2)) p2 ();
|
||||||
|
p #(.P(3)) p3 ();
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
cyc <= cyc + 1;
|
cyc <= cyc + 1;
|
||||||
v_strp <= ~v_strp;
|
v_strp <= ~v_strp;
|
||||||
@@ -65,3 +68,7 @@ module t (clk);
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module p;
|
||||||
|
parameter P = 1;
|
||||||
|
endmodule
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
$version Generated by VerilatedVcd $end
|
$version Generated by VerilatedVcd $end
|
||||||
$date Sat Dec 14 18:56:47 2013
|
$date Sat Mar 8 15:28:22 2014
|
||||||
$end
|
$end
|
||||||
$timescale 1ns $end
|
$timescale 1ns $end
|
||||||
|
|
||||||
@@ -19,6 +19,12 @@ $timescale 1ns $end
|
|||||||
$var wire 1 ? v_arru_arru(3)(2) $end
|
$var wire 1 ? v_arru_arru(3)(2) $end
|
||||||
$var wire 1 @ v_arru_arru(4)(1) $end
|
$var wire 1 @ v_arru_arru(4)(1) $end
|
||||||
$var wire 1 A v_arru_arru(4)(2) $end
|
$var wire 1 A v_arru_arru(4)(2) $end
|
||||||
|
$scope module p2 $end
|
||||||
|
$var wire 32 B P [31:0] $end
|
||||||
|
$upscope $end
|
||||||
|
$scope module p3 $end
|
||||||
|
$var wire 32 C P [31:0] $end
|
||||||
|
$upscope $end
|
||||||
$scope module unnamedblk1 $end
|
$scope module unnamedblk1 $end
|
||||||
$var wire 32 9 b [31:0] $end
|
$var wire 32 9 b [31:0] $end
|
||||||
$scope module unnamedblk2 $end
|
$scope module unnamedblk2 $end
|
||||||
@@ -102,6 +108,8 @@ b00000000000000000000000000000000 :
|
|||||||
0?
|
0?
|
||||||
0@
|
0@
|
||||||
0A
|
0A
|
||||||
|
b00000000000000000000000000000010 B
|
||||||
|
b00000000000000000000000000000011 C
|
||||||
#10
|
#10
|
||||||
b00000000000000000000000000000001 #
|
b00000000000000000000000000000001 #
|
||||||
1$
|
1$
|
||||||
|
|||||||
Reference in New Issue
Block a user