2012-04-12 21:08:20 -04:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2008-12-12 15:34:02 -05:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Netlist (top level) functions
|
|
|
|
|
//
|
2019-11-07 22:33:59 -05:00
|
|
|
// Code available from: https://verilator.org
|
2008-12-12 15:34:02 -05:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2026-01-26 20:24:34 -05:00
|
|
|
// 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-FileCopyrightText: 2003-2026 Wilson Snyder
|
2020-03-21 11:24:24 -04:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2008-12-12 15:34:02 -05:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// COVERAGEJOIN TRANSFORMATIONS:
|
2019-05-19 16:13:13 -04:00
|
|
|
// If two COVERTOGGLEs have same VARSCOPE, combine them
|
2008-12-12 15:34:02 -05:00
|
|
|
//*************************************************************************
|
2019-10-04 20:17:11 -04:00
|
|
|
|
2023-10-18 06:37:46 -04:00
|
|
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
|
|
|
|
|
2008-12-12 15:34:02 -05:00
|
|
|
#include "V3CoverageJoin.h"
|
2022-08-05 10:56:57 +01:00
|
|
|
|
2021-05-21 01:41:46 +01:00
|
|
|
#include "V3DupFinder.h"
|
2008-12-12 15:34:02 -05:00
|
|
|
#include "V3Stats.h"
|
|
|
|
|
|
2018-10-14 13:43:24 -04:00
|
|
|
#include <vector>
|
|
|
|
|
|
2022-09-18 20:53:42 +01:00
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2008-12-12 15:34:02 -05:00
|
|
|
//######################################################################
|
|
|
|
|
// CoverageJoin state, as a visitor of each AstNode
|
|
|
|
|
|
2022-01-02 13:56:40 -05:00
|
|
|
class CoverageJoinVisitor final : public VNVisitor {
|
2008-12-12 15:34:02 -05:00
|
|
|
// NODE STATE
|
2022-01-02 13:56:40 -05:00
|
|
|
// VNUser4InUse In V3Hasher via V3DupFinder
|
2008-12-12 15:34:02 -05:00
|
|
|
|
2024-10-09 18:12:55 -04:00
|
|
|
// STATE - per active
|
2021-03-12 17:26:53 -05:00
|
|
|
std::vector<AstCoverToggle*> m_toggleps; // List of of all AstCoverToggle's
|
2008-12-12 15:34:02 -05:00
|
|
|
|
2024-10-09 18:12:55 -04:00
|
|
|
// STATE - Statistic tracking
|
2020-04-13 22:51:35 -04:00
|
|
|
VDouble0 m_statToggleJoins; // Statistic tracking
|
2008-12-12 15:34:02 -05:00
|
|
|
|
|
|
|
|
// METHODS
|
2009-01-21 16:56:50 -05:00
|
|
|
|
2008-12-12 15:34:02 -05:00
|
|
|
void detectDuplicates() {
|
2025-05-22 20:29:32 -04:00
|
|
|
UINFO(9, "Finding duplicates");
|
2019-05-19 16:13:13 -04:00
|
|
|
// Note uses user4
|
2021-05-21 01:41:46 +01:00
|
|
|
V3DupFinder dupFinder; // Duplicate code detection
|
2019-05-19 16:13:13 -04:00
|
|
|
// Hash all of the original signals we toggle cover
|
2025-08-19 22:02:10 +01:00
|
|
|
for (const AstCoverToggle* const nodep : m_toggleps) dupFinder.insert(nodep->origp());
|
2024-02-08 19:21:44 -05:00
|
|
|
if (dumpLevel() || debug() >= 9)
|
|
|
|
|
dupFinder.dumpFile(v3Global.debugFilename("coveragejoin") + ".hash", false);
|
2019-05-19 16:13:13 -04:00
|
|
|
// Find if there are any duplicates
|
2020-08-16 11:43:49 -04:00
|
|
|
for (AstCoverToggle* nodep : m_toggleps) {
|
2024-02-08 19:10:38 -05:00
|
|
|
// nodep->backp() is null if we already detected it's a duplicate and unlinked earlier
|
|
|
|
|
if (!nodep->backp()) continue;
|
|
|
|
|
// Want to choose a base node, and keep finding duplicates that are identical.
|
|
|
|
|
// This prevents making chains where a->b, then c->d, then b->c, as we'll
|
|
|
|
|
// find a->b, a->c, a->d directly.
|
|
|
|
|
while (true) {
|
|
|
|
|
const auto dupit = dupFinder.findDuplicate(nodep->origp());
|
|
|
|
|
if (dupit == dupFinder.end()) break;
|
|
|
|
|
const AstNode* const duporigp = dupit->second;
|
|
|
|
|
// Remove node from comparison so don't hit it again
|
|
|
|
|
dupFinder.erase(dupit);
|
|
|
|
|
//
|
|
|
|
|
// Note dupFinder will point to the original toggle-increment equation (what's
|
|
|
|
|
// duplicated), not the covertoggle, but we need to get back to the
|
|
|
|
|
// covertoggle which is immediately above, so:
|
|
|
|
|
AstCoverToggle* const removep = VN_AS(duporigp->backp(), CoverToggle);
|
|
|
|
|
UASSERT_OBJ(removep, nodep, "CoverageJoin duplicate of wrong type");
|
2025-05-22 20:29:32 -04:00
|
|
|
UINFO(8, " Orig " << nodep << " -->> " << nodep->incp()->declp());
|
|
|
|
|
UINFO(8, " dup " << removep << " -->> " << removep->incp()->declp());
|
2024-02-08 19:10:38 -05:00
|
|
|
// The CoverDecl the duplicate pointed to now needs to point to the
|
|
|
|
|
// original's data. I.e. the duplicate will get the coverage number
|
|
|
|
|
// from the non-duplicate
|
2025-08-04 14:29:56 +02:00
|
|
|
AstNodeCoverDecl* const datadeclp = nodep->incp()->declp()->dataDeclThisp();
|
2024-02-08 19:10:38 -05:00
|
|
|
removep->incp()->declp()->dataDeclp(datadeclp);
|
2025-05-22 20:29:32 -04:00
|
|
|
UINFO(8, " new " << removep->incp()->declp());
|
2024-02-08 19:10:38 -05:00
|
|
|
// Mark the found node as a duplicate of the first node
|
|
|
|
|
// (Not vice-versa as we have the iterator for the found node)
|
|
|
|
|
removep->unlinkFrBack();
|
|
|
|
|
VL_DO_DANGLING(pushDeletep(removep), removep);
|
|
|
|
|
++m_statToggleJoins;
|
2019-05-19 16:13:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-12 15:34:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VISITORS
|
2024-02-08 19:21:44 -05:00
|
|
|
void visit(AstActive* nodep) override {
|
|
|
|
|
m_toggleps.clear();
|
2019-05-19 16:13:13 -04:00
|
|
|
// Find all Coverage's
|
2018-05-10 20:55:37 -04:00
|
|
|
iterateChildren(nodep);
|
2019-05-19 16:13:13 -04:00
|
|
|
// Simplify
|
|
|
|
|
detectDuplicates();
|
2008-12-12 15:34:02 -05:00
|
|
|
}
|
2022-09-16 11:22:11 +01:00
|
|
|
void visit(AstCoverToggle* nodep) override {
|
2019-05-19 16:13:13 -04:00
|
|
|
m_toggleps.push_back(nodep);
|
2018-05-10 20:55:37 -04:00
|
|
|
iterateChildren(nodep);
|
2008-12-12 15:34:02 -05:00
|
|
|
}
|
|
|
|
|
//--------------------
|
2022-10-12 10:19:21 +01:00
|
|
|
void visit(AstNodeExpr*) override {} // Accelerate
|
2022-09-16 11:22:11 +01:00
|
|
|
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
2008-12-12 15:34:02 -05:00
|
|
|
|
|
|
|
|
public:
|
2019-09-12 07:22:22 -04:00
|
|
|
// CONSTRUCTORS
|
2020-04-13 22:51:35 -04:00
|
|
|
explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); }
|
2022-09-16 11:22:11 +01:00
|
|
|
~CoverageJoinVisitor() override {
|
2019-05-19 16:13:13 -04:00
|
|
|
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
|
2008-12-12 15:34:02 -05:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Coverage class functions
|
|
|
|
|
|
|
|
|
|
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
|
2025-05-22 20:29:32 -04:00
|
|
|
UINFO(2, __FUNCTION__ << ":");
|
2021-11-26 10:52:36 -05:00
|
|
|
{ CoverageJoinVisitor{rootp}; } // Destruct before checking
|
2024-01-09 16:35:13 +01:00
|
|
|
V3Global::dumpCheckGlobalTree("coveragejoin", 0, dumpTreeEitherLevel() >= 3);
|
2008-12-12 15:34:02 -05:00
|
|
|
}
|