Internals: Make consistent left/right/lo/hi accessors to ranges.

Change order of Range to store always left:right.
XML output changes to now show left:right (previously info was lost), no other change intended.
This commit is contained in:
Wilson Snyder 2020-12-06 21:13:56 -05:00
parent b32d530000
commit cd248f6bd7
16 changed files with 177 additions and 206 deletions

View File

@ -981,61 +981,53 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) {
class VNumRange final { class VNumRange final {
public: public:
int m_hi = 0; // HI part, HI always >= LO int m_left = 0;
int m_lo = 0; // LO int m_right = 0;
union { bool m_ranged = false; // Has a range
int mu_flags;
struct {
bool m_ranged : 1; // Has a range
bool m_littleEndian : 1; // Bit vector is little endian
};
};
bool operator==(const VNumRange& rhs) const { bool operator==(const VNumRange& rhs) const {
return m_hi == rhs.m_hi && m_lo == rhs.m_lo && mu_flags == rhs.mu_flags; return m_left == rhs.m_left && m_right == rhs.m_right && m_ranged == rhs.m_ranged;
} }
bool operator<(const VNumRange& rhs) const { bool operator<(const VNumRange& rhs) const {
if ((m_hi < rhs.m_hi)) return true; if ((m_left < rhs.m_left)) return true;
if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs if (!(m_left == rhs.m_left)) return false; // lhs > rhs
if ((m_lo < rhs.m_lo)) return true; if ((m_right < rhs.m_right)) return true;
if (!(m_lo == rhs.m_lo)) return false; // lhs > rhs if (!(m_right == rhs.m_right)) return false; // lhs > rhs
if ((mu_flags < rhs.mu_flags)) return true; if ((m_ranged < rhs.m_ranged)) return true;
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs if (!(m_ranged == rhs.m_ranged)) return false; // lhs > rhs
return false; return false;
} }
// //
class LeftRight {}; VNumRange() {}
VNumRange() VNumRange(int hi, int lo, bool littleEndian) { init(hi, lo, littleEndian); }
: mu_flags{0} {} VNumRange(int left, int right)
VNumRange(int hi, int lo, bool littleEndian) : m_left{left}
: mu_flags{0} { , m_right{right}
init(hi, lo, littleEndian); , m_ranged{true} {}
}
VNumRange(LeftRight, int left, int right)
: mu_flags{0} {
init((right > left) ? right : left, (right > left) ? left : right, (right > left));
}
~VNumRange() = default; ~VNumRange() = default;
// MEMBERS // MEMBERS
void init(int hi, int lo, bool littleEndian) { void init(int hi, int lo, bool littleEndian) {
m_hi = hi; if (lo > hi) {
m_lo = lo; int t = hi;
mu_flags = 0; hi = lo;
lo = t;
}
m_left = littleEndian ? lo : hi;
m_right = littleEndian ? hi : lo;
m_ranged = true; m_ranged = true;
m_littleEndian = littleEndian;
} }
int hi() const { return m_hi; } int left() const { return m_left; }
int lo() const { return m_lo; } int right() const { return m_right; }
int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration int hi() const { return m_left > m_right ? m_left : m_right; } // How to show a declaration
int right() const { return littleEndian() ? hi() : lo(); } int lo() const { return m_left > m_right ? m_right : m_left; } // How to show a declaration
int leftToRightInc() const { return littleEndian() ? 1 : -1; } int leftToRightInc() const { return littleEndian() ? 1 : -1; }
int elements() const { return hi() - lo() + 1; } int elements() const { return hi() - lo() + 1; }
bool ranged() const { return m_ranged; } bool ranged() const { return m_ranged; }
bool littleEndian() const { return m_littleEndian; } bool littleEndian() const { return m_left < m_right; }
int hiMaxSelect() const { int hiMaxSelect() const {
return (lo() < 0 ? hi() - lo() : hi()); return (lo() < 0 ? hi() - lo() : hi());
} // Maximum value a [] select may index } // Maximum value a [] select may index
bool representableByWidth() const { // Could be represented by just width=1, or [width-1:0] bool representableByWidth() const { // Could be represented by just width=1, or [width-1:0]
return (!m_ranged || (m_lo == 0 && m_hi >= 1 && !m_littleEndian)); return (!m_ranged || (m_right == 0 && m_left >= 1));
} }
void dump(std::ostream& str) const { void dump(std::ostream& str) const {
if (ranged()) { if (ranged()) {
@ -2491,12 +2483,11 @@ public:
virtual void dump(std::ostream& str) const override; virtual void dump(std::ostream& str) const override;
// For basicp() we reuse the size to indicate a "fake" basic type of same size // For basicp() we reuse the size to indicate a "fake" basic type of same size
virtual AstBasicDType* basicp() const override { virtual AstBasicDType* basicp() const override {
return (isFourstate() ? VN_CAST( return (isFourstate()
findLogicRangeDType(VNumRange(width() - 1, 0, false), width(), numeric()), ? VN_CAST(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()),
BasicDType) BasicDType)
: VN_CAST(findBitRangeDType(VNumRange(width() - 1, 0, false), : VN_CAST(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()),
width(), numeric()), BasicDType));
BasicDType));
} }
virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
@ -2526,9 +2517,9 @@ public:
const auto it = m_members.find(name); const auto it = m_members.find(name);
return (it == m_members.end()) ? nullptr : it->second; return (it == m_members.end()) ? nullptr : it->second;
} }
static int lsb() { return 0; } static int lo() { return 0; }
int msb() const { return dtypep()->width() - 1; } // Packed classes look like arrays int hi() const { return dtypep()->width() - 1; } // Packed classes look like arrays
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); } VNumRange declRange() const { return VNumRange{hi(), lo()}; }
}; };
class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType { class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType {
@ -2554,17 +2545,17 @@ public:
} }
virtual bool same(const AstNode* samep) const override { virtual bool same(const AstNode* samep) const override {
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep); const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
return (msb() == asamep->msb() && subDTypep() == asamep->subDTypep() return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep()
&& rangenp()->sameTree(asamep->rangenp())); && rangenp()->sameTree(asamep->rangenp()));
} // HashedDT doesn't recurse, so need to check children } // HashedDT doesn't recurse, so need to check children
virtual bool similarDType(AstNodeDType* samep) const override { virtual bool similarDType(AstNodeDType* samep) const override {
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep); const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
return (asamep && type() == samep->type() && msb() == asamep->msb() return (asamep && type() == samep->type() && hi() == asamep->hi()
&& rangenp()->sameTree(asamep->rangenp()) && rangenp()->sameTree(asamep->rangenp())
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
} }
virtual V3Hash sameHash() const override { virtual V3Hash sameHash() const override {
return V3Hash(V3Hash(m_refDTypep), V3Hash(msb()), V3Hash(lsb())); return V3Hash(V3Hash(m_refDTypep), V3Hash(hi()), V3Hash(lo()));
} }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
@ -2588,8 +2579,10 @@ public:
virtual int widthTotalBytes() const override { virtual int widthTotalBytes() const override {
return elementsConst() * subDTypep()->widthTotalBytes(); return elementsConst() * subDTypep()->widthTotalBytes();
} }
int msb() const; int left() const;
int lsb() const; int right() const;
int hi() const;
int lo() const;
int elementsConst() const; int elementsConst() const;
VNumRange declRange() const; VNumRange declRange() const;
}; };
@ -3004,12 +2997,12 @@ inline void AstNodeVarRef::varp(AstVar* varp) {
inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); } inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); }
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); } inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); } inline int AstNodeArrayDType::left() const { return rangep()->leftConst(); }
inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); } inline int AstNodeArrayDType::right() const { return rangep()->rightConst(); }
inline int AstNodeArrayDType::hi() const { return rangep()->hiConst(); }
inline int AstNodeArrayDType::lo() const { return rangep()->loConst(); }
inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); } inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
inline VNumRange AstNodeArrayDType::declRange() const { inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right()}; }
return VNumRange(msb(), lsb(), rangep()->littleEndian());
}
inline const char* AstNodeFTaskRef::broken() const { inline const char* AstNodeFTaskRef::broken() const {
BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); BROKEN_RTN(m_taskp && !m_taskp->brokeExists());

View File

@ -185,46 +185,25 @@ public:
class AstRange final : public AstNodeRange { class AstRange final : public AstNodeRange {
// Range specification, for use under variables and cells // Range specification, for use under variables and cells
private:
bool m_littleEndian : 1; // Bit vector is little endian
public: public:
AstRange(FileLine* fl, AstNode* msbp, AstNode* lsbp) AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp)
: ASTGEN_SUPER(fl) { : ASTGEN_SUPER(fl) {
m_littleEndian = false; setOp2p(leftp);
setOp2p(msbp); setOp3p(rightp);
setOp3p(lsbp);
} }
AstRange(FileLine* fl, int msb, int lsb) AstRange(FileLine* fl, int left, int right)
: ASTGEN_SUPER(fl) { : ASTGEN_SUPER(fl) {
m_littleEndian = false; setOp2p(new AstConst(fl, left));
setOp2p(new AstConst(fl, msb)); setOp3p(new AstConst(fl, right));
setOp3p(new AstConst(fl, lsb));
} }
AstRange(FileLine* fl, const VNumRange& range) AstRange(FileLine* fl, const VNumRange& range)
: ASTGEN_SUPER(fl) { : ASTGEN_SUPER(fl) {
m_littleEndian = range.littleEndian(); setOp2p(new AstConst(fl, range.left()));
setOp2p(new AstConst(fl, range.hi())); setOp3p(new AstConst(fl, range.right()));
setOp3p(new AstConst(fl, range.lo()));
} }
ASTNODE_NODE_FUNCS(Range) ASTNODE_NODE_FUNCS(Range)
AstNode* msbp() const { return op2p(); } // op2 = Msb expression AstNode* leftp() const { return op2p(); }
AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression AstNode* rightp() const { return op3p(); }
AstNode* leftp() const {
return littleEndian() ? lsbp() : msbp();
} // How to show a declaration
AstNode* rightp() const { return littleEndian() ? msbp() : lsbp(); }
int msbConst() const {
AstConst* constp = VN_CAST(msbp(), Const);
return (constp ? constp->toSInt() : 0);
}
int lsbConst() const {
AstConst* constp = VN_CAST(lsbp(), Const);
return (constp ? constp->toSInt() : 0);
}
int elementsConst() const {
return (msbConst() > lsbConst()) ? msbConst() - lsbConst() + 1
: lsbConst() - msbConst() + 1;
}
int leftConst() const { int leftConst() const {
AstConst* constp = VN_CAST(leftp(), Const); AstConst* constp = VN_CAST(leftp(), Const);
return (constp ? constp->toSInt() : 0); return (constp ? constp->toSInt() : 0);
@ -233,9 +212,18 @@ public:
AstConst* constp = VN_CAST(rightp(), Const); AstConst* constp = VN_CAST(rightp(), Const);
return (constp ? constp->toSInt() : 0); return (constp ? constp->toSInt() : 0);
} }
int leftToRightInc() const { return littleEndian() ? 1 : -1; } int hiConst() const {
bool littleEndian() const { return m_littleEndian; } int l = leftConst();
void littleEndian(bool flag) { m_littleEndian = flag; } int r = rightConst();
return l > r ? l : r;
}
int loConst() const {
int l = leftConst();
int r = rightConst();
return l > r ? r : l;
}
int elementsConst() const { return hiConst() - loConst() + 1; }
bool littleEndian() const { return leftConst() < rightConst(); }
virtual void dump(std::ostream& str) const override; virtual void dump(std::ostream& str) const override;
virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual V3Hash sameHash() const override { return V3Hash(); } virtual V3Hash sameHash() const override { return V3Hash(); }
@ -924,22 +912,20 @@ public:
bool isDpiPrimitive() const { // DPI uses a primitive type bool isDpiPrimitive() const { // DPI uses a primitive type
return !isDpiBitVec() && !isDpiLogicVec(); return !isDpiBitVec() && !isDpiLogicVec();
} }
// Generally the msb/lsb/etc funcs should be used instead // Generally the lo/hi/left/right funcs should be used instead of nrange()
const VNumRange& nrange() const { return m.m_nrange; } const VNumRange& nrange() const { return m.m_nrange; }
int msb() const { return (rangep() ? rangep()->msbConst() : m.m_nrange.hi()); } int hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); }
int lsb() const { return (rangep() ? rangep()->lsbConst() : m.m_nrange.lo()); } int lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); }
int left() const { return littleEndian() ? lsb() : msb(); } // How to show a declaration int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration
int right() const { return littleEndian() ? msb() : lsb(); } int right() const { return littleEndian() ? hi() : lo(); }
bool littleEndian() const { bool littleEndian() const {
return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian());
} }
bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; } bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; }
VNumRange declRange() const { VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; }
return isRanged() ? VNumRange(msb(), lsb(), littleEndian()) : VNumRange();
}
void cvtRangeConst() { // Convert to smaller representation void cvtRangeConst() { // Convert to smaller representation
if (rangep() && VN_IS(rangep()->msbp(), Const) && VN_IS(rangep()->lsbp(), Const)) { if (rangep() && VN_IS(rangep()->leftp(), Const) && VN_IS(rangep()->rightp(), Const)) {
m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(), rangep()->littleEndian()); m.m_nrange = VNumRange{rangep()->leftConst(), rangep()->rightConst()};
rangep()->unlinkFrBackWithNext()->deleteTree(); rangep()->unlinkFrBackWithNext()->deleteTree();
rangep(nullptr); rangep(nullptr);
} }
@ -1658,8 +1644,8 @@ public:
AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp) AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp)
: ASTGEN_SUPER(fl, fromp, msbp, lsbp) {} : ASTGEN_SUPER(fl, fromp, msbp, lsbp) {}
ASTNODE_NODE_FUNCS(SelExtract) ASTNODE_NODE_FUNCS(SelExtract)
AstNode* msbp() const { return rhsp(); } AstNode* leftp() const { return rhsp(); }
AstNode* lsbp() const { return thsp(); } AstNode* rightp() const { return thsp(); }
}; };
class AstSelBit final : public AstNodePreSel { class AstSelBit final : public AstNodePreSel {

View File

@ -310,9 +310,9 @@ private:
const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant const ToggleEnt& above, AstVar* varp, AstVar* chgVarp) { // Constant
if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) { if (const AstBasicDType* bdtypep = VN_CAST(dtypep, BasicDType)) {
if (bdtypep->isRanged()) { if (bdtypep->isRanged()) {
for (int index_docs = bdtypep->lsb(); index_docs < bdtypep->msb() + 1; for (int index_docs = bdtypep->lo(); index_docs < bdtypep->hi() + 1;
index_docs++) { ++index_docs) {
int index_code = index_docs - bdtypep->lsb(); int index_code = index_docs - bdtypep->lo();
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true), new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code, 1), index_code, 1),
@ -325,8 +325,8 @@ private:
toggleVarBottom(above, varp); toggleVarBottom(above, varp);
} }
} else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { } else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) { for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) {
int index_code = index_docs - adtypep->lsb(); int index_code = index_docs - adtypep->lo();
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstArraySel(varp->fileline(), new AstArraySel(varp->fileline(),
above.m_varRefp->cloneTree(true), index_code), above.m_varRefp->cloneTree(true), index_code),
@ -337,9 +337,9 @@ private:
newent.cleanup(); newent.cleanup();
} }
} else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) { } else if (AstPackArrayDType* adtypep = VN_CAST(dtypep, PackArrayDType)) {
for (int index_docs = adtypep->lsb(); index_docs <= adtypep->msb(); ++index_docs) { for (int index_docs = adtypep->lo(); index_docs <= adtypep->hi(); ++index_docs) {
AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp(); AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
int index_code = index_docs - adtypep->lsb(); int index_code = index_docs - adtypep->lo();
ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]", ToggleEnt newent(above.m_comment + string("[") + cvtToStr(index_docs) + "]",
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true), new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code * subtypep->width(), subtypep->width()), index_code * subtypep->width(), subtypep->width()),

View File

@ -631,7 +631,7 @@ public:
putbs(", "); putbs(", ");
// Need real storage width // Need real storage width
puts(cvtToStr(nodep->memp()->dtypep()->subDTypep()->widthMin())); puts(cvtToStr(nodep->memp()->dtypep()->subDTypep()->widthMin()));
uint32_t array_lsb = 0; uint32_t array_lo = 0;
{ {
const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef);
if (!varrefp) { if (!varrefp) {
@ -642,9 +642,9 @@ public:
= VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) {
putbs(", "); putbs(", ");
puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements())); puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements()));
array_lsb = adtypep->lsb(); array_lo = adtypep->lo();
putbs(", "); putbs(", ");
puts(cvtToStr(array_lsb)); puts(cvtToStr(array_lo));
} else { } else {
nodep->v3error(nodep->verilogKwd() nodep->v3error(nodep->verilogKwd()
<< " loading other than unpacked/associative-array variable"); << " loading other than unpacked/associative-array variable");
@ -658,7 +658,7 @@ public:
if (nodep->lsbp()) { if (nodep->lsbp()) {
iterateAndNextNull(nodep->lsbp()); iterateAndNextNull(nodep->lsbp());
} else { } else {
puts(cvtToStr(array_lsb)); puts(cvtToStr(array_lo));
} }
putbs(", "); putbs(", ");
if (nodep->msbp()) { if (nodep->msbp()) {
@ -710,7 +710,7 @@ public:
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
putbs(","); putbs(",");
bool memory = false; bool memory = false;
uint32_t array_lsb = 0; uint32_t array_lo = 0;
uint32_t array_size = 0; uint32_t array_size = 0;
{ {
const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef);
@ -720,14 +720,14 @@ public:
} else if (const AstUnpackArrayDType* adtypep } else if (const AstUnpackArrayDType* adtypep
= VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) {
memory = true; memory = true;
array_lsb = adtypep->lsb(); array_lo = adtypep->lo();
array_size = adtypep->elementsConst(); array_size = adtypep->elementsConst();
} else { } else {
nodep->v3error(nodep->verilogKwd() nodep->v3error(nodep->verilogKwd()
<< " loading other than unpacked-array variable"); << " loading other than unpacked-array variable");
} }
} }
puts(cvtToStr(array_lsb)); puts(cvtToStr(array_lo));
putbs(","); putbs(",");
puts(cvtToStr(array_size)); puts(cvtToStr(array_size));
putbs(", "); putbs(", ");
@ -740,7 +740,7 @@ public:
if (nodep->startp()) { if (nodep->startp()) {
iterateAndNextNull(nodep->startp()); iterateAndNextNull(nodep->startp());
} else { } else {
puts(cvtToStr(array_lsb)); puts(cvtToStr(array_lo));
} }
putbs(", "); putbs(", ");
if (nodep->countp()) { if (nodep->countp()) {
@ -1789,7 +1789,7 @@ class EmitCImp final : EmitCStmts {
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1,
".atDefault()" + cvtarray); ".atDefault()" + cvtarray);
} else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { } else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
UASSERT_OBJ(adtypep->msb() >= adtypep->lsb(), varp, UASSERT_OBJ(adtypep->hi() >= adtypep->lo(), varp,
"Should have swapped msb & lsb earlier."); "Should have swapped msb & lsb earlier.");
string ivar = string("__Vi") + cvtToStr(depth); string ivar = string("__Vi") + cvtToStr(depth);
string pre = ("for (int " + ivar + "=" + cvtToStr(0) + "; " + ivar + "<" string pre = ("for (int " + ivar + "=" + cvtToStr(0) + "; " + ivar + "<"
@ -1921,7 +1921,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
emitDeclArrayBrackets(nodep); emitDeclArrayBrackets(nodep);
// If it's a packed struct/array then nodep->width is the whole // If it's a packed struct/array then nodep->width is the whole
// thing, msb/lsb is just lowest dimension // thing, msb/lsb is just lowest dimension
puts("," + cvtToStr(basicp->lsb() + nodep->width() - 1) + "," + cvtToStr(basicp->lsb())); puts("," + cvtToStr(basicp->lo() + nodep->width() - 1) + "," + cvtToStr(basicp->lo()));
if (nodep->isWide()) puts("," + cvtToStr(nodep->widthWords())); if (nodep->isWide()) puts("," + cvtToStr(nodep->widthWords()));
puts(");\n"); puts(");\n");
} else { } else {
@ -2600,7 +2600,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
for (AstUnpackArrayDType* arrayp = VN_CAST(elementp, UnpackArrayDType); for (AstUnpackArrayDType* arrayp = VN_CAST(elementp, UnpackArrayDType);
arrayp; arrayp = VN_CAST(elementp, UnpackArrayDType)) { arrayp; arrayp = VN_CAST(elementp, UnpackArrayDType)) {
int vecnum = vects++; int vecnum = vects++;
UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, UASSERT_OBJ(arrayp->hi() >= arrayp->lo(), varp,
"Should have swapped msb & lsb earlier."); "Should have swapped msb & lsb earlier.");
string ivar = string("__Vi") + cvtToStr(vecnum); string ivar = string("__Vi") + cvtToStr(vecnum);
puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(0)); puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(0));
@ -2687,11 +2687,11 @@ void EmitCImp::emitSensitives() {
arrayp; arrayp;
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
int vecnum = vects++; int vecnum = vects++;
UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, UASSERT_OBJ(arrayp->hi() >= arrayp->lo(), varp,
"Should have swapped msb & lsb earlier."); "Should have swapped msb & lsb earlier.");
string ivar = string("__Vi") + cvtToStr(vecnum); string ivar = string("__Vi") + cvtToStr(vecnum);
puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(arrayp->lsb())); puts("for (int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(arrayp->lo()));
puts("; " + ivar + "<=" + cvtToStr(arrayp->msb())); puts("; " + ivar + "<=" + cvtToStr(arrayp->hi()));
puts("; ++" + ivar + ") {\n"); puts("; ++" + ivar + ") {\n");
} }
puts("sensitive << " + varp->nameProtect()); puts("sensitive << " + varp->nameProtect());

View File

@ -752,9 +752,9 @@ void EmitCSyms::emitSymImp() {
// Range is always first, it's not in "C" order // Range is always first, it's not in "C" order
if (basicp->isRanged()) { if (basicp->isRanged()) {
bounds += " ,"; bounds += " ,";
bounds += cvtToStr(basicp->msb()); bounds += cvtToStr(basicp->hi());
bounds += ","; bounds += ",";
bounds += cvtToStr(basicp->lsb()); bounds += cvtToStr(basicp->lo());
pdim++; pdim++;
} }
for (AstNodeDType* dtypep = varp->dtypep(); dtypep;) { for (AstNodeDType* dtypep = varp->dtypep(); dtypep;) {
@ -762,9 +762,9 @@ void EmitCSyms::emitSymImp() {
= dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) {
bounds += " ,"; bounds += " ,";
bounds += cvtToStr(adtypep->msb()); bounds += cvtToStr(adtypep->hi());
bounds += ","; bounds += ",";
bounds += cvtToStr(adtypep->lsb()); bounds += cvtToStr(adtypep->lo());
if (VN_IS(dtypep, PackArrayDType)) { if (VN_IS(dtypep, PackArrayDType)) {
pdim++; pdim++;
} else { } else {

View File

@ -513,11 +513,11 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
virtual void visit(AstRange* nodep) override { virtual void visit(AstRange* nodep) override {
puts("["); puts("[");
if (VN_IS(nodep->msbp(), Const) && VN_IS(nodep->lsbp(), Const)) { if (VN_IS(nodep->leftp(), Const) && VN_IS(nodep->rightp(), Const)) {
// Looks nicer if we print [1:0] rather than [32'sh1:32sh0] // Looks nicer if we print [1:0] rather than [32'sh1:32sh0]
puts(cvtToStr(VN_CAST(nodep->leftp(), Const)->toSInt())); puts(cvtToStr(nodep->leftConst()));
puts(":"); puts(":");
puts(cvtToStr(VN_CAST(nodep->rightp(), Const)->toSInt())); puts(cvtToStr(nodep->rightConst()));
puts("]"); puts("]");
} else { } else {
iterateAndNextNull(nodep->leftp()); iterateAndNextNull(nodep->leftp());
@ -570,7 +570,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
puts(" "); puts(" ");
} else if (nodep->isRanged()) { } else if (nodep->isRanged()) {
puts(" ["); puts(" [");
puts(cvtToStr(nodep->msb())); puts(cvtToStr(nodep->hi()));
puts(":0] "); puts(":0] ");
} }
} }

View File

@ -207,7 +207,7 @@ private:
UINFO(8, " dv-vec-VAR " << nodep << endl); UINFO(8, " dv-vec-VAR " << nodep << endl);
AstUnpackArrayDType* arrdtype = VN_CAST(nodep->dtypep(), UnpackArrayDType); AstUnpackArrayDType* arrdtype = VN_CAST(nodep->dtypep(), UnpackArrayDType);
AstNode* prevp = nullptr; AstNode* prevp = nullptr;
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) { for (int i = arrdtype->lo(); i <= arrdtype->hi(); ++i) {
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__"; string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
UINFO(8, "VAR name insert " << varNewName << " " << nodep << endl); UINFO(8, "VAR name insert " << varNewName << " " << nodep << endl);
if (!m_deModVars.find(varNewName)) { if (!m_deModVars.find(varNewName)) {
@ -255,7 +255,7 @@ private:
for (int i = 0; i < m_cellRangep->elementsConst(); i++) { for (int i = 0; i < m_cellRangep->elementsConst(); i++) {
m_instSelNum m_instSelNum
= m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i; = m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i;
int instNum = m_cellRangep->lsbConst() + i; int instNum = m_cellRangep->loConst() + i;
AstCell* newp = nodep->cloneTree(false); AstCell* newp = nodep->cloneTree(false);
nodep->addNextHere(newp); nodep->addNextHere(newp);
@ -341,10 +341,11 @@ private:
// Arrayed instants: one bit for each of the instants (each // Arrayed instants: one bit for each of the instants (each
// assign is 1 pinwidth wide) // assign is 1 pinwidth wide)
if (m_cellRangep->littleEndian()) { if (m_cellRangep->littleEndian()) {
nodep->exprp()->v3warn(LITENDIAN, "Little endian cell range connecting to " nodep->exprp()->v3warn(
"vector: left < right of cell range: [" LITENDIAN,
<< m_cellRangep->leftConst() << ":" "Little endian cell range connecting to vector: left < right of cell range: ["
<< m_cellRangep->rightConst() << "]"); << m_cellRangep->leftConst() << ":" << m_cellRangep->rightConst()
<< "]");
} }
AstNode* exprp = nodep->exprp()->unlinkFrBack(); AstNode* exprp = nodep->exprp()->unlinkFrBack();
bool inputPin = nodep->modVarp()->isNonOutput(); bool inputPin = nodep->modVarp()->isNonOutput();
@ -396,7 +397,7 @@ private:
AstNode* prevPinp = nullptr; AstNode* prevPinp = nullptr;
// Clone the var referenced by the pin, and clone each var referenced by the varref // Clone the var referenced by the pin, and clone each var referenced by the varref
// Clone pin varp: // Clone pin varp:
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) { for (int i = pinArrp->lo(); i <= pinArrp->hi(); ++i) {
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__"; string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
AstVar* varNewp = nullptr; AstVar* varNewp = nullptr;
@ -529,7 +530,7 @@ public:
&& connectXRefp->varp()->isIfaceRef()) { && connectXRefp->varp()->isIfaceRef()) {
} else if (!alwaysCvt && connBasicp && pinBasicp } else if (!alwaysCvt && connBasicp && pinBasicp
&& connBasicp->width() == pinBasicp->width() && connBasicp->width() == pinBasicp->width()
&& connBasicp->lsb() == pinBasicp->lsb() && connBasicp->lo() == pinBasicp->lo()
&& !connectRefp->varp() && !connectRefp->varp()
->isSc() // Need the signal as a 'shell' to convert types ->isSc() // Need the signal as a 'shell' to convert types
&& connBasicp->width() == pinVarp->width()) { && connBasicp->width() == pinVarp->width()) {

View File

@ -151,16 +151,16 @@ private:
cleanFileline(nodep); cleanFileline(nodep);
iterateChildren(nodep); iterateChildren(nodep);
if (nodep->rangep()) { if (nodep->rangep()) {
if (!VN_IS(nodep->rangep()->msbp(), Const) // if (!VN_IS(nodep->rangep()->leftp(), Const) //
|| !VN_IS(nodep->rangep()->lsbp(), Const)) { || !VN_IS(nodep->rangep()->rightp(), Const)) {
nodep->v3error("Enum ranges must be integral, per spec"); nodep->v3error("Enum ranges must be integral, per spec");
} }
int msb = nodep->rangep()->msbConst(); int left = nodep->rangep()->leftConst();
int lsb = nodep->rangep()->lsbConst(); int right = nodep->rangep()->rightConst();
int increment = (msb > lsb) ? -1 : 1; int increment = (left > right) ? -1 : 1;
int offset_from_init = 0; int offset_from_init = 0;
AstNode* addp = nullptr; AstNode* addp = nullptr;
for (int i = msb; i != (lsb + increment); i += increment, offset_from_init++) { for (int i = left; i != (right + increment); i += increment, offset_from_init++) {
string name = nodep->name() + cvtToStr(i); string name = nodep->name() + cvtToStr(i);
AstNode* valuep = nullptr; AstNode* valuep = nullptr;
if (nodep->valuep()) { if (nodep->valuep()) {

View File

@ -152,7 +152,7 @@ private:
int msb = lsb + width - 1; int msb = lsb + width - 1;
V3Number fieldNum(nump, width); V3Number fieldNum(nump, width);
fieldNum.opSel(*nump, msb, lsb); fieldNum.opSel(*nump, msb, lsb);
int arrayElem = arrayp->lsb() + element; int arrayElem = arrayp->lo() + element;
out << arrayElem << " = " << prettyNumber(&fieldNum, childTypep); out << arrayElem << " = " << prettyNumber(&fieldNum, childTypep);
if (element < arrayElements - 1) out << ", "; if (element < arrayElements - 1) out << ", ";
} }

View File

@ -405,7 +405,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
static int outerMostSizeOfUnpackedArray(AstVar* nodep) { static int outerMostSizeOfUnpackedArray(AstVar* nodep) {
AstUnpackArrayDType* dtypep = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType); AstUnpackArrayDType* dtypep = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType);
UASSERT_OBJ(dtypep, nodep, "Must be unapcked array"); UASSERT_OBJ(dtypep, nodep, "Must be unapcked array");
return dtypep->msb() - dtypep->lsb() + 1; return dtypep->elementsConst();
} }
void setContextAndIterateChildren(AstNode* nodep) { void setContextAndIterateChildren(AstNode* nodep) {
@ -585,7 +585,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
const VNumRange selRange{nodep->declRange().hi() + dtypep->declRange().lo(), const VNumRange selRange{nodep->declRange().hi() + dtypep->declRange().lo(),
nodep->declRange().lo() + dtypep->declRange().lo(), nodep->declRange().lo() + dtypep->declRange().lo(),
nodep->declRange().littleEndian()}; nodep->declRange().littleEndian()};
UASSERT_OBJ(dtypep->lsb() <= selRange.lo() && selRange.hi() <= dtypep->msb(), nodep, UASSERT_OBJ(dtypep->lo() <= selRange.lo() && selRange.hi() <= dtypep->hi(), nodep,
"Range check for AstSliceSel must have been finished in V3Width.cpp"); "Range check for AstSliceSel must have been finished in V3Width.cpp");
UINFO(4, "add " << nodep << " for " << refp->varp()->prettyName() << "\n"); UINFO(4, "add " << nodep << " for " << refp->varp()->prettyName() << "\n");
m_refs.tryAdd(m_contextp, refp, nodep, nodep->declRange().hi(), m_refs.tryAdd(m_contextp, refp, nodep, nodep->declRange().hi(),
@ -614,12 +614,12 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
AstVar* varp = newVar(nodep->fileline(), AstVarType::VAR, name, dtypep); AstVar* varp = newVar(nodep->fileline(), AstVarType::VAR, name, dtypep);
// Variable will be registered in the caller side. // Variable will be registered in the caller side.
UINFO(3, varp->prettyNameQ() UINFO(3, varp->prettyNameQ()
<< " is created lsb:" << dtypep->lsb() << " msb:" << dtypep->msb() << "\n"); << " is created lsb:" << dtypep->lo() << " msb:" << dtypep->hi() << "\n");
// Use AstAssign if true, otherwise AstAssignW // Use AstAssign if true, otherwise AstAssignW
const bool use_simple_assign const bool use_simple_assign
= (context && VN_IS(context, NodeFTaskRef)) || (assignp && VN_IS(assignp, Assign)); = (context && VN_IS(context, NodeFTaskRef)) || (assignp && VN_IS(assignp, Assign));
for (int i = 0; i <= dtypep->msb() - dtypep->lsb(); ++i) { for (int i = 0; i < dtypep->elementsConst(); ++i) {
AstNode* lhsp = newVarRef(nodep->fileline(), vars.at(start_idx + i), AstNode* lhsp = newVarRef(nodep->fileline(), vars.at(start_idx + i),
lvalue ? VAccess::WRITE : VAccess::READ); lvalue ? VAccess::WRITE : VAccess::READ);
AstNode* rhsp = new AstArraySel( AstNode* rhsp = new AstArraySel(
@ -689,10 +689,10 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
const bool needNext = VN_IS(subTypep, UnpackArrayDType); // Still unpacked array. const bool needNext = VN_IS(subTypep, UnpackArrayDType); // Still unpacked array.
std::vector<AstVar*> vars; std::vector<AstVar*> vars;
// Add the split variables // Add the split variables
for (vlsint32_t i = 0; i <= dtypep->msb() - dtypep->lsb(); ++i) { for (vlsint32_t i = 0; i < dtypep->elementsConst(); ++i) {
// Unpacked array is traced as var(idx), not var[idx]. // Unpacked array is traced as var(idx), not var[idx].
const std::string name const std::string name
= varp->name() + AstNode::encodeName('(' + cvtToStr(i + dtypep->lsb()) + ')'); = varp->name() + AstNode::encodeName('(' + cvtToStr(i + dtypep->lo()) + ')');
AstVar* newp = newVar(varp->fileline(), AstVarType::VAR, name, subTypep); AstVar* newp = newVar(varp->fileline(), AstVarType::VAR, name, subTypep);
newp->propagateAttrFrom(varp); newp->propagateAttrFrom(varp);
// If varp is an IO, varp will remain and will be traced. // If varp is an IO, varp will remain and will be traced.
@ -722,7 +722,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
refp = VN_CAST(selp->fromp(), VarRef); refp = VN_CAST(selp->fromp(), VarRef);
UASSERT_OBJ(refp, selp, "Unexpected op is registered"); UASSERT_OBJ(refp, selp, "Unexpected op is registered");
adtypep = VN_CAST(selp->dtypep()->skipRefp(), UnpackArrayDType); adtypep = VN_CAST(selp->dtypep()->skipRefp(), UnpackArrayDType);
lsb = adtypep->lsb(); lsb = adtypep->lo();
} }
AstVarRef* newrefp = createTempVar(sit->context(), refp, adtypep, varp->name(), AstVarRef* newrefp = createTempVar(sit->context(), refp, adtypep, varp->name(),
vars, lsb, refp->access(), sit->ftask()); vars, lsb, refp->access(), sit->ftask());
@ -922,8 +922,8 @@ public:
points.emplace_back(std::make_pair(it->msb() + 1, true)); // End of a region points.emplace_back(std::make_pair(it->msb() + 1, true)); // End of a region
} }
if (skipUnused && !m_rhs.empty()) { // Range to be read must be kept, so add points here if (skipUnused && !m_rhs.empty()) { // Range to be read must be kept, so add points here
int lsb = m_basicp->msb() + 1; int lsb = m_basicp->hi() + 1;
int msb = m_basicp->lsb() - 1; int msb = m_basicp->lo() - 1;
for (size_t i = 0; i < m_rhs.size(); ++i) { for (size_t i = 0; i < m_rhs.size(); ++i) {
lsb = std::min(lsb, m_rhs[i].lsb()); lsb = std::min(lsb, m_rhs[i].lsb());
msb = std::max(msb, m_rhs[i].msb()); msb = std::max(msb, m_rhs[i].msb());
@ -933,8 +933,8 @@ public:
points.emplace_back(std::make_pair(msb + 1, true)); points.emplace_back(std::make_pair(msb + 1, true));
} }
if (!skipUnused) { // All bits are necessary if (!skipUnused) { // All bits are necessary
points.emplace_back(std::make_pair(m_basicp->lsb(), false)); points.emplace_back(std::make_pair(m_basicp->lo(), false));
points.emplace_back(std::make_pair(m_basicp->msb() + 1, true)); points.emplace_back(std::make_pair(m_basicp->hi() + 1, true));
} }
std::sort(points.begin(), points.end(), SortByFirst()); std::sort(points.begin(), points.end(), SortByFirst());
@ -985,10 +985,10 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
UASSERT_OBJ(!nodep->classOrPackagep(), nodep, UASSERT_OBJ(!nodep->classOrPackagep(), nodep,
"variable in package must have been dropped beforehand."); "variable in package must have been dropped beforehand.");
const AstBasicDType* basicp = refit->second.basicp(); const AstBasicDType* basicp = refit->second.basicp();
refit->second.append(PackedVarRefEntry(nodep, basicp->lsb(), varp->width()), refit->second.append(PackedVarRefEntry(nodep, basicp->lo(), varp->width()),
nodep->access()); nodep->access());
UINFO(5, varp->prettyName() UINFO(5, varp->prettyName()
<< " Entire bit of [" << basicp->lsb() << ":+" << varp->width() << "] \n"); << " Entire bit of [" << basicp->lo() << "+:" << varp->width() << "] \n");
} }
virtual void visit(AstSel* nodep) override { virtual void visit(AstSel* nodep) override {
AstVarRef* vrefp = VN_CAST(nodep->fromp(), VarRef); AstVarRef* vrefp = VN_CAST(nodep->fromp(), VarRef);
@ -1010,12 +1010,12 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
VN_CAST(nodep->widthp(), Const)}}; // GCC 3.8.0 wants {{}} VN_CAST(nodep->widthp(), Const)}}; // GCC 3.8.0 wants {{}}
if (consts[0] && consts[1]) { // OK if (consts[0] && consts[1]) { // OK
refit->second.append( refit->second.append(
PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(), PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lo(),
consts[1]->toUInt()), consts[1]->toUInt()),
vrefp->access()); vrefp->access());
UINFO(5, varp->prettyName() UINFO(5, varp->prettyName()
<< " [" << consts[0]->toSInt() << ":+" << consts[1]->toSInt() << " [" << consts[0]->toSInt() << ":+" << consts[1]->toSInt()
<< "] lsb:" << refit->second.basicp()->lsb() << "\n"); << "] lsb:" << refit->second.basicp()->lo() << "\n");
} else { } else {
nodep->v3warn(SPLITVAR, vrefp->prettyNameQ() nodep->v3warn(SPLITVAR, vrefp->prettyNameQ()
<< notSplitMsg << notSplitMsg
@ -1081,7 +1081,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
void createVars(AstVar* varp, const AstBasicDType* basicp, std::vector<SplitNewVar>& vars) { void createVars(AstVar* varp, const AstBasicDType* basicp, std::vector<SplitNewVar>& vars) {
for (size_t i = 0; i < vars.size(); ++i) { for (size_t i = 0; i < vars.size(); ++i) {
SplitNewVar* newvarp = &vars[i]; SplitNewVar* newvarp = &vars[i];
int left = newvarp->msb(), right = newvarp->lsb(); int left = newvarp->msb();
int right = newvarp->lsb();
if (basicp->littleEndian()) std::swap(left, right); if (basicp->littleEndian()) std::swap(left, right);
const std::string name const std::string name
= (left == right) = (left == right)
@ -1101,8 +1102,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
break; break;
default: UASSERT_OBJ(false, basicp, "Only bit and logic are allowed"); default: UASSERT_OBJ(false, basicp, "Only bit and logic are allowed");
} }
dtypep->rangep(new AstRange(varp->fileline(), newvarp->msb(), newvarp->lsb())); dtypep->rangep(new AstRange{varp->fileline(), VNumRange{newvarp->msb(), newvarp->lsb(),
dtypep->rangep()->littleEndian(basicp->littleEndian()); basicp->littleEndian()}});
newvarp->varp(new AstVar(varp->fileline(), AstVarType::VAR, name, dtypep)); newvarp->varp(new AstVar(varp->fileline(), AstVarType::VAR, name, dtypep));
newvarp->varp()->propagateAttrFrom(varp); newvarp->varp()->propagateAttrFrom(varp);
newvarp->varp()->funcLocal(varp->isFuncLocal() || varp->isFuncReturn()); newvarp->varp()->funcLocal(varp->isFuncLocal() || varp->isFuncReturn());

View File

@ -447,7 +447,8 @@ private:
FileLine* const flp = m_topScopep->fileline(); FileLine* const flp = m_topScopep->fileline();
AstNodeDType* const newScalarDtp = new AstBasicDType(flp, VFlagLogicPacked(), 1); AstNodeDType* const newScalarDtp = new AstBasicDType(flp, VFlagLogicPacked(), 1);
v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp); v3Global.rootp()->typeTablep()->addTypesp(newScalarDtp);
AstRange* const newArange = new AstRange(flp, VNumRange(m_activityNumber - 1, 0, false)); AstRange* const newArange
= new AstRange{flp, VNumRange{static_cast<int>(m_activityNumber) - 1, 0}};
AstNodeDType* const newArrDtp = new AstUnpackArrayDType(flp, newScalarDtp, newArange); AstNodeDType* const newArrDtp = new AstUnpackArrayDType(flp, newScalarDtp, newArange);
v3Global.rootp()->typeTablep()->addTypesp(newArrDtp); v3Global.rootp()->typeTablep()->addTypesp(newArrDtp);
AstVar* const newvarp AstVar* const newvarp

View File

@ -99,7 +99,7 @@ private:
// misreflects one element // misreflects one element
VNumRange bitRange; VNumRange bitRange;
if (widthOverride) { if (widthOverride) {
bitRange = VNumRange(widthOverride - 1, 0, false); bitRange = VNumRange{widthOverride - 1, 0};
} else if (const AstBasicDType* const bdtypep = m_traValuep->dtypep()->basicp()) { } else if (const AstBasicDType* const bdtypep = m_traValuep->dtypep()->basicp()) {
bitRange = bdtypep->nrange(); bitRange = bdtypep->nrange();
} }
@ -238,13 +238,13 @@ private:
} else { } else {
// Unroll now, as have no other method to get right signal names // Unroll now, as have no other method to get right signal names
AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump();
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) { for (int i = nodep->lo(); i <= nodep->hi(); ++i) {
VL_RESTORER(m_traShowname); VL_RESTORER(m_traShowname);
VL_RESTORER(m_traValuep); VL_RESTORER(m_traValuep);
{ {
m_traShowname += string("(") + cvtToStr(i) + string(")"); m_traShowname += string("(") + cvtToStr(i) + string(")");
m_traValuep = new AstArraySel( m_traValuep = new AstArraySel(
nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lsb()); nodep->fileline(), m_traValuep->cloneTree(true), i - nodep->lo());
m_traValuep->dtypep(subtypep); m_traValuep->dtypep(subtypep);
iterate(subtypep); iterate(subtypep);
@ -263,14 +263,14 @@ private:
addTraceDecl(VNumRange(), nodep->width()); addTraceDecl(VNumRange(), nodep->width());
} else { } else {
AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump();
for (int i = nodep->lsb(); i <= nodep->msb(); ++i) { for (int i = nodep->lo(); i <= nodep->hi(); ++i) {
VL_RESTORER(m_traShowname); VL_RESTORER(m_traShowname);
VL_RESTORER(m_traValuep); VL_RESTORER(m_traValuep);
{ {
m_traShowname += string("(") + cvtToStr(i) + string(")"); m_traShowname += string("(") + cvtToStr(i) + string(")");
m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), m_traValuep
(i - nodep->lsb()) * subtypep->width(), = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
subtypep->width()); (i - nodep->lo()) * subtypep->width(), subtypep->width());
m_traValuep->dtypep(subtypep); m_traValuep->dtypep(subtypep);
iterate(subtypep); iterate(subtypep);
VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr); VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr);

View File

@ -90,14 +90,14 @@ private:
int lsb = bit + 1; int lsb = bit + 1;
if (bits != "") bits += ","; if (bits != "") bits += ",";
if (lsb == msb) { if (lsb == msb) {
bits += cvtToStr(lsb + bdtypep->lsb()); bits += cvtToStr(lsb + bdtypep->lo());
} else { } else {
if (bdtypep->littleEndian()) { if (bdtypep->littleEndian()) {
bits += cvtToStr(lsb + bdtypep->lsb()) + ":" bits
+ cvtToStr(msb + bdtypep->lsb()); += cvtToStr(lsb + bdtypep->lo()) + ":" + cvtToStr(msb + bdtypep->lo());
} else { } else {
bits += cvtToStr(msb + bdtypep->lsb()) + ":" bits
+ cvtToStr(lsb + bdtypep->lsb()); += cvtToStr(msb + bdtypep->lo()) + ":" + cvtToStr(lsb + bdtypep->lo());
} }
} }
prev = false; prev = false;

View File

@ -752,21 +752,10 @@ private:
// Signed: unsigned output, input either // Signed: unsigned output, input either
// Convert all range values to constants // Convert all range values to constants
UINFO(6, "RANGE " << nodep << endl); UINFO(6, "RANGE " << nodep << endl);
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node V3Const::constifyParamsEdit(nodep->leftp()); // May relink pointed to node
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node V3Const::constifyParamsEdit(nodep->rightp()); // May relink pointed to node
checkConstantOrReplace(nodep->msbp(), "MSB of bit range isn't a constant"); checkConstantOrReplace(nodep->leftp(), "left side of bit range isn't a constant");
checkConstantOrReplace(nodep->lsbp(), "LSB of bit range isn't a constant"); checkConstantOrReplace(nodep->rightp(), "right side of bit range isn't a constant");
int msb = nodep->msbConst();
int lsb = nodep->lsbConst();
if (msb < lsb) {
// Little endian bits are legal, just remember to swap
// Warning is in V3Width to avoid false warnings when in "off" generate if's
nodep->littleEndian(!nodep->littleEndian());
// Internally we'll always have msb() be the greater number
// We only need to correct when doing [] AstSel extraction,
// and when tracing the vector.
nodep->msbp()->swapWith(nodep->lsbp());
}
if (m_vup->prelim()) { if (m_vup->prelim()) {
// Don't need to iterate because V3Const already constified // Don't need to iterate because V3Const already constified
int width = nodep->elementsConst(); int width = nodep->elementsConst();
@ -807,7 +796,7 @@ private:
int width = nodep->widthConst(); int width = nodep->widthConst();
UASSERT_OBJ(nodep->dtypep(), nodep, "dtype wasn't set"); // by V3WidthSel UASSERT_OBJ(nodep->dtypep(), nodep, "dtype wasn't set"); // by V3WidthSel
if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) { if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: MSB < LSB of bit extract: " nodep->v3warn(E_UNSUPPORTED, "Unsupported: left < right of bit extract: "
<< nodep->msbConst() << "<" << nodep->lsbConst()); << nodep->msbConst() << "<" << nodep->lsbConst());
width = (nodep->lsbConst() - nodep->msbConst() + 1); width = (nodep->lsbConst() - nodep->msbConst() + 1);
nodep->dtypeSetLogicSized(width, VSigning::UNSIGNED); nodep->dtypeSetLogicSized(width, VSigning::UNSIGNED);
@ -903,8 +892,8 @@ private:
int fromlsb; int fromlsb;
AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp(); AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp();
if (const AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { if (const AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) {
frommsb = adtypep->msb(); frommsb = adtypep->hi();
fromlsb = adtypep->lsb(); fromlsb = adtypep->lo();
if (fromlsb > frommsb) { if (fromlsb > frommsb) {
int t = frommsb; int t = frommsb;
frommsb = fromlsb; frommsb = fromlsb;
@ -1929,7 +1918,7 @@ private:
// "foo[0]" from a parameter but not a wire // "foo[0]" from a parameter but not a wire
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(), nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),
VSigning::fromBool(issigned)); VSigning::fromBool(issigned));
nodep->dtypep(nodep->findLogicRangeDType(VNumRange(0, 0, false), nodep->dtypep(nodep->findLogicRangeDType(VNumRange{0, 0},
nodep->valuep()->widthMin(), nodep->valuep()->widthMin(),
VSigning::fromBool(issigned))); VSigning::fromBool(issigned)));
} else { } else {

View File

@ -96,8 +96,8 @@ private:
} else if (adtypep->isRanged()) { } else if (adtypep->isRanged()) {
UASSERT_OBJ( UASSERT_OBJ(
!(adtypep->rangep() !(adtypep->rangep()
&& (!VN_IS(adtypep->rangep()->msbp(), Const) && (!VN_IS(adtypep->rangep()->leftp(), Const)
|| !VN_IS(adtypep->rangep()->lsbp(), Const))), || !VN_IS(adtypep->rangep()->rightp(), Const))),
nodep, nodep,
"Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep) "Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep)
fromRange = adtypep->declRange(); fromRange = adtypep->declRange();
@ -324,12 +324,12 @@ private:
UINFO(6, "SELEXTRACT " << nodep << endl); UINFO(6, "SELEXTRACT " << nodep << endl);
// if (debug() >= 9) nodep->dumpTree(cout, "--SELEX0: "); // if (debug() >= 9) nodep->dumpTree(cout, "--SELEX0: ");
// Below 2 lines may change nodep->widthp() // Below 2 lines may change nodep->widthp()
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node V3Const::constifyParamsEdit(nodep->leftp()); // May relink pointed to node
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node V3Const::constifyParamsEdit(nodep->rightp()); // May relink pointed to node
// if (debug() >= 9) nodep->dumpTree(cout, "--SELEX3: "); // if (debug() >= 9) nodep->dumpTree(cout, "--SELEX3: ");
checkConstantOrReplace(nodep->lsbp(), checkConstantOrReplace(nodep->leftp(),
"First value of [a:b] isn't a constant, maybe you want +: or -:"); "First value of [a:b] isn't a constant, maybe you want +: or -:");
checkConstantOrReplace(nodep->msbp(), checkConstantOrReplace(nodep->rightp(),
"Second value of [a:b] isn't a constant, maybe you want +: or -:"); "Second value of [a:b] isn't a constant, maybe you want +: or -:");
AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* fromp = nodep->lhsp()->unlinkFrBack();
AstNode* msbp = nodep->rhsp()->unlinkFrBack(); AstNode* msbp = nodep->rhsp()->unlinkFrBack();
@ -351,9 +351,9 @@ private:
nodep->replaceWith(newp); nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else { // Slice } else { // Slice
AstSliceSel* newp = new AstSliceSel( AstSliceSel* newp
nodep->fileline(), fromp, = new AstSliceSel{nodep->fileline(), fromp,
VNumRange(VNumRange::LeftRight(), msb - fromRange.lo(), lsb - fromRange.lo())); VNumRange{msb - fromRange.lo(), lsb - fromRange.lo()}};
nodep->replaceWith(newp); nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }

View File

@ -72,8 +72,8 @@
<refdtype fl="d31" loc="d,31,4,31,13" id="16" name="my_struct" sub_dtype_id="2"/> <refdtype fl="d31" loc="d,31,4,31,13" id="16" name="my_struct" sub_dtype_id="2"/>
<unpackarraydtype fl="d31" loc="d,31,26,31,27" id="4" sub_dtype_id="2"> <unpackarraydtype fl="d31" loc="d,31,26,31,27" id="4" sub_dtype_id="2">
<range fl="d31" loc="d,31,26,31,27"> <range fl="d31" loc="d,31,26,31,27">
<const fl="d31" loc="d,31,27,31,28" name="32&apos;h1" dtype_id="5"/>
<const fl="d31" loc="d,31,27,31,28" name="32&apos;h0" dtype_id="5"/> <const fl="d31" loc="d,31,27,31,28" name="32&apos;h0" dtype_id="5"/>
<const fl="d31" loc="d,31,27,31,28" name="32&apos;h1" dtype_id="5"/>
</range> </range>
</unpackarraydtype> </unpackarraydtype>
<basicdtype fl="d35" loc="d,35,21,35,27" id="7" name="string"/> <basicdtype fl="d35" loc="d,35,21,35,27" id="7" name="string"/>