Fix streaming with descending unpacked arrays and unpacked-to-queue (#7287)
This commit is contained in:
parent
9180eebdba
commit
998ec5b1d7
|
|
@ -2417,6 +2417,46 @@ static inline void VL_REVCOPY_Q(VlQueue<T>& q, const VlQueue<T>& from, int lbits
|
|||
}
|
||||
}
|
||||
|
||||
// Reverse element order of an unpacked array in-place.
|
||||
// Used by emitter for descending-range arrays after VL_UNPACK_*.
|
||||
template <typename T_Value, std::size_t N_Depth>
|
||||
static inline void VL_UNPACK_REVERSED(VlUnpacked<T_Value, N_Depth>& q) {
|
||||
for (size_t i = 0; i < N_Depth / 2; ++i) {
|
||||
const T_Value tmp = q[i];
|
||||
q[i] = q[N_Depth - 1 - i];
|
||||
q[N_Depth - 1 - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a reversed copy of an unpacked array.
|
||||
// Used by emitter for descending-range arrays before VL_PACK_*.
|
||||
template <typename T_Value, std::size_t N_Depth>
|
||||
static inline VlUnpacked<T_Value, N_Depth>
|
||||
VL_PACK_REVERSED(const VlUnpacked<T_Value, N_Depth>& q) {
|
||||
VlUnpacked<T_Value, N_Depth> ret;
|
||||
for (size_t i = 0; i < N_Depth; ++i) ret[i] = q[N_Depth - 1 - i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Overloads for VlUnpacked source -> VlQueue destination
|
||||
template <typename T, std::size_t N_Depth>
|
||||
static inline void VL_COPY_Q(VlQueue<T>& q, const VlUnpacked<T, N_Depth>& from, int lbits,
|
||||
int srcElementBits, int dstElementBits) {
|
||||
VlQueue<T> srcQ;
|
||||
srcQ.renew(N_Depth);
|
||||
for (size_t i = 0; i < N_Depth; ++i) srcQ.atWrite(i) = from[i];
|
||||
VL_COPY_Q(q, srcQ, lbits, srcElementBits, dstElementBits);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N_Depth>
|
||||
static inline void VL_REVCOPY_Q(VlQueue<T>& q, const VlUnpacked<T, N_Depth>& from, int lbits,
|
||||
int srcElementBits, int dstElementBits) {
|
||||
VlQueue<T> srcQ;
|
||||
srcQ.renew(N_Depth);
|
||||
for (size_t i = 0; i < N_Depth; ++i) srcQ.atWrite(i) = from[N_Depth - 1 - i];
|
||||
VL_COPY_Q(q, srcQ, lbits, srcElementBits, dstElementBits);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Expressions needing insert/select
|
||||
|
||||
|
|
|
|||
|
|
@ -2389,6 +2389,32 @@ class ConstVisitor final : public VNVisitor {
|
|||
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
|
||||
const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp();
|
||||
// Handle unpacked/queue/dynarray source -> queue/dynarray dest via
|
||||
// CvtArrayToArray (StreamL reverses, so reverse=true)
|
||||
if ((VN_IS(srcDTypep, UnpackArrayDType) || VN_IS(srcDTypep, QueueDType)
|
||||
|| VN_IS(srcDTypep, DynArrayDType))
|
||||
&& (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType))) {
|
||||
int blockSize = 1;
|
||||
if (const AstConst* const constp
|
||||
= VN_CAST(VN_AS(streamp, StreamL)->rhsp(), Const)) {
|
||||
blockSize = constp->toSInt();
|
||||
if (VL_UNLIKELY(blockSize <= 0)) blockSize = 1;
|
||||
}
|
||||
int srcElementBits = 0;
|
||||
if (const AstNodeDType* const elemDtp = srcDTypep->subDTypep()) {
|
||||
srcElementBits = elemDtp->width();
|
||||
}
|
||||
int dstElementBits = 0;
|
||||
if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
dstElementBits = elemDtp->width();
|
||||
}
|
||||
nodep->lhsp(dstp);
|
||||
nodep->rhsp(new AstCvtArrayToArray{srcp->fileline(), srcp, dstDTypep, true,
|
||||
blockSize, dstElementBits, srcElementBits});
|
||||
nodep->dtypep(dstDTypep);
|
||||
VL_DO_DANGLING(pushDeletep(streamp), streamp);
|
||||
return true;
|
||||
}
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
// Connect the rhs to the stream operator and update its width
|
||||
|
|
@ -2420,6 +2446,44 @@ class ConstVisitor final : public VNVisitor {
|
|||
AstNodeExpr* const dstp = VN_AS(streamp, StreamR)->lhsp()->unlinkFrBack();
|
||||
AstNodeDType* const dstDTypep = dstp->dtypep()->skipRefp();
|
||||
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
|
||||
// Handle unpacked/queue/dynarray source -> queue/dynarray dest via
|
||||
// CvtArrayToArray (StreamR does not reverse, so reverse=false).
|
||||
// V3Width may have wrapped the source in CvtArrayToPacked; unwrap it.
|
||||
if (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType)) {
|
||||
AstNodeExpr* origSrcp = srcp;
|
||||
if (AstCvtArrayToPacked* const cvtp = VN_CAST(srcp, CvtArrayToPacked)) {
|
||||
origSrcp = cvtp->fromp();
|
||||
}
|
||||
const AstNodeDType* const origSrcDTypep = origSrcp->dtypep()->skipRefp();
|
||||
if (VN_IS(origSrcDTypep, UnpackArrayDType) || VN_IS(origSrcDTypep, QueueDType)
|
||||
|| VN_IS(origSrcDTypep, DynArrayDType)) {
|
||||
int srcElementBits = 0;
|
||||
if (const AstNodeDType* const elemDtp = origSrcDTypep->subDTypep()) {
|
||||
srcElementBits = elemDtp->width();
|
||||
}
|
||||
int dstElementBits = 0;
|
||||
if (const AstNodeDType* const elemDtp = dstDTypep->subDTypep()) {
|
||||
dstElementBits = elemDtp->width();
|
||||
}
|
||||
if (VN_IS(srcp, CvtArrayToPacked)) {
|
||||
origSrcp = VN_AS(srcp, CvtArrayToPacked)->fromp()->unlinkFrBack();
|
||||
VL_DO_DANGLING(pushDeletep(srcp), srcp);
|
||||
srcp = origSrcp;
|
||||
}
|
||||
// Descending unpacked arrays need element reversal
|
||||
bool reverse = false;
|
||||
if (const AstUnpackArrayDType* const unpackDtp
|
||||
= VN_CAST(origSrcDTypep, UnpackArrayDType)) {
|
||||
reverse = !unpackDtp->declRange().ascending();
|
||||
}
|
||||
nodep->lhsp(dstp);
|
||||
nodep->rhsp(new AstCvtArrayToArray{srcp->fileline(), srcp, dstDTypep, reverse,
|
||||
1, dstElementBits, srcElementBits});
|
||||
nodep->dtypep(dstDTypep);
|
||||
VL_DO_DANGLING(pushDeletep(streamp), streamp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const int sWidth = srcp->width();
|
||||
const int dWidth = dstp->width();
|
||||
if (VN_IS(dstDTypep, UnpackArrayDType)) {
|
||||
|
|
|
|||
|
|
@ -456,12 +456,23 @@ public:
|
|||
void visit(AstCvtArrayToPacked* nodep) override {
|
||||
AstNodeDType* const fromDtp = nodep->fromp()->dtypep()->skipRefp();
|
||||
AstNodeDType* const elemDtp = fromDtp->subDTypep()->skipRefp();
|
||||
const bool descending = [&]() {
|
||||
if (const AstUnpackArrayDType* const unpackDtp = VN_CAST(fromDtp, UnpackArrayDType))
|
||||
return !unpackDtp->declRange().ascending();
|
||||
return false;
|
||||
}();
|
||||
puts("VL_PACK_");
|
||||
emitIQW(nodep);
|
||||
puts("_");
|
||||
emitRU(fromDtp);
|
||||
emitIQW(elemDtp);
|
||||
emitOpName(nodep, "(%nw, %rw, %P, %li)", nodep->fromp(), elemDtp, nullptr);
|
||||
if (descending) {
|
||||
// Wrap source in VL_PACK_REVERSED so VL_PACK sees ascending order
|
||||
emitOpName(nodep, "(%nw, %rw, %P, VL_PACK_REVERSED(%li))", nodep->fromp(), elemDtp,
|
||||
nullptr);
|
||||
} else {
|
||||
emitOpName(nodep, "(%nw, %rw, %P, %li)", nodep->fromp(), elemDtp, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstCvtUnpackedToQueue* nodep) override {
|
||||
|
|
@ -499,6 +510,7 @@ public:
|
|||
bool paren = true;
|
||||
bool decind = false;
|
||||
bool rhs = true;
|
||||
bool reverseUnpack = false; // Set for descending CvtPackedToArray
|
||||
if (AstSel* const selp = VN_CAST(nodep->lhsp(), Sel)) {
|
||||
UASSERT_OBJ(selp->widthMin() == selp->widthConst(), selp, "Width mismatch");
|
||||
if (selp->widthMin() == 1) {
|
||||
|
|
@ -567,6 +579,11 @@ public:
|
|||
puts(", ");
|
||||
rhs = false;
|
||||
iterateAndNextConstNull(castp->fromp());
|
||||
// Descending unpacked dest: reverse after unpack
|
||||
if (const AstUnpackArrayDType* const unpackDtp
|
||||
= VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
if (!unpackDtp->declRange().ascending()) reverseUnpack = true;
|
||||
}
|
||||
} else if (const AstCvtArrayToArray* const castp
|
||||
= VN_CAST(nodep->rhsp(), CvtArrayToArray)) {
|
||||
if (castp->reverse()) {
|
||||
|
|
@ -618,6 +635,11 @@ public:
|
|||
if (paren) puts(")");
|
||||
if (decind) ofp()->blockDec();
|
||||
puts(";\n");
|
||||
if (reverseUnpack) {
|
||||
puts("VL_UNPACK_REVERSED(");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
void visit(AstAssocSel* nodep) override {
|
||||
iterateAndNextConstNull(nodep->fromp());
|
||||
|
|
|
|||
|
|
@ -111,23 +111,19 @@ module t (
|
|||
// 2D packed array into unpacked array
|
||||
if (unpacked_siz_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
if (unpacked_asc_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
// TODO: VL_UNPACK does not account for descending unpacked array
|
||||
// index direction -- re-enable once fixed.
|
||||
// if (unpacked_des_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
if (unpacked_des_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
// 2D unpacked array into packed array
|
||||
if (packed_siz_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
if (packed_asc_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
// TODO: Descending-range packed array streaming + pattern comparison
|
||||
// if (packed_des_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
if (packed_des_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
// 2D packed array into queue
|
||||
if (packed_siz_queue_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
if (packed_asc_queue_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
if (packed_des_queue_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
// TODO: Streaming from unpacked array into queue produces empty
|
||||
// queue -- re-enable once fixed.
|
||||
// if (unpacked_siz_queue_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
// if (unpacked_asc_queue_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
// if (unpacked_des_queue_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
// 2D unpacked array into queue
|
||||
if (unpacked_siz_queue_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
if (unpacked_asc_queue_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
if (unpacked_des_queue_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
end
|
||||
|
||||
if (cyc == 3) begin
|
||||
|
|
|
|||
Loading…
Reference in New Issue