mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Internals: Add range Left/Right/Lo/Hi iterable sequences (#8585)
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user