Fix too-short bit pack returning wrong value (#7111).

Fixes #7111.
This commit is contained in:
Wilson Snyder 2026-02-20 22:25:02 -05:00
parent 927b6fd3c1
commit 0051d91555
3 changed files with 67 additions and 16 deletions

View File

@ -121,6 +121,7 @@ Verilator 5.045 devel
* Fix time to not advance after `$finish` (#7095).
* Fix associative array size() constraint generating invalid resize() call (#7103) (#7112). [Yilou Wang]
* Fix circular class reference %p-printing causing infinite recursion (#7106).
* Fix too-short bit pack returning wrong value (#7111).
* Fix randomize of real (#7115). [Srinivasan Venkataramanan]

View File

@ -1718,24 +1718,33 @@ static inline QData VL_PACK_Q_UQ(int obits, int lbits, const VlUnpacked<QData, N
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);
if (VL_UNLIKELY(obits < q.size() * lbits)) return owp; // Though is illegal for q to be larger
const int offset = obits - q.size() * lbits;
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(q.size() - i - 1), i * lbits + lbits - 1, i * lbits);
_vl_insert_WI(owp, q.at(q.size() - i - 1), i * lbits + lbits - 1 + offset,
i * lbits + offset);
return owp;
}
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);
if (VL_UNLIKELY(obits < q.size() * lbits)) return owp; // Though is illegal for q to be larger
const int offset = obits - q.size() * lbits;
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(q.size() - i - 1), i * lbits + lbits - 1, i * lbits);
_vl_insert_WI(owp, q.at(q.size() - i - 1), i * lbits + lbits - 1 + offset,
i * lbits + offset);
return owp;
}
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);
if (VL_UNLIKELY(obits < q.size() * lbits)) return owp; // Though is illegal for q to be larger
const int offset = obits - q.size() * lbits;
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WI(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1 + offset,
i * lbits + offset);
return owp;
}
@ -1769,8 +1778,11 @@ static inline WDataOutP VL_PACK_W_UI(int obits, int lbits, WDataOutP owp,
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);
if (VL_UNLIKELY(obits < q.size() * lbits)) return owp; // Though is illegal for q to be larger
const int offset = obits - q.size() * lbits;
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WQ(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WQ(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1 + offset,
i * lbits + offset);
return owp;
}
@ -1787,8 +1799,11 @@ template <std::size_t N_Words>
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);
if (VL_UNLIKELY(obits < q.size() * lbits)) return owp; // Though is illegal for q to be larger
const int offset = obits - q.size() * lbits;
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WW(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1, i * lbits);
_vl_insert_WW(owp, q.at(q.size() - 1 - i), i * lbits + lbits - 1 + offset,
i * lbits + offset);
return owp;
}
@ -1796,8 +1811,10 @@ template <std::size_t N_Depth, std::size_t N_Words>
static inline WDataOutP VL_PACK_W_UW(int obits, int lbits, WDataOutP owp,
const VlUnpacked<VlWide<N_Words>, N_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
if (VL_UNLIKELY(obits < q.size() * lbits)) return owp; // Though is illegal for q to be larger
const int offset = obits - q.size() * lbits;
for (size_t i = 0; i < N_Depth; ++i)
_vl_insert_WW(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
_vl_insert_WW(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1 + offset, i * lbits + offset);
return owp;
}

View File

@ -48,14 +48,14 @@ module t ( /*AUTOARG*/
`checkh(bit_q[2], 1'b1);
`checkh(bit_q[3], 1'b0);
bit_q = bit_q_t'(4'h3);
bit_q = bit_q_t'(4'h3);
bit_qq = bit_q;
`checkh(bit_qq[0], 1'b0);
`checkh(bit_qq[1], 1'b0);
`checkh(bit_qq[2], 1'b1);
`checkh(bit_qq[3], 1'b1);
bit_q = bit_q_t'(4'h2);
bit_q = bit_q_t'(4'h2);
bit_qq = bit_q_t'(bit_q);
`checkh(bit_qq[0], 1'b0);
`checkh(bit_qq[1], 1'b0);
@ -256,7 +256,7 @@ module t ( /*AUTOARG*/
begin
byte_q_t bytq_init;
byte_q_t bytq;
bit_q_t bitq;
bit_q_t bitq;
bytq_init.push_back(8'h84);
bytq_init.push_back(8'haa);
@ -269,8 +269,9 @@ module t ( /*AUTOARG*/
bitq = {<<8{bit_q_t'({<<{bytq}})}};
bytq = {<<8{bit_q_t'({<<{bitq}})}};
s = $sformatf("bitq=%p", bitq);
`checks(s,
"bitq='{'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1}");
`checks(
s,
"bitq='{'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1}");
s = $sformatf("bytq=%p", bytq);
`checks(s, "bytq='{'h84, 'haa}");
@ -403,7 +404,7 @@ module t ( /*AUTOARG*/
// Test StreamR (>>) operations - fairly simple since this should maintain left-to-right order.
begin
bit_q_t bitq;
bit_q_t bitq;
byte_q_t bytq;
bitq = {1'b1, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0};
@ -414,8 +415,9 @@ module t ( /*AUTOARG*/
bytq = {8'h84, 8'haa};
bitq = {>>{bit_q_t'({<<{bytq}})}};
s = $sformatf("bitq=%p", bitq);
`checks(s,
"bitq='{'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1}");
`checks(
s,
"bitq='{'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1}");
bitq = {
1'b1,
@ -452,8 +454,9 @@ module t ( /*AUTOARG*/
bytq = {8'h84, 8'haa};
bitq = {>>{bit_q_t'({>>{bytq}})}};
s = $sformatf("bitq=%p", bitq);
`checks(s,
"bitq='{'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0}");
`checks(
s,
"bitq='{'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0}");
bitq = {
1'b1,
@ -483,6 +486,36 @@ module t ( /*AUTOARG*/
`checks(s, "bytq='{'h12, 'h34, 'h56}");
end
begin
bit wide_bits[];
bit [1023:0] wide_stream;
// verilator lint_off ASCRANGE
bit [0:1023] wide_streamr;
// verilator lint_on ASCRANGE
// verilog_format: off
wide_bits = '{1,0,1,0,1,0,1,1,0,0,1,1,0,0,0,1,0,1,0,1,0,1,1,0,1,1,0,1,0,1,0,0,
1,0,1,1,0,1,1,1,0,1,0,1,0,0,1,0,1,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,
0,1,0,1,0,0,1,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0,0,0,1,1,0,1,1,1,1,1,
1,0,1,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,0,1,1,1,
1,0,0,0,1,0,1,0,1,1,1,1,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,1,1,0,1,1,1,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,0,1,0,1,1,1,
1,1,0,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,0,1,1,1,
1,0,0,1,0,1,0,1,1,1,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,1,1,
1,1,1,1,0,1,0,1,1,1,0,0,1,1,0,0};
// verilog_format: on
`checkh(wide_bits.size(), 432);
wide_stream = {>>bit{wide_bits}};
`checkh(wide_stream,
1024'hab3156d4b752f843537d68dfbf48f1f78af787ff8df2c257cd6fa7c795d300000000000000000000000000000000ffffffffa5bbf5cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
end
$write("*-* All Finished *-*\n");
$finish;
end