From f84907313709db0e5cafb495f7c5fcc53f67c41a Mon Sep 17 00:00:00 2001 From: Todd Strader Date: Tue, 3 Oct 2023 19:55:25 -0400 Subject: [PATCH] Fix non-inlined interface tracing (#3984) (#4530) --- src/CMakeLists.txt | 2 + src/Makefile_obj.in | 1 + src/V3Inline.cpp | 83 ----------- src/V3Interface.cpp | 129 ++++++++++++++++++ src/V3Interface.h | 34 +++++ src/Verilator.cpp | 3 + test_regress/t/t_interface_ref_trace_noinl.pl | 28 ++++ .../t/t_interface_ref_trace_noinl_notrace.pl | 24 ++++ 8 files changed, 221 insertions(+), 83 deletions(-) create mode 100644 src/V3Interface.cpp create mode 100644 src/V3Interface.h create mode 100755 test_regress/t/t_interface_ref_trace_noinl.pl create mode 100755 test_regress/t/t_interface_ref_trace_noinl_notrace.pl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 396d79fd6..393eba402 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -96,6 +96,7 @@ set(HEADERS V3Inline.h V3Inst.h V3InstrCount.h + V3Interface.h V3LangCode.h V3LanguageWords.h V3Life.h @@ -243,6 +244,7 @@ set(COMMON_SOURCES V3Inline.cpp V3Inst.cpp V3InstrCount.cpp + V3Interface.cpp V3Life.cpp V3LifePost.cpp V3LinkCells.cpp diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 162da5d85..b076f1a2a 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -219,6 +219,7 @@ RAW_OBJS = \ V3Inline.o \ V3Inst.o \ V3InstrCount.o \ + V3Interface.o \ V3Life.o \ V3LifePost.o \ V3LinkCells.o \ diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 996e9d9bf..f704c9fb7 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -623,88 +623,6 @@ public: } }; -//###################################################################### -// Track interface references under the Cell they reference - -class InlineIntfRefVisitor final : public VNVisitor { -private: - // 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(m_scope); - if (m_scope.empty()) { - m_scope = nodep->name(); - } else { - m_scope += "__DOT__" + nodep->name(); - } - - if (VN_IS(nodep->modp(), Iface)) { - nodep->addIntfRefsp(new AstIntfRef{nodep->fileline(), m_scope}); - } - { - 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(AstAssignVarScope* 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; -}; - //###################################################################### // Inline class functions @@ -730,6 +648,5 @@ void V3Inline::inlineAll(AstNetlist* nodep) { } } - { InlineIntfRefVisitor{nodep}; } V3Global::dumpCheckGlobalTree("inline", 0, dumpTreeLevel() >= 3); } diff --git a/src/V3Interface.cpp b/src/V3Interface.cpp new file mode 100644 index 000000000..a0b641885 --- /dev/null +++ b/src/V3Interface.cpp @@ -0,0 +1,129 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Interface references for tracing +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2023 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 +// +//************************************************************************* +// 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 +// +//************************************************************************* + +#define VL_MT_DISABLED_CODE_UNIT 1 + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3Interface.h" + +#include "V3Ast.h" +#include "V3Global.h" + +VL_DEFINE_DEBUG_FUNCTIONS; + +//###################################################################### +// Track interface references under the Cell they reference + +class InlineIntfRefVisitor final : public VNVisitor { +private: + // 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(m_scope); + if (m_scope.empty()) { + m_scope = nodep->name(); + } else { + m_scope += "__DOT__" + nodep->name(); + } + + if (VN_IS(nodep->modp(), Iface)) { + nodep->addIntfRefsp(new AstIntfRef{nodep->fileline(), m_scope}); + } + { + 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(AstAssignVarScope* 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__ << ": " << endl); + + { InlineIntfRefVisitor{nodep}; } + + V3Global::dumpCheckGlobalTree("interface", 0, dumpTreeLevel() >= 3); +} diff --git a/src/V3Interface.h b/src/V3Interface.h new file mode 100644 index 000000000..08bea3574 --- /dev/null +++ b/src/V3Interface.h @@ -0,0 +1,34 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Interface references for tracing +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2023 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 +// +//************************************************************************* + +#ifndef VERILATOR_V3INTERFACE_H_ +#define VERILATOR_V3INTERFACE_H_ + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3ThreadSafety.h" + +class AstNetlist; + +//============================================================================ + +class V3Interface final { +public: + static void interfaceAll(AstNetlist* nodep) VL_MT_DISABLED; +}; + +#endif // Guard diff --git a/src/Verilator.cpp b/src/Verilator.cpp index cb2109ea0..99af25820 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -58,6 +58,7 @@ #include "V3HierBlock.h" #include "V3Inline.h" #include "V3Inst.h" +#include "V3Interface.h" #include "V3Life.h" #include "V3LifePost.h" #include "V3LinkDot.h" @@ -274,6 +275,8 @@ static void process() { } } + if (v3Global.opt.trace()) V3Interface::interfaceAll(v3Global.rootp()); + if (v3Global.opt.fDfgPostInline()) { // Post inline DFG optimization V3DfgOptimizer::optimize(v3Global.rootp(), "post inline"); diff --git a/test_regress/t/t_interface_ref_trace_noinl.pl b/test_regress/t/t_interface_ref_trace_noinl.pl new file mode 100755 index 000000000..f183f40d1 --- /dev/null +++ b/test_regress/t/t_interface_ref_trace_noinl.pl @@ -0,0 +1,28 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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 + +scenarios(simulator => 1); + +top_filename("t/t_interface_ref_trace.v"); +golden_filename("t/t_interface_ref_trace.out"); + +compile( + verilator_flags2 => ['-fno-inline --trace-structs --trace'], + ); + +execute( + check_finished => 1, + ); + +vcd_identical($Self->trace_filename, + $Self->{golden_filename}); + +ok(1); +1; diff --git a/test_regress/t/t_interface_ref_trace_noinl_notrace.pl b/test_regress/t/t_interface_ref_trace_noinl_notrace.pl new file mode 100755 index 000000000..b41a3654b --- /dev/null +++ b/test_regress/t/t_interface_ref_trace_noinl_notrace.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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 + +scenarios(simulator => 1); + +top_filename("t/t_interface_ref_trace.v"); + +compile( + verilator_flags2 => ['-fno-inline'], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1;