From 36c824d9733567c631b14560379d27062a7a6992 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 26 Sep 2023 18:37:39 -0400 Subject: [PATCH] Add trace() API even when Verilated without --trace (#4462). --- Changes | 1 + src/V3EmitCModel.cpp | 32 ++++++++++++++++--------- test_regress/t/t_trace_noflag_bad.out | 2 ++ test_regress/t/t_trace_noflag_bad.pl | 27 +++++++++++++++++++++ test_regress/t/t_trace_noflag_bad.v | 14 +++++++++++ test_regress/t/t_trace_noflag_bad_c.cpp | 24 +++++++++++++++++++ 6 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 test_regress/t/t_trace_noflag_bad.out create mode 100755 test_regress/t/t_trace_noflag_bad.pl create mode 100644 test_regress/t/t_trace_noflag_bad.v create mode 100644 test_regress/t/t_trace_noflag_bad_c.cpp diff --git a/Changes b/Changes index a23881b92..283efe579 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,7 @@ Verilator 5.017 devel **Minor:** +* Add trace() API even when Verilated without --trace (#4462). [phelter] * Support randc (#4349). * Support resizing function call inout arguments (#4467). diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp index 8eff11e6f..9c694d37c 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -197,15 +197,13 @@ class EmitCModel final : public EmitCFunc { puts("/// Returns time at next time slot. Aborts if !eventsPending()\n"); puts("uint64_t nextTimeSlot();\n"); - if (v3Global.opt.trace()) { - puts("/// Trace signals in the model; called by application code\n"); - puts("void trace(" + v3Global.opt.traceClassBase() - + "C* tfp, int levels, int options = 0);\n"); - if (optSystemC()) { - puts("/// SC tracing; avoid overloaded virtual function lint warning\n"); - puts("void trace(sc_trace_file* tfp) const override { " - "::sc_core::sc_module::trace(tfp); }\n"); - } + puts("/// Trace signals in the model; called by application code\n"); + puts("void trace(" + v3Global.opt.traceClassBase() + + "C* tfp, int levels, int options = 0);\n"); + if (v3Global.opt.trace() && optSystemC()) { + puts("/// SC tracing; avoid overloaded virtual function lint warning\n"); + puts("void trace(sc_trace_file* tfp) const override { " + "::sc_core::sc_module::trace(tfp); }\n"); } if (!optSystemC()) { @@ -591,6 +589,15 @@ class EmitCModel final : public EmitCFunc { puts("}\n"); } + void emitTraceOffMethods(AstNodeModule* modp) { + putSectionDelimiter("Trace configuration"); + // ::trace + puts("\nVL_ATTR_COLD void " + topClassName() + "::trace("); + puts(v3Global.opt.traceClassBase() + "C* tfp, int levels, int options) {\n"); + puts(/**/ "vl_fatal(__FILE__, __LINE__, __FILE__,\"'" + topClassName() + + +"::trace()' called on model that was Verilated without --trace option\");\n"); + puts("}\n"); + } void emitSerializationFunctions() { putSectionDelimiter("Model serialization"); @@ -635,8 +642,11 @@ class EmitCModel final : public EmitCFunc { emitDestructorImplementation(); emitStandardMethods1(modp); emitStandardMethods2(modp); - if (v3Global.opt.trace()) { emitTraceMethods(modp); } - if (v3Global.opt.savable()) { emitSerializationFunctions(); } + if (v3Global.opt.trace()) + emitTraceMethods(modp); + else + emitTraceOffMethods(modp); + if (v3Global.opt.savable()) emitSerializationFunctions(); VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } diff --git a/test_regress/t/t_trace_noflag_bad.out b/test_regress/t/t_trace_noflag_bad.out new file mode 100644 index 000000000..e8156e0c9 --- /dev/null +++ b/test_regress/t/t_trace_noflag_bad.out @@ -0,0 +1,2 @@ +%Error: Vt_trace_noflag_bad.cpp:106: 'Vt_trace_noflag_bad::trace()' called on model that was Verilated without --trace option +Aborting... diff --git a/test_regress/t/t_trace_noflag_bad.pl b/test_regress/t/t_trace_noflag_bad.pl new file mode 100755 index 000000000..8271fa41d --- /dev/null +++ b/test_regress/t/t_trace_noflag_bad.pl @@ -0,0 +1,27 @@ +#!/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 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(vlt => 1); + +compile( + # We need to list verilated_vcd_c.cpp because without --trace Verilator + # won't build it itself automatically. + verilator_flags2 => ["--cc --exe $Self->{t_dir}/$Self->{name}_c.cpp verilated_vcd_c.cpp"], + make_top_shell => 0, + make_main => 0, + ); + +execute( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_trace_noflag_bad.v b/test_regress/t/t_trace_noflag_bad.v new file mode 100644 index 000000000..fc9beb176 --- /dev/null +++ b/test_regress/t/t_trace_noflag_bad.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + int i; + initial begin + i = 10; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_trace_noflag_bad_c.cpp b/test_regress/t/t_trace_noflag_bad_c.cpp new file mode 100644 index 000000000..1fccdddd3 --- /dev/null +++ b/test_regress/t/t_trace_noflag_bad_c.cpp @@ -0,0 +1,24 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Yu-Sheng Lin. +// SPDX-License-Identifier: CC0-1.0 + +#include +#include + +#include "Vt_trace_noflag_bad.h" + +int main(int argc, char** argv) { + std::unique_ptr contextp{new VerilatedContext}; + contextp->traceEverOn(true); + std::unique_ptr tfp{new VerilatedVcdC}; + const std::unique_ptr topp{new VM_PREFIX{contextp.get()}}; + topp->trace(tfp.get(), 99); // Error! + tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/dump.vcd"); // Error! shall put to the next line! + tfp->dump(0); + tfp->close(); + return 0; +}