mirror of
https://github.com/verilator/verilator.git
synced 2025-02-01 19:24:05 +00:00
113 lines
3.3 KiB
C++
113 lines
3.3 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
|
//
|
|
// 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
|
|
//
|
|
//*************************************************************************
|
|
// AstSenTree related utilities.
|
|
//*************************************************************************
|
|
|
|
#ifndef _V3SENTREE_H_
|
|
#define _V3SENTREE_H_
|
|
|
|
#include "config_build.h"
|
|
#include "verilatedos.h"
|
|
|
|
#include "V3Ast.h"
|
|
#include "V3Hashed.h"
|
|
|
|
#include <unordered_set>
|
|
|
|
//######################################################################
|
|
// Collect SenTrees under the entire scope
|
|
// And provide functions to find/add a new one
|
|
|
|
class SenTreeSet final {
|
|
// Hash table of sensitive blocks.
|
|
private:
|
|
// TYPES
|
|
struct HashSenTree {
|
|
size_t operator()(const AstSenTree* kp) const {
|
|
return V3Hashed::uncachedHash(kp).fullValue();
|
|
}
|
|
};
|
|
|
|
struct EqSenTree {
|
|
bool operator()(const AstSenTree* ap, const AstSenTree* bp) const {
|
|
return ap->sameTree(bp);
|
|
}
|
|
};
|
|
|
|
// MEMBERS
|
|
typedef std::unordered_set<AstSenTree*, HashSenTree, EqSenTree> Set;
|
|
Set m_trees; // Set of sensitive blocks, for folding.
|
|
|
|
public:
|
|
// CONSTRUCTORS
|
|
SenTreeSet() = default;
|
|
|
|
// METHODS
|
|
void add(AstSenTree* nodep) { m_trees.insert(nodep); }
|
|
|
|
AstSenTree* find(AstSenTree* likep) {
|
|
AstSenTree* resultp = nullptr;
|
|
const auto 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 final {
|
|
private:
|
|
// STATE
|
|
AstTopScope* m_topScopep = nullptr; // Top scope to add global SenTrees to
|
|
SenTreeSet m_trees; // Set of global SenTrees
|
|
|
|
VL_UNCOPYABLE(SenTreeFinder);
|
|
|
|
public:
|
|
// CONSTRUCTORS
|
|
SenTreeFinder() = default;
|
|
|
|
// METHODS
|
|
AstSenTree* getSenTree(AstSenTree* senTreep) {
|
|
// Return a global SenTree that matches given SenTree. If no such global
|
|
// SenTree exists, create one and add it to the stored TopScope.
|
|
AstSenTree* treep = m_trees.find(senTreep);
|
|
// Not found, form a new one
|
|
if (!treep) {
|
|
UASSERT(m_topScopep, "Never called init()");
|
|
treep = senTreep->cloneTree(false);
|
|
m_topScopep->addStmtsp(treep);
|
|
UINFO(8, " New SENTREE " << treep << endl);
|
|
m_trees.add(treep);
|
|
}
|
|
return treep;
|
|
}
|
|
|
|
void init(AstTopScope* topScopep) {
|
|
// Keep hold of top scope so we can add global SenTrees later
|
|
m_topScopep = topScopep;
|
|
// Gather existing global SenTrees
|
|
for (AstNode* nodep = topScopep->stmtsp(); nodep; nodep = nodep->nextp()) {
|
|
if (AstSenTree* senTreep = VN_CAST(nodep, SenTree)) m_trees.add(senTreep);
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif // Guard
|