Internals: Rework AstInitArray to have O(1) access. No functional change intended.
This commit is contained in:
parent
704f40b1a2
commit
4767083a72
|
|
@ -902,6 +902,15 @@ void AstIfaceRefDType::dumpSmall(std::ostream& str) const {
|
||||||
this->AstNodeDType::dumpSmall(str);
|
this->AstNodeDType::dumpSmall(str);
|
||||||
str<<"iface";
|
str<<"iface";
|
||||||
}
|
}
|
||||||
|
void AstInitArray::dump(std::ostream& str) const {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
int n = 0;
|
||||||
|
const AstInitArray::KeyItemMap& mapr = map();
|
||||||
|
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
|
||||||
|
if (n++ > 5) { str<<" ..."; break; }
|
||||||
|
str<<" ["<<it->first<<"]="<<(void*)it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
void AstJumpGo::dump(std::ostream& str) const {
|
void AstJumpGo::dump(std::ostream& str) const {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" -> ";
|
str<<" -> ";
|
||||||
|
|
|
||||||
|
|
@ -805,7 +805,7 @@ public:
|
||||||
ASTNODE_NODE_FUNCS(EnumItemRef)
|
ASTNODE_NODE_FUNCS(EnumItemRef)
|
||||||
virtual void dump(std::ostream& str) const;
|
virtual void dump(std::ostream& str) const;
|
||||||
virtual string name() const { return itemp()->name(); }
|
virtual string name() const { return itemp()->name(); }
|
||||||
virtual const char* broken() const { BROKEN_RTN(!itemp()); return NULL; }
|
virtual const char* broken() const { BROKEN_RTN(!VN_IS(itemp(), EnumItem)); return NULL; }
|
||||||
virtual int instrCount() const { return 0; }
|
virtual int instrCount() const { return 0; }
|
||||||
virtual void cloneRelink() { if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); }
|
virtual void cloneRelink() { if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); }
|
||||||
virtual bool same(const AstNode* samep) const {
|
virtual bool same(const AstNode* samep) const {
|
||||||
|
|
@ -3476,14 +3476,33 @@ public:
|
||||||
virtual bool cleanOut() const { return false; } // NA
|
virtual bool cleanOut() const { return false; } // NA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AstInitItem : public AstNode {
|
||||||
|
// Container for a item in an init array
|
||||||
|
// This container is present so that the value underneath may get replaced with a new nodep
|
||||||
|
// and the upper AstInitArray's map will remain correct (pointing to this InitItem)
|
||||||
|
public:
|
||||||
|
// Parents: INITARRAY
|
||||||
|
AstInitItem(FileLine* fl, AstNode* valuep)
|
||||||
|
: AstNode(fl) { addOp1p(valuep); }
|
||||||
|
ASTNODE_NODE_FUNCS(InitItem)
|
||||||
|
virtual bool maybePointedTo() const { return true; }
|
||||||
|
virtual bool hasDType() const { return false; } // See valuep()'s dtype instead
|
||||||
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
|
AstNode* valuep() const { return op1p(); } // op1 = Value
|
||||||
|
void valuep(AstNode* nodep) { addOp1p(nodep); }
|
||||||
|
};
|
||||||
|
|
||||||
class AstInitArray : public AstNode {
|
class AstInitArray : public AstNode {
|
||||||
// Set a var to a large list of values
|
// Set a var to a map of values
|
||||||
// The values must be in sorted order, and not exceed the size of the var's array.
|
// The list of initsp() is not relevant
|
||||||
// The first value on the initsp() list is for the lo() index of the array.
|
|
||||||
// If default is specified, the vector may be sparse, and not provide each value.
|
// If default is specified, the vector may be sparse, and not provide each value.
|
||||||
|
// Key values are C++ array style, with lo() at index 0
|
||||||
// Parents: ASTVAR::init()
|
// Parents: ASTVAR::init()
|
||||||
// Children: CONSTs...
|
// Children: AstInitItem
|
||||||
std::deque<uint32_t> m_indices; // Which array index each entry in the list is for (if defaultp)
|
public:
|
||||||
|
typedef std::map<uint32_t, AstInitItem*> KeyItemMap;
|
||||||
|
private:
|
||||||
|
KeyItemMap m_map; // Node value for each array index
|
||||||
public:
|
public:
|
||||||
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* defaultp)
|
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* defaultp)
|
||||||
: AstNode(fl) {
|
: AstNode(fl) {
|
||||||
|
|
@ -3491,27 +3510,55 @@ public:
|
||||||
addNOp1p(defaultp);
|
addNOp1p(defaultp);
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(InitArray)
|
ASTNODE_NODE_FUNCS(InitArray)
|
||||||
AstNode* defaultp() const { return op1p(); } // op1 = Default if sparse
|
virtual void dump(std::ostream& str) const;
|
||||||
void defaultp(AstNode* newp) { setOp1p(newp); }
|
virtual const char* broken() const {
|
||||||
AstNode* initsp() const { return op2p(); } // op2 = Initial value expressions
|
for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
void addValuep(AstNode* newp) { addIndexValuep(m_indices.size(), newp); }
|
BROKEN_RTN(!VN_IS(it->second, InitItem));
|
||||||
void addIndexValuep(uint32_t index, AstNode* newp) {
|
BROKEN_RTN(!it->second->brokeExists());
|
||||||
// Must insert in sorted order
|
}
|
||||||
if (!m_indices.empty()) UASSERT(index > m_indices.back(), "InitArray adding index <= previous index");
|
return NULL;
|
||||||
m_indices.push_back(index);
|
}
|
||||||
addOp2p(newp); }
|
virtual void cloneRelink() {
|
||||||
void addFrontValuep(AstNode* newp) { // Add to front of list, e.g. index 0.
|
for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
// e.g. 0:100, 1:101 when addFront(200), get 0:200, 1:100, 2:101
|
if (it->second->clonep()) it->second = it->second->clonep();
|
||||||
initsp()->addHereThisAsNext(newp);
|
}
|
||||||
m_indices.push_back(m_indices.size());
|
|
||||||
}
|
}
|
||||||
int posIndex(int listPos) {
|
|
||||||
UASSERT(listPos < (int)m_indices.size(), "InitArray past end of indices list");
|
|
||||||
return m_indices[listPos]; }
|
|
||||||
virtual bool hasDType() const { return true; }
|
virtual bool hasDType() const { return true; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
virtual bool same(const AstNode* samep) const {
|
virtual bool same(const AstNode* samep) const {
|
||||||
return m_indices == static_cast<const AstInitArray*>(samep)->m_indices; }
|
// Only works if exact same children, instead should override comparison
|
||||||
|
// of children list, and instead use map-vs-map key/value compare
|
||||||
|
return m_map == static_cast<const AstInitArray*>(samep)->m_map;
|
||||||
|
}
|
||||||
|
AstNode* defaultp() const { return op1p(); } // op1 = Default if sparse
|
||||||
|
void defaultp(AstNode* newp) { setOp1p(newp); }
|
||||||
|
AstNode* initsp() const { return op2p(); } // op2 = Initial value expressions
|
||||||
|
void addValuep(AstNode* newp) { addIndexValuep(m_map.size(), newp); }
|
||||||
|
const KeyItemMap& map() const { return m_map; }
|
||||||
|
AstNode* addIndexValuep(uint32_t index, AstNode* newp) {
|
||||||
|
// Returns old value, caller must garbage collect
|
||||||
|
AstNode* oldp = NULL;
|
||||||
|
KeyItemMap::iterator it = m_map.find(index);
|
||||||
|
if (it != m_map.end()) {
|
||||||
|
oldp = it->second->valuep();
|
||||||
|
it->second->valuep(newp);
|
||||||
|
} else {
|
||||||
|
AstInitItem* itemp = new AstInitItem(fileline(), newp);
|
||||||
|
m_map.insert(it, make_pair(index, itemp));
|
||||||
|
addOp2p(itemp);
|
||||||
|
}
|
||||||
|
return oldp;
|
||||||
|
}
|
||||||
|
AstNode* getIndexValuep(uint32_t index) const {
|
||||||
|
KeyItemMap::const_iterator it = m_map.find(index);
|
||||||
|
if (it == m_map.end()) return NULL;
|
||||||
|
else return it->second->valuep();
|
||||||
|
}
|
||||||
|
AstNode* getIndexDefaultedValuep(uint32_t index) const {
|
||||||
|
AstNode* valuep = getIndexValuep(index);
|
||||||
|
if (!valuep) valuep = defaultp();
|
||||||
|
return valuep;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstPragma : public AstNode {
|
class AstPragma : public AstNode {
|
||||||
|
|
|
||||||
|
|
@ -1589,19 +1589,7 @@ private:
|
||||||
else if (m_selp && VN_IS(valuep, InitArray)) {
|
else if (m_selp && VN_IS(valuep, InitArray)) {
|
||||||
AstInitArray* initarp = VN_CAST(valuep, InitArray);
|
AstInitArray* initarp = VN_CAST(valuep, InitArray);
|
||||||
uint32_t bit = m_selp->bitConst();
|
uint32_t bit = m_selp->bitConst();
|
||||||
int pos = 0;
|
AstNode* itemp = initarp->getIndexDefaultedValuep(bit);
|
||||||
AstNode* itemp = initarp->initsp();
|
|
||||||
for (; itemp; ++pos, itemp=itemp->nextp()) {
|
|
||||||
uint32_t index = initarp->posIndex(pos);
|
|
||||||
if (index == bit) break;
|
|
||||||
if (index > bit) {
|
|
||||||
if (initarp->defaultp()) {
|
|
||||||
itemp = initarp->defaultp();
|
|
||||||
} else {
|
|
||||||
initarp->v3fatalSrc("Not enough values in array initialization");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (VN_IS(itemp, Const)) {
|
if (VN_IS(itemp, Const)) {
|
||||||
const V3Number& num = VN_CAST(itemp, Const)->num();
|
const V3Number& num = VN_CAST(itemp, Const)->num();
|
||||||
//UINFO(2,"constVisit "<<cvtToHex(valuep)<<" "<<num<<endl);
|
//UINFO(2,"constVisit "<<cvtToHex(valuep)<<" "<<num<<endl);
|
||||||
|
|
@ -2122,7 +2110,9 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitArray* nodep) {
|
virtual void visit(AstInitArray* nodep) {
|
||||||
// Constant if all children are constant
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
virtual void visit(AstInitItem* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
// These are converted by V3Param. Don't constify as we don't want the
|
// These are converted by V3Param. Don't constify as we don't want the
|
||||||
|
|
|
||||||
|
|
@ -1749,13 +1749,13 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||||
VN_CAST(initarp->defaultp(), Const));
|
VN_CAST(initarp->defaultp(), Const));
|
||||||
puts("}}\n");
|
puts("}}\n");
|
||||||
}
|
}
|
||||||
int pos = 0;
|
const AstInitArray::KeyItemMap& mapr = initarp->map();
|
||||||
for (AstNode* itemp = initarp->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
|
||||||
int index = initarp->posIndex(pos);
|
it != mapr.end(); ++it) {
|
||||||
UASSERT_OBJ(initarp->defaultp() || index==pos, initarp,
|
AstNode* valuep = it->second->valuep();
|
||||||
"Not enough values in array initialization");
|
|
||||||
emitSetVarConstant(varp->nameProtect()
|
emitSetVarConstant(varp->nameProtect()
|
||||||
+"["+cvtToStr(index)+"]", VN_CAST(itemp, Const));
|
+"["+cvtToStr(it->first)+"]",
|
||||||
|
VN_CAST(valuep, Const));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||||
|
|
|
||||||
|
|
@ -467,13 +467,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitArray* nodep) {
|
virtual void visit(AstInitArray* nodep) {
|
||||||
putfs(nodep, "`{");
|
putfs(nodep, "`{");
|
||||||
int pos = 0;
|
int comma = 0;
|
||||||
for (AstNode* itemp = nodep->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
const AstInitArray::KeyItemMap& mapr = nodep->map();
|
||||||
int index = nodep->posIndex(pos);
|
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
|
||||||
puts(cvtToStr(index));
|
it != mapr.end(); ++it) {
|
||||||
|
if (comma++) putbs(", ");
|
||||||
|
puts(cvtToStr(it->first));
|
||||||
puts(":");
|
puts(":");
|
||||||
iterate(itemp);
|
AstNode* valuep = it->second->valuep();
|
||||||
if (itemp->nextp()) putbs(",");
|
iterate(valuep);
|
||||||
}
|
}
|
||||||
puts("}");
|
puts("}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,12 +86,9 @@ class SliceVisitor : public AstNVisitor {
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
if (AstInitArray* initp = VN_CAST(nodep, InitArray)) {
|
if (AstInitArray* initp = VN_CAST(nodep, InitArray)) {
|
||||||
UINFO(9," cloneInitArray("<<elements<<","<<offset<<") "<<nodep<<endl);
|
UINFO(9," cloneInitArray("<<elements<<","<<offset<<") "<<nodep<<endl);
|
||||||
AstNode* itemp = initp->initsp();
|
|
||||||
int leOffset = !arrayp->rangep()->littleEndian()
|
int leOffset = !arrayp->rangep()->littleEndian()
|
||||||
? arrayp->rangep()->elementsConst()-1-offset : offset;
|
? arrayp->rangep()->elementsConst()-1-offset : offset;
|
||||||
for (int pos = 0; itemp && pos < leOffset; ++pos) {
|
AstNode* itemp = initp->getIndexDefaultedValuep(leOffset);
|
||||||
itemp = itemp->nextp();
|
|
||||||
}
|
|
||||||
if (!itemp) {
|
if (!itemp) {
|
||||||
nodep->v3error("Array initialization has too few elements, need element "<<offset);
|
nodep->v3error("Array initialization has too few elements, need element "<<offset);
|
||||||
itemp = initp->initsp();
|
itemp = initp->initsp();
|
||||||
|
|
|
||||||
|
|
@ -1438,6 +1438,9 @@ private:
|
||||||
}
|
}
|
||||||
nodep->dtypeFrom(nodep->itemp());
|
nodep->dtypeFrom(nodep->itemp());
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstInitItem* nodep) {
|
||||||
|
userIterateChildren(nodep, m_vup);
|
||||||
|
}
|
||||||
virtual void visit(AstInitArray* nodep) {
|
virtual void visit(AstInitArray* nodep) {
|
||||||
// InitArray has type of the array; children are array values
|
// InitArray has type of the array; children are array values
|
||||||
if (m_vup->prelim()) { // First stage evaluation
|
if (m_vup->prelim()) { // First stage evaluation
|
||||||
|
|
@ -1983,13 +1986,9 @@ private:
|
||||||
if (!newp) {
|
if (!newp) {
|
||||||
AstInitArray* newap
|
AstInitArray* newap
|
||||||
= new AstInitArray(nodep->fileline(), arrayp, NULL);
|
= new AstInitArray(nodep->fileline(), arrayp, NULL);
|
||||||
newap->addValuep(valuep);
|
|
||||||
newp = newap;
|
newp = newap;
|
||||||
} else {
|
|
||||||
// We iterate hi()..lo() as that is what packed needs,
|
|
||||||
// but INITARRAY needs lo() first
|
|
||||||
VN_CAST(newp, InitArray)->addFrontValuep(valuep);
|
|
||||||
}
|
}
|
||||||
|
VN_CAST(newp, InitArray)->addIndexValuep(ent - range.lo(), valuep);
|
||||||
} else { // Packed. Convert to concat for now.
|
} else { // Packed. Convert to concat for now.
|
||||||
if (!newp) newp = valuep;
|
if (!newp) newp = valuep;
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue