Fix stream operator widening (#6693) (#6697)

This commit is contained in:
Jean-Nicolas Strauss 2025-11-16 04:52:52 +01:00 committed by GitHub
parent 048c97f0ae
commit 6454a8802e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 0 deletions

View File

@ -105,6 +105,7 @@ Jamey Hicks
Jamie Iles
Jan Van Winkel
Jean Berniolles
Jean-Nicolas Strauss
Jens Yuechao Liu
Jeremy Bennett
Jesse Taube

View File

@ -8175,6 +8175,25 @@ class WidthVisitor final : public VNVisitor {
} else if (pinp && pinp->modVarp()->direction() != VDirection::INPUT) {
// V3Inst::pinReconnectSimple must deal
UINFO(5, "pinInSizeMismatch: " << pinp);
} else if (assignp && VN_IS(underp, NodeStream)
&& expWidth > underp->width()) {
// IEEE 1800-2023 11.4.14: When assigning a stream to a wider fixed-size
// target, widen by filling zero bits on the right. That is, left-justify
// the stream bits within the target width.
// Build: ShiftL(Extend(stream, expWidth), expWidth - streamWidth)
UINFO(5, "Widen NodeStream RHS with left-justify per 11.4.14");
VNRelinker linker;
const int shift = expWidth - underp->width();
underp->unlinkFrBack(&linker);
AstExtend* const widenedp = new AstExtend{underp->fileline(), underp};
widenedp->didWidth(true);
// Shift left so zeros fill on the right
AstNodeExpr* const shiftedp = new AstShiftL{
underp->fileline(), widenedp,
new AstConst{underp->fileline(), static_cast<uint32_t>(shift)}, expWidth};
// Final dtype should match expected
shiftedp->dtypep(expDTypep);
linker.relink(shiftedp);
} else {
VL_DO_DANGLING(fixWidthExtend(underp, expDTypep, extendRule), underp);
}

View File

@ -18,6 +18,10 @@ module t;
logic [7:0] dst_2; // 8 bits wide target
logic [7:0] exp_2; // 8 bits wide target
logic [7:0] src_3 = 8'hA5; // 8 bits wide source
logic [27:0] dst_3; // 28 bits wide target
logic [27:0] exp_3; // 28 bits wide target
string expv;
string gotv;
@ -49,6 +53,24 @@ module t;
gotv = $sformatf("%p", dst_2);
`checks(gotv, expv);
// unpack as source, StreamL
// verilator lint_off WIDTHEXPAND
dst_3 = {<<{src_3}};
// verilator lint_on WIDTHEXPAND
exp_3 = 28'hA500000;
expv = $sformatf("%p", exp_3);
gotv = $sformatf("%p", dst_3);
`checks(gotv, expv);
// unpack as source, StreamR
// verilator lint_off WIDTHEXPAND
dst_3 = {>>{src_3}};
// verilator lint_on WIDTHEXPAND
exp_3 = 28'hA500000;
expv = $sformatf("%p", exp_3);
gotv = $sformatf("%p", dst_3);
`checks(gotv, expv);
$write("*-* All Finished *-*\n");
$finish;
end