Fix streaming operator packing order (#5903) (#6077)

This commit is contained in:
Paul Swirhun 2025-06-10 14:23:16 -07:00 committed by GitHub
parent 58ea7ad361
commit ac06b6fc4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 151 additions and 27 deletions

View File

@ -1607,19 +1607,21 @@ static inline WDataOutP VL_STREAML_WWI(int lbits, WDataOutP owp, WDataInP const
static inline IData VL_PACK_I_RI(int obits, int lbits, const VlQueue<CData>& q) {
IData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= static_cast<IData>(q.at(i)) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i)
ret |= static_cast<IData>(q.at(q.size() - 1 - i)) << (i * lbits);
return ret;
}
static inline IData VL_PACK_I_RI(int obits, int lbits, const VlQueue<SData>& q) {
IData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= static_cast<IData>(q.at(i)) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i)
ret |= static_cast<IData>(q.at(q.size() - 1 - i)) << (i * lbits);
return ret;
}
static inline IData VL_PACK_I_RI(int obits, int lbits, const VlQueue<IData>& q) {
IData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= q.at(i) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i) ret |= q.at(q.size() - 1 - i) << (i * lbits);
return ret;
}
@ -1648,19 +1650,22 @@ static inline IData VL_PACK_I_UI(int obits, int lbits, const VlUnpacked<IData, N
static inline QData VL_PACK_Q_RI(int obits, int lbits, const VlQueue<CData>& q) {
QData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= static_cast<QData>(q.at(i)) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i)
ret |= static_cast<QData>(q.at(q.size() - 1 - i)) << (i * lbits);
return ret;
}
static inline QData VL_PACK_Q_RI(int obits, int lbits, const VlQueue<SData>& q) {
QData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= static_cast<QData>(q.at(i)) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i)
ret |= static_cast<QData>(q.at(q.size() - 1 - i)) << (i * lbits);
return ret;
}
static inline QData VL_PACK_Q_RI(int obits, int lbits, const VlQueue<IData>& q) {
QData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= static_cast<QData>(q.at(i)) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i)
ret |= static_cast<QData>(q.at(q.size() - 1 - i)) << (i * lbits);
return ret;
}
@ -1690,7 +1695,7 @@ static inline QData VL_PACK_Q_UI(int obits, int lbits, const VlUnpacked<IData, N
static inline QData VL_PACK_Q_RQ(int obits, int lbits, const VlQueue<QData>& q) {
QData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= q.at(i) << (i * lbits);
for (size_t i = 0; i < q.size(); ++i) ret |= q.at(q.size() - 1 - i) << (i * lbits);
return ret;
}
@ -1705,7 +1710,7 @@ static inline WDataOutP VL_PACK_W_RI(int obits, int lbits, WDataOutP owp,
const VlQueue<CData>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WI(owp, q.at(q.size() - i - 1), i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -1713,7 +1718,7 @@ static inline WDataOutP VL_PACK_W_RI(int obits, int lbits, WDataOutP owp,
const VlQueue<SData>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WI(owp, q.at(q.size() - i - 1), i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -1721,7 +1726,7 @@ static inline WDataOutP VL_PACK_W_RI(int obits, int lbits, WDataOutP owp,
const VlQueue<IData>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WI(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -1756,7 +1761,7 @@ static inline WDataOutP VL_PACK_W_RQ(int obits, int lbits, WDataOutP owp,
const VlQueue<QData>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WQ(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WQ(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -1774,7 +1779,7 @@ static inline WDataOutP VL_PACK_W_RW(int obits, int lbits, WDataOutP owp,
const VlQueue<VlWide<N_Words>>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WW(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WW(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1, i * lbits);
return owp;
}
@ -2230,49 +2235,49 @@ static inline void VL_UNPACK_RI_I(int lbits, int rbits, VlQueue<CData>& q, IData
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RI_I(int lbits, int rbits, VlQueue<SData>& q, IData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RI_I(int lbits, int rbits, VlQueue<IData>& q, IData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RI_Q(int lbits, int rbits, VlQueue<CData>& q, QData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RI_Q(int lbits, int rbits, VlQueue<SData>& q, QData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RI_Q(int lbits, int rbits, VlQueue<IData>& q, QData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RQ_Q(int lbits, int rbits, VlQueue<QData>& q, QData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < size; ++i) q.atWrite(i) = (from >> (i * lbits)) & mask;
for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask;
}
static inline void VL_UNPACK_RI_W(int lbits, int rbits, VlQueue<CData>& q, WDataInP rwp) {

View File

@ -14,7 +14,7 @@ typedef enum bit [5:0] {
} enum_t;
module t (/*AUTOARG*/);
initial begin
task test1;
bit arr[];
bit [1:0] arr2[$];
bit [5:0] arr6[$];
@ -36,9 +36,7 @@ module t (/*AUTOARG*/);
arr160 = '{2{160'h0123456789abcdef0123456789abcdef01234567}};
{ >> bit {arr}} = bit6;
`checkp(arr, "'{'h0, 'h0, 'h0, 'h1, 'h1, 'h1} "); // Majority rules
// `checkp(arr, "'{'h1, 'h1, 'h1, 'h0, 'h0, 'h0} "); // VCS
`checkp(arr, "'{'h1, 'h1, 'h1, 'h0, 'h0, 'h0} ");
ans = { >> bit {arr} };
`checkh(ans, bit6);
@ -46,8 +44,7 @@ module t (/*AUTOARG*/);
`checkh(ans_enum, bit6);
{ << bit {arr}} = bit6;
`checkp(arr, "'{'h1, 'h1, 'h1, 'h0, 'h0, 'h0} "); // Majority rules
// `checkp(arr, "'{'h0, 'h0, 'h0, 'h1, 'h1, 'h1} "); // VCS
`checkp(arr, "'{'h0, 'h0, 'h0, 'h1, 'h1, 'h1} ");
ans = { << bit {arr} };
`checkh(ans, bit6);
@ -58,7 +55,7 @@ module t (/*AUTOARG*/);
`ifdef VERILATOR
// This set flags errors on other simulators
{ >> bit[1:0] {arr2}} = bit6;
`checkp(arr2, "'{'h0, 'h2, 'h3} ");
`checkp(arr2, "'{'h3, 'h2, 'h0} ");
ans = { >> bit[1:0] {arr2} };
`checkh(ans, bit6);
@ -67,7 +64,7 @@ module t (/*AUTOARG*/);
`checkh(ans_enum, bit6);
{ << bit[1:0] {arr2}} = bit6;
`checkp(arr2, "'{'h3, 'h2, 'h0} ");
`checkp(arr2, "'{'h0, 'h2, 'h3} ");
ans = { << bit[1:0] {arr2} };
`checkh(ans, bit6);
@ -143,6 +140,64 @@ module t (/*AUTOARG*/);
`checkh(arr160[0], 160'h67452301efcdab8967452301efcdab8967452301);
{ << byte {arr160} } = bit320;
`checkh(arr160[0], 160'h0123456789abcdef0123456789abcdef01234567);
endtask
task test2;
byte unpack [8]; // [0] is left-most for purposes of streaming
bit [63:0] bits; // [63] is left-most for purposes of streaming
longint word; // [63] is left-most for purposes of streaming
// Using packed bits
$display("Test2");
bits = {8'hfa, 8'hde, 8'hca, 8'hfe,
8'hde, 8'had, 8'hbe, 8'hef};
word = {>>{bits}};
`checkh(word, 64'hfadecafedeadbeef);
word = {<<8{bits}};
`checkh(word, 64'hefbeaddefecadefa);
// Using byte unpacked array
unpack = '{8'hfa, 8'hde, 8'hca, 8'hfe,
8'hde, 8'had, 8'hbe, 8'hef};
`checkh(unpack[0], 8'hfa);
`checkh(unpack[7], 8'hef);
word = {>>{unpack}};
`checkh(word, 64'hfadecafedeadbeef);
word = {<<8{unpack}};
`checkh(word, 64'hefbeaddefecadefa);
endtask
task test3;
byte dyn8 []; // [0] is left-most for purposes of streaming
longint word; // [63] is left-most for purposes of streaming
// verilator lint_off ASCRANGE
bit [0:63] rbits; // [63] is still left-most for purposes of streaming
// verilator lint_on ASCRANGE
// Using byte dynamic array
dyn8 = new[8]('{8'hfa, 8'hde, 8'hca, 8'hfe,
8'hde, 8'had, 8'hbe, 8'hef});
`checkh(dyn8[0], 8'hfa);
`checkh(dyn8[7], 8'hef);
word = {>>{dyn8}};
`checkh(word, 64'hfadecafedeadbeef);
word = {<<1{dyn8}};
`checkh(word, 64'hf77db57b7f537b5f);
word = {<<8{dyn8}};
`checkh(word, 64'hefbeaddefecadefa);
rbits = {>>{dyn8}};
`checkh(rbits, 64'hfadecafedeadbeef);
rbits = {<<1{dyn8}};
`checkh(rbits, 64'hf77db57b7f537b5f);
rbits = {<<8{dyn8}};
`checkh(rbits, 64'hefbeaddefecadefa);
endtask
initial begin;
test1();
test2();
test3();
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -33,6 +33,14 @@ module t (/*AUTOARG*/);
logic f [8];
logic [1:0][7:0] g;
logic [1:0][1:0][3:0] h;
byte i [];
longint j;
int k;
int l [];
logic [127:0] m;
longint n [];
logic [255:0] o;
logic [127:0] p[];
{ >> bit {arr}} = bit6;
`checkp(arr, "'{'h1, 'h1, 'h1, 'h0, 'h0, 'h0} ");
@ -219,6 +227,62 @@ module t (/*AUTOARG*/);
h = { << 8 {16'hABCD}};
`checkh(h, 16'hCDAB);
i = new[8]('{8'hfa, 8'hde, 8'hca, 8'hfe,
8'hde, 8'had, 8'hbe, 8'hef});
`checkh(i[0], 8'hfa);
`checkh(i[7], 8'hef);
j = {>>{i}};
`checkh(j, 64'hfadecafedeadbeef);
j = {<<8{i}};
`checkh(j, 64'hefbeaddefecadefa);
i = new[4]('{8'hba, 8'hbe, 8'hfa, 8'hce});
k = {>>{i}};
`checkh(k, 32'hbabeface);
k = {<<8{i}};
`checkh(k, 32'hcefabeba);
i = new[8]('{8'hba, 8'hbe, 8'hfa, 8'hce, 8'hde, 8'had, 8'hbe, 8'hef});
j = {>>{i}};
`checkh(j, 64'hbabefacedeadbeef);
j = {<<8{i}};
`checkh(j, 64'hefbeaddecefabeba);
i = new[16]('{8'hba, 8'hbe, 8'hfa, 8'hce, 8'hde, 8'had, 8'hbe, 8'hef,
8'hde, 8'had, 8'hbe, 8'hef, 8'hde, 8'had, 8'hbe, 8'hef});
m = {>>{i}};
`checkh(m, 128'hbabefacedeadbeefdeadbeefdeadbeef);
m = {<<8{i}};
`checkh(m, 128'hefbeaddeefbeaddeefbeaddecefabeba);
l = new[2]('{32'hbabeface, 32'hdeadbeef});
j = {>>{l}};
`checkh(j, 64'hbabefacedeadbeef);
j = {<<8{l}};
`checkh(j, 64'hefbeaddecefabeba);
l = new[4]('{32'hbabeface, 32'hdeadbeef, 32'hdeadbeef, 32'hdeadbeef});
m = {>>{l}};
`checkh(m, 128'hbabefacedeadbeefdeadbeefdeadbeef);
m = {<<8{l}};
`checkh(m, 128'hefbeaddeefbeaddeefbeaddecefabeba);
n = new[2]('{64'hfadecafedeadbeef, 64'habcd0123456789ab});
m = {>>{n}};
`checkh(m, 128'hfadecafedeadbeefabcd0123456789ab);
m = {<<64{n}};
`checkh(m, 128'habcd0123456789abfadecafedeadbeef);
p = new[2]('{128'hfadecafedeadbeefabcd0123456789ab,
128'habcd0123456789abfadecafedeadbeef});
o = {>>{p}};
`checkh(o, 256'hfadecafedeadbeefabcd0123456789ababcd0123456789abfadecafedeadbeef);
o = {<<128{p}};
`checkh(o, 256'habcd0123456789abfadecafedeadbeeffadecafedeadbeefabcd0123456789ab);
{>>{p}} = o;
`checkh(p[0], 128'hfadecafedeadbeefabcd0123456789ab);
`checkh(p[1], 128'habcd0123456789abfadecafedeadbeef);
$write("*-* All Finished *-*\n");
$finish;
end