forked from github/verilator
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:
parent
b32d530000
commit
cd248f6bd7
105
src/V3Ast.h
105
src/V3Ast.h
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -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()),
|
||||
|
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -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] ");
|
||||
}
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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()) {
|
||||
|
@ -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 << ", ";
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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'h1" dtype_id="5"/>
|
||||
<const fl="d31" loc="d,31,27,31,28" name="32'h0" dtype_id="5"/>
|
||||
<const fl="d31" loc="d,31,27,31,28" name="32'h1" dtype_id="5"/>
|
||||
</range>
|
||||
</unpackarraydtype>
|
||||
<basicdtype fl="d35" loc="d,35,21,35,27" id="7" name="string"/>
|
||||
|
Loading…
Reference in New Issue
Block a user