diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 47b02f9ff..9b46ab26c 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -171,6 +171,7 @@ Richard Myers Risto Pejašinović Robert Balas Rupert Swarbrick +Ryan Ziegler Ryszard Rozak Samuel Riedel Sean Cross diff --git a/include/verilated.h b/include/verilated.h index 90836de85..56af9686e 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -448,14 +448,14 @@ public: // METHODS - User called - /// Enable assertions - void assertOn(bool flag) VL_MT_SAFE; /// Return if assertions enabled bool assertOn() const VL_MT_SAFE { return m_s.m_assertOn; } - /// Enable calculation of unused signals (for traces) - void calcUnusedSigs(bool flag) VL_MT_SAFE; + /// Enable assertions + void assertOn(bool flag) VL_MT_SAFE; /// Return if calculating of unused signals (for traces) bool calcUnusedSigs() const VL_MT_SAFE { return m_s.m_calcUnusedSigs; } + /// Enable calculation of unused signals (for traces) + void calcUnusedSigs(bool flag) VL_MT_SAFE; /// Record command-line arguments, for retrieval by $test$plusargs/$value$plusargs, /// and for parsing +verilator+ run-time arguments. /// This should be called before the first model is created. @@ -470,52 +470,51 @@ public: /// Return VerilatedCovContext, allocate if needed /// Note if get unresolved reference then likely forgot to link verilated_cov.cpp VerilatedCovContext* coveragep() VL_MT_SAFE; - /// Set debug level + /// Return debug level + static inline int debug() VL_MT_SAFE; /// Set debug level /// Debug is currently global, but for forward compatibility have a per-context method static inline void debug(int val) VL_MT_SAFE; - /// Return debug level - static inline int debug() VL_MT_SAFE; + /// Return current number of errors/assertions + int errorCount() const VL_MT_SAFE { return m_s.m_errorCount; } /// Set current number of errors/assertions void errorCount(int val) VL_MT_SAFE; /// Increment current number of errors/assertions void errorCountInc() VL_MT_SAFE; - /// Return current number of errors/assertions - int errorCount() const VL_MT_SAFE { return m_s.m_errorCount; } - /// Set number of errors/assertions before stop - void errorLimit(int val) VL_MT_SAFE; /// Return number of errors/assertions before stop int errorLimit() const VL_MT_SAFE { return m_s.m_errorLimit; } - /// Set to throw fatal error on $stop/non-fatal error - void fatalOnError(bool flag) VL_MT_SAFE; + /// Set number of errors/assertions before stop + void errorLimit(int val) VL_MT_SAFE; /// Return if to throw fatal error on $stop/non-fatal bool fatalOnError() const VL_MT_SAFE { return m_s.m_fatalOnError; } - /// Set to throw fatal error on VPI errors - void fatalOnVpiError(bool flag) VL_MT_SAFE; + /// Set to throw fatal error on $stop/non-fatal error + void fatalOnError(bool flag) VL_MT_SAFE; /// Return if to throw fatal error on VPI errors bool fatalOnVpiError() const VL_MT_SAFE { return m_s.m_fatalOnVpiError; } - /// Set if got a $stop or non-fatal error - void gotError(bool flag) VL_MT_SAFE; + /// Set to throw fatal error on VPI errors + void fatalOnVpiError(bool flag) VL_MT_SAFE; /// Return if got a $stop or non-fatal error bool gotError() const VL_MT_SAFE { return m_s.m_gotError; } - /// Set if got a $finish or $stop/error - void gotFinish(bool flag) VL_MT_SAFE; + /// Set if got a $stop or non-fatal error + void gotError(bool flag) VL_MT_SAFE; /// Return if got a $finish or $stop/error bool gotFinish() const VL_MT_SAFE { return m_s.m_gotFinish; } - /// Enable quiet (also prevents need for OS calls to get CPU time) - void quiet(bool flag) VL_MT_SAFE; + /// Set if got a $finish or $stop/error + void gotFinish(bool flag) VL_MT_SAFE; /// Return if quiet enabled bool quiet() const VL_MT_SAFE { return m_s.m_quiet; } + /// Enable quiet (also prevents need for OS calls to get CPU time) + void quiet(bool flag) VL_MT_SAFE; + /// Return randReset value + int randReset() VL_MT_SAFE { return m_s.m_randReset; } /// Select initial value of otherwise uninitialized signals. /// 0 = Set to zeros /// 1 = Set all bits to one /// 2 = Randomize all bits void randReset(int val) VL_MT_SAFE; - /// Return randReset value - int randReset() VL_MT_SAFE { return m_s.m_randReset; } - /// Return default random seed - void randSeed(int val) VL_MT_SAFE; /// Set default random seed, 0 = seed it automatically int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; } + /// Return default random seed + void randSeed(int val) VL_MT_SAFE; /// Return statistic: CPU time delta from model created until now double statCpuTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex); @@ -607,27 +606,27 @@ public: enableExecutionProfiler(VerilatedVirtualBase* (*construct)(VerilatedContext&)); // Internal: coverage - void coverageFilename(const std::string& flag) VL_MT_SAFE; std::string coverageFilename() const VL_MT_SAFE; + void coverageFilename(const std::string& flag) VL_MT_SAFE; // Internal: $dumpfile - void dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex); std::string dumpfile() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex); + void dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex); std::string dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex); // Internal: --prof-exec related settings - void profExecStart(uint64_t flag) VL_MT_SAFE; uint64_t profExecStart() const VL_MT_SAFE { return m_ns.m_profExecStart; } - void profExecWindow(uint64_t flag) VL_MT_SAFE; + void profExecStart(uint64_t flag) VL_MT_SAFE; uint32_t profExecWindow() const VL_MT_SAFE { return m_ns.m_profExecWindow; } - void profExecFilename(const std::string& flag) VL_MT_SAFE; + void profExecWindow(uint64_t flag) VL_MT_SAFE; std::string profExecFilename() const VL_MT_SAFE; - void profVltFilename(const std::string& flag) VL_MT_SAFE; + void profExecFilename(const std::string& flag) VL_MT_SAFE; std::string profVltFilename() const VL_MT_SAFE; + void profVltFilename(const std::string& flag) VL_MT_SAFE; // Internal: SMT solver program - void solverProgram(const std::string& flag) VL_MT_SAFE; std::string solverProgram() const VL_MT_SAFE; + void solverProgram(const std::string& flag) VL_MT_SAFE; // Internal: Find scope const VerilatedScope* scopeFind(const char* namep) const VL_MT_SAFE; @@ -804,18 +803,18 @@ public: } #ifndef VL_NO_LEGACY - /// Call VerilatedContext::assertOn using current thread's VerilatedContext - static void assertOn(bool flag) VL_MT_SAFE { Verilated::threadContextp()->assertOn(flag); } /// Return VerilatedContext::assertOn() using current thread's VerilatedContext static bool assertOn() VL_MT_SAFE { return Verilated::threadContextp()->assertOn(); } - /// Call VerilatedContext::calcUnusedSigs using current thread's VerilatedContext - static void calcUnusedSigs(bool flag) VL_MT_SAFE { - Verilated::threadContextp()->calcUnusedSigs(flag); - } + /// Call VerilatedContext::assertOn using current thread's VerilatedContext + static void assertOn(bool flag) VL_MT_SAFE { Verilated::threadContextp()->assertOn(flag); } /// Return VerilatedContext::calcUnusedSigs using current thread's VerilatedContext static bool calcUnusedSigs() VL_MT_SAFE { return Verilated::threadContextp()->calcUnusedSigs(); } + /// Call VerilatedContext::calcUnusedSigs using current thread's VerilatedContext + static void calcUnusedSigs(bool flag) VL_MT_SAFE { + Verilated::threadContextp()->calcUnusedSigs(flag); + } /// Call VerilatedContext::commandArgs using current thread's VerilatedContext static void commandArgs(int argc, const char** argv) VL_MT_SAFE { Verilated::threadContextp()->commandArgs(argc, argv); @@ -958,8 +957,8 @@ public: // Internal: Set the mtaskId, called when an mtask starts // Per thread, so no need to be in VerilatedContext - static void mtaskId(uint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; } static uint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; } + static void mtaskId(uint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; } static void endOfEvalReqdInc() VL_MT_SAFE { ++t_s.t_endOfEvalReqd; } static void endOfEvalReqdDec() VL_MT_SAFE { --t_s.t_endOfEvalReqd; } diff --git a/include/verilated_cov.h b/include/verilated_cov.h index 51a0c3b4f..13c3d2806 100644 --- a/include/verilated_cov.h +++ b/include/verilated_cov.h @@ -92,9 +92,9 @@ public: std::string defaultFilename() VL_MT_SAFE; /// Make all data per_instance, overriding point's per_instance void forcePerInstance(bool flag) VL_MT_SAFE; + void write() VL_MT_SAFE { write(defaultFilename()); } /// Write all coverage data to a file void write(const std::string& filename) VL_MT_SAFE; - void write() VL_MT_SAFE { write(defaultFilename()); } /// Clear coverage points (and call delete on all items) void clear() VL_MT_SAFE; /// Clear items not matching the provided string diff --git a/test_regress/t/t_dist_getsetorder.pl b/test_regress/t/t_dist_getsetorder.pl new file mode 100755 index 000000000..240c3c471 --- /dev/null +++ b/test_regress/t/t_dist_getsetorder.pl @@ -0,0 +1,60 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Hacky import order checker, used to ensure all getters +# come before setters for consistent codegen when using autocxx (#5182) +# +# Copyright 2024 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(dist => 1); + +my $root = ".."; + +### Must trim output before and after our file list +my %files = %{get_source_files($root)}; + +foreach my $file (sort keys %files) { + my $filename = "$root/$file"; + next if !-f $filename; # git file might be deleted but not yet staged + next unless $file =~ /include.*verilated.*\.(h)(\.in)?$/; + next if $file =~ /gtkwave/; + + my $contents = file_contents($filename); + my %seen_setters; + my %seen_getters; + foreach my $line (split(/\n/, $contents . "\n\n")) { + next if $line =~ /^\s*\/\//; # skip commented lines + if($line =~ /\s*void\s+([a-zA-Z0-9]+)\([a-zA-Z0-9]+.*/) { + my $setter_name = $1; + $seen_setters{$setter_name} = 1; + } else { + next unless $line =~ /\s*[a-zA-Z0-9]+\s+([a-zA-Z0-9]+)\(\s*\)/; + my $getter_name = $1; + if($file =~ /verilated_sc_trace/ and $getter_name == "cycle") { + next; # hardcoded check for cycle() which looks like a setter but isn't + } + if(exists $seen_setters{$getter_name} and not (exists $seen_getters{$getter_name})) { + error("$getter_name came after its setter in $file"); + } + $seen_getters{$getter_name} = 1; + } + } +} + +ok(1); +1; + +sub get_source_files { + my $root = shift; + my $git_files = `cd $root && git ls-files`; + print "MF $git_files\n" if $Self->{verbose}; + my %files; + foreach my $file (split /\s+/, $git_files) { + next if $file eq ''; + $files{$file} |= 1; + } + return \%files; +}