Compare commits

...
91 Commits
Author SHA1 Message Date
Wilson Snyder b350b6a0ff Version bump 2020-12-02 20:09:23 -05:00
Wilson Snyder 80564a8f89 Remove vgen test to avoid Bit::Vector for testing. 2020-12-02 20:06:07 -05:00
Yuri Victorovich 016611021d Fix the default GNU Make executable name on FreeBSD (#2553) 2020-12-02 19:27:53 -05:00
Wilson Snyder fa20614277 Fix Ubuntu 16.04 LTS warning 2020-12-02 19:20:03 -05:00
Wilson Snyder 1e69167191 Internals: Move function in V3Width. No functional change. 2020-12-02 18:51:29 -05:00
Wilson Snyder faa5edc068 Add TspStateBase destructor (#2620). 2020-12-02 07:37:34 -05:00
Wilson Snyder e3c32adad4 Rename static/thread misnamed variables. No functional change. 2020-12-01 19:32:01 -05:00
Wilson Snyder b054d937cb Rename static/thread misnamed variables. No functional change. 2020-12-01 19:01:20 -05:00
Wilson Snyder 212e8fb14b Internals: Cleanup some inlines, use constexpr. No functional change intended. 2020-12-01 18:49:03 -05:00
Wilson Snyder 014e43f0ef Reset index counts on clearing verilated_cov (static removal) 2020-12-01 18:30:25 -05:00
Wilson Snyder d21b4e3fc7 Internal cast preparatory cleanups. 2020-11-29 18:26:06 -05:00
Wilson Snyder 0818d88113 Tests: Cast enum test 2020-11-29 16:59:08 -05:00
Wilson Snyder 77ec2dc875 Internals: Rename some CI comments 2020-11-29 15:06:29 -05:00
Wilson Snyder 665e8edaff Support $monitor and $strobe. 2020-11-29 11:31:38 -05:00
Wilson Snyder 67103d346b Fix $fwriteh/$fwriteo 2020-11-29 10:53:44 -05:00
Wilson Snyder aebb54444e Internals: Favor NodeProcedure. No functional change intended. 2020-11-29 09:50:30 -05:00
Wilson Snyder a54ac52a35 Internals: Use 'Bit' where mean 2-state type. No functional change. 2020-11-29 08:23:36 -05:00
Wilson Snyder aa360052a8 Internals: Code movement, no functional change. 2020-11-28 22:01:11 -05:00
Wilson Snyder e09f039a36 Internals: Remove dead code. No functional change. 2020-11-28 21:43:37 -05:00
Wilson Snyder ff262fc4fb Support type(t) static casting 2020-11-28 17:29:21 -05:00
Wilson Snyder 9a9931fb9d Support complex function arguments. 2020-11-28 13:46:14 -05:00
Wilson Snyder 30686d8550 Support passing of objects to functions 2020-11-28 12:43:24 -05:00
Wilson Snyder 05f3fd7c6e Fix class new with math. 2020-11-28 12:26:44 -05:00
Wilson Snyder e14319b401 Internals: Refactor V3Param through code movement only. No functional change intended. 2020-11-28 12:04:29 -05:00
Wilson Snyder 1299b70945 Internals: Pass class parameters through link. 2020-11-27 22:48:42 -05:00
Wilson Snyder cf2810db8b Change -sv option to select 1800-2017 instead of 1800-2005. 2020-11-27 21:49:47 -05:00
Wilson Snyder d77beecc6e Fix $countbits(..., 'z) 2020-11-27 21:34:40 -05:00
Wilson Snyder 0c6bd42da3 Fix $countbits(..., 'x) 2020-11-27 20:51:32 -05:00
Wilson Snyder 5091298fae Internals: Cleanup V3Unknown. No functional change intended. 2020-11-27 20:25:02 -05:00
Wilson Snyder cef7610b14 Fix crash on virtual interfaces. 2020-11-27 20:02:17 -05:00
Wilson Snyder ed268805ce Lint check for pure virtual in non-virtual class. 2020-11-27 19:53:04 -05:00
Wilson Snyder 123d1af29d Fix crash on non-class static function 2020-11-27 14:58:50 -05:00
Wilson Snyder cc307626c0 Tests: Add class name test. 2020-11-27 10:34:31 -05:00
Wilson Snyder 963fd0664d Fix class-in-module issues 2020-11-27 09:42:51 -05:00
Wilson Snyder 4643d6e883 Internals: Refactor V3Param through code movement only. No functional change intended. 2020-11-27 09:17:44 -05:00
Wilson Snyder d89fc05da1 Internals: Refactor V3Param through code movement only. No functional change intended. 2020-11-27 09:04:56 -05:00
Wilson Snyder 84d7380588 Internals: Param immediate delete, in prep for next commit. No functional change intended. 2020-11-27 08:50:29 -05:00
Wilson Snyder 04febb1944 Internals: Move V3Param code. No functional change. 2020-11-26 15:03:55 -05:00
Wilson Snyder d56b923eaa Fix 'randomize() with {}' crash 2020-11-26 11:50:50 -05:00
Wilson Snyder a37866ee92 Support 'super'. 2020-11-26 11:06:59 -05:00
Wilson Snyder 1a92a44c7d Internals: Assert on misexpected 'new'. 2020-11-26 09:38:47 -05:00
Wilson Snyder 60a1d25a96 Fix extern function member references. 2020-11-26 08:55:32 -05:00
Wilson Snyder ad21f2e850 Fix 'this' in extern functions. 2020-11-26 08:28:53 -05:00
Wilson Snyder ffbae97a3d Tests: Make t_lint_syncasyncnet_bad etc tolerate -Oi. 2020-11-25 21:54:50 -05:00
Wilson Snyder 380137a402 Fix internal pointer shown on CLKDATA warnings 2020-11-25 21:34:56 -05:00
Wilson Snyder ac2058c7ec Tests: Fix t_unopt_combo_waive with -Oi 2020-11-25 21:18:13 -05:00
Wilson Snyder de931d6a97 Fix LHS is not a lvalue when using tristate with -Oi. 2020-11-25 21:09:25 -05:00
Wilson Snyder f2d8e45d72 For performance, use unordered_set/map where possible. No functional change intended. 2020-11-25 20:57:30 -05:00
Wilson Snyder 085ef5fc05 Fix extern function var refs getting errors. 2020-11-25 20:05:44 -05:00
Wilson Snyder 6095efd84e Check for proper 'local' and 'protected' (#2228). 2020-11-25 07:03:01 -05:00
Wilson Snyder 114ab1378f Internals: Track class package on membersels 2020-11-24 23:36:09 -05:00
Wilson Snyder 8622c754b7 Fix unstable statistic 2020-11-24 23:35:44 -05:00
Wilson Snyder bf24fa9478 Fix access to non-overridden base class variable (#2654). 2020-11-24 22:46:02 -05:00
Wilson Snyder e1c45440fc Internals: Rename packagep(). No functional change. 2020-11-24 21:56:03 -05:00
Wilson Snyder b0cb43b2f2 Fix not iterating some extended classes depending on declaration order. 2020-11-24 21:41:32 -05:00
Wilson Snyder dc1f44840d Internals: Fix not clearing packagep on some assignments. Should affect assertions only. 2020-11-24 21:34:11 -05:00
Wilson Snyder fd21a41acd Internals: Minor cleanups before class fix (#2654). No functional change intended. 2020-11-24 21:28:26 -05:00
Wilson Snyder cf09a9b6d2 Commentary 2020-11-24 18:45:36 -05:00
Wilson Snyder dc306cf371 Internal debug: avoid segflt with gdb "pnt" 2020-11-24 18:35:12 -05:00
Wilson Snyder 35374f09b4 Add error on class extending itself 2020-11-24 18:15:49 -05:00
Wilson Snyder e85a2e860e Support 'with item.index'. 2020-11-23 23:18:58 -05:00
Wilson Snyder 103ba1fb6d Commentary 2020-11-20 21:48:11 -05:00
Wilson Snyder b684995292 Support $random and $urandom seeds. 2020-11-19 21:32:33 -05:00
Wilson Snyder c371a63d41 Internals: Fix missing final. No functional change. 2020-11-19 08:23:15 -05:00
Yutetsu TAKATSUKASA 0102efd4ea Support unpacked array in DPI-C (#2648)
* Add tests for unpacked array in DPI-C

* Add more generic parameter generator to AstNodes

* Supports multi dimensional array in DPI ( DPI argmuments <=> Verilator internal type conversion)

consider typedef in V3Task

fix export test

fix inout for scalar

support export func of time

* V3Premit does not show an error for wide words nor ArraySel

* Unnecessary pack func for unapcked array does not appear anymore

* Support unpacked array in runtime header

- Add an overload for lvalue VL_CVT_PACK_STR_NN
- Allow conversion from void *

* touch up tests for codacy advices

* resolve free functions. no functional change intended.
2020-11-19 22:02:58 +09:00
Wilson Snyder abfee1270f Improve internal code coverage 2020-11-18 22:21:48 -05:00
Wilson Snyder 5992d678be Fix clang error, broke last commit. 2020-11-18 22:18:29 -05:00
Wilson Snyder b6ded59c2b Internals: Use and enforce class final for ~5% performance boost. 2020-11-18 21:32:16 -05:00
Wilson Snyder c0888c1b0f Internals: Use newline instead of endl to avoid unneeded flush. 2020-11-18 21:03:23 -05:00
Wilson Snyder fa77141519 Fix unpacked array parameters near functions (#2639). 2020-11-18 20:12:14 -05:00
Wilson Snyder b3760911e7 Internals: Param minor cleanups. No functional change intended. 2020-11-18 19:50:47 -05:00
Yutetsu TAKATSUKASA b500e57991 Add an overload of VL_CVT_PACK_STR_NN for lvalue (#2651) 2020-11-19 06:52:03 +09:00
Yutetsu TAKATSUKASA 19e4013ab5 Allow conversion from const void * to QData (#2650) 2020-11-18 23:44:45 +09:00
Wilson Snyder 82b2af3b83 Commentary 2020-11-17 22:48:37 -05:00
Wilson Snyder e6f7510895 Add check for rand_mode/constraint_mode. 2020-11-17 22:14:18 -05:00
Wilson Snyder 2f718b9ea0 Show IEEE reference in array port message, plus internal cleanups. 2020-11-17 21:10:50 -05:00
Marlon James 899e7bacb2 Fix VPI callback list iteration (#2644)
The end iterator always points to an element past the end of the list.
When new elements are added to the back of the list, they are inserted
before the end iterator.
Instead, track the last element in the list at the start of processing
and stop after it's been processed.
2020-11-17 17:19:51 -05:00
Tomasz Gorochowik 5b3717b369 Tests: Memory clean up in tests (#2645)
This patch normalizes what the tests do before exiting. After this
change each test should call final on the top module and explicitly
free the top module object before exiting.
2020-11-17 06:37:55 -05:00
Wilson Snyder 1e7c61b23e Internals: Refactor huge func in V3Param. No functional change intended. 2020-11-16 22:35:51 -05:00
Marlon James 0e1e380a55 Fix test for callCbs() so it can fail (#2613) 2020-11-16 21:00:09 -05:00
Wilson Snyder 1b0a48ea02 Internals: Use C++11 = default where obvious. No functional change intended. 2020-11-16 19:56:16 -05:00
Wilson Snyder 70b3a599ce Fix trace signal names getting hashed (#2643). 2020-11-16 18:11:27 -05:00
Wilson Snyder 26c0e6ba00 Fix missing array include. 2020-11-16 07:31:12 -05:00
Wilson Snyder efc6fb7fc3 Internals: Better pack AstNode. No functional change. 2020-11-15 22:03:06 -05:00
Wilson Snyder b68038a73f clang-tidy fix. No functional change. 2020-11-15 17:23:02 -05:00
Wilson Snyder f4ef4ad9f3 Internals: Favor std::array where easy. No functional change intended. 2020-11-15 16:21:26 -05:00
Wilson Snyder f6f7684ccd Internal member initialization. No functional change intended. 2020-11-15 15:40:35 -05:00
Wilson Snyder e74cc32f2d Add internal assertion that VarScopes properly formed. 2020-11-14 16:13:06 -05:00
Wilson Snyder c64cc989f0 verilator_gantt: Show CPU physical info. 2020-11-14 12:22:15 -05:00
Wilson Snyder f94fcaa8e4 Move YYDEBUG into header. No functional change intended. 2020-11-14 10:20:27 -05:00
Wilson Snyder 297b297bc7 devel release 2020-11-14 10:00:01 -05:00
421 changed files with 13443 additions and 5591 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-modernize*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-default-arguments,-fuchsia-overloaded-operator,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance'
Checks: '*,-hicpp*,-android-cloexec-fopen,-cert-dcl50-cpp,-cert-env33-c,-cert-err34-c,-cert-err58-cpp,-clang-analyzer-core.UndefinedBinaryOperatorResult,-clang-analyzer-security*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-no-malloc,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-special-member-functions,-fuchsia-*,-google-default-arguments,-google-readability-todo,-google-runtime-references,-llvm-header-guard,-llvm-include-order,-misc-string-integer-assignment,-misc-string-literal-with-embedded-nul,-modernize-use-auto,-modernize-use-trailing-return-type,-readability-braces-around-statements,-readability-container-size-empty,-readability-delete-null-pointer,-readability-else-after-return,-readability-implicit-bool-conversion,-readability-named-parameter,-readability-static-accessed-through-instance'
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none
+27 -1
View File
@@ -2,9 +2,35 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.106 2020-12-02
** Change -sv option to select 1800-2017 instead of 1800-2005.
*** Check for proper 'local' and 'protected' (#2228).
*** Support $random and $urandom seeds.
*** Support $monitor and $strobe.
*** Support complex function arguments.
*** Support 'super'.
*** Support 'with item.index'.
**** Fix the default GNU Make executable name on FreeBSD (#2553). [Yuri Victorovich]
**** Fix trace signal names getting hashed (#2643). [Barbara Gigerl]
**** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva]
**** Fix access to non-overridden base class variable (#2654). [Tobias Rosenkranz]
* Verilator 4.104 2020-11-14
*** Support queue and associative array 'with' statements. (#2616)
*** Support queue and associative array 'with' statements (#2616).
*** Support queue slicing (#2326).
+3 -2
View File
@@ -445,12 +445,13 @@ CLANGTIDY = clang-tidy
CLANGTIDY_FLAGS = -config='' -checks='-fuchsia-*,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-init-variables'
CLANGTIDY_DEP = $(subst .h,.h.tidy,$(CPPCHECK_H)) \
$(subst .cpp,.cpp.tidy,$(CPPCHECK_CPP))
CLANGTIDY_DEFS = -DVL_DEBUG=1 -DVL_THREADED=1 -DVL_CPPCHECK=1
clang-tidy: $(CLANGTIDY_DEP)
%.cpp.tidy: %.cpp
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
%.h.tidy: %.h
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) | 2>&1 tee $@
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
analyzer-src:
-rm -rf src/obj_dbg
+10 -14
View File
@@ -1461,7 +1461,7 @@ future version of Verilator no longer always packs unpacked structures.
=item -sv
Specifies SystemVerilog language features should be enabled; equivalent to
"--language 1800-2005". This option is selected by default, it exists for
"--language 1800-2017". This option is selected by default, it exists for
compatibility with other simulators.
=item +systemverilogext+I<ext>
@@ -1996,14 +1996,15 @@ section below for descriptions of some of the files that were created.
(Verilator included a default compile rule and link rule, since we used
--exe and passed a .cpp file on the Verilator command line. Verilator also
then used C<make> to build a final executable. You can also write your own
compile rules, and run make yourself as we'll show in the SYSTEMC section.)
then used C<make> to build a final executable, since we used --build. You
can also write your own compile rules, and run make yourself as we'll show
in the SYSTEMC section.
And now we run it
And now we run it:
obj_dir/Vour
And we get as output
And we get as output:
Hello World
- our.v:2: Verilog $finish
@@ -4106,17 +4107,12 @@ $setup, $setuphold, $skew, $timeskew, $width
All specify blocks and timing checks are ignored.
=item $monitor, $strobe
Monitor and strobe are not supported, convert to always_comb $display or
similar.
=item $random, $urandom, $urandom_range
$random and $urandom do not support the optional argument to set the seed.
Use +verilator+seed argument to set the seed. There is one random seed per
C thread, not per module for $random, nor per object for random stability
of $urandom/$urandom_range.
Use +verilator+seed argument to set the seed if there is no $random or
$urandom optional argument to set the seed. There is one random seed per C
thread, not per module for $random, nor per object for random stability of
$urandom/$urandom_range.
=item $readmemb, $readmemh
+72 -4
View File
@@ -60,6 +60,7 @@ sub process {
my $filename = shift;
read_data($filename);
read_cpuinfo();
report();
}
@@ -70,7 +71,7 @@ sub read_data {
%Global = (rdtsc_cycle_time => 0);
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,";
while (my $line = $fh->getline) {
if ($line =~ m/VLPROF mtask\s(\d+)\sstart\s(\d+)\send\s(\d+)\selapsed\s(\d+)\spredict_time\s(\d+)\scpu\s(\d+)\son thread (\d+)/) {
my $mtask = $1;
@@ -113,6 +114,27 @@ sub read_data {
}
}
sub read_cpuinfo {
my $filename = "/proc/cpuinfo";
my $fh = IO::File->new("<$filename") or return;
my $cpu;
while (my $line = $fh->getline) {
chomp $line;
if ($line =~ m/^processor\s*:\s*(\d+)\s*$/) {
$cpu = $1;
}
if ($cpu && $line =~ m/^([a-z_ ]+)\s*:\s*(.*)$/) {
my ($term, $value) = ($1, $2);
$term =~ s/\s+$//;
$term =~ s/\s+/_/;
$value =~ s/\s+$//;
$Global{cpuinfo}{$cpu}{$term} = $value;
}
}
}
#######################################################################
sub report {
print "Verilator Gantt report\n";
@@ -162,9 +184,9 @@ sub report {
printf " Total eval time = %d rdtsc ticks\n", $Global{last_end};
printf " Longest mtask time = %d rdtsc ticks\n", $long_mtask_time;
printf " All-thread mtask time = %d rdtsc ticks\n", $mt_mtask_time;
my $long_efficiency = $long_mtask_time/($Global{last_end});
my $long_efficiency = $long_mtask_time/($Global{last_end} || 1);
printf " Longest-thread efficiency = %0.1f%%\n", $long_efficiency*100;
my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads);
my $mt_efficiency = $mt_mtask_time/($Global{last_end}*$nthreads || 1);
printf " All-thread efficiency = %0.1f%%\n", $mt_efficiency*100;
printf " All-thread speedup = %0.1f\n", $mt_efficiency*$nthreads;
if ($Global{rdtsc_cycle_time} > 0) {
@@ -210,13 +232,58 @@ sub report {
printf " mean = %0.3f\n", $mean;
printf " stddev = %0.3f\n", $stddev;
printf " e ^ stddev = %0.3f\n", exp($stddev);
print "\n";
report_cpus();
if ($nthreads > $ncpus) {
print "\n";
print "%Warning: There were fewer CPUs ($ncpus) then threads ($nthreads).\n";
print " : See docs on use of numactl.\n";
} else {
if ($Global{cpu_socket_cores_warning}) {
print "\n";
print "%Warning: Multiple threads scheduled on same hyperthreaded core.\n";
print " : See docs on use of numactl.\n";
}
if ($Global{cpu_sockets_warning}) {
print "\n";
print "%Warning: Threads scheduled on multiple sockets.\n";
print " : See docs on use of numactl.\n";
}
}
print "\n";
}
sub report_cpus {
print "\nCPUs:\n";
# Test - show all cores
# for (my $i=0; $i<73; ++$i) { $Global{cpus}{$i} ||= {cpu_time => 0}; }
$Global{cpu_sockets} ||= {};
$Global{cpu_socket_cores} ||= {};
foreach my $cpu (sort {$a <=> $b} keys %{$Global{cpus}}) {
printf " cpu %d: ", $cpu;
printf "cpu_time=%d", $Global{cpus}{$cpu}{cpu_time};
my $socket = $Global{cpuinfo}{$cpu}{physical_id};
$Global{cpu_sockets}{$socket}++ if defined $socket;
printf " socket=%d", $socket if defined $socket;
my $core = $Global{cpuinfo}{$cpu}{core_id};
$Global{cpu_socket_cores}{$socket."__".$core}++ if defined $socket && defined $core;
printf " core=%d", $core if defined $core;
my $model = $Global{cpuinfo}{$cpu}{model_name};
printf " %s", $model if defined $model;
print "\n";
}
$Global{cpu_sockets_warning} = 1
if (scalar keys %{$Global{cpu_sockets}} > 1);
foreach my $scn (values %{$Global{cpu_socket_cores}}) {
$Global{cpu_socket_cores_warning} = 1 if $scn > 1;
}
}
sub report_graph {
@@ -230,6 +297,7 @@ sub report_graph {
}
# One more step so we can fit more labels
$time_per = int($time_per/2);
$time_per ||= 1;
}
my ($graph, $conflicts) = _make_graph($time_per);
+1 -1
View File
@@ -40,7 +40,7 @@ RUN apt-get update \
WORKDIR /tmp
RUN cpan install -fi Unix::Processors Parallel::Forker Bit::Vector
RUN cpan install -fi Unix::Processors Parallel::Forker
RUN git clone https://github.com/veripool/vcddiff.git && \
make -C vcddiff && \
-1
View File
@@ -94,7 +94,6 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
if [ "$TRAVIS_DIST" != "trusty" ]; then
TRAVIS_CPAN_REPO=https://cpan.org
fi
# Not listing Bit::Vector as slow to install, and only skips one test
yes yes | sudo cpan -M $TRAVIS_CPAN_REPO -fi Unix::Processors Parallel::Forker
install-vcddiff
else
+1 -1
View File
@@ -7,7 +7,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[4.104 2020-11-14],
AC_INIT([Verilator],[4.106 2020-12-02],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file
-1
View File
@@ -102,7 +102,6 @@ Those developing Verilator itself may also want these (see internals.adoc):
cpan install Pod::Perldoc
cpan install Unix::Processors
cpan install Parallel::Forker
cpan install Bit::Vector
==== Install SystemC
+2 -4
View File
@@ -628,8 +628,6 @@ https://github.com/veripool/vcddiff
* Cmake for build paths that use it.
* Bit::Vector to test vgen.pl
=== Controlling the Test Driver
Test drivers are written in PERL. All invoke the main test driver script,
@@ -959,9 +957,9 @@ Then, when the watch fires, to break at every following change to that node:
To print a node:
pn nodep
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
# or: call dumpGdb(nodep) # aliased to "pn" in src/.gdbinit
pnt nodep
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
# or: call dumpTreeGdb(nodep) # aliased to "pnt" in src/.gdbinit
When GDB halts, it is useful to understand that the backtrace will commonly
show the iterator functions between each invocation of `visit` in the
+165 -156
View File
@@ -61,7 +61,7 @@ typedef union {
// Global variables
// Slow path variables
VerilatedMutex Verilated::m_mutex;
VerilatedMutex Verilated::s_mutex;
// Keep below together in one cache line
Verilated::Serialized Verilated::s_s;
@@ -75,7 +75,7 @@ VerilatedImp::VerilatedImpU VerilatedImp::s_s;
struct VerilatedImpInitializer {
VerilatedImpInitializer() { VerilatedImp::setup(); }
~VerilatedImpInitializer() { VerilatedImp::teardown(); }
} g_VerilatedImpInitializer;
} s_VerilatedImpInitializer;
//===========================================================================
// User definable functions
@@ -256,6 +256,7 @@ Verilated::Serialized::Serialized() {
s_errorLimit = 1;
s_randReset = 0;
s_randSeed = 0;
s_randSeedEpoch = 1;
s_timeunit = VL_TIME_UNIT; // Initial value until overriden by _Vconfigure
s_timeprecision = VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
}
@@ -279,6 +280,8 @@ void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.v.m_s
static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
// Return random 32-bits using system library.
// Used only to construct seed for Verilator's PNRG.
static VerilatedMutex s_mutex;
const VerilatedLockGuard lock(s_mutex); // Otherwise rand is unsafe
#if defined(_WIN32) && !defined(__CYGWIN__)
// Windows doesn't have lrand48(), although Cygwin does.
return (rand() << 16) ^ rand();
@@ -288,29 +291,18 @@ static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
}
vluint64_t vl_rand64() VL_MT_SAFE {
static VerilatedMutex s_mutex;
static VL_THREAD_LOCAL bool t_seeded = false;
static VL_THREAD_LOCAL vluint32_t t_seedEpoch = 0;
static VL_THREAD_LOCAL vluint64_t t_state[2];
if (VL_UNLIKELY(!t_seeded)) {
t_seeded = true;
{
const VerilatedLockGuard lock(s_mutex);
if (Verilated::randSeed() != 0) {
t_state[0] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
^ (static_cast<vluint64_t>(Verilated::randSeed())));
t_state[1] = ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
^ (static_cast<vluint64_t>(Verilated::randSeed())));
} else {
t_state[0] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
^ (static_cast<vluint64_t>(vl_sys_rand32())));
t_state[1] = ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
^ (static_cast<vluint64_t>(vl_sys_rand32())));
}
// Fix state as algorithm is slow to randomize if many zeros
// This causes a loss of ~ 1 bit of seed entropy, no big deal
if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0];
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
}
// For speed, we use a thread-local epoch number to know when to reseed
if (VL_UNLIKELY(t_seedEpoch != Verilated::randSeedEpoch())) {
// Set epoch before state, in case races with new seeding
t_seedEpoch = Verilated::randSeedEpoch();
t_state[0] = Verilated::randSeedDefault64();
t_state[1] = t_state[0];
// Fix state as algorithm is slow to randomize if many zeros
// This causes a loss of ~ 1 bit of seed entropy, no big deal
if (VL_COUNTONES_I(t_state[0]) < 10) t_state[0] = ~t_state[0];
if (VL_COUNTONES_I(t_state[1]) < 10) t_state[1] = ~t_state[1];
}
// Xoroshiro128+ algorithm
vluint64_t result = t_state[0] + t_state[1];
@@ -334,6 +326,11 @@ WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
}
// LCOV_EXCL_STOP
IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE {
Verilated::randSeed(static_cast<int>(seed));
return VL_RANDOM_I(obits);
}
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
if (Verilated::randReset() == 0) return 0;
IData data = ~0;
@@ -688,7 +685,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
// Note uses a single buffer internally; presumes only one usage per printf
// Note also assumes variables < 64 are not wide, this assumption is
// sometimes not true in low-level routines written here in verilated.cpp
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD_LOCAL char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
const char* pctp = nullptr; // Most recent %##.##g format
bool inPct = false;
bool widthSet = false;
@@ -766,11 +763,11 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
if (lbits) {} // UNUSED - always 64
if (fmt == '^') { // Realtime
if (!widthSet) width = VerilatedImp::timeFormatWidth();
output += _vl_vsformat_time(tmp, d, left, width);
output += _vl_vsformat_time(t_tmp, d, left, width);
} else {
std::string fmts(pctp, pos - pctp + 1);
sprintf(tmp, fmts.c_str(), d);
output += tmp;
sprintf(t_tmp, fmts.c_str(), d);
output += t_tmp;
}
break;
}
@@ -814,9 +811,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
int digits = 0;
std::string append;
if (lbits <= VL_QUADSIZE) {
digits = sprintf(tmp, "%" VL_PRI64 "d",
digits = sprintf(t_tmp, "%" VL_PRI64 "d",
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
append = tmp;
append = t_tmp;
} else {
if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
WData neg[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
@@ -843,8 +840,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
int digits = 0;
std::string append;
if (lbits <= VL_QUADSIZE) {
digits = sprintf(tmp, "%" VL_PRI64 "u", ld);
append = tmp;
digits = sprintf(t_tmp, "%" VL_PRI64 "u", ld);
append = t_tmp;
} else {
append = VL_DECIMAL_NW(lbits, lwp);
digits = append.length();
@@ -863,7 +860,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
case 't': { // Time
if (!widthSet) width = VerilatedImp::timeFormatWidth();
output += _vl_vsformat_time(tmp, static_cast<double>(ld), left, width);
output += _vl_vsformat_time(t_tmp, static_cast<double>(ld), left, width);
break;
}
case 'b':
@@ -1037,7 +1034,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
// Read a Verilog $sscanf/$fscanf style format into the output list
// The format must be pre-processed (and lower cased) by Verilator
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD_LOCAL char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
int floc = fbits - 1;
IData got = 0;
bool inPct = false;
@@ -1045,7 +1042,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
const char* pos = formatp;
for (; *pos && !_vl_vsss_eof(fp, floc); ++pos) {
// VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
// fromp, fstr)<<"'"<<endl);
// fromp, fstr)<<"'\n");
if (!inPct && pos[0] == '%') {
inPct = true;
inIgnore = false;
@@ -1101,13 +1098,13 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
}
case 's': {
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, nullptr);
if (!tmp[0]) goto done;
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, nullptr);
if (!t_tmp[0]) goto done;
if (owp) {
int lpos = (static_cast<int>(strlen(tmp))) - 1;
int lpos = (static_cast<int>(strlen(t_tmp))) - 1;
int lsb = 0;
for (int i = 0; i < obits && lpos >= 0; --lpos) {
_vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]);
_vl_vsss_setbit(owp, obits, lsb, 8, t_tmp[lpos]);
lsb += 8;
}
}
@@ -1115,10 +1112,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
}
case 'd': { // Signed decimal
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
if (!t_tmp[0]) goto done;
vlsint64_t ld = 0;
sscanf(tmp, "%30" VL_PRI64 "d", &ld);
sscanf(t_tmp, "%30" VL_PRI64 "d", &ld);
VL_SET_WQ(owp, ld);
break;
}
@@ -1126,46 +1123,47 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
case 'e':
case 'g': { // Real number
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done;
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "+-.0123456789eE");
if (!t_tmp[0]) goto done;
// cppcheck-suppress unusedStructMember // It's used
union {
double r;
vlsint64_t ld;
} u;
u.r = strtod(tmp, nullptr);
u.r = strtod(t_tmp, nullptr);
VL_SET_WQ(owp, u.ld);
break;
}
case 't': // FALLTHRU // Time
case '#': { // Unsigned decimal
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
if (!t_tmp[0]) goto done;
QData ld = 0;
sscanf(tmp, "%30" VL_PRI64 "u", &ld);
sscanf(t_tmp, "%30" VL_PRI64 "u", &ld);
VL_SET_WQ(owp, ld);
break;
}
case 'b': {
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "01xXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_based(owp, obits, 1, tmp, 0, strlen(tmp));
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01xXzZ?_");
if (!t_tmp[0]) goto done;
_vl_vsss_based(owp, obits, 1, t_tmp, 0, strlen(t_tmp));
break;
}
case 'o': {
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "01234567xXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_based(owp, obits, 3, tmp, 0, strlen(tmp));
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01234567xXzZ?_");
if (!t_tmp[0]) goto done;
_vl_vsss_based(owp, obits, 3, t_tmp, 0, strlen(t_tmp));
break;
}
case 'x': {
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, "0123456789abcdefABCDEFxXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_based(owp, obits, 4, tmp, 0, strlen(tmp));
_vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp,
"0123456789abcdefABCDEFxXzZ?_");
if (!t_tmp[0]) goto done;
_vl_vsss_based(owp, obits, 4, t_tmp, 0, strlen(t_tmp));
break;
}
case 'u': {
@@ -1208,7 +1206,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
if (obits == 0) { // Due to inIgnore
} else if (obits == -1) { // string
std::string* p = va_arg(ap, std::string*);
*p = tmp;
*p = t_tmp;
} else if (obits <= VL_BYTESIZE) {
CData* p = va_arg(ap, CData*);
*p = owp[0];
@@ -1332,58 +1330,58 @@ void VL_FCLOSE_I(IData fdi) VL_MT_SAFE {
void VL_FFLUSH_ALL() VL_MT_SAFE { fflush(stdout); }
void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
}
void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
}
void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
}
void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
_VL_STRING_TO_VINT(obits, &destr, t_output.length(), t_output.c_str());
}
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, destp, output.length(), output.c_str());
_VL_STRING_TO_VINT(obits, destp, t_output.length(), t_output.c_str());
}
void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE {
@@ -1396,38 +1394,38 @@ void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, .
}
std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
return output;
return t_output;
}
void VL_WRITEF(const char* formatp, ...) VL_MT_SAFE {
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
VL_PRINTF_MT("%s", output.c_str());
VL_PRINTF_MT("%s", t_output.c_str());
}
void VL_FWRITEF(IData fpi, const char* formatp, ...) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles
static VL_THREAD_LOCAL std::string output; // static only for speed
output = "";
static VL_THREAD_LOCAL std::string t_output; // static only for speed
t_output = "";
va_list ap;
va_start(ap, formatp);
_vl_vsformat(output, formatp, ap);
_vl_vsformat(t_output, formatp, ap);
va_end(ap);
VerilatedImp::fdWrite(fpi, output);
VerilatedImp::fdWrite(fpi, t_output);
}
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
@@ -1648,12 +1646,12 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD_LOCAL char t_outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match.empty()) return nullptr;
outstr[0] = '\0';
strncat(outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+"
t_outstr[0] = '\0';
strncat(t_outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+"
VL_VALUE_STRING_MAX_WIDTH - 1);
return outstr;
return t_outstr;
}
//===========================================================================
@@ -1759,31 +1757,31 @@ const char* vl_dumpctl_filenamep(bool setit, const std::string& filename) VL_MT_
static const char* memhFormat(int nBits) {
assert((nBits >= 1) && (nBits <= 32));
static VL_THREAD_LOCAL char buf[32];
static VL_THREAD_LOCAL char t_buf[32];
switch ((nBits - 1) / 4) {
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
case 0: VL_SNPRINTF(t_buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(t_buf, 32, "%%02x"); break;
case 2: VL_SNPRINTF(t_buf, 32, "%%03x"); break;
case 3: VL_SNPRINTF(t_buf, 32, "%%04x"); break;
case 4: VL_SNPRINTF(t_buf, 32, "%%05x"); break;
case 5: VL_SNPRINTF(t_buf, 32, "%%06x"); break;
case 6: VL_SNPRINTF(t_buf, 32, "%%07x"); break;
case 7: VL_SNPRINTF(t_buf, 32, "%%08x"); break;
default: assert(false); break; // LCOV_EXCL_LINE
}
return buf;
return t_buf;
}
static const char* formatBinary(int nBits, vluint32_t bits) {
assert((nBits >= 1) && (nBits <= 32));
static VL_THREAD_LOCAL char buf[64];
static VL_THREAD_LOCAL char t_buf[64];
for (int i = 0; i < nBits; i++) {
bool isOne = bits & (1 << (nBits - 1 - i));
buf[i] = (isOne ? '1' : '0');
t_buf[i] = (isOne ? '1' : '0');
}
buf[nBits] = '\0';
return buf;
t_buf[nBits] = '\0';
return t_buf;
}
VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end)
@@ -2202,11 +2200,8 @@ void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
//===========================================================================
// Verilated:: Methods
Verilated::ThreadLocal::ThreadLocal() {}
Verilated::ThreadLocal::~ThreadLocal() {}
void Verilated::debug(int level) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_debug = level;
if (level) {
#ifdef VL_DEBUG
@@ -2220,49 +2215,65 @@ void Verilated::debug(int level) VL_MT_SAFE {
}
}
void Verilated::randReset(int val) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_randReset = val;
}
void Verilated::randSeed(int val) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_randSeed = val;
vluint64_t newEpoch = s_s.s_randSeedEpoch + 1;
if (VL_UNLIKELY(newEpoch == 0)) newEpoch = 1;
// Obververs must see new epoch AFTER seed updated
#ifdef VL_THREADED
std::atomic_signal_fence(std::memory_order_release);
#endif
s_s.s_randSeedEpoch = newEpoch;
}
vluint64_t Verilated::randSeedDefault64() VL_MT_SAFE {
if (Verilated::randSeed() != 0) {
return ((static_cast<vluint64_t>(Verilated::randSeed()) << 32)
^ (static_cast<vluint64_t>(Verilated::randSeed())));
} else {
return ((static_cast<vluint64_t>(vl_sys_rand32()) << 32)
^ (static_cast<vluint64_t>(vl_sys_rand32())));
}
}
void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_calcUnusedSigs = flag;
}
void Verilated::errorCount(int val) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_errorCount = val;
}
void Verilated::errorCountInc() VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
++s_s.s_errorCount;
}
void Verilated::errorLimit(int val) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_errorLimit = val;
}
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_gotFinish = flag;
}
void Verilated::assertOn(bool flag) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_assertOn = flag;
}
void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_fatalOnVpiError = flag;
}
void Verilated::timeunit(int value) VL_MT_SAFE {
if (value < 0) value = -value; // Stored as 0..15
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_timeunit = value;
}
void Verilated::timeprecision(int value) VL_MT_SAFE {
if (value < 0) value = -value; // Stored as 0..15
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_s.s_timeprecision = value;
#ifdef SYSTEMC_VERSION
sc_time sc_res = sc_get_time_resolution();
@@ -2293,15 +2304,15 @@ void Verilated::timeprecision(int value) VL_MT_SAFE {
#endif
}
void Verilated::profThreadsStart(vluint64_t flag) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_ns.s_profThreadsStart = flag;
}
void Verilated::profThreadsWindow(vluint64_t flag) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
s_ns.s_profThreadsWindow = flag;
}
void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
const VerilatedLockGuard lock(s_mutex);
if (s_ns.s_profThreadsFilenamep) free(const_cast<char*>(s_ns.s_profThreadsFilenamep));
s_ns.s_profThreadsFilenamep = strdup(flagp);
}
@@ -2309,18 +2320,18 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
// Returns new'ed data
// Used by symbol table creation to make module names
static VL_THREAD_LOCAL char* strp = nullptr;
static VL_THREAD_LOCAL size_t len = 0;
static VL_THREAD_LOCAL char* t_strp = nullptr;
static VL_THREAD_LOCAL size_t t_len = 0;
size_t newlen = strlen(n1) + strlen(n2) + strlen(delimiter) + 1;
if (!strp || newlen > len) {
if (strp) delete[] strp;
strp = new char[newlen];
len = newlen;
if (!t_strp || newlen > t_len) {
if (t_strp) delete[] t_strp;
t_strp = new char[newlen];
t_len = newlen;
}
strcpy(strp, n1);
if (*n1) strcat(strp, delimiter);
strcat(strp, n2);
return strp;
strcpy(t_strp, n1);
if (*n1) strcat(t_strp, delimiter);
strcat(t_strp, n2);
return t_strp;
}
//=========================================================================
@@ -2329,8 +2340,8 @@ const char* Verilated::catName(const char* n1, const char* n2, const char* delim
// Keeping these out of class Verilated to avoid having to include <list>
// in verilated.h (for compilation speed)
typedef std::list<std::pair<Verilated::VoidPCb, void*>> VoidPCbList;
static VoidPCbList g_flushCbs;
static VoidPCbList g_exitCbs;
static VoidPCbList s_flushCbs;
static VoidPCbList s_exitCbs;
static void addCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) {
std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
@@ -2346,16 +2357,16 @@ static void runCallbacks(VoidPCbList& cbs) VL_MT_SAFE {
}
void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
addCb(cb, datap, g_flushCbs);
const VerilatedLockGuard lock(s_mutex);
addCb(cb, datap, s_flushCbs);
}
void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
removeCb(cb, datap, g_flushCbs);
const VerilatedLockGuard lock(s_mutex);
removeCb(cb, datap, s_flushCbs);
}
void Verilated::runFlushCallbacks() VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
runCallbacks(g_flushCbs);
const VerilatedLockGuard lock(s_mutex);
runCallbacks(s_flushCbs);
fflush(stderr);
fflush(stdout);
// When running internal code coverage (gcc --coverage, as opposed to
@@ -2365,16 +2376,16 @@ void Verilated::runFlushCallbacks() VL_MT_SAFE {
}
void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
addCb(cb, datap, g_exitCbs);
const VerilatedLockGuard lock(s_mutex);
addCb(cb, datap, s_exitCbs);
}
void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
removeCb(cb, datap, g_exitCbs);
const VerilatedLockGuard lock(s_mutex);
removeCb(cb, datap, s_exitCbs);
}
void Verilated::runExitCallbacks() VL_MT_SAFE {
const VerilatedLockGuard lock(m_mutex);
runCallbacks(g_exitCbs);
const VerilatedLockGuard lock(s_mutex);
runCallbacks(s_exitCbs);
}
const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; }
@@ -2389,11 +2400,11 @@ void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
const char* Verilated::commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE {
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD_LOCAL char t_outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match.empty()) return "";
outstr[0] = '\0';
strncat(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1);
return outstr;
t_outstr[0] = '\0';
strncat(t_outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1);
return t_outstr;
}
void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
@@ -2648,8 +2659,6 @@ void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const
//======================================================================
// VerilatedScope:: Methods
VerilatedScope::VerilatedScope() {}
VerilatedScope::~VerilatedScope() {
// Memory cleanup - not called during normal operation
VerilatedImp::scopeErase(this);
+33 -27
View File
@@ -129,12 +129,12 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
/// Mutex, wrapped to allow -fthread_safety checks
class VL_CAPABILITY("mutex") VerilatedMutex {
class VL_CAPABILITY("mutex") VerilatedMutex final {
private:
std::mutex m_mutex; // Mutex
public:
VerilatedMutex() {}
~VerilatedMutex() {}
VerilatedMutex() = default;
~VerilatedMutex() = default;
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
/// Acquire/lock mutex
void lock() VL_ACQUIRE() {
@@ -155,7 +155,7 @@ public:
};
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
class VL_SCOPED_CAPABILITY VerilatedLockGuard {
class VL_SCOPED_CAPABILITY VerilatedLockGuard final {
VL_UNCOPYABLE(VerilatedLockGuard);
private:
@@ -174,19 +174,19 @@ public:
#else // !VL_THREADED
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
class VerilatedMutex {
class VerilatedMutex final {
public:
void lock() {}
void unlock() {}
};
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
class VerilatedLockGuard {
class VerilatedLockGuard final {
VL_UNCOPYABLE(VerilatedLockGuard);
public:
explicit VerilatedLockGuard(VerilatedMutex&) {}
~VerilatedLockGuard() {}
~VerilatedLockGuard() = default;
void lock() {}
void unlock() {}
};
@@ -194,7 +194,7 @@ public:
#endif // VL_THREADED
/// Remember the calling thread at construction time, and make sure later calls use same thread
class VerilatedAssertOneThread {
class VerilatedAssertOneThread final {
// MEMBERS
#if defined(VL_THREADED) && defined(VL_DEBUG)
vluint32_t m_threadid; /// Thread that is legal
@@ -230,7 +230,7 @@ public:
class VerilatedScope;
class VerilatedModule {
class VerilatedModule VL_NOT_FINAL {
VL_UNCOPYABLE(VerilatedModule);
private:
@@ -269,7 +269,8 @@ public:
#define VL_CELL(instname, type) ///< Declare a cell, ala SP_CELL
/// Declare a module, ala SC_MODULE
#define VL_MODULE(modname) class modname : public VerilatedModule
#define VL_MODULE(modname) class modname VL_NOT_FINAL : public VerilatedModule
// Not class final in VL_MODULE, as users might be abstracting our models (--hierarchical)
/// Constructor, ala SC_CTOR
#define VL_CTOR(modname) modname(const char* __VCname = "")
@@ -298,7 +299,7 @@ public:
//===========================================================================
/// Verilator symbol table base class
class VerilatedSyms {
class VerilatedSyms VL_NOT_FINAL {
public: // But for internal use only
#ifdef VL_THREADED
VerilatedEvalMsgQueue* __Vm_evalMsgQp;
@@ -311,7 +312,7 @@ public: // But for internal use only
/// Verilator global class information class
/// This class is initialized by main thread only. Reading post-init is thread safe.
class VerilatedScope {
class VerilatedScope final {
public:
typedef enum : vluint8_t {
SCOPE_MODULE,
@@ -330,7 +331,7 @@ private:
Type m_type = SCOPE_OTHER; ///< Type of the scope
public: // But internals only - called from VerilatedModule's
VerilatedScope();
VerilatedScope() = default;
~VerilatedScope();
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
const char* identifier, vlsint8_t timeunit, const Type& type) VL_MT_UNSAFE;
@@ -359,7 +360,7 @@ public: // But internals only - called from VerilatedModule's
Type type() const { return m_type; }
};
class VerilatedHierarchy {
class VerilatedHierarchy final {
public:
static void add(VerilatedScope* fromp, VerilatedScope* top);
};
@@ -367,10 +368,10 @@ public:
//===========================================================================
/// Verilator global static information class
class Verilated {
class Verilated final {
// MEMBERS
// Slow path variables
static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
static VerilatedMutex s_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
static struct Serialized { // All these members serialized/deserialized
// Fast path
@@ -386,8 +387,9 @@ class Verilated {
int s_errorLimit; ///< Stop on error number
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
int s_randSeed; ///< Random seed: 0=random
int s_randSeedEpoch; ///< Number incrementing on each reseed, 0=illegal
Serialized();
~Serialized() {}
~Serialized() = default;
} s_s;
static struct NonSerialized { // Non-serialized information
@@ -407,8 +409,8 @@ class Verilated {
VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED
int argc = 0;
const char** argv = nullptr;
CommandArgValues() {}
~CommandArgValues() {}
CommandArgValues() = default;
~CommandArgValues() = default;
} s_args;
// Not covered by mutex, as per-thread
@@ -422,8 +424,8 @@ class Verilated {
const char* t_dpiFilename = nullptr; ///< DPI context filename
int t_dpiLineno = 0; ///< DPI context line number
ThreadLocal();
~ThreadLocal();
ThreadLocal() = default;
~ThreadLocal() = default;
} t_s;
private:
@@ -442,6 +444,9 @@ public:
static int randReset() VL_MT_SAFE { return s_s.s_randReset; } ///< Return randReset value
static void randSeed(int val) VL_MT_SAFE;
static int randSeed() VL_MT_SAFE { return s_s.s_randSeed; } ///< Return randSeed value
static vluint32_t randSeedEpoch() VL_MT_SAFE { return s_s.s_randSeedEpoch; }
/// Random seed extended to 64 bits, and defaulted if user seed==0
static vluint64_t randSeedDefault64() VL_MT_SAFE;
/// Enable debug of internal verilated code
static void debug(int level) VL_MT_SAFE;
@@ -452,7 +457,7 @@ public:
static inline int debug() VL_MT_SAFE { return s_s.s_debug; }
#else
/// Return constant 0 debug level, so C++'s optimizer rips up
static inline int debug() VL_PURE { return 0; }
static constexpr int debug() VL_PURE { return 0; }
#endif
/// Enable calculation of unused signals
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
@@ -567,8 +572,8 @@ public:
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
static int exportFuncNum(const char* namep) VL_MT_SAFE;
static size_t serialized1Size() VL_PURE { return sizeof(s_s); }
static void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
static constexpr size_t serialized1Size() VL_PURE { return sizeof(s_s); }
static constexpr void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // For Serialize only
static size_t serialized2Size() VL_PURE;
static void* serialized2Ptr() VL_MT_UNSAFE;
#ifdef VL_THREADED
@@ -648,6 +653,7 @@ extern vluint64_t vl_rand64() VL_MT_SAFE;
inline IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
inline QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
extern IData VL_RANDOM_SEEDED_II(int obits, IData seed) VL_MT_SAFE;
inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
vluint64_t rnd = vl_rand64();
if (VL_LIKELY(hi > lo)) {
@@ -753,9 +759,9 @@ static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
u.q = lhs;
return u.fp;
}
/// Return QData from void*
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
union { void* fp; QData q; } u;
/// Return QData from const void*
static inline QData VL_CVT_VP_Q(const void* fp) VL_PURE {
union { const void* fp; QData q; } u;
u.q = 0;
u.fp = fp;
return u.q;
+15 -14
View File
@@ -29,7 +29,7 @@
// VerilatedCovImpBase
/// Implementation base class for constants
struct VerilatedCovImpBase {
struct VerilatedCovImpBase VL_NOT_FINAL {
// TYPES
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
@@ -39,7 +39,7 @@ struct VerilatedCovImpBase {
// VerilatedCovImpItem
/// Implementation class for a VerilatedCov item
class VerilatedCovImpItem : VerilatedCovImpBase {
class VerilatedCovImpItem VL_NOT_FINAL : VerilatedCovImpBase {
public: // But only local to this file
// MEMBERS
int m_keys[MAX_KEYS]; ///< Key
@@ -52,7 +52,7 @@ public: // But only local to this file
m_vals[i] = 0;
}
}
virtual ~VerilatedCovImpItem() {}
virtual ~VerilatedCovImpItem() = default;
virtual vluint64_t count() const = 0;
virtual void zero() const = 0;
};
@@ -63,7 +63,7 @@ public: // But only local to this file
/// This isn't in the header file for auto-magic conversion because it
/// inlines to too much code and makes compilation too slow.
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
template <class T> class VerilatedCoverItemSpec final : public VerilatedCovImpItem {
private:
// MEMBERS
T* m_countp; ///< Count value
@@ -78,7 +78,7 @@ public:
: m_countp{countp} {
*m_countp = 0;
}
virtual ~VerilatedCoverItemSpec() override {}
virtual ~VerilatedCoverItemSpec() override = default;
};
//=============================================================================
@@ -87,7 +87,7 @@ public:
/// All value and keys are indexed into a unique number. Thus we can greatly reduce
/// the storage requirements for otherwise identical keys.
class VerilatedCovImp : VerilatedCovImpBase {
class VerilatedCovImp final : VerilatedCovImpBase {
private:
// TYPES
typedef std::map<const std::string, int> ValueIndexMap;
@@ -99,13 +99,14 @@ private:
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
int m_nextIndex VL_GUARDED_BY(m_mutex) = (KEY_UNDEF + 1); ///< Next insert value
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex) = nullptr; ///< Item about to insert
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex) = nullptr; ///< Filename about to insert
int m_insertLineno VL_GUARDED_BY(m_mutex) = 0; ///< Line number about to insert
// CONSTRUCTORS
VerilatedCovImp() {}
VerilatedCovImp() = default;
VL_UNCOPYABLE(VerilatedCovImp);
public:
@@ -118,14 +119,13 @@ public:
private:
// PRIVATE METHODS
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
static int nextIndex = KEY_UNDEF + 1;
const auto iter = m_valueIndexes.find(value);
if (iter != m_valueIndexes.end()) return iter->second;
nextIndex++;
assert(nextIndex > 0); // Didn't rollover
m_valueIndexes.insert(std::make_pair(value, nextIndex));
m_indexValues.insert(std::make_pair(nextIndex, value));
return nextIndex;
m_nextIndex++;
assert(m_nextIndex > 0); // Didn't rollover
m_valueIndexes.insert(std::make_pair(value, m_nextIndex));
m_indexValues.insert(std::make_pair(m_nextIndex, value));
return m_nextIndex;
}
static std::string dequote(const std::string& text) VL_PURE {
// Quote any special characters
@@ -235,6 +235,7 @@ private:
m_items.clear();
m_indexValues.clear();
m_valueIndexes.clear();
m_nextIndex = KEY_UNDEF + 1;
}
public:
@@ -399,7 +400,7 @@ public:
os << i.first;
if (!i.second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, i.second.first);
os << "' " << i.second.second;
os << std::endl;
os << '\n';
}
}
};
+1 -1
View File
@@ -88,7 +88,7 @@ template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
/// Global class with methods affecting all coverage data.
/// All public methods in this class are thread safe.
class VerilatedCov {
class VerilatedCov final {
VL_UNCOPYABLE(VerilatedCov);
public:
+1 -1
View File
@@ -102,7 +102,7 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
/// Verilator coverage global class.
/// This class is thread safe.
class VerilatedCovKey {
class VerilatedCovKey final {
public:
static std::string shortKey(const std::string& key) VL_PURE {
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
+2 -2
View File
@@ -35,7 +35,7 @@
/// Base class to create a Verilator FST dump
/// This is an internally used class - see VerilatedFstC for what to call from applications
class VerilatedFst : public VerilatedTrace<VerilatedFst> {
class VerilatedFst final : public VerilatedTrace<VerilatedFst> {
private:
// Give the superclass access to private bits (to avoid virtual functions)
friend class VerilatedTrace<VerilatedFst>;
@@ -128,7 +128,7 @@ template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::st
/// Also derived for use in SystemC simulations.
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
class VerilatedFstC {
class VerilatedFstC final {
VerilatedFst m_sptrace; ///< Trace file being created
// CONSTRUCTORS
+99 -59
View File
@@ -32,6 +32,7 @@
#include <memory>
#include <set>
#include <string>
#include <unordered_set>
//===================================================================
// String formatters (required by below containers)
@@ -46,7 +47,7 @@ extern std::string VL_TO_STRING_W(int words, WDataInP obj);
//===================================================================
// Shuffle RNG
class VlURNG {
class VlURNG final {
public:
typedef size_t result_type;
static constexpr size_t min() { return 0; }
@@ -57,7 +58,7 @@ public:
//===================================================================
// Readmem/Writemem operation classes
class VlReadMem {
class VlReadMem final {
bool m_hex; // Hex format
int m_bits; // Bit width of values
const std::string& m_filename; // Filename
@@ -74,7 +75,7 @@ public:
void setData(void* valuep, const std::string& rhs);
};
class VlWriteMem {
class VlWriteMem final {
bool m_hex; // Hex format
int m_bits; // Bit width of values
FILE* m_fp; // File handle for filename
@@ -93,7 +94,7 @@ public:
//
// Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound
// For dynamic arrays it is always zero
template <class T_Value, size_t T_MaxSize = 0> class VlQueue {
template <class T_Value, size_t T_MaxSize = 0> class VlQueue final {
private:
// TYPES
typedef std::deque<T_Value> Deque;
@@ -108,10 +109,13 @@ private:
public:
// CONSTRUCTORS
VlQueue() {
// m_defaultValue isn't defaulted. Caller's constructor must do it.
}
~VlQueue() {}
// m_defaultValue isn't defaulted. Caller's constructor must do it.
VlQueue() = default;
~VlQueue() = default;
VlQueue(const VlQueue&) = default;
VlQueue(VlQueue&&) = default;
VlQueue& operator=(const VlQueue&) = default;
VlQueue& operator=(VlQueue&&) = default;
// Standard copy constructor works. Verilog: assoca = assocb
// Also must allow conversion from a different T_MaxSize queue
@@ -150,6 +154,7 @@ public:
// METHODS
T_Value& atDefault() { return m_defaultValue; }
const T_Value& atDefault() const { return m_defaultValue; }
const Deque& privateDeque() const { return m_deque; }
// Size. Verilog: function int size(), or int num()
@@ -247,20 +252,24 @@ public:
void sort() { std::sort(m_deque.begin(), m_deque.end()); }
template <typename Func> void sort(Func with_func) {
// with_func returns arbitrary type to use for the sort comparison
std::sort(m_deque.begin(), m_deque.end(),
[=](const T_Value& a, const T_Value& b) { return with_func(a) < with_func(b); });
std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) {
// index number is meaninless with sort, as it changes
return with_func(0, a) < with_func(0, b);
});
}
void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); }
template <typename Func> void rsort(Func with_func) {
// with_func returns arbitrary type to use for the sort comparison
std::sort(m_deque.rbegin(), m_deque.rend(),
[=](const T_Value& a, const T_Value& b) { return with_func(a) < with_func(b); });
std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) {
// index number is meaninless with sort, as it changes
return with_func(0, a) < with_func(0, b);
});
}
void reverse() { std::reverse(m_deque.begin(), m_deque.end()); }
void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG()); }
VlQueue unique() const {
VlQueue out;
std::set<T_Value> saw;
std::unordered_set<T_Value> saw;
for (const auto& i : m_deque) {
auto it = saw.find(i);
if (it == saw.end()) {
@@ -273,7 +282,7 @@ public:
VlQueue<IData> unique_index() const {
VlQueue<IData> out;
IData index = 0;
std::set<T_Value> saw;
std::unordered_set<T_Value> saw;
for (const auto& i : m_deque) {
auto it = saw.find(i);
if (it == saw.end()) {
@@ -286,39 +295,54 @@ public:
}
template <typename Func> VlQueue find(Func with_func) const {
VlQueue out;
for (const auto& i : m_deque)
if (with_func(i)) out.push_back(i);
IData index = 0;
for (const auto& i : m_deque) {
if (with_func(index, i)) out.push_back(i);
++index;
}
return out;
}
template <typename Func> VlQueue<IData> find_index(Func with_func) const {
VlQueue<IData> out;
IData index = 0;
for (const auto& i : m_deque) {
if (with_func(i)) out.push_back(index);
if (with_func(index, i)) out.push_back(index);
++index;
}
return out;
}
template <typename Func> VlQueue find_first(Func with_func) const {
const auto it = std::find_if(m_deque.begin(), m_deque.end(), with_func);
if (it == m_deque.end()) return VlQueue{};
return VlQueue::cons(*it);
// Can't use std::find_if as need index number
IData index = 0;
for (const auto& i : m_deque) {
if (with_func(index, i)) return VlQueue::cons(i);
++index;
}
return VlQueue{};
}
template <typename Func> VlQueue<IData> find_first_index(Func with_func) const {
const auto it = std::find_if(m_deque.begin(), m_deque.end(), with_func);
if (it == m_deque.end()) return VlQueue<IData>{};
return VlQueue<IData>::cons(std::distance(m_deque.begin(), it));
IData index = 0;
for (const auto& i : m_deque) {
if (with_func(index, i)) return VlQueue<IData>::cons(index);
++index;
}
return VlQueue<IData>{};
}
template <typename Func> VlQueue find_last(Func with_func) const {
const auto it = std::find_if(m_deque.rbegin(), m_deque.rend(), with_func);
if (it == m_deque.rend()) return VlQueue{};
return VlQueue::cons(*it);
IData index = m_deque.size() - 1;
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
if (with_func(index, *it)) return VlQueue::cons(*it);
--index;
}
return VlQueue{};
}
template <typename Func> VlQueue<IData> find_last_index(Func with_func) const {
const auto it = std::find_if(m_deque.rbegin(), m_deque.rend(), with_func);
if (it == m_deque.rend()) return VlQueue<IData>{};
// Return index must be relative to beginning
return VlQueue<IData>::cons(m_deque.size() - 1 - std::distance(m_deque.rbegin(), it));
IData index = m_deque.size() - 1;
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
if (with_func(index, *it)) return VlQueue<IData>::cons(index);
--index;
}
return VlQueue<IData>{};
}
// Reduction operators
@@ -340,7 +364,8 @@ public:
}
template <typename Func> T_Value r_sum(Func with_func) const {
T_Value out(0); // Type must have assignment operator
for (const auto& i : m_deque) out += with_func(i);
IData index = 0;
for (const auto& i : m_deque) out += with_func(index++, i);
return out;
}
T_Value r_product() const {
@@ -354,9 +379,11 @@ public:
template <typename Func> T_Value r_product(Func with_func) const {
if (m_deque.empty()) return T_Value(0);
auto it = m_deque.begin();
T_Value out{with_func(*it)};
IData index = 0;
T_Value out{with_func(index, *it)};
++it;
for (; it != m_deque.end(); ++it) out *= with_func(*it);
++index;
for (; it != m_deque.end(); ++it) out *= with_func(index++, *it);
return out;
}
T_Value r_and() const {
@@ -370,9 +397,11 @@ public:
template <typename Func> T_Value r_and(Func with_func) const {
if (m_deque.empty()) return T_Value(0);
auto it = m_deque.begin();
T_Value out{with_func(*it)};
IData index = 0;
T_Value out{with_func(index, *it)};
++it;
for (; it != m_deque.end(); ++it) out &= with_func(*it);
++index;
for (; it != m_deque.end(); ++it) out &= with_func(index, *it);
return out;
}
T_Value r_or() const {
@@ -382,7 +411,8 @@ public:
}
template <typename Func> T_Value r_or(Func with_func) const {
T_Value out(0); // Type must have assignment operator
for (const auto& i : m_deque) out |= with_func(i);
IData index = 0;
for (const auto& i : m_deque) out |= with_func(index++, i);
return out;
}
T_Value r_xor() const {
@@ -392,7 +422,8 @@ public:
}
template <typename Func> T_Value r_xor(Func with_func) const {
T_Value out(0); // Type must have assignment operator
for (const auto& i : m_deque) out ^= with_func(i);
IData index = 0;
for (const auto& i : m_deque) out ^= with_func(index++, i);
return out;
}
@@ -421,13 +452,18 @@ template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
// This is only used when we need an upper-level container and so can't
// simply use a C style array (which is just a pointer).
template <std::size_t T_Words> class VlWide {
template <std::size_t T_Words> class VlWide final {
WData m_storage[T_Words];
public:
// cppcheck-suppress uninitVar
VlWide() {}
~VlWide() {}
VlWide() = default;
~VlWide() = default;
VlWide(const VlWide&) = default;
VlWide(VlWide&&) = default;
VlWide& operator=(const VlWide&) = default;
VlWide& operator=(VlWide&&) = default;
// METHODS
const WData& at(size_t index) const { return m_storage[index]; }
WData& at(size_t index) { return m_storage[index]; }
WData* data() { return &m_storage[0]; }
@@ -452,7 +488,7 @@ template <std::size_t T_Words> std::string VL_TO_STRING(const VlWide<T_Words>& o
// There are no multithreaded locks on this; the base variable must
// be protected by other means
//
template <class T_Key, class T_Value> class VlAssocArray {
template <class T_Key, class T_Value> class VlAssocArray final {
private:
// TYPES
typedef std::map<T_Key, T_Value> Map;
@@ -467,14 +503,17 @@ private:
public:
// CONSTRUCTORS
VlAssocArray() {
// m_defaultValue isn't defaulted. Caller's constructor must do it.
}
~VlAssocArray() {}
// Standard copy constructor works. Verilog: assoca = assocb
// m_defaultValue isn't defaulted. Caller's constructor must do it.
VlAssocArray() = default;
~VlAssocArray() = default;
VlAssocArray(const VlAssocArray&) = default;
VlAssocArray(VlAssocArray&&) = default;
VlAssocArray& operator=(const VlAssocArray&) = default;
VlAssocArray& operator=(VlAssocArray&&) = default;
// METHODS
T_Value& atDefault() { return m_defaultValue; }
const T_Value& atDefault() const { return m_defaultValue; }
// Size of array. Verilog: function int size(), or int num()
int size() const { return m_map.size(); }
@@ -578,19 +617,19 @@ public:
template <typename Func> VlQueue<T_Value> find(Func with_func) const {
VlQueue<T_Value> out;
for (const auto& i : m_map)
if (with_func(i.second)) out.push_back(i.second);
if (with_func(i.first, i.second)) out.push_back(i.second);
return out;
}
template <typename Func> VlQueue<T_Key> find_index(Func with_func) const {
VlQueue<T_Key> out;
for (const auto& i : m_map)
if (with_func(i.second)) out.push_back(i.first);
if (with_func(i.first, i.second)) out.push_back(i.first);
return out;
}
template <typename Func> VlQueue<T_Value> find_first(Func with_func) const {
const auto it
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
return with_func(i.second);
return with_func(i.first, i.second);
});
if (it == m_map.end()) return VlQueue<T_Value>{};
return VlQueue<T_Value>::cons(it->second);
@@ -598,7 +637,7 @@ public:
template <typename Func> VlQueue<T_Key> find_first_index(Func with_func) const {
const auto it
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
return with_func(i.second);
return with_func(i.first, i.second);
});
if (it == m_map.end()) return VlQueue<T_Value>{};
return VlQueue<T_Key>::cons(it->first);
@@ -606,7 +645,7 @@ public:
template <typename Func> VlQueue<T_Value> find_last(Func with_func) const {
const auto it
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
return with_func(i.second);
return with_func(i.first, i.second);
});
if (it == m_map.rend()) return VlQueue<T_Value>{};
return VlQueue<T_Value>::cons(it->second);
@@ -614,7 +653,7 @@ public:
template <typename Func> VlQueue<T_Key> find_last_index(Func with_func) const {
const auto it
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
return with_func(i.second);
return with_func(i.first, i.second);
});
if (it == m_map.rend()) return VlQueue<T_Value>{};
return VlQueue<T_Key>::cons(it->first);
@@ -647,7 +686,7 @@ public:
}
template <typename Func> T_Value r_sum(Func with_func) const {
T_Value out(0); // Type must have assignment operator
for (const auto& i : m_map) out += with_func(i.second);
for (const auto& i : m_map) out += with_func(i.first, i.second);
return out;
}
T_Value r_product() const {
@@ -661,9 +700,9 @@ public:
template <typename Func> T_Value r_product(Func with_func) const {
if (m_map.empty()) return T_Value(0);
auto it = m_map.begin();
T_Value out{with_func(it->second)};
T_Value out{with_func(it->first, it->second)};
++it;
for (; it != m_map.end(); ++it) out *= with_func(it->second);
for (; it != m_map.end(); ++it) out *= with_func(it->first, it->second);
return out;
}
T_Value r_and() const {
@@ -677,9 +716,9 @@ public:
template <typename Func> T_Value r_and(Func with_func) const {
if (m_map.empty()) return T_Value(0);
auto it = m_map.begin();
T_Value out{with_func(it->second)};
T_Value out{with_func(it->first, it->second)};
++it;
for (; it != m_map.end(); ++it) out &= with_func(it->second);
for (; it != m_map.end(); ++it) out &= with_func(it->first, it->second);
return out;
}
T_Value r_or() const {
@@ -689,7 +728,7 @@ public:
}
template <typename Func> T_Value r_or(Func with_func) const {
T_Value out(0); // Type must have assignment operator
for (const auto& i : m_map) out |= with_func(i.second);
for (const auto& i : m_map) out |= with_func(i.first, i.second);
return out;
}
T_Value r_xor() const {
@@ -699,7 +738,7 @@ public:
}
template <typename Func> T_Value r_xor(Func with_func) const {
T_Value out(0); // Type must have assignment operator
for (const auto& i : m_map) out ^= with_func(i.second);
for (const auto& i : m_map) out ^= with_func(i.first, i.second);
return out;
}
@@ -773,6 +812,7 @@ inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
return VL_CVT_PACK_STR_NW(VL_WQ_WORDS_E, lw);
}
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE { return lhs; }
inline std::string& VL_CVT_PACK_STR_NN(std::string& lhs) VL_PURE { return lhs; }
inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE {
WData lw[VL_WQ_WORDS_E];
VL_SET_WI(lw, lhs);
+18 -14
View File
@@ -46,7 +46,7 @@ class VerilatedScope;
#ifdef VL_THREADED
/// Message, enqueued on an mtask, and consumed on the main eval thread
class VerilatedMsg {
class VerilatedMsg final {
public:
// TYPES
struct Cmp {
@@ -64,7 +64,11 @@ public:
VerilatedMsg(const std::function<void()>& cb)
: m_mtaskId{Verilated::mtaskId()}
, m_cb{cb} {}
~VerilatedMsg() {}
~VerilatedMsg() = default;
VerilatedMsg(const VerilatedMsg&) = default;
VerilatedMsg(VerilatedMsg&&) = default;
VerilatedMsg& operator=(const VerilatedMsg&) = default;
VerilatedMsg& operator=(VerilatedMsg&&) = default;
// METHODS
vluint32_t mtaskId() const { return m_mtaskId; }
/// Execute the lambda function
@@ -74,7 +78,7 @@ public:
/// Each thread has a queue it pushes to
/// This assumes no thread starts pushing the next tick until the previous has drained.
/// If more aggressiveness is needed, a double-buffered scheme might work well.
class VerilatedEvalMsgQueue {
class VerilatedEvalMsgQueue final {
typedef std::multiset<VerilatedMsg, VerilatedMsg::Cmp> VerilatedThreadQueue;
std::atomic<vluint64_t> m_depth; ///< Current depth of queue (see comments below)
@@ -87,7 +91,7 @@ public:
: m_depth{0} {
assert(atomic_is_lock_free(&m_depth));
}
~VerilatedEvalMsgQueue() {}
~VerilatedEvalMsgQueue() = default;
private:
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
@@ -126,7 +130,7 @@ public:
};
/// Each thread has a local queue to build up messages until the end of the eval() call
class VerilatedThreadMsgQueue {
class VerilatedThreadMsgQueue final {
std::queue<VerilatedMsg> m_queue;
public:
@@ -170,7 +174,7 @@ public:
#endif // VL_THREADED
// FILE* list constructed from a file-descriptor
class VerilatedFpList {
class VerilatedFpList final {
FILE* m_fp[31];
std::size_t m_sz = 0;
@@ -189,7 +193,7 @@ public:
//======================================================================
// VerilatedImp
class VerilatedImpData {
class VerilatedImpData final {
// Whole class is internal use only - Global information shared between verilated*.cpp files.
protected:
friend class Verilated;
@@ -207,8 +211,8 @@ protected:
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
int m_timeFormatWidth = 20; // $timeformat character width
enum { UNITS_NONE = 99 }; // Default based on precision
Serialized() {}
~Serialized() {}
Serialized() = default;
~Serialized() = default;
} m_ser;
VerilatedMutex m_sergMutex; ///< Protect m_ser
@@ -260,7 +264,7 @@ protected:
}
};
class VerilatedImp {
class VerilatedImp final {
// Whole class is internal use only - Global information shared between verilated*.cpp files.
protected:
friend class Verilated;
@@ -268,15 +272,15 @@ protected:
// MEMBERS
union VerilatedImpU { ///< Enclose in an union to call ctor/dtor manually
VerilatedImpData v;
VerilatedImpU() {}
~VerilatedImpU() {}
VerilatedImpU() {} // Can't be = default;
~VerilatedImpU() {} // Can't be = default;
};
static VerilatedImpU s_s; ///< Static Singleton; One and only static this
public: // But only for verilated*.cpp
// CONSTRUCTORS
VerilatedImp() {}
~VerilatedImp() {}
VerilatedImp() = default;
~VerilatedImp() = default;
static void setup();
static void teardown();
+10 -10
View File
@@ -28,7 +28,7 @@
// VerilatedSerialize - convert structures to a stream representation
// This class is not thread safe, it must be called by a single thread
class VerilatedSerialize {
class VerilatedSerialize VL_NOT_FINAL {
protected:
// MEMBERS
// For speed, keep m_cp as the first member of this structure
@@ -38,8 +38,8 @@ protected:
std::string m_filename; ///< Filename, for error messages
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
inline static size_t bufferInsertSize() { return 16 * 1024; }
static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
static constexpr size_t bufferInsertSize() { return 16 * 1024; }
void header() VL_MT_UNSAFE_ONE;
void trailer() VL_MT_UNSAFE_ONE;
@@ -87,7 +87,7 @@ private:
// VerilatedDeserial - load structures from a stream representation
// This class is not thread safe, it must be called by a single thread
class VerilatedDeserialize {
class VerilatedDeserialize VL_NOT_FINAL {
protected:
// MEMBERS
// For speed, keep m_cp as the first member of this structure
@@ -98,8 +98,8 @@ protected:
std::string m_filename; ///< Filename, for error messages
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
inline static size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
inline static size_t bufferInsertSize() { return 16 * 1024; }
static constexpr size_t bufferSize() { return 256 * 1024; } // See below for slack calculation
static constexpr size_t bufferInsertSize() { return 16 * 1024; }
virtual void fill() = 0;
void header() VL_MT_UNSAFE_ONE;
@@ -154,13 +154,13 @@ private:
// VerilatedSave - serialize to a file
// This class is not thread safe, it must be called by a single thread
class VerilatedSave : public VerilatedSerialize {
class VerilatedSave final : public VerilatedSerialize {
private:
int m_fd = -1; ///< File descriptor we're writing to
public:
// CONSTRUCTORS
VerilatedSave() {}
VerilatedSave() = default;
virtual ~VerilatedSave() override { close(); }
// METHODS
/// Open the file; call isOpen() to see if errors
@@ -174,13 +174,13 @@ public:
// VerilatedRestore - deserialize from a file
// This class is not thread safe, it must be called by a single thread
class VerilatedRestore : public VerilatedDeserialize {
class VerilatedRestore final : public VerilatedDeserialize {
private:
int m_fd = -1; ///< File descriptor we're writing to
public:
// CONSTRUCTORS
VerilatedRestore() {}
VerilatedRestore() = default;
virtual ~VerilatedRestore() override { close(); }
// METHODS
+1 -1
View File
@@ -34,7 +34,7 @@
// This class is thread safe (though most of SystemC is not).
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
class VlScBvExposer : public sc_bv_base {
class VlScBvExposer final : public sc_bv_base {
public:
static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
return static_cast<const VlScBvExposer*>(&base)->sp_datatp();
+11 -13
View File
@@ -36,16 +36,14 @@
/// Thread safety: Assume is constructed only with model, then any number of readers
// See also V3Ast::VNumRange
class VerilatedRange {
int m_left;
int m_right;
class VerilatedRange final {
int m_left = 0;
int m_right = 0;
protected:
friend class VerilatedVarProps;
friend class VerilatedScope;
VerilatedRange()
: m_left{0}
, m_right{0} {}
VerilatedRange() = default;
VerilatedRange(int left, int right)
: m_left{left}
, m_right{right} {}
@@ -55,7 +53,7 @@ protected:
}
public:
~VerilatedRange() {}
~VerilatedRange() = default;
int left() const { return m_left; }
int right() const { return m_right; }
int low() const { return (m_left < m_right) ? m_left : m_right; }
@@ -70,7 +68,7 @@ public:
/// Verilator variable
/// Thread safety: Assume is constructed only with model, then any number of readers
class VerilatedVarProps {
class VerilatedVarProps VL_NOT_FINAL {
// TYPES
enum { MAGIC = 0xddc4f829 };
// MEMBERS
@@ -138,7 +136,7 @@ public:
}
public:
~VerilatedVarProps() {}
~VerilatedVarProps() = default;
// METHODS
bool magicOk() const { return m_magic == MAGIC; }
VerilatedVarType vltype() const { return m_vltype; }
@@ -189,7 +187,7 @@ public:
//===========================================================================
/// Verilator DPI open array variable
class VerilatedDpiOpenVar {
class VerilatedDpiOpenVar final {
// MEMBERS
const VerilatedVarProps* m_propsp; // Variable properties
void* m_datap; // Location of data (local to thread always, so safe)
@@ -201,7 +199,7 @@ public:
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
: m_propsp{propsp}
, m_datap{const_cast<void*>(datap)} {}
~VerilatedDpiOpenVar() {}
~VerilatedDpiOpenVar() = default;
// METHODS
void* datap() const { return m_datap; }
// METHODS - from VerilatedVarProps
@@ -227,7 +225,7 @@ public:
/// Verilator variable
/// Thread safety: Assume is constructed only with model, then any number of readers
class VerilatedVar : public VerilatedVarProps {
class VerilatedVar final : public VerilatedVarProps {
// MEMBERS
void* m_datap; // Location of data
const char* m_namep; // Name - slowpath
@@ -243,7 +241,7 @@ protected:
, m_isParam{isParam} {}
public:
~VerilatedVar() {}
~VerilatedVar() = default;
// ACCESSORS
void* datap() const { return m_datap; }
const VerilatedRange& range() const { return packed(); } // Deprecated
+11 -9
View File
@@ -31,6 +31,7 @@
#include "verilated_sym_props.h"
#include <map>
#include <unordered_map>
#include <vector>
//======================================================================
@@ -42,26 +43,27 @@ struct VerilatedCStrCmp {
};
/// Map of sorted scope names to find associated scope class
class VerilatedScopeNameMap
class VerilatedScopeNameMap final
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
public:
VerilatedScopeNameMap() {}
~VerilatedScopeNameMap() {}
VerilatedScopeNameMap() = default;
~VerilatedScopeNameMap() = default;
};
/// Map of sorted variable names to find associated variable class
class VerilatedVarNameMap : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
class VerilatedVarNameMap final : public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
public:
VerilatedVarNameMap() {}
~VerilatedVarNameMap() {}
VerilatedVarNameMap() = default;
~VerilatedVarNameMap() = default;
};
typedef std::vector<const VerilatedScope*> VerilatedScopeVector;
class VerilatedHierarchyMap : public std::map<const VerilatedScope*, VerilatedScopeVector> {
class VerilatedHierarchyMap final
: public std::unordered_map<const VerilatedScope*, VerilatedScopeVector> {
public:
VerilatedHierarchyMap() {}
~VerilatedHierarchyMap() {}
VerilatedHierarchyMap() = default;
~VerilatedHierarchyMap() = default;
};
#endif // Guard
+6 -6
View File
@@ -52,7 +52,7 @@ typedef void* VlThrSymTab;
typedef void (*VlExecFnp)(bool, VlThrSymTab);
/// Track dependencies for a single MTask.
class VlMTaskVertex {
class VlMTaskVertex final {
// MEMBERS
static std::atomic<vluint64_t> s_yields; // Statistics
@@ -82,7 +82,7 @@ public:
// that must notify this MTaskVertex before it will become ready
// to run.
explicit VlMTaskVertex(vluint32_t upstreamDepCount);
~VlMTaskVertex() {}
~VlMTaskVertex() = default;
static vluint64_t yields() { return s_yields; }
static void yieldThread() {
@@ -124,7 +124,7 @@ public:
};
// Profiling support
class VlProfileRec {
class VlProfileRec final {
protected:
friend class VlThreadPool;
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
@@ -136,7 +136,7 @@ protected:
unsigned m_cpu; // Execution CPU number (at start anyways)
public:
class Barrier {};
VlProfileRec() {}
VlProfileRec() = default;
explicit VlProfileRec(Barrier) { m_cpu = getcpu(); }
void startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) {
m_type = VlProfileRec::TYPE_MTASK_RUN;
@@ -168,7 +168,7 @@ public:
class VlThreadPool;
class VlWorkerThread {
class VlWorkerThread final {
private:
// TYPES
struct ExecRec {
@@ -247,7 +247,7 @@ public:
static void startWorker(VlWorkerThread* workerp);
};
class VlThreadPool {
class VlThreadPool final {
// TYPES
typedef std::vector<VlProfileRec> ProfileTrace;
typedef std::set<ProfileTrace*> ProfileSet;
+3 -3
View File
@@ -40,7 +40,7 @@
// Threaded tracing
// A simple synchronized first in first out queue
template <class T> class VerilatedThreadQueue { // LCOV_EXCL_LINE // lcov bug
template <class T> class VerilatedThreadQueue final { // LCOV_EXCL_LINE // lcov bug
private:
VerilatedMutex m_mutex; // Protects m_queue
std::condition_variable_any m_cv;
@@ -83,7 +83,7 @@ public:
// Commands used by thread tracing. Anonymous enum in class, as we want
// it scoped, but we also want the automatic conversion to integer types.
class VerilatedTraceCommand {
class VerilatedTraceCommand final {
public:
// These must all fit in 4 bit at the moment, as the tracing routines
// pack parameters in the top bits.
@@ -110,7 +110,7 @@ public:
// VerilatedTrace uses F-bounded polymorphism to access duck-typed
// implementations in the format specific derived class, which must be passed
// as the type parameter T_Derived
template <class T_Derived> class VerilatedTrace {
template <class T_Derived> class VerilatedTrace VL_NOT_FINAL {
public:
//=========================================================================
// Generic tracing internals
+4 -4
View File
@@ -559,7 +559,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::fullDouble(vluint32_t* oldp, doub
// All of these take a destination pointer where the string will be emitted,
// and a value to convert. There are a couple of variants for efficiency.
inline static void cvtCDataToStr(char* dstp, CData value) {
static inline void cvtCDataToStr(char* dstp, CData value) {
#ifdef VL_HAVE_SSE2
// Similar to cvtSDataToStr but only the bottom 8 byte lanes are used
const __m128i a = _mm_cvtsi32_si128(value);
@@ -581,7 +581,7 @@ inline static void cvtCDataToStr(char* dstp, CData value) {
#endif
}
inline static void cvtSDataToStr(char* dstp, SData value) {
static inline void cvtSDataToStr(char* dstp, SData value) {
#ifdef VL_HAVE_SSE2
// We want each bit in the 16-bit input value to end up in a byte lane
// within the 128-bit XMM register. Note that x86 is little-endian and we
@@ -617,7 +617,7 @@ inline static void cvtSDataToStr(char* dstp, SData value) {
#endif
}
inline static void cvtIDataToStr(char* dstp, IData value) {
static inline void cvtIDataToStr(char* dstp, IData value) {
#ifdef VL_HAVE_AVX2
// Similar to cvtSDataToStr but the bottom 16-bits are processed in the
// top half of the YMM registerss
@@ -636,7 +636,7 @@ inline static void cvtIDataToStr(char* dstp, IData value) {
#endif
}
inline static void cvtQDataToStr(char* dstp, QData value) {
static inline void cvtQDataToStr(char* dstp, QData value) {
cvtIDataToStr(dstp, value >> 32);
cvtIDataToStr(dstp + 32, value);
}
+5 -5
View File
@@ -34,13 +34,13 @@ class VerilatedVcd;
// VerilatedFile
/// File handling routines, which can be overrode for e.g. socket I/O
class VerilatedVcdFile {
class VerilatedVcdFile final {
private:
int m_fd = 0; ///< File descriptor we're writing to
public:
// METHODS
VerilatedVcdFile() {}
virtual ~VerilatedVcdFile() {}
VerilatedVcdFile() = default;
virtual ~VerilatedVcdFile() = default;
virtual bool open(const std::string& name) VL_MT_UNSAFE;
virtual void close() VL_MT_UNSAFE;
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
@@ -51,7 +51,7 @@ public:
/// Base class to create a Verilator VCD dump
/// This is an internally used class - see VerilatedVcdC for what to call from applications
class VerilatedVcd : public VerilatedTrace<VerilatedVcd> {
class VerilatedVcd VL_NOT_FINAL : public VerilatedTrace<VerilatedVcd> {
private:
// Give the superclass access to private bits (to avoid virtual functions)
friend class VerilatedTrace<VerilatedVcd>;
@@ -329,7 +329,7 @@ template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const std::st
/// Also derived for use in SystemC simulations.
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
class VerilatedVcdC {
class VerilatedVcdC VL_NOT_FINAL {
VerilatedVcd m_sptrace; ///< Trace file being created
// CONSTRUCTORS
+1 -1
View File
@@ -31,7 +31,7 @@
/// This class is passed to the SystemC simulation kernel, just like a
/// documented SystemC trace format.
class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
class VerilatedVcdSc final : sc_trace_file, public VerilatedVcdC {
// CONSTRUCTORS
VL_UNCOPYABLE(VerilatedVcdSc);
+118 -114
View File
@@ -55,15 +55,15 @@ constexpr unsigned VL_VPI_LINE_SIZE = 8192;
// Implementation
// Base VPI handled object
class VerilatedVpio {
class VerilatedVpio VL_NOT_FINAL {
// MEM MANGLEMENT
static VL_THREAD_LOCAL vluint8_t* t_freeHead;
public:
// CONSTRUCTORS
VerilatedVpio() {}
virtual ~VerilatedVpio() {}
inline static void* operator new(size_t size) VL_MT_SAFE {
VerilatedVpio() = default;
virtual ~VerilatedVpio() = default;
static void* operator new(size_t size) VL_MT_SAFE {
// We new and delete tons of vpi structures, so keep them around
// To simplify our free list, we use a size large enough for all derived types
// We reserve word zero for the next pointer, as that's safer in case a
@@ -79,13 +79,13 @@ public:
vluint8_t* newp = reinterpret_cast<vluint8_t*>(::operator new(chunk + 8));
return newp + 8;
}
inline static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE {
static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE {
vluint8_t* oldp = (static_cast<vluint8_t*>(obj)) - 8;
*(reinterpret_cast<void**>(oldp)) = t_freeHead;
t_freeHead = oldp;
}
// MEMBERS
static inline VerilatedVpio* castp(vpiHandle h) {
static VerilatedVpio* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpio*>(reinterpret_cast<VerilatedVpio*>(h));
}
inline vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
@@ -101,7 +101,7 @@ public:
typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data*);
class VerilatedVpioCb : public VerilatedVpio {
class VerilatedVpioCb final : public VerilatedVpio {
t_cb_data m_cbData;
s_vpi_value m_value;
QData m_time;
@@ -114,8 +114,8 @@ public:
m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal;
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() override {}
static inline VerilatedVpioCb* castp(vpiHandle h) {
virtual ~VerilatedVpioCb() override = default;
static VerilatedVpioCb* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioCb*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiCallback; }
@@ -125,21 +125,21 @@ public:
QData time() const { return m_time; }
};
class VerilatedVpioConst : public VerilatedVpio {
class VerilatedVpioConst final : public VerilatedVpio {
vlsint32_t m_num;
public:
explicit VerilatedVpioConst(vlsint32_t num)
: m_num{num} {}
virtual ~VerilatedVpioConst() override {}
static inline VerilatedVpioConst* castp(vpiHandle h) {
virtual ~VerilatedVpioConst() override = default;
static VerilatedVpioConst* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioConst*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiConstant; }
vlsint32_t num() const { return m_num; }
};
class VerilatedVpioParam : public VerilatedVpio {
class VerilatedVpioParam final : public VerilatedVpio {
const VerilatedVar* m_varp;
const VerilatedScope* m_scopep;
@@ -148,9 +148,9 @@ public:
: m_varp{varp}
, m_scopep{scopep} {}
virtual ~VerilatedVpioParam() override {}
virtual ~VerilatedVpioParam() override = default;
static inline VerilatedVpioParam* castp(vpiHandle h) {
static VerilatedVpioParam* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioParam*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiParameter; }
@@ -159,21 +159,21 @@ public:
const VerilatedScope* scopep() const { return m_scopep; }
virtual const char* name() const override { return m_varp->name(); }
virtual const char* fullname() const override {
static VL_THREAD_LOCAL std::string out;
out = std::string(m_scopep->name()) + "." + name();
return out.c_str();
static VL_THREAD_LOCAL std::string t_out;
t_out = std::string(m_scopep->name()) + "." + name();
return t_out.c_str();
}
};
class VerilatedVpioRange : public VerilatedVpio {
class VerilatedVpioRange final : public VerilatedVpio {
const VerilatedRange* m_range;
vlsint32_t m_iteration = 0;
public:
explicit VerilatedVpioRange(const VerilatedRange* range)
: m_range{range} {}
virtual ~VerilatedVpioRange() override {}
static inline VerilatedVpioRange* castp(vpiHandle h) {
virtual ~VerilatedVpioRange() override = default;
static VerilatedVpioRange* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioRange*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiRange; }
@@ -191,15 +191,15 @@ public:
}
};
class VerilatedVpioScope : public VerilatedVpio {
class VerilatedVpioScope VL_NOT_FINAL : public VerilatedVpio {
protected:
const VerilatedScope* m_scopep;
public:
explicit VerilatedVpioScope(const VerilatedScope* scopep)
: m_scopep{scopep} {}
virtual ~VerilatedVpioScope() override {}
static inline VerilatedVpioScope* castp(vpiHandle h) {
virtual ~VerilatedVpioScope() override = default;
static VerilatedVpioScope* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioScope*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiScope; }
@@ -208,10 +208,10 @@ public:
virtual const char* fullname() const override { return m_scopep->name(); }
};
class VerilatedVpioVar : public VerilatedVpio {
class VerilatedVpioVar VL_NOT_FINAL : public VerilatedVpio {
const VerilatedVar* m_varp;
const VerilatedScope* m_scopep;
vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange
vluint8_t* m_prevDatap = nullptr; // Previous value of data, for cbValueChange
union {
vluint8_t u8[4];
vluint32_t u32;
@@ -219,7 +219,7 @@ class VerilatedVpioVar : public VerilatedVpio {
vluint32_t m_entSize; // memoized variable size
protected:
void* m_varDatap; // varp()->datap() adjusted for array entries
vlsint32_t m_index;
vlsint32_t m_index = 0;
const VerilatedRange& get_range() const {
// Determine number of dimensions and return outermost
return (m_varp->dims() > 1) ? m_varp->unpacked() : m_varp->packed();
@@ -228,9 +228,7 @@ protected:
public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp{varp}
, m_scopep{scopep}
, m_index{0} {
m_prevDatap = nullptr;
, m_scopep{scopep} {
m_mask.u32 = VL_MASK_I(varp->packed().elements());
m_entSize = varp->entSize();
m_varDatap = varp->datap();
@@ -238,7 +236,7 @@ public:
virtual ~VerilatedVpioVar() override {
if (m_prevDatap) VL_DO_CLEAR(delete[] m_prevDatap, m_prevDatap = nullptr);
}
static inline VerilatedVpioVar* castp(vpiHandle h) {
static VerilatedVpioVar* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioVar*>(reinterpret_cast<VerilatedVpio*>(h));
}
const VerilatedVar* varp() const { return m_varp; }
@@ -254,9 +252,9 @@ public:
virtual const VerilatedRange* rangep() const override { return &get_range(); }
virtual const char* name() const override { return m_varp->name(); }
virtual const char* fullname() const override {
static VL_THREAD_LOCAL std::string out;
out = std::string(m_scopep->name()) + "." + name();
return out.c_str();
static VL_THREAD_LOCAL std::string t_out;
t_out = std::string(m_scopep->name()) + "." + name();
return t_out.c_str();
}
void* prevDatap() const { return m_prevDatap; }
void* varDatap() const { return m_varDatap; }
@@ -268,7 +266,7 @@ public:
}
};
class VerilatedVpioMemoryWord : public VerilatedVpioVar {
class VerilatedVpioMemoryWord final : public VerilatedVpioVar {
public:
VerilatedVpioMemoryWord(const VerilatedVar* varp, const VerilatedScope* scopep,
vlsint32_t index, int offset)
@@ -276,23 +274,23 @@ public:
m_index = index;
m_varDatap = (static_cast<vluint8_t*>(varp->datap())) + entSize() * offset;
}
virtual ~VerilatedVpioMemoryWord() override {}
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) {
virtual ~VerilatedVpioMemoryWord() override = default;
static VerilatedVpioMemoryWord* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWord*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiMemoryWord; }
virtual vluint32_t size() const override { return varp()->packed().elements(); }
virtual const VerilatedRange* rangep() const override { return &(varp()->packed()); }
virtual const char* fullname() const override {
static VL_THREAD_LOCAL std::string out;
static VL_THREAD_LOCAL std::string t_out;
char num[20];
sprintf(num, "%d", m_index);
out = std::string(scopep()->name()) + "." + name() + "[" + num + "]";
return out.c_str();
t_out = std::string(scopep()->name()) + "." + name() + "[" + num + "]";
return t_out.c_str();
}
};
class VerilatedVpioVarIter : public VerilatedVpio {
class VerilatedVpioVarIter final : public VerilatedVpio {
const VerilatedScope* m_scopep;
VerilatedVarNameMap::const_iterator m_it;
bool m_started = false;
@@ -300,8 +298,8 @@ class VerilatedVpioVarIter : public VerilatedVpio {
public:
explicit VerilatedVpioVarIter(const VerilatedScope* scopep)
: m_scopep{scopep} {}
virtual ~VerilatedVpioVarIter() override {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) {
virtual ~VerilatedVpioVarIter() override = default;
static VerilatedVpioVarIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioVarIter*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiIterator; }
@@ -323,7 +321,7 @@ public:
}
};
class VerilatedVpioMemoryWordIter : public VerilatedVpio {
class VerilatedVpioMemoryWordIter final : public VerilatedVpio {
const vpiHandle m_handle;
const VerilatedVar* m_varp;
vlsint32_t m_iteration;
@@ -336,8 +334,8 @@ public:
, m_varp{varp}
, m_iteration{varp->unpacked().right()}
, m_direction{VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) ? 1 : -1} {}
virtual ~VerilatedVpioMemoryWordIter() override {}
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
virtual ~VerilatedVpioMemoryWordIter() override = default;
static VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWordIter*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiIterator; }
@@ -353,7 +351,7 @@ public:
}
};
class VerilatedVpioModule : public VerilatedVpioScope {
class VerilatedVpioModule final : public VerilatedVpioScope {
const char* m_name;
const char* m_fullname;
@@ -364,7 +362,7 @@ public:
if (strncmp(m_fullname, "TOP.", 4) == 0) m_fullname += 4;
m_name = m_scopep->identifier();
}
static inline VerilatedVpioModule* castp(vpiHandle h) {
static VerilatedVpioModule* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioModule*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiModule; }
@@ -372,7 +370,7 @@ public:
virtual const char* fullname() const override { return m_fullname; }
};
class VerilatedVpioModuleIter : public VerilatedVpio {
class VerilatedVpioModuleIter final : public VerilatedVpio {
const std::vector<const VerilatedScope*>* m_vec;
std::vector<const VerilatedScope*>::const_iterator m_it;
@@ -381,8 +379,8 @@ public:
: m_vec{&vec} {
m_it = m_vec->begin();
}
virtual ~VerilatedVpioModuleIter() override {}
static inline VerilatedVpioModuleIter* castp(vpiHandle h) {
virtual ~VerilatedVpioModuleIter() override = default;
static VerilatedVpioModuleIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioModuleIter*>(reinterpret_cast<VerilatedVpio*>(h));
}
virtual vluint32_t type() const override { return vpiIterator; }
@@ -407,15 +405,11 @@ struct VerilatedVpiTimedCbsCmp {
class VerilatedVpiError;
class VerilatedVpiImp {
class VerilatedVpiImp final {
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime + 1 }; // Maxium callback reason
typedef std::list<VerilatedVpioCb*> VpioCbList;
typedef std::set<std::pair<QData, VerilatedVpioCb*>, VerilatedVpiTimedCbsCmp> VpioTimedCbs;
struct product_info {
PLI_BYTE8* product;
};
VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
VpioTimedCbs m_timedCbs; // Time based callbacks
VerilatedVpiError* m_errorInfop = nullptr; // Container for vpi error info
@@ -424,8 +418,8 @@ class VerilatedVpiImp {
static VerilatedVpiImp s_s; // Singleton
public:
VerilatedVpiImp() {}
~VerilatedVpiImp() {}
VerilatedVpiImp() = default;
~VerilatedVpiImp() = default;
static void assertOneCheck() { s_s.m_assertOne.check(); }
static void cbReasonAdd(VerilatedVpioCb* vop) {
if (vop->reason() == cbValueChange) {
@@ -477,16 +471,21 @@ public:
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE {
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
bool called = false;
const auto end = cbObjList.end(); // prevent looping over newly added elements
for (auto it = cbObjList.begin(); it != end;) {
if (cbObjList.empty()) return called;
const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements
for (auto it = cbObjList.begin(); true;) {
// cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
bool was_last = it == last;
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
it = cbObjList.erase(it);
if (was_last) break;
continue;
}
VerilatedVpioCb* vop = *it++;
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback %d %p\n", reason, vop););
(vop->cb_rtnp())(vop->cb_datap());
called = true;
if (was_last) break;
}
return called;
}
@@ -494,12 +493,16 @@ public:
assertOneCheck();
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
bool called = false;
typedef std::set<VerilatedVpioVar*> VpioVarSet;
typedef std::unordered_set<VerilatedVpioVar*> VpioVarSet;
VpioVarSet update; // set of objects to update after callbacks
const auto end = cbObjList.end(); // prevent looping over newly added elements
for (auto it = cbObjList.begin(); it != end;) {
if (cbObjList.empty()) return called;
const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements
for (auto it = cbObjList.begin(); true;) {
// cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
bool was_last = it == last;
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
it = cbObjList.erase(it);
if (was_last) break;
continue;
}
VerilatedVpioCb* vop = *it++;
@@ -518,6 +521,7 @@ public:
called = true;
}
}
if (was_last) break;
}
for (const auto& ip : update) { memcpy(ip->prevDatap(), ip->varDatap(), ip->entSize()); }
return called;
@@ -526,7 +530,7 @@ public:
static VerilatedVpiError* error_info() VL_MT_UNSAFE_ONE; // getter for vpi error info
};
class VerilatedVpiError {
class VerilatedVpiError final {
//// Container for vpi error info
t_vpi_error_info m_errorInfo;
@@ -555,7 +559,7 @@ public:
m_buff[0] = '\0';
m_errorInfo.product = const_cast<PLI_BYTE8*>(Verilated::productName());
}
~VerilatedVpiError() {}
~VerilatedVpiError() = default;
static void selfTest() VL_MT_UNSAFE_ONE;
VerilatedVpiError* setMessage(PLI_INT32 level) {
m_flag = true;
@@ -564,14 +568,14 @@ public:
}
void setMessage(const std::string& file, PLI_INT32 line, const char* message, ...) {
// message cannot be a const string& as va_start cannot use a reference
static VL_THREAD_LOCAL std::string filehold;
static VL_THREAD_LOCAL std::string t_filehold;
va_list args;
va_start(args, message);
VL_VSNPRINTF(m_buff, sizeof(m_buff), message, args);
va_end(args);
m_errorInfo.state = vpiPLI;
filehold = file;
setError((PLI_BYTE8*)m_buff, nullptr, const_cast<PLI_BYTE8*>(filehold.c_str()), line);
t_filehold = file;
setError((PLI_BYTE8*)m_buff, nullptr, const_cast<PLI_BYTE8*>(t_filehold.c_str()), line);
}
p_vpi_error_info getError() {
if (m_flag) return &m_errorInfo;
@@ -1415,34 +1419,34 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
const char* fullname) {
if (!vl_check_format(varp, valuep, fullname, true)) return;
// Maximum required size is for binary string, one byte per bit plus null termination
static VL_THREAD_LOCAL char outStr[1 + VL_MULS_MAX_WORDS * 32];
static VL_THREAD_LOCAL char t_outStr[1 + VL_MULS_MAX_WORDS * 32];
// cppcheck-suppress variableScope
static VL_THREAD_LOCAL int outStrSz = sizeof(outStr) - 1;
static VL_THREAD_LOCAL int t_outStrSz = sizeof(t_outStr) - 1;
// We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
// This may cause backward compatibility issues with older code.
if (valuep->format == vpiVectorVal) {
// Vector pointer must come from our memory pool
// It only needs to persist until the next vpi_get_value
static VL_THREAD_LOCAL t_vpi_vecval out[VL_MULS_MAX_WORDS * 2];
valuep->value.vector = out;
static VL_THREAD_LOCAL t_vpi_vecval t_out[VL_MULS_MAX_WORDS * 2];
valuep->value.vector = t_out;
if (varp->vltype() == VLVT_UINT8) {
out[0].aval = *(reinterpret_cast<CData*>(varDatap));
out[0].bval = 0;
t_out[0].aval = *(reinterpret_cast<CData*>(varDatap));
t_out[0].bval = 0;
return;
} else if (varp->vltype() == VLVT_UINT16) {
out[0].aval = *(reinterpret_cast<SData*>(varDatap));
out[0].bval = 0;
t_out[0].aval = *(reinterpret_cast<SData*>(varDatap));
t_out[0].bval = 0;
return;
} else if (varp->vltype() == VLVT_UINT32) {
out[0].aval = *(reinterpret_cast<IData*>(varDatap));
out[0].bval = 0;
t_out[0].aval = *(reinterpret_cast<IData*>(varDatap));
t_out[0].bval = 0;
return;
} else if (varp->vltype() == VLVT_UINT64) {
QData data = *(reinterpret_cast<QData*>(varDatap));
out[1].aval = static_cast<IData>(data >> 32ULL);
out[1].bval = 0;
out[0].aval = static_cast<IData>(data);
out[0].bval = 0;
t_out[1].aval = static_cast<IData>(data >> 32ULL);
t_out[1].bval = 0;
t_out[0].aval = static_cast<IData>(data);
t_out[0].bval = 0;
return;
} else if (varp->vltype() == VLVT_WDATA) {
int words = VL_WORDS_I(varp->packed().elements());
@@ -1453,47 +1457,47 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
}
WDataInP datap = (reinterpret_cast<EData*>(varDatap));
for (int i = 0; i < words; ++i) {
out[i].aval = datap[i];
out[i].bval = 0;
t_out[i].aval = datap[i];
t_out[i].bval = 0;
}
return;
}
} else if (valuep->format == vpiBinStrVal) {
valuep->value.str = outStr;
valuep->value.str = t_outStr;
int bits = varp->packed().elements();
CData* datap = (reinterpret_cast<CData*>(varDatap));
int i;
if (bits > outStrSz) {
if (bits > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
bits = outStrSz;
bits = t_outStrSz;
_VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz,
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz,
VL_MULS_MAX_WORDS, bits);
}
for (i = 0; i < bits; ++i) {
char val = (datap[i >> 3] >> (i & 7)) & 1;
outStr[bits - i - 1] = val ? '1' : '0';
t_outStr[bits - i - 1] = val ? '1' : '0';
}
outStr[i] = '\0';
t_outStr[i] = '\0';
return;
} else if (valuep->format == vpiOctStrVal) {
valuep->value.str = outStr;
valuep->value.str = t_outStr;
int chars = (varp->packed().elements() + 2) / 3;
int bytes = VL_BYTES_I(varp->packed().elements());
CData* datap = (reinterpret_cast<CData*>(varDatap));
int i;
if (chars > outStrSz) {
if (chars > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz,
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz,
VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
chars = t_outStrSz;
}
for (i = 0; i < chars; ++i) {
div_t idx = div(i * 3, 8);
@@ -1514,44 +1518,44 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
val &= (1 << rem) - 1;
}
}
outStr[chars - i - 1] = '0' + (val & 7);
t_outStr[chars - i - 1] = '0' + (val & 7);
}
outStr[i] = '\0';
t_outStr[i] = '\0';
return;
} else if (valuep->format == vpiDecStrVal) {
valuep->value.str = outStr;
valuep->value.str = t_outStr;
// outStrSz does not include nullptr termination so add one
if (varp->vltype() == VLVT_UINT8) {
VL_SNPRINTF(outStr, outStrSz + 1, "%hhu",
VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%hhu",
static_cast<unsigned char>(*(reinterpret_cast<CData*>(varDatap))));
return;
} else if (varp->vltype() == VLVT_UINT16) {
VL_SNPRINTF(outStr, outStrSz + 1, "%hu",
VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%hu",
static_cast<unsigned short>(*(reinterpret_cast<SData*>(varDatap))));
return;
} else if (varp->vltype() == VLVT_UINT32) {
VL_SNPRINTF(outStr, outStrSz + 1, "%u",
VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%u",
static_cast<unsigned int>(*(reinterpret_cast<IData*>(varDatap))));
return;
} else if (varp->vltype() == VLVT_UINT64) {
VL_SNPRINTF(outStr, outStrSz + 1, "%llu",
VL_SNPRINTF(t_outStr, t_outStrSz + 1, "%llu",
static_cast<unsigned long long>(*(reinterpret_cast<QData*>(varDatap))));
return;
}
} else if (valuep->format == vpiHexStrVal) {
valuep->value.str = outStr;
valuep->value.str = t_outStr;
int chars = (varp->packed().elements() + 3) >> 2;
CData* datap = (reinterpret_cast<CData*>(varDatap));
int i;
if (chars > outStrSz) {
if (chars > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz,
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz,
VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
chars = t_outStrSz;
}
for (i = 0; i < chars; ++i) {
char val = (datap[i >> 1] >> ((i & 1) << 2)) & 15;
@@ -1564,35 +1568,35 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
val &= (1 << rem) - 1;
}
}
outStr[chars - i - 1] = "0123456789abcdef"[static_cast<int>(val)];
t_outStr[chars - i - 1] = "0123456789abcdef"[static_cast<int>(val)];
}
outStr[i] = '\0';
t_outStr[i] = '\0';
return;
} else if (valuep->format == vpiStringVal) {
if (varp->vltype() == VLVT_STRING) {
valuep->value.str = reinterpret_cast<char*>(varDatap);
return;
} else {
valuep->value.str = outStr;
valuep->value.str = t_outStr;
int bytes = VL_BYTES_I(varp->packed().elements());
CData* datap = (reinterpret_cast<CData*>(varDatap));
int i;
if (bytes > outStrSz) {
if (bytes > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, outStrSz,
VL_MULS_MAX_WORDS, bytes);
bytes = outStrSz;
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), fullname,
t_outStrSz, VL_MULS_MAX_WORDS, bytes);
bytes = t_outStrSz;
}
for (i = 0; i < bytes; ++i) {
char val = datap[bytes - i - 1];
// other simulators replace [leading?] zero chars with spaces, replicate here.
outStr[i] = val ? val : ' ';
t_outStr[i] = val ? val : ' ';
}
outStr[i] = '\0';
t_outStr[i] = '\0';
return;
}
} else if (valuep->format == vpiIntVal) {
+1 -1
View File
@@ -33,7 +33,7 @@
//======================================================================
class VerilatedVpi {
class VerilatedVpi final {
public:
/// Call timed callbacks
/// Users should call this from their main loops
+4 -1
View File
@@ -374,7 +374,10 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//=========================================================================
// Class definition helpers
// Used to declare a class as uncopyable; put after a private:
/// Used to indicate a base class, e.g. cannot label "class final"
#define VL_NOT_FINAL
/// Used to declare a class as uncopyable; put after a private:
#define VL_UNCOPYABLE(Type) \
Type(const Type& other) = delete; \
Type& operator=(const Type&) = delete
+32 -32
View File
@@ -83,28 +83,28 @@ sub test {
require "./nodist/code_coverage.dat";
if ($Opt_Stages{1}) {
travis_fold_start("configure");
ci_fold_start("configure");
print "Stage 1: configure (coverage on)\n";
run("make distclean || true");
run("autoconf");
# Exceptions can pollute the branch coverage data
run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'");
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{2}) {
travis_fold_start("build");
ci_fold_start("build");
print "Stage 2: build\n";
my $nproc = Unix::Processors->new->max_online;
run("make -k -j $nproc VERILATOR_NO_OPT_BUILD=1");
# The optimized versions will not collect good coverage, overwrite them
run("cp bin/verilator_bin_dbg bin/verilator_bin");
run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin");
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{3}) {
travis_fold_start("test");
ci_fold_start("test");
print "Stage 3: make tests (with coverage on)\n";
if ($#Opt_Tests < 0) {
run("make examples VERILATOR_NO_OPT_BUILD=1")
@@ -121,12 +121,12 @@ sub test {
run($test);
}
}
travis_fold_end();
ci_fold_end();
}
my $cc_dir = "nodist/obj_dir/coverage";
if ($Opt_Stages{4}) {
travis_fold_start("gcno");
ci_fold_start("gcno");
print "Stage 4: Create gcno files under $cc_dir\n";
mkpath($cc_dir);
mkpath("$cc_dir/info");
@@ -165,11 +165,11 @@ sub test {
}
}
}
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{5} && $Opt_Fastcov) {
travis_fold_start("fastcov");
ci_fold_start("fastcov");
# Must run in root directory to find all files
mkpath($cc_dir);
#run("${RealBin}/fastcov.py -b -c src/obj_dbg -X".
@@ -178,11 +178,11 @@ sub test {
run("${RealBin}/fastcov.py -b -c src/obj_dbg -X --lcov".
" --exclude /usr --exclude test_regress"
." -o ${cc_dir}/app_total.info");
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{5} && !$Opt_Fastcov) {
travis_fold_start("infos");
ci_fold_start("infos");
print "Stage 5: make infos\n";
my $dats = `find . -print | grep .gcda`;
my %dirs;
@@ -199,20 +199,20 @@ sub test {
})->run;
}
$Fork->wait_all;
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{6}) {
travis_fold_start("clone");
ci_fold_start("clone");
# No control file to override single lines, so replicate the sources
# Also lets us see the insertion markers in the HTML source res
print "Stage 6: Clone sources under $cc_dir\n";
clone_sources($cc_dir);
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{8} && !$Opt_Fastcov) {
travis_fold_start("copy");
ci_fold_start("copy");
print "Stage 8: Copy .gcno files\n";
my $dats = `find . -print | grep .gcno`;
foreach my $dat (sort (split '\n', $dats)) {
@@ -221,11 +221,11 @@ sub test {
#print "cp $dat, $outdat);\n";
cp($dat, $outdat);
}
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{10} && !$Opt_Fastcov) {
travis_fold_start("combine");
ci_fold_start("combine");
print "Stage 10: Combine data files\n";
{
run("cd $cc_dir ; lcov -c -i -d src/obj_dbg -o app_base.info");
@@ -243,11 +243,11 @@ sub test {
}
}
}
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{11}) {
travis_fold_start("dirs");
ci_fold_start("dirs");
print "Stage 11: Cleanup paths\n";
if ($Opt_Fastcov) {
cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info");
@@ -255,11 +255,11 @@ sub test {
} else {
cleanup_abs_paths_info($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info");
}
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{12}) {
travis_fold_start("filter");
ci_fold_start("filter");
print "Stage 12: Filter processed source files\n";
my $inc = '';
foreach my $glob (@Source_Globs) {
@@ -282,24 +282,24 @@ sub test {
} else {
run("cd $cc_dir ; lcov --remove app_total.info $exc -o app_total_f.info");
}
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{17}) {
travis_fold_start("report");
ci_fold_start("report");
print "Stage 17: Create HTML\n";
run("cd $cc_dir ; genhtml app_total_f.info --demangle-cpp"
." --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html");
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{18}) {
travis_fold_start("upload");
ci_fold_start("upload");
print "Stage 18: Upload\n";
my $cmd = "bash <(curl -s https://codecov.io/bash) -f $cc_dir/app_total.info";
print "print: Not running: export CODECOV_TOKEN=<hidden>\n";
print "print: Not running: $cmd\n";
travis_fold_end();
ci_fold_end();
}
if ($Opt_Stages{19}) {
@@ -425,13 +425,13 @@ sub run {
($status == 0) or die "%Error: Command Failed $command, $status, stopped";
}
our $_Travis_Action;
sub travis_fold_start {
$_Travis_Action = shift;
print "travis_fold:start:$_Travis_Action\n";
our $_Ci_Action;
sub ci_fold_start {
$_Ci_Action = shift;
print "travis_fold:start:$_Ci_Action\n";
}
sub travis_fold_end {
print "travis_fold:end:$_Travis_Action\n";
sub ci_fold_end {
print "travis_fold:end:$_Ci_Action\n";
}
#######################################################################
+1
View File
@@ -57,6 +57,7 @@ exclude_line_regexp(qr/(\bv3fatalSrc\b
# Exclude for branch coverage only
exclude_branch_regexp(qr/(\bdebug\(\)
|\bassert\(
|\bBROKEN_RTK\(
|\bSELF_CHECK)/x);
1;
+3 -3
View File
@@ -7,21 +7,21 @@
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
define pn
call $arg0->dumpGdb()
call AstNode::dumpGdb($arg0)
end
document pn
Verilator: Print single AstNode NODEP
end
define pnt
call $arg0->dumpTreeGdb()
call AstNode::dumpTreeGdb($arg0)
end
document pnt
Verilator: Print AstNode NODEP's tree
end
define dtf
call AstNode::dumpTreeFileGdb(0)
call AstNode::dumpTreeFileGdb($arg0, 0)
end
document dtf
Verilator: Dump AstNode tree to file
-1
View File
@@ -94,7 +94,6 @@ LIBS = $(CFG_LIBS) -lm
CPPFLAGS += -MMD
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) -I../../include
CPPFLAGS += -DYYDEBUG # Required to get nice error messages
#CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
CPPFLAGS += $(COPT)
CPPFLAGS += -MP # Only works on recent GCC versions
+16 -8
View File
@@ -43,12 +43,12 @@
//######################################################################
// Collect existing active names
class ActiveBaseVisitor : public AstNVisitor {
class ActiveBaseVisitor VL_NOT_FINAL : public AstNVisitor {
protected:
VL_DEBUG_FUNC; // Declare debug()
};
class ActiveNamer : public ActiveBaseVisitor {
class ActiveNamer final : public ActiveBaseVisitor {
private:
// STATE
AstScope* m_scopep = nullptr; // Current scope to add statement to
@@ -130,15 +130,15 @@ public:
}
// CONSTRUCTORS
ActiveNamer() {}
virtual ~ActiveNamer() override {}
ActiveNamer() = default;
virtual ~ActiveNamer() override = default;
void main(AstScope* nodep) { iterate(nodep); }
};
//######################################################################
// Active AssignDly replacement functions
class ActiveDlyVisitor : public ActiveBaseVisitor {
class ActiveDlyVisitor final : public ActiveBaseVisitor {
public:
enum CheckType : uint8_t { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
@@ -205,13 +205,13 @@ public:
, m_alwaysp{nodep} {
iterate(nodep);
}
virtual ~ActiveDlyVisitor() override {}
virtual ~ActiveDlyVisitor() override = default;
};
//######################################################################
// Active class functions
class ActiveVisitor : public ActiveBaseVisitor {
class ActiveVisitor final : public ActiveBaseVisitor {
private:
// NODE STATE
// Each call to V3Const::constify
@@ -364,6 +364,14 @@ private:
}
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
}
virtual void visit(AstAlwaysPostponed* nodep) override {
UINFO(4, " ALW " << nodep << endl);
if (!nodep->bodysp()) {
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS);
}
virtual void visit(AstAlwaysPublic* nodep) override {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4, " ALWPub " << nodep << endl);
@@ -406,7 +414,7 @@ private:
public:
// CONSTRUCTORS
explicit ActiveVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~ActiveVisitor() override {}
virtual ~ActiveVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Active {
class V3Active final {
public:
static void activeAll(AstNetlist* nodep);
};
+2 -2
View File
@@ -35,7 +35,7 @@
//######################################################################
// Active class functions
class ActiveTopVisitor : public AstNVisitor {
class ActiveTopVisitor final : public AstNVisitor {
private:
// NODE STATE
// Entire netlist
@@ -128,7 +128,7 @@ private:
public:
// CONSTRUCTORS
explicit ActiveTopVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~ActiveTopVisitor() override {}
virtual ~ActiveTopVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3ActiveTop {
class V3ActiveTop final {
public:
static void activeTopAll(AstNetlist* nodep);
};
+76 -6
View File
@@ -26,7 +26,7 @@
//######################################################################
// Assert class functions
class AssertVisitor : public AstNVisitor {
class AssertVisitor final : public AstNVisitor {
private:
// NODE STATE/TYPES
// Cleared on netlist
@@ -36,7 +36,11 @@ private:
// STATE
AstNodeModule* m_modp = nullptr; // Last module
AstBegin* m_beginp = nullptr; // Last begin
unsigned m_monitorNum = 0; // Global $monitor numbering (not per module)
AstVar* m_monitorNumVarp = nullptr; // $monitor number variable
AstVar* m_monitorOffVarp = nullptr; // $monitoroff variable
unsigned m_modPastNum = 0; // Module past numbering
unsigned m_modStrobeNum = 0; // Module $strobe numbering
VDouble0 m_statCover; // Statistic tracking
VDouble0 m_statAsNotImm; // Statistic tracking
VDouble0 m_statAsImm; // Statistic tracking
@@ -62,7 +66,26 @@ private:
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
}
}
AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) {
if (!m_monitorNumVarp) {
m_monitorNumVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP,
"__VmonitorNum", nodep->findUInt64DType()};
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp);
}
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access);
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
return varrefp;
}
AstVarRef* newMonitorOffVarRefp(AstNode* nodep, VAccess access) {
if (!m_monitorOffVarp) {
m_monitorOffVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP,
"__VmonitorOff", nodep->findBitDType()};
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp);
}
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access);
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
return varrefp;
}
AstNode* newIfAssertOn(AstNode* nodep) {
// Add a internal if to check assertions are on.
// Don't make this a AND term, as it's unlikely to need to test this.
@@ -73,7 +96,7 @@ private:
// This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
: static_cast<AstNode*>(new AstConst(fl, AstConst::BitFalse()))),
nodep, nullptr);
newp->user1(true); // Don't assert/cover this if
return newp;
@@ -207,7 +230,7 @@ private:
bool allow_none = nodep->unique0Pragma();
// Empty case means no property
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::BitFalse());
// Note: if this ends with an 'else', then we don't need to validate that one of the
// predicates evaluates to true.
@@ -276,7 +299,7 @@ private:
}
}
// Empty case means no property
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::BitFalse());
bool allow_none = has_default || nodep->unique0Pragma();
AstNode* ohot
@@ -342,9 +365,54 @@ private:
} else if (nodep->displayType() == AstDisplayType::DT_ERROR
|| nodep->displayType() == AstDisplayType::DT_FATAL) {
replaceDisplay(nodep, "%%Error");
} else if (nodep->displayType() == AstDisplayType::DT_MONITOR) {
nodep->displayType(AstDisplayType::DT_DISPLAY);
const auto fl = nodep->fileline();
const auto monNum = ++m_monitorNum;
// Where $monitor was we do "__VmonitorNum = N;"
const auto newsetp = new AstAssign{fl, newMonitorNumVarRefp(nodep, VAccess::WRITE),
new AstConst{fl, monNum}};
nodep->replaceWith(newsetp);
// Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);"
AstNode* stmtsp = nodep;
AstIf* ifp = new AstIf{
fl,
new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)},
new AstEq{fl, new AstConst{fl, monNum},
newMonitorNumVarRefp(nodep, VAccess::READ)}},
stmtsp, nullptr};
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* newp = new AstAlwaysPostponed{fl, ifp};
m_modp->addStmtp(newp);
} else if (nodep->displayType() == AstDisplayType::DT_STROBE) {
nodep->displayType(AstDisplayType::DT_DISPLAY);
// Need one-shot
const auto fl = nodep->fileline();
const auto varp
= new AstVar{fl, AstVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
nodep->findBitDType()};
m_modp->addStmtp(varp);
// Where $strobe was we do "__Vstrobe = '1;"
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
new AstConst{fl, AstConst::BitTrue{}}};
nodep->replaceWith(newsetp);
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
AstNode* stmtsp = nodep;
AstIf* ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp, nullptr};
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* newp = new AstAlwaysPostponed{fl, ifp};
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
new AstConst{fl, AstConst::BitFalse{}}});
m_modp->addStmtp(newp);
}
}
virtual void visit(AstMonitorOff* nodep) override {
const auto newp
= new AstAssign(nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
new AstConst(nodep->fileline(), AstConst::BitTrue{}, nodep->off()));
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstAssert* nodep) override {
iterateChildren(nodep);
newPslAssertion(nodep, nodep->failsp());
@@ -362,9 +430,11 @@ private:
virtual void visit(AstNodeModule* nodep) override {
VL_RESTORER(m_modp);
VL_RESTORER(m_modPastNum);
VL_RESTORER(m_modStrobeNum);
{
m_modp = nodep;
m_modPastNum = 0;
m_modStrobeNum = 0;
iterateChildren(nodep);
}
}
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Assert {
class V3Assert final {
public:
static void assertAll(AstNetlist* nodep);
};
+6 -6
View File
@@ -26,7 +26,7 @@
//######################################################################
// Assert class functions
class AssertPreVisitor : public AstNVisitor {
class AssertPreVisitor final : public AstNVisitor {
// Removes clocks and other pre-optimizations
// Eventually inlines calls to sequences, properties, etc.
// We're not parsing the tree, or anything more complicated.
@@ -103,7 +103,7 @@ private:
AstNode* past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp);
exprp = new AstAnd(fl, past, new AstNot(fl, exprp->cloneTree(false)));
exprp->dtypeSetLogicBool();
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep));
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@@ -122,7 +122,7 @@ private:
AstNode* past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp);
exprp = new AstAnd(fl, new AstNot(fl, past), exprp->cloneTree(false));
exprp->dtypeSetLogicBool();
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep));
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@@ -135,7 +135,7 @@ private:
AstNode* past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp);
exprp = new AstEq(fl, past, exprp->cloneTree(false));
exprp->dtypeSetLogicBool();
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep));
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@@ -153,7 +153,7 @@ private:
AstNode* past = new AstPast(fl, lhsp, nullptr);
past->dtypeFrom(lhsp);
AstNode* exprp = new AstOr(fl, new AstNot(fl, past), rhsp);
exprp->dtypeSetLogicBool();
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep));
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@@ -197,7 +197,7 @@ public:
// Process
iterate(nodep);
}
virtual ~AssertPreVisitor() override {}
virtual ~AssertPreVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3AssertPre {
class V3AssertPre final {
public:
static void assertPreAll(AstNetlist* nodep);
};
+40 -26
View File
@@ -127,8 +127,9 @@ string AstNode::encodeName(const string& namein) {
}
// Shorten names
// TODO long term use VName in place of "string name"
VName vname(out);
out = vname.hashedName();
// Then we also won't need to save the table of hased values
VName vname{out};
return vname.hashedName();
return out;
}
@@ -161,7 +162,8 @@ string AstNode::dedotName(const string& namein) {
string AstNode::vcdName(const string& namein) {
// VCD tracing expects space to separate hierarchy
// Dots are reserved for dots the user put in the name
string pretty = namein;
// We earlier hashed all symbols, dehash them so user sees real name
string pretty{VName::dehash(namein)};
string::size_type pos;
while ((pos = pretty.find("__DOT__")) != string::npos) pretty.replace(pos, 7, " ");
while ((pos = pretty.find('.')) != string::npos) pretty.replace(pos, 1, " ");
@@ -1027,28 +1029,40 @@ void AstNode::checkTree() {
}
// cppcheck-suppress unusedFunction // Debug only
void AstNode::dumpGdb() { // For GDB only // LCOV_EXCL_LINE
dumpGdbHeader(); // LCOV_EXCL_LINE
void AstNode::dumpGdb(const AstNode* nodep) { // For GDB only // LCOV_EXCL_LINE
if (!nodep) {
cout << "<nullptr>" << endl;
return;
}
nodep->dumpGdbHeader();
cout << " ";
dump(cout);
cout << endl; // LCOV_EXCL_LINE
}
nodep->dump(cout);
cout << endl;
} // LCOV_EXCL_STOP
// cppcheck-suppress unusedFunction // Debug only
void AstNode::dumpGdbHeader() const { // For GDB only // LCOV_EXCL_LINE
dumpPtrs(cout); // LCOV_EXCL_LINE
cout << " Fileline = " << fileline() << endl; // LCOV_EXCL_LINE
}
void AstNode::dumpGdbHeader() const { // For GDB only // LCOV_EXCL_START
dumpPtrs(cout);
cout << " Fileline = " << fileline() << endl;
} // LCOV_EXCL_STOP
// cppcheck-suppress unusedFunction // Debug only
void AstNode::dumpTreeGdb() { // For GDB only // LCOV_EXCL_LINE
dumpGdbHeader(); // LCOV_EXCL_LINE
dumpTree(cout); // LCOV_EXCL_LINE
}
void AstNode::dumpTreeGdb(const AstNode* nodep) { // For GDB only // LCOV_EXCL_START
if (!nodep) {
cout << "<nullptr>" << endl;
return;
}
nodep->dumpGdbHeader();
nodep->dumpTree(cout);
} // LCOV_EXCL_STOP
// cppcheck-suppress unusedFunction // Debug only
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only // LCOV_EXCL_LINE
string filename
= filenamep ? filenamep : v3Global.debugFilename("debug.tree", 98); // LCOV_EXCL_LINE
v3Global.rootp()->dumpTreeFile(filename); // LCOV_EXCL_LINE
}
void AstNode::dumpTreeFileGdb(const AstNode* nodep, // LCOV_EXCL_START
const char* filenamep) { // For GDB only
if (!nodep) {
cout << "<nullptr>" << endl;
return;
}
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree", 98);
v3Global.rootp()->dumpTreeFile(filename);
} // LCOV_EXCL_STOP
// cppcheck-suppress unusedFunction // Debug only
void AstNode::checkIter() const {
@@ -1086,14 +1100,14 @@ void AstNode::dumpPtrs(std::ostream& os) const {
void AstNode::dumpTree(std::ostream& os, const string& indent, int maxDepth) const {
static int s_debugFileline = v3Global.opt.debugSrcLevel("fileline"); // --debugi-fileline 9
os << indent << " " << this << endl;
os << indent << " " << this << '\n';
if (debug() > 8) {
os << indent << " ";
dumpPtrs(os);
}
if (s_debugFileline >= 9) { os << fileline()->warnContextSecondary(); }
if (maxDepth == 1) {
if (op1p() || op2p() || op3p() || op4p()) { os << indent << "1: ...(maxDepth)" << endl; }
if (op1p() || op2p() || op3p() || op4p()) os << indent << "1: ...(maxDepth)\n";
} else {
for (const AstNode* nodep = op1p(); nodep; nodep = nodep->nextp()) {
nodep->dumpTree(os, indent + "1:", maxDepth - 1);
@@ -1125,9 +1139,9 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo
const std::unique_ptr<std::ofstream> logsp(V3File::new_ofstream(filename, append));
if (logsp->fail()) v3fatal("Can't write " << filename);
*logsp << "Verilator Tree Dump (format 0x3900) from <e" << std::dec << editCountLast();
*logsp << "> to <e" << std::dec << editCountGbl() << ">" << endl;
*logsp << "> to <e" << std::dec << editCountGbl() << ">\n";
if (editCountGbl() == editCountLast() && !(v3Global.opt.dumpTree() >= 9)) {
*logsp << endl;
*logsp << '\n';
*logsp << "No changes since last dump!\n";
} else {
dumpTree(*logsp);
@@ -1197,7 +1211,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const {
std::ostringstream nsstr;
nsstr << str.str();
if (debug()) {
nsstr << endl;
nsstr << '\n';
nsstr << "-node: ";
const_cast<AstNode*>(this)->dump(nsstr);
nsstr << endl;
+147 -136
View File
@@ -71,7 +71,7 @@ typedef std::set<int> MTaskIdSet; // Set of mtaskIds for Var sorting
//######################################################################
class AstType {
class AstType final {
public:
#include "V3Ast__gen_types.h" // From ./astgen
// Above include has:
@@ -94,7 +94,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return o
//######################################################################
class VLifetime {
class VLifetime final {
public:
enum en : uint8_t { NONE, AUTOMATIC, STATIC };
enum en m_e;
@@ -123,7 +123,7 @@ inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) {
//######################################################################
class VAccess {
class VAccess final {
public:
enum en : uint8_t {
READ, // Read/Consumed, variable not changed
@@ -166,7 +166,7 @@ inline std::ostream& operator<<(std::ostream& os, const VAccess& rhs) { return o
//######################################################################
class VSigning {
class VSigning final {
public:
enum en : uint8_t {
UNSIGNED,
@@ -203,7 +203,7 @@ inline std::ostream& operator<<(std::ostream& os, const VSigning& rhs) {
//######################################################################
class AstPragmaType {
class AstPragmaType final {
public:
enum en : uint8_t {
ILLEGAL,
@@ -236,7 +236,7 @@ inline bool operator==(AstPragmaType::en lhs, const AstPragmaType& rhs) { return
//######################################################################
class AstCFuncType {
class AstCFuncType final {
public:
enum en : uint8_t {
FT_NORMAL,
@@ -269,7 +269,7 @@ inline bool operator==(AstCFuncType::en lhs, const AstCFuncType& rhs) { return l
//######################################################################
class VEdgeType {
class VEdgeType final {
public:
// REMEMBER to edit the strings below too
enum en : uint8_t {
@@ -355,7 +355,7 @@ inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs ==
//######################################################################
class AstAttrType {
class AstAttrType final {
public:
// clang-format off
enum en: uint8_t {
@@ -436,7 +436,7 @@ inline bool operator==(AstAttrType::en lhs, const AstAttrType& rhs) { return lhs
//######################################################################
class AstBasicDTypeKwd {
class AstBasicDTypeKwd final {
public:
enum en : uint8_t {
UNKNOWN,
@@ -450,7 +450,6 @@ public:
LONGINT,
DOUBLE,
SHORTINT,
FLOAT,
TIME,
// Closer to a class type, but limited usage
STRING,
@@ -468,18 +467,16 @@ public:
enum en m_e;
const char* ascii() const {
static const char* const names[] = {
"%E-unk", //
"bit", "byte", "chandle", "event", "int", "integer", "logic",
"longint", "real", "shortint", "shortreal", "time", "string", "VerilatedScope*",
"char*", "IData", "QData", "LOGIC_IMPLICIT", " MAX"};
"%E-unk", "bit", "byte", "chandle", "event", "int", "integer",
"logic", "longint", "real", "shortint", "time", "string", "VerilatedScope*",
"char*", "IData", "QData", "LOGIC_IMPLICIT", " MAX"};
return names[m_e];
}
const char* dpiType() const {
static const char* const names[]
= {"%E-unk", //
"svBit", "char", "void*", "char", "int", "%E-integer",
"svLogic", "long long", "double", "short", "float", "%E-time",
"const char*", "dpiScope", "const char*", "IData", "QData", "%E-logic-implicit",
= {"%E-unk", "svBit", "char", "void*", "char", "int",
"%E-integer", "svLogic", "long long", "double", "short", "%E-time",
"const char*", "dpiScope", "const char*", "IData", "QData", "%E-logic-implicit",
" MAX"};
return names[m_e];
}
@@ -508,7 +505,6 @@ public:
case LOGIC: return 1; // scalar, can't bit extract unless ranged
case LONGINT: return 64;
case DOUBLE: return 64; // opaque
case FLOAT: return 32; // opaque
case SHORTINT: return 16;
case TIME: return 64;
case STRING: return 64; // opaque // Just the pointer, for today
@@ -521,7 +517,7 @@ public:
}
bool isSigned() const {
return m_e == BYTE || m_e == SHORTINT || m_e == INT || m_e == LONGINT || m_e == INTEGER
|| m_e == DOUBLE || m_e == FLOAT;
|| m_e == DOUBLE;
}
bool isUnsigned() const {
return m_e == CHANDLE || m_e == EVENTVALUE || m_e == STRING || m_e == SCOPEPTR
@@ -532,8 +528,7 @@ public:
}
bool isZeroInit() const { // Otherwise initializes to X
return (m_e == BIT || m_e == BYTE || m_e == CHANDLE || m_e == EVENTVALUE || m_e == INT
|| m_e == LONGINT || m_e == SHORTINT || m_e == STRING || m_e == DOUBLE
|| m_e == FLOAT);
|| m_e == LONGINT || m_e == SHORTINT || m_e == STRING || m_e == DOUBLE);
}
bool isIntNumeric() const { // Enum increment supported
return (m_e == BIT || m_e == BYTE || m_e == INT || m_e == INTEGER || m_e == LOGIC
@@ -553,8 +548,7 @@ public:
|| m_e == DOUBLE || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64);
}
bool isOpaque() const { // IE not a simple number we can bit optimize
return (m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR || m_e == DOUBLE
|| m_e == FLOAT);
return (m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR || m_e == DOUBLE);
}
bool isDouble() const { return m_e == DOUBLE; }
bool isEventValue() const { return m_e == EVENTVALUE; }
@@ -572,7 +566,7 @@ inline bool operator==(AstBasicDTypeKwd::en lhs, const AstBasicDTypeKwd& rhs) {
//######################################################################
class VDirection {
class VDirection final {
public:
enum en : uint8_t { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF };
enum en m_e;
@@ -617,7 +611,7 @@ inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) {
//######################################################################
/// Boolean or unknown
class VBoolOrUnknown {
class VBoolOrUnknown final {
public:
enum en : uint8_t { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END };
enum en m_e;
@@ -656,7 +650,7 @@ inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) {
//######################################################################
/// Join type
class VJoinType {
class VJoinType final {
public:
enum en : uint8_t { JOIN = 0, JOIN_ANY = 1, JOIN_NONE = 2 };
enum en m_e;
@@ -689,7 +683,7 @@ inline std::ostream& operator<<(std::ostream& os, const VJoinType& rhs) {
//######################################################################
class AstVarType {
class AstVarType final {
public:
enum en : uint8_t {
UNKNOWN,
@@ -757,7 +751,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) {
//######################################################################
class VBranchPred {
class VBranchPred final {
public:
enum en : uint8_t { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END };
enum en m_e;
@@ -798,7 +792,7 @@ inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) {
//######################################################################
class VVarAttrClocker {
class VVarAttrClocker final {
public:
enum en : uint8_t { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END };
enum en m_e;
@@ -841,7 +835,7 @@ inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) {
//######################################################################
class VAlwaysKwd {
class VAlwaysKwd final {
public:
enum en : uint8_t { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB };
enum en m_e;
@@ -864,7 +858,7 @@ inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs =
//######################################################################
class VCaseType {
class VCaseType final {
public:
enum en : uint8_t { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE };
enum en m_e;
@@ -883,14 +877,23 @@ inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs ==
//######################################################################
class AstDisplayType {
class AstDisplayType final {
public:
enum en : uint8_t { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL };
enum en : uint8_t {
DT_DISPLAY,
DT_WRITE,
DT_MONITOR,
DT_STROBE,
DT_INFO,
DT_ERROR,
DT_WARNING,
DT_FATAL
};
enum en m_e;
inline AstDisplayType()
AstDisplayType()
: m_e{DT_DISPLAY} {}
// cppcheck-suppress noExplicitConstructor
inline AstDisplayType(en _e)
AstDisplayType(en _e)
: m_e{_e} {}
explicit inline AstDisplayType(int _e)
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
@@ -899,7 +902,7 @@ public:
bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; }
const char* ascii() const {
static const char* const names[]
= {"display", "write", "info", "error", "warning", "fatal"};
= {"display", "write", "monitor", "strobe", "info", "error", "warning", "fatal"};
return names[m_e];
}
};
@@ -915,7 +918,7 @@ inline bool operator==(AstDisplayType::en lhs, const AstDisplayType& rhs) {
//######################################################################
class VDumpCtlType {
class VDumpCtlType final {
public:
enum en : uint8_t { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON };
enum en m_e;
@@ -941,7 +944,7 @@ inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return l
//######################################################################
class VParseRefExp {
class VParseRefExp final {
public:
enum en : uint8_t {
PX_NONE, // Used in V3LinkParse only
@@ -975,10 +978,10 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) {
// VNumRange - Structure containing numeric range information
// See also AstRange, which is a symbolic version of this
class VNumRange {
class VNumRange final {
public:
int m_hi; // HI part, HI always >= LO
int m_lo; // LO
int m_hi = 0; // HI part, HI always >= LO
int m_lo = 0; // LO
union {
int mu_flags;
struct {
@@ -986,10 +989,10 @@ public:
bool m_littleEndian : 1; // Bit vector is little endian
};
};
inline bool operator==(const VNumRange& rhs) const {
bool operator==(const VNumRange& rhs) const {
return m_hi == rhs.m_hi && m_lo == rhs.m_lo && mu_flags == rhs.mu_flags;
}
inline bool operator<(const VNumRange& rhs) const {
bool operator<(const VNumRange& rhs) const {
if ((m_hi < rhs.m_hi)) return true;
if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs
if ((m_lo < rhs.m_lo)) return true;
@@ -1001,22 +1004,16 @@ public:
//
class LeftRight {};
VNumRange()
: m_hi{0}
, m_lo{0}
, mu_flags{0} {}
: mu_flags{0} {}
VNumRange(int hi, int lo, bool littleEndian)
: m_hi{0}
, m_lo{0}
, mu_flags{0} {
: mu_flags{0} {
init(hi, lo, littleEndian);
}
VNumRange(LeftRight, int left, int right)
: m_hi{0}
, m_lo{0}
, mu_flags{0} {
: mu_flags{0} {
init((right > left) ? right : left, (right > left) ? left : right, (right > left));
}
~VNumRange() {}
~VNumRange() = default;
// MEMBERS
void init(int hi, int lo, bool littleEndian) {
m_hi = hi;
@@ -1054,7 +1051,7 @@ inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) {
//######################################################################
class VUseType {
class VUseType final {
public:
enum en : uint8_t {
IMP_INCLUDE, // Implementation (.cpp) needs an include
@@ -1087,18 +1084,18 @@ inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) {
//######################################################################
class VBasicTypeKey {
class VBasicTypeKey final {
public:
int m_width; // From AstNodeDType: Bit width of operation
int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation
VSigning m_numeric; // From AstNodeDType: Node is signed
AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
inline bool operator==(const VBasicTypeKey& rhs) const {
bool operator==(const VBasicTypeKey& rhs) const {
return m_width == rhs.m_width && m_widthMin == rhs.m_widthMin && m_numeric == rhs.m_numeric
&& m_keyword == rhs.m_keyword && m_nrange == rhs.m_nrange;
}
inline bool operator<(const VBasicTypeKey& rhs) const {
bool operator<(const VBasicTypeKey& rhs) const {
if ((m_width < rhs.m_width)) return true;
if (!(m_width == rhs.m_width)) return false; // lhs > rhs
if ((m_widthMin < rhs.m_widthMin)) return true;
@@ -1118,7 +1115,7 @@ public:
, m_numeric{numeric}
, m_keyword{kwd}
, m_nrange{nrange} {}
~VBasicTypeKey() {}
~VBasicTypeKey() = default;
};
//######################################################################
@@ -1129,7 +1126,7 @@ class WidthVP;
class V3GraphVertex;
class VSymEnt;
class VNUser {
class VNUser final {
union {
void* up;
int ui;
@@ -1144,14 +1141,14 @@ public:
m_u.ui = i;
}
explicit VNUser(void* p) { m_u.up = p; }
~VNUser() {}
~VNUser() = default;
// Casters
WidthVP* c() const { return reinterpret_cast<WidthVP*>(m_u.up); }
VSymEnt* toSymEnt() const { return reinterpret_cast<VSymEnt*>(m_u.up); }
AstNode* toNodep() const { return reinterpret_cast<AstNode*>(m_u.up); }
V3GraphVertex* toGraphVertex() const { return reinterpret_cast<V3GraphVertex*>(m_u.up); }
int toInt() const { return m_u.ui; }
static inline VNUser fromInt(int i) { return VNUser(i); }
static VNUser fromInt(int i) { return VNUser(i); }
};
//######################################################################
@@ -1165,7 +1162,7 @@ public:
// user2. When the member goes out of scope it will be automagically
// freed up.
class AstUserInUseBase {
class AstUserInUseBase VL_NOT_FINAL {
protected:
static void allocate(int id, uint32_t& cntGblRef, bool& userBusyRef) {
// Perhaps there's still a AstUserInUse in scope for this?
@@ -1196,7 +1193,7 @@ protected:
// We let AstNode peek into here, because when under low optimization even
// an accessor would be way too slow.
// clang-format off
class AstUser1InUse : AstUserInUseBase {
class AstUser1InUse final : AstUserInUseBase {
protected:
friend class AstNode;
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
@@ -1207,7 +1204,7 @@ public:
static void clear() { clearcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
static void check() { checkcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
};
class AstUser2InUse : AstUserInUseBase {
class AstUser2InUse final : AstUserInUseBase {
protected:
friend class AstNode;
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
@@ -1218,7 +1215,7 @@ public:
static void clear() { clearcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
static void check() { checkcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
};
class AstUser3InUse : AstUserInUseBase {
class AstUser3InUse final : AstUserInUseBase {
protected:
friend class AstNode;
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
@@ -1229,7 +1226,7 @@ public:
static void clear() { clearcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
static void check() { checkcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
};
class AstUser4InUse : AstUserInUseBase {
class AstUser4InUse final : AstUserInUseBase {
protected:
friend class AstNode;
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
@@ -1240,7 +1237,7 @@ public:
static void clear() { clearcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
static void check() { checkcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
};
class AstUser5InUse : AstUserInUseBase {
class AstUser5InUse final : AstUserInUseBase {
protected:
friend class AstNode;
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
@@ -1257,7 +1254,7 @@ public:
// AstNVisitor -- Allows new functions to be called on each node
// type without changing the base classes. See "Modern C++ Design".
class AstNVisitor {
class AstNVisitor VL_NOT_FINAL {
private:
// MEMBERS
std::vector<AstNode*> m_deleteps; // Nodes to delete when doDeletes() called
@@ -1304,7 +1301,7 @@ public:
// AstNRelinker -- Holds the state of a unlink so a new node can be
// added at the same point.
class AstNRelinker {
class AstNRelinker final {
protected:
friend class AstNode;
enum RelinkWhatEn : uint8_t {
@@ -1321,7 +1318,7 @@ protected:
AstNode** m_iterpp = nullptr;
public:
AstNRelinker() {}
AstNRelinker() = default;
void relink(AstNode* newp);
AstNode* oldp() const { return m_oldp; }
void dump(std::ostream& str = std::cout) const;
@@ -1334,7 +1331,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstNRelinker& rhs) {
//######################################################################
// V3Hash -- Node hashing for V3Combine
class V3Hash {
class V3Hash final {
// A hash of a tree of nodes, consisting of 8 bits with the number of nodes in the hash
// and 24 bit value hash of relevant information about the node.
// A value of 0 is illegal
@@ -1353,9 +1350,9 @@ public:
uint32_t depth() const { return (m_both >> 24) & 255; }
uint32_t hshval() const { return m_both & M24; }
// OPERATORS
inline bool operator==(const V3Hash& rh) const { return m_both == rh.m_both; }
inline bool operator!=(const V3Hash& rh) const { return m_both != rh.m_both; }
inline bool operator<(const V3Hash& rh) const { return m_both < rh.m_both; }
bool operator==(const V3Hash& rh) const { return m_both == rh.m_both; }
bool operator!=(const V3Hash& rh) const { return m_both != rh.m_both; }
bool operator<(const V3Hash& rh) const { return m_both < rh.m_both; }
// CONSTRUCTORS
class Illegal {}; // for creator type-overload selection
class FullValue {}; // for creator type-overload selection
@@ -1387,7 +1384,7 @@ std::ostream& operator<<(std::ostream& os, const V3Hash& rhs);
//######################################################################
// Callback base class to determine if node matches some formula
class VNodeMatcher {
class VNodeMatcher VL_NOT_FINAL {
public:
virtual bool nodeMatch(const AstNode* nodep) const { return true; }
};
@@ -1401,11 +1398,11 @@ public:
do { \
if (nodep) { \
VL_PREFETCH_RD(&((nodep)->m_nextp)); \
VL_PREFETCH_RD(&((nodep)->m_iterpp)); \
VL_PREFETCH_RD(&((nodep)->m_type)); \
} \
} while (false)
class AstNode {
class AstNode VL_NOT_FINAL {
// v ASTNODE_PREFETCH depends on below ordering of members
AstNode* m_nextp; // Next peer in the parent's list
AstNode* m_backp; // Node that points to this one (via next/op1/op2/...)
@@ -1414,22 +1411,21 @@ class AstNode {
AstNode* m_op3p; // Generic pointer 3
AstNode* m_op4p; // Generic pointer 4
AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node.
const AstType m_type; // Node sub-type identifier
// ^ ASTNODE_PREFETCH depends on above ordering of members
// padding - 2 extra bytes here after m_type
int m_cloneCnt; // Mark of when userp was set
AstNodeDType* m_dtypep; // Data type of output or assignment (etc)
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
const AstType m_type; // Node sub-type identifier
FileLine* m_fileline; // Where it was declared
vluint64_t m_editCount; // When it was last edited
static vluint64_t s_editCntGbl; // Global edit counter
// Global edit counter, last value for printing * near node #s
static vluint64_t s_editCntLast;
AstNodeDType* m_dtypep; // Data type of output or assignment (etc)
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
int m_cloneCnt; // Mark of when userp was set
static int s_cloneCntGbl; // Count of which userp is set
// Attributes
@@ -1545,7 +1541,7 @@ public:
bool brokeExistsBelow() const;
// CONSTRUCTORS
virtual ~AstNode() {}
virtual ~AstNode() = default;
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
static void operator delete(void* obj, size_t size);
@@ -1734,7 +1730,7 @@ public:
void dtypeSetLogicSized(int width, VSigning numeric) {
dtypep(findLogicDType(width, width, numeric)); // Since sized, widthMin is width
}
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
void dtypeSetBit() { dtypep(findBitDType()); }
void dtypeSetDouble() { dtypep(findDoubleDType()); }
void dtypeSetString() { dtypep(findStringDType()); }
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
@@ -1743,7 +1739,7 @@ public:
void dtypeSetVoid() { dtypep(findVoidDType()); }
// Data type locators
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
AstNodeDType* findBitDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); }
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
@@ -1768,7 +1764,7 @@ public:
string warnOther() const { return fileline()->warnOther(); }
virtual void dump(std::ostream& str = std::cout) const;
void dumpGdb(); // For GDB only
static void dumpGdb(const AstNode* nodep); // For GDB only
void dumpGdbHeader() const;
// METHODS - Tree modifications
@@ -1818,12 +1814,12 @@ public:
void dumpTree(const string& indent, int maxDepth = 0) const {
dumpTree(cout, indent, maxDepth);
}
void dumpTreeGdb(); // For GDB only
static void dumpTreeGdb(const AstNode* nodep); // For GDB only
void dumpTreeAndNext(std::ostream& os = std::cout, const string& indent = " ",
int maxDepth = 0) const;
void dumpTreeFile(const string& filename, bool append = false, bool doDump = true,
bool doCheck = true);
static void dumpTreeFileGdb(const char* filenamep = nullptr);
static void dumpTreeFileGdb(const AstNode* nodep, const char* filenamep = nullptr);
// METHODS - queries
// Changes control flow, disable some optimizations
@@ -1912,7 +1908,7 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
//=== AstNode* : Derived generic node types
#define ASTNODE_BASE_FUNCS(name) \
virtual ~Ast##name() {} \
virtual ~Ast##name() override = default; \
static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \
return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \
} \
@@ -1921,7 +1917,7 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
} \
Ast##name* clonep() const { return static_cast<Ast##name*>(AstNode::clonep()); }
class AstNodeMath : public AstNode {
class AstNodeMath VL_NOT_FINAL : public AstNode {
// Math -- anything that's part of an expression tree
public:
AstNodeMath(AstType t, FileLine* fl)
@@ -1941,7 +1937,7 @@ public:
bool isOpaque() { return VN_IS(this, CvtPackString); }
};
class AstNodeTermop : public AstNodeMath {
class AstNodeTermop VL_NOT_FINAL : public AstNodeMath {
// Terminal operator -- a operator with no "inputs"
public:
AstNodeTermop(AstType t, FileLine* fl)
@@ -1954,7 +1950,7 @@ public:
virtual void dump(std::ostream& str) const override;
};
class AstNodeUniop : public AstNodeMath {
class AstNodeUniop VL_NOT_FINAL : public AstNodeMath {
// Unary math
public:
AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp)
@@ -1980,7 +1976,7 @@ public:
virtual bool same(const AstNode*) const override { return true; }
};
class AstNodeBiop : public AstNodeMath {
class AstNodeBiop VL_NOT_FINAL : public AstNodeMath {
// Binary math
public:
AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
@@ -2012,7 +2008,7 @@ public:
virtual bool same(const AstNode*) const override { return true; }
};
class AstNodeTriop : public AstNodeMath {
class AstNodeTriop VL_NOT_FINAL : public AstNodeMath {
// Trinary math
public:
AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
@@ -2045,7 +2041,7 @@ public:
virtual bool same(const AstNode*) const override { return true; }
};
class AstNodeQuadop : public AstNodeMath {
class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath {
// Quaternary math
public:
AstNodeQuadop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs)
@@ -2082,7 +2078,7 @@ public:
virtual bool same(const AstNode*) const override { return true; }
};
class AstNodeBiCom : public AstNodeBiop {
class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop {
// Binary math with commutative properties
public:
AstNodeBiCom(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
@@ -2090,14 +2086,14 @@ public:
ASTNODE_BASE_FUNCS(NodeBiCom)
};
class AstNodeBiComAsv : public AstNodeBiCom {
class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom {
// Binary math with commutative & associative properties
public:
AstNodeBiComAsv(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiCom{t, fl, lhs, rhs} {}
ASTNODE_BASE_FUNCS(NodeBiComAsv)
};
class AstNodeCond : public AstNodeTriop {
class AstNodeCond VL_NOT_FINAL : public AstNodeTriop {
public:
AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop{t, fl, condp, expr1p, expr2p} {
@@ -2128,7 +2124,7 @@ public:
virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0;
};
class AstNodeBlock : public AstNode {
class AstNodeBlock VL_NOT_FINAL : public AstNode {
// A Begin/fork block
// Parents: statement
// Children: statements
@@ -2152,7 +2148,7 @@ public:
bool unnamed() const { return m_unnamed; }
};
class AstNodePreSel : public AstNode {
class AstNodePreSel VL_NOT_FINAL : public AstNode {
// Something that becomes an AstSel
public:
AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
@@ -2176,7 +2172,7 @@ public:
virtual bool same(const AstNode*) const override { return true; }
};
class AstNodeProcedure : public AstNode {
class AstNodeProcedure VL_NOT_FINAL : public AstNode {
// IEEE procedure: initial, final, always
public:
AstNodeProcedure(AstType t, FileLine* fl, AstNode* bodysp)
@@ -2191,7 +2187,7 @@ public:
bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); }
};
class AstNodeStmt : public AstNode {
class AstNodeStmt VL_NOT_FINAL : public AstNode {
// Statement -- anything that's directly under a function
bool m_statement; // Really a statement (e.g. not a function with return)
public:
@@ -2209,7 +2205,7 @@ public:
virtual void dump(std::ostream& str = std::cout) const override;
};
class AstNodeAssign : public AstNodeStmt {
class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt {
public:
AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt{t, fl} {
@@ -2234,7 +2230,7 @@ public:
virtual bool brokeLhsMustBeLvalue() const = 0;
};
class AstNodeFor : public AstNodeStmt {
class AstNodeFor VL_NOT_FINAL : public AstNodeStmt {
public:
AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp,
AstNode* bodysp)
@@ -2255,7 +2251,7 @@ public:
virtual bool same(const AstNode* samep) const override { return true; }
};
class AstNodeIf : public AstNodeStmt {
class AstNodeIf VL_NOT_FINAL : public AstNodeStmt {
private:
VBranchPred m_branchPred; // Branch prediction as taken/untaken?
public:
@@ -2281,7 +2277,7 @@ public:
VBranchPred branchPred() const { return m_branchPred; }
};
class AstNodeCase : public AstNodeStmt {
class AstNodeCase VL_NOT_FINAL : public AstNodeStmt {
public:
AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp)
: AstNodeStmt{t, fl} {
@@ -2299,15 +2295,16 @@ public:
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
};
class AstNodeVarRef : public AstNodeMath {
class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath {
// An AstVarRef or AstVarXRef
private:
VAccess m_access; // Left hand side assignment
AstVar* m_varp; // [AfterLink] Pointer to variable itself
AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy
AstNodeModule* m_packagep = nullptr; // Package hierarchy
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
string m_name; // Name of variable
string m_hiername; // Scope converted into name-> for emitting
string m_hiernameToProt; // Scope converted into name-> for emitting
string m_hiernameToUnprot; // Scope converted into name-> for emitting
bool m_hierThis = false; // Hiername points to "this" function
public:
@@ -2338,20 +2335,22 @@ public:
void varp(AstVar* varp);
AstVarScope* varScopep() const { return m_varScopep; }
void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
string hiername() const { return m_hiername; }
string hiernameToProt() const { return m_hiernameToProt; }
void hiernameToProt(const string& hn) { m_hiernameToProt = hn; }
string hiernameToUnprot() const { return m_hiernameToUnprot; }
void hiernameToUnprot(const string& hn) { m_hiernameToUnprot = hn; }
string hiernameProtect() const;
void hiername(const string& hn) { m_hiername = hn; }
bool hierThis() const { return m_hierThis; }
void hierThis(bool flag) { m_hierThis = flag; }
AstNodeModule* packagep() const { return m_packagep; }
void packagep(AstNodeModule* nodep) { m_packagep = nodep; }
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
// Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v) {}
};
class AstNodeText : public AstNode {
class AstNodeText VL_NOT_FINAL : public AstNode {
private:
string m_text;
@@ -2371,7 +2370,7 @@ public:
const string& text() const { return m_text; }
};
class AstNodeDType : public AstNode {
class AstNodeDType VL_NOT_FINAL : public AstNode {
// Ideally width() would migrate to BasicDType as that's where it makes sense,
// but it's currently so prevalent in the code we leave it here.
// Note the below members are included in AstTypeTable::Key lookups
@@ -2467,7 +2466,7 @@ private:
CTypeRecursed cTypeRecurse(bool compound) const;
};
class AstNodeUOrStructDType : public AstNodeDType {
class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType {
// A struct or union; common handling
private:
// TYPES
@@ -2531,7 +2530,7 @@ public:
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
};
class AstNodeArrayDType : public AstNodeDType {
class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds)
@@ -2594,7 +2593,7 @@ public:
VNumRange declRange() const;
};
class AstNodeSel : public AstNodeBiop {
class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
// Single bit range extraction, perhaps with non-constant selection or array selection
public:
AstNodeSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* bitp)
@@ -2610,7 +2609,7 @@ public:
virtual bool hasDType() const override { return true; }
};
class AstNodeStream : public AstNodeBiop {
class AstNodeStream VL_NOT_FINAL : public AstNodeBiop {
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
public:
AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
@@ -2623,11 +2622,12 @@ public:
//######################################################################
// Tasks/functions common handling
class AstNodeCCall : public AstNodeStmt {
class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt {
// A call of a C++ function, perhaps a AstCFunc or perhaps globally named
// Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal.
AstCFunc* m_funcp;
string m_hiername;
string m_hiernameToProt;
string m_hiernameToUnprot;
string m_argTypes;
public:
@@ -2641,7 +2641,8 @@ public:
AstNodeCCall(AstType t, AstNodeCCall* oldp, AstCFunc* funcp)
: AstNodeStmt{t, oldp->fileline(), true}
, m_funcp{funcp} {
m_hiername = oldp->hiername();
m_hiernameToProt = oldp->hiernameToProt();
m_hiernameToUnprot = oldp->hiernameToUnprot();
m_argTypes = oldp->argTypes();
if (oldp->argsp()) addNOp2p(oldp->argsp()->unlinkFrBackWithNext());
}
@@ -2661,8 +2662,10 @@ public:
virtual bool isPure() const override;
virtual bool isOutputter() const override { return !isPure(); }
AstCFunc* funcp() const { return m_funcp; }
string hiername() const { return m_hiername; }
void hiername(const string& hn) { m_hiername = hn; }
string hiernameToProt() const { return m_hiernameToProt; }
void hiernameToProt(const string& hn) { m_hiernameToProt = hn; }
string hiernameToUnprot() const { return m_hiernameToUnprot; }
void hiernameToUnprot(const string& hn) { m_hiernameToUnprot = hn; }
string hiernameProtect() const;
void argTypes(const string& str) { m_argTypes = str; }
string argTypes() const { return m_argTypes; }
@@ -2671,7 +2674,7 @@ public:
void addArgsp(AstNode* nodep) { addOp2p(nodep); }
};
class AstNodeFTask : public AstNode {
class AstNodeFTask VL_NOT_FINAL : public AstNode {
private:
string m_name; // Name of task
string m_cname; // Name of task if DPI import
@@ -2688,6 +2691,8 @@ private:
bool m_dpiOpenChild : 1; // DPI import open array child wrapper
bool m_dpiTask : 1; // DPI import task (vs. void function)
bool m_isConstructor : 1; // Class constructor
bool m_isHideLocal : 1; // Verilog local
bool m_isHideProtected : 1; // Verilog protected
bool m_pure : 1; // DPI import pure (vs. virtual pure)
bool m_pureVirtual : 1; // Pure virtual
bool m_virtual : 1; // Virtual method in class
@@ -2708,6 +2713,8 @@ public:
, m_dpiOpenChild{false}
, m_dpiTask{false}
, m_isConstructor{false}
, m_isHideLocal{false}
, m_isHideProtected{false}
, m_pure{false}
, m_pureVirtual{false}
, m_virtual{false} {
@@ -2730,8 +2737,8 @@ public:
void addFvarp(AstNode* nodep) { addNOp1p(nodep); }
bool isFunction() const { return fvarp() != nullptr; }
// op2 = Class/package scope
AstNode* packagep() const { return op2p(); }
void packagep(AstNode* nodep) { setNOp2p(nodep); }
AstNode* classOrPackagep() const { return op2p(); }
void classOrPackagep(AstNode* nodep) { setNOp2p(nodep); }
// op3 = Statements/Ports/Vars
AstNode* stmtsp() const { return op3p(); } // op3 = List of statements
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
@@ -2766,6 +2773,10 @@ public:
bool dpiTask() const { return m_dpiTask; }
void isConstructor(bool flag) { m_isConstructor = flag; }
bool isConstructor() const { return m_isConstructor; }
bool isHideLocal() const { return m_isHideLocal; }
void isHideLocal(bool flag) { m_isHideLocal = flag; }
bool isHideProtected() const { return m_isHideProtected; }
void isHideProtected(bool flag) { m_isHideProtected = flag; }
void pure(bool flag) { m_pure = flag; }
bool pure() const { return m_pure; }
void pureVirtual(bool flag) { m_pureVirtual = flag; }
@@ -2776,12 +2787,12 @@ public:
VLifetime lifetime() const { return m_lifetime; }
};
class AstNodeFTaskRef : public AstNodeStmt {
class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt {
// A reference to a task (or function)
// Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal.
private:
AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced
AstNodeModule* m_packagep = nullptr; // Package hierarchy
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
string m_name; // Name of variable
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
@@ -2815,8 +2826,8 @@ public:
void taskp(AstNodeFTask* taskp) { m_taskp = taskp; }
virtual void name(const string& name) override { m_name = name; }
void dotted(const string& name) { m_dotted = name; }
AstNodeModule* packagep() const { return m_packagep; }
void packagep(AstNodeModule* nodep) { m_packagep = nodep; }
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
bool pli() const { return m_pli; }
void pli(bool flag) { m_pli = flag; }
// op1 = namep
@@ -2830,7 +2841,7 @@ public:
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
};
class AstNodeModule : public AstNode {
class AstNodeModule VL_NOT_FINAL : public AstNode {
// A module, package, program or interface declaration;
// something that can live directly under the TOP,
// excluding $unit package stuff
@@ -2909,7 +2920,7 @@ public:
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
};
class AstNodeRange : public AstNode {
class AstNodeRange VL_NOT_FINAL : public AstNode {
// A range, sized or unsized
public:
AstNodeRange(AstType t, FileLine* fl)
@@ -3001,7 +3012,7 @@ inline VNumRange AstNodeArrayDType::declRange() const {
inline const char* AstNodeFTaskRef::broken() const {
BROKEN_RTN(m_taskp && !m_taskp->brokeExists());
BROKEN_RTN(m_packagep && !m_packagep->brokeExists());
BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
return nullptr;
}
+125 -44
View File
@@ -54,7 +54,7 @@ void AstNodeVarRef::cloneRelink() {
}
string AstNodeVarRef::hiernameProtect() const {
return VIdProtect::protectWordsIf(hiername(), protect());
return hiernameToUnprot() + VIdProtect::protectWordsIf(hiernameToProt(), protect());
}
int AstNodeSel::bitConst() const {
@@ -107,7 +107,7 @@ const char* AstNodeCCall::broken() const {
}
bool AstNodeCCall::isPure() const { return funcp()->pure(); }
string AstNodeCCall::hiernameProtect() const {
return VIdProtect::protectWordsIf(hiername(), protect());
return hiernameToUnprot() + VIdProtect::protectWordsIf(hiernameToProt(), protect());
}
void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
@@ -455,38 +455,99 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
return arg;
}
string AstVar::dpiArgType(bool named, bool forReturn) const {
if (forReturn) named = false;
string arg;
if (isDpiOpenArray()) {
arg = "const svOpenArrayHandle";
} else if (!basicp()) {
arg = "UNKNOWN";
} else if (basicp()->isDpiBitVec()) {
if (forReturn) {
arg = "svBitVecVal";
} else if (isReadOnly()) {
arg = "const svBitVecVal*";
} else {
arg = "svBitVecVal*";
}
} else if (basicp()->isDpiLogicVec()) {
if (forReturn) {
arg = "svLogicVecVal";
} else if (isReadOnly()) {
arg = "const svLogicVecVal*";
} else {
arg = "svLogicVecVal*";
}
} else {
arg = basicp()->keyword().dpiType();
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
arg = "unsigned " + arg;
}
if (!forReturn && isWritable()) arg += "*";
class dpiTypesToStringConverter VL_NOT_FINAL {
public:
virtual string openArray(const AstVar*) const { return "const svOpenArrayHandle"; }
virtual string bitLogicVector(const AstVar* varp, bool isBit) const {
return isBit ? "svBitVecVal" : "svLogicVecVal";
}
if (named) arg += " " + name();
return arg;
virtual string primitive(const AstVar* varp) const {
string type;
if (varp->basicp()->keyword().isDpiUnsignable() && !varp->basicp()->isSigned()) {
type = "unsigned ";
}
type += varp->basicp()->keyword().dpiType();
return type;
}
string convert(const AstVar* varp) const {
if (varp->isDpiOpenArray()) {
return openArray(varp);
} else if (!varp->basicp()) {
return "UNKNOWN";
} else if (varp->basicp()->isDpiBitVec() || varp->basicp()->isDpiLogicVec()) {
return bitLogicVector(varp, varp->basicp()->isDpiBitVec());
} else {
return primitive(varp);
}
}
};
string AstVar::dpiArgType(bool named, bool forReturn) const {
if (forReturn) {
return dpiTypesToStringConverter{}.convert(this);
} else {
class converter final : public dpiTypesToStringConverter {
virtual string bitLogicVector(const AstVar* varp, bool isBit) const override {
return string(varp->isReadOnly() ? "const " : "")
+ dpiTypesToStringConverter::bitLogicVector(varp, isBit) + '*';
}
virtual string primitive(const AstVar* varp) const override {
string type = dpiTypesToStringConverter::primitive(varp);
if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
if (!varp->isWritable()
&& varp->basicp()->keyword() != AstBasicDTypeKwd::STRING)
type = "const " + type;
type += "*";
}
return type;
}
};
string arg = converter{}.convert(this);
if (named) arg += " " + name();
return arg;
}
}
string AstVar::dpiTmpVarType(const string& varName) const {
class converter final : public dpiTypesToStringConverter {
string m_name;
string arraySuffix(const AstVar* varp, size_t n) const {
if (AstUnpackArrayDType* unpackp
= VN_CAST(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
// Convert multi dimensional unpacked array to 1D array
if (n == 0) n = 1;
n *= unpackp->arrayUnpackedElements();
return '[' + cvtToStr(n) + ']';
} else if (n > 0) {
return '[' + cvtToStr(n) + ']';
} else {
return "";
}
}
virtual string openArray(const AstVar* varp) const override {
return dpiTypesToStringConverter::openArray(varp) + ' ' + m_name
+ arraySuffix(varp, 0);
}
virtual string bitLogicVector(const AstVar* varp, bool isBit) const override {
string type = dpiTypesToStringConverter::bitLogicVector(varp, isBit);
type += ' ' + m_name + arraySuffix(varp, varp->widthWords());
return type;
}
virtual string primitive(const AstVar* varp) const override {
string type = dpiTypesToStringConverter::primitive(varp);
if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
if (!varp->isWritable() && varp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE)
type = "const " + type;
}
type += ' ' + m_name + arraySuffix(varp, 0);
return type;
}
public:
explicit converter(const string& name)
: m_name(name) {}
};
return converter{varName}.convert(this);
}
string AstVar::scType() const {
@@ -553,7 +614,7 @@ string AstVar::mtasksString() const {
return os.str();
}
class AstNodeDType::CTypeRecursed {
class AstNodeDType::CTypeRecursed final {
public:
string m_type; // The base type, e.g.: "Foo_t"s
string m_dims; // Array dimensions, e.g.: "[3][2][1]"
@@ -610,8 +671,6 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const {
info.m_type = "const VerilatedScope*";
} else if (bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) {
info.m_type = "double";
} else if (bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) {
info.m_type = "float";
} else if (bdtypep->keyword() == AstBasicDTypeKwd::STRING) {
info.m_type = "std::string";
} else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width
@@ -1112,6 +1171,13 @@ void AstClass::repairCache() {
clearCache();
for (AstNode* itemp = membersp(); itemp; itemp = itemp->nextp()) { insertCache(itemp); }
}
bool AstClass::isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp) {
// TAIL RECURSIVE
if (!refClassp || !baseClassp) return false;
if (refClassp == baseClassp) return true;
if (!refClassp->extendsp()) return false;
return isClassExtendedFrom(refClassp->extendsp()->classp(), baseClassp);
}
void AstClass::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isExtended()) str << " [EXT]";
@@ -1119,6 +1185,9 @@ void AstClass::dump(std::ostream& str) const {
}
AstClass* AstClassExtends::classp() const {
AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType);
if (VL_UNLIKELY(!refp)) { // LinkDot uses this for 'super.'
refp = VN_CAST(childDTypep(), ClassRefDType);
}
UASSERT_OBJ(refp, this, "class extends non-ref");
return refp->classp();
}
@@ -1347,6 +1416,18 @@ string AstUnpackArrayDType::prettyDTypeName() const {
os << subp->prettyDTypeName() << "$" << ranges;
return os.str();
}
std::vector<AstUnpackArrayDType*> AstUnpackArrayDType::unpackDimensions() {
std::vector<AstUnpackArrayDType*> dims;
for (AstUnpackArrayDType* unpackp = this; unpackp;) {
dims.push_back(unpackp);
if (AstNodeDType* subp = unpackp->subDTypep()) {
unpackp = VN_CAST(subp, UnpackArrayDType);
} else {
unpackp = nullptr;
}
}
return dims;
}
void AstNetlist::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " [" << timeunit() << "/" << timeprecision() << "]";
@@ -1397,7 +1478,7 @@ void AstTypeTable::dump(std::ostream& str) const {
this->AstNode::dump(str);
for (int i = 0; i < static_cast<int>(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
if (AstBasicDType* subnodep = m_basicps[i]) {
str << endl; // Newline from caller, so newline first
str << '\n'; // Newline from caller, so newline first
str << "\t\t" << std::setw(8) << AstBasicDTypeKwd(i).ascii();
str << " -> ";
subnodep->dump(str);
@@ -1407,7 +1488,7 @@ void AstTypeTable::dump(std::ostream& str) const {
const DetailedMap& mapr = m_detailedMap;
for (const auto& itr : mapr) {
AstBasicDType* dtypep = itr.second;
str << endl; // Newline from caller, so newline first
str << '\n'; // Newline from caller, so newline first
str << "\t\tdetailed -> ";
dtypep->dump(str);
}
@@ -1453,11 +1534,13 @@ void AstVarScope::dump(std::ostream& str) const {
str << " ->UNLINKED";
}
}
void AstNodeVarRef::dump(std::ostream& str) const { this->AstNodeMath::dump(str); }
void AstNodeVarRef::dump(std::ostream& str) const {
this->AstNodeMath::dump(str);
if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep());
str << " " << access().arrow() << " ";
}
void AstVarXRef::dump(std::ostream& str) const {
this->AstNodeVarRef::dump(str);
if (packagep()) str << " pkg=" << nodeAddr(packagep());
str << " " << access().arrow() << " ";
str << ".=" << dotted() << " ";
if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - ";
if (varScopep()) {
@@ -1470,8 +1553,6 @@ void AstVarXRef::dump(std::ostream& str) const {
}
void AstVarRef::dump(std::ostream& str) const {
this->AstNodeVarRef::dump(str);
if (packagep()) str << " pkg=" << nodeAddr(packagep());
str << " " << access().arrow() << " ";
if (varScopep()) {
varScopep()->dump(str);
} else if (varp()) {
@@ -1547,7 +1628,7 @@ void AstActive::dump(std::ostream& str) const {
}
void AstNodeFTaskRef::dump(std::ostream& str) const {
this->AstNodeStmt::dump(str);
if (packagep()) { str << " pkg=" << nodeAddr(packagep()); }
if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep());
str << " -> ";
if (dotted() != "") { str << ".=" << dotted() << " "; }
if (taskp()) {
+539 -478
View File
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -36,7 +36,7 @@
//######################################################################
class BeginState {
class BeginState final {
private:
// NODE STATE
// Entire netlist:
@@ -45,8 +45,8 @@ private:
bool m_anyFuncInBegin = false;
public:
BeginState() {}
~BeginState() {}
BeginState() = default;
~BeginState() = default;
void userMarkChanged(AstNode* nodep) {
nodep->user1(true);
m_anyFuncInBegin = true;
@@ -56,7 +56,7 @@ public:
//######################################################################
class BeginVisitor : public AstNVisitor {
class BeginVisitor final : public AstNVisitor {
private:
// STATE
BeginState* m_statep; // Current global state
@@ -242,12 +242,12 @@ public:
: m_statep{statep} {
iterate(nodep);
}
virtual ~BeginVisitor() override {}
virtual ~BeginVisitor() override = default;
};
//######################################################################
class BeginRelinkVisitor : public AstNVisitor {
class BeginRelinkVisitor final : public AstNVisitor {
// Replace tasks with new pointer
private:
// NODE STATE
@@ -283,7 +283,7 @@ private:
public:
// CONSTRUCTORS
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) { iterate(nodep); }
virtual ~BeginRelinkVisitor() override {}
virtual ~BeginRelinkVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Begin {
class V3Begin final {
public:
static void debeginAll(AstNetlist* nodep);
};
+2 -2
View File
@@ -35,7 +35,7 @@
//######################################################################
// Branch state, as a visitor of each AstNode
class BranchVisitor : public AstNVisitor {
class BranchVisitor final : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
@@ -118,7 +118,7 @@ public:
iterateChildren(nodep);
calc_tasks();
}
virtual ~BranchVisitor() override {}
virtual ~BranchVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Branch {
class V3Branch final {
public:
// CONSTRUCTORS
static void branchAll(AstNetlist* nodep);
+25 -7
View File
@@ -36,7 +36,7 @@
//######################################################################
class BrokenTable : public AstNVisitor {
class BrokenTable VL_NOT_FINAL : public AstNVisitor {
// Table of brokenExists node pointers
private:
// MEMBERS
@@ -190,8 +190,8 @@ public:
}
// CONSTRUCTORS
BrokenTable() {}
virtual ~BrokenTable() override {}
BrokenTable() = default;
virtual ~BrokenTable() override = default;
};
BrokenTable::NodeMap BrokenTable::s_nodes;
@@ -211,7 +211,7 @@ bool AstNode::brokeExistsBelow() const {
//######################################################################
class BrokenMarkVisitor : public AstNVisitor {
class BrokenMarkVisitor final : public AstNVisitor {
// Mark every node in the tree
private:
// NODE STATE
@@ -231,13 +231,15 @@ private:
public:
// CONSTRUCTORS
explicit BrokenMarkVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~BrokenMarkVisitor() override {}
virtual ~BrokenMarkVisitor() override = default;
};
//######################################################################
// Broken state, as a visitor of each AstNode
class BrokenCheckVisitor : public AstNVisitor {
class BrokenCheckVisitor final : public AstNVisitor {
bool m_inScope = false; // Under AstScope
private:
static void checkWidthMin(const AstNode* nodep) {
UASSERT_OBJ(nodep->width() == nodep->widthMin()
@@ -278,6 +280,22 @@ private:
&& !VN_CAST(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()),
nodep, "Assignment LHS is not an lvalue");
}
virtual void visit(AstScope* nodep) override {
VL_RESTORER(m_inScope);
{
m_inScope = true;
processAndIterate(nodep);
}
}
virtual void visit(AstNodeVarRef* nodep) override {
processAndIterate(nodep);
// m_inScope because some Vars have initial variable references without scopes
// This might false fire with some debug flags, as not certain we don't have temporary
// clear varScopep's during some an infrequent dump just before we re-LinkDot.
UASSERT_OBJ(
!(v3Global.assertScoped() && m_inScope && nodep->varp() && !nodep->varScopep()), nodep,
"VarRef missing VarScope pointer");
}
virtual void visit(AstNode* nodep) override {
// Process not just iterate
processAndIterate(nodep);
@@ -286,7 +304,7 @@ private:
public:
// CONSTRUCTORS
explicit BrokenCheckVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~BrokenCheckVisitor() override {}
virtual ~BrokenCheckVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Broken {
class V3Broken final {
public:
static void brokenAll(AstNetlist* nodep);
static void addNewed(AstNode* nodep);
+4 -6
View File
@@ -34,7 +34,7 @@
#include <algorithm>
#include <map>
class V3CCtorsVisitor {
class V3CCtorsVisitor final {
private:
string m_basename;
string m_argsp;
@@ -42,8 +42,8 @@ private:
AstNodeModule* m_modp; // Current module
AstCFunc* m_tlFuncp; // Top level function being built
AstCFunc* m_funcp; // Current function
int m_numStmts; // Number of statements output
int m_funcNum; // Function number being built
int m_numStmts = 0; // Number of statements output
int m_funcNum = 0; // Function number being built
public:
void add(AstNode* nodep) {
@@ -76,8 +76,6 @@ public:
m_argsp = argsp;
m_callargsp = callargsp;
m_modp = nodep;
m_numStmts = 0;
m_funcNum = 0;
m_tlFuncp = new AstCFunc(nodep->fileline(), basename, nullptr, "void");
m_tlFuncp->declPrivate(true);
m_tlFuncp->isStatic(false);
@@ -87,7 +85,7 @@ public:
m_funcp = m_tlFuncp;
m_modp->addStmtp(m_tlFuncp);
}
~V3CCtorsVisitor() {}
~V3CCtorsVisitor() = default;
private:
VL_UNCOPYABLE(V3CCtorsVisitor);
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3CCtors {
class V3CCtors final {
public:
static void cctorsAll();
+7 -7
View File
@@ -36,7 +36,7 @@
//######################################################################
class CUseState {
class CUseState final {
private:
// MEMBERS
AstNodeModule* m_modInsertp; // Current module to insert AstCUse under
@@ -68,14 +68,14 @@ public:
// CONSTRUCTORS
explicit CUseState(AstNodeModule* nodep)
: m_modInsertp{nodep} {}
virtual ~CUseState() {}
virtual ~CUseState() = default;
VL_UNCOPYABLE(CUseState);
};
// Visit within a module all nodes and data types they reference, finding
// any classes so we can make sure they are defined when Verilated code
// compiles
class CUseDTypeVisitor : public AstNVisitor {
class CUseDTypeVisitor final : public AstNVisitor {
// MEMBERS
CUseState& m_stater; // State for inserter
bool m_impOnly = false; // In details needed only for implementation
@@ -84,7 +84,7 @@ class CUseDTypeVisitor : public AstNVisitor {
if (nodep->user2SetOnce()) return; // Process once
if (!m_impOnly) m_stater.newUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name());
// No class.h, it's inside the class package's h file
m_stater.newUse(nodep, VUseType::IMP_INCLUDE, nodep->classp()->packagep()->name());
m_stater.newUse(nodep, VUseType::IMP_INCLUDE, nodep->classp()->classOrPackagep()->name());
// Need to include extends() when we implement, but no need for pointers to know
VL_RESTORER(m_impOnly);
{
@@ -109,11 +109,11 @@ public:
: m_stater(stater) { // Need () or GCC 4.8 false warning
iterate(nodep);
}
virtual ~CUseDTypeVisitor() override {}
virtual ~CUseDTypeVisitor() override = default;
VL_UNCOPYABLE(CUseDTypeVisitor);
};
class CUseVisitor : public AstNVisitor {
class CUseVisitor final : public AstNVisitor {
// MEMBERS
CUseState m_state; // Inserter state
@@ -219,7 +219,7 @@ public:
: m_state{nodep} {
iterate(nodep);
}
virtual ~CUseVisitor() override {}
virtual ~CUseVisitor() override = default;
VL_UNCOPYABLE(CUseVisitor);
};
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3CUse {
class V3CUse final {
public:
static void cUseAll();
};
+9 -10
View File
@@ -50,7 +50,7 @@
//######################################################################
class CaseLintVisitor : public AstNVisitor {
class CaseLintVisitor final : public AstNVisitor {
private:
AstNodeCase* m_caseExprp
= nullptr; // Under a CASE value node, if so the relevant case statement
@@ -111,13 +111,13 @@ private:
public:
// CONSTRUCTORS
explicit CaseLintVisitor(AstNodeCase* nodep) { iterate(nodep); }
virtual ~CaseLintVisitor() override {}
virtual ~CaseLintVisitor() override = default;
};
//######################################################################
// Case state, as a visitor of each AstNode
class CaseVisitor : public AstNVisitor {
class CaseVisitor final : public AstNVisitor {
private:
// NODE STATE
// Cleared each Case
@@ -133,7 +133,7 @@ private:
int m_caseItems = 0; // Number of caseItem unique values
bool m_caseNoOverlapsAllCovered = false; // Proven to be synopsys parallel_case compliant
// For each possible value, the case branch we need
AstNode* m_valueItem[1 << CASE_OVERLAP_WIDTH];
std::array<AstNode*, 1 << CASE_OVERLAP_WIDTH> m_valueItem;
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@@ -318,7 +318,7 @@ private:
itemp = VN_CAST(itemp->nextp(), CaseItem)) {
if (!itemp->condsp()) {
// Default clause. Just make true, we'll optimize it away later
itemp->condsp(new AstConst(itemp->fileline(), AstConst::LogicTrue()));
itemp->condsp(new AstConst(itemp->fileline(), AstConst::BitTrue()));
hadDefault = true;
} else {
// Expressioned clause
@@ -336,7 +336,7 @@ private:
VL_DANGLING(iconstp);
// For simplicity, make expression that is not equal, and let later
// optimizations remove it
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
condp = new AstConst(itemp->fileline(), AstConst::BitFalse());
} else if (AstInsideRange* irangep = VN_CAST(icondp, InsideRange)) {
// Similar logic in V3Width::visit(AstInside)
condp = irangep->newAndFromInside(cexprp, irangep->lhsp()->unlinkFrBack(),
@@ -375,9 +375,8 @@ private:
if (!hadDefault) {
// If there was no default, add a empty one, this greatly simplifies below code
// and constant propagation will just eliminate it for us later.
nodep->addItemsp(
new AstCaseItem(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::LogicTrue()), nullptr));
nodep->addItemsp(new AstCaseItem(
nodep->fileline(), new AstConst(nodep->fileline(), AstConst::BitTrue()), nullptr));
}
if (debug() >= 9) nodep->dumpTree(cout, " _comp_COND: ");
// Now build the IF statement tree
@@ -419,7 +418,7 @@ private:
VL_DANGLING(ifexprp);
if (depth == CASE_ENCODER_GROUP_DEPTH) { // End of group - can skip the condition
VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp);
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
itemexprp = new AstConst(itemp->fileline(), AstConst::BitTrue());
}
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, nullptr);
if (itemnextp) {
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Case {
class V3Case final {
public:
static void caseAll(AstNetlist* nodep);
static void caseLint(AstNodeCase* nodep);
+2 -2
View File
@@ -49,7 +49,7 @@
//######################################################################
// Cast state, as a visitor of each AstNode
class CastVisitor : public AstNVisitor {
class CastVisitor final : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
@@ -193,7 +193,7 @@ private:
public:
// CONSTRUCTORS
explicit CastVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~CastVisitor() override {}
virtual ~CastVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Cast {
class V3Cast final {
public:
static void castAll(AstNetlist* nodep);
};
+19 -19
View File
@@ -41,7 +41,7 @@ constexpr int CDC_WEIGHT_ASYNC = 0x1000; // Weight for edges that feed async lo
//######################################################################
class CdcBaseVisitor : public AstNVisitor {
class CdcBaseVisitor VL_NOT_FINAL : public AstNVisitor {
public:
VL_DEBUG_FUNC; // Declare debug()
};
@@ -49,7 +49,7 @@ public:
//######################################################################
// Graph support classes
class CdcEitherVertex : public V3GraphVertex {
class CdcEitherVertex VL_NOT_FINAL : public V3GraphVertex {
AstScope* m_scopep;
AstNode* m_nodep;
AstSenTree* m_srcDomainp = nullptr;
@@ -66,7 +66,7 @@ public:
, m_srcDomainSet{false}
, m_dstDomainSet{false}
, m_asyncPath{false} {}
virtual ~CdcEitherVertex() override {}
virtual ~CdcEitherVertex() override = default;
// ACCESSORS
virtual FileLine* fileline() const override { return nodep()->fileline(); }
AstScope* scopep() const { return m_scopep; }
@@ -83,7 +83,7 @@ public:
void asyncPath(bool flag) { m_asyncPath = flag; }
};
class CdcVarVertex : public CdcEitherVertex {
class CdcVarVertex final : public CdcEitherVertex {
AstVarScope* m_varScp;
int m_cntAsyncRst = 0;
bool m_fromFlop = false;
@@ -92,7 +92,7 @@ public:
CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: CdcEitherVertex{graphp, scopep, varScp}
, m_varScp{varScp} {}
virtual ~CdcVarVertex() override {}
virtual ~CdcVarVertex() override = default;
// ACCESSORS
AstVarScope* varScp() const { return m_varScp; }
virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
@@ -105,7 +105,7 @@ public:
void fromFlop(bool flag) { m_fromFlop = flag; }
};
class CdcLogicVertex : public CdcEitherVertex {
class CdcLogicVertex final : public CdcEitherVertex {
bool m_hazard : 1;
bool m_isFlop : 1;
@@ -117,7 +117,7 @@ public:
srcDomainp(sensenodep);
dstDomainp(sensenodep);
}
virtual ~CdcLogicVertex() override {}
virtual ~CdcLogicVertex() override = default;
// ACCESSORS
virtual string name() const override {
return (cvtToHex(nodep()) + "@" + scopep()->prettyName());
@@ -135,7 +135,7 @@ public:
//######################################################################
class CdcDumpVisitor : public CdcBaseVisitor {
class CdcDumpVisitor final : public CdcBaseVisitor {
private:
// NODE STATE
// Entire netlist:
@@ -150,7 +150,7 @@ private:
} else {
*m_ofp << " ";
}
*m_ofp << nodep->prettyTypeName() << " " << endl;
*m_ofp << nodep->prettyTypeName() << "\n";
string lastPrefix = m_prefix;
m_prefix = lastPrefix + "1:";
iterateAndNextNull(nodep->op1p());
@@ -170,12 +170,12 @@ public:
, m_prefix{prefix} {
iterate(nodep);
}
virtual ~CdcDumpVisitor() override {}
virtual ~CdcDumpVisitor() override = default;
};
//######################################################################
class CdcWidthVisitor : public CdcBaseVisitor {
class CdcWidthVisitor final : public CdcBaseVisitor {
private:
int m_maxLineno = 0;
size_t m_maxFilenameLen = 0;
@@ -194,7 +194,7 @@ private:
public:
// CONSTRUCTORS
explicit CdcWidthVisitor(AstNode* nodep) { iterate(nodep); }
virtual ~CdcWidthVisitor() override {}
virtual ~CdcWidthVisitor() override = default;
// ACCESSORS
int maxWidth() const {
size_t width = 1;
@@ -209,7 +209,7 @@ public:
//######################################################################
// Cdc class functions
class CdcVisitor : public CdcBaseVisitor {
class CdcVisitor final : public CdcBaseVisitor {
private:
// NODE STATE
// Entire netlist:
@@ -292,7 +292,7 @@ private:
told_file = true;
std::cerr << V3Error::msgPrefix() << " See details in " << m_ofFilename << endl;
}
*m_ofp << "%Warning-" << code.ascii() << ": " << nodep->fileline() << " " << msg << endl;
*m_ofp << "%Warning-" << code.ascii() << ": " << nodep->fileline() << " " << msg << '\n';
}
void setNodeHazard(AstNode* nodep) {
@@ -462,7 +462,7 @@ private:
string front
= pad(filelineWidth(), nodep->fileline()->ascii() + ":") + " " + prefix + " +- ";
if (VN_IS(nodep, VarScope)) {
*m_ofp << front << "Variable: " << nodep->prettyName() << endl;
*m_ofp << front << "Variable: " << nodep->prettyName() << '\n';
} else {
V3EmitV::verilogPrefixedTree(nodep, *m_ofp, prefix + " +- ", filelineWidth(),
vertexp->srcDomainp(), true);
@@ -509,7 +509,7 @@ private:
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__cdc_edges.txt";
const std::unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
if (ofp->fail()) v3fatal("Can't write " << filename);
*ofp << "Edge Report for " << v3Global.opt.prefix() << endl;
*ofp << "Edge Report for " << v3Global.opt.prefix() << '\n';
std::deque<string> report; // Sort output by name
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
@@ -536,7 +536,7 @@ private:
V3EmitV::verilogForTree(vvertexp->dstDomainp(), os);
}
os << std::setw(0);
os << endl;
os << '\n';
report.push_back(os.str());
}
}
@@ -732,7 +732,7 @@ public:
m_ofp = V3File::new_ofstream(filename);
if (m_ofp->fail()) v3fatal("Can't write " << filename);
m_ofFilename = filename;
*m_ofp << "CDC Report for " << v3Global.opt.prefix() << endl;
*m_ofp << "CDC Report for " << v3Global.opt.prefix() << '\n';
*m_ofp
<< "Each dump below traces logic from inputs/source flops to destination flop(s).\n";
*m_ofp << "First source logic is listed, then a variable that logic generates,\n";
@@ -745,7 +745,7 @@ public:
if (false) {
*m_ofp << "\nDBG-test-dumper\n";
V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ", 40, nullptr, true);
*m_ofp << endl;
*m_ofp << '\n';
}
}
virtual ~CdcVisitor() override {
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Cdc {
class V3Cdc final {
public:
static void cdcAll(AstNetlist* nodep);
};
+9 -10
View File
@@ -38,7 +38,7 @@
//######################################################################
class ChangedState {
class ChangedState final {
public:
// STATE
AstNodeModule* m_topModp = nullptr; // Top module
@@ -48,8 +48,8 @@ public:
int m_numStmts = 0; // Number of statements added to m_chgFuncp
int m_funcNum = 0; // Number of change functions emitted
ChangedState() {}
~ChangedState() {}
ChangedState() = default;
~ChangedState() = default;
void maybeCreateChgFuncp() {
// Don't create an extra function call if splitting is disabled
@@ -94,7 +94,7 @@ public:
//######################################################################
// Utility visitor to find elements to be compared
class ChangedInsertVisitor : public AstNVisitor {
class ChangedInsertVisitor final : public AstNVisitor {
private:
// STATE
ChangedState* m_statep; // Shared state across visitors
@@ -117,10 +117,9 @@ private:
"Unsupported: Can't detect more than "
<< cvtToStr(DETECTARRAY_MAX_INDEXES)
<< " array indexes (probably with UNOPTFLAT warning suppressed): "
<< m_vscp->prettyName() << endl
<< m_vscp->prettyName() << '\n'
<< m_vscp->warnMore()
<< "... Could recompile with DETECTARRAY_MAX_INDEXES increased"
<< endl);
<< "... Could recompile with DETECTARRAY_MAX_INDEXES increased");
return;
}
m_statep->maybeCreateChgFuncp();
@@ -208,14 +207,14 @@ public:
m_newLvEqnp->deleteTree();
m_newRvEqnp->deleteTree();
}
virtual ~ChangedInsertVisitor() override {}
virtual ~ChangedInsertVisitor() override = default;
VL_UNCOPYABLE(ChangedInsertVisitor);
};
//######################################################################
// Changed state, as a visitor of each AstNode
class ChangedVisitor : public AstNVisitor {
class ChangedVisitor final : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
@@ -280,7 +279,7 @@ public:
: m_statep{statep} {
iterate(nodep);
}
virtual ~ChangedVisitor() override {}
virtual ~ChangedVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Changed {
class V3Changed final {
public:
static void changedAll(AstNetlist* nodep);
};
+6 -5
View File
@@ -29,7 +29,7 @@
//######################################################################
class ClassVisitor : public AstNVisitor {
class ClassVisitor final : public AstNVisitor {
private:
// MEMBERS
AstUser1InUse m_inuser1;
@@ -56,7 +56,7 @@ private:
// Note origName is the same as the class origName so errors look correct
AstClassPackage* packagep = new AstClassPackage(nodep->fileline(), nodep->origName());
packagep->name(nodep->name() + "__Vclpkg");
nodep->packagep(packagep);
nodep->classOrPackagep(packagep);
packagep->classp(nodep);
v3Global.rootp()->addModulep(packagep);
// Add package to hierarchy
@@ -87,7 +87,8 @@ private:
iterateChildren(nodep);
}
}
virtual void visit(AstPackage* nodep) override {
virtual void visit(AstNodeModule* nodep) override {
// Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule)
VL_RESTORER(m_prefix);
{
m_prefix = nodep->name() + "__03a__03a"; // ::
@@ -99,7 +100,7 @@ private:
iterateChildren(nodep);
// Don't move now, or wouldn't keep interating the class
// TODO move class statics too
if (m_ftaskp && m_ftaskp->lifetime().isStatic()) {
if (m_packageScopep && m_ftaskp && m_ftaskp->lifetime().isStatic()) {
m_moves.push_back(make_pair(nodep, m_packageScopep));
}
}
@@ -114,7 +115,7 @@ private:
{
m_ftaskp = nodep;
iterateChildren(nodep);
if (nodep->lifetime().isStatic()) {
if (m_packageScopep && nodep->lifetime().isStatic()) {
m_moves.push_back(make_pair(nodep, m_packageScopep));
}
}
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Class {
class V3Class final {
public:
static void classAll(AstNetlist* nodep);
};
+2 -2
View File
@@ -35,7 +35,7 @@
//######################################################################
// Clean state, as a visitor of each AstNode
class CleanVisitor : public AstNVisitor {
class CleanVisitor final : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
@@ -305,7 +305,7 @@ private:
public:
// CONSTRUCTORS
explicit CleanVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~CleanVisitor() override {}
virtual ~CleanVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Clean {
class V3Clean final {
public:
static void cleanAll(AstNetlist* nodep);
};
+12 -12
View File
@@ -40,7 +40,7 @@
//######################################################################
// Clock state, as a visitor of each AstNode
class ClockVisitor : public AstNVisitor {
class ClockVisitor final : public AstNVisitor {
private:
// NODE STATE
// Cleared each Module:
@@ -293,7 +293,7 @@ private:
}
m_scopep = nullptr;
}
virtual void visit(AstAlways* nodep) override {
virtual void visit(AstNodeProcedure* nodep) override {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) {
@@ -311,6 +311,15 @@ private:
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstAlwaysPostponed* nodep) override {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) {
stmtsp->unlinkFrBackWithNext();
cmtp->addNextHere(stmtsp);
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstCoverToggle* nodep) override {
// nodep->dumpTree(cout, "ct:");
// COVERTOGGLE(INC, ORIG, CHANGE) ->
@@ -328,15 +337,6 @@ private:
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstInitial* nodep) override {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) {
stmtsp->unlinkFrBackWithNext();
cmtp->addNextHere(stmtsp);
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstCFunc* nodep) override {
iterateChildren(nodep);
// Link to global function
@@ -454,7 +454,7 @@ public:
// easily without iterating through the tree.
nodep->evalp(m_evalFuncp);
}
virtual ~ClockVisitor() override {}
virtual ~ClockVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Clock {
class V3Clock final {
public:
static void clockAll(AstNetlist* nodep);
};
+8 -8
View File
@@ -51,19 +51,19 @@ constexpr int COMBINE_MIN_STATEMENTS = 50; // Min # of statements to be worth m
//######################################################################
class CombBaseVisitor : public AstNVisitor {
class CombBaseVisitor VL_NOT_FINAL : public AstNVisitor {
protected:
// STATE
// METHODS
virtual ~CombBaseVisitor() override {}
virtual ~CombBaseVisitor() override = default;
VL_DEBUG_FUNC; // Declare debug()
};
//######################################################################
// Combine replacement function
class CombCallVisitor : CombBaseVisitor {
class CombCallVisitor final : CombBaseVisitor {
// Find all CCALLS of each CFUNC, so that we can later rename them
private:
// NODE STATE
@@ -131,15 +131,15 @@ private:
public:
// CONSTRUCTORS
CombCallVisitor() {}
virtual ~CombCallVisitor() override {}
CombCallVisitor() = default;
virtual ~CombCallVisitor() override = default;
void main(AstNetlist* nodep) { iterate(nodep); }
};
//######################################################################
// Combine marking function
class CombMarkVisitor : CombBaseVisitor {
class CombMarkVisitor final : CombBaseVisitor {
// Mark all nodes under specified one.
private:
// OUTPUT:
@@ -153,13 +153,13 @@ private:
public:
// CONSTRUCTORS
explicit CombMarkVisitor(AstNode* nodep) { iterate(nodep); }
virtual ~CombMarkVisitor() override {}
virtual ~CombMarkVisitor() override = default;
};
//######################################################################
// Combine state, as a visitor of each AstNode
class CombineVisitor : CombBaseVisitor {
class CombineVisitor final : CombBaseVisitor {
private:
// NODE STATE
// Entire netlist:
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Combine {
class V3Combine final {
public:
static void combineAll(AstNetlist* nodep);
};
+20 -21
View File
@@ -38,8 +38,8 @@ template <typename T> class V3ConfigWildcardResolver {
Map m_mapWildcard; // Wildcard strings to entities
Map m_mapResolved; // Resolved strings to converged entities
public:
V3ConfigWildcardResolver() {}
~V3ConfigWildcardResolver() {}
V3ConfigWildcardResolver() = default;
~V3ConfigWildcardResolver() = default;
/// Update into maps from other
void update(const V3ConfigWildcardResolver& other) {
@@ -82,7 +82,7 @@ public:
};
// Only public_flat_rw has the sensitity tree
class V3ConfigVarAttr {
class V3ConfigVarAttr final {
public:
AstAttrType m_type; // Type of attribute
AstSenTree* m_sentreep; // Sensitivity tree for public_flat_rw
@@ -92,7 +92,7 @@ public:
};
// Overload vector with the required update function and to apply all entries
class V3ConfigVar : public std::vector<V3ConfigVarAttr> {
class V3ConfigVar final : public std::vector<V3ConfigVarAttr> {
public:
// Update from other by copying all attributes
void update(const V3ConfigVar& node) {
@@ -116,14 +116,14 @@ typedef V3ConfigWildcardResolver<V3ConfigVar> V3ConfigVarResolver;
//######################################################################
// Function or task: Have variables and properties
class V3ConfigFTask {
class V3ConfigFTask final {
V3ConfigVarResolver m_vars; // Variables in function/task
bool m_isolate = false; // Isolate function return
bool m_noinline = false; // Don't inline function/task
bool m_public = false; // Public function/task
public:
V3ConfigFTask() {}
V3ConfigFTask() = default;
void update(const V3ConfigFTask& f) {
// Don't overwrite true with false
if (f.m_isolate) m_isolate = true;
@@ -153,7 +153,7 @@ typedef V3ConfigWildcardResolver<V3ConfigFTask> V3ConfigFTaskResolver;
//######################################################################
// Modules have tasks, variables, named blocks and properties
class V3ConfigModule {
class V3ConfigModule final {
typedef std::unordered_set<string> StringSet;
typedef std::set<AstPragmaType> PragmaSet;
@@ -165,7 +165,7 @@ class V3ConfigModule {
bool m_inlineValue = false; // The inline value (on/off)
public:
V3ConfigModule() {}
V3ConfigModule() = default;
void update(const V3ConfigModule& m) {
m_tasks.update(m.m_tasks);
@@ -224,7 +224,7 @@ typedef V3ConfigWildcardResolver<V3ConfigModule> V3ConfigModuleResolver;
// - Line attributes: Attributes attached to lines
// lint/coverage/tracing on/off
class V3ConfigIgnoresLine {
class V3ConfigIgnoresLine final {
public:
int m_lineno; // Line number to make change at
V3ErrorCode m_code; // Error code
@@ -233,8 +233,8 @@ public:
: m_lineno{lineno}
, m_code{code}
, m_on{on} {}
~V3ConfigIgnoresLine() {}
inline bool operator<(const V3ConfigIgnoresLine& rh) const {
~V3ConfigIgnoresLine() = default;
bool operator<(const V3ConfigIgnoresLine& rh) const {
if (m_lineno < rh.m_lineno) return true;
if (m_lineno > rh.m_lineno) return false;
if (m_code < rh.m_code) return true;
@@ -253,7 +253,7 @@ std::ostream& operator<<(std::ostream& os, const V3ConfigIgnoresLine& rhs) {
typedef std::bitset<AstPragmaType::ENUM_SIZE> V3ConfigLineAttribute;
// File entity
class V3ConfigFile {
class V3ConfigFile final {
typedef std::map<int, V3ConfigLineAttribute> LineAttrMap; // Map line->bitset of attributes
typedef std::multiset<V3ConfigIgnoresLine> IgnLines; // list of {line,code,on}
typedef std::pair<V3ErrorCode, string> WaiverSetting; // Waive code if string matches
@@ -347,16 +347,16 @@ typedef V3ConfigWildcardResolver<V3ConfigFile> V3ConfigFileResolver;
//######################################################################
// Resolve modules and files in the design
class V3ConfigResolver {
class V3ConfigResolver final {
V3ConfigModuleResolver m_modules; // Access to module names (with wildcards)
V3ConfigFileResolver m_files; // Access to file names (with wildcards)
static V3ConfigResolver s_singleton; // Singleton (not via local static, as that's slow)
V3ConfigResolver() {}
~V3ConfigResolver() {}
V3ConfigResolver() = default;
~V3ConfigResolver() = default;
public:
inline static V3ConfigResolver& s() { return s_singleton; }
static V3ConfigResolver& s() { return s_singleton; }
V3ConfigModuleResolver& modules() { return m_modules; }
V3ConfigFileResolver& files() { return m_files; }
@@ -405,7 +405,7 @@ void V3Config::addInline(FileLine* fl, const string& module, const string& ftask
V3ConfigResolver::s().modules().at(module).setInline(on);
} else {
if (!on) {
fl->v3error("no_inline not supported for tasks" << endl);
fl->v3error("no_inline not supported for tasks");
} else {
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setNoInline(on);
}
@@ -416,15 +416,14 @@ void V3Config::addVarAttr(FileLine* fl, const string& module, const string& ftas
const string& var, AstAttrType attr, AstSenTree* sensep) {
// Semantics: sensep only if public_flat_rw
if ((attr != AstAttrType::VAR_PUBLIC_FLAT_RW) && sensep) {
sensep->v3error("sensitivity not expected for attribute" << endl);
sensep->v3error("sensitivity not expected for attribute");
return;
}
// Semantics: Most of the attributes operate on signals
if (var.empty()) {
if (attr == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
if (ftask.empty()) {
fl->v3error("isolate_assignments only applies to signals or functions/tasks"
<< endl);
fl->v3error("isolate_assignments only applies to signals or functions/tasks");
} else {
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setIsolate(true);
}
@@ -437,7 +436,7 @@ void V3Config::addVarAttr(FileLine* fl, const string& module, const string& ftas
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setPublic(true);
}
} else {
fl->v3error("missing -signal" << endl);
fl->v3error("missing -signal");
}
} else {
V3ConfigModule& mod = V3ConfigResolver::s().modules().at(module);
+1 -1
View File
@@ -26,7 +26,7 @@
//######################################################################
class V3Config {
class V3Config final {
public:
static void addCaseFull(const string& file, int lineno);
static void addCaseParallel(const string& file, int lineno);
+11 -10
View File
@@ -36,7 +36,7 @@
//######################################################################
// Utilities
class ConstVarMarkVisitor : public AstNVisitor {
class ConstVarMarkVisitor final : public AstNVisitor {
// NODE STATE
// AstVar::user4p -> bool, Var marked, 0=not set yet
private:
@@ -52,10 +52,10 @@ public:
AstNode::user4ClearTree(); // Check marked InUse before we're called
iterate(nodep);
}
virtual ~ConstVarMarkVisitor() override {}
virtual ~ConstVarMarkVisitor() override = default;
};
class ConstVarFindVisitor : public AstNVisitor {
class ConstVarFindVisitor final : public AstNVisitor {
// NODE STATE
// AstVar::user4p -> bool, input from ConstVarMarkVisitor
// MEMBERS
@@ -71,7 +71,7 @@ private:
public:
// CONSTRUCTORS
explicit ConstVarFindVisitor(AstNode* nodep) { iterateAndNextNull(nodep); }
virtual ~ConstVarFindVisitor() override {}
virtual ~ConstVarFindVisitor() override = default;
// METHODS
bool found() const { return m_found; }
};
@@ -79,7 +79,7 @@ public:
//######################################################################
// Const state, as a visitor of each AstNode
class ConstVisitor : public AstNVisitor {
class ConstVisitor final : public AstNVisitor {
private:
// NODE STATE
// ** only when m_warn/m_doExpensive is set. If state is needed other times,
@@ -1262,7 +1262,7 @@ private:
AstNode* errorp = simvis.whyNotNodep();
if (!errorp) errorp = nodep;
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
<< nodep->prettyTypeName() << endl
<< nodep->prettyTypeName() << '\n'
<< errorp->warnOther() << "... Location of non-constant "
<< errorp->prettyTypeName() << ": " << simvis.whyNotMessage());
VL_DO_DANGLING(replaceZero(nodep), nodep);
@@ -1730,7 +1730,7 @@ private:
}
struct SenItemCmp {
inline bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const {
bool operator()(const AstSenItem* lhsp, const AstSenItem* rhsp) const {
if (lhsp->type() < rhsp->type()) return true;
if (lhsp->type() > rhsp->type()) return false;
// Looks visually better if we keep sorted by name
@@ -1930,8 +1930,9 @@ private:
nodep->replaceWith(ifp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else if (ifSameAssign(nodep)) {
UINFO(4, "IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"
<< endl);
UINFO(
4,
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})\n");
AstNodeAssign* ifp = VN_CAST(nodep->ifsp(), NodeAssign);
AstNodeAssign* elsep = VN_CAST(nodep->elsesp(), NodeAssign);
ifp->unlinkFrBack();
@@ -2563,7 +2564,7 @@ public:
}
// clang-format on
}
virtual ~ConstVisitor() override {}
virtual ~ConstVisitor() override = default;
AstNode* mainAcceptEdit(AstNode* nodep) {
// Operate starting at a random place
return iterateSubtreeReturnEdits(nodep);
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Const {
class V3Const final {
public:
static AstNode* constifyParamsEdit(AstNode* nodep);
static AstNode* constifyGenerateParamsEdit(AstNode* nodep);
+4 -4
View File
@@ -37,7 +37,7 @@
//######################################################################
// Coverage state, as a visitor of each AstNode
class CoverageVisitor : public AstNVisitor {
class CoverageVisitor final : public AstNVisitor {
private:
// TYPES
typedef std::unordered_map<string, int> VarNameMap;
@@ -52,7 +52,7 @@ private:
: m_comment{comment}
, m_varRefp{vp}
, m_chgRefp{cp} {}
~ToggleEnt() {}
~ToggleEnt() = default;
void cleanup() {
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = nullptr);
VL_DO_CLEAR(m_chgRefp->deleteTree(), m_chgRefp = nullptr);
@@ -64,7 +64,7 @@ private:
bool m_inModOff = false; // In module with no coverage
int m_handle = 0; // Opaque handle for index into line tracking
const AstNode* m_nodep = nullptr; // Node establishing this state
CheckState() {}
CheckState() = default;
bool lineCoverageOn(const AstNode* nodep) const {
return m_on && !m_inModOff && nodep->fileline()->coverageOn()
&& v3Global.opt.coverageLine();
@@ -534,7 +534,7 @@ private:
public:
// CONSTRUCTORS
explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); }
virtual ~CoverageVisitor() override {}
virtual ~CoverageVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Coverage {
class V3Coverage final {
public:
// CONSTRUCTORS
static void coverage(AstNetlist* rootp);
+1 -1
View File
@@ -30,7 +30,7 @@
//######################################################################
// CoverageJoin state, as a visitor of each AstNode
class CoverageJoinVisitor : public AstNVisitor {
class CoverageJoinVisitor final : public AstNVisitor {
private:
// NODE STATE
// V3Hashed
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3CoverageJoin {
class V3CoverageJoin final {
public:
// CONSTRUCTORS
static void coverageJoin(AstNetlist* rootp);
+51 -51
View File
@@ -30,9 +30,8 @@
// Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links
// are no longer used, but their presence prevents us from removing empty
// packages. As the links as no longer used after V3Scope, we remove them
// here after scoping to allow more dead node
// removal.
// *************************************************************************
// here after scoping to allow more dead node removal.
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
@@ -46,7 +45,7 @@
//######################################################################
class DeadModVisitor : public AstNVisitor {
class DeadModVisitor final : public AstNVisitor {
// In a module that is dead, cleanup the in-use counts of the modules
private:
// NODE STATE
@@ -63,13 +62,13 @@ private:
public:
// CONSTRUCTORS
explicit DeadModVisitor(AstNodeModule* nodep) { iterate(nodep); }
virtual ~DeadModVisitor() override {}
virtual ~DeadModVisitor() override = default;
};
//######################################################################
// Dead state, as a visitor of each AstNode
class DeadVisitor : public AstNVisitor {
class DeadVisitor final : public AstNVisitor {
private:
// NODE STATE
// Entire Netlist:
@@ -83,7 +82,7 @@ private:
typedef std::multimap<AstVarScope*, AstNodeAssign*> AssignMap;
// STATE
AstNodeModule* m_modp; // Current module
AstNodeModule* m_modp = nullptr; // Current module
// List of all encountered to avoid another loop through tree
std::vector<AstVar*> m_varsp;
std::vector<AstNode*> m_dtypesp;
@@ -93,10 +92,10 @@ private:
std::vector<AstClass*> m_classesp;
AssignMap m_assignMap; // List of all simple assignments for each variable
bool m_elimUserVars; // Allow removal of user's vars
bool m_elimDTypes; // Allow removal of DTypes
bool m_elimCells; // Allow removal of Cells
bool m_sideEffect; // Side effects discovered in assign RHS
const bool m_elimUserVars; // Allow removal of user's vars
const bool m_elimDTypes; // Allow removal of DTypes
const bool m_elimCells; // Allow removal of Cells
bool m_sideEffect = false; // Side effects discovered in assign RHS
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@@ -107,6 +106,9 @@ private:
}
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
}
void checkVarRef(AstNodeVarRef* nodep) {
if (nodep->classOrPackagep() && m_elimCells) nodep->classOrPackagep(nullptr);
}
void checkDType(AstNodeDType* nodep) {
if (!nodep->generic() // Don't remove generic types
&& m_elimDTypes // dtypes stick around until post-widthing
@@ -120,6 +122,7 @@ private:
// VISITORS
virtual void visit(AstNodeModule* nodep) override {
if (m_modp) m_modp->user1Inc(); // e.g. Class under Package
VL_RESTORER(m_modp);
{
m_modp = nodep;
@@ -128,7 +131,7 @@ private:
checkAll(nodep);
if (AstClass* classp = VN_CAST(nodep, Class)) {
if (classp->extendsp()) classp->extendsp()->user1Inc();
if (classp->packagep()) classp->packagep()->user1Inc();
if (classp->classOrPackagep()) classp->classOrPackagep()->user1Inc();
m_classesp.push_back(classp);
// TODO we don't reclaim dead classes yet - graph implementation instead?
classp->user1Inc();
@@ -160,29 +163,25 @@ private:
}
virtual void visit(AstNodeVarRef* nodep) override {
// Note NodeAssign skips calling this in some cases
iterateChildren(nodep);
checkAll(nodep);
checkVarRef(nodep);
if (nodep->varScopep()) {
nodep->varScopep()->user1Inc();
nodep->varScopep()->varp()->user1Inc();
}
if (nodep->varp()) nodep->varp()->user1Inc();
if (nodep->packagep()) {
if (m_elimCells) {
nodep->packagep(nullptr);
} else {
nodep->packagep()->user1Inc();
}
}
if (nodep->classOrPackagep()) nodep->classOrPackagep()->user1Inc();
}
virtual void visit(AstNodeFTaskRef* nodep) override {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->packagep()) {
if (nodep->classOrPackagep()) {
if (m_elimCells) {
nodep->packagep(nullptr);
nodep->classOrPackagep(nullptr);
} else {
nodep->packagep()->user1Inc();
nodep->classOrPackagep()->user1Inc();
}
}
}
@@ -196,11 +195,11 @@ private:
checkAll(nodep);
UASSERT_OBJ(!(m_elimCells && nodep->typedefp()), nodep,
"RefDType should point to data type before typedefs removed");
if (nodep->packagep()) {
if (nodep->classOrPackagep()) {
if (m_elimCells) {
nodep->packagep(nullptr);
nodep->classOrPackagep(nullptr);
} else {
nodep->packagep()->user1Inc();
nodep->classOrPackagep()->user1Inc();
}
}
}
@@ -208,11 +207,11 @@ private:
iterateChildren(nodep);
checkDType(nodep);
checkAll(nodep);
if (nodep->packagep()) {
if (nodep->classOrPackagep()) {
if (m_elimCells) {
nodep->packagep(nullptr);
nodep->classOrPackagep(nullptr);
} else {
nodep->packagep()->user1Inc();
nodep->classOrPackagep()->user1Inc();
}
}
if (nodep->classp()) nodep->classp()->user1Inc();
@@ -225,11 +224,11 @@ private:
virtual void visit(AstEnumItemRef* nodep) override {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->packagep()) {
if (nodep->classOrPackagep()) {
if (m_elimCells) {
nodep->packagep(nullptr);
nodep->classOrPackagep(nullptr);
} else {
nodep->packagep()->user1Inc();
nodep->classOrPackagep()->user1Inc();
}
}
checkAll(nodep);
@@ -277,19 +276,22 @@ private:
// See if simple assignments to variables may be eliminated because
// that variable is never used.
// Similar code in V3Life
m_sideEffect = false;
iterateAndNextNull(nodep->rhsp());
checkAll(nodep);
// Has to be direct assignment without any EXTRACTing.
AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef);
if (varrefp && !m_sideEffect
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
checkAll(varrefp); // Must track reference to dtype()
} else { // Track like any other statement
iterateAndNextNull(nodep->lhsp());
VL_RESTORER(m_sideEffect);
{
m_sideEffect = false;
iterateAndNextNull(nodep->rhsp());
checkAll(nodep);
// Has to be direct assignment without any EXTRACTing.
AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef);
if (varrefp && !m_sideEffect
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
checkAll(varrefp); // Must track reference to dtype()
checkVarRef(varrefp);
} else { // Track like any other statement
iterateAndNextNull(nodep->lhsp());
}
}
checkAll(nodep);
}
//-----
@@ -371,7 +373,7 @@ private:
if (AstClass* nodep = itr) { // nullptr if deleted earlier
if (nodep->user1() == 0) {
if (nodep->extendsp()) nodep->extendsp()->user1Inc(-1);
if (nodep->packagep()) nodep->packagep()->user1Inc(-1);
if (nodep->classOrPackagep()) nodep->classOrPackagep()->user1Inc(-1);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
itr = nullptr;
retry = true;
@@ -438,12 +440,10 @@ private:
public:
// CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes,
bool elimCells) {
m_modp = nullptr;
m_elimCells = elimCells;
m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes;
m_sideEffect = false;
bool elimCells)
: m_elimUserVars{elimUserVars}
, m_elimDTypes{elimDTypes}
, m_elimCells{elimCells} {
// Prepare to remove some datatypes
nodep->typeTablep()->clearCache();
// Operate on whole netlist
@@ -461,7 +461,7 @@ public:
// We may have removed some datatypes, cleanup
nodep->typeTablep()->repairCache();
}
virtual ~DeadVisitor() override {}
virtual ~DeadVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Dead {
class V3Dead final {
public:
// Modules, no vars/dtypes
static void deadifyModules(AstNetlist* nodep);
+8 -8
View File
@@ -63,7 +63,7 @@
//######################################################################
// Delayed state, as a visitor of each AstNode
class DelayedVisitor : public AstNVisitor {
class DelayedVisitor final : public AstNVisitor {
private:
// NODE STATE
// Cleared each module:
@@ -98,7 +98,7 @@ private:
typedef std::map<const std::pair<AstNodeModule*, string>, AstVar*> VarMap;
VarMap m_modVarMap; // Table of new var names created under module
VDouble0 m_statSharedSet; // Statistic tracking
typedef std::map<const AstVarScope*, int> ScopeVecMap;
typedef std::unordered_map<const AstVarScope*, int> ScopeVecMap;
ScopeVecMap m_scopeVecMap; // Next var number for each scope
// METHODS
@@ -160,10 +160,10 @@ private:
varrefp->varp()->v3warn(
MULTIDRIVEN,
"Signal has multiple driving blocks with different clocking: "
<< varrefp->varp()->prettyNameQ() << endl
<< varrefp->warnOther() << "... Location of first driving block" << endl
<< varrefp->warnContextPrimary() << endl
<< oldactivep->warnOther() << "... Location of other driving block" << endl
<< varrefp->varp()->prettyNameQ() << '\n'
<< varrefp->warnOther() << "... Location of first driving block\n"
<< varrefp->warnContextPrimary() << '\n'
<< oldactivep->warnOther() << "... Location of other driving block\n"
<< oldactivep->warnContextSecondary());
varrefp->varp()->user2(true);
}
@@ -289,7 +289,7 @@ private:
new AstConst(nodep->fileline(), 0));
AstAssign* setassignp = new AstAssign(
nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, VAccess::WRITE),
new AstConst(nodep->fileline(), AstConst::LogicTrue()));
new AstConst(nodep->fileline(), AstConst::BitTrue()));
nodep->addNextHere(setassignp);
}
if (m_nextDlyp) { // Tell next assigndly it can share the variable
@@ -436,7 +436,7 @@ private:
prep = new AstAssignPre(
nodep->fileline(),
new AstVarRef(nodep->fileline(), dlyvscp, VAccess::WRITE),
new AstConst(nodep->fileline(), AstConst::LogicFalse()));
new AstConst(nodep->fileline(), AstConst::BitFalse()));
} else {
prep = new AstAssignPre(
nodep->fileline(),
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Delayed {
class V3Delayed final {
public:
static void delayedAll(AstNetlist* nodep);
};
+2 -2
View File
@@ -34,7 +34,7 @@
//######################################################################
class DepthVisitor : public AstNVisitor {
class DepthVisitor final : public AstNVisitor {
private:
// NODE STATE
@@ -155,7 +155,7 @@ private:
public:
// CONSTRUCTORS
explicit DepthVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~DepthVisitor() override {}
virtual ~DepthVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Depth {
class V3Depth final {
public:
static void depthAll(AstNetlist* nodep);
};
+2 -2
View File
@@ -32,7 +32,7 @@
//######################################################################
class DepthBlockVisitor : public AstNVisitor {
class DepthBlockVisitor final : public AstNVisitor {
private:
// NODE STATE
@@ -117,7 +117,7 @@ private:
public:
// CONSTRUCTORS
explicit DepthBlockVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~DepthBlockVisitor() override {}
virtual ~DepthBlockVisitor() override = default;
};
//######################################################################
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3DepthBlock {
class V3DepthBlock final {
public:
static void depthBlockAll(AstNetlist* nodep);
};
+19 -6
View File
@@ -34,7 +34,7 @@
//######################################################################
class DescopeVisitor : public AstNVisitor {
class DescopeVisitor final : public AstNVisitor {
private:
// NODE STATE
// Cleared entire netlist
@@ -76,7 +76,8 @@ private:
// Sets 'hierThisr' true if the object is local to this scope
// (and could be made into a function-local later in V3Localize),
// false if the object is in another scope.
string descopedName(const AstScope* scopep, bool& hierThisr, const AstVar* varp = nullptr) {
string descopedName(bool& hierThisr, string& hierUnprot, const AstScope* scopep,
const AstVar* varp) {
UASSERT(scopep, "Var/Func not scoped");
hierThisr = (scopep == m_scopep);
@@ -118,6 +119,9 @@ private:
} else if (relativeRefOk && scopep == m_scopep) {
m_needThis = true;
return "this->";
} else if (VN_IS(scopep->modp(), Class)) {
hierUnprot = v3Global.opt.modPrefix() + "_"; // Prefix before protected part
return scopep->modp()->name() + "::";
} else if (relativeRefOk && scopep->aboveScopep() && scopep->aboveScopep() == m_scopep) {
// Reference to scope of cell directly under this module, can just "cell->"
string name = scopep->name();
@@ -249,12 +253,17 @@ private:
virtual void visit(AstNodeVarRef* nodep) override {
iterateChildren(nodep);
// Convert the hierch name
UINFO(9, " ref-in " << nodep << endl);
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
bool hierThis;
nodep->hiername(descopedName(nodep->varScopep()->scopep(), hierThis /*ref*/,
nodep->varScopep()->varp()));
string hierUnprot;
nodep->hiernameToProt(descopedName(hierThis /*ref*/, hierUnprot /*ref*/,
nodep->varScopep()->scopep(),
nodep->varScopep()->varp()));
nodep->hiernameToUnprot(hierUnprot);
nodep->hierThis(hierThis);
nodep->varScopep(nullptr);
UINFO(9, " refout " << nodep << endl);
}
virtual void visit(AstNodeCCall* nodep) override {
// UINFO(9, " " << nodep << endl);
@@ -263,7 +272,10 @@ private:
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
UASSERT_OBJ(nodep->funcp()->scopep(), nodep, "CFunc not under scope");
bool hierThis;
nodep->hiername(descopedName(nodep->funcp()->scopep(), hierThis /*ref*/));
string hierUnprot;
nodep->hiernameToProt(
descopedName(hierThis /*ref*/, hierUnprot /*ref*/, nodep->funcp()->scopep(), nullptr));
nodep->hiernameToUnprot(hierUnprot);
// Can't do this, as we may have more calls later
// nodep->funcp()->scopep(nullptr);
}
@@ -296,7 +308,7 @@ private:
public:
// CONSTRUCTORS
explicit DescopeVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~DescopeVisitor() override {}
virtual ~DescopeVisitor() override = default;
};
//######################################################################
@@ -304,6 +316,7 @@ public:
void V3Descope::descopeAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl);
v3Global.assertScoped(false);
{ DescopeVisitor visitor(nodep); } // Destruct before checking
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3Descope {
class V3Descope final {
public:
static void descopeAll(AstNetlist* nodep);
};
+22 -15
View File
@@ -39,7 +39,7 @@ constexpr int EMITC_NUM_CONSTW
//######################################################################
// Emit statements and math operators
class EmitCStmts : public EmitCBaseVisitor {
class EmitCStmts VL_NOT_FINAL : public EmitCBaseVisitor {
private:
typedef std::vector<const AstVar*> VarVec;
typedef std::map<int, VarVec> VarSortMap; // Map size class to VarVec
@@ -216,7 +216,7 @@ public:
}
struct CmpName {
inline bool operator()(const AstNode* lhsp, const AstNode* rhsp) const {
bool operator()(const AstNode* lhsp, const AstNode* rhsp) const {
return lhsp->name() < rhsp->name();
}
};
@@ -430,8 +430,12 @@ public:
virtual void visit(AstWith* nodep) override {
// With uses a C++11 lambda
putbs("[=](");
if (auto* argrefp = nodep->argrefp()) {
putbs(argrefp->dtypep()->cType(nodep->argrefp()->nameProtect(), false, false));
if (auto* argrefp = nodep->indexArgRefp()) {
putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false));
puts(",");
}
if (auto* argrefp = nodep->valueArgRefp()) {
putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false));
}
// Probably fragile, V3Task may need to convert to a AstCReturn
puts(") { return ");
@@ -836,6 +840,9 @@ public:
putsQuoted(nodep->timeunit().ascii());
puts(");\n");
}
virtual void visit(AstRand* nodep) override {
emitOpName(nodep, nodep->emitC(), nodep->seedp(), nullptr, nullptr);
}
virtual void visit(AstTime* nodep) override {
puts("VL_TIME_UNITED_Q(");
if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time has no units");
@@ -1258,25 +1265,25 @@ public:
m_trackText = trackText;
iterate(nodep);
}
virtual ~EmitCStmts() override {}
virtual ~EmitCStmts() override = default;
};
//######################################################################
// Establish mtask variable sort order in mtasks mode
class EmitVarTspSorter : public V3TSP::TspStateBase {
class EmitVarTspSorter final : public V3TSP::TspStateBase {
private:
// MEMBERS
const MTaskIdSet& m_mtaskIds; // Mtask we're ordering
static unsigned m_serialNext; // Unique ID to establish serial order
static unsigned s_serialNext; // Unique ID to establish serial order
unsigned m_serial; // Serial ordering
public:
// CONSTRUCTORS
explicit EmitVarTspSorter(const MTaskIdSet& mtaskIds)
: m_mtaskIds(mtaskIds) { // Cannot be {} or GCC 4.8 false warning
m_serial = ++m_serialNext; // Cannot be ()/{} or GCC 4.8 false warning
m_serial = ++s_serialNext; // Cannot be ()/{} or GCC 4.8 false warning
}
virtual ~EmitVarTspSorter() {}
virtual ~EmitVarTspSorter() = default;
// METHODS
virtual bool operator<(const TspStateBase& other) const override {
return operator<(dynamic_cast<const EmitVarTspSorter&>(other));
@@ -1301,12 +1308,12 @@ public:
}
};
unsigned EmitVarTspSorter::m_serialNext = 0;
unsigned EmitVarTspSorter::s_serialNext = 0;
//######################################################################
// Internal EmitC implementation
class EmitCImp : EmitCStmts {
class EmitCImp final : EmitCStmts {
// MEMBERS
AstNodeModule* m_modp = nullptr;
std::vector<AstChangeDet*> m_blkChangeDetVec; // All encountered changes in block
@@ -1840,8 +1847,8 @@ class EmitCImp : EmitCStmts {
void maybeSplit(AstNodeModule* modp);
public:
EmitCImp() {}
virtual ~EmitCImp() override {}
EmitCImp() = default;
virtual ~EmitCImp() override = default;
void mainImp(AstNodeModule* modp, bool slow);
void mainInt(AstNodeModule* modp);
void mainDoFunc(AstCFunc* nodep) { iterate(nodep); }
@@ -3401,7 +3408,7 @@ void EmitCImp::mainImp(AstNodeModule* modp, bool slow) {
//######################################################################
// Tracing routines
class EmitCTrace : EmitCStmts {
class EmitCTrace final : EmitCStmts {
// NODE STATE/TYPES
// Cleared on netlist
// AstNode::user1() -> int. Enum number
@@ -3840,7 +3847,7 @@ class EmitCTrace : EmitCStmts {
public:
explicit EmitCTrace(bool slow)
: m_slow{slow} {}
virtual ~EmitCTrace() override {}
virtual ~EmitCTrace() override = default;
void main() {
// Put out the file
newOutCFile(0);
+1 -1
View File
@@ -25,7 +25,7 @@
//============================================================================
class V3EmitC {
class V3EmitC final {
public:
static void emitc();
static void emitcInlines();
+5 -5
View File
@@ -30,7 +30,7 @@
//######################################################################
// Base Visitor class -- holds output file pointer
class EmitCBaseVisitor : public AstNVisitor {
class EmitCBaseVisitor VL_NOT_FINAL : public AstNVisitor {
public:
// STATE
V3OutCFile* m_ofp = nullptr;
@@ -106,14 +106,14 @@ public:
}
// CONSTRUCTORS
EmitCBaseVisitor() {}
virtual ~EmitCBaseVisitor() override {}
EmitCBaseVisitor() = default;
virtual ~EmitCBaseVisitor() override = default;
};
//######################################################################
// Count operations under the given node, as a visitor of each AstNode
class EmitCBaseCounterVisitor : public AstNVisitor {
class EmitCBaseCounterVisitor final : public AstNVisitor {
private:
// MEMBERS
int m_count = 0; // Number of statements
@@ -126,7 +126,7 @@ private:
public:
// CONSTRUCTORS
explicit EmitCBaseCounterVisitor(AstNode* nodep) { iterate(nodep); }
virtual ~EmitCBaseCounterVisitor() override {}
virtual ~EmitCBaseCounterVisitor() override = default;
int count() const { return m_count; }
};
+1 -1
View File
@@ -26,7 +26,7 @@
//######################################################################
class EmitCInlines : EmitCBaseVisitor {
class EmitCInlines final : EmitCBaseVisitor {
// STATE
// METHODS
+1 -1
View File
@@ -26,7 +26,7 @@
//######################################################################
class EmitCMain : EmitCBaseVisitor {
class EmitCMain final : EmitCBaseVisitor {
// METHODS
// VISITORS
+1 -1
View File
@@ -22,7 +22,7 @@
//============================================================================
class V3EmitCMain {
class V3EmitCMain final {
public:
static void emit();
};
+2 -2
View File
@@ -28,7 +28,7 @@
//######################################################################
// Emit statements
class CMakeEmitter {
class CMakeEmitter final {
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@@ -256,7 +256,7 @@ class CMakeEmitter {
public:
explicit CMakeEmitter() { emitOverallCMake(); }
virtual ~CMakeEmitter() {}
virtual ~CMakeEmitter() = default;
};
void V3EmitCMake::emit() {
+1 -1
View File
@@ -22,7 +22,7 @@
//============================================================================
class V3EmitCMake {
class V3EmitCMake final {
public:
static void emit();
};
+5 -5
View File
@@ -29,7 +29,7 @@
//######################################################################
// Symbol table emitting
class EmitCSyms : EmitCBaseVisitor {
class EmitCSyms final : EmitCBaseVisitor {
// NODE STATE
// Cleared on Netlist
// AstNodeModule::user1() -> bool. Set true __Vconfigure called
@@ -79,12 +79,12 @@ class EmitCSyms : EmitCBaseVisitor {
typedef std::vector<string> ScopeNameList;
typedef std::map<const string, ScopeNameList> ScopeNameHierarchy;
struct CmpName {
inline bool operator()(const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
bool operator()(const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
return lhsp.first->name() < rhsp.first->name();
}
};
struct CmpDpi {
inline bool operator()(const AstCFunc* lhsp, const AstCFunc* rhsp) const {
bool operator()(const AstCFunc* lhsp, const AstCFunc* rhsp) const {
if (lhsp->dpiImport() != rhsp->dpiImport()) {
// cppcheck-suppress comparisonOfFuncReturningBoolError
return lhsp->dpiImport() < rhsp->dpiImport();
@@ -109,7 +109,7 @@ class EmitCSyms : EmitCBaseVisitor {
int m_numStmts = 0; // Number of statements output
int m_funcNum = 0; // CFunc split function number
V3OutCFile* m_ofpBase = nullptr; // Base (not split) C file
std::map<int, bool> m_usesVfinal; // Split method uses __Vfinal
std::unordered_map<int, bool> m_usesVfinal; // Split method uses __Vfinal
// METHODS
void emitSymHdr();
@@ -467,7 +467,7 @@ void EmitCSyms::emitSymHdr() {
puts("\n// CREATORS\n");
puts(symClassName() + "(" + topClassName() + "* topp, const char* namep);\n");
puts(string("~") + symClassName() + "() {}\n");
puts(string("~") + symClassName() + "() = default;\n");
for (const auto& i : m_usesVfinal) {
puts("void " + symClassName() + "_" + cvtToStr(i.first) + "(");
+3 -3
View File
@@ -26,7 +26,7 @@
//######################################################################
// Emit statements and math operators
class EmitMk {
class EmitMk final {
public:
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@@ -285,11 +285,11 @@ public:
emitClassMake();
emitOverallMake();
}
virtual ~EmitMk() {}
virtual ~EmitMk() = default;
};
//######################################################################
class EmitMkHierVerilation {
class EmitMkHierVerilation final {
const V3HierBlockPlan* const m_planp;
const string m_makefile; // path of this makefile
void emitCommonOpts(V3OutMkFile& of) const {

Some files were not shown because too many files have changed in this diff Show More