Support , and related functions, bug448.
This commit is contained in:
parent
00bd947385
commit
929aeebf12
2
Changes
2
Changes
|
|
@ -14,6 +14,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
*** Support VPI product info, warning calls, etc, bug588. [Rick Porter]
|
*** Support VPI product info, warning calls, etc, bug588. [Rick Porter]
|
||||||
|
|
||||||
|
*** Support $left, $right and related functions, bug448. [Iztok Jeras]
|
||||||
|
|
||||||
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
|
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
|
||||||
|
|
||||||
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]
|
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]
|
||||||
|
|
|
||||||
18
src/V3Ast.h
18
src/V3Ast.h
|
|
@ -219,7 +219,16 @@ class AstAttrType {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
ILLEGAL,
|
ILLEGAL,
|
||||||
EXPR_BITS, // V3Const converts to constant
|
//
|
||||||
|
DIM_BITS, // V3Const converts to constant
|
||||||
|
DIM_DIMENSIONS, // V3Width converts to constant
|
||||||
|
DIM_HIGH, // V3Width processes
|
||||||
|
DIM_INCREMENT, // V3Width processes
|
||||||
|
DIM_LEFT, // V3Width processes
|
||||||
|
DIM_LOW, // V3Width processes
|
||||||
|
DIM_RIGHT, // V3Width processes
|
||||||
|
DIM_SIZE, // V3Width processes
|
||||||
|
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
|
||||||
//
|
//
|
||||||
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||||
//
|
//
|
||||||
|
|
@ -237,7 +246,10 @@ public:
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"%E-AT", "EXPR_BITS", "MEMBER_BASE",
|
"%E-AT",
|
||||||
|
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||||
|
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||||
|
"MEMBER_BASE",
|
||||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||||
|
|
@ -1520,7 +1532,7 @@ public:
|
||||||
bool generic() const { return m_generic; }
|
bool generic() const { return m_generic; }
|
||||||
void generic(bool flag) { m_generic = flag; }
|
void generic(bool flag) { m_generic = flag; }
|
||||||
AstNodeDType* dtypeDimensionp(int depth);
|
AstNodeDType* dtypeDimensionp(int depth);
|
||||||
pair<uint32_t,uint32_t> dimensions();
|
pair<uint32_t,uint32_t> dimensions(bool includeBasic);
|
||||||
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
||||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -358,21 +358,22 @@ uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
|
pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
|
||||||
// How many array dimensions (packed,unpacked) does this Var have?
|
// How many array dimensions (packed,unpacked) does this Var have?
|
||||||
uint32_t packed = 0;
|
uint32_t packed = 0;
|
||||||
uint32_t unpacked = 0;
|
uint32_t unpacked = 0;
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
if (adtypep->castPackArrayDType()) packed += 1;
|
if (adtypep->castPackArrayDType()) packed++;
|
||||||
else unpacked += 1;
|
else unpacked++;
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
// AstBasicDType - nothing below, 1
|
if (includeBasic && adtypep->isRanged()) packed++;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return make_pair(packed, unpacked);
|
return make_pair(packed, unpacked);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,11 @@ public:
|
||||||
:AstNodeMath(fl)
|
:AstNodeMath(fl)
|
||||||
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
|
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
|
||||||
AstNumeric::UNSIGNED); }
|
AstNumeric::UNSIGNED); }
|
||||||
|
class Signed32 {}; // for creator type-overload selection
|
||||||
|
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
|
||||||
|
:AstNodeMath(fl)
|
||||||
|
,m_num(V3Number(fl,32,num)) { m_num.width(32,32); dtypeSetLogicSized(32,m_num.widthMin(),
|
||||||
|
AstNumeric::SIGNED); }
|
||||||
class RealDouble {}; // for creator type-overload selection
|
class RealDouble {}; // for creator type-overload selection
|
||||||
AstConst(FileLine* fl, RealDouble, double num)
|
AstConst(FileLine* fl, RealDouble, double num)
|
||||||
:AstNodeMath(fl)
|
:AstNodeMath(fl)
|
||||||
|
|
@ -2736,12 +2741,14 @@ private:
|
||||||
// Return a value of a attribute, for example a LSB or array LSB of a signal
|
// Return a value of a attribute, for example a LSB or array LSB of a signal
|
||||||
AstAttrType m_attrType; // What sort of extraction
|
AstAttrType m_attrType; // What sort of extraction
|
||||||
public:
|
public:
|
||||||
AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp=NULL)
|
AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp=NULL, AstNode* dimp=NULL)
|
||||||
: AstNode(fl) {
|
: AstNode(fl) {
|
||||||
setNOp1p(fromp);
|
setNOp1p(fromp);
|
||||||
|
setNOp2p(dimp);
|
||||||
m_attrType = attrtype; }
|
m_attrType = attrtype; }
|
||||||
ASTNODE_NODE_FUNCS(AttrOf, ATTROF)
|
ASTNODE_NODE_FUNCS(AttrOf, ATTROF)
|
||||||
AstNode* fromp() const { return op1p(); }
|
AstNode* fromp() const { return op1p(); }
|
||||||
|
AstNode* dimp() const { return op2p(); }
|
||||||
AstAttrType attrType() const { return m_attrType; }
|
AstAttrType attrType() const { return m_attrType; }
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -440,6 +440,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||||
putfs(nodep,"$_ATTROF(");
|
putfs(nodep,"$_ATTROF(");
|
||||||
nodep->fromp()->iterateAndNext(*this);
|
nodep->fromp()->iterateAndNext(*this);
|
||||||
|
if (nodep->dimp()) {
|
||||||
|
putbs(",");
|
||||||
|
nodep->dimp()->iterateAndNext(*this);
|
||||||
|
}
|
||||||
puts(")");
|
puts(")");
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||||
if (m_vecIdx == (int)m_selBits.size()) {
|
if (m_vecIdx == (int)m_selBits.size()) {
|
||||||
m_selBits.push_back(vector<unsigned>());
|
m_selBits.push_back(vector<unsigned>());
|
||||||
AstVar* varp = m_refp->varp();
|
AstVar* varp = m_refp->varp();
|
||||||
pair<uint32_t,uint32_t> arrDim = varp->dtypep()->dimensions();
|
pair<uint32_t,uint32_t> arrDim = varp->dtypep()->dimensions(false);
|
||||||
uint32_t dimensions = arrDim.second;
|
uint32_t dimensions = arrDim.second;
|
||||||
for (uint32_t i = 0; i < dimensions; ++i) {
|
for (uint32_t i = 0; i < dimensions; ++i) {
|
||||||
m_selBits[m_vecIdx].push_back(0);
|
m_selBits[m_vecIdx].push_back(0);
|
||||||
|
|
@ -292,7 +292,7 @@ class SliceVisitor : public AstNVisitor {
|
||||||
// The LHS/RHS of an Assign may be to a Var that is an array. In this
|
// The LHS/RHS of an Assign may be to a Var that is an array. In this
|
||||||
// case we need to create a slice accross the entire Var
|
// case we need to create a slice accross the entire Var
|
||||||
if (m_assignp && !nodep->backp()->castArraySel()) {
|
if (m_assignp && !nodep->backp()->castArraySel()) {
|
||||||
pair<uint32_t,uint32_t> arrDim = nodep->varp()->dtypep()->dimensions();
|
pair<uint32_t,uint32_t> arrDim = nodep->varp()->dtypep()->dimensions(false);
|
||||||
uint32_t dimensions = arrDim.second; // unpacked only
|
uint32_t dimensions = arrDim.second; // unpacked only
|
||||||
if (dimensions > 0) {
|
if (dimensions > 0) {
|
||||||
AstVarRef* clonep = nodep->cloneTree(false);
|
AstVarRef* clonep = nodep->cloneTree(false);
|
||||||
|
|
@ -326,7 +326,7 @@ class SliceVisitor : public AstNVisitor {
|
||||||
if (nodep->user3()) return; // Prevent recursion on just created nodes
|
if (nodep->user3()) return; // Prevent recursion on just created nodes
|
||||||
unsigned dim = explicitDimensions(nodep);
|
unsigned dim = explicitDimensions(nodep);
|
||||||
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
|
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
|
||||||
pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions();
|
pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions(false);
|
||||||
uint32_t implicit = (arrDim.second) - dim;
|
uint32_t implicit = (arrDim.second) - dim;
|
||||||
if (implicit > 0) {
|
if (implicit > 0) {
|
||||||
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
|
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
|
||||||
|
|
@ -428,7 +428,7 @@ class SliceVisitor : public AstNVisitor {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
} else {
|
} else {
|
||||||
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
|
||||||
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions();
|
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
|
||||||
if ((int)(dim - varDim.second) < 0) {
|
if ((int)(dim - varDim.second) < 0) {
|
||||||
// Unpacked dimensions are referenced first, make sure we have them all
|
// Unpacked dimensions are referenced first, make sure we have them all
|
||||||
nodep->v3error("Unary operator used across unpacked dimensions");
|
nodep->v3error("Unary operator used across unpacked dimensions");
|
||||||
|
|
|
||||||
141
src/V3Width.cpp
141
src/V3Width.cpp
|
|
@ -121,6 +121,7 @@ private:
|
||||||
AstAttrOf* m_attrp; // Current attribute
|
AstAttrOf* m_attrp; // Current attribute
|
||||||
AstNodeDType* m_assDTypep; // Assign LHS data type for assignment pattern
|
AstNodeDType* m_assDTypep; // Assign LHS data type for assignment pattern
|
||||||
bool m_doGenerate; // Do errors later inside generate statement
|
bool m_doGenerate; // Do errors later inside generate statement
|
||||||
|
int m_dtTables; // Number of created data type tables
|
||||||
|
|
||||||
// CLASSES
|
// CLASSES
|
||||||
#define ANYSIZE 0
|
#define ANYSIZE 0
|
||||||
|
|
@ -655,14 +656,41 @@ private:
|
||||||
m_attrp = nodep;
|
m_attrp = nodep;
|
||||||
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
// Don't iterate children, don't want to lose VarRef.
|
// Don't iterate children, don't want to lose VarRef.
|
||||||
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
|
if (nodep->attrType()==AstAttrType::VAR_BASE) {
|
||||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
|
||||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->width());
|
|
||||||
nodep->replaceWith(new AstConst(nodep->fileline(), num)); nodep->deleteTree(); nodep=NULL;
|
|
||||||
} else if (nodep->attrType()==AstAttrType::VAR_BASE) {
|
|
||||||
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
||||||
} else if (nodep->attrType()==AstAttrType::MEMBER_BASE) {
|
} else if (nodep->attrType()==AstAttrType::MEMBER_BASE) {
|
||||||
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
|
||||||
|
} else if (nodep->attrType()==AstAttrType::DIM_DIMENSIONS
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS) {
|
||||||
|
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||||
|
pair<uint32_t,uint32_t> dim = nodep->fromp()->dtypep()->dimensions(true);
|
||||||
|
int val = (nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS
|
||||||
|
? dim.second : (dim.first+dim.second));
|
||||||
|
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); nodep->deleteTree(); nodep=NULL;
|
||||||
|
} else if (nodep->attrType()==AstAttrType::DIM_BITS
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_HIGH
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_INCREMENT
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_LEFT
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_LOW
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_RIGHT
|
||||||
|
|| nodep->attrType()==AstAttrType::DIM_SIZE) {
|
||||||
|
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||||
|
pair<uint32_t,uint32_t> dim = nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
|
||||||
|
uint32_t maxdim = dim.first+dim.second;
|
||||||
|
if (!nodep->dimp() || nodep->dimp()->castConst() || maxdim<1) {
|
||||||
|
int dim = !nodep->dimp() ? 1 : nodep->dimp()->castConst()->toSInt();
|
||||||
|
int val = dimensionValue(nodep->fromp()->dtypep(), nodep->attrType(), dim);
|
||||||
|
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
|
else { // Need a runtime lookup table. Yuk.
|
||||||
|
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||||
|
AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType());
|
||||||
|
AstNode* dimp = nodep->dimp()->unlinkFrBack();
|
||||||
|
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
|
||||||
|
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||||
|
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp);
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
} else { // Everything else resolved earlier
|
} else { // Everything else resolved earlier
|
||||||
nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32
|
nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32
|
||||||
UINFO(1,"Missing ATTR type case node: "<<nodep<<endl);
|
UINFO(1,"Missing ATTR type case node: "<<nodep<<endl);
|
||||||
|
|
@ -862,7 +890,9 @@ private:
|
||||||
if (nodep->valuep()) {
|
if (nodep->valuep()) {
|
||||||
//if (debug()) nodep->dumpTree(cout," final: ");
|
//if (debug()) nodep->dumpTree(cout," final: ");
|
||||||
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep()->width(),0,BOTH).p());
|
if (!didchk) nodep->valuep()->iterateAndNext(*this,WidthVP(nodep->dtypep()->width(),0,BOTH).p());
|
||||||
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
if (!nodep->valuep()->castInitArray()) { // No dtype at present, perhaps TODO
|
||||||
|
widthCheck(nodep,"Initial value",nodep->valuep(),nodep->width(),nodep->widthMin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UINFO(4,"varWidthed "<<nodep<<endl);
|
UINFO(4,"varWidthed "<<nodep<<endl);
|
||||||
//if (debug()) nodep->dumpTree(cout," InitOut: ");
|
//if (debug()) nodep->dumpTree(cout," InitOut: ");
|
||||||
|
|
@ -963,6 +993,11 @@ private:
|
||||||
}
|
}
|
||||||
nodep->dtypeFrom(nodep->itemp());
|
nodep->dtypeFrom(nodep->itemp());
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstInitArray* nodep, AstNUser* vup) {
|
||||||
|
// Should be correct by construction, so we'll just loop through all types
|
||||||
|
nodep->iterateChildren(*this, vup);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeClassDType* nodep, AstNUser* vup) {
|
virtual void visit(AstNodeClassDType* nodep, AstNUser* vup) {
|
||||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||||
UINFO(5," NODECLASS "<<nodep<<endl);
|
UINFO(5," NODECLASS "<<nodep<<endl);
|
||||||
|
|
@ -2372,6 +2407,99 @@ private:
|
||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dimensionValue(AstNodeDType* nodep, AstAttrType attrType, int dim) {
|
||||||
|
// Return the dimension value for the specified attribute and constant dimension
|
||||||
|
AstNodeDType* dtypep = nodep->skipRefp();
|
||||||
|
VNumRange declRange; // ranged() set false
|
||||||
|
for (int i = 1; i <= dim; ++i) {
|
||||||
|
//UINFO(9, " dim at "<<dim<<" "<<dtypep<<endl);
|
||||||
|
declRange = VNumRange(); // ranged() set false
|
||||||
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
|
declRange = adtypep->declRange();
|
||||||
|
if (i<dim) dtypep = adtypep->subDTypep()->skipRefp();
|
||||||
|
continue;
|
||||||
|
} else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|
||||||
|
declRange = adtypep->declRange();
|
||||||
|
if (adtypep) {} // UNUSED
|
||||||
|
break; // Sub elements don't look like arrays and can't iterate into
|
||||||
|
} else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
|
if (adtypep->isRanged()) declRange = adtypep->declRange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int val = 0;
|
||||||
|
if (attrType==AstAttrType::DIM_BITS) {
|
||||||
|
int bits = 1;
|
||||||
|
while (dtypep) {
|
||||||
|
//UINFO(9, " bits at "<<bits<<" "<<dtypep<<endl);
|
||||||
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
|
bits *= adtypep->declRange().elements();
|
||||||
|
dtypep = adtypep->subDTypep()->skipRefp();
|
||||||
|
continue;
|
||||||
|
} else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|
||||||
|
bits *= adtypep->width();
|
||||||
|
break;
|
||||||
|
} else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
||||||
|
bits *= adtypep->width();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dim == 0) {
|
||||||
|
val = 0;
|
||||||
|
} else if (dim == 1 && !declRange.ranged() && bits==1) { // $bits should be sane for non-arrays
|
||||||
|
val = nodep->width();
|
||||||
|
} else {
|
||||||
|
val = bits;
|
||||||
|
}
|
||||||
|
} else if (attrType==AstAttrType::DIM_HIGH) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.hi();
|
||||||
|
} else if (attrType==AstAttrType::DIM_LEFT) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.left();
|
||||||
|
} else if (attrType==AstAttrType::DIM_LOW) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.lo();
|
||||||
|
} else if (attrType==AstAttrType::DIM_RIGHT) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.right();
|
||||||
|
} else if (attrType==AstAttrType::DIM_INCREMENT) {
|
||||||
|
val = (declRange.ranged() && declRange.littleEndian()) ? -1 : 1;
|
||||||
|
} else if (attrType==AstAttrType::DIM_SIZE) {
|
||||||
|
val = !declRange.ranged() ? 0 : declRange.elements();
|
||||||
|
} else {
|
||||||
|
nodep->v3fatalSrc("Missing DIM ATTR type case");
|
||||||
|
}
|
||||||
|
UINFO(9," $dimension "<<attrType.ascii()<<"("<<((void*)dtypep)<<","<<dim<<")="<<val<<endl);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
AstVar* dimensionVarp(AstNodeDType* nodep, AstAttrType attrType) {
|
||||||
|
// Return a variable table which has specified dimension properties for this variable
|
||||||
|
pair<uint32_t,uint32_t> dim = nodep->skipRefp()->dimensions(true);
|
||||||
|
uint32_t maxdim = dim.first+dim.second;
|
||||||
|
//
|
||||||
|
AstInitArray* initp = new AstInitArray (nodep->fileline(), NULL);
|
||||||
|
AstNodeDType* vardtypep = new AstUnpackArrayDType(nodep->fileline(),
|
||||||
|
nodep->findSigned32DType(),
|
||||||
|
new AstRange(nodep->fileline(), maxdim, 0));
|
||||||
|
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||||
|
AstVar* varp = new AstVar (nodep->fileline(), AstVarType::MODULETEMP,
|
||||||
|
"__Vdimtable" + cvtToStr(m_dtTables++),
|
||||||
|
vardtypep);
|
||||||
|
varp->isConst(true);
|
||||||
|
varp->isStatic(true);
|
||||||
|
varp->valuep(initp);
|
||||||
|
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||||
|
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
|
||||||
|
// Element 0 is a non-index and has speced values
|
||||||
|
initp->addInitsp(new AstConst(nodep->fileline(), AstConst::Signed32(),
|
||||||
|
dimensionValue(nodep, attrType, 0)));
|
||||||
|
for (unsigned i=1; i<maxdim+1; ++i) {
|
||||||
|
initp->addInitsp(new AstConst(nodep->fileline(), AstConst::Signed32(),
|
||||||
|
dimensionValue(nodep, attrType, i)));
|
||||||
|
}
|
||||||
|
varp->iterate(*this); // May have already done $unit so must do this var
|
||||||
|
return varp;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// METHODS - special type detection
|
// METHODS - special type detection
|
||||||
bool backRequiresUnsigned(AstNode* nodep) {
|
bool backRequiresUnsigned(AstNode* nodep) {
|
||||||
|
|
@ -2402,6 +2530,7 @@ public:
|
||||||
m_attrp = NULL;
|
m_attrp = NULL;
|
||||||
m_assDTypep = NULL;
|
m_assDTypep = NULL;
|
||||||
m_doGenerate = doGenerate;
|
m_doGenerate = doGenerate;
|
||||||
|
m_dtTables = 0;
|
||||||
}
|
}
|
||||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||||
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());
|
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());
|
||||||
|
|
|
||||||
|
|
@ -386,12 +386,20 @@ word [a-zA-Z0-9_]+
|
||||||
"$bits" { FL; return yD_BITS; }
|
"$bits" { FL; return yD_BITS; }
|
||||||
"$clog2" { FL; return yD_CLOG2; }
|
"$clog2" { FL; return yD_CLOG2; }
|
||||||
"$countones" { FL; return yD_COUNTONES; }
|
"$countones" { FL; return yD_COUNTONES; }
|
||||||
|
"$dimensions" { FL; return yD_DIMENSIONS; }
|
||||||
"$error" { FL; return yD_ERROR; }
|
"$error" { FL; return yD_ERROR; }
|
||||||
"$fatal" { FL; return yD_FATAL; }
|
"$fatal" { FL; return yD_FATAL; }
|
||||||
|
"$high" { FL; return yD_HIGH; }
|
||||||
|
"$increment" { FL; return yD_INCREMENT; }
|
||||||
"$info" { FL; return yD_INFO; }
|
"$info" { FL; return yD_INFO; }
|
||||||
"$isunknown" { FL; return yD_ISUNKNOWN; }
|
"$isunknown" { FL; return yD_ISUNKNOWN; }
|
||||||
|
"$left" { FL; return yD_LEFT; }
|
||||||
|
"$low" { FL; return yD_LOW; }
|
||||||
"$onehot" { FL; return yD_ONEHOT; }
|
"$onehot" { FL; return yD_ONEHOT; }
|
||||||
"$onehot0" { FL; return yD_ONEHOT0; }
|
"$onehot0" { FL; return yD_ONEHOT0; }
|
||||||
|
"$right" { FL; return yD_RIGHT; }
|
||||||
|
"$size" { FL; return yD_SIZE; }
|
||||||
|
"$unpacked_dimensions" { FL; return yD_UNPACKED_DIMENSIONS; }
|
||||||
"$warning" { FL; return yD_WARNING; }
|
"$warning" { FL; return yD_WARNING; }
|
||||||
/* SV2005 Keywords */
|
/* SV2005 Keywords */
|
||||||
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */
|
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,7 @@ class AstSenTree;
|
||||||
%token<fl> yD_CEIL "$ceil"
|
%token<fl> yD_CEIL "$ceil"
|
||||||
%token<fl> yD_CLOG2 "$clog2"
|
%token<fl> yD_CLOG2 "$clog2"
|
||||||
%token<fl> yD_COUNTONES "$countones"
|
%token<fl> yD_COUNTONES "$countones"
|
||||||
|
%token<fl> yD_DIMENSIONS "$dimensions"
|
||||||
%token<fl> yD_DISPLAY "$display"
|
%token<fl> yD_DISPLAY "$display"
|
||||||
%token<fl> yD_ERROR "$error"
|
%token<fl> yD_ERROR "$error"
|
||||||
%token<fl> yD_EXP "$exp"
|
%token<fl> yD_EXP "$exp"
|
||||||
|
|
@ -429,11 +430,15 @@ class AstSenTree;
|
||||||
%token<fl> yD_FOPEN "$fopen"
|
%token<fl> yD_FOPEN "$fopen"
|
||||||
%token<fl> yD_FSCANF "$fscanf"
|
%token<fl> yD_FSCANF "$fscanf"
|
||||||
%token<fl> yD_FWRITE "$fwrite"
|
%token<fl> yD_FWRITE "$fwrite"
|
||||||
|
%token<fl> yD_HIGH "$high"
|
||||||
|
%token<fl> yD_INCREMENT "$increment"
|
||||||
%token<fl> yD_INFO "$info"
|
%token<fl> yD_INFO "$info"
|
||||||
%token<fl> yD_ISUNKNOWN "$isunknown"
|
%token<fl> yD_ISUNKNOWN "$isunknown"
|
||||||
%token<fl> yD_ITOR "$itor"
|
%token<fl> yD_ITOR "$itor"
|
||||||
|
%token<fl> yD_LEFT "$left"
|
||||||
%token<fl> yD_LN "$ln"
|
%token<fl> yD_LN "$ln"
|
||||||
%token<fl> yD_LOG10 "$log10"
|
%token<fl> yD_LOG10 "$log10"
|
||||||
|
%token<fl> yD_LOW "$low"
|
||||||
%token<fl> yD_ONEHOT "$onehot"
|
%token<fl> yD_ONEHOT "$onehot"
|
||||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||||
%token<fl> yD_POW "$pow"
|
%token<fl> yD_POW "$pow"
|
||||||
|
|
@ -442,9 +447,11 @@ class AstSenTree;
|
||||||
%token<fl> yD_READMEMH "$readmemh"
|
%token<fl> yD_READMEMH "$readmemh"
|
||||||
%token<fl> yD_REALTIME "$realtime"
|
%token<fl> yD_REALTIME "$realtime"
|
||||||
%token<fl> yD_REALTOBITS "$realtobits"
|
%token<fl> yD_REALTOBITS "$realtobits"
|
||||||
|
%token<fl> yD_RIGHT "$right"
|
||||||
%token<fl> yD_RTOI "$rtoi"
|
%token<fl> yD_RTOI "$rtoi"
|
||||||
%token<fl> yD_SFORMAT "$sformat"
|
%token<fl> yD_SFORMAT "$sformat"
|
||||||
%token<fl> yD_SIGNED "$signed"
|
%token<fl> yD_SIGNED "$signed"
|
||||||
|
%token<fl> yD_SIZE "$size"
|
||||||
%token<fl> yD_SQRT "$sqrt"
|
%token<fl> yD_SQRT "$sqrt"
|
||||||
%token<fl> yD_SSCANF "$sscanf"
|
%token<fl> yD_SSCANF "$sscanf"
|
||||||
%token<fl> yD_STIME "$stime"
|
%token<fl> yD_STIME "$stime"
|
||||||
|
|
@ -454,6 +461,7 @@ class AstSenTree;
|
||||||
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
|
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
|
||||||
%token<fl> yD_TIME "$time"
|
%token<fl> yD_TIME "$time"
|
||||||
%token<fl> yD_UNIT "$unit"
|
%token<fl> yD_UNIT "$unit"
|
||||||
|
%token<fl> yD_UNPACKED_DIMENSIONS "$unpacked_dimensions"
|
||||||
%token<fl> yD_UNSIGNED "$unsigned"
|
%token<fl> yD_UNSIGNED "$unsigned"
|
||||||
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
||||||
%token<fl> yD_WARNING "$warning"
|
%token<fl> yD_WARNING "$warning"
|
||||||
|
|
@ -2409,39 +2417,55 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||||
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
|
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
|
||||||
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
||||||
//
|
//
|
||||||
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
|
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
|
||||||
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
|
| yD_BITS '(' data_type ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
|
||||||
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
|
||||||
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
|
| yD_BITS '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
|
||||||
| yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); }
|
|
||||||
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
|
||||||
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
|
||||||
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
|
|
||||||
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
|
|
||||||
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
|
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
|
||||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
||||||
|
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
|
||||||
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
|
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
|
||||||
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
|
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
|
||||||
|
| yD_DIMENSIONS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_DIMENSIONS,$3); }
|
||||||
|
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
|
||||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
||||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
||||||
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||||
|
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
||||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
| yD_HIGH '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
|
||||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
| yD_HIGH '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); }
|
||||||
|
| yD_INCREMENT '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,NULL); }
|
||||||
|
| yD_INCREMENT '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,$5); }
|
||||||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
||||||
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
|
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
|
||||||
|
| yD_LEFT '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,NULL); }
|
||||||
|
| yD_LEFT '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,$5); }
|
||||||
|
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
|
||||||
|
| yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); }
|
||||||
|
| yD_LOW '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,NULL); }
|
||||||
|
| yD_LOW '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,$5); }
|
||||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
||||||
|
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
||||||
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
|
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
|
||||||
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
||||||
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
||||||
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
||||||
|
| yD_RIGHT '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); }
|
||||||
|
| yD_RIGHT '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); }
|
||||||
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
|
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
|
||||||
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
|
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
|
||||||
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
||||||
|
| yD_SIZE '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,NULL); }
|
||||||
|
| yD_SIZE '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,$5); }
|
||||||
|
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
||||||
|
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||||
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||||
| yD_TIME parenE { $$ = new AstTime($1); }
|
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
||||||
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
|
||||||
|
| yD_TIME parenE { $$ = new AstTime($1); }
|
||||||
|
| yD_UNPACKED_DIMENSIONS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
|
||||||
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
||||||
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
| yD_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug448");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ module t (/*AUTOARG*/
|
||||||
`check($increment (array_bg[2], dim-1), 1 );
|
`check($increment (array_bg[2], dim-1), 1 );
|
||||||
`check($size (array_bg[2], dim-1), wdt );
|
`check($size (array_bg[2], dim-1), wdt );
|
||||||
end
|
end
|
||||||
|
`ifndef VERILATOR // Unsupported slices don't maintain size correctly
|
||||||
end else if (slc==2) begin
|
end else if (slc==2) begin
|
||||||
// half array
|
// half array
|
||||||
`check($dimensions (array_bg[WA/2+1:2]), 3);
|
`check($dimensions (array_bg[WA/2+1:2]), 3);
|
||||||
|
|
@ -119,6 +120,7 @@ module t (/*AUTOARG*/
|
||||||
`check($increment (array_bg[WA/2+1:2], dim), 1 );
|
`check($increment (array_bg[WA/2+1:2], dim), 1 );
|
||||||
`check($size (array_bg[WA/2+1:2], dim), wdt);
|
`check($size (array_bg[WA/2+1:2], dim), wdt);
|
||||||
end
|
end
|
||||||
|
`endif
|
||||||
end
|
end
|
||||||
end else if (cnt[30:4]==2) begin
|
end else if (cnt[30:4]==2) begin
|
||||||
// little endian
|
// little endian
|
||||||
|
|
@ -146,6 +148,7 @@ module t (/*AUTOARG*/
|
||||||
`check($increment (array_lt[2], dim-1), -1 );
|
`check($increment (array_lt[2], dim-1), -1 );
|
||||||
`check($size (array_lt[2], dim-1), wdt );
|
`check($size (array_lt[2], dim-1), wdt );
|
||||||
end
|
end
|
||||||
|
`ifndef VERILATOR // Unsupported slices don't maintain size correctly
|
||||||
end else if (slc==2) begin
|
end else if (slc==2) begin
|
||||||
// half array
|
// half array
|
||||||
`check($dimensions (array_lt[2:WA/2+1]), 3);
|
`check($dimensions (array_lt[2:WA/2+1]), 3);
|
||||||
|
|
@ -158,6 +161,7 @@ module t (/*AUTOARG*/
|
||||||
`check($increment (array_lt[2:WA/2+1], dim), -1 );
|
`check($increment (array_lt[2:WA/2+1], dim), -1 );
|
||||||
`check($size (array_lt[2:WA/2+1], dim), wdt );
|
`check($size (array_lt[2:WA/2+1], dim), wdt );
|
||||||
end
|
end
|
||||||
|
`endif
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug448");
|
|
||||||
|
|
||||||
compile (
|
compile (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,30 @@ module t (/*AUTOARG*/);
|
||||||
c_t [17:16] d;
|
c_t [17:16] d;
|
||||||
} e_t;
|
} e_t;
|
||||||
|
|
||||||
`define check(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: Line%0d: got=0b%b exp=0b%b\n", `__LINE__, (gotv), (expv)); $stop; end while(0);
|
`define check(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: Line%0d: got=0x%x exp=0x%x\n", `__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
`define checkb(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: Line%0d: got=0b%b exp=0b%b\n", `__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
e_t e;
|
e_t e;
|
||||||
if ($bits(ab_t)!=6) $stop;
|
`check($bits(ab_t),6);
|
||||||
if ($bits(c_t)!=12) $stop;
|
`check($bits(c_t),12);
|
||||||
if ($bits(e_t)!=24) $stop;
|
`check($bits(e_t),24);
|
||||||
e = 24'b101101010111010110101010;
|
`check($bits(e), 24);
|
||||||
`check(e, 24'b101101010111010110101010);
|
`check($bits(e.d[17]),12);
|
||||||
e.d[17] = 12'b111110011011;
|
`check($bits(e.d[16][6]),6);
|
||||||
`check(e, 24'b111110011011010110101010);
|
`check($bits(e.d[16][6].b[5]),2);
|
||||||
e.d[16][6] = 6'b010101;
|
`check($bits(e.d[16][6].b[5][2]), 1);
|
||||||
`check(e, 24'b111110011011010110010101);
|
//
|
||||||
e.d[16][6].b[5] = 2'b10;
|
e = 24'b101101010111010110101010;
|
||||||
`check(e, 24'b111110011011010110011001);
|
`checkb(e, 24'b101101010111010110101010);
|
||||||
e.d[16][6].b[5][2] = 1'b1;
|
e.d[17] = 12'b111110011011;
|
||||||
|
`checkb(e, 24'b111110011011010110101010);
|
||||||
|
e.d[16][6] = 6'b010101;
|
||||||
|
`checkb(e, 24'b111110011011010110010101);
|
||||||
|
e.d[16][6].b[5] = 2'b10;
|
||||||
|
`checkb(e, 24'b111110011011010110011001);
|
||||||
|
e.d[16][6].b[5][2] = 1'b1;
|
||||||
|
//
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -49,14 +49,14 @@ module t (/*AUTOARG*/
|
||||||
if ($bits (struct_bg.e1) != 2) $stop;
|
if ($bits (struct_bg.e1) != 2) $stop;
|
||||||
if ($bits (struct_bg.e2) != 4) $stop;
|
if ($bits (struct_bg.e2) != 4) $stop;
|
||||||
if ($bits (struct_bg.e3) != 8) $stop;
|
if ($bits (struct_bg.e3) != 8) $stop;
|
||||||
// if ($increment (struct_bg, 1) != 1) $stop;
|
if ($increment (struct_bg, 1) != 1) $stop;
|
||||||
// little endian
|
// little endian
|
||||||
if ($bits (struct_lt ) != 15) $stop;
|
if ($bits (struct_lt ) != 15) $stop;
|
||||||
if ($bits (struct_lt.e0) != 1) $stop;
|
if ($bits (struct_lt.e0) != 1) $stop;
|
||||||
if ($bits (struct_lt.e1) != 2) $stop;
|
if ($bits (struct_lt.e1) != 2) $stop;
|
||||||
if ($bits (struct_lt.e2) != 4) $stop;
|
if ($bits (struct_lt.e2) != 4) $stop;
|
||||||
if ($bits (struct_lt.e3) != 8) $stop;
|
if ($bits (struct_lt.e3) != 8) $stop;
|
||||||
// if ($increment (struct_lt, 1) != -1) $stop;
|
if ($increment (struct_lt, 1) != 1) $stop; // Structure itself always big numbered
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue