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

View File

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

View File

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

View File

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

View File

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

View File

@ -513,11 +513,11 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
}
virtual void visit(AstRange* nodep) override {
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]
puts(cvtToStr(VN_CAST(nodep->leftp(), Const)->toSInt()));
puts(cvtToStr(nodep->leftConst()));
puts(":");
puts(cvtToStr(VN_CAST(nodep->rightp(), Const)->toSInt()));
puts(cvtToStr(nodep->rightConst()));
puts("]");
} else {
iterateAndNextNull(nodep->leftp());
@ -570,7 +570,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
puts(" ");
} else if (nodep->isRanged()) {
puts(" [");
puts(cvtToStr(nodep->msb()));
puts(cvtToStr(nodep->hi()));
puts(":0] ");
}
}

View File

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

View File

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

View File

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

View File

@ -405,7 +405,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
static int outerMostSizeOfUnpackedArray(AstVar* nodep) {
AstUnpackArrayDType* dtypep = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType);
UASSERT_OBJ(dtypep, nodep, "Must be unapcked array");
return dtypep->msb() - dtypep->lsb() + 1;
return dtypep->elementsConst();
}
void setContextAndIterateChildren(AstNode* nodep) {
@ -585,7 +585,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
const VNumRange selRange{nodep->declRange().hi() + dtypep->declRange().lo(),
nodep->declRange().lo() + dtypep->declRange().lo(),
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");
UINFO(4, "add " << nodep << " for " << refp->varp()->prettyName() << "\n");
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);
// Variable will be registered in the caller side.
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
const bool use_simple_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),
lvalue ? VAccess::WRITE : VAccess::READ);
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.
std::vector<AstVar*> vars;
// 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].
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);
newp->propagateAttrFrom(varp);
// 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);
UASSERT_OBJ(refp, selp, "Unexpected op is registered");
adtypep = VN_CAST(selp->dtypep()->skipRefp(), UnpackArrayDType);
lsb = adtypep->lsb();
lsb = adtypep->lo();
}
AstVarRef* newrefp = createTempVar(sit->context(), refp, adtypep, varp->name(),
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
}
if (skipUnused && !m_rhs.empty()) { // Range to be read must be kept, so add points here
int lsb = m_basicp->msb() + 1;
int msb = m_basicp->lsb() - 1;
int lsb = m_basicp->hi() + 1;
int msb = m_basicp->lo() - 1;
for (size_t i = 0; i < m_rhs.size(); ++i) {
lsb = std::min(lsb, m_rhs[i].lsb());
msb = std::max(msb, m_rhs[i].msb());
@ -933,8 +933,8 @@ public:
points.emplace_back(std::make_pair(msb + 1, true));
}
if (!skipUnused) { // All bits are necessary
points.emplace_back(std::make_pair(m_basicp->lsb(), false));
points.emplace_back(std::make_pair(m_basicp->msb() + 1, true));
points.emplace_back(std::make_pair(m_basicp->lo(), false));
points.emplace_back(std::make_pair(m_basicp->hi() + 1, true));
}
std::sort(points.begin(), points.end(), SortByFirst());
@ -985,10 +985,10 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
UASSERT_OBJ(!nodep->classOrPackagep(), nodep,
"variable in package must have been dropped beforehand.");
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());
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 {
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 {{}}
if (consts[0] && consts[1]) { // OK
refit->second.append(
PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(),
PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lo(),
consts[1]->toUInt()),
vrefp->access());
UINFO(5, varp->prettyName()
<< " [" << consts[0]->toSInt() << ":+" << consts[1]->toSInt()
<< "] lsb:" << refit->second.basicp()->lsb() << "\n");
<< "] lsb:" << refit->second.basicp()->lo() << "\n");
} else {
nodep->v3warn(SPLITVAR, vrefp->prettyNameQ()
<< notSplitMsg
@ -1081,7 +1081,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
void createVars(AstVar* varp, const AstBasicDType* basicp, std::vector<SplitNewVar>& vars) {
for (size_t i = 0; i < vars.size(); ++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);
const std::string name
= (left == right)
@ -1101,8 +1102,8 @@ class SplitPackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
break;
default: UASSERT_OBJ(false, basicp, "Only bit and logic are allowed");
}
dtypep->rangep(new AstRange(varp->fileline(), newvarp->msb(), newvarp->lsb()));
dtypep->rangep()->littleEndian(basicp->littleEndian());
dtypep->rangep(new AstRange{varp->fileline(), VNumRange{newvarp->msb(), newvarp->lsb(),
basicp->littleEndian()}});
newvarp->varp(new AstVar(varp->fileline(), AstVarType::VAR, name, dtypep));
newvarp->varp()->propagateAttrFrom(varp);
newvarp->varp()->funcLocal(varp->isFuncLocal() || varp->isFuncReturn());

View File

@ -447,7 +447,8 @@ private:
FileLine* const flp = m_topScopep->fileline();
AstNodeDType* const newScalarDtp = new AstBasicDType(flp, VFlagLogicPacked(), 1);
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);
v3Global.rootp()->typeTablep()->addTypesp(newArrDtp);
AstVar* const newvarp

View File

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

View File

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

View File

@ -752,21 +752,10 @@ private:
// Signed: unsigned output, input either
// Convert all range values to constants
UINFO(6, "RANGE " << nodep << endl);
V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node
V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node
checkConstantOrReplace(nodep->msbp(), "MSB of bit range isn't a constant");
checkConstantOrReplace(nodep->lsbp(), "LSB 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());
}
V3Const::constifyParamsEdit(nodep->leftp()); // May relink pointed to node
V3Const::constifyParamsEdit(nodep->rightp()); // May relink pointed to node
checkConstantOrReplace(nodep->leftp(), "left side of bit range isn't a constant");
checkConstantOrReplace(nodep->rightp(), "right side of bit range isn't a constant");
if (m_vup->prelim()) {
// Don't need to iterate because V3Const already constified
int width = nodep->elementsConst();
@ -807,7 +796,7 @@ private:
int width = nodep->widthConst();
UASSERT_OBJ(nodep->dtypep(), nodep, "dtype wasn't set"); // by V3WidthSel
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());
width = (nodep->lsbConst() - nodep->msbConst() + 1);
nodep->dtypeSetLogicSized(width, VSigning::UNSIGNED);
@ -903,8 +892,8 @@ private:
int fromlsb;
AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp();
if (const AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) {
frommsb = adtypep->msb();
fromlsb = adtypep->lsb();
frommsb = adtypep->hi();
fromlsb = adtypep->lo();
if (fromlsb > frommsb) {
int t = frommsb;
frommsb = fromlsb;
@ -1929,7 +1918,7 @@ private:
// "foo[0]" from a parameter but not a wire
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),
VSigning::fromBool(issigned));
nodep->dtypep(nodep->findLogicRangeDType(VNumRange(0, 0, false),
nodep->dtypep(nodep->findLogicRangeDType(VNumRange{0, 0},
nodep->valuep()->widthMin(),
VSigning::fromBool(issigned)));
} else {

View File

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