mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Fix +: and -: on unpacked arrays. (#2304)
This commit is contained in:
+38
-3
@@ -191,6 +191,13 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void warnTri(AstNode* nodep) {
|
||||
if (VN_IS(nodep, Const) && VN_CAST(nodep, Const)->num().isFourState()) {
|
||||
nodep->v3error(
|
||||
"Selection index is constantly unknown or tristated: " << nodep->name());
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
// If adding new visitors, ensure V3Width's visit(TYPE) calls into here
|
||||
|
||||
@@ -451,6 +458,7 @@ private:
|
||||
UINFO(6, "SELPLUS/MINUS " << nodep << endl);
|
||||
// Below 2 lines may change nodep->widthp()
|
||||
if (debug() >= 9) nodep->dumpTree(cout, "--SELPM0: ");
|
||||
V3Const::constifyEdit(nodep->rhsp()); // May relink pointed to node, ok if not const
|
||||
V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node
|
||||
checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant");
|
||||
if (debug() >= 9) nodep->dumpTree(cout, "--SELPM3: ");
|
||||
@@ -458,6 +466,7 @@ private:
|
||||
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->thsp()->unlinkFrBack();
|
||||
warnTri(rhsp);
|
||||
int width = VN_CAST(widthp, Const)->toSInt();
|
||||
if (width > (1 << 28)) {
|
||||
nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "
|
||||
@@ -467,9 +476,35 @@ private:
|
||||
FromData fromdata = fromDataForArray(nodep, fromp);
|
||||
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
||||
VNumRange fromRange = fromdata.m_fromRange;
|
||||
if (VN_IS(ddtypep, BasicDType) || VN_IS(ddtypep, PackArrayDType)
|
||||
|| (VN_IS(ddtypep, NodeUOrStructDType)
|
||||
&& VN_CAST(ddtypep, NodeUOrStructDType)->packedUnsup())) {
|
||||
if (VN_IS(ddtypep, UnpackArrayDType)) {
|
||||
// Slice +: and -: extraction
|
||||
if (fromRange.elements() == width && VN_IS(rhsp, Const)
|
||||
&& VN_CAST(rhsp, Const)->toSInt()
|
||||
== fromRange.lo()) { // Extracting whole of original array
|
||||
nodep->replaceWith(fromp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else if (fromRange.elements() == 1) { // Extracting single element
|
||||
AstArraySel* newp = new AstArraySel(nodep->fileline(), fromp, rhsp);
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else if (VN_IS(rhsp, Const)) { // Slice
|
||||
vlsint32_t rhs = VN_CAST(rhsp, Const)->toSInt();
|
||||
// down array: lsb/lo +: width
|
||||
// down array: msb/hi -: width
|
||||
// up array: msb/lo +: width
|
||||
// up array: lsb/hi -: width
|
||||
vlsint32_t msb = VN_IS(nodep, SelPlus) ? rhs + width - 1 : rhs;
|
||||
vlsint32_t lsb = VN_IS(nodep, SelPlus) ? rhs : rhs - width + 1;
|
||||
AstSliceSel* newp = new AstSliceSel(nodep->fileline(), fromp,
|
||||
VNumRange(msb, lsb, fromRange.littleEndian()));
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else {
|
||||
nodep->v3error("Unsupported: Slice of non-constant bounds");
|
||||
}
|
||||
} else if (VN_IS(ddtypep, BasicDType) || VN_IS(ddtypep, PackArrayDType)
|
||||
|| (VN_IS(ddtypep, NodeUOrStructDType)
|
||||
&& VN_CAST(ddtypep, NodeUOrStructDType)->packedUnsup())) {
|
||||
int elwidth = 1;
|
||||
AstNode* newwidthp = widthp;
|
||||
if (const AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) {
|
||||
|
||||
Reference in New Issue
Block a user