forked from github/verilator
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 $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]
|
||||
|
18
src/V3Ast.h
18
src/V3Ast.h
@ -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; }
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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*) {
|
||||
|
@ -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");
|
||||
|
141
src/V3Width.cpp
141
src/V3Width.cpp
@ -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());
|
||||
|
@ -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 */
|
||||
|
@ -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); }
|
||||
;
|
||||
|
@ -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 (
|
||||
);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 (
|
||||
);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user