92 lines
3.2 KiB
C++
92 lines
3.2 KiB
C++
// -*- 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 "V3Hasher.h"
|
|
|
|
//######################################################################
|
|
// Visitor that computes node hashes
|
|
|
|
class HasherVisitor final : public AstNVisitor {
|
|
private:
|
|
// NODE STATE
|
|
// AstNode::user4() -> V3Hash. Hash value of this node (hash of 0 is illegal)
|
|
// AstUser4InUse in V3Hasher.h
|
|
|
|
// STATE
|
|
V3Hash m_lowerHash; // Hash of the statement we're building
|
|
const bool m_cacheInUser4; // Use user4 to cache each V3Hash?
|
|
|
|
// METHODS
|
|
VL_DEBUG_FUNC; // Declare debug()
|
|
|
|
//--------------------
|
|
virtual void visit(AstVar*) override {}
|
|
virtual void visit(AstTypedef*) override {}
|
|
virtual void visit(AstParamTypeDType*) override {}
|
|
|
|
virtual void visit(AstNode* nodep) override {
|
|
V3Hash thisHash;
|
|
if (!m_cacheInUser4 || !nodep->user4()) {
|
|
VL_RESTORER(m_lowerHash);
|
|
{
|
|
m_lowerHash = nodep->sameHash();
|
|
UASSERT_OBJ(!m_lowerHash.isIllegal(), nodep,
|
|
"sameHash function undefined (returns 0) for node under CFunc.");
|
|
// For identical nodes, the type should be the same thus
|
|
// dtypep should be the same too
|
|
m_lowerHash = V3Hash(m_lowerHash,
|
|
V3Hash(V3Hash(nodep->type() << 6), V3Hash(nodep->dtypep())));
|
|
// Now update m_lowerHash for our children's (and next children) contributions
|
|
iterateChildrenConst(nodep);
|
|
// Store the hash value
|
|
if (m_cacheInUser4) { nodep->user4(m_lowerHash.fullValue()); }
|
|
thisHash = m_lowerHash;
|
|
}
|
|
}
|
|
// Update what will become the above node's hash
|
|
m_lowerHash += m_cacheInUser4 ? V3Hash(nodep->user4()) : thisHash;
|
|
}
|
|
|
|
public:
|
|
// CONSTRUCTORS
|
|
explicit HasherVisitor(AstNode* nodep)
|
|
: m_cacheInUser4{true} {
|
|
iterate(nodep);
|
|
}
|
|
explicit HasherVisitor(const AstNode* nodep)
|
|
: m_cacheInUser4{false} {
|
|
iterate(const_cast<AstNode*>(nodep));
|
|
}
|
|
V3Hash finalHash() const { return m_lowerHash; }
|
|
virtual ~HasherVisitor() override = default;
|
|
};
|
|
|
|
//######################################################################
|
|
// V3Hasher methods
|
|
|
|
V3Hash V3Hasher::operator()(AstNode* nodep) const {
|
|
if (!nodep->user4()) { HasherVisitor visitor(nodep); }
|
|
return V3Hash(nodep->user4());
|
|
}
|
|
|
|
V3Hash V3Hasher::uncachedHash(const AstNode* nodep) {
|
|
HasherVisitor visitor(nodep);
|
|
return visitor.finalHash();
|
|
}
|