mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Support streaming operator on arrays and wide data (#5326)
Signed-off-by: Arkadiusz Kozdra <akozdra@antmicro.com>
This commit is contained in:
parent
3b81654c72
commit
a32b8d80f9
@ -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 {
|
||||
|
@ -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; }
|
||||
};
|
||||
|
@ -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)) {
|
||||
|
@ -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(");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
@ -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
|
@ -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;
|
@ -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
|
Loading…
Reference in New Issue
Block a user