Support , and related functions, bug448.

This commit is contained in:
Wilson Snyder 2013-01-20 12:19:22 -05:00
parent 00bd947385
commit 929aeebf12
14 changed files with 246 additions and 51 deletions

View File

@ -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 $left, $right and related functions, bug448. [Iztok Jeras]
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]

View File

@ -219,7 +219,16 @@ class AstAttrType {
public:
enum en {
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
//
@ -237,7 +246,10 @@ public:
enum en m_e;
const char* ascii() const {
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_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
@ -1520,7 +1532,7 @@ public:
bool generic() const { return m_generic; }
void generic(bool flag) { m_generic = flag; }
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
static int uniqueNumInc() { return ++s_uniqueNum; }
};

View File

@ -358,21 +358,22 @@ uint32_t AstNodeDType::arrayUnpackedElements() {
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?
uint32_t packed = 0;
uint32_t unpacked = 0;
for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
if (adtypep->castPackArrayDType()) packed += 1;
else unpacked += 1;
if (adtypep->castPackArrayDType()) packed++;
else unpacked++;
dtypep = adtypep->subDTypep();
continue;
}
else {
// AstBasicDType - nothing below, 1
break;
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
if (includeBasic && adtypep->isRanged()) packed++;
}
break;
}
return make_pair(packed, unpacked);
}

View File

@ -65,6 +65,11 @@ public:
:AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); dtypeSetLogicSized(32,m_num.widthMin(),
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
AstConst(FileLine* fl, RealDouble, double num)
:AstNodeMath(fl)
@ -2736,12 +2741,14 @@ private:
// Return a value of a attribute, for example a LSB or array LSB of a signal
AstAttrType m_attrType; // What sort of extraction
public:
AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp=NULL)
AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp=NULL, AstNode* dimp=NULL)
: AstNode(fl) {
setNOp1p(fromp);
setNOp2p(dimp);
m_attrType = attrtype; }
ASTNODE_NODE_FUNCS(AttrOf, ATTROF)
AstNode* fromp() const { return op1p(); }
AstNode* dimp() const { return op2p(); }
AstAttrType attrType() const { return m_attrType; }
virtual void dump(ostream& str=cout);
};

View File

@ -440,6 +440,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
virtual void visit(AstAttrOf* nodep, AstNUser*) {
putfs(nodep,"$_ATTROF(");
nodep->fromp()->iterateAndNext(*this);
if (nodep->dimp()) {
putbs(",");
nodep->dimp()->iterateAndNext(*this);
}
puts(")");
}
virtual void visit(AstNodeCond* nodep, AstNUser*) {

View File

@ -76,7 +76,7 @@ class SliceCloneVisitor : public AstNVisitor {
if (m_vecIdx == (int)m_selBits.size()) {
m_selBits.push_back(vector<unsigned>());
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;
for (uint32_t i = 0; i < dimensions; ++i) {
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
// case we need to create a slice accross the entire Var
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
if (dimensions > 0) {
AstVarRef* clonep = nodep->cloneTree(false);
@ -326,7 +326,7 @@ class SliceVisitor : public AstNVisitor {
if (nodep->user3()) return; // Prevent recursion on just created nodes
unsigned dim = explicitDimensions(nodep);
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;
if (implicit > 0) {
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
@ -428,7 +428,7 @@ class SliceVisitor : public AstNVisitor {
nodep->iterateChildren(*this);
} else {
AstVarRef* refp = findVarRefRecurse(nodep->lhsp());
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions();
ArrayDimensions varDim = refp->varp()->dtypep()->dimensions(false);
if ((int)(dim - varDim.second) < 0) {
// Unpacked dimensions are referenced first, make sure we have them all
nodep->v3error("Unary operator used across unpacked dimensions");

View File

@ -121,6 +121,7 @@ private:
AstAttrOf* m_attrp; // Current attribute
AstNodeDType* m_assDTypep; // Assign LHS data type for assignment pattern
bool m_doGenerate; // Do errors later inside generate statement
int m_dtTables; // Number of created data type tables
// CLASSES
#define ANYSIZE 0
@ -655,14 +656,41 @@ private:
m_attrp = nodep;
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
// Don't iterate children, don't want to lose VarRef.
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
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) {
if (nodep->attrType()==AstAttrType::VAR_BASE) {
// Soon to be handled in V3LinkWidth SEL generation, under attrp() and newSubLsbOf
} else if (nodep->attrType()==AstAttrType::MEMBER_BASE) {
// 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
nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32
UINFO(1,"Missing ATTR type case node: "<<nodep<<endl);
@ -862,7 +890,9 @@ private:
if (nodep->valuep()) {
//if (debug()) nodep->dumpTree(cout," final: ");
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);
//if (debug()) nodep->dumpTree(cout," InitOut: ");
@ -963,6 +993,11 @@ private:
}
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) {
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
UINFO(5," NODECLASS "<<nodep<<endl);
@ -2372,6 +2407,99 @@ private:
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
bool backRequiresUnsigned(AstNode* nodep) {
@ -2402,6 +2530,7 @@ public:
m_attrp = NULL;
m_assDTypep = NULL;
m_doGenerate = doGenerate;
m_dtTables = 0;
}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this, WidthVP(ANYSIZE,0,BOTH).p());

View File

@ -386,12 +386,20 @@ word [a-zA-Z0-9_]+
"$bits" { FL; return yD_BITS; }
"$clog2" { FL; return yD_CLOG2; }
"$countones" { FL; return yD_COUNTONES; }
"$dimensions" { FL; return yD_DIMENSIONS; }
"$error" { FL; return yD_ERROR; }
"$fatal" { FL; return yD_FATAL; }
"$high" { FL; return yD_HIGH; }
"$increment" { FL; return yD_INCREMENT; }
"$info" { FL; return yD_INFO; }
"$isunknown" { FL; return yD_ISUNKNOWN; }
"$left" { FL; return yD_LEFT; }
"$low" { FL; return yD_LOW; }
"$onehot" { FL; return yD_ONEHOT; }
"$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; }
/* SV2005 Keywords */
"$unit" { FL; return yD_UNIT; } /* Yes, a keyword, not task */

View File

@ -414,6 +414,7 @@ class AstSenTree;
%token<fl> yD_CEIL "$ceil"
%token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COUNTONES "$countones"
%token<fl> yD_DIMENSIONS "$dimensions"
%token<fl> yD_DISPLAY "$display"
%token<fl> yD_ERROR "$error"
%token<fl> yD_EXP "$exp"
@ -429,11 +430,15 @@ class AstSenTree;
%token<fl> yD_FOPEN "$fopen"
%token<fl> yD_FSCANF "$fscanf"
%token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_HIGH "$high"
%token<fl> yD_INCREMENT "$increment"
%token<fl> yD_INFO "$info"
%token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_LEFT "$left"
%token<fl> yD_LN "$ln"
%token<fl> yD_LOG10 "$log10"
%token<fl> yD_LOW "$low"
%token<fl> yD_ONEHOT "$onehot"
%token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_POW "$pow"
@ -442,9 +447,11 @@ class AstSenTree;
%token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_RIGHT "$right"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SIGNED "$signed"
%token<fl> yD_SIZE "$size"
%token<fl> yD_SQRT "$sqrt"
%token<fl> yD_SSCANF "$sscanf"
%token<fl> yD_STIME "$stime"
@ -454,6 +461,7 @@ class AstSenTree;
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_UNIT "$unit"
%token<fl> yD_UNPACKED_DIMENSIONS "$unpacked_dimensions"
%token<fl> yD_UNSIGNED "$unsigned"
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
%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 '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
//
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
| 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_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
| yD_BITS '(' data_type ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
| yD_BITS '(' expr ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($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_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_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
| 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_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
| yD_HIGH '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
| 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_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_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 parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| 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_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
| 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_TIME parenE { $$ = new AstTime($1); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($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_VALUEPLUSARGS '(' str ',' expr ')' { $$ = new AstValuePlusArgs($1,*$3,$5); }
;

View File

@ -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
# Version 2.0.
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug448");
compile (
);

View File

@ -107,6 +107,7 @@ module t (/*AUTOARG*/
`check($increment (array_bg[2], dim-1), 1 );
`check($size (array_bg[2], dim-1), wdt );
end
`ifndef VERILATOR // Unsupported slices don't maintain size correctly
end else if (slc==2) begin
// half array
`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($size (array_bg[WA/2+1:2], dim), wdt);
end
`endif
end
end else if (cnt[30:4]==2) begin
// little endian
@ -146,6 +148,7 @@ module t (/*AUTOARG*/
`check($increment (array_lt[2], dim-1), -1 );
`check($size (array_lt[2], dim-1), wdt );
end
`ifndef VERILATOR // Unsupported slices don't maintain size correctly
end else if (slc==2) begin
// half array
`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($size (array_lt[2:WA/2+1], dim), wdt );
end
`endif
end
end
end

View File

@ -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
# Version 2.0.
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug448");
compile (
);

View File

@ -14,22 +14,30 @@ module t (/*AUTOARG*/);
c_t [17:16] d;
} 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
e_t e;
if ($bits(ab_t)!=6) $stop;
if ($bits(c_t)!=12) $stop;
if ($bits(e_t)!=24) $stop;
e = 24'b101101010111010110101010;
`check(e, 24'b101101010111010110101010);
e.d[17] = 12'b111110011011;
`check(e, 24'b111110011011010110101010);
e.d[16][6] = 6'b010101;
`check(e, 24'b111110011011010110010101);
e.d[16][6].b[5] = 2'b10;
`check(e, 24'b111110011011010110011001);
e.d[16][6].b[5][2] = 1'b1;
`check($bits(ab_t),6);
`check($bits(c_t),12);
`check($bits(e_t),24);
`check($bits(e), 24);
`check($bits(e.d[17]),12);
`check($bits(e.d[16][6]),6);
`check($bits(e.d[16][6].b[5]),2);
`check($bits(e.d[16][6].b[5][2]), 1);
//
e = 24'b101101010111010110101010;
`checkb(e, 24'b101101010111010110101010);
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");
$finish;
end

View File

@ -49,14 +49,14 @@ module t (/*AUTOARG*/
if ($bits (struct_bg.e1) != 2) $stop;
if ($bits (struct_bg.e2) != 4) $stop;
if ($bits (struct_bg.e3) != 8) $stop;
// if ($increment (struct_bg, 1) != 1) $stop;
if ($increment (struct_bg, 1) != 1) $stop;
// little endian
if ($bits (struct_lt ) != 15) $stop;
if ($bits (struct_lt.e0) != 1) $stop;
if ($bits (struct_lt.e1) != 2) $stop;
if ($bits (struct_lt.e2) != 4) $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
endmodule