Fix queue issues, bug1643.

Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Stefan Wallentowitz 2019-12-18 18:17:18 -05:00 committed by Wilson Snyder
parent 0465b6a3b1
commit 9a54b2144b
5 changed files with 201 additions and 29 deletions

View File

@ -22,7 +22,7 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** 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

View File

@ -622,8 +622,16 @@ std::pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
dtypep = adtypep->subDTypep();
continue;
}
else if (const AstQueueDType* qdtypep = VN_CAST(dtypep, QueueDType)) {
unpacked++;
dtypep = qdtypep->subDTypep();
continue;
}
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;
}

View File

@ -392,17 +392,22 @@ private:
FileLine* fl = varsp->fileline();
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
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,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT,
new AstVarRef(fl, arrayp->name(), false),
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;
// Assign left-dimension into the loop var:
stmtsp->addNext(new AstAssign
(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
// we count the loop variable up or down:
AstNode* countupp = new AstLte(fl, leftp->cloneTree(true),
@ -414,13 +419,15 @@ private:
rightp->cloneTree(true)),
// Left decrements down to right
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(
fl, new AstVarRef(fl, varp->name(), true),
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
new AstCond(fl, countupp,
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);
dimension--;
}

View File

@ -1076,31 +1076,74 @@ private:
case AstAttrType::DIM_LOW:
case AstAttrType::DIM_RIGHT:
case AstAttrType::DIM_SIZE: {
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep,
"Unsized expression");
std::pair<uint32_t,uint32_t> dim
= nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
uint32_t msbdim = dim.first + dim.second;
if (!nodep->dimp() || msbdim < 1) {
int dim = 1;
AstConst* newp = dimensionValue(nodep->fileline(),
nodep->fromp()->dtypep(), nodep->attrType(), dim);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
} else if (VN_IS(nodep->dimp(), Const)) {
int dim = VN_CAST(nodep->dimp(), Const)->toSInt();
AstConst* newp = dimensionValue(nodep->fileline(),
nodep->fromp()->dtypep(), nodep->attrType(), dim);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
}
else { // Need a runtime lookup table. Yuk.
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep,
"Unsized expression");
AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim);
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(); VL_DANGLING(nodep);
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "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
= nodep->fromp()->dtypep()->skipRefp()->dimensions(true);
uint32_t msbdim = dim.first + dim.second;
if (!nodep->dimp() || msbdim < 1) {
int dim = 1;
AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(),
nodep->attrType(), dim);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
} else if (VN_IS(nodep->dimp(), Const)) {
int dim = VN_CAST(nodep->dimp(), Const)->toSInt();
AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(),
nodep->attrType(), dim);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
}
else { // Need a runtime lookup table. Yuk.
UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep,
"Unsized expression");
AstVar* varp
= dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim);
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(); VL_DANGLING(nodep);
}
}
break;
}

View File

@ -20,12 +20,71 @@ module t (/*AUTOARG*/
always @ (posedge clk) begin
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
// Simple test using integer
typedef bit [3:0] nibble_t;
nibble_t q[$];
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);
q.push_back(4'd1); // 1
q.push_front(4'd2); // 2 1
@ -37,8 +96,22 @@ module t (/*AUTOARG*/
// Strings
string q[$];
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");
//Unsup: `checkh($bits(q), 16);
q.push_back("b1");
q.push_front("f2");
q.push_back("b2");
@ -60,12 +133,28 @@ module t (/*AUTOARG*/
//v = q[0]; `checks(v, "ins0");
//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();
v = q.pop_front(); `checks(v, "f1");
v = q.pop_back(); `checks(v, "b2");
v = q.pop_back(); `checks(v, "b1");
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");
i = q.size(); `checkh(i, 1);
q.delete();
@ -83,6 +172,31 @@ module t (/*AUTOARG*/
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
$write("*-* All Finished *-*\n");