mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Support assignments of packed values to stream expressions on queues (#4401)
This commit is contained in:
@@ -1013,6 +1013,20 @@ public:
|
||||
// May return nullptr on parse failure.
|
||||
static AstConst* parseParamLiteral(FileLine* fl, const string& literal);
|
||||
};
|
||||
class AstCvtPackedToDynArray final : public AstNodeExpr {
|
||||
// Cast from packed array to dynamic queue data type
|
||||
// @astgen op1 := fromp : AstNodeExpr
|
||||
public:
|
||||
AstCvtPackedToDynArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
|
||||
: ASTGEN_SUPER_CvtPackedToDynArray(fl) {
|
||||
this->fromp(fromp);
|
||||
dtypeFrom(dtp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCvtPackedToDynArray;
|
||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||
bool cleanOut() const override { return true; }
|
||||
};
|
||||
class AstDot final : public AstNodeExpr {
|
||||
// A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
|
||||
// These are eliminated in the link stage
|
||||
|
||||
+15
-15
@@ -2158,12 +2158,11 @@ private:
|
||||
return true;
|
||||
} else if (m_doV && VN_IS(nodep->lhsp(), StreamL)) {
|
||||
// Push the stream operator to the rhs of the assignment statement
|
||||
const int dWidth = VN_AS(nodep->lhsp(), StreamL)->lhsp()->width();
|
||||
const int sWidth = nodep->rhsp()->width();
|
||||
// Unlink the stuff
|
||||
AstNodeExpr* const dstp = VN_AS(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* streamp = VN_AS(nodep->lhsp(), StreamL)->unlinkFrBack();
|
||||
AstNodeExpr* streamp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const dstp = VN_AS(streamp, StreamL)->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
// Connect the rhs to the stream operator and update its width
|
||||
VN_AS(streamp, StreamL)->lhsp(srcp);
|
||||
if (VN_IS(srcp->dtypep(), DynArrayDType) || VN_IS(srcp->dtypep(), QueueDType)
|
||||
@@ -2172,11 +2171,11 @@ private:
|
||||
} else {
|
||||
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
|
||||
}
|
||||
// Shrink the RHS if necessary
|
||||
if (sWidth > dWidth) {
|
||||
if (dWidth == 0) {
|
||||
streamp = new AstCvtPackedToDynArray{nodep->fileline(), streamp, dstp->dtypep()};
|
||||
} else if (sWidth > dWidth) {
|
||||
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};
|
||||
}
|
||||
// Link the nodes back in
|
||||
nodep->lhsp(dstp);
|
||||
nodep->rhsp(streamp);
|
||||
return true;
|
||||
@@ -2184,14 +2183,15 @@ private:
|
||||
// The right stream operator on lhs of assignment statement does
|
||||
// not reorder bits. However, if the rhs is wider than the lhs,
|
||||
// then we select bits from the left-most, not the right-most.
|
||||
const int dWidth = VN_AS(nodep->lhsp(), StreamR)->lhsp()->width();
|
||||
const int sWidth = nodep->rhsp()->width();
|
||||
// Unlink the stuff
|
||||
AstNodeExpr* const dstp = VN_AS(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack();
|
||||
AstNode* const sizep = VN_AS(nodep->lhsp(), StreamR)->rhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const streamp = VN_AS(nodep->lhsp(), StreamR)->unlinkFrBack();
|
||||
AstNodeExpr* const streamp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNodeExpr* const dstp = VN_AS(streamp, StreamR)->lhsp()->unlinkFrBack();
|
||||
AstNode* const sizep = VN_AS(streamp, StreamR)->rhsp()->unlinkFrBack();
|
||||
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
|
||||
if (sWidth > dWidth) {
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
if (dWidth == 0) {
|
||||
srcp = new AstCvtPackedToDynArray{nodep->fileline(), srcp, dstp->dtypep()};
|
||||
} else if (sWidth > dWidth) {
|
||||
srcp = new AstSel{streamp->fileline(), srcp, sWidth - dWidth, dWidth};
|
||||
}
|
||||
nodep->lhsp(dstp);
|
||||
|
||||
@@ -401,6 +401,19 @@ public:
|
||||
puts(cvtToStr(nodep->widthMin()) + ",");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
puts(", ");
|
||||
} else if (const AstCvtPackedToDynArray* const castp
|
||||
= VN_CAST(nodep->rhsp(), CvtPackedToDynArray)) {
|
||||
puts("VL_ASSIGN_DYN_Q<");
|
||||
putbs(castp->dtypep()->subDTypep()->cType("", false, false));
|
||||
puts(">(");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
puts(", ");
|
||||
puts(cvtToStr(castp->dtypep()->subDTypep()->widthMin()));
|
||||
puts(", ");
|
||||
puts(cvtToStr(castp->fromp()->widthMin()));
|
||||
puts(", ");
|
||||
rhs = false;
|
||||
iterateAndNextConstNull(castp->fromp());
|
||||
} else if (nodep->isWide() && VN_IS(nodep->lhsp(), VarRef) //
|
||||
&& !VN_IS(nodep->rhsp(), CExpr) //
|
||||
&& !VN_IS(nodep->rhsp(), CMethodHard) //
|
||||
|
||||
+7
-3
@@ -840,9 +840,13 @@ private:
|
||||
} else {
|
||||
nodep->v3error("Slice size isn't a constant or basic data type.");
|
||||
}
|
||||
if (VN_IS(nodep->lhsp()->dtypep(), DynArrayDType)
|
||||
|| VN_IS(nodep->lhsp()->dtypep(), QueueDType)
|
||||
|| VN_IS(nodep->lhsp()->dtypep(), UnpackArrayDType)) {
|
||||
const AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep();
|
||||
if (VN_IS(lhsDtypep, DynArrayDType) || VN_IS(lhsDtypep, QueueDType)) {
|
||||
nodep->dtypeSetStream();
|
||||
} else if (VN_IS(lhsDtypep, UnpackArrayDType) || lhsDtypep->isCompound()) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: Stream operation on a variable of a type "
|
||||
<< lhsDtypep->prettyDTypeNameQ());
|
||||
nodep->dtypeSetStream();
|
||||
} else {
|
||||
nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), nodep->lhsp()->widthMin(),
|
||||
|
||||
Reference in New Issue
Block a user