1 // -*- mode: C++; c-file-style: "cc-mode" -*-
2 //*************************************************************************
3 // DESCRIPTION: Verilator: Hashed common code into functions
4 //
5 // Code available from: https://verilator.org
6 //
7 //*************************************************************************
8 //
9 // Copyright 2003-2021 by Wilson Snyder. This program is free software; you
10 // can redistribute it and/or modify it under the terms of either the GNU
11 // Lesser General Public License Version 3 or the Perl Artistic License
12 // Version 2.0.
13 // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
14 //
15 //*************************************************************************
16
17 #include "config_build.h"
18 #include "verilatedos.h"
19
20 #include "V3Global.h"
21 #include "V3DupFinder.h"
22 #include "V3Ast.h"
23 #include "V3File.h"
24
25 #include <algorithm>
26 #include <iomanip>
27 #include <map>
28 #include <memory>
29
30 //######################################################################
31 // V3DupFinder class functions
32
findDuplicate(AstNode * nodep,V3DupFinderUserSame * checkp)33 V3DupFinder::iterator V3DupFinder::findDuplicate(AstNode* nodep, V3DupFinderUserSame* checkp) {
34 const auto& er = equal_range(m_hasher(nodep));
35 for (iterator it = er.first; it != er.second; ++it) {
36 AstNode* const node2p = it->second;
37 if (nodep == node2p) continue; // Same node is not a duplicate
38 if (checkp && !checkp->isSame(nodep, node2p)) continue; // User says it is not a duplicate
39 if (!nodep->sameTree(node2p)) continue; // Not the same trees
40 // Found duplicate!
41 return it;
42 }
43 return end();
44 }
45
dumpFile(const string & filename,bool tree)46 void V3DupFinder::dumpFile(const string& filename, bool tree) {
47 const std::unique_ptr<std::ofstream> logp{V3File::new_ofstream(filename)};
48 if (logp->fail()) v3fatal("Can't write " << filename);
49
50 std::unordered_map<int, int> dist;
51
52 V3Hash lasthash;
53 int num_in_bucket = 0;
54 for (auto it = cbegin(); true; ++it) {
55 if (it == cend() || lasthash != it->first) {
56 if (it != cend()) lasthash = it->first;
57 if (num_in_bucket) {
58 if (dist.find(num_in_bucket) == dist.end()) {
59 dist.emplace(num_in_bucket, 1);
60 } else {
61 ++dist[num_in_bucket];
62 }
63 }
64 num_in_bucket = 0;
65 }
66 if (it == cend()) break;
67 num_in_bucket++;
68 }
69 *logp << "\n*** STATS:\n\n";
70 *logp << " #InBucket Occurrences\n";
71 for (const auto& i : dist) {
72 *logp << " " << std::setw(9) << i.first << " " << std::setw(12) << i.second << '\n';
73 }
74
75 *logp << "\n*** Dump:\n\n";
76 for (const auto& it : *this) {
77 if (lasthash != it.first) {
78 lasthash = it.first;
79 *logp << " " << it.first << '\n';
80 }
81 *logp << "\t" << it.second << '\n';
82 // Dumping the entire tree may make nearly N^2 sized dumps,
83 // because the nodes under this one may also be in the hash table!
84 if (tree) it.second->dumpTree(*logp, " ");
85 }
86 }
87
dumpFilePrefixed(const string & nameComment,bool tree)88 void V3DupFinder::dumpFilePrefixed(const string& nameComment, bool tree) {
89 if (v3Global.opt.dumpTree()) { //
90 dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree);
91 }
92 }
93