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 queues as statements, bug1641. [Peter Monsson, Stefan Wallentowitz]
|
||||
**** Fix queue issues, bug1641, bug1643. [Peter Monsson, Stefan Wallentowitz]
|
||||
|
||||
|
||||
* Verilator 4.024 2019-12-08
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue