Internals: Add range Left/Right/Lo/Hi iterable sequences (#8585)

This commit is contained in:
Geza Lore
2026-10-02 20:19:10 +01:00
committed by GitHub
parent e7abfa391b
commit 5c9a804e8b
8 changed files with 56 additions and 26 deletions
+36
View File
@@ -1815,6 +1815,34 @@ inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) {
class VNumRange final {
public:
// Iterable sequence of integers
class Sequence final {
class Iterator final {
int m_index; // Current index
const int m_inc; // Step, +1 or -1
public:
Iterator(int index, int inc)
: m_index{index}
, m_inc{inc} {}
int operator*() const { return m_index; }
Iterator& operator++() {
m_index += m_inc;
return *this;
}
bool operator!=(const Iterator& that) const { return m_index != that.m_index; }
};
const int m_begin; // First index
const int m_end; // One past the last index
const int m_inc; // Step, +1 or -1
public:
Sequence(int first, int last, int inc)
: m_begin{first}
, m_end{last + inc}
, m_inc{inc} {}
Iterator begin() const { return Iterator{m_begin, m_inc}; }
Iterator end() const { return Iterator{m_end, m_inc}; }
};
int m_left = 0; // Left side of range (pre-':')
int m_right = 0; // Right side of range (post-':')
bool m_ranged = false; // Has a range
@@ -1854,6 +1882,14 @@ public:
return m_left > m_right ? m_right : m_left;
} // How to show a declaration
int leftToRightInc() const { return ascending() ? 1 : -1; }
// Iterate indices from left() to right() inclusive: 'for (int i : range.seqLeftToRight())'
Sequence seqLeftToRight() const { return {m_left, m_right, leftToRightInc()}; }
// Iterate indices from right() to left() inclusive: 'for (int i : range.seqRightToLeft())'
Sequence seqRightToLeft() const { return {m_right, m_left, -leftToRightInc()}; }
// Iterate indices from lo() to hi() inclusive: 'for (int i : range.seqLoToHi())'
Sequence seqLoToHi() const { return {lo(), hi(), 1}; }
// Iterate indices from hi() to lo() inclusive: 'for (int i : range.seqHiToLo())'
Sequence seqHiToLo() const { return {hi(), lo(), -1}; }
int elements() const VL_MT_SAFE { return hi() - lo() + 1; }
bool ranged() const { return m_ranged; }
bool ascending() const { return m_left < m_right; }
+8
View File
@@ -3420,6 +3420,14 @@ public:
}
int elementsConst() const VL_MT_STABLE { return hiConst() - loConst() + 1; }
bool ascending() const { return leftConst() < rightConst(); }
// Iterate indices from left to right inclusive, see VNumRange::seqLeftToRight()
VNumRange::Sequence seqLeftToRight() const {
return VNumRange{leftConst(), rightConst()}.seqLeftToRight();
}
// Iterate indices from right to left inclusive, see VNumRange::seqRightToLeft()
VNumRange::Sequence seqRightToLeft() const {
return VNumRange{leftConst(), rightConst()}.seqRightToLeft();
}
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
virtual string emitC() { V3ERROR_NA_RETURN(""); }
+1 -5
View File
@@ -1015,14 +1015,10 @@ class ConstVisitor final : public VNVisitor {
const bool packReal) {
const AstNodeDType* const dtypep = fromp->dtypep()->skipRefp();
if (const AstUnpackArrayDType* const unpackDtypep = VN_CAST(dtypep, UnpackArrayDType)) {
const int left = unpackDtypep->left();
const int right = unpackDtypep->right();
const int step = left <= right ? 1 : -1;
for (int idx = left;; idx += step) {
for (const int idx : unpackDtypep->declRange().seqLeftToRight()) {
AstArraySel* const selp
= new AstArraySel{fromp->fileline(), fromp->cloneTreePure(false), idx};
collectFixedAggregateTerms(selp, termps, packReal);
if (idx == right) break;
}
VL_DO_DANGLING(pushDeletep(fromp), fromp);
} else if (const AstNodeUOrStructDType* const sdtypep
+2 -2
View File
@@ -461,7 +461,7 @@ class CoverageVisitor final : public VNVisitor {
if (const AstBasicDType* const basicp = VN_CAST(dtypep, BasicDType)) {
toggleVarBottom(above, varp, basicp->nrange());
} else if (const AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) {
for (const int index_docs : adtypep->declRange().seqLoToHi()) {
const int index_code = index_docs - adtypep->lo();
ToggleEnt newent{above.m_comment + "["s + cvtToStr(index_docs) + "]",
new AstArraySel{varp->fileline(),
@@ -472,7 +472,7 @@ class CoverageVisitor final : public VNVisitor {
newent.cleanup();
}
} else if (const AstPackArrayDType* const adtypep = VN_CAST(dtypep, PackArrayDType)) {
for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) {
for (const int index_docs : adtypep->declRange().seqLoToHi()) {
const AstNodeDType* const subtypep = adtypep->subDTypep()->skipRefp();
const int index_code = index_docs - adtypep->lo();
ToggleEnt newent{above.m_comment + "["s + cvtToStr(index_docs) + "]",
+2 -4
View File
@@ -335,13 +335,10 @@ class LinkParseVisitor final : public VNVisitor {
// We check this rule in the parser, so shouldn't fire
nodep->v3error("Enum ranges must be integral, per spec");
} // LCOV_EXCL_STOP
const int left = nodep->rangep()->leftConst();
const int right = nodep->rangep()->rightConst();
const int increment = (left > right) ? -1 : 1;
uint32_t offset_from_init = 0;
AstEnumItem* addp = nullptr;
FileLine* const flp = nodep->fileline();
for (int i = left; i != (right + increment); i += increment, ++offset_from_init) {
for (const int i : nodep->rangep()->seqLeftToRight()) {
const string name = nodep->name() + cvtToStr(i);
AstNodeExpr* valuep = nullptr;
if (nodep->valuep()) {
@@ -351,6 +348,7 @@ class LinkParseVisitor final : public VNVisitor {
new AstConst{flp, AstConst::Unsized32{}, offset_from_init}};
}
addp = AstNode::addNext(addp, new AstEnumItem{flp, name, nullptr, valuep});
++offset_from_init;
}
nodep->replaceWith(addp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
+2 -8
View File
@@ -2966,10 +2966,7 @@ class ParamVisitor final : public VNVisitor {
// Enumerate the current dimension given by 'arrp'
// Each element is added right after 'portp', so go from right to left,
// to end with an enumeration from the left index to the right index.
const int left = arrp->left();
const int right = arrp->right();
const int step = arrp->declRange().ascending() ? 1 : -1;
for (int n = right; n != left - step; n -= step) {
for (const int n : arrp->declRange().seqRightToLeft()) {
const std::string s = suffix + "__BRA__" + AstNode::encodeNumber(n) + "__KET__";
expandIfaceArrayPortDimensions(portp, arrp->subDTypep(), s);
}
@@ -3011,12 +3008,9 @@ class ParamVisitor final : public VNVisitor {
// Enumerate the current dimension given by 'rangep'
// Each element is added right after 'arrayedCellp', so go from right to left,
// to end with an enumeration from the left index to the right index.
const int left = rangep->leftConst();
const int right = rangep->rightConst();
const int step = rangep->ascending() ? 1 : -1;
idx = (idx + 1) * rangep->elementsConst();
const AstRange* const subRangep = VN_AS(rangep->nextp(), Range);
for (int n = right; n != left - step; n -= step) {
for (const int n : rangep->seqRightToLeft()) {
const std::string s = suffix + "__BRA__" + AstNode::encodeNumber(n) + "__KET__";
expandCellArrayDimensions(arrayedCellp, ifaceVarp, subRangep, s, --idx);
}
+2 -4
View File
@@ -558,8 +558,7 @@ class TraceDeclVisitor final : public VNVisitor {
} else {
AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump();
// Always iterate left index to right index
const int inc = nodep->rangep()->ascending() ? 1 : -1;
for (int i = nodep->left(); i != nodep->right() + inc; i += inc) {
for (const int i : nodep->declRange().seqLeftToRight()) {
VL_RESTORER(m_traValuep);
m_traName = '[' + std::to_string(i) + ']';
m_traValuep = m_traValuep->cloneTree(false);
@@ -583,8 +582,7 @@ class TraceDeclVisitor final : public VNVisitor {
nodep->left(), nodep->right(), !newFunc});
// Always iterate left index to right index
const int inc = nodep->rangep()->ascending() ? 1 : -1;
for (int i = nodep->left(); i != nodep->right() + inc; i += inc) {
for (const int i : nodep->declRange().seqLeftToRight()) {
VL_RESTORER(m_traValuep);
m_traName = '[' + std::to_string(i) + ']';
const int lsb = (i - nodep->lo()) * subtypep->width();
+3 -3
View File
@@ -6349,7 +6349,7 @@ class WidthVisitor final : public VNVisitor {
PatVecMap patmap = patVectorMap(nodep, range);
UINFO(9, "ent " << range.hi() << " to " << range.lo());
AstNodeExpr* newp = nullptr;
for (int ent = range.hi(); ent >= range.lo(); --ent) {
for (const int ent : range.seqHiToLo()) {
AstPatMember* newpatp = nullptr;
AstPatMember* patp = nullptr;
const auto it = patmap.find(ent);
@@ -9646,7 +9646,7 @@ class WidthVisitor final : public VNVisitor {
AstInitArray* newp = new AstInitArray{
constp->fileline(), lhsDTypep,
new AstConst{constp->fileline(), AstConst::WidthedValue{}, 8, 0}};
for (int aindex = arrayp->lo(); aindex <= arrayp->hi(); ++aindex) {
for (const int aindex : arrayp->declRange().seqLoToHi()) {
int cindex = arrayp->declRange().ascending() ? (arrayp->hi() - aindex)
: (aindex - arrayp->lo());
V3Number selected{constp, 8};
@@ -10828,7 +10828,7 @@ class WidthVisitor final : public VNVisitor {
// as the element variables are in that order, indexed from lo
AstInitArray* const initp = new AstInitArray{flp, arrp, nullptr};
const VNumRange range = arrp->declRange();
for (int n = 0, i = range.left(); n < range.elements(); ++n, i += range.leftToRightInc()) {
for (const int i : range.seqLeftToRight()) {
const std::string s = name + "__BRA__" + AstNode::encodeNumber(i) + "__KET__";
initp->addIndexValuep(
i - range.lo(), newIfaceArrayInit(refp, arrp->subDTypep(), s, suffix, elemVarpr));