forked from github/verilator
Support wide operands in queues and dynamic arrays (#2352)
This commit is contained in:
parent
9ffad7f0db
commit
a7432bdea7
2
Changes
2
Changes
@ -21,6 +21,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
**** Fix $isunknown with constant Z's.
|
||||
|
||||
**** Fix queues and dynamic array wide ops. (#2352) [Vassilis Papaefstathiou]
|
||||
|
||||
|
||||
* Verilator 4.034 2020-05-03
|
||||
|
||||
|
@ -48,6 +48,7 @@ Tim Snyder
|
||||
Tobias Rosenkranz
|
||||
Tobias Wölfel
|
||||
Todd Strader
|
||||
Vassilis Papaefstathiou
|
||||
Veripool API Bot
|
||||
Wilson Snyder
|
||||
Yossi Nivin
|
||||
|
@ -304,13 +304,7 @@ public:
|
||||
AstAssocArrayDType* adtypep = VN_CAST(nodep->fromp()->dtypep(), AssocArrayDType);
|
||||
UASSERT_OBJ(adtypep, nodep, "Associative select on non-associative type");
|
||||
if (adtypep->keyDTypep()->isWide()) {
|
||||
// Container class must take non-C-array (pointer) argument, so convert
|
||||
putbs("VL_CVT_W_A(");
|
||||
iterateAndNextNull(nodep->bitp());
|
||||
puts(", ");
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
putbs(".atDefault()"); // Not accessed; only to get the proper type of values
|
||||
puts(")");
|
||||
emitCvtWideArray(nodep->bitp(), nodep->fromp());
|
||||
} else {
|
||||
iterateAndNextNull(nodep->bitp());
|
||||
}
|
||||
@ -351,10 +345,21 @@ public:
|
||||
bool comma = false;
|
||||
for (AstNode* subnodep = nodep->pinsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||
if (comma) puts(", ");
|
||||
iterate(subnodep);
|
||||
// handle wide arguments to the queues
|
||||
if (VN_IS(nodep->fromp()->dtypep(), QueueDType) && subnodep->dtypep()->isWide()) {
|
||||
emitCvtWideArray(subnodep, nodep->fromp());
|
||||
} else {
|
||||
iterate(subnodep);
|
||||
}
|
||||
comma = true;
|
||||
}
|
||||
puts(")");
|
||||
// if there is a return value that is wide convert to array
|
||||
if (nodep->dtypep()->isWide()
|
||||
&& (VN_IS(nodep->fromp()->dtypep(), QueueDType)
|
||||
|| VN_IS(nodep->fromp()->dtypep(), DynArrayDType))) {
|
||||
puts(".data()"); // Access returned std::array as C array
|
||||
}
|
||||
// Some are statements some are math.
|
||||
if (nodep->isStatement()) puts(";\n");
|
||||
UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType), nodep,
|
||||
@ -1041,6 +1046,14 @@ public:
|
||||
puts(")");
|
||||
}
|
||||
}
|
||||
void emitCvtWideArray(AstNode* nodep, AstNode* fromp) {
|
||||
putbs("VL_CVT_W_A(");
|
||||
iterate(nodep);
|
||||
puts(", ");
|
||||
iterate(fromp);
|
||||
putbs(".atDefault()"); // Not accessed; only to get the proper type of values
|
||||
puts(")");
|
||||
}
|
||||
void emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
|
||||
// Put out constant set to the specified variable, or given variable in a string
|
||||
if (nodep->num().isFourState()) {
|
||||
@ -1638,17 +1651,22 @@ class EmitCImp : EmitCStmts {
|
||||
AstBasicDType* basicp = dtypep->basicp();
|
||||
// Returns string to do resetting, empty to do nothing (which caller should handle)
|
||||
if (AstAssocArrayDType* adtypep = VN_CAST(dtypep, AssocArrayDType)) {
|
||||
string cvtarray
|
||||
= (adtypep->subDTypep()->isWide() ? ".data()"
|
||||
: ""); // Access std::array as C array
|
||||
// Access std::array as C array
|
||||
string cvtarray = (adtypep->subDTypep()->isWide() ? ".data()" : "");
|
||||
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1,
|
||||
".atDefault()" + cvtarray);
|
||||
} else if (AstClassRefDType* adtypep = VN_CAST(dtypep, ClassRefDType)) {
|
||||
return ""; // Constructor does it
|
||||
} else if (AstDynArrayDType* adtypep = VN_CAST(dtypep, DynArrayDType)) {
|
||||
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, ".atDefault()");
|
||||
// Access std::array as C array
|
||||
string cvtarray = (adtypep->subDTypep()->isWide() ? ".data()" : "");
|
||||
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1,
|
||||
".atDefault()" + cvtarray);
|
||||
} else if (AstQueueDType* adtypep = VN_CAST(dtypep, QueueDType)) {
|
||||
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, ".atDefault()");
|
||||
// Access std::array as C array
|
||||
string cvtarray = (adtypep->subDTypep()->isWide() ? ".data()" : "");
|
||||
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1,
|
||||
".atDefault()" + cvtarray);
|
||||
} else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
UASSERT_OBJ(adtypep->msb() >= adtypep->lsb(), varp,
|
||||
"Should have swapped msb & lsb earlier.");
|
||||
|
@ -27,6 +27,15 @@ module t (/*AUTOARG*/
|
||||
byte_t a[];
|
||||
byte_t b[];
|
||||
|
||||
// wide data array
|
||||
typedef struct packed {
|
||||
logic [15:0] header;
|
||||
logic [223:0] payload;
|
||||
logic [15:0] checksum;
|
||||
} pck256_t;
|
||||
|
||||
pck256_t p256[];
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
begin
|
||||
@ -100,6 +109,33 @@ module t (/*AUTOARG*/
|
||||
`checkh(b[1], 0);
|
||||
`checkh(b[2], 0);
|
||||
`checkh(b[4], 0);
|
||||
|
||||
// test wide dynamic array
|
||||
p256 = new [11];
|
||||
`checkh(p256.size, 11);
|
||||
`checkh(p256.size(), 11);
|
||||
|
||||
p256[1].header = 16'hcafe;
|
||||
p256[1].payload = {14{16'hbabe}};
|
||||
p256[1].checksum = 16'hdead;
|
||||
`checkh(p256[1].header, 16'hcafe);
|
||||
`checkh(p256[1], {16'hcafe,{14{16'hbabe}},16'hdead});
|
||||
|
||||
`checkh(p256[0], '0);
|
||||
|
||||
p256[5] = '1;
|
||||
`checkh(p256[5], {32{8'hff}});
|
||||
|
||||
p256[5].header = 16'h2;
|
||||
`checkh(p256[5], {16'h2,{30{8'hff}}});
|
||||
|
||||
p256[2] = ( p256[5].header == 2 ) ? p256[1] : p256[5];
|
||||
`checkh(p256[2], {16'hcafe,{14{16'hbabe}},16'hdead});
|
||||
|
||||
|
||||
p256.delete();
|
||||
`checkh(p256.size, 0);
|
||||
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
@ -195,6 +195,45 @@ module t (/*AUTOARG*/
|
||||
|
||||
end
|
||||
|
||||
// testing a wide queue
|
||||
begin
|
||||
typedef struct packed {
|
||||
bit [7:0] opcode;
|
||||
bit [23:0] addr;
|
||||
bit [127:0] data;
|
||||
} instructionW; // named structure type
|
||||
|
||||
instructionW inst_push;
|
||||
instructionW inst_pop;
|
||||
|
||||
instructionW q[$];
|
||||
`checkh($dimensions(q), 2);
|
||||
|
||||
`checkh(q[0].opcode, 0);
|
||||
`checkh(q[0].addr, 0);
|
||||
`checkh(q[0].data, 0);
|
||||
|
||||
inst_push.opcode = 1;
|
||||
inst_push.addr = 42;
|
||||
inst_push.data = {4{32'hdeadbeef}};
|
||||
q.push_back(inst_push);
|
||||
`checkh(q[0].opcode, 1);
|
||||
`checkh(q[0].addr, 42);
|
||||
`checkh(q[0].data, {4{32'hdeadbeef}});
|
||||
|
||||
|
||||
inst_pop = q.pop_front();
|
||||
`checkh(inst_pop.opcode, 1);
|
||||
`checkh(inst_pop.addr, 42);
|
||||
`checkh(inst_pop.data, {4{32'hdeadbeef}});
|
||||
|
||||
`checkh(q.size(), 0);
|
||||
|
||||
`checkh(q[0].opcode, 0);
|
||||
`checkh(q[0].addr, 0);
|
||||
`checkh(q[0].data, 0);
|
||||
end
|
||||
|
||||
/* Unsup:
|
||||
begin
|
||||
int q[4][$];
|
||||
|
Loading…
Reference in New Issue
Block a user