mirror of
https://github.com/verilator/verilator.git
synced 2026-08-29 17:28:46 +02:00
Restrict VL_RESTORER to be usable only with trivially copyable types. Introduce VL_RESTORER_COPY and VL_RESTORER_CLEAR, which are more efficient versions usable for non trivially copyable types. VL_RESTORER_COPY semantically behaves the same as VL_RESTORER, but only does one copy at initialization, and on scope exit restores via a move. VL_RESTORER_CLEAR swaps the variable with an new one constructed via the no-args constructor (e.g. empty collection), which does not require any copying at any point. Static assertions enforce picking one of the new flavours when copying might be expensive.
118 lines
4.2 KiB
C++
118 lines
4.2 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Interface references for tracing
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
//*************************************************************************
|
|
//
|
|
// 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
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
//
|
|
//*************************************************************************
|
|
// V3Interface's Transformations:
|
|
//
|
|
// Each module:
|
|
// Look for CELL...
|
|
// Keep track of scope and concrete interface along the way
|
|
// Find all interface references
|
|
// Add INTFREF to concrete interface's list of references
|
|
//
|
|
//*************************************************************************
|
|
|
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
|
|
|
#include "V3Interface.h"
|
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
//######################################################################
|
|
// Track interface references under the Cell they reference
|
|
|
|
class InlineIntfRefVisitor final : public VNVisitor {
|
|
// NODE STATE
|
|
// AstVar::user1p() // AstCell which this Var points to
|
|
const VNUser1InUse m_inuser1;
|
|
const VNUser2InUse m_inuser2;
|
|
|
|
string m_scope; // Scope name
|
|
|
|
// VISITORS
|
|
void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); }
|
|
void visit(AstCell* nodep) override {
|
|
VL_RESTORER_COPY(m_scope);
|
|
if (m_scope.empty()) {
|
|
m_scope = nodep->name();
|
|
} else {
|
|
m_scope += "__DOT__" + nodep->name();
|
|
}
|
|
|
|
AstNodeModule* const modp = nodep->modp();
|
|
// Pass Cell pointers down to the next module
|
|
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
|
AstVar* const varp = pinp->modVarp();
|
|
const AstVarRef* const varrefp = VN_CAST(pinp->exprp(), VarRef);
|
|
if (!varrefp) continue;
|
|
const AstVar* const fromVarp = varrefp->varp();
|
|
const AstIfaceRefDType* const irdtp = VN_CAST(fromVarp->dtypep(), IfaceRefDType);
|
|
if (!irdtp) continue;
|
|
|
|
AstCell* cellp;
|
|
if ((cellp = VN_CAST(fromVarp->user1p(), Cell)) || (cellp = irdtp->cellp())) {
|
|
varp->user1p(cellp);
|
|
const string alias = m_scope + "__DOT__" + pinp->name();
|
|
cellp->addIntfRefsp(new AstIntfRef{pinp->fileline(), alias});
|
|
}
|
|
}
|
|
|
|
iterateChildren(modp);
|
|
}
|
|
void visit(AstAliasScope* nodep) override {
|
|
// Reference
|
|
const AstVarRef* const reflp = VN_CAST(nodep->lhsp(), VarRef);
|
|
// What the reference refers to
|
|
const AstVarRef* const refrp = VN_CAST(nodep->rhsp(), VarRef);
|
|
if (!(reflp && refrp)) return;
|
|
|
|
const AstVar* const varlp = reflp->varp();
|
|
const AstVar* const varrp = refrp->varp();
|
|
if (!(varlp && varrp)) return;
|
|
|
|
AstCell* cellp = VN_CAST(varrp->user1p(), Cell);
|
|
if (!cellp) {
|
|
const AstIfaceRefDType* const irdtp = VN_CAST(varrp->dtypep(), IfaceRefDType);
|
|
if (!irdtp) return;
|
|
|
|
cellp = irdtp->cellp();
|
|
}
|
|
if (!cellp) return;
|
|
string alias;
|
|
if (!m_scope.empty()) alias = m_scope + "__DOT__";
|
|
alias += varlp->name();
|
|
cellp->addIntfRefsp(new AstIntfRef{varlp->fileline(), alias});
|
|
}
|
|
//--------------------
|
|
void visit(AstNodeExpr*) override {} // Accelerate
|
|
void visit(AstNodeStmt*) override {} // Accelerate
|
|
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
|
|
|
public:
|
|
// CONSTRUCTORS
|
|
explicit InlineIntfRefVisitor(AstNode* nodep) { iterate(nodep); }
|
|
~InlineIntfRefVisitor() override = default;
|
|
};
|
|
|
|
//######################################################################
|
|
// Interface class functions
|
|
|
|
void V3Interface::interfaceAll(AstNetlist* nodep) {
|
|
UINFO(2, __FUNCTION__ << ":");
|
|
|
|
{ InlineIntfRefVisitor{nodep}; }
|
|
|
|
V3Global::dumpCheckGlobalTree("interface", 0, dumpTreeEitherLevel() >= 3);
|
|
}
|