forked from verilator/verilator
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split V3Hashed to V3Hasher and V3DupFinder (verilator#2967)
V3Hasher is responsible for computing AstNode hashes, while V3DupFinder can be used to find duplicate trees based on hashes. Interface of V3DupFinder simplified somewhat. No functional change intended at this point, but hash computation might differ in minor details, this however should have no perceivable effect on output/runtime. Implements (verilator#2964)
- Loading branch information
Showing
17 changed files
with
389 additions
and
382 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// -*- mode: C++; c-file-style: "cc-mode" -*- | ||
//************************************************************************* | ||
// DESCRIPTION: Verilator: Hashed common code into functions | ||
// | ||
// Code available from: https://verilator.org | ||
// | ||
//************************************************************************* | ||
// | ||
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you | ||
// can redistribute it and/or modify it under the terms of either the GNU | ||
// Lesser General Public License Version 3 or the Perl Artistic License | ||
// Version 2.0. | ||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 | ||
// | ||
//************************************************************************* | ||
|
||
#include "config_build.h" | ||
#include "verilatedos.h" | ||
|
||
#include "V3Global.h" | ||
#include "V3DupFinder.h" | ||
#include "V3Ast.h" | ||
#include "V3File.h" | ||
|
||
#include <algorithm> | ||
#include <iomanip> | ||
#include <map> | ||
#include <memory> | ||
|
||
//###################################################################### | ||
// V3DupFinder class functions | ||
|
||
bool V3DupFinder::sameNodes(AstNode* node1p, AstNode* node2p) { | ||
return m_hasher(node1p) == m_hasher(node2p) // Same hash | ||
&& node1p->sameTree(node2p); // Same tree | ||
} | ||
|
||
V3DupFinder::iterator V3DupFinder::findDuplicate(AstNode* nodep, V3DupFinderUserSame* checkp) { | ||
const auto& er = equal_range(m_hasher(nodep)); | ||
for (iterator it = er.first; it != er.second; ++it) { | ||
AstNode* const node2p = it->second; | ||
if (nodep == node2p) continue; // Same node is not a duplicate | ||
if (checkp && !checkp->isSame(nodep, node2p)) continue; // User says it is not a duplicate | ||
if (!nodep->sameTree(node2p)) continue; // Not the same trees | ||
// Found duplicate! | ||
return it; | ||
} | ||
return end(); | ||
} | ||
|
||
void V3DupFinder::dumpFile(const string& filename, bool tree) { | ||
const std::unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename)); | ||
if (logp->fail()) v3fatal("Can't write " << filename); | ||
|
||
std::unordered_map<int, int> dist; | ||
|
||
V3Hash lasthash; | ||
int num_in_bucket = 0; | ||
for (auto it = cbegin(); true; ++it) { | ||
if (it == cend() || lasthash != it->first) { | ||
if (it != cend()) lasthash = it->first; | ||
if (num_in_bucket) { | ||
if (dist.find(num_in_bucket) == dist.end()) { | ||
dist.emplace(num_in_bucket, 1); | ||
} else { | ||
++dist[num_in_bucket]; | ||
} | ||
} | ||
num_in_bucket = 0; | ||
} | ||
if (it == cend()) break; | ||
num_in_bucket++; | ||
} | ||
*logp << "\n*** STATS:\n\n"; | ||
*logp << " #InBucket Occurrences\n"; | ||
for (const auto& i : dist) { | ||
*logp << " " << std::setw(9) << i.first << " " << std::setw(12) << i.second << '\n'; | ||
} | ||
|
||
*logp << "\n*** Dump:\n\n"; | ||
for (const auto& it : *this) { | ||
if (lasthash != it.first) { | ||
lasthash = it.first; | ||
*logp << " " << it.first << '\n'; | ||
} | ||
*logp << "\t" << it.second << '\n'; | ||
// Dumping the entire tree may make nearly N^2 sized dumps, | ||
// because the nodes under this one may also be in the hash table! | ||
if (tree) it.second->dumpTree(*logp, " "); | ||
} | ||
} | ||
|
||
void V3DupFinder::dumpFilePrefixed(const string& nameComment, bool tree) { | ||
if (v3Global.opt.dumpTree()) { // | ||
dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// -*- mode: C++; c-file-style: "cc-mode" -*- | ||
//************************************************************************* | ||
// DESCRIPTION: Verilator: Hash AST trees to find duplicates | ||
// | ||
// Code available from: https://verilator.org | ||
// | ||
//************************************************************************* | ||
// | ||
// Copyright 2005-2021 by Wilson Snyder. This program is free software; you | ||
// can redistribute it and/or modify it under the terms of either the GNU | ||
// Lesser General Public License Version 3 or the Perl Artistic License | ||
// Version 2.0. | ||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 | ||
// | ||
//************************************************************************* | ||
// | ||
// Datastructure for finding duplicate AstNode trees via hashing | ||
// | ||
//************************************************************************* | ||
|
||
#ifndef VERILATOR_V3DUPFINDER_H_ | ||
#define VERILATOR_V3DUPFINDER_H_ | ||
#include "config_build.h" | ||
#include "verilatedos.h" | ||
|
||
#include "V3Error.h" | ||
#include "V3Ast.h" | ||
#include "V3Hasher.h" | ||
|
||
#include <map> | ||
|
||
//============================================================================ | ||
|
||
struct V3DupFinderUserSame { | ||
// Functor for V3DupFinder::findDuplicate | ||
virtual bool isSame(AstNode*, AstNode*) = 0; | ||
V3DupFinderUserSame() = default; | ||
virtual ~V3DupFinderUserSame() = default; | ||
}; | ||
|
||
// This really is just a multimap from 'node hash' to 'node pointer', with some minor extensions. | ||
class V3DupFinder final : private std::multimap<V3Hash, AstNode*> { | ||
using Super = std::multimap<V3Hash, AstNode*>; | ||
|
||
// MEMBERS | ||
const V3Hasher m_hasher; | ||
|
||
public: | ||
// CONSTRUCTORS | ||
V3DupFinder(){}; | ||
~V3DupFinder() = default; | ||
|
||
// METHODS | ||
VL_DEBUG_FUNC; // Declare debug() | ||
|
||
// Expose minimal set of superclass interface | ||
using Super::begin; | ||
using Super::cbegin; | ||
using Super::cend; | ||
using Super::clear; | ||
using Super::const_iterator; | ||
using Super::empty; | ||
using Super::end; | ||
using Super::erase; | ||
using Super::iterator; | ||
|
||
// Insert node into data structure | ||
iterator insert(AstNode* nodep) { return emplace(m_hasher(nodep), nodep); } | ||
|
||
// Check if nodes are the same (same as node1p->sameTree(node2p), | ||
// but first checks the hashes are equal for speed) | ||
bool sameNodes(AstNode* node1p, AstNode* node2p); | ||
|
||
// Return duplicate, if one was inserted, with optional user check for sameness | ||
iterator findDuplicate(AstNode* nodep, V3DupFinderUserSame* checkp = nullptr); | ||
|
||
// Dump for debug | ||
void dumpFile(const string& filename, bool tree); | ||
void dumpFilePrefixed(const string& nameComment, bool tree = false); | ||
}; | ||
|
||
#endif // Guard |
Oops, something went wrong.