2021-05-21 02:41:46 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
2021-05-21 15:34:27 +02:00
|
|
|
// DESCRIPTION: Verilator: AstNode hash computation
|
2021-05-21 02:41:46 +02:00
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2025-01-01 14:30:25 +01:00
|
|
|
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
2021-05-21 02:41:46 +02:00
|
|
|
// 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
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
2023-10-18 04:50:27 +02:00
|
|
|
#include "V3PchAstMT.h"
|
|
|
|
|
|
2023-10-18 12:37:46 +02:00
|
|
|
#include "V3Hasher.h"
|
|
|
|
|
|
2021-05-21 15:34:27 +02:00
|
|
|
#include <functional>
|
|
|
|
|
|
2022-09-18 21:53:42 +02:00
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2021-05-21 02:41:46 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Visitor that computes node hashes
|
|
|
|
|
|
2023-03-18 17:17:25 +01:00
|
|
|
class HasherVisitor final : public VNVisitorConst {
|
2021-05-21 02:41:46 +02:00
|
|
|
// NODE STATE
|
|
|
|
|
// AstNode::user4() -> V3Hash. Hash value of this node (hash of 0 is illegal)
|
2022-01-02 19:56:40 +01:00
|
|
|
// VNUser4InUse in V3Hasher.h
|
2021-05-21 02:41:46 +02:00
|
|
|
|
|
|
|
|
// STATE
|
2021-05-21 15:34:27 +02:00
|
|
|
V3Hash m_hash; // Hash value accumulator
|
2021-05-21 02:41:46 +02:00
|
|
|
const bool m_cacheInUser4; // Use user4 to cache each V3Hash?
|
2024-08-26 18:18:52 +02:00
|
|
|
std::set<AstNode*> m_visited; // Keeps track of some visited nodes to prevent
|
|
|
|
|
// infinite recursion
|
2021-05-21 02:41:46 +02:00
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
|
2024-08-26 18:18:52 +02:00
|
|
|
void guardRecursion(AstNode* const nodep, std::function<void()>&& f) {
|
|
|
|
|
// Guard against infinite recursion if there's no caching
|
|
|
|
|
// Otherwise caching does the same but faster
|
|
|
|
|
if (!m_cacheInUser4) {
|
|
|
|
|
if (m_visited.find(nodep) != m_visited.end()) {
|
|
|
|
|
m_hash += V3Hash{nodep->name()};
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
m_visited.insert(nodep);
|
|
|
|
|
}
|
|
|
|
|
f();
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 15:34:27 +02:00
|
|
|
V3Hash hashNodeAndIterate(AstNode* nodep, bool hashDType, bool hashChildren,
|
|
|
|
|
std::function<void()>&& f) {
|
2022-01-05 02:19:58 +01:00
|
|
|
// See comments in visit(AstCFunc) about this breaking recursion
|
2021-05-21 15:34:27 +02:00
|
|
|
if (m_cacheInUser4 && nodep->user4()) {
|
2022-11-20 19:11:01 +01:00
|
|
|
return V3Hash{nodep->user4()};
|
2021-05-21 15:34:27 +02:00
|
|
|
} else {
|
|
|
|
|
VL_RESTORER(m_hash);
|
|
|
|
|
// Reset accumulator
|
2022-11-20 19:11:01 +01:00
|
|
|
m_hash = V3Hash{nodep->type()}; // Node type
|
2024-09-11 01:04:55 +02:00
|
|
|
f(); // Node-specific hash
|
2023-03-18 17:17:25 +01:00
|
|
|
if (hashDType && nodep != nodep->dtypep())
|
|
|
|
|
iterateConstNull(nodep->dtypep()); // Node dtype
|
2021-05-21 15:34:27 +02:00
|
|
|
if (hashChildren) iterateChildrenConst(nodep); // Children
|
|
|
|
|
if (m_cacheInUser4) nodep->user4(m_hash.value());
|
|
|
|
|
return m_hash;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VISITORS
|
|
|
|
|
|
|
|
|
|
constexpr static bool HASH_DTYPE = true;
|
|
|
|
|
constexpr static bool HASH_CHILDREN = true;
|
|
|
|
|
|
2024-09-11 01:04:55 +02:00
|
|
|
// Each visitor below contributes to the hash any node-specific content
|
2021-05-21 15:34:27 +02:00
|
|
|
// that is not dependent on either of the following, as these are
|
|
|
|
|
// included by default by hashNode:
|
|
|
|
|
// - Node type (as given by AstNode::type())
|
|
|
|
|
// - Node dtype (unless !hashDType)
|
|
|
|
|
// - child nodes (unless !hashChildren)
|
|
|
|
|
//
|
|
|
|
|
// The hash must be stable, which means in particular it cannot rely on
|
|
|
|
|
// pointer values, or any other value that might differ between separate
|
|
|
|
|
// invocations of Verilator over the same design.
|
|
|
|
|
//
|
|
|
|
|
// Note there is a circularity problem where some child nodes can back
|
|
|
|
|
// to their ancestral nodes via member pointers, which can lead to an
|
|
|
|
|
// infinite traversal. To break this, nodes that are subject to such
|
|
|
|
|
// referencing and represent code which can reasonably be assumed not to
|
|
|
|
|
// be equivalent to any other code, are hashed either by name (e.g.:
|
|
|
|
|
// AstNodeModule), or by unique identifier (e.g.: AstNodeUOrStructDType).
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
// AstNode - Warns to help find missing cases
|
2021-05-21 02:41:46 +02:00
|
|
|
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNode* nodep) override {
|
2021-05-21 15:34:27 +02:00
|
|
|
#if VL_DEBUG
|
2025-05-23 02:29:32 +02:00
|
|
|
UINFO(0, "%Warning: Hashing node as AstNode: " << nodep);
|
2021-05-21 15:34:27 +02:00
|
|
|
#endif
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
// AstNodeDType
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeArrayDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->left();
|
|
|
|
|
m_hash += nodep->right();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeUOrStructDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, false, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->uniqueNum();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstParamTypeDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
m_hash += nodep->varType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstMemberDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstDefImplicitDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->uniqueNum();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstAssocArrayDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
|
|
|
|
iterateConstNull(nodep->virtRefDType2p());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2024-11-29 15:20:02 +01:00
|
|
|
void visit(AstBracketArrayDType* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() {
|
|
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstDynArrayDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstUnsizedArrayDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstWildcardArrayDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
2022-07-20 15:01:36 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstBasicDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->keyword();
|
2023-10-15 21:15:46 +02:00
|
|
|
m_hash += nodep->numeric();
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->nrange().left();
|
|
|
|
|
m_hash += nodep->nrange().right();
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-09-19 03:17:21 +02:00
|
|
|
void visit(AstCDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2023-09-19 03:17:21 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstConstDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstClassRefDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->classp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstIfaceRefDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->cellp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstQueueDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->virtRefDTypep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstRefDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->typedefp());
|
|
|
|
|
iterateConstNull(nodep->refDTypep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2023-09-16 00:33:02 +02:00
|
|
|
void visit(AstStreamDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, []() {});
|
2023-09-16 00:33:02 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstVoidDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstEnumDType* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, false, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->uniqueNum();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
2022-10-12 11:19:21 +02:00
|
|
|
// AstNodeExpr
|
|
|
|
|
void visit(AstNodeExpr* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2025-06-24 17:59:09 +02:00
|
|
|
void visit(AstSel* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
|
|
|
|
m_hash += nodep->widthConst();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstConst* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->num().toHash();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNullCheck* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCCast* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->size();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstVarRef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
if (nodep->varScopep()) {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->varScopep());
|
2021-05-21 15:34:27 +02:00
|
|
|
} else {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->varp());
|
2023-09-08 13:34:35 +02:00
|
|
|
m_hash += nodep->selfPointer().asString();
|
2021-05-21 02:41:46 +02:00
|
|
|
}
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstVarXRef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->varp());
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->dotted();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstMemberSel* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstFScanF* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->text();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSScanF* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->text();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstAddrOfCFunc* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->funcp());
|
2021-06-13 15:33:11 +02:00
|
|
|
});
|
|
|
|
|
}
|
2021-05-21 15:34:27 +02:00
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
// AstNodeStmt
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeStmt* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeCCall* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->funcp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeFTaskRef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->taskp());
|
|
|
|
|
iterateConstNull(nodep->classOrPackagep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCMethodHard* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2025-09-27 14:22:17 +02:00
|
|
|
m_hash += nodep->method();
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 17:15:10 +02:00
|
|
|
void visit(AstCAwait* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2025-08-18 01:14:34 +02:00
|
|
|
iterateConstNull(nodep->sentreep());
|
Timing support (#3363)
Adds timing support to Verilator. It makes it possible to use delays,
event controls within processes (not just at the start), wait
statements, and forks.
Building a design with those constructs requires a compiler that
supports C++20 coroutines (GCC 10, Clang 5).
The basic idea is to have processes and tasks with delays/event controls
implemented as C++20 coroutines. This allows us to suspend and resume
them at any time.
There are five main runtime classes responsible for managing suspended
coroutines:
* `VlCoroutineHandle`, a wrapper over C++20's `std::coroutine_handle`
with move semantics and automatic cleanup.
* `VlDelayScheduler`, for coroutines suspended by delays. It resumes
them at a proper simulation time.
* `VlTriggerScheduler`, for coroutines suspended by event controls. It
resumes them if its corresponding trigger was set.
* `VlForkSync`, used for syncing `fork..join` and `fork..join_any`
blocks.
* `VlCoroutine`, the return type of all verilated coroutines. It allows
for suspending a stack of coroutines (normally, C++ coroutines are
stackless).
There is a new visitor in `V3Timing.cpp` which:
* scales delays according to the timescale,
* simplifies intra-assignment timing controls and net delays into
regular timing controls and assignments,
* simplifies wait statements into loops with event controls,
* marks processes and tasks with timing controls in them as
suspendable,
* creates delay, trigger scheduler, and fork sync variables,
* transforms timing controls and fork joins into C++ awaits
There are new functions in `V3SchedTiming.cpp` (used by `V3Sched.cpp`)
that integrate static scheduling with timing. This involves providing
external domains for variables, so that the necessary combinational
logic gets triggered after coroutine resumption, as well as statements
that need to be injected into the design eval function to perform this
resumption at the correct time.
There is also a function that transforms forked processes into separate
functions.
See the comments in `verilated_timing.h`, `verilated_timing.cpp`,
`V3Timing.cpp`, and `V3SchedTiming.cpp`, as well as the internals
documentation for more details.
Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
2022-08-22 14:26:32 +02:00
|
|
|
});
|
|
|
|
|
}
|
2023-09-16 00:33:02 +02:00
|
|
|
void visit(AstCLocalScope* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2023-09-16 00:33:02 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCoverInc* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->declp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstDisplay* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->displayType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstMonitorOff* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->off();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstJumpGo* nodep) override {
|
2025-07-23 18:51:16 +02:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, false, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstTraceInc* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->declp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeCoverOrAssert* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
2022-12-23 17:32:38 +01:00
|
|
|
// AstNode direct descendants
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeRange* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeModule* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [this, nodep]() { //
|
2023-05-11 00:34:29 +02:00
|
|
|
m_hash += nodep->name();
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodePreSel* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstClassExtends* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSelLoopVars* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstDefParam* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstArg* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstParseRef* nodep) override {
|
2025-10-03 12:49:13 +02:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstClassOrPackageRef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->classOrPackageNodep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSenItem* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->edgeType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSenTree* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSFormatF* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->text();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstElabDisplay* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->displayType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstInitItem* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstInitArray* nodep) override {
|
2024-08-06 14:48:12 +02:00
|
|
|
if (VN_IS(nodep->dtypep(), AssocArrayDType)) {
|
2021-12-11 17:29:01 +01:00
|
|
|
if (nodep->defaultp()) {
|
|
|
|
|
m_hash
|
2023-11-06 13:13:31 +01:00
|
|
|
+= hashNodeAndIterate(nodep->defaultp(), HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-06-13 16:05:55 +02:00
|
|
|
}
|
2021-12-11 17:29:01 +01:00
|
|
|
const auto& mapr = nodep->map();
|
|
|
|
|
for (const auto& itr : mapr) { // mapr is sorted, so hash should get stable results
|
|
|
|
|
m_hash += itr.first;
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(itr.second, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-12-11 17:29:01 +01:00
|
|
|
}
|
|
|
|
|
} else if (const AstUnpackArrayDType* const dtypep
|
|
|
|
|
= VN_CAST(nodep->dtypep(), UnpackArrayDType)) {
|
|
|
|
|
// Hash unpacked array initializers by value, as the order of initializer nodes does
|
|
|
|
|
// not matter, and we want semantically equivalent initializers to map to the same
|
|
|
|
|
// hash.
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(
|
|
|
|
|
nodep, HASH_DTYPE, /* hashChildren: */ !dtypep, [this, nodep, dtypep]() {
|
|
|
|
|
if (dtypep) {
|
|
|
|
|
const uint32_t size = dtypep->elementsConst();
|
|
|
|
|
for (uint32_t n = 0; n < size; ++n) { //
|
|
|
|
|
iterateConstNull(nodep->getIndexDefaultedValuep(n));
|
|
|
|
|
}
|
2021-12-11 17:29:01 +01:00
|
|
|
}
|
2023-11-06 13:13:31 +01:00
|
|
|
});
|
2021-12-11 17:29:01 +01:00
|
|
|
}
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstPragma* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->pragType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstAttrOf* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->attrType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeFile* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCFunc* nodep) override {
|
2024-08-26 18:18:52 +02:00
|
|
|
guardRecursion(nodep, [this, nodep]() { //
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
|
|
|
|
// We might be in a recursive function, if so on *second* call
|
|
|
|
|
// here we need to break what would be an infinite loop.
|
|
|
|
|
if (m_cacheInUser4) nodep->user4(V3Hash{1}.value()); // Set this "first" call
|
|
|
|
|
// So that a second call will then exit hashNodeAndIterate
|
|
|
|
|
// Having a constant in the hash just means the recursion will
|
|
|
|
|
// end, it shouldn't change the CFunc having a unique hash itself.
|
|
|
|
|
m_hash += nodep->isLoose();
|
|
|
|
|
});
|
2021-06-13 15:33:11 +02:00
|
|
|
});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstVar* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
m_hash += nodep->varType();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstScope* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->aboveScopep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstVarScope* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->varp());
|
|
|
|
|
iterateConstNull(nodep->scopep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstEnumItem* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstTypedef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstTypedefFwd* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstActive* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2025-08-18 01:14:34 +02:00
|
|
|
iterateConstNull(nodep->sentreep());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCell* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->modp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCellInline* nodep) override {
|
2024-04-02 05:11:15 +02:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN,
|
|
|
|
|
[this, nodep]() { m_hash += nodep->name(); });
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeFTask* nodep) override {
|
2024-08-26 18:18:52 +02:00
|
|
|
guardRecursion(nodep, [this, nodep]() { //
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
|
|
|
|
m_hash += nodep->name();
|
|
|
|
|
// See comments in AstCFunc
|
|
|
|
|
if (m_cacheInUser4) nodep->user4(V3Hash{1}.value());
|
|
|
|
|
});
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstModport* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstModportVarRef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->varp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstModportFTaskRef* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConstNull(nodep->ftaskp());
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstMTaskBody* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-09-27 04:51:11 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeProcedure* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
2021-05-21 15:34:27 +02:00
|
|
|
}
|
2025-10-24 15:00:07 +02:00
|
|
|
void visit(AstBegin* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
|
|
|
|
m_hash += nodep->name();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
void visit(AstFork* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
2025-10-24 15:00:07 +02:00
|
|
|
m_hash += nodep->joinType();
|
2021-05-21 15:34:27 +02:00
|
|
|
});
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstPin* nodep) override {
|
2023-11-06 13:13:31 +01:00
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [this, nodep]() {
|
2021-05-21 15:34:27 +02:00
|
|
|
m_hash += nodep->name();
|
|
|
|
|
m_hash += nodep->pinNum();
|
|
|
|
|
});
|
2021-05-21 02:41:46 +02:00
|
|
|
}
|
Internals: Refactor text based Ast constructs (#6280) (#6571)
Remove the large variety of ways raw "text" is represented in the Ast.
Particularly, the only thing that represents a string to be emitted in
the output is AstText.
There are 5 AstNodes that can contain AstText, and V3Emit will throw an
error if an AstText is encountered anywhere else:
- AstCStmt: Internally generated procedural statements involving raw
text.
- AstCStmtUser: This is the old AstUCStmt, renamed so it sorts next to
AstCStmt, as it's largely equivalent. We should never create this
internally unless used to represent user input. It is used for $c,
statements in the input, and for some 'systemc_* blocks.
- AstCExpr: Internally generaged expression involving raw text.
- AstCExprUser: This is the old AstUCFunc, renamed so it sorts next to
AstCExpr. It is largely equivalent, but also has more optimizations
disabled. This should never be created internally, it is only used for
$c expressions in the input.
- AstTextBlock: Use by V3ProtectLib only, to generate the hierarchical
wrappers.
Text "tracking" for indentation is always on for AstCStmt, AstCExpr, and
AstTextBlock, as these are always generated by us, and should always be
well formed.
Tracking is always off for AstCStmtUser and AstCExprUser, as these
contain arbitrary user input that might not be safe to parse for
indentation.
Remove subsequently redundant AstNodeSimpleText and AstNodeText types.
This patch also fixes incorrect indentation in emitted waveform tracing
functions, and makes the output more readable for hier block SV stubs.
With that, all raw text nodes are handled as a proper AstNodeStmt or
AstNodeExpr as required for #6280.
2025-10-21 13:41:29 +02:00
|
|
|
void visit(AstText* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
|
|
|
|
m_hash += nodep->text();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
void visit(AstTextBlock* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
|
|
|
|
|
m_hash += nodep->prefix();
|
|
|
|
|
m_hash += nodep->separator();
|
|
|
|
|
m_hash += nodep->suffix();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
void visit(AstCStmt* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, []() {});
|
|
|
|
|
}
|
|
|
|
|
void visit(AstCStmtUser* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, []() {});
|
|
|
|
|
}
|
|
|
|
|
void visit(AstCExpr* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
|
|
|
|
}
|
|
|
|
|
void visit(AstCExprUser* nodep) override {
|
|
|
|
|
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, []() {});
|
|
|
|
|
}
|
2021-05-21 02:41:46 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// CONSTRUCTORS
|
2022-07-30 16:01:25 +02:00
|
|
|
explicit HasherVisitor(AstNode* nodep)
|
2021-05-21 02:41:46 +02:00
|
|
|
: m_cacheInUser4{true} {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConst(nodep);
|
2021-05-21 02:41:46 +02:00
|
|
|
}
|
2022-01-05 02:19:58 +01:00
|
|
|
class Uncached {};
|
|
|
|
|
HasherVisitor(const AstNode* nodep, Uncached)
|
2021-05-21 02:41:46 +02:00
|
|
|
: m_cacheInUser4{false} {
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConst(const_cast<AstNode*>(nodep));
|
2021-05-21 02:41:46 +02:00
|
|
|
}
|
2021-05-21 15:34:27 +02:00
|
|
|
V3Hash finalHash() const { return m_hash; }
|
2022-09-16 12:22:11 +02:00
|
|
|
~HasherVisitor() override = default;
|
2021-05-21 02:41:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3Hasher methods
|
|
|
|
|
|
|
|
|
|
V3Hash V3Hasher::operator()(AstNode* nodep) const {
|
2022-01-05 02:19:58 +01:00
|
|
|
if (!nodep->user4()) HasherVisitor{nodep};
|
2022-11-20 19:11:01 +01:00
|
|
|
return V3Hash{nodep->user4()};
|
2021-05-21 02:41:46 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-27 16:54:04 +01:00
|
|
|
V3Hash V3Hasher::rehash(AstNode* nodep) const {
|
|
|
|
|
nodep->user4(0);
|
2022-07-30 16:01:25 +02:00
|
|
|
{ HasherVisitor{nodep}; }
|
2022-11-20 19:11:01 +01:00
|
|
|
return V3Hash{nodep->user4()};
|
2022-02-27 16:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
2021-05-21 02:41:46 +02:00
|
|
|
V3Hash V3Hasher::uncachedHash(const AstNode* nodep) {
|
2022-01-05 02:19:58 +01:00
|
|
|
const HasherVisitor visitor{nodep, HasherVisitor::Uncached{}};
|
2021-05-21 02:41:46 +02:00
|
|
|
return visitor.finalHash();
|
|
|
|
|
}
|
2022-02-05 17:04:48 +01:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// This is used by the std::hash specialization for VNRef.
|
|
|
|
|
// Declared separately to avoid a circular header dependency.
|
|
|
|
|
|
2022-05-15 14:30:04 +02:00
|
|
|
size_t V3HasherUncachedHash(const AstNode& node) {
|
2022-02-05 17:04:48 +01:00
|
|
|
return static_cast<size_t>(V3Hasher::uncachedHash(&node).value());
|
|
|
|
|
}
|