Support streaming operator on arrays and wide data (#5326)

Signed-off-by: Arkadiusz Kozdra <akozdra@antmicro.com>
This commit is contained in:
Arkadiusz Kozdra 2024-08-06 14:48:46 +02:00 committed by GitHub
parent 3b81654c72
commit a32b8d80f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 194 additions and 243 deletions

View File

@ -1586,46 +1586,68 @@ static inline WDataOutP VL_STREAML_WWI(int lbits, WDataOutP owp, WDataInP const
}
template <typename T>
static inline void VL_ASSIGN_DYN_Q(VlQueue<T>& q, int elem_size, int lbits, QData from) {
const int size = (lbits + elem_size - 1) / elem_size;
q.renew(size);
const QData mask = VL_MASK_Q(elem_size);
for (int i = 0; i < size; ++i) q.at(i) = (T)((from >> (i * elem_size)) & mask);
static inline IData VL_PACK_II(int obits, int lbits, const VlQueue<T>& q) {
IData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= q.at(i) << (i * lbits);
return ret;
}
template <typename T, std::size_t T_Depth>
static inline void VL_ASSIGN_UNPACK_Q(VlUnpacked<T, T_Depth>& q, size_t elem_size, QData from) {
const QData mask = VL_MASK_Q(elem_size);
static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked<T, T_Depth>& q) {
IData ret = 0;
for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * lbits);
return ret;
}
#define VL_PACK_QI VL_PACK_QQ
template <typename T>
static inline QData VL_PACK_QQ(int obits, int lbits, const VlQueue<T>& q) {
QData ret = 0;
for (size_t i = 0; i < q.size(); ++i) ret |= static_cast<QData>(q.at(i)) << (i * lbits);
return ret;
}
template <typename T, std::size_t T_Depth>
static inline QData VL_PACK_QQ(int obits, int lbits, const VlUnpacked<T, T_Depth>& q) {
QData ret = 0;
for (size_t i = 0; i < T_Depth; ++i)
q[i] = (T)((from >> ((T_Depth - 1 - i) * elem_size)) & mask);
}
template <typename T>
static inline IData VL_DYN_TO_I(const VlQueue<T>& q, int elem_size) {
IData ret = 0;
for (int i = 0; i < q.size(); ++i) ret |= q.at(i) << (i * elem_size);
ret |= static_cast<QData>(q[T_Depth - 1 - i]) << (i * lbits);
return ret;
}
template <typename T>
static inline QData VL_DYN_TO_Q(const VlQueue<T>& q, int elem_size) {
QData ret = 0;
for (int i = 0; i < q.size(); ++i) ret |= q.at(i) << (i * elem_size);
return ret;
static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp, const VlQueue<T>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WI(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
return owp;
}
template <typename T, std::size_t T_Depth>
static inline IData VL_UNPACK_TO_I(const VlUnpacked<T, T_Depth>& q, size_t elem_size) {
IData ret = 0;
for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * elem_size);
return ret;
static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp,
const VlUnpacked<T, T_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
template <typename T>
static inline WDataOutP VL_PACK_WQ(int obits, int lbits, WDataOutP owp, const VlQueue<T>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < q.size(); ++i)
_vl_insert_WQ(owp, q.at(i), i * lbits + lbits - 1, i * lbits);
return owp;
}
template <typename T, std::size_t T_Depth>
static inline QData VL_UNPACK_TO_Q(const VlUnpacked<T, T_Depth>& q, size_t elem_size) {
QData ret = 0;
for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * elem_size);
return ret;
static inline WDataOutP VL_PACK_WQ(int obits, int lbits, WDataOutP owp,
const VlUnpacked<T, T_Depth>& q) {
VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1);
for (size_t i = 0; i < T_Depth; ++i)
_vl_insert_WQ(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits);
return owp;
}
// Because concats are common and wide, it's valuable to always have a clean output.
@ -2067,6 +2089,70 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, WDataOutP owp, WDataIn
//======================================================================
// Expressions needing insert/select
template <typename T>
static inline void VL_UNPACK_II(int lbits, int rbits, VlQueue<T>& q, IData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i) q.at(i) = static_cast<T>((from >> (i * lbits)) & mask);
}
#define VL_UNPACK_IQ VL_UNPACK_QQ
template <typename T>
static inline void VL_UNPACK_QQ(int lbits, int rbits, VlQueue<T>& q, QData from) {
const size_t size = (rbits + lbits - 1) / lbits;
q.renew(size);
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < size; ++i) q.at(i) = static_cast<T>((from >> (i * lbits)) & mask);
}
template <typename T>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlQueue<T>& q, WDataInP rwp) {
const int size = (rbits + lbits - 1) / lbits;
q.renew(size);
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < size; ++i)
q.at(i) = static_cast<T>(VL_SEL_IWII(rbits, rwp, i * lbits, lbits) & mask);
}
template <typename T>
static inline void VL_UNPACK_QW(int lbits, int rbits, VlQueue<T>& q, WDataInP rwp) {
const int size = (rbits + lbits - 1) / lbits;
q.renew(size);
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < size; ++i)
q.at(i) = static_cast<T>(VL_SEL_QWII(rbits, rwp, i * lbits, lbits) & mask);
}
template <typename T, std::size_t T_Depth>
static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked<T, T_Depth>& q, QData from) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = static_cast<T>((from >> ((T_Depth - 1 - i) * lbits)) & mask);
}
template <typename T, std::size_t T_Depth>
static inline void VL_UNPACK_QQ(int lbits, int rbits, VlUnpacked<T, T_Depth>& q, QData from) {
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = static_cast<T>((from >> ((T_Depth - 1 - i) * lbits)) & mask);
}
template <typename T, std::size_t T_Depth>
static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked<T, T_Depth>& q, WDataInP rwp) {
const IData mask = VL_MASK_I(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = static_cast<T>(VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask);
}
template <typename T, std::size_t T_Depth>
static inline void VL_UNPACK_QW(int lbits, int rbits, VlUnpacked<T, T_Depth>& q, WDataInP rwp) {
const QData mask = VL_MASK_Q(lbits);
for (size_t i = 0; i < T_Depth; ++i)
q[i] = static_cast<T>(VL_SEL_QWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask);
}
// Return QData from double (numeric)
// EMIT_RULE: VL_RTOIROUND_Q_D: oclean=dirty; lclean==clean/real
static inline QData VL_RTOIROUND_Q_D(double lhs) VL_PURE {

View File

@ -1124,58 +1124,30 @@ public:
string emitC() final override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
};
class AstCvtDynArrayToPacked final : public AstNodeExpr {
class AstCvtArrayToPacked final : public AstNodeExpr {
// Cast from dynamic queue data type to packed array
// @astgen op1 := fromp : AstNodeExpr
public:
AstCvtDynArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtDynArrayToPacked(fl) {
AstCvtArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtArrayToPacked(fl) {
this->fromp(fromp);
dtypeFrom(dtp);
}
ASTGEN_MEMBERS_AstCvtDynArrayToPacked;
ASTGEN_MEMBERS_AstCvtArrayToPacked;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
string emitC() override { return "VL_PACK_%nq%rq(%nw, %rw, %P, %li)"; }
bool cleanOut() const override { return true; }
};
class AstCvtPackedToDynArray final : public AstNodeExpr {
// Cast from packed array to dynamic queue data type
class AstCvtPackedToArray final : public AstNodeExpr {
// Cast from packed array to dynamic/unpacked queue data type
// @astgen op1 := fromp : AstNodeExpr
public:
AstCvtPackedToDynArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtPackedToDynArray(fl) {
AstCvtPackedToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtPackedToArray(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 AstCvtPackedToUnpackArray final : public AstNodeExpr {
// Cast from packed array to dynamic queue data type
// @astgen op1 := fromp : AstNodeExpr
public:
AstCvtPackedToUnpackArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtPackedToUnpackArray(fl) {
this->fromp(fromp);
dtypeFrom(dtp);
}
ASTGEN_MEMBERS_AstCvtPackedToUnpackArray;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
};
class AstCvtUnpackArrayToPacked final : public AstNodeExpr {
// Cast from dynamic queue data type to packed array
// @astgen op1 := fromp : AstNodeExpr
public:
AstCvtUnpackArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
: ASTGEN_SUPER_CvtUnpackArrayToPacked(fl) {
this->fromp(fromp);
dtypeFrom(dtp);
}
ASTGEN_MEMBERS_AstCvtUnpackArrayToPacked;
ASTGEN_MEMBERS_AstCvtPackedToArray;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
@ -4284,7 +4256,7 @@ public:
bool cleanOut() const override { return true; }
bool cleanLhs() const override { return true; }
bool cleanRhs() const override { return true; }
bool sizeMattersLhs() const override { return true; }
bool sizeMattersLhs() const override { return false; }
bool sizeMattersRhs() const override { return false; }
int instrCount() const override { return widthInstrs() * 2; }
};
@ -4305,7 +4277,7 @@ public:
bool cleanOut() const override { return false; }
bool cleanLhs() const override { return false; }
bool cleanRhs() const override { return false; }
bool sizeMattersLhs() const override { return true; }
bool sizeMattersLhs() const override { return false; }
bool sizeMattersRhs() const override { return false; }
int instrCount() const override { return widthInstrs() * 2; }
};

View File

@ -2171,26 +2171,17 @@ class ConstVisitor final : public VNVisitor {
AstNodeExpr* srcp = streamp->lhsp()->unlinkFrBack();
AstNodeDType* const srcDTypep = srcp->dtypep();
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
if (nodep->lhsp()->widthMin() > 64) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Assignment of stream of dynamic "
"array to a variable of size greater than 64");
}
srcp = new AstCvtDynArrayToPacked{srcp->fileline(), srcp, srcDTypep};
srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, nodep->dtypep()};
} else if (VN_IS(srcDTypep, UnpackArrayDType)) {
if (nodep->lhsp()->widthMin() > 64) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Assignment of stream of dynamic "
"array to a variable of size greater than 64");
}
srcp = new AstCvtUnpackArrayToPacked{srcp->fileline(), srcp,
nodep->lhsp()->dtypep()};
srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, srcDTypep};
// Handling the case where lhs is wider than rhs by inserting zeros. StreamL does
// not require this, since the left streaming operator implicitly handles this.
const uint32_t packedBits = nodep->lhsp()->widthMin();
const uint32_t unpackBits
const int packedBits = nodep->lhsp()->widthMin();
const int unpackBits
= srcDTypep->arrayUnpackedElements() * srcDTypep->subDTypep()->widthMin();
const uint32_t offset = packedBits > unpackBits ? packedBits - unpackBits : 0;
srcp = new AstShiftL{srcp->fileline(), srcp,
new AstConst{srcp->fileline(), offset}, 64};
new AstConst{srcp->fileline(), offset}, packedBits};
}
nodep->rhsp(srcp);
VL_DO_DANGLING(pushDeletep(streamp), streamp);
@ -2212,19 +2203,18 @@ class ConstVisitor final : public VNVisitor {
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
}
if (VN_IS(dstp->dtypep(), UnpackArrayDType)) {
streamp
= new AstCvtPackedToUnpackArray{nodep->fileline(), streamp, dstp->dtypep()};
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstp->dtypep()};
} else {
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
if (dWidth == 0) {
streamp
= new AstCvtPackedToDynArray{nodep->fileline(), streamp, dstp->dtypep()};
streamp = new AstCvtPackedToArray{nodep->fileline(), streamp, dstp->dtypep()};
} else if (sWidth >= dWidth) {
streamp = new AstSel{streamp->fileline(), streamp, sWidth - dWidth, dWidth};
}
}
nodep->lhsp(dstp);
nodep->rhsp(streamp);
nodep->dtypep(dstp->dtypep());
return true;
} else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) {
// The right stream operator on lhs of assignment statement does
@ -2245,17 +2235,18 @@ class ConstVisitor final : public VNVisitor {
srcp
= new AstSel{streamp->fileline(), srcp, sWidth - dstBitWidth, dstBitWidth};
}
srcp = new AstCvtPackedToUnpackArray{nodep->fileline(), srcp, dstp->dtypep()};
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstp->dtypep()};
} else {
UASSERT(sWidth >= dWidth, "sWidth >= dWidth should have caused an error earlier");
if (dWidth == 0) {
srcp = new AstCvtPackedToDynArray{nodep->fileline(), srcp, dstp->dtypep()};
srcp = new AstCvtPackedToArray{nodep->fileline(), srcp, dstp->dtypep()};
} else if (sWidth >= dWidth) {
srcp = new AstSel{streamp->fileline(), srcp, sWidth - dWidth, dWidth};
}
}
nodep->lhsp(dstp);
nodep->rhsp(srcp);
nodep->dtypep(dstp->dtypep());
VL_DO_DANGLING(pushDeletep(streamp), streamp);
// Further reduce, any of the nodes may have more reductions.
return true;
@ -2264,21 +2255,10 @@ class ConstVisitor final : public VNVisitor {
AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL);
AstNodeExpr* const srcp = streamp->lhsp();
const AstNodeDType* const srcDTypep = srcp->dtypep();
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) {
if (lhsDtypep->widthMin() > 64) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Assignment of stream of dynamic "
"array to a variable of size greater than 64");
}
srcp->unlinkFrBack();
streamp->lhsp(new AstCvtDynArrayToPacked{srcp->fileline(), srcp, lhsDtypep});
streamp->dtypeFrom(lhsDtypep);
} else if (VN_IS(srcDTypep, UnpackArrayDType)) {
if (lhsDtypep->widthMin() > 64) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Assignment of stream of unpacked "
"array to a variable of size greater than 64");
}
srcp->unlinkFrBack();
streamp->lhsp(new AstCvtUnpackArrayToPacked{srcp->fileline(), srcp, lhsDtypep});
if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)
|| VN_IS(srcDTypep, UnpackArrayDType)) {
streamp->lhsp(new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(),
nodep->dtypep()});
streamp->dtypeFrom(lhsDtypep);
}
} else if (m_doV && replaceAssignMultiSel(nodep)) {

View File

@ -385,32 +385,9 @@ public:
emitVarDecl(nodep);
}
void visit(AstCvtDynArrayToPacked* nodep) override {
putns(nodep, "VL_DYN_TO_");
emitIQW(nodep);
const AstNodeDType* const elemDTypep = nodep->fromp()->dtypep()->subDTypep();
putns(elemDTypep, "<");
putbs(elemDTypep->cType("", false, false));
puts(">(");
iterateAndNextConstNull(nodep->fromp());
puts(", ");
putns(elemDTypep, cvtToStr(elemDTypep->widthMin()));
puts(")");
}
void visit(AstCvtUnpackArrayToPacked* nodep) override {
putns(nodep, "VL_UNPACK_TO_");
emitIQW(nodep);
const AstNodeDType* const elemDTypep = nodep->fromp()->dtypep()->subDTypep();
putns(elemDTypep, "<");
putbs(elemDTypep->cType("", false, false));
puts(",");
puts(cvtToStr(nodep->fromp()->dtypep()->arrayUnpackedElements()));
puts(">(");
iterateAndNextConstNull(nodep->fromp());
puts(", ");
putns(elemDTypep, cvtToStr(elemDTypep->widthMin()));
puts(")");
void visit(AstCvtArrayToPacked* nodep) override {
AstNodeDType* const elemDTypep = nodep->fromp()->dtypep()->subDTypep();
emitOpName(nodep, nodep->emitC(), nodep->fromp(), elemDTypep, nullptr);
}
void visit(AstNodeAssign* nodep) override {
@ -467,30 +444,24 @@ public:
puts(cvtToStr(nodep->widthMin()) + ",");
iterateAndNextConstNull(nodep->lhsp());
puts(", ");
} else if (const AstCvtPackedToDynArray* const castp
= VN_CAST(nodep->rhsp(), CvtPackedToDynArray)) {
putns(castp, "VL_ASSIGN_DYN_Q<");
} else if (const AstCvtPackedToArray* const castp
= VN_CAST(nodep->rhsp(), CvtPackedToArray)) {
putns(castp, "VL_UNPACK_");
emitIQW(nodep->dtypep()->subDTypep());
emitIQW(castp->fromp());
puts("<");
putbs(castp->dtypep()->subDTypep()->cType("", false, false));
if (VN_IS(castp->dtypep(), UnpackArrayDType)) {
puts(", ");
puts(cvtToStr(castp->dtypep()->arrayUnpackedElements()));
}
puts(">(");
iterateAndNextConstNull(nodep->lhsp());
puts(", ");
putns(castp->dtypep(), cvtToStr(castp->dtypep()->subDTypep()->widthMin()));
puts(", ");
puts(cvtToStr(castp->fromp()->widthMin()));
puts(", ");
rhs = false;
iterateAndNextConstNull(castp->fromp());
} else if (const AstCvtPackedToUnpackArray* const castp
= VN_CAST(nodep->rhsp(), CvtPackedToUnpackArray)) {
putns(castp, "VL_ASSIGN_UNPACK_Q<");
putbs(castp->dtypep()->subDTypep()->cType("", false, false));
puts(", ");
puts(cvtToStr(castp->dtypep()->arrayUnpackedElements()));
puts(">(");
iterateAndNextConstNull(nodep->lhsp());
puts(", ");
putns(castp->dtypep(), cvtToStr(castp->dtypep()->subDTypep()->widthMin()));
puts(", ");
rhs = false;
iterateAndNextConstNull(castp->fromp());
} else if (nodep->isWide() && VN_IS(nodep->lhsp(), VarRef) //
@ -1298,8 +1269,7 @@ public:
return;
}
}
emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)", nodep->lhsp(), nodep->rhsp(),
nullptr);
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr);
}
void visit(AstCastDynamic* nodep) override {
putnbs(nodep, "VL_CAST_DYNAMIC(");

View File

@ -274,6 +274,10 @@ class PremitVisitor final : public VNVisitor {
iterateChildren(nodep);
checkNode(nodep);
}
void visit(AstCvtArrayToPacked* nodep) override {
iterateChildren(nodep);
checkNode(nodep);
}
void visit(AstSel* nodep) override {
iterateAndNextNull(nodep->fromp());
{ // Only the 'from' is part of the assignment LHS

View File

@ -228,7 +228,7 @@ class SliceVisitor final : public VNVisitor {
AstNodeDType* const dtp = nodep->lhsp()->dtypep()->skipRefp();
AstNode* stp = nodep->rhsp();
if (const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType)) {
if (!VN_IS(stp, CvtPackedToUnpackArray)) {
if (!VN_IS(stp, CvtPackedToArray)) {
// Left and right could have different ascending/descending range,
// but #elements is common and all variables are realigned to start at zero
// Assign of an ascending range slice to a descending range one must reverse

View File

@ -20,6 +20,12 @@ module t (/*AUTOARG*/);
bit [5:0] arr6[$];
bit [5:0] bit6 = 6'b111000;
bit [5:0] ans;
bit [3:0] arr4[] = '{25{4'b1000}};
bit [7:0] arr8[] = '{8{8'b00110011}};
bit [63:0] arr64[] = '{5{64'h0123456789abcdef}};
bit [63:0] bit64;
bit [99:0] bit100;
bit [319:0] bit320;
enum_t ans_enum;
{ >> bit {arr}} = bit6;
@ -76,6 +82,35 @@ module t (/*AUTOARG*/);
ans_enum = enum_t'({ << bit[5:0] {arr6} });
`checkh(ans_enum, bit6);
bit64 = { >> bit {arr8} };
`checkh(bit64[7:0], 8'b00110011);
bit64 = { << bit {arr8} };
`checkh(bit64[7:0], 8'b11001100);
{ >> bit {arr8} } = bit64;
`checkh(arr8[0], 8'b11001100);
{ << bit {arr8} } = bit64;
`checkh(arr8[0], 8'b00110011);
bit100 = { >> bit {arr4} };
`checkh(bit100[3:0], 4'b1000);
bit100 = { << bit {arr4} };
`checkh(bit100[3:0], 4'b0001);
bit320 = { >> byte {arr64} };
`checkh(bit320[63:0], 64'h0123456789abcdef);
bit320 = { << byte {arr64} };
`checkh(bit320[63:0], 64'hefcdab8967452301);
{ >> bit {arr4} } = bit100;
`checkh(arr4[0], 4'b0001);
{ << bit {arr4} } = bit100;
`checkh(arr4[0], 4'b1000);
{ >> byte {arr64} } = bit320;
`checkh(arr64[0], 64'hefcdab8967452301);
{ << byte {arr64} } = bit320;
`checkh(arr64[0], 64'h0123456789abcdef);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -1,10 +0,0 @@
%Error-UNSUPPORTED: t/t_stream_dynamic_wide_unsup.v:15:14: Unsupported: Assignment of stream of dynamic array to a variable of size greater than 64
: ... note: In instance 't'
15 | bit100 = { >> bit {arr} };
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_stream_dynamic_wide_unsup.v:17:14: Unsupported: Assignment of stream of dynamic array to a variable of size greater than 64
: ... note: In instance 't'
17 | bit100 = { << bit {arr} };
| ^
%Error: Exiting due to

View File

@ -1,19 +0,0 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2020 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -1,23 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
module t (/*AUTOARG*/);
initial begin
bit[3:0] arr[] = '{25{4'b1000}};
bit [99:0] bit100;
bit100 = { >> bit {arr} };
`checkh(bit100[3:0], 4'b1000);
bit100 = { << bit {arr} };
`checkh(bit100[3:0], 4'b0001);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
compile(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
execute(
check_finished => 1,
) if !$Self->{vlt_all};
);
ok(1);
1;

View File

@ -1,42 +0,0 @@
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:120:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
120 | packed_data_128 = {<<32{int_in}};
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:121:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
121 | packed_data_128_i = {<<32{integer_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:122:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
122 | packed_data_256 = {<<64{longint_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:123:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
123 | packed_time_256 = {<<64{time_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:126:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
126 | v_packed_data_128 = {<<32{reg_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:152:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
152 | packed_data_128 = {<<int{int_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:153:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
153 | packed_data_128_i = {<<integer{integer_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:154:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
154 | packed_data_256 = {<<longint{longint_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:155:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
155 | packed_time_256 = {<<time{time_in}};
| ^
%Error-UNSUPPORTED: t/t_stream_integer_type_unsup.v:158:28: Unsupported: Assignment of stream of unpacked array to a variable of size greater than 64
: ... note: In instance 't'
158 | v_packed_data_128 = {<<test_word{reg_in}};
| ^
%Error: Exiting due to