Support negative bit indexes.
Allow arbitrary characters in symbols (to make '-' work.) Final merge from negative_lsb branch.
This commit is contained in:
parent
cdd6ea8e60
commit
3b1929259a
3
Changes
3
Changes
|
|
@ -5,6 +5,9 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
* Verilator 3.67**
|
* Verilator 3.67**
|
||||||
|
|
||||||
|
** Support negative bit indexes. [Stephane Laurent]
|
||||||
|
Tracing negative indexes requires latest Verilog-Perl and SystemPerl.
|
||||||
|
|
||||||
*** Suppress width warnings between constant strings and wider vectors.
|
*** Suppress width warnings between constant strings and wider vectors.
|
||||||
[Rodney Sinclair]
|
[Rodney Sinclair]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,14 @@ string AstNode::encodeName(const string& namein) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstNode::encodeNumber(vlsint64_t num) {
|
||||||
|
if (num < 0) {
|
||||||
|
return "__2D"+cvtToStr(-num); // 2D=-
|
||||||
|
} else {
|
||||||
|
return cvtToStr(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string AstNode::shortName() const {
|
string AstNode::shortName() const {
|
||||||
string pretty = name();
|
string pretty = name();
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
|
|
|
||||||
|
|
@ -579,6 +579,7 @@ public:
|
||||||
static string dedotName(const string& namein); // Name with dots removed
|
static string dedotName(const string& namein); // Name with dots removed
|
||||||
static string prettyName(const string& namein); // Name for printing out to the user
|
static string prettyName(const string& namein); // Name for printing out to the user
|
||||||
static string encodeName(const string& namein); // Encode user name into internal C representation
|
static string encodeName(const string& namein); // Encode user name into internal C representation
|
||||||
|
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
|
||||||
string prettyName() const { return prettyName(name()); }
|
string prettyName() const { return prettyName(name()); }
|
||||||
FileLine* fileline() const { return m_fileline; }
|
FileLine* fileline() const { return m_fileline; }
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ void AstNodeVarRef::cloneRelink() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int AstNodeSel::bitConst() const {
|
int AstNodeSel::bitConst() const {
|
||||||
AstConst* constp=bitp()->castConst(); return (constp?constp->asInt():0);
|
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isSigPublic() const {
|
bool AstVar::isSigPublic() const {
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ public:
|
||||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||||
virtual string name() const { return num().ascii(); } // * = Value
|
virtual string name() const { return num().ascii(); } // * = Value
|
||||||
virtual const V3Number& num() const { return m_num; } // * = Value
|
virtual const V3Number& num() const { return m_num; } // * = Value
|
||||||
uint32_t asInt() const { return num().asInt(); } // Old, should be removed
|
|
||||||
uint32_t toUInt() const { return num().toUInt(); }
|
uint32_t toUInt() const { return num().toUInt(); }
|
||||||
|
vlsint32_t toSInt() const { return num().toSInt(); }
|
||||||
vluint64_t toUQuad() const { return num().toUQuad(); }
|
vluint64_t toUQuad() const { return num().toUQuad(); }
|
||||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||||
|
|
@ -79,8 +79,8 @@ struct AstRange : public AstNode {
|
||||||
AstRange* cloneTree(bool cloneNextLink) { return AstNode::cloneTree(cloneNextLink)->castRange(); }
|
AstRange* cloneTree(bool cloneNextLink) { return AstNode::cloneTree(cloneNextLink)->castRange(); }
|
||||||
AstNode* msbp() const { return op2p()->castNode(); } // op2 = Msb expression
|
AstNode* msbp() const { return op2p()->castNode(); } // op2 = Msb expression
|
||||||
AstNode* lsbp() const { return op3p()->castNode(); } // op3 = Lsb expression
|
AstNode* lsbp() const { return op3p()->castNode(); } // op3 = Lsb expression
|
||||||
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->asInt():0); }
|
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->toSInt():0); }
|
||||||
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->asInt():0); }
|
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->toSInt():0); }
|
||||||
int elementsConst() const { return msbConst()-lsbConst()+1; }
|
int elementsConst() const { return msbConst()-lsbConst()+1; }
|
||||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
|
|
@ -193,7 +193,7 @@ struct AstSel : public AstNodeTriop {
|
||||||
// Children: varref|arraysel, math, constant math
|
// Children: varref|arraysel, math, constant math
|
||||||
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
|
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
|
||||||
:AstNodeTriop(fl, fromp, lsbp, widthp) {
|
:AstNodeTriop(fl, fromp, lsbp, widthp) {
|
||||||
if (widthp->castConst()) width(widthp->castConst()->asInt(), widthp->castConst()->asInt());
|
if (widthp->castConst()) width(widthp->castConst()->toUInt(), widthp->castConst()->toUInt());
|
||||||
}
|
}
|
||||||
AstSel(FileLine* fl, AstNode* fromp, int lsbp, int bitwidth)
|
AstSel(FileLine* fl, AstNode* fromp, int lsbp, int bitwidth)
|
||||||
:AstNodeTriop(fl, fromp,
|
:AstNodeTriop(fl, fromp,
|
||||||
|
|
@ -205,7 +205,7 @@ struct AstSel : public AstNodeTriop {
|
||||||
virtual AstNode* clone() { return new AstSel(*this); }
|
virtual AstNode* clone() { return new AstSel(*this); }
|
||||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) {
|
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) {
|
||||||
out.opRange(from, bit.asInt()+width.asInt()-1, bit.asInt()); }
|
out.opRange(from, bit.toUInt()+width.toUInt()-1, bit.toUInt()); }
|
||||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||||
virtual string emitC() {
|
virtual string emitC() {
|
||||||
return this->widthp()->isOne()
|
return this->widthp()->isOne()
|
||||||
|
|
@ -222,9 +222,9 @@ struct AstSel : public AstNodeTriop {
|
||||||
AstNode* fromp() const { return op1p()->castNode(); } // op1 = Extracting what (NULL=TBD during parsing)
|
AstNode* fromp() const { return op1p()->castNode(); } // op1 = Extracting what (NULL=TBD during parsing)
|
||||||
AstNode* lsbp() const { return op2p()->castNode(); } // op2 = Msb selection expression
|
AstNode* lsbp() const { return op2p()->castNode(); } // op2 = Msb selection expression
|
||||||
AstNode* widthp() const { return op3p()->castNode(); } // op3 = Width
|
AstNode* widthp() const { return op3p()->castNode(); } // op3 = Width
|
||||||
uint32_t lsbConst() const { return lsbp()->castConst()->asInt(); }
|
int widthConst() const { return widthp()->castConst()->toSInt(); }
|
||||||
uint32_t widthConst() const { return widthp()->castConst()->toUInt(); }
|
int lsbConst() const { return lsbp()->castConst()->toSInt(); }
|
||||||
uint32_t msbConst() const { return lsbConst()+widthConst()-1; }
|
int msbConst() const { return lsbConst()+widthConst()-1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstVar : public AstNode {
|
struct AstVar : public AstNode {
|
||||||
|
|
@ -363,8 +363,9 @@ public:
|
||||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||||
int widthAlignBytes() const; // Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
int widthAlignBytes() const; // Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||||
int widthTotalBytes() const; // Width in bytes rounding up 1,2,4,8,12,...
|
int widthTotalBytes() const; // Width in bytes rounding up 1,2,4,8,12,...
|
||||||
uint32_t msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
|
int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
|
||||||
uint32_t lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); }
|
int lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); }
|
||||||
|
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
|
||||||
uint32_t arrayElements() const; // 1, or total multiplication of all dimensions
|
uint32_t arrayElements() const; // 1, or total multiplication of all dimensions
|
||||||
virtual string verilogKwd() const;
|
virtual string verilogKwd() const;
|
||||||
void propagateAttrFrom(AstVar* fromp) {
|
void propagateAttrFrom(AstVar* fromp) {
|
||||||
|
|
@ -1694,8 +1695,8 @@ struct AstTraceDecl : public AstNodeStmt {
|
||||||
private:
|
private:
|
||||||
string m_showname; // Name of variable
|
string m_showname; // Name of variable
|
||||||
uint32_t m_code; // Trace identifier code; converted to ASCII by trace routines
|
uint32_t m_code; // Trace identifier code; converted to ASCII by trace routines
|
||||||
uint32_t m_lsb; // Property of var the trace details
|
int m_lsb; // Property of var the trace details
|
||||||
uint32_t m_msb; // Property of var the trace details
|
int m_msb; // Property of var the trace details
|
||||||
uint32_t m_arrayLsb; // Property of var the trace details
|
uint32_t m_arrayLsb; // Property of var the trace details
|
||||||
uint32_t m_arrayMsb; // Property of var the trace details
|
uint32_t m_arrayMsb; // Property of var the trace details
|
||||||
uint32_t m_codeInc; // Code increment
|
uint32_t m_codeInc; // Code increment
|
||||||
|
|
@ -1723,8 +1724,8 @@ public:
|
||||||
uint32_t code() const { return m_code; }
|
uint32_t code() const { return m_code; }
|
||||||
void code(uint32_t code) { m_code=code; }
|
void code(uint32_t code) { m_code=code; }
|
||||||
uint32_t codeInc() const { return m_codeInc; }
|
uint32_t codeInc() const { return m_codeInc; }
|
||||||
uint32_t msb() const { return m_msb; }
|
int msb() const { return m_msb; }
|
||||||
uint32_t lsb() const { return m_lsb; }
|
int lsb() const { return m_lsb; }
|
||||||
uint32_t arrayMsb() const { return m_arrayMsb; }
|
uint32_t arrayMsb() const { return m_arrayMsb; }
|
||||||
uint32_t arrayLsb() const { return m_arrayLsb; }
|
uint32_t arrayLsb() const { return m_arrayLsb; }
|
||||||
uint32_t arrayWidth() const { if (!arrayMsb()) return 0; return arrayMsb()-arrayLsb()+1; }
|
uint32_t arrayWidth() const { if (!arrayMsb()) return 0; return arrayMsb()-arrayLsb()+1; }
|
||||||
|
|
|
||||||
|
|
@ -134,11 +134,11 @@ private:
|
||||||
}
|
}
|
||||||
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->width()));
|
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()));
|
||||||
}
|
}
|
||||||
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->lhsp()->width()));
|
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()));
|
||||||
}
|
}
|
||||||
bool operandIsTwo(AstNode* nodep) {
|
bool operandIsTwo(AstNode* nodep) {
|
||||||
return (nodep->castConst()
|
return (nodep->castConst()
|
||||||
|
|
@ -215,15 +215,18 @@ private:
|
||||||
bool warnSelect(AstSel* nodep) {
|
bool warnSelect(AstSel* nodep) {
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||||
|
AstVar* varp = varrefp->varp();
|
||||||
if (m_warn
|
if (m_warn
|
||||||
&& nodep->lsbp()->castConst()
|
&& nodep->lsbp()->castConst()
|
||||||
&& nodep->widthp()->castConst()
|
&& nodep->widthp()->castConst()
|
||||||
&& (!varrefp->varp()->rangep() || varrefp->varp()->msb()) // else it's non-resolvable parameterized
|
&& (!varp->rangep() || varp->msb()) // else it's non-resolvable parameterized
|
||||||
&& ( ( (nodep->msbConst() > varrefp->varp()->msb())
|
&& ( ( (nodep->msbConst() > varp->msbMaxSelect())
|
||||||
|| (nodep->lsbConst() > varrefp->varp()->msb())))) {
|
|| (nodep->lsbConst() > varp->msbMaxSelect())))) {
|
||||||
nodep->v3error("Selection index out of range: "
|
nodep->v3error("Selection index out of range: "
|
||||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||||
<<" outside "<<varrefp->varp()->msb()<<":0");
|
<<" outside "<<varp->msbMaxSelect()<<":0"
|
||||||
|
<<(varp->lsb()>=0 ? ""
|
||||||
|
:" (adjusted +"+cvtToStr(-varp->lsb())+" to account for negative lsb)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false; // Not a transform, so NOP
|
return false; // Not a transform, so NOP
|
||||||
|
|
@ -432,8 +435,8 @@ private:
|
||||||
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
||||||
} else {
|
} else {
|
||||||
// We know shift amounts are constant, but might be a mixed left/right shift
|
// We know shift amounts are constant, but might be a mixed left/right shift
|
||||||
int shift1 = shift1p->castConst()->asInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
||||||
int shift2 = shift2p->castConst()->asInt(); if (nodep->castShiftR()) shift2=-shift2;
|
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
|
||||||
int newshift = shift1+shift2;
|
int newshift = shift1+shift2;
|
||||||
shift1p->deleteTree(); shift1p=NULL;
|
shift1p->deleteTree(); shift1p=NULL;
|
||||||
shift2p->deleteTree(); shift1p=NULL;
|
shift2p->deleteTree(); shift1p=NULL;
|
||||||
|
|
@ -490,9 +493,9 @@ private:
|
||||||
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
|
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
|
||||||
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
|
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
|
||||||
// Swap?
|
// Swap?
|
||||||
if (( con1p->asInt() != con2p->asInt() + sel2p->width())
|
if (( con1p->toSInt() != con2p->toSInt() + sel2p->width())
|
||||||
&&(con2p->asInt() != con1p->asInt() + sel1p->width())) return false;
|
&&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false;
|
||||||
bool lsbFirstAssign = (con1p->asInt() < con2p->asInt());
|
bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt());
|
||||||
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
|
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
|
||||||
//if (VL_BITBIT_I(con1p->toUInt()) == 0) return false;
|
//if (VL_BITBIT_I(con1p->toUInt()) == 0) return false;
|
||||||
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
|
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
|
||||||
|
|
@ -648,7 +651,7 @@ private:
|
||||||
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
|
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
|
||||||
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
|
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
|
||||||
if (!shiftp->rhsp()->castConst()) return false;
|
if (!shiftp->rhsp()->castConst()) return false;
|
||||||
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->asInt()) return false;
|
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->toUInt()) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void replaceBoolShift(AstNode* nodep) {
|
void replaceBoolShift(AstNode* nodep) {
|
||||||
|
|
@ -784,7 +787,7 @@ private:
|
||||||
AstNode* newlsbp;
|
AstNode* newlsbp;
|
||||||
if (lsb1p->castConst() && lsb2p->castConst()) {
|
if (lsb1p->castConst() && lsb2p->castConst()) {
|
||||||
newlsbp = new AstConst(lsb1p->fileline(),
|
newlsbp = new AstConst(lsb1p->fileline(),
|
||||||
lsb1p->castConst()->asInt() + lsb2p->castConst()->asInt());
|
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
|
||||||
lsb1p->deleteTree(); lsb1p=NULL;
|
lsb1p->deleteTree(); lsb1p=NULL;
|
||||||
lsb2p->deleteTree(); lsb2p=NULL;
|
lsb2p->deleteTree(); lsb2p=NULL;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -851,7 +854,7 @@ private:
|
||||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||||
AstSel* newp = new AstSel(nodep->fileline(),
|
AstSel* newp = new AstSel(nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
new AstConst(lsbp->fileline(), lsbp->asInt() % fromp->width()),
|
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||||
widthp);
|
widthp);
|
||||||
newp->widthSignedFrom(nodep);
|
newp->widthSignedFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||||
|
|
|
||||||
|
|
@ -362,11 +362,11 @@ public:
|
||||||
if (nodep->widthp()->isOne()) {
|
if (nodep->widthp()->isOne()) {
|
||||||
nodep->lsbp()->iterateAndNext(*this);
|
nodep->lsbp()->iterateAndNext(*this);
|
||||||
} else {
|
} else {
|
||||||
puts(cvtToStr(nodep->lsbp()->castConst()->asInt()
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()
|
||||||
+nodep->widthp()->castConst()->asInt()
|
+nodep->widthp()->castConst()->toSInt()
|
||||||
-1));
|
-1));
|
||||||
puts(":");
|
puts(":");
|
||||||
nodep->lsbp()->iterateAndNext(*this);
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->lsbp()->iterateAndNext(*this); puts("+:");
|
nodep->lsbp()->iterateAndNext(*this); puts("+:");
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ private:
|
||||||
// Return equation to get the VL_BITWORD of a constant or non-constant
|
// Return equation to get the VL_BITWORD of a constant or non-constant
|
||||||
if (lsbp->castConst()) {
|
if (lsbp->castConst()) {
|
||||||
return new AstConst (lsbp->fileline(),
|
return new AstConst (lsbp->fileline(),
|
||||||
wordAdder + VL_BITWORD_I(lsbp->castConst()->asInt()));
|
wordAdder + VL_BITWORD_I(lsbp->castConst()->toUInt()));
|
||||||
} else {
|
} else {
|
||||||
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
|
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
|
||||||
lsbp->cloneTree(true),
|
lsbp->cloneTree(true),
|
||||||
|
|
@ -203,7 +203,7 @@ private:
|
||||||
// Return equation to get the VL_BITBIT of a constant or non-constant
|
// Return equation to get the VL_BITBIT of a constant or non-constant
|
||||||
if (lsbp->castConst()) {
|
if (lsbp->castConst()) {
|
||||||
return new AstConst (lsbp->fileline(),
|
return new AstConst (lsbp->fileline(),
|
||||||
VL_BITBIT_I(lsbp->castConst()->asInt()));
|
VL_BITBIT_I(lsbp->castConst()->toUInt()));
|
||||||
} else {
|
} else {
|
||||||
return new AstAnd (lsbp->fileline(),
|
return new AstAnd (lsbp->fileline(),
|
||||||
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
|
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,8 @@ private:
|
||||||
m_dotText = "";
|
m_dotText = "";
|
||||||
nodep->lhsp()->iterateAndNext(*this);
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
||||||
m_dotText = m_dotText+"__BRA__"+cvtToStr(constp->asInt())+"__KET__";
|
string index = AstNode::encodeNumber(constp->toSInt());
|
||||||
|
m_dotText = m_dotText+"__BRA__"+index+"__KET__";
|
||||||
} else {
|
} else {
|
||||||
nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference");
|
nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,7 @@ private:
|
||||||
AstNode* widthp;
|
AstNode* widthp;
|
||||||
if (msbp->castConst() && lsbp->castConst()) {
|
if (msbp->castConst() && lsbp->castConst()) {
|
||||||
// Quite common, save V3Const some effort
|
// Quite common, save V3Const some effort
|
||||||
V3Number widnum (msbp->fileline(),32,msbp->castConst()->asInt() +1-lsbp->castConst()->asInt());
|
V3Number widnum (msbp->fileline(),32,msbp->castConst()->toSInt() +1-lsbp->castConst()->toSInt());
|
||||||
widnum.width(32,false); // Unsized so width from user
|
widnum.width(32,false); // Unsized so width from user
|
||||||
widthp = new AstConst (msbp->fileline(), widnum);
|
widthp = new AstConst (msbp->fileline(), widnum);
|
||||||
pushDeletep(msbp);
|
pushDeletep(msbp);
|
||||||
|
|
|
||||||
|
|
@ -470,10 +470,16 @@ uint32_t V3Number::toUInt() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
vlsint32_t V3Number::toSInt() const {
|
vlsint32_t V3Number::toSInt() const {
|
||||||
uint32_t v = toUInt();
|
if (isSigned()) {
|
||||||
uint32_t signExtend = (-(v & (1UL<<(width()-1))));
|
uint32_t v = toUInt();
|
||||||
uint32_t extended = v | signExtend;
|
uint32_t signExtend = (-(v & (1UL<<(width()-1))));
|
||||||
return (vlsint32_t)(extended);
|
uint32_t extended = v | signExtend;
|
||||||
|
return (vlsint32_t)(extended);
|
||||||
|
} else {
|
||||||
|
// Where we use this (widths, etc) and care about signedness,
|
||||||
|
// we can reasonably assume the MSB isn't set on unsigned numbers.
|
||||||
|
return (vlsint32_t)toUInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vluint64_t V3Number::toUQuad() const {
|
vluint64_t V3Number::toUQuad() const {
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,6 @@ public:
|
||||||
void width(int width, bool sized=true);
|
void width(int width, bool sized=true);
|
||||||
void isSigned(bool ssigned) { m_signed=ssigned; }
|
void isSigned(bool ssigned) { m_signed=ssigned; }
|
||||||
bool isUnknown() const;
|
bool isUnknown() const;
|
||||||
uint32_t asInt() const { return toUInt(); } // Deprecated, use toUInt/toSInt
|
|
||||||
uint32_t toUInt() const;
|
uint32_t toUInt() const;
|
||||||
vlsint32_t toSInt() const;
|
vlsint32_t toSInt() const;
|
||||||
vluint64_t toUQuad() const;
|
vluint64_t toUQuad() const;
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,11 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int unrollCount() {
|
||||||
|
return m_generate ? v3Global.opt.unrollCount()*16
|
||||||
|
: v3Global.opt.unrollCount();
|
||||||
|
}
|
||||||
|
|
||||||
bool forUnrollCheck(AstNode* nodep,
|
bool forUnrollCheck(AstNode* nodep,
|
||||||
AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp)
|
AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp)
|
||||||
AstNode* precondsp, AstNode* condp,
|
AstNode* precondsp, AstNode* condp,
|
||||||
|
|
@ -158,16 +163,16 @@ private:
|
||||||
|| constStopp->width()>32 || constStopp->num().isFourState()
|
|| constStopp->width()>32 || constStopp->num().isFourState()
|
||||||
|| constIncp->width()>32 || constIncp->num().isFourState())
|
|| constIncp->width()>32 || constIncp->num().isFourState())
|
||||||
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().toUInt(); // Extract as unsigned, then make signed
|
vlsint32_t valInit = constInitp->num().toSInt();
|
||||||
vlsint32_t valStop = constStopp->num().toUInt(); // Extract as unsigned, then make signed
|
vlsint32_t valStop = constStopp->num().toSInt();
|
||||||
if (lte) valStop++; if (gte) valStop--;
|
if (lte) valStop++; if (gte) valStop--;
|
||||||
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");
|
||||||
//
|
//
|
||||||
if (!m_generate) {
|
if (!m_generate) {
|
||||||
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<v3Global.opt.unrollCount()<<endl);
|
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<unrollCount()<<endl);
|
||||||
if (((valStop - valInit)/valInc) > v3Global.opt.unrollCount())
|
if (((valStop - valInit)/valInc) > unrollCount())
|
||||||
return cantUnroll(nodep, "too many iterations");
|
return cantUnroll(nodep, "too many iterations");
|
||||||
|
|
||||||
// Less than 10 statements in the body?
|
// Less than 10 statements in the body?
|
||||||
|
|
@ -253,8 +258,8 @@ private:
|
||||||
else newbodysp = oneloopp;
|
else newbodysp = oneloopp;
|
||||||
|
|
||||||
m_statIters++;
|
m_statIters++;
|
||||||
if (++times > v3Global.opt.unrollCount()*3) {
|
if (++times > unrollCount()*3) {
|
||||||
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop.");
|
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,9 +352,10 @@ private:
|
||||||
) {
|
) {
|
||||||
// Rename it, as otherwise we may get a conflict
|
// Rename it, as otherwise we may get a conflict
|
||||||
// V3Begin sees these DOTs and makes CellInlines for us.
|
// V3Begin sees these DOTs and makes CellInlines for us.
|
||||||
string nname = (string)"genfor"+cvtToStr(m_varValuep->asInt())+"__DOT__"+nodep->name();
|
string index = AstNode::encodeNumber(m_varValuep->toSInt());
|
||||||
|
string nname = (string)"genfor"+index+"__DOT__"+nodep->name();
|
||||||
// Verilog seems to drop the for loop name and tack on [#]
|
// Verilog seems to drop the for loop name and tack on [#]
|
||||||
nname = nodep->name() + "__BRA__" + cvtToStr(m_varValuep->asInt()) + "__KET__";
|
nname = nodep->name() + "__BRA__" + index + "__KET__";
|
||||||
//UINFO(8," Rename begin "<<nname<<" "<<nodep<<endl);
|
//UINFO(8," Rename begin "<<nname<<" "<<nodep<<endl);
|
||||||
nodep->name(nname);
|
nodep->name(nname);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -238,9 +238,9 @@ private:
|
||||||
if (!lsbConstp) nodep->v3error("LSB of bit range isn't a constant");
|
if (!lsbConstp) nodep->v3error("LSB of bit range isn't a constant");
|
||||||
nodep->width(1,1); return;
|
nodep->width(1,1); return;
|
||||||
}
|
}
|
||||||
uint32_t msb = msbConstp->asInt();
|
int msb = msbConstp->toSInt();
|
||||||
uint32_t lsb = lsbConstp->asInt();
|
int lsb = lsbConstp->toSInt();
|
||||||
if (msb > (1UL<<28)) nodep->v3error("MSB of bit range is huge; vector of over 1billion bits: 0x"<<hex<<msb);
|
if (msb > (1<<28)) nodep->v3error("MSB of bit range is huge; vector of over 1billion bits: 0x"<<hex<<msb);
|
||||||
if (msb<lsb) {
|
if (msb<lsb) {
|
||||||
// If it's a array, ok to have either ordering, we'll just correct
|
// If it's a array, ok to have either ordering, we'll just correct
|
||||||
// So, see if we're sitting under a variable's arrayp.
|
// So, see if we're sitting under a variable's arrayp.
|
||||||
|
|
@ -296,7 +296,7 @@ private:
|
||||||
int fromlsb = 0;
|
int fromlsb = 0;
|
||||||
AstNodeVarRef* varrp = nodep->fromp()->castNodeVarRef();
|
AstNodeVarRef* varrp = nodep->fromp()->castNodeVarRef();
|
||||||
if (varrp && varrp->varp()->rangep()) { // Selecting a bit from a multibit register
|
if (varrp && varrp->varp()->rangep()) { // Selecting a bit from a multibit register
|
||||||
frommsb = varrp->varp()->msb();
|
frommsb = varrp->varp()->msbMaxSelect(); // Corrected for negative lsb
|
||||||
fromlsb = varrp->varp()->lsb();
|
fromlsb = varrp->varp()->lsb();
|
||||||
}
|
}
|
||||||
int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit
|
int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit
|
||||||
|
|
@ -332,6 +332,8 @@ private:
|
||||||
frommsb = varrp->varp()->arrayp(dimension)->msbConst();
|
frommsb = varrp->varp()->arrayp(dimension)->msbConst();
|
||||||
fromlsb = varrp->varp()->arrayp(dimension)->lsbConst();
|
fromlsb = varrp->varp()->arrayp(dimension)->lsbConst();
|
||||||
if (fromlsb>frommsb) {int t=frommsb; frommsb=fromlsb; fromlsb=t; }
|
if (fromlsb>frommsb) {int t=frommsb; frommsb=fromlsb; fromlsb=t; }
|
||||||
|
// However, if the lsb<0 we may go negative, so need more bits!
|
||||||
|
if (fromlsb < 0) frommsb += -fromlsb;
|
||||||
nodep->width(outwidth,outwidth); // Width out = width of array
|
nodep->width(outwidth,outwidth); // Width out = width of array
|
||||||
}
|
}
|
||||||
int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit
|
int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ module t (
|
||||||
output reg RESET
|
output reg RESET
|
||||||
);
|
);
|
||||||
|
|
||||||
|
neg neg (.clk(CLK));
|
||||||
glbl glbl;
|
glbl glbl;
|
||||||
|
|
||||||
initial RESET = 1'b1;
|
initial RESET = 1'b1;
|
||||||
|
|
@ -28,3 +29,19 @@ module glbl();
|
||||||
wire GSR /*verilator public*/;
|
wire GSR /*verilator public*/;
|
||||||
`endif
|
`endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module neg (
|
||||||
|
input clk
|
||||||
|
);
|
||||||
|
|
||||||
|
reg [0:-7] i8; initial i8 = '0;
|
||||||
|
reg [-1:-48] i48; initial i48 = '0;
|
||||||
|
reg [63:-64] i128; initial i128 = '0;
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
i8 <= ~i8;
|
||||||
|
i48 <= ~i48;
|
||||||
|
i128 <= ~i128;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
$version Generated by SpTraceVcd $end
|
$version Generated by SpTraceVcd $end
|
||||||
$date Wed Jun 11 19:43:32 2008
|
$date Thu Sep 18 07:54:41 2008
|
||||||
$end
|
$end
|
||||||
$timescale 1ns $end
|
$timescale 1ns $end
|
||||||
|
|
||||||
$scope module TOP $end
|
$scope module TOP $end
|
||||||
$var wire 1 $ CLK $end
|
$var wire 1 , CLK $end
|
||||||
$var wire 1 % RESET $end
|
$var wire 1 - RESET $end
|
||||||
$scope module v $end
|
$scope module v $end
|
||||||
$var wire 1 $ CLK $end
|
$var wire 1 , CLK $end
|
||||||
$var wire 1 # RESET $end
|
$var wire 1 # RESET $end
|
||||||
$scope module glbl $end
|
$scope module glbl $end
|
||||||
$var wire 1 & GSR $end
|
$var wire 1 + GSR $end
|
||||||
|
$upscope $end
|
||||||
|
$scope module neg $end
|
||||||
|
$var wire 1 , clk $end
|
||||||
|
$var wire 128 ' i128 [63:-64] $end
|
||||||
|
$var wire 48 % i48 [-1:-48] $end
|
||||||
|
$var wire 8 $ i8 [0:-7] $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
|
|
@ -19,35 +25,47 @@ $enddefinitions $end
|
||||||
|
|
||||||
#0
|
#0
|
||||||
1#
|
1#
|
||||||
0$
|
b00000000 $
|
||||||
1%
|
b000000000000000000000000000000000000000000000000 %
|
||||||
1&
|
b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
|
||||||
|
1+
|
||||||
|
1-
|
||||||
|
0,
|
||||||
#1
|
#1
|
||||||
#2
|
#2
|
||||||
#3
|
#3
|
||||||
1$
|
b11111111 $
|
||||||
|
b111111111111111111111111111111111111111111111111 %
|
||||||
|
b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 '
|
||||||
|
1,
|
||||||
#4
|
#4
|
||||||
#5
|
#5
|
||||||
#6
|
#6
|
||||||
0$
|
0,
|
||||||
#7
|
#7
|
||||||
0&
|
0+
|
||||||
#8
|
#8
|
||||||
#9
|
#9
|
||||||
0#
|
0#
|
||||||
1$
|
b00000000 $
|
||||||
0%
|
b000000000000000000000000000000000000000000000000 %
|
||||||
|
b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
|
||||||
|
0-
|
||||||
|
1,
|
||||||
#10
|
#10
|
||||||
#11
|
#11
|
||||||
#12
|
#12
|
||||||
0$
|
0,
|
||||||
#13
|
#13
|
||||||
#14
|
#14
|
||||||
#15
|
#15
|
||||||
1$
|
b11111111 $
|
||||||
|
b111111111111111111111111111111111111111111111111 %
|
||||||
|
b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 '
|
||||||
|
1,
|
||||||
#16
|
#16
|
||||||
#17
|
#17
|
||||||
#18
|
#18
|
||||||
0$
|
0,
|
||||||
#19
|
#19
|
||||||
#20
|
#20
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
$version Generated by SpTraceVcd $end
|
$version Generated by SpTraceVcd $end
|
||||||
$date Wed Jun 11 19:43:32 2008
|
$date Thu Sep 18 07:55:56 2008
|
||||||
$end
|
$end
|
||||||
$timescale 1ns $end
|
$timescale 1ns $end
|
||||||
|
|
||||||
$scope module TOP $end
|
$scope module TOP $end
|
||||||
$var wire 1 $ CLK $end
|
$var wire 1 + CLK $end
|
||||||
$var wire 1 % RESET $end
|
$var wire 1 , RESET $end
|
||||||
$scope module v $end
|
$scope module v $end
|
||||||
$var wire 1 $ CLK $end
|
$var wire 1 + CLK $end
|
||||||
$var wire 1 # RESET $end
|
$var wire 1 # RESET $end
|
||||||
$scope module glbl $end
|
$scope module glbl $end
|
||||||
$var wire 1 & GSR $end
|
$var wire 1 - GSR $end
|
||||||
|
$upscope $end
|
||||||
|
$scope module neg $end
|
||||||
|
$var wire 1 + clk $end
|
||||||
|
$var wire 128 ' i128 [63:-64] $end
|
||||||
|
$var wire 48 % i48 [-1:-48] $end
|
||||||
|
$var wire 8 $ i8 [0:-7] $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
$upscope $end
|
$upscope $end
|
||||||
|
|
@ -19,35 +25,47 @@ $enddefinitions $end
|
||||||
|
|
||||||
#0
|
#0
|
||||||
1#
|
1#
|
||||||
0$
|
b00000000 $
|
||||||
1%
|
b000000000000000000000000000000000000000000000000 %
|
||||||
1&
|
b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
|
||||||
|
1,
|
||||||
|
0+
|
||||||
|
1-
|
||||||
#1
|
#1
|
||||||
#2
|
#2
|
||||||
#3
|
#3
|
||||||
1$
|
b11111111 $
|
||||||
|
b111111111111111111111111111111111111111111111111 %
|
||||||
|
b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 '
|
||||||
|
1+
|
||||||
#4
|
#4
|
||||||
#5
|
#5
|
||||||
#6
|
#6
|
||||||
0$
|
0+
|
||||||
#7
|
#7
|
||||||
0&
|
0-
|
||||||
#8
|
#8
|
||||||
#9
|
#9
|
||||||
0#
|
0#
|
||||||
1$
|
b00000000 $
|
||||||
0%
|
b000000000000000000000000000000000000000000000000 %
|
||||||
|
b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 '
|
||||||
|
0,
|
||||||
|
1+
|
||||||
#10
|
#10
|
||||||
#11
|
#11
|
||||||
#12
|
#12
|
||||||
0$
|
0+
|
||||||
#13
|
#13
|
||||||
#14
|
#14
|
||||||
#15
|
#15
|
||||||
1$
|
b11111111 $
|
||||||
|
b111111111111111111111111111111111111111111111111 %
|
||||||
|
b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 '
|
||||||
|
1+
|
||||||
#16
|
#16
|
||||||
#17
|
#17
|
||||||
#18
|
#18
|
||||||
0$
|
0+
|
||||||
#19
|
#19
|
||||||
#20
|
#20
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ our $Rerun_Args = $0." ".join(' ',@Orig_ARGV);
|
||||||
|
|
||||||
use vars qw (@Blocks
|
use vars qw (@Blocks
|
||||||
%Vars
|
%Vars
|
||||||
|
%VarAttrs
|
||||||
%VarsBlock
|
%VarsBlock
|
||||||
%Tree
|
%Tree
|
||||||
@Commit
|
@Commit
|
||||||
|
|
@ -40,6 +41,7 @@ use vars qw (@Blocks
|
||||||
# width=> Number of bits the output size is, 0=you tell me.
|
# width=> Number of bits the output size is, 0=you tell me.
|
||||||
# func=> What to put in output file
|
# func=> What to put in output file
|
||||||
# signed=> 0=unsigned output, 1=signed output, '%1'=signed if op1 signed
|
# signed=> 0=unsigned output, 1=signed output, '%1'=signed if op1 signed
|
||||||
|
# lsb=> LSB for variable declarations
|
||||||
# em=> How to calculate emulated return value
|
# em=> How to calculate emulated return value
|
||||||
# %w Width of this output op ($treeref->{width})
|
# %w Width of this output op ($treeref->{width})
|
||||||
# %v Output value ($treeref->{val})
|
# %v Output value ($treeref->{val})
|
||||||
|
|
@ -118,13 +120,31 @@ my %ops2 =
|
||||||
(
|
(
|
||||||
'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'},
|
'VCONST'=> {pl=>'', rnd=>'rnd_const(%tr);'},
|
||||||
'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};',
|
'VIDNEW'=> {pl=>'%tv=$Vars{%i}{val};',
|
||||||
rnd=>'%i=next_id(%tw); $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg); id_commit(%tr,"%i");1;',},
|
rnd=>'%i=next_id(%tw);'
|
||||||
|
.' $Vars{%i}=gen_leaf(width=>%tw,trunc=>1,signed=>%tg);'
|
||||||
|
.' $VarAttrs{%i}{lsb} = rnd_lsb();'
|
||||||
|
.' id_commit(%tr,"%i");1;',},
|
||||||
'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_old(%tr);', ok_id_width=>1,},
|
'VIDOLD'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_old(%tr);', ok_id_width=>1,},
|
||||||
'VIDSAME'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_same(%tr);', ok_id_width=>1,},
|
'VIDSAME'=> {pl=>'%tv=$Vars{%i}{val};', rnd=>'%i=id_same(%tr);', ok_id_width=>1,},
|
||||||
'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1; %2r=val_leaf($msb); %3r=val_leaf($lsb); $Vars{%i}=gen_leaf(width=>($msb+1));'},
|
# These create IDs they then extract from
|
||||||
'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v);', rnd=>'%i=next_id(%tw); my $wid=min(128,rnd_width()|3); %2r=gen_leaf(width=>(log2($wid)-1),signed=>0); $Vars{%i}=gen_leaf(width=>$wid);'},
|
'VRANGE'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});',
|
||||||
'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0)); $Vars{%i}=gen_leaf(width=>$wid);'},
|
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
|
||||||
'VBITSELM'=> {pl=>'VBITSELM(%tr,$Vars{%i}{val},%2v,%3v);', rnd=>'%i=next_id(%tw); my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-1; my $minval=%tw-1; %2r=val_leaf(rnd($maxval-$minval)+$minval); $Vars{%i}=gen_leaf(width=>$wid);'}, # No easy way to make expr with specified minimum
|
.' my $lsb=rnd(128-%tw); my $msb=$lsb+%tw-1;'
|
||||||
|
.' %2r=val_leaf($msb); %3r=val_leaf($lsb);'
|
||||||
|
.' $Vars{%i}=gen_leaf(width=>($msb+1));'},
|
||||||
|
'VBITSEL'=> {pl=>'VRANGE(%tr,$Vars{%i}{val},%2v,%2v,$VarAttrs{%i}{lsb});',
|
||||||
|
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
|
||||||
|
.' my $wid=min(128,rnd_width()|3);'
|
||||||
|
.' %2r=gen_leaf(width=>(log2($wid)-1),signed=>0);'
|
||||||
|
.' $Vars{%i}=gen_leaf(width=>$wid);'},
|
||||||
|
'VBITSELP'=> {pl=>'VBITSELP(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});',
|
||||||
|
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
|
||||||
|
.' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-%tw; %2r=(($maxval<4)?val_leaf($maxval):gen_leaf(width=>(log2($maxval)-1),signed=>0));'
|
||||||
|
.' $Vars{%i}=gen_leaf(width=>$wid);'},
|
||||||
|
'VBITSELM'=> {pl=>'VBITSELM(%tr,$Vars{%i}{val},%2v,%3v,$VarAttrs{%i}{lsb});',
|
||||||
|
rnd=>'%i=next_id(%tw); $VarAttrs{%i}{lsb} = 0&&rnd_lsb();'
|
||||||
|
.' my $wid=min(128,(%tw+rnd_width()|3)); %3r=val_leaf(%tw); my $maxval = $wid-1; my $minval=%tw-1; %2r=val_leaf(rnd($maxval-$minval)+$minval);'
|
||||||
|
.' $Vars{%i}=gen_leaf(width=>$wid);'}, # No easy way to make expr with specified minimum
|
||||||
# Unary
|
# Unary
|
||||||
'VEXTEND'=> {pl=>'VRESIZE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>rnd_width(%tw-1));'},
|
'VEXTEND'=> {pl=>'VRESIZE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>rnd_width(%tw-1));'},
|
||||||
'VLOGNOT'=> {pl=>'VLOGNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
|
'VLOGNOT'=> {pl=>'VLOGNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
|
||||||
|
|
@ -388,6 +408,11 @@ sub rnd_int {
|
||||||
return rnd32();
|
return rnd32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub rnd_lsb {
|
||||||
|
return 0;
|
||||||
|
#return rnd(8)-4; # Not working yet
|
||||||
|
}
|
||||||
|
|
||||||
sub rnd {
|
sub rnd {
|
||||||
return (int(rand($_[0]))) if ($_[0] < (1<<15));
|
return (int(rand($_[0]))) if ($_[0] < (1<<15));
|
||||||
return (rnd32() % $_[0]);
|
return (rnd32() % $_[0]);
|
||||||
|
|
@ -818,12 +843,14 @@ sub decl_text {
|
||||||
return sprintf " %s<%s> %s; //=%s"
|
return sprintf " %s<%s> %s; //=%s"
|
||||||
, $decl_with, $type, $var, $varref->{val}->to_Hex;
|
, $decl_with, $type, $var, $varref->{val}->to_Hex;
|
||||||
} else {
|
} else {
|
||||||
return sprintf " reg %s [%3d:0] %s %s; //=%s"
|
return sprintf " reg %s [%3d:%3d] %s %s; //=%d'h%s"
|
||||||
, ($varref->{signed}?"signed":" ")
|
, ($varref->{signed}?"signed":" ")
|
||||||
, ($varref->{val}->Size)-1,
|
, ($varref->{val}->Size)-1+$VarAttrs{$var}{lsb},
|
||||||
|
, $VarAttrs{$var}{lsb}
|
||||||
, $var
|
, $var
|
||||||
, (rnd(100)<30 ? "/*verilator public*/":(" "x length("/*verilator public*/")))
|
, (rnd(100)<30 ? "/*verilator public*/":(" "x length("/*verilator public*/")))
|
||||||
, $varref->{val}->to_Hex;
|
, $varref->{val}->Size
|
||||||
|
, lc $varref->{val}->to_Hex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -948,29 +975,35 @@ sub VPOW { # Power is a signed operation
|
||||||
print "VV = $o\n";
|
print "VV = $o\n";
|
||||||
}
|
}
|
||||||
sub VRANGE { #print "RANGE ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[3]->to_Hex," \n";
|
sub VRANGE { #print "RANGE ",$_[1]->to_Hex,' ',$_[2]->to_Hex,' ',$_[3]->to_Hex," \n";
|
||||||
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0),$_[3]->Word_Read(0)); }
|
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0),$_[3]->Word_Read(0), $_[4]); }
|
||||||
sub VBITSELP {
|
sub VBITSELP {
|
||||||
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0)+$_[3]->Word_Read(0)-1, $_[2]->Word_Read(0)); }
|
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0)+$_[3]->Word_Read(0)-1, $_[2]->Word_Read(0), $_[4]); }
|
||||||
sub VBITSELM {
|
sub VBITSELM {
|
||||||
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0), $_[2]->Word_Read(0)-$_[3]->Word_Read(0)+1); }
|
return VRANGE_CONST($_[0],$_[1],$_[2]->Word_Read(0), $_[2]->Word_Read(0)-$_[3]->Word_Read(0)+1, $_[4]); }
|
||||||
sub VRANGE_CONST { #print "RANGE ",$_[1]->to_Hex,' ',$_[2],' ',$_[3]," \n";
|
sub VRANGE_CONST {
|
||||||
my $size = $_[2] - $_[3] + 1;
|
# to, from, msb, lsb, variable_lsb_to_subtract
|
||||||
my $o=Bit::Vector->new($size);
|
#print "RANGE ",$_[1]->to_Hex,' ',$_[2],' ',$_[3],' ',$_[4]," \n";
|
||||||
if ($_[3] < $_[1]->Size) {
|
my $size = $_[2] - $_[3] + 1;
|
||||||
$o->Interval_Copy($_[1],0,$_[3],$size);
|
my $o=Bit::Vector->new($size);
|
||||||
}
|
if ($_[3] < $_[1]->Size) {
|
||||||
$_[0]{val}=$o; }
|
$o->Interval_Copy($_[1],0,$_[3]-$_[4],$size);
|
||||||
sub VCONCAT { my $o=Bit::Vector->new($_[1]->Size + $_[2]->Size);
|
}
|
||||||
$o->Interval_Copy($_[1],$_[2]->Size,0,$_[1]->Size);
|
$_[0]{val}=$o; }
|
||||||
$o->Interval_Copy($_[2],0,0,$_[2]->Size);
|
sub VCONCAT {
|
||||||
$_[0]{val}=$o; }
|
my $o=Bit::Vector->new($_[1]->Size + $_[2]->Size);
|
||||||
sub VREPLIC { my $o=Bit::Vector->new($_[1]->Word_Read(0) * $_[2]->Size);
|
$o->Interval_Copy($_[1],$_[2]->Size,0,$_[1]->Size);
|
||||||
my $pos = 0;
|
$o->Interval_Copy($_[2],0,0,$_[2]->Size);
|
||||||
for (my $time=0; $time<($_[1]->Word_Read(0)); $time++) {
|
$_[0]{val}=$o;
|
||||||
$o->Interval_Copy($_[2],$pos,0,$_[2]->Size);
|
}
|
||||||
$pos += $_[2]->Size;
|
sub VREPLIC {
|
||||||
}
|
my $o=Bit::Vector->new($_[1]->Word_Read(0) * $_[2]->Size);
|
||||||
$_[0]{val}=$o; }
|
my $pos = 0;
|
||||||
|
for (my $time=0; $time<($_[1]->Word_Read(0)); $time++) {
|
||||||
|
$o->Interval_Copy($_[2],$pos,0,$_[2]->Size);
|
||||||
|
$pos += $_[2]->Size;
|
||||||
|
}
|
||||||
|
$_[0]{val}=$o;
|
||||||
|
}
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue