Fix queue issues, bug1643.
Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
parent
0465b6a3b1
commit
9a54b2144b
2
Changes
2
Changes
|
|
@ -22,7 +22,7 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
**** Fix little endian cell ranges, bug1631. [Julien Margetts]
|
**** Fix little endian cell ranges, bug1631. [Julien Margetts]
|
||||||
|
|
||||||
**** Fix queues as statements, bug1641. [Peter Monsson, Stefan Wallentowitz]
|
**** Fix queue issues, bug1641, bug1643. [Peter Monsson, Stefan Wallentowitz]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 4.024 2019-12-08
|
* Verilator 4.024 2019-12-08
|
||||||
|
|
|
||||||
|
|
@ -622,8 +622,16 @@ std::pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (const AstQueueDType* qdtypep = VN_CAST(dtypep, QueueDType)) {
|
||||||
|
unpacked++;
|
||||||
|
dtypep = qdtypep->subDTypep();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) {
|
else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) {
|
||||||
if (includeBasic && adtypep->isRanged()) packed++;
|
if (includeBasic && (adtypep->isRanged() || adtypep->isString())) packed++;
|
||||||
|
}
|
||||||
|
else if (const AstStructDType* sdtypep = VN_CAST(dtypep, StructDType)) {
|
||||||
|
packed++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -392,17 +392,22 @@ private:
|
||||||
FileLine* fl = varsp->fileline();
|
FileLine* fl = varsp->fileline();
|
||||||
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
|
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
|
||||||
varsp->name(), nodep->findSigned32DType());
|
varsp->name(), nodep->findSigned32DType());
|
||||||
// These will be the left and right dimensions of the array:
|
// These will be the left and right dimensions and size of the array:
|
||||||
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
|
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
|
||||||
new AstVarRef(fl, arrayp->name(), false),
|
new AstVarRef(fl, arrayp->name(), false),
|
||||||
new AstConst(fl, dimension));
|
new AstConst(fl, dimension));
|
||||||
AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT,
|
AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT,
|
||||||
new AstVarRef(fl, arrayp->name(), false),
|
new AstVarRef(fl, arrayp->name(), false),
|
||||||
new AstConst(fl, dimension));
|
new AstConst(fl, dimension));
|
||||||
|
AstNode* sizep = new AstAttrOf(fl, AstAttrType::DIM_SIZE,
|
||||||
|
new AstVarRef(fl, arrayp->name(), false),
|
||||||
|
new AstConst(fl, dimension));
|
||||||
AstNode* stmtsp = varp;
|
AstNode* stmtsp = varp;
|
||||||
// Assign left-dimension into the loop var:
|
// Assign left-dimension into the loop var:
|
||||||
stmtsp->addNext(new AstAssign
|
stmtsp->addNext(new AstAssign
|
||||||
(fl, new AstVarRef(fl, varp->name(), true), leftp));
|
(fl, new AstVarRef(fl, varp->name(), true), leftp));
|
||||||
|
// This will turn into a constant bool for static arrays
|
||||||
|
AstNode* notemptyp = new AstGt(fl, sizep, new AstConst(fl, 0));
|
||||||
// This will turn into a bool constant, indicating whether
|
// This will turn into a bool constant, indicating whether
|
||||||
// we count the loop variable up or down:
|
// we count the loop variable up or down:
|
||||||
AstNode* countupp = new AstLte(fl, leftp->cloneTree(true),
|
AstNode* countupp = new AstLte(fl, leftp->cloneTree(true),
|
||||||
|
|
@ -414,13 +419,15 @@ private:
|
||||||
rightp->cloneTree(true)),
|
rightp->cloneTree(true)),
|
||||||
// Left decrements down to right
|
// Left decrements down to right
|
||||||
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
|
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
|
||||||
|
// This will reduce to comparep for static arrays
|
||||||
|
AstNode* condp = new AstAnd(fl, notemptyp, comparep);
|
||||||
AstNode* incp = new AstAssign(
|
AstNode* incp = new AstAssign(
|
||||||
fl, new AstVarRef(fl, varp->name(), true),
|
fl, new AstVarRef(fl, varp->name(), true),
|
||||||
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
|
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
|
||||||
new AstCond(fl, countupp,
|
new AstCond(fl, countupp,
|
||||||
new AstConst(fl, 1),
|
new AstConst(fl, 1),
|
||||||
new AstConst(fl, -1))));
|
new AstConst(fl, -1))));
|
||||||
stmtsp->addNext(new AstWhile(fl, comparep, newp, incp));
|
stmtsp->addNext(new AstWhile(fl, condp, newp, incp));
|
||||||
newp = new AstBegin(nodep->fileline(), "", stmtsp);
|
newp = new AstBegin(nodep->fileline(), "", stmtsp);
|
||||||
dimension--;
|
dimension--;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1076,32 +1076,75 @@ private:
|
||||||
case AstAttrType::DIM_LOW:
|
case AstAttrType::DIM_LOW:
|
||||||
case AstAttrType::DIM_RIGHT:
|
case AstAttrType::DIM_RIGHT:
|
||||||
case AstAttrType::DIM_SIZE: {
|
case AstAttrType::DIM_SIZE: {
|
||||||
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep,
|
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "Unsized expression");
|
||||||
"Unsized expression");
|
if (VN_IS(nodep->fromp()->dtypep(), QueueDType)) {
|
||||||
|
switch (nodep->attrType()) {
|
||||||
|
case AstAttrType::DIM_SIZE: {
|
||||||
|
AstNode* newp = new AstCMethodCall(
|
||||||
|
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", NULL);
|
||||||
|
newp->dtypeSetSigned32();
|
||||||
|
newp->didWidth(true);
|
||||||
|
newp->protect(false);
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AstAttrType::DIM_LEFT:
|
||||||
|
case AstAttrType::DIM_LOW: {
|
||||||
|
AstNode* newp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0);
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AstAttrType::DIM_RIGHT:
|
||||||
|
case AstAttrType::DIM_HIGH: {
|
||||||
|
AstNode* sizep = new AstCMethodCall(
|
||||||
|
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", NULL);
|
||||||
|
sizep->dtypeSetSigned32();
|
||||||
|
sizep->didWidth(true);
|
||||||
|
sizep->protect(false);
|
||||||
|
AstNode* newp
|
||||||
|
= new AstSub(nodep->fileline(), sizep,
|
||||||
|
new AstConst(nodep->fileline(), AstConst::Signed32(), 1));
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AstAttrType::DIM_INCREMENT: {
|
||||||
|
AstNode* newp = new AstConst(nodep->fileline(), AstConst::Signed32(), -1);
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AstAttrType::DIM_BITS: {
|
||||||
|
nodep->v3error("Unsupported: $bits for queue");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: nodep->v3error("Unhandled attribute type");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
std::pair<uint32_t, uint32_t> dim
|
std::pair<uint32_t, uint32_t> dim
|
||||||
= nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
|
= nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
|
||||||
uint32_t msbdim = dim.first + dim.second;
|
uint32_t msbdim = dim.first + dim.second;
|
||||||
if (!nodep->dimp() || msbdim < 1) {
|
if (!nodep->dimp() || msbdim < 1) {
|
||||||
int dim = 1;
|
int dim = 1;
|
||||||
AstConst* newp = dimensionValue(nodep->fileline(),
|
AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(),
|
||||||
nodep->fromp()->dtypep(), nodep->attrType(), dim);
|
nodep->attrType(), dim);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
} else if (VN_IS(nodep->dimp(), Const)) {
|
} else if (VN_IS(nodep->dimp(), Const)) {
|
||||||
int dim = VN_CAST(nodep->dimp(), Const)->toSInt();
|
int dim = VN_CAST(nodep->dimp(), Const)->toSInt();
|
||||||
AstConst* newp = dimensionValue(nodep->fileline(),
|
AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(),
|
||||||
nodep->fromp()->dtypep(), nodep->attrType(), dim);
|
nodep->attrType(), dim);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else { // Need a runtime lookup table. Yuk.
|
else { // Need a runtime lookup table. Yuk.
|
||||||
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep,
|
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep,
|
||||||
"Unsized expression");
|
"Unsized expression");
|
||||||
AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim);
|
AstVar* varp
|
||||||
|
= dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim);
|
||||||
AstNode* dimp = nodep->dimp()->unlinkFrBack();
|
AstNode* dimp = nodep->dimp()->unlinkFrBack();
|
||||||
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
|
AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false);
|
||||||
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
|
varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||||
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp);
|
AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,71 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
cyc <= cyc + 1;
|
cyc <= cyc + 1;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Very simple test using bit
|
||||||
|
bit q[$];
|
||||||
|
bit x;
|
||||||
|
|
||||||
|
`checkh($left(q), 0);
|
||||||
|
`checkh($right(q), -1);
|
||||||
|
`checkh($increment(q), -1);
|
||||||
|
`checkh($low(q), 0);
|
||||||
|
`checkh($high(q), -1);
|
||||||
|
`checkh($size(q), 0);
|
||||||
|
`checkh($dimensions(q), 1);
|
||||||
|
// Unsup: `checkh($bits(q), 0);
|
||||||
|
|
||||||
|
q.push_back(1'b1);
|
||||||
|
`checkh($left(q), 0);
|
||||||
|
`checkh($right(q), 0);
|
||||||
|
`checkh($increment(q), -1);
|
||||||
|
`checkh($low(q), 0);
|
||||||
|
`checkh($high(q), 0);
|
||||||
|
`checkh($size(q), 1);
|
||||||
|
`checkh($dimensions(q), 1);
|
||||||
|
// Unsup: `checkh($bits(q), 2);
|
||||||
|
`checkh(q.size(), 1);
|
||||||
|
|
||||||
|
q.push_back(1'b1);
|
||||||
|
q.push_back(1'b0);
|
||||||
|
q.push_back(1'b1);
|
||||||
|
`checkh($left(q), 0);
|
||||||
|
`checkh($right(q), 3);
|
||||||
|
`checkh($low(q), 0);
|
||||||
|
`checkh($high(q), 3);
|
||||||
|
`checkh($size(q), 4);
|
||||||
|
// Unsup: `checkh($bits(q), 4);
|
||||||
|
`checkh(q.size(), 4);
|
||||||
|
|
||||||
|
x = q.pop_back(); `checkh(x, 1'b1);
|
||||||
|
`checkh($left(q), 0);
|
||||||
|
`checkh($right(q), 2);
|
||||||
|
`checkh($low(q), 0);
|
||||||
|
`checkh($high(q), 2);
|
||||||
|
`checkh($size(q), 3);
|
||||||
|
// sure those are working now..
|
||||||
|
|
||||||
|
x = q.pop_front(); `checkh(x, 1'b1);
|
||||||
|
x = q.pop_front(); `checkh(x, 1'b1);
|
||||||
|
x = q.pop_front(); `checkh(x, 1'b0);
|
||||||
|
`checkh(q.size(), 0);
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
// Simple test using integer
|
// Simple test using integer
|
||||||
typedef bit [3:0] nibble_t;
|
typedef bit [3:0] nibble_t;
|
||||||
nibble_t q[$];
|
nibble_t q[$];
|
||||||
nibble_t v;
|
nibble_t v;
|
||||||
|
|
||||||
|
`checkh($left(q), 0);
|
||||||
|
`checkh($right(q), -1);
|
||||||
|
`checkh($increment(q), -1);
|
||||||
|
`checkh($low(q), 0);
|
||||||
|
`checkh($high(q), -1);
|
||||||
|
`checkh($size(q), 0);
|
||||||
|
`checkh($dimensions(q), 2);
|
||||||
|
|
||||||
i = q.size(); `checkh(i, 0);
|
i = q.size(); `checkh(i, 0);
|
||||||
q.push_back(4'd1); // 1
|
q.push_back(4'd1); // 1
|
||||||
q.push_front(4'd2); // 2 1
|
q.push_front(4'd2); // 2 1
|
||||||
|
|
@ -37,8 +96,22 @@ module t (/*AUTOARG*/
|
||||||
// Strings
|
// Strings
|
||||||
string q[$];
|
string q[$];
|
||||||
string v;
|
string v;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
// Empty queue checks
|
||||||
|
`checkh($left(q), 0);
|
||||||
|
`checkh($right(q), -1);
|
||||||
|
`checkh($increment(q), -1);
|
||||||
|
`checkh($low(q), 0);
|
||||||
|
`checkh($high(q), -1);
|
||||||
|
`checkh($size(q), 0);
|
||||||
|
`checkh($dimensions(q), 2);
|
||||||
|
//Unsup: `checkh($bits(q), 0);
|
||||||
|
|
||||||
q.push_front("f1");
|
q.push_front("f1");
|
||||||
|
|
||||||
|
//Unsup: `checkh($bits(q), 16);
|
||||||
|
|
||||||
q.push_back("b1");
|
q.push_back("b1");
|
||||||
q.push_front("f2");
|
q.push_front("f2");
|
||||||
q.push_back("b2");
|
q.push_back("b2");
|
||||||
|
|
@ -60,12 +133,28 @@ module t (/*AUTOARG*/
|
||||||
//v = q[0]; `checks(v, "ins0");
|
//v = q[0]; `checks(v, "ins0");
|
||||||
//v = q[3]; `checks(v, "ins3");
|
//v = q[3]; `checks(v, "ins3");
|
||||||
|
|
||||||
|
foreach (q[i]) begin
|
||||||
|
j++;
|
||||||
|
v = q[i];
|
||||||
|
if (i == 0) `checks(v, "f2");
|
||||||
|
if (i == 1) `checks(v, "f1");
|
||||||
|
if (i == 2) `checks(v, "b1");
|
||||||
|
if (i == 3) `checks(v, "b2");
|
||||||
|
end
|
||||||
|
`checkh(j,4);
|
||||||
|
|
||||||
q.pop_front();
|
q.pop_front();
|
||||||
v = q.pop_front(); `checks(v, "f1");
|
v = q.pop_front(); `checks(v, "f1");
|
||||||
v = q.pop_back(); `checks(v, "b2");
|
v = q.pop_back(); `checks(v, "b2");
|
||||||
v = q.pop_back(); `checks(v, "b1");
|
v = q.pop_back(); `checks(v, "b1");
|
||||||
i = q.size(); `checkh(i, 0);
|
i = q.size(); `checkh(i, 0);
|
||||||
|
|
||||||
|
// Empty queue, this should be 0
|
||||||
|
foreach (q[i]) begin
|
||||||
|
j++;
|
||||||
|
end
|
||||||
|
`checkh(j,4);
|
||||||
|
|
||||||
q.push_front("non-empty");
|
q.push_front("non-empty");
|
||||||
i = q.size(); `checkh(i, 1);
|
i = q.size(); `checkh(i, 1);
|
||||||
q.delete();
|
q.delete();
|
||||||
|
|
@ -83,6 +172,31 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
typedef struct packed {
|
||||||
|
bit [7:0] opcode;
|
||||||
|
bit [23:0] addr;
|
||||||
|
} instruction; // named structure type
|
||||||
|
|
||||||
|
instruction q[$];
|
||||||
|
|
||||||
|
`checkh($dimensions(q), 2);
|
||||||
|
//Unsup: `checkh($bits(q), 0);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Unsup:
|
||||||
|
begin
|
||||||
|
int q[4][$];
|
||||||
|
|
||||||
|
q[0].push_back(0);
|
||||||
|
q[0].push_back(1);
|
||||||
|
q[1].push_back(2);
|
||||||
|
q[2].push_back(3);
|
||||||
|
|
||||||
|
end
|
||||||
|
*/
|
||||||
|
|
||||||
// See t_queue_unsup_bad for more unsupported stuff
|
// See t_queue_unsup_bad for more unsupported stuff
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue