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);
|
||||
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 {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> ";
|
||||
|
|
|
|||
|
|
@ -805,7 +805,7 @@ public:
|
|||
ASTNODE_NODE_FUNCS(EnumItemRef)
|
||||
virtual void dump(std::ostream& str) const;
|
||||
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 void cloneRelink() { if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); }
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
|
|
@ -3476,14 +3476,33 @@ public:
|
|||
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 {
|
||||
// Set a var to a large list of values
|
||||
// The values must be in sorted order, and not exceed the size of the var's array.
|
||||
// The first value on the initsp() list is for the lo() index of the array.
|
||||
// Set a var to a map of values
|
||||
// The list of initsp() is not relevant
|
||||
// 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()
|
||||
// Children: CONSTs...
|
||||
std::deque<uint32_t> m_indices; // Which array index each entry in the list is for (if defaultp)
|
||||
// Children: AstInitItem
|
||||
public:
|
||||
typedef std::map<uint32_t, AstInitItem*> KeyItemMap;
|
||||
private:
|
||||
KeyItemMap m_map; // Node value for each array index
|
||||
public:
|
||||
AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* defaultp)
|
||||
: AstNode(fl) {
|
||||
|
|
@ -3491,27 +3510,55 @@ public:
|
|||
addNOp1p(defaultp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(InitArray)
|
||||
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_indices.size(), newp); }
|
||||
void addIndexValuep(uint32_t index, AstNode* newp) {
|
||||
// Must insert in sorted order
|
||||
if (!m_indices.empty()) UASSERT(index > m_indices.back(), "InitArray adding index <= previous index");
|
||||
m_indices.push_back(index);
|
||||
addOp2p(newp); }
|
||||
void addFrontValuep(AstNode* newp) { // Add to front of list, e.g. index 0.
|
||||
// e.g. 0:100, 1:101 when addFront(200), get 0:200, 1:100, 2:101
|
||||
initsp()->addHereThisAsNext(newp);
|
||||
m_indices.push_back(m_indices.size());
|
||||
virtual void dump(std::ostream& str) const;
|
||||
virtual const char* broken() const {
|
||||
for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
BROKEN_RTN(!VN_IS(it->second, InitItem));
|
||||
BROKEN_RTN(!it->second->brokeExists());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void cloneRelink() {
|
||||
for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->second->clonep()) it->second = it->second->clonep();
|
||||
}
|
||||
}
|
||||
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 V3Hash sameHash() const { return V3Hash(); }
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -1589,19 +1589,7 @@ private:
|
|||
else if (m_selp && VN_IS(valuep, InitArray)) {
|
||||
AstInitArray* initarp = VN_CAST(valuep, InitArray);
|
||||
uint32_t bit = m_selp->bitConst();
|
||||
int pos = 0;
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
AstNode* itemp = initarp->getIndexDefaultedValuep(bit);
|
||||
if (VN_IS(itemp, Const)) {
|
||||
const V3Number& num = VN_CAST(itemp, Const)->num();
|
||||
//UINFO(2,"constVisit "<<cvtToHex(valuep)<<" "<<num<<endl);
|
||||
|
|
@ -2122,7 +2110,9 @@ private:
|
|||
}
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) {
|
||||
// Constant if all children are constant
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstInitItem* nodep) {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
// 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));
|
||||
puts("}}\n");
|
||||
}
|
||||
int pos = 0;
|
||||
for (AstNode* itemp = initarp->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
||||
int index = initarp->posIndex(pos);
|
||||
UASSERT_OBJ(initarp->defaultp() || index==pos, initarp,
|
||||
"Not enough values in array initialization");
|
||||
const AstInitArray::KeyItemMap& mapr = initarp->map();
|
||||
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
|
||||
it != mapr.end(); ++it) {
|
||||
AstNode* valuep = it->second->valuep();
|
||||
emitSetVarConstant(varp->nameProtect()
|
||||
+"["+cvtToStr(index)+"]", VN_CAST(itemp, Const));
|
||||
+"["+cvtToStr(it->first)+"]",
|
||||
VN_CAST(valuep, Const));
|
||||
}
|
||||
} else {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
|
|
|
|||
|
|
@ -467,13 +467,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
virtual void visit(AstInitArray* nodep) {
|
||||
putfs(nodep, "`{");
|
||||
int pos = 0;
|
||||
for (AstNode* itemp = nodep->initsp(); itemp; ++pos, itemp=itemp->nextp()) {
|
||||
int index = nodep->posIndex(pos);
|
||||
puts(cvtToStr(index));
|
||||
int comma = 0;
|
||||
const AstInitArray::KeyItemMap& mapr = nodep->map();
|
||||
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
|
||||
it != mapr.end(); ++it) {
|
||||
if (comma++) putbs(", ");
|
||||
puts(cvtToStr(it->first));
|
||||
puts(":");
|
||||
iterate(itemp);
|
||||
if (itemp->nextp()) putbs(",");
|
||||
AstNode* valuep = it->second->valuep();
|
||||
iterate(valuep);
|
||||
}
|
||||
puts("}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,12 +86,9 @@ class SliceVisitor : public AstNVisitor {
|
|||
AstNode* newp;
|
||||
if (AstInitArray* initp = VN_CAST(nodep, InitArray)) {
|
||||
UINFO(9," cloneInitArray("<<elements<<","<<offset<<") "<<nodep<<endl);
|
||||
AstNode* itemp = initp->initsp();
|
||||
int leOffset = !arrayp->rangep()->littleEndian()
|
||||
? arrayp->rangep()->elementsConst()-1-offset : offset;
|
||||
for (int pos = 0; itemp && pos < leOffset; ++pos) {
|
||||
itemp = itemp->nextp();
|
||||
}
|
||||
AstNode* itemp = initp->getIndexDefaultedValuep(leOffset);
|
||||
if (!itemp) {
|
||||
nodep->v3error("Array initialization has too few elements, need element "<<offset);
|
||||
itemp = initp->initsp();
|
||||
|
|
|
|||
|
|
@ -1438,6 +1438,9 @@ private:
|
|||
}
|
||||
nodep->dtypeFrom(nodep->itemp());
|
||||
}
|
||||
virtual void visit(AstInitItem* nodep) {
|
||||
userIterateChildren(nodep, m_vup);
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) {
|
||||
// InitArray has type of the array; children are array values
|
||||
if (m_vup->prelim()) { // First stage evaluation
|
||||
|
|
@ -1983,13 +1986,9 @@ private:
|
|||
if (!newp) {
|
||||
AstInitArray* newap
|
||||
= new AstInitArray(nodep->fileline(), arrayp, NULL);
|
||||
newap->addValuep(valuep);
|
||||
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.
|
||||
if (!newp) newp = valuep;
|
||||
else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue