Fix streaming of unpacked arrays concatenations (#5856)

This commit is contained in:
Ryszard Rozak 2025-03-13 13:56:29 +01:00 committed by GitHub
parent 51a97ccb90
commit 9a6598b36f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 0 deletions

View File

@ -198,6 +198,16 @@ class PremitVisitor final : public VNVisitor {
void visit(AstNodeAssign* nodep) override {
START_STATEMENT_OR_RETURN(nodep);
if (AstCvtArrayToPacked* const packedp = VN_CAST(nodep->lhsp(), CvtArrayToPacked)) {
// AstCvtArrayToPacked is converted to VL_PACK, which returns rvalue,
// so it shouldn't be on the LHS. It is now replaced with unpacking of RHS.
AstNodeExpr* const exprLhsp = packedp->fromp()->unlinkFrBack();
packedp->replaceWith(exprLhsp);
VL_DO_DANGLING(pushDeletep(packedp), packedp);
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
nodep->rhsp(new AstCvtPackedToArray{rhsp->fileline(), rhsp, exprLhsp->dtypep()});
nodep->dtypeFrom(exprLhsp);
}
// Direct assignment to a simple variable
if (VN_IS(nodep->lhsp(), VarRef) && !AstVar::scVarRecurse(nodep->lhsp())) {
AstNode* const rhsp = nodep->rhsp();

View File

@ -223,6 +223,7 @@ class WidthVisitor final : public VNVisitor {
const AstNodeExpr* m_randomizeFromp = nullptr; // Current randomize method call fromp
const bool m_paramsOnly; // Computing parameter value; limit operation
const bool m_doGenerate; // Do errors later inside generate statement
bool m_streamConcat = false; // True if visiting arguments of stream concatenation
int m_dtTables = 0; // Number of created data type tables
TableMap m_tableMap; // Created tables so can remove duplicates
std::map<const AstNodeDType*, AstQueueDType*>
@ -238,6 +239,18 @@ class WidthVisitor final : public VNVisitor {
EXTEND_OFF // No extension
};
static void packIfUnpacked(AstNodeExpr* const nodep) {
if (AstUnpackArrayDType* const unpackDTypep = VN_CAST(nodep->dtypep(), UnpackArrayDType)) {
const int elementsNum = unpackDTypep->arrayUnpackedElements();
const int unpackMinBits = elementsNum * unpackDTypep->subDTypep()->widthMin();
const int unpackBits = elementsNum * unpackDTypep->subDTypep()->width();
VNRelinker relinker;
nodep->unlinkFrBack(&relinker);
relinker.relink(new AstCvtArrayToPacked{
nodep->fileline(), nodep,
nodep->findLogicDType(unpackBits, unpackMinBits, VSigning::UNSIGNED)});
}
}
// VISITORS
// Naming: width_O{outputtype}_L{lhstype}_R{rhstype}_W{widthing}_S{signing}
// Where type:
@ -612,6 +625,11 @@ class WidthVisitor final : public VNVisitor {
} else {
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
if (m_streamConcat) {
packIfUnpacked(nodep->lhsp());
packIfUnpacked(nodep->rhsp());
}
nodep->dtypeSetLogicUnsized(nodep->lhsp()->width() + nodep->rhsp()->width(),
nodep->lhsp()->widthMin() + nodep->rhsp()->widthMin(),
VSigning::UNSIGNED);
@ -877,8 +895,11 @@ class WidthVisitor final : public VNVisitor {
}
}
void visit(AstNodeStream* nodep) override {
VL_RESTORER(m_streamConcat);
if (m_vup->prelim()) {
m_streamConcat = true;
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
m_streamConcat = false;
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change
if (const AstConst* const constp = VN_CAST(nodep->rhsp(), Const)) {

View File

@ -21,6 +21,12 @@ module t (/*AUTOARG*/);
bit [5:0] bit6 = 6'b111000;
bit [5:0] ans;
enum_t ans_enum;
logic [1:0] a [3] = {1, 0, 3};
logic [1:0] b [3] = {1, 2, 0};
logic c [4] = {1, 1, 0, 0};
logic [15:0] d;
logic [3:0] e [2];
logic f [8];
{ >> bit {arr}} = bit6;
`checkp(arr, "'{'h1, 'h1, 'h1, 'h0, 'h0, 'h0} ");
@ -76,6 +82,20 @@ module t (/*AUTOARG*/);
ans_enum = enum_t'({ << bit[5:0] {arr6} });
`checkh(ans_enum, bit6);
d = { >> {a, b, c}};
`checkh(d, 16'b0100110110001100);
{ >> {e, f}} = d;
`checkp(e, "'{'h4, 'hd} ");
`checkp(f, "'{'h1, 'h0, 'h0, 'h0, 'h1, 'h1, 'h0, 'h0} ");
d = { << 4 {a, b, c}};
`checkh(d, 16'b1100100011010100);
{ << 2 {e, f}} = d;
`checkp(e, "'{'h1, 'h7} ");
`checkp(f, "'{'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h1, 'h1} ");
$write("*-* All Finished *-*\n");
$finish;
end