Fix linear searches. bug1316.
This commit is contained in:
parent
c124fe6d0c
commit
3e739db7fa
1
Changes
1
Changes
|
|
@ -24,6 +24,7 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
|||
|
||||
**** Fix parsing error on bad missing #, bug1308. [Dan Kirkham]
|
||||
|
||||
**** Fix Verilation performance issues, bug1316. [John Coiner]
|
||||
|
||||
* Verilator 3.922 2018-03-17
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
#include "V3Ast.h"
|
||||
#include "V3EmitCBase.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3SenTree.h" // for SenTreeSet
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
|
||||
//***** See below for main transformation engine
|
||||
|
||||
|
|
@ -62,7 +64,11 @@ private:
|
|||
AstScope* m_scopep; // Current scope to add statement to
|
||||
AstActive* m_iActivep; // For current scope, the IActive we're building
|
||||
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
|
||||
std::vector<AstActive*> m_activeVec; // List of sensitive actives, for folding
|
||||
|
||||
SenTreeSet m_activeSens; // Sen lists for each active we've made
|
||||
typedef vl_unordered_map<AstSenTree*, AstActive*> ActiveMap;
|
||||
ActiveMap m_activeMap; // Map sentree to active, for folding.
|
||||
|
||||
// METHODS
|
||||
void addActive(AstActive* nodep) {
|
||||
if (!m_scopep) nodep->v3fatalSrc("NULL scope");
|
||||
|
|
@ -73,7 +79,8 @@ private:
|
|||
m_scopep = nodep;
|
||||
m_iActivep = NULL;
|
||||
m_cActivep = NULL;
|
||||
m_activeVec.clear();
|
||||
m_activeSens.clear();
|
||||
m_activeMap.clear();
|
||||
iterateChildren(nodep);
|
||||
// Don't clear scopep, the namer persists beyond this visit
|
||||
}
|
||||
|
|
@ -112,22 +119,15 @@ public:
|
|||
}
|
||||
AstActive* getActive(FileLine* fl, AstSenTree* sensesp) {
|
||||
// Return a sentree in this scope that matches given sense list.
|
||||
// Not the fastest, but scopes tend to have few clocks
|
||||
|
||||
AstActive* activep = NULL;
|
||||
//sitemsp->dumpTree(cout," Lookingfor: ");
|
||||
for (std::vector<AstActive*>::iterator it = m_activeVec.begin(); it!=m_activeVec.end(); ++it) {
|
||||
activep = *it;
|
||||
if (activep) { // Not deleted
|
||||
// Compare the list
|
||||
AstSenTree* asenp = activep->sensesp();
|
||||
if (asenp->sameTree(sensesp)) {
|
||||
UINFO(8," Found ACTIVE "<<activep<<endl);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
activep = NULL;
|
||||
}
|
||||
found:
|
||||
AstSenTree* activeSenp = m_activeSens.find(sensesp);
|
||||
if (activeSenp) {
|
||||
ActiveMap::iterator it = m_activeMap.find(activeSenp);
|
||||
UASSERT(it != m_activeMap.end(), "Corrupt active map");
|
||||
activep = it->second;
|
||||
}
|
||||
|
||||
// Not found, form a new one
|
||||
if (!activep) {
|
||||
AstSenTree* newsenp = sensesp->cloneTree(false);
|
||||
|
|
@ -136,7 +136,8 @@ public:
|
|||
UINFO(8," New ACTIVE "<<activep<<endl);
|
||||
// Form the sensitivity list
|
||||
addActive(activep);
|
||||
m_activeVec.push_back(activep);
|
||||
m_activeMap[newsenp] = activep;
|
||||
m_activeSens.add(newsenp);
|
||||
// Note actives may have also been added above in the Active visitor
|
||||
}
|
||||
return activep;
|
||||
|
|
|
|||
|
|
@ -2120,6 +2120,7 @@ public:
|
|||
ASTNODE_NODE_FUNCS(SenTree)
|
||||
virtual void dump(std::ostream& str);
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
bool isMulti() const { return m_multi; }
|
||||
AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list
|
||||
void addSensesp(AstNodeSenItem* nodep) { addOp1p(nodep); }
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ private:
|
|||
AstActive* createActivePost(AstVarRef* varrefp) {
|
||||
AstActive* newactp = new AstActive (varrefp->fileline(), "sequentdly",
|
||||
m_activep->sensesp());
|
||||
m_activep->addNext(newactp);
|
||||
// Was addNext(), but addNextHere() avoids a linear search.
|
||||
m_activep->addNextHere(newactp);
|
||||
return newactp;
|
||||
}
|
||||
void checkActivePost(AstVarRef* varrefp, AstActive* oldactivep) {
|
||||
|
|
|
|||
|
|
@ -52,17 +52,19 @@ private:
|
|||
|
||||
// STATE
|
||||
V3Hash m_lowerHash; // Hash of the statement we're building
|
||||
bool m_cacheInUser4; // Use user4 to cache each V3Hash?
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void nodeHashIterate(AstNode* nodep) {
|
||||
if (!nodep->user4()) {
|
||||
V3Hash thisHash;
|
||||
if (!m_cacheInUser4 || !nodep->user4()) {
|
||||
if (VN_IS(nodep->backp(), CFunc)
|
||||
&& !(VN_IS(nodep, NodeStmt) || VN_IS(nodep, CFunc))) {
|
||||
nodep->v3fatalSrc("Node "<<nodep->prettyTypeName()<<" in statement position but not marked stmt (node under function)");
|
||||
}
|
||||
V3Hash oldHash = m_lowerHash;
|
||||
V3Hash oldHash = m_lowerHash;
|
||||
{
|
||||
m_lowerHash = nodep->sameHash();
|
||||
if (m_lowerHash.isIllegal()) {
|
||||
|
|
@ -76,10 +78,12 @@ private:
|
|||
nodep->user4(m_lowerHash.fullValue());
|
||||
//UINFO(9, " hashnode "<<m_lowerHash<<" "<<nodep<<endl);
|
||||
}
|
||||
thisHash = m_lowerHash;
|
||||
m_lowerHash = oldHash;
|
||||
}
|
||||
// Update what will become the above node's hash
|
||||
m_lowerHash += V3Hashed::nodeHash(nodep);
|
||||
m_lowerHash += m_cacheInUser4
|
||||
? V3Hashed::nodeHash(nodep) : thisHash;
|
||||
}
|
||||
|
||||
//--------------------
|
||||
|
|
@ -94,15 +98,26 @@ private:
|
|||
public:
|
||||
// CONSTUCTORS
|
||||
explicit HashedVisitor(AstNode* nodep) {
|
||||
m_cacheInUser4 = true;
|
||||
nodeHashIterate(nodep);
|
||||
//UINFO(9," stmthash "<<hex<<V3Hashed::nodeHash(nodep)<<" "<<nodep<<endl);
|
||||
}
|
||||
explicit HashedVisitor(const AstNode* nodep) {
|
||||
m_cacheInUser4 = false;
|
||||
nodeHashIterate(const_cast<AstNode*>(nodep));
|
||||
}
|
||||
V3Hash finalHash() const { return m_lowerHash; }
|
||||
virtual ~HashedVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Hashed class functions
|
||||
|
||||
V3Hash V3Hashed::uncachedHash(const AstNode* nodep) {
|
||||
HashedVisitor visitor(nodep);
|
||||
return visitor.finalHash();
|
||||
}
|
||||
|
||||
V3Hashed::iterator V3Hashed::hashAndInsert(AstNode* nodep) {
|
||||
hash(nodep);
|
||||
return m_hashMmap.insert(make_pair(nodeHash(nodep), nodep));
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ public:
|
|||
void dumpFile(const string& filename, bool tree);
|
||||
void dumpFilePrefixed(const string& nameComment, bool tree=false);
|
||||
static V3Hash nodeHash(AstNode* nodep) { return V3Hash(nodep->user4p()); }
|
||||
// Hash of the nodep tree, without caching in user4.
|
||||
static V3Hash uncachedHash(const AstNode* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -41,19 +41,69 @@
|
|||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include VL_INCLUDE_UNORDERED_SET
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Hashed.h"
|
||||
|
||||
//######################################################################
|
||||
// Collect SenTrees under the entire scope
|
||||
// And provide functions to find/add a new one
|
||||
|
||||
class SenTreeSet {
|
||||
// Hash table of sensitive blocks.
|
||||
private:
|
||||
// TYPES
|
||||
class HashSenTree {
|
||||
public:
|
||||
HashSenTree() {}
|
||||
size_t operator() (const AstSenTree* kp) const {
|
||||
return V3Hashed::uncachedHash(kp).fullValue();
|
||||
}
|
||||
private:
|
||||
VL_UNCOPYABLE(HashSenTree);
|
||||
};
|
||||
|
||||
class EqSenTree {
|
||||
public:
|
||||
EqSenTree() {}
|
||||
bool operator() (const AstSenTree* ap, const AstSenTree* bp) const {
|
||||
return ap->sameTree(bp);
|
||||
}
|
||||
private:
|
||||
VL_UNCOPYABLE(EqSenTree);
|
||||
};
|
||||
|
||||
// MEMBERS
|
||||
typedef vl_unordered_set<AstSenTree*, HashSenTree, EqSenTree> Set;
|
||||
Set m_trees; // Set of sensitive blocks, for folding.
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
SenTreeSet() {}
|
||||
|
||||
// METHODS
|
||||
void add(AstSenTree* nodep) { m_trees.insert(nodep); }
|
||||
AstSenTree* find(AstSenTree* likep) {
|
||||
AstSenTree* resultp = NULL;
|
||||
Set::iterator it = m_trees.find(likep);
|
||||
if (it != m_trees.end()) {
|
||||
resultp = *it;
|
||||
}
|
||||
return resultp;
|
||||
}
|
||||
void clear() { m_trees.clear(); }
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(SenTreeSet);
|
||||
};
|
||||
|
||||
class SenTreeFinder : public AstNVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstTopScope* m_topscopep; // Top scope to add statement to
|
||||
std::vector<AstSenTree*> m_treesp; // List of sensitive blocks, for folding
|
||||
AstTopScope* m_topscopep; // Top scope to add statement to
|
||||
SenTreeSet m_trees; // Set of sensitive blocks, for folding
|
||||
|
||||
// VISITORS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -77,9 +127,7 @@ private:
|
|||
// Don't grab SenTrees under Actives, only those that are global (under Scope directly)
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) {
|
||||
m_treesp.push_back(nodep);
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) { m_trees.add(nodep); }
|
||||
// Empty visitors, speed things up
|
||||
virtual void visit(AstNodeStmt* nodep) { }
|
||||
virtual void visit(AstNode* nodep) {
|
||||
|
|
@ -89,31 +137,18 @@ private:
|
|||
public:
|
||||
void clear() {
|
||||
m_topscopep = NULL;
|
||||
m_treesp.clear();
|
||||
m_trees.clear();
|
||||
}
|
||||
AstSenTree* getSenTree(FileLine* fl, AstSenTree* sensesp) {
|
||||
// Return a global sentree that matches given sense list.
|
||||
// Not the fastest, but there tend to be few clocks
|
||||
AstSenTree* treep = NULL;
|
||||
//sensesp->dumpTree(cout," Lookingfor: ");
|
||||
for (std::vector<AstSenTree*>::iterator it = m_treesp.begin(); it!=m_treesp.end(); ++it) {
|
||||
treep = *it;
|
||||
if (treep) { // Not deleted
|
||||
if (treep->sameTree(sensesp)) {
|
||||
UINFO(8," Found SBLOCK "<<treep<<endl);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
treep = NULL;
|
||||
}
|
||||
found:
|
||||
AstSenTree* treep = m_trees.find(sensesp);
|
||||
// Not found, form a new one
|
||||
if (!treep) {
|
||||
UASSERT(m_topscopep,"Never called main()");
|
||||
treep = sensesp->cloneTree(false);
|
||||
m_topscopep->addStmtsp(treep);
|
||||
UINFO(8," New SENTREE "<<treep<<endl);
|
||||
m_treesp.push_back(treep);
|
||||
m_trees.add(treep);
|
||||
// Note blocks may have also been added above in the Active visitor
|
||||
}
|
||||
return treep;
|
||||
|
|
|
|||
Loading…
Reference in New Issue