diff --git a/.clang-format b/.clang-format
index 0fd60f7dd..5e66ff611 100644
--- a/.clang-format
+++ b/.clang-format
@@ -13,7 +13,7 @@ AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
-AllowShortLoopsOnASingleLine: false
+AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 3e438348e..5873b5bd7 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -11,4 +11,6 @@ Thanks for taking the time to report this.
Can you attach an example that shows the issue? (Must be openly licensed, ideally in test_regress format.)
-May we assist you in trying to fix this yourself?
+What 'verilator --version' are you using? Did you try it with the git master version?
+
+Would you be willing to try to fix Verilator yourself with assistance?
diff --git a/.travis.yml b/.travis.yml
index b0623c38c..e9cbc4c3b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,7 +19,6 @@ env:
- VERILATOR_NUM_JOBS=$(echo `nproc` + 1 | bc)
- VERILATOR_CONFIG_FLAGS="--enable-maintainer-mode --enable-longtests"
- VERILATOR_AUTHOR_SITE=1
- - OBJCACHE=ccache
cache:
directories:
@@ -28,6 +27,7 @@ cache:
before_install:
# Perl modules needed for testing
# Not listing Bit::Vector as slow to install, and only skips one test
+ - touch temp.cpp ; g++ -E -dM -c temp.cpp | sort ; rm -rf temp.cpp
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker
- sudo apt-get install gdb gtkwave
- sudo apt-get install libgoogle-perftools-dev
diff --git a/Changes b/Changes
index 719aa2d10..cfff91f11 100644
--- a/Changes
+++ b/Changes
@@ -3,6 +3,52 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
+* Verilator 4.034 2020-05-03
+
+** Add simplistic class support with many restrictions, see manual, #377.
+
+** Support IEEE time units and time precisions, #234.
+ Includes `timescale, $printtimescale, $timeformat.
+ VL_TIME_MULTIPLIER, VL_TIME_PRECISION, VL_TIME_UNIT have been removed
+ and the time precision must now match the SystemC time precision. To
+ get closer behavior to older versions, use e.g. --timescale-override
+ "1ps/1ps".
+
+** Add --build to call make automatically, #2249. [Yutetsu TAKATSUKASA]
+
+** Configuring with ccache present now defaults to using it; see OBJCACHE.
+
+** Fix DPI import/export to be standard compliant, #2236. [Geza Lore]
+
+** Add --trace-threads for general multithreaded tracing, #2269. [Geza Lore]
+
+*** Add --flatten for use with --xml-only, #2270. [James Hanlon]
+
+**** Greatly improve FST/VCD dump performance, #2244, #2246, #2250, #2257. [Geza Lore]
+
+**** Support $ferror, and $fflush without arguments, #1638.
+
+**** Support event data type (with some restrictions).
+
+**** Support $root, #2150. [Keyi Zhang]
+
+**** Add error if use SystemC 2.2 and earlier (pre-2011) as is deprecated.
+
+**** Fix build of fast path tracing code to use OPT_FAST, #2245. [Geza Lore]
+
+**** Fix arrayed instances connecting to slices, #2263. [Don/engr248]
+
+**** Fix error on unpacked connecting to packed, #2288. [Joseph Shaker]
+
+**** Fix logical not optimization with empty begin, #2291. [Baltazar Ortiz]
+
+**** Fix reduction OR on wide data, broke in v4.026, #2300. [Jack Koenig]
+
+**** Fix clock enables with bit-extends, #2299. [Marco Widmer]
+
+**** Fix MacOs Homebrew by removing default LIBS, #2298. [Ryan Clarke]
+
+
* Verilator 4.032 2020-04-04
*** Add column numbers to errors and warnings.
diff --git a/Makefile.in b/Makefile.in
index f9d9bffad..b49baf8ae 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -336,6 +336,7 @@ installdata:
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_c
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_sc
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_protect_lib
+ $(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/xml_py
cd $(srcdir) \
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
@@ -370,8 +371,8 @@ uninstall:
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_c
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_sc
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_protect_lib
+ -rmdir $(DESTDIR)$(pkgdatadir)/examples/xml_py
-rmdir $(DESTDIR)$(pkgdatadir)/examples
- -rmdir $(DESTDIR)$(pkgdatadir)/cmake
-rmdir $(DESTDIR)$(pkgdatadir)
-rmdir $(DESTDIR)$(pkgconfigdir)
@@ -455,6 +456,14 @@ analyzer-include:
-rm -rf examples/*/obj*
scan-build $(MAKE) -k examples
+CLANGFORMAT = clang-format
+CLANGFORMAT_FLAGS = -i
+
+clang-format:
+ @$(CLANGFORMAT) --version | egrep 10.0 > /dev/null \
+ || echo "*** You are not using clang-format 10.0, indents may differ from master's ***"
+ $(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CPPCHECK_CPP) $(CPPCHECK_H)
+
ftp: info
install-msg:
diff --git a/README.adoc b/README.adoc
index 3e2eb528b..45f2c7409 100644
--- a/README.adoc
+++ b/README.adoc
@@ -4,7 +4,7 @@
ifdef::env-github[]
image:https://img.shields.io/badge/License-LGPL%20v3-blue.svg[license LGPLv3,link=https://www.gnu.org/licenses/lgpl-3.0]
image:https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg[license Artistic-2.0,link=https://opensource.org/licenses/Artistic-2.0]
-image:https://api.codacy.com/project/badge/Grade/48478c986f13400682ffe4a5e0939b3a[Code Quality,link=https://www.codacy.com/gh/verilator/verilator]
+image:https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f[Code Quality,link=https://www.codacy.com/gh/verilator/verilator]
image:https://travis-ci.com/verilator/verilator.svg?branch=master[Build Status (Travis CI),link=https://travis-ci.com/verilator/verilator]
endif::[]
@@ -22,7 +22,7 @@ endif::[]
[cols="a,a",indent=0,frame="none"]
|===
-^.^| *Welcome to Verilator, the fastest free Verilog HDL simulator.*
+^.^| *Welcome to Verilator, the fastest Verilog HDL simulator.*
+++
+++ • Accepts synthesizable Verilog or SystemVerilog
+++
+++ • Performs lint code-quality checks
+++
+++ • Compiles into multithreaded {cpp}, or SystemC
@@ -56,7 +56,7 @@ endif::[]
== What Verilator Does
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
-"Verilates" the specified synthesizable Verilog or SystemVerilog code by
+"Verilates" the specified Verilog or SystemVerilog code by
reading it, performing lint checks, and optionally inserting assertion
checks and coverage-analysis points. It outputs single- or multi-threaded
.cpp and .h files, the "Verilated" code.
@@ -72,30 +72,30 @@ Verilator may not be the best choice if you are expecting a full featured
replacement for NC-Verilog, VCS or another commercial Verilog simulator, or
if you are looking for a behavioral Verilog simulator e.g. for a quick
class project (we recommend http://iverilog.icarus.com[Icarus Verilog] for
-this.) However, if you are looking for a path to migrate synthesizable
-Verilog to {cpp} or SystemC, and your team is comfortable writing just a
+this.) However, if you are looking for a path to migrate SystemVerilog to
+{cpp} or SystemC, and your team is comfortable writing just a
touch of {cpp} code, Verilator is the tool for you.
== Performance
-Verilator does not simply convert Verilog HDL to {cpp} or SystemC. Rather
-than only translate, Verilator compiles your code into a much faster
-optimized and optionally thread-partitioned model, which is in turn wrapped
-inside a {cpp}/SystemC/{cpp}-under-Python module. The results are a compiled Verilog
-model that executes even on a single-thread over 10x faster than standalone
-SystemC, and on a single thread is about 100 times faster than interpreted
-Verilog simulators such as http://iverilog.icarus.com[Icarus
+Verilator does not simply convert Verilog HDL to {cpp} or SystemC. Rather,
+Verilator compiles your code into a much faster optimized and optionally
+thread-partitioned model, which is in turn wrapped inside a
+{cpp}/SystemC/{cpp}-under-Python module. The results are a compiled
+Verilog model that executes even on a single-thread over 10x faster than
+standalone SystemC, and on a single thread is about 100 times faster than
+interpreted Verilog simulators such as http://iverilog.icarus.com[Icarus
Verilog]. Another 2-10x speedup might be gained from multithreading
(yielding 200-1000x total over interpreted simulators).
-Verilator has typically similar or better performance versus the commercial
-Verilog simulators (Carbon Design Systems Carbonator, Modelsim, Cadence
-Incisive/NC-Verilog, Synopsys VCS, VTOC, and Pragmatic CVer/CVC). But,
-Verilator is free, so you can spend on computes rather than licenses. Thus
-Verilator gives you more cycles/dollar than anything else available.
+Verilator has typically similar or better performance versus the
+closed-source Verilog simulators (Carbon Design Systems Carbonator,
+Modelsim, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and Pragmatic
+CVer/CVC). But, Verilator is open-sourced, so you can spend on computes
+rather than licenses. Thus Verilator gives you the best cycles/dollar.
For more information on how Verilator stacks up to some of the other
-commercial and free Verilog simulators, see the
+closed-sourced and open-sourced Verilog simulators, see the
https://www.veripool.org/verilog_sim_benchmarks.html[Verilog Simulator
Benchmarks]. (If you benchmark Verilator, please see the notes in the
https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)], and also
diff --git a/bin/verilator b/bin/verilator
index 68c42e97e..2d3c6c538 100755
--- a/bin/verilator
+++ b/bin/verilator
@@ -184,11 +184,14 @@ sub run {
if (($status & 127) == 4 # SIGILL
|| ($status & 127) == 8 # SIGFPA
|| ($status & 127) == 11) { # SIGSEGV
- warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
+ warn "%Error: Verilator internal fault, sorry. "
+ ."Suggest trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 127) == 6) { # SIGABRT
- warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
+ warn "%Error: Verilator aborted. "
+ ."Suggest trying --debug --gdbbt\n" if !$Debug;
} else {
- warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
+ warn "%Error: Verilator threw signal $status. "
+ ."Suggest trying --debug --gdbbt\n" if !$Debug;
}
}
if (!$opt_quiet_exit && ($status != 256 || $Debug)) { # i.e. not normal exit(1)
@@ -271,11 +274,12 @@ detailed descriptions in L"VERILATION ARGUMENTS"> for more information.
--bbox-sys Blackbox unknown $system calls
--bbox-unsup Blackbox unsupported language features
--bin Override Verilator binary
+ --build Build model executable/library after Verilation
-CFLAGS C++ Compiler flags for makefile
--cc Create C++ output
--cdc Clock domain crossing analysis
--clk Mark specified signal as clock
- --make Generate scripts for specified make system
+ --make Generate scripts for specified build tool
--compiler Tune for specified C++ compiler
--converge-limit Tune convergence settle time
--coverage Enable all coverage
@@ -302,6 +306,7 @@ detailed descriptions in L"VERILATION ARGUMENTS"> for more information.
-F Parse options from a file, relatively
-f Parse options from a file
-FI Force include of a file
+ --flatten Force inlining of all modules, tasks and functions
-G= Overwrite toplevel parameter
--gdb Run Verilator under GDB interactively
--gdbbt Run Verilator under GDB for backtrace
@@ -309,6 +314,7 @@ detailed descriptions in L"VERILATION ARGUMENTS"> for more information.
--getenv Get environment variable with defaults
--help Display this help
-I Directory to search for includes
+ -j Parallelism for --build
--gate-stmts Tune gate optimizer depth
--if-depth Tune IFDEPTH warning
+incdir+ Directory to search for includes
@@ -319,6 +325,7 @@ detailed descriptions in L"VERILATION ARGUMENTS"> for more information.
--language Default language standard to parse
+libext++[ext]... Extensions for finding modules
--lint-only Lint, but do not make output
+ -MAKEFLAGS Options to make during --build
--max-num-width Maximum number width (default: 64K)
--MMD Create .d dependency files
--MP Create phony dependency targets
@@ -334,6 +341,7 @@ detailed descriptions in L"VERILATION ARGUMENTS"> for more information.
-O Selectable optimizations
-o Name of final executable
--no-order-clock-delay Disable ordering clock enable assignments
+ --no-verilate Skip verilation and just compile previously verilated code.
--output-split Split .cpp files into pieces
--output-split-cfuncs Split .cpp functions
--output-split-ctrace Split tracing functions
@@ -368,16 +376,18 @@ detailed descriptions in L"VERILATION ARGUMENTS"> for more information.
--threads Enable multithreading
--threads-dpi Enable multithreaded DPI
--threads-max-mtasks Tune maximum mtask partitioning
+ --timescale Sets default timescale
+ --timescale-override Overrides all timescales
--top-module Name of top level input module
--trace Enable waveform creation
- --trace-depth Depth of tracing
--trace-coverage Enable tracing of coverage
+ --trace-depth Depth of tracing
--trace-fst Enable FST waveform creation
- --trace-fst-thread Enable FST threaded waveform creation
--trace-max-array Maximum bit width for tracing
--trace-max-width Maximum array depth for tracing
--trace-params Enable tracing of parameters
--trace-structs Enable tracing structure names
+ --trace-threads Enable waveform creation on separate threads
--trace-underscore Enable tracing of _signals
-U Undefine preprocessor define
--unroll-count Tune maximum loop iterations
@@ -515,6 +525,8 @@ unsized zero. Arguments to such functions will be parsed, but not
otherwise checked. This prevents errors when linting in the presence of
company specific PLI calls.
+Using this argument will likely cause incorrect simulation.
+
=item --bbox-unsup
Black box some unsupported language features, currently UDP tables, the
@@ -522,6 +534,8 @@ cmos and tran gate primitives, deassign statements, and mixed edge errors.
This may enable linting the rest of the design even when unsupported
constructs are present.
+Using this argument will likely cause incorrect simulation.
+
=item --bin I
Rarely needed. Override the default filename for Verilator itself. When a
@@ -529,6 +543,13 @@ dependency (.d) file is created, this filename will become a source
dependency, such that a change in this binary will have make rebuild the
output files.
+=item --build
+
+After generating the SystemC/C++ code, Verilator will invoke the toolchain to
+build the model library (and executable when C<--exe> is also used). Verilator
+manages the build itself, and for this --build requires GNU Make to be
+available on the platform.
+
=item -CFLAGS I
Add specified C compiler flag to the generated makefiles. For multiple
@@ -574,12 +595,17 @@ If clock signals are assigned to vectors and then later used individually,
Verilator will attempt to decompose the vector and connect the single-bit
clock signals directly. This should be transparent to the user.
-=item --make I
+=item --make I
-Generates a script for the specified make system.
+Generates a script for the specified build tool.
-Supported make systems are gmake and cmake. Both can be specified.
-If no make system is specified, gmake is assumed.
+Supported values are C for GNU Make and C for CMake. Both can be
+specified together. If no build tool is specified, gmake is assumed. The
+executable of gmake can be configured via environment variable "MAKE".
+
+When using --build Verilator takes over the responsibility of building the
+model library/executable. For this reason --make cannot be specified when
+using --build.
=item --compiler I
@@ -829,6 +855,12 @@ specified file might be used to contain define prototypes of custom
VL_VPRINTF functions, and may need to include verilatedos.h as this file is
included before any other standard includes.
+=item --flatten
+
+Force flattening of the design's hierarchy, with all modules, tasks and
+functions inlined. Typically used with C<--xml-only>. Note flattening
+large designs may require significant CPU time, memory and storage.
+
=item -GI=I
Overwrites the given parameter of the toplevel module. The value is limited
@@ -921,6 +953,14 @@ values, or a value < 1 will inline everything, will lead to longer compile
times, but potentially faster simulation runtimes. This setting is ignored
for very small modules; they will always be inlined, if allowed.
+=item -j
+
+Specify the level of parallelism for --build. must be a positive
+integer specifying the maximum number of parallel build jobs, or can be
+omitted. When is omitted, the build will not try to limit the number of
+parallel build jobs but attempt to execute all independent build steps in
+parallel.
+
=item -LDFLAGS I
Add specified C linker flags to the generated makefiles. For multiple
@@ -966,6 +1006,14 @@ stylistic and not enabled by default.
If the design is not to be completely Verilated see also the --bbox-sys and
--bbox-unsup options.
+=item -MAKEFLAGS
+
+When using --build, add the specified flag to the invoked make command line.
+For multiple flags either pass them as a single argument with space separators
+quoted in the shell (e.g. C<-MAKEFLAGS "-a -b">), or use multiple -MAKEFLAGS
+arguments (e.g. C<-MAKEFLAGS -l -MAKEFLAGS -k>). Use of this option should not
+be required for simple builds using the host toolchain.
+
=item --max-num-width I
Set the maximum number literal width (e.g. in 1024'd22 this it the 1024).
@@ -1080,7 +1128,8 @@ design --output-split 20000 resulted in splitting into approximately
one-minute-compile chunks.
Typically when using this, make with VM_PARALLEL_BUILDS=1 (set for you if
-using the default makefiles), and use I.
+using the default makefiles), and use I (set for you if present at
+configure time).
=item --output-split-cfuncs I
@@ -1236,6 +1285,10 @@ This allows for the secure delivery of sensitive IP without the need for
encrypted RTL (i.e. IEEE P1735). See examples/make_protect_lib in the
distribution for a demonstration of how to build and use the DPI library.
+When using --protect-lib it is advised to also use C<--timescale-override
+/1fs> to ensure the model has a time resolution that is always compatible
+with the time precision of the upper instantiating module.
+
=item --private
Opposite of --public. Is the default; this option exists for backwards
@@ -1394,6 +1447,24 @@ Rarely needed. When using --threads, specify the number of mtasks the
model is to be partitioned into. If unspecified, Verilator approximates a
good value.
+=item --timescale I/I
+
+Sets default timescale, timeunit and timeprecision for when `timescale does
+not occur in sources. Default is "1ps/1ps" (to match SystemC). This is
+overriden by C<--timescale-override>.
+
+=item --timescale-override I/I
+
+=item --timescale-override /I
+
+Overrides all `timescales in sources. The timeunit may be left empty to
+specify only to override the timeprecision, e.g. "/1fs".
+
+The time precision must be consistent with SystemC's
+sc_set_time_resolution, or the C++ code instantiating the Verilated module.
+As 1fs is the finest time precision it may be desirable to always use a
+precision of 1fs.
+
=item --top-module I
When the input Verilog contains more than one top level module, specifies
@@ -1416,6 +1487,8 @@ need to add these to your Makefile manually.
Having tracing compiled in may result in some small performance losses,
even when waveforms are not turned on during model execution.
+See also C<--trace-threads>.
+
=item --trace-coverage
With --trace and --coverage-*, enable tracing to include a traced signal
@@ -1437,14 +1510,8 @@ improve simulation runtime and trace file size.
=item --trace-fst
-Enable FST waveform tracing in the model. This overrides C<--trace> and
-C<--trace-fst-thread>. See also C<--trace-fst-thread>.
-
-=item --trace-fst-thread
-
-Enable FST waveform tracing in the model, using a separate thread. This is
-typically faster in simulation runtime but slower in total computes than
-C<--trace-fst>. This overrides C<--trace> and C<--trace-fst>.
+Enable FST waveform tracing in the model. This overrides C<--trace>.
+See also C<--trace-threads>.
=item --trace-max-array I
@@ -1469,6 +1536,15 @@ array fields, rather than a single combined packed bus. Due to VCD file
format constraints this may result in significantly slower trace times and
larger trace files.
+=item --trace-threads I
+
+Enable waveform tracing using separate threads. This is typically faster in
+simulation runtime but uses more total compute. This option is independend of,
+and works with, both C<--trace> and C<--trace-fst>. Different trace formats can
+take advantage of more trace threads to varying degrees. Currently VCD tracing
+can utilize at most --trace-threads 1, and FST tracing can utilize at most
+--trace-threads 2. This overrides C<--no-threads>.
+
=item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these
@@ -1505,6 +1581,12 @@ Read the filename as a Verilog library. Any modules in the file may be
used to resolve cell instantiations in the top level module, else ignored.
Note -v is fairly standard across Verilog tools.
+=item --no-verilate
+
+When using --build, disable generation of C++/SC code, and execute only the
+build. This can be useful for rebuilding verilated code produced by a previous
+invocation of Verilator.
+
=item +verilog1995ext+I
=item +verilog2001ext+I
@@ -1752,10 +1834,10 @@ Defaults to "profile_threads.dat".
=item +verilator+prof+threads+start+I
When using --prof-threads at simulation runtime, Verilator will wait until
-$time is at this value, then start the profiling warmup, then
-capturing. Generally this should be set to some time that is well within
-the normal operation of the simulation, i.e. outside of reset. If 0, the
-dump is disabled. Defaults to 1.
+$time is at this value (expressed in units of the time precision), then
+start the profiling warmup, then capturing. Generally this should be set to
+some time that is well within the normal operation of the simulation,
+i.e. outside of reset. If 0, the dump is disabled. Defaults to 1.
=item +verilator+prof+threads+window+I
@@ -1833,20 +1915,17 @@ compiled Verilator, you need to point to the kit:
Now we run Verilator on our little example.
- verilator -Wall --cc our.v --exe sim_main.cpp
+ verilator -Wall --cc our.v --exe --build sim_main.cpp
We can see the source code under the "obj_dir" directory. See the FILES
section below for descriptions of some of the files that were created.
ls -l obj_dir
-We then can compile it
-
- make -j -C obj_dir -f Vour.mk Vour
-
(Verilator included a default compile rule and link rule, since we used
---exe and passed a .cpp file on the Verilator command line. You can also
-write your own compile rules, as we'll show in the SYSTEMC section.)
+--exe and passed a .cpp file on the Verilator command line. Verilator also
+then used C 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.)
And now we run it
@@ -2001,18 +2080,18 @@ OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
the compiler or linker. Or, just for one run, pass them on the command
line to make:
- make OPT_FAST="-Os -fno-stack-protector" -f Vour.mk Vour__ALL.a
+ make OPT_FAST="-Os -march=native -fno-stack-protector" -f Vour.mk Vour__ALL.a
OPT_FAST specifies optimizations for those programs that are part of the
fast path, mostly code that is executed every cycle. OPT_SLOW specifies
optimizations for slow-path files (plus tracing), which execute only
rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those
-OPT_FAST and OPT_SLOW control. For best results, use OPT="-Os", and link
-with "-static". Nearly the same results can be had with much better
-compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
-such as "-O2" or "-O3" may help, but gcc compile times may be excessive
-under O3 on even medium sized designs.
+OPT_FAST and OPT_SLOW control. For best results, use OPT="-Os
+-march=native", and link with "-static". Nearly the same results can be
+had with much better compile times with OPT_FAST="-O1 -fstrict-aliasing".
+Higher optimization such as "-O2" or "-O3" may help, but gcc compile times
+may be excessive under O3 on even medium sized designs.
Unfortunately, using the optimizer with SystemC files can result in
compiles taking several minutes. (The SystemC libraries have many little
@@ -2105,9 +2184,8 @@ After running Make, the C++ compiler may produce the following:
{mod_prefix}{misc}.o // Intermediate objects
{prefix} // Final executable (w/--exe argument)
{prefix}__ALL.a // Library of all Verilated objects
- {prefix}__ALLboth.cpp // Include of classes for single compile
- {prefix}__ALLcls.cpp // Include of user classes for single compile
- {prefix}__ALLsup.cpp // Include of support files for single compile
+ {prefix}__ALLfast.cpp // Include of hot code for single compile
+ {prefix}__ALLslow.cpp // Include of slow code for single compile
{prefix}{misc}.d // Intermediate dependencies
{prefix}{misc}.o // Intermediate objects
@@ -2122,12 +2200,19 @@ A generic Linux/OS variable specifying what directories have shared object
(.so) files. This path should include SystemC and any other shared objects
needed at simulation runtime.
+=item MAKE
+
+Names the executable of the make command invoked when using the --build option.
+Some operating systems may require "gmake" to this variable to launch GNU make.
+If this variable is not specified, "make" is used.
+
=item OBJCACHE
Optionally specifies a caching or distribution program to place in front of
-all runs of the C++ Compiler. For example, "objcache --read --write", or
-"ccache". If using distcc or icecc/icecream, they would generally be run
-under either objcache or ccache; see the documentation for those programs.
+all runs of the C++ compiler. For example, "ccache". If using distcc or
+icecc/icecream, they would generally be run under cache; see the
+documentation for those programs. If OBJCACHE is not set, and at configure
+time ccache was present, ccache will be used as a default.
=item SYSTEMC
@@ -2212,7 +2297,8 @@ example:
vluint64_t main_time = 0; // Current simulation time
// This is a 64-bit integer to reduce wrap over issues and
- // allow modulus. You can also use a double, if you wish.
+ // allow modulus. This is in units of the timeprecision
+ // used in Verilog (or from --timescale-override)
double sc_time_stamp () { // Called by $time in Verilog
return main_time; // converts to double, to match
@@ -2683,8 +2769,8 @@ underneath NC:
cd obj_dir
ncsc_run \
sc_main.cpp \
- Vour__ALLcls.cpp \
- Vour__ALLsup.cpp \
+ Vour__ALLfast.cpp \
+ Vour__ALLslow.cpp \
verilated.cpp
For larger designs you'll want to automate this using makefiles, which pull
@@ -2704,7 +2790,7 @@ performance.
With --threads 1, the generated model is single threaded, however the
support libraries are multithread safe. This allows different
instantiations of model(s) to potentially each be run under a different
-thread. All threading is the responsibility of the user's C++ testbench.
+thread. All threading is the responsibility of the user's C++ testbench.
With --threads N, where N is at least 2, the generated model will be
designed to run in parallel on N threads. The thread calling eval()
@@ -2715,9 +2801,6 @@ Verilated model should not livelock nor deadlock, however, you can expect
performance to be far worse than it would be with proper ratio of
threads and CPU cores.
-With --trace-fst-thread, tracing occurs in a separate thread from the main
-simulation thread(s). This option is orthogonal to --threads.
-
The remainder of this section describe behavior with --threads 1 or
--threads N (not --no-threads).
@@ -2731,12 +2814,28 @@ be done by a "main thread". In most cases the eval thread and main thread
are the same thread (i.e. the user's top C++ testbench runs on a single
thread), but this is not required.
+The --trace-threads options can be used to produce trace dumps using multiple
+threads. If --trace-threads is set without --threads, then --trace-threads will
+imply --threads 1, i.e.: the support libraries will be thread safe.
+
+With --trace-threads 0, trace dumps are produced on the main thread. This again
+gives the highest single thread performance.
+
+With --trace-threads N, where N is at least 1, N additional threads will be
+created and managed by the trace files (e.g.: VerilatedVcdC or VerilatedFstC),
+to generate the trace dump. The main thread will be released to proceed with
+execution as soon as possible, though some blocking of the main thread is still
+necessary while capturing the trace. Different trace formats can utilize a
+various number of threads. See the --trace-threads option.
+
When running a multithreaded model, the default Linux task scheduler often
works against the model, by assuming threads are short lived, and thus
often schedules threads using multiple hyperthreads within the same
physical core. For best performance use the C program to (when the
-threading count fits) select unique physical cores on the same socket. For
-example, if a model was Verilated with "--threads 4", we consult
+threading count fits) select unique physical cores on the same socket. The
+same applies for --trace-threads as well.
+
+As an example, if a model was Verilated with "--threads 4", we consult
egrep 'processor|physical id|core id' /proc/cpuinfo
@@ -3558,6 +3657,12 @@ ___05F (5F is the hex code of an underscore.)
Verilator only supports "bind" to a target module name, not an instance
path.
+=head2 Class
+
+Verilator class support is very limited and in active development.
+Verilator supports members, and methods. Verilator doe not support class
+static members, class extend, or class parameters.
+
=head2 Dotted cross-hierarchy references
Verilator supports dotted references to variables, functions and tasks in
@@ -3744,7 +3849,7 @@ This section describes specific limitations for each language keyword.
`begin_keywords, `begin_keywords, `define, `else, `elsif, `end_keywords,
`endif, `error, `ifdef, `ifndef, `include, `line, `systemc_ctor,
`systemc_dtor, `systemc_header, `systemc_imp_header,
-`systemc_implementation, `systemc_interface, `timescale, `undef, `verilog
+`systemc_implementation, `systemc_interface, `undef, `verilog
Fully supported.
@@ -3860,7 +3965,8 @@ $dumplimit/$dumpportlimit are currently ignored.
The rarely used optional parameter to $finish and $stop is ignored.
-=item $fopen, $fclose, $fdisplay, $feof, $fflush, $fgetc, $fgets, $fscanf, $fwrite
+=item $fopen, $fclose, $fdisplay, $ferror, $feof, $fflush, $fgetc, $fgets,
+$fscanf, $fwrite
File descriptors passed to the file PLI calls must be file descriptors, not
MCDs, which includes the mode parameter to $fopen being mandatory.
@@ -3895,13 +4001,6 @@ Supported, but the instantiating C++/SystemC testbench must call
to register the command line before calling $test$plusargs or
$value$plusargs.
-=item $timeformat
-
-Not supported as Verilator needs to determine all formatting at compile
-time. Generally you can just ifdef them out for no ill effect. Note also
-VL_TIME_MULTIPLIER can be defined at compile time to move the decimal point
-when displaying all times, model wide.
-
=back
@@ -4574,6 +4673,18 @@ increases.
Ignoring this warning will only slow simulations, it will simulate
correctly.
+=item TIMESCALEMOD
+
+Error that `timescale is used in some but not all modules.
+Recommend using --timescale argument, or in front of all modules use:
+
+ `include "timescale.vh"
+
+Then in that file set the timescale.
+
+This is an error due to IEEE specifications, but it may be disabled similar
+to warnings. Ignoring this error may result in a module having an
+unexpected timescale.
=item UNDRIVEN
@@ -4809,10 +4920,12 @@ configured with --enable-prec11. This flag will be removed and C++11
compilers will be required for both compiling Verilator and compiling
Verilated models no sooner than September 2020.
-=item SystemC 2.1 and earlier support
+=item SystemC 2.2 and earlier support
-Support for SystemC versions 2.1 and earlier and the related sc_clock
-variable attribute will be removed no sooner than July 2020.
+Support for SystemC versions 2.2 and earlier including the related sc_clock
+variable attribute will be removed no sooner than August 2020. The
+supported versions will be SystemC 2.3.0 (SYSTEMC_VERSION 20111121) and
+later (presently 2.3.0, 2.3.1, 2.3.2, 2.3.3).
=item Configuration File -msg
@@ -4961,8 +5074,8 @@ to VerilatedVcdSc in the examples/make_tracing_sc/sc_main.cpp file of the
distribution, and below.
Alternatively you may use the C++ trace mechanism described in the previous
-question, however the timescale and timeprecision will not inherited from
-your SystemC settings.
+question, note the timescale and timeprecision will be inherited from your
+SystemC settings.
You also need to compile verilated_vcd_sc.cpp and verilated_vcd_c.cpp and
add them to your link, preferably by adding the dependencies in
@@ -4972,6 +5085,12 @@ using the Verilator --exe flag.
Note you can also call ->trace on multiple Verilated objects with the same
trace file if you want all data to land in the same output file.
+When using SystemC 2.3, the SystemC library must have been built with the
+experiemntal simulation phase callback based tracing disabled. This is
+disabled by default when building SystemC with its configure based build
+system, but when building SystemC with CMake, you must pass
+-DENABLE_PHASE_CALLBACKS_TRACING=OFF to disable this feature.
+
#include "verilated_vcd_sc.h"
...
int main(int argc, char** argv, char** env) {
@@ -5128,9 +5247,9 @@ now relatively old GCC 3.0 to 3.3 being horrible.
Compile in parallel on many machines and use caching; see the web for the
ccache, distcc and icecream packages. ccache will skip GCC runs between
-identical source builds, even across different users. You can use the
-OBJCACHE environment variable to use these CC wrappers. Also see the
---output-split option.
+identical source builds, even across different users. If ccache was
+installed when Verilator was built it is used, or see OBJCACHE environment
+variable to override this. Also see the --output-split option.
To reduce the compile time of classes that use a Verilated module (e.g. a
top CPP file) you may wish to add /*verilator no_inline_module*/ to your
@@ -5164,17 +5283,21 @@ be accessing with a /*verilator public*/ comment before the closing
semicolon. Then scope into the C++ class to read the value of the signal,
as you would any other member variable.
-Signals are the smallest of 8-bit chars, 16-bit shorts, 32-bit longs, or
-64-bit long longs that fits the width of the signal. Generally, you can
-use just uint32_t's for 1 to 32 bits, or vluint64_t for 1 to 64 bits, and
-the compiler will properly up-convert smaller entities.
+Signals are the smallest of 8-bit unsigned chars (equivalent to uint8_t),
+16-bit unsigned shorts (uint16_t), 32-bit unsigned longs (uint32_t), or
+64-bit unsigned long longs (uint64_t) that fits the width of the signal.
+Generally, you can use just uint32_t's for 1 to 32 bits, or vluint64_t for
+1 to 64 bits, and the compiler will properly up-convert smaller entities.
+Note even signed ports are declared as unsigned; you must sign extend
+yourself to the appropriate signal width.
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
Thus to read bits 31:0, access signal[0], and for bits 63:32, access
signal[1]. Unused bits (for example bit numbers 65-96 of a 65-bit vector)
-will always be zero. if you change the value you must make sure to pack
-zeros in the unused bits or core-dumps may result. (Because Verilator
-strips array bound checks where it believes them to be unnecessary.)
+will always be zero. If you change the value you must make sure to pack
+zeros in the unused bits or core-dumps may result, because Verilator strips
+array bound checks where it believes them to be unnecessary to improve
+performance.
In the SYSTEMC example above, if you had in our.v:
diff --git a/ci/docker/run/Dockerfile b/ci/docker/run/Dockerfile
index 315123203..e5e063a13 100644
--- a/ci/docker/run/Dockerfile
+++ b/ci/docker/run/Dockerfile
@@ -15,11 +15,13 @@ RUN apt-get update \
bison=2:3.0.4.dfsg-1build1 \
build-essential=12.4ubuntu1 \
ca-certificates=20180409 \
+ ccache \
flex=2.6.4-6 \
- git=1:2.17.1-1ubuntu0.5 \
+ git \
libfl-dev=2.6.4-6 \
- perl=5.26.1-6ubuntu0.3 \
- python3=3.6.7-1~18.04 \
+ libgoogle-perftools-dev \
+ perl \
+ python3 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
diff --git a/configure.ac b/configure.ac
index 23ec1a6e1..b21cc5868 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
-AC_INIT([Verilator],[4.032 2020-04-04],
+AC_INIT([Verilator],[4.034 2020-05-03],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file
@@ -159,6 +159,12 @@ if test "x$YACC" = "x" ; then
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
fi
+AC_CHECK_PROG(OBJCACHE,ccache,ccache)
+if test "x$OBJCACHE" != "x" ; then
+ objcache_version=$($OBJCACHE --version | head -1)
+ AC_MSG_RESULT([objcache is $OBJCACHE --version = $objcache_version])
+fi
+
# Checks for libraries.
# Checks for typedefs, structures
@@ -328,6 +334,7 @@ m4_foreach([cflag],[
[-mno-cet],
[-Qunused-arguments],
[-Wno-bool-operation],
+ [-Wno-tautological-bitwise-compare],
[-Wno-parentheses-equality],
[-Wno-sign-compare],
[-Wno-uninitialized],
diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS
index 0060aa607..9b948c0e6 100644
--- a/docs/CONTRIBUTORS
+++ b/docs/CONTRIBUTORS
@@ -1,9 +1,7 @@
The contributors listed below have certified their Verilator contributions
-under the Developer Certificate of Origin
-(https://developercertificate.org/).
+under the Developer Certificate of Origin (https://developercertificate.org/).
-Please see the Verilator manual for 200+ additional contributors. Thanks to
-all.
+Please see the Verilator manual for 200+ additional contributors. Thanks to all.
Ahmed El-Mahmoudy
Alex Chadwick
@@ -16,8 +14,10 @@ Geza Lore
Gianfranco Costamagna
Howard Su
Iztok Jeras
+James Hanlon
Jeremy Bennett
John Coiner
+John Demme
Julien Margetts
Kanad Kanhere
Kevin Kiningham
@@ -28,10 +28,14 @@ Maciej Sobkowski
Marco Widmer
Matthew Ballance
Mike Popoloski
+Nathan Kohagen
+Nathan Myers
Patrick Stewart
+Peter Horvath
Peter Monsson
Philipp Wagner
Pieter Kapsenberg
+Qingyao Sun
Richard Myers
Sean Cross
Sebastien Van Cauwenberghe
@@ -39,6 +43,7 @@ Stefan Wallentowitz
Tobias Rosenkranz
Tobias Wölfel
Todd Strader
+Veripool API Bot
Wilson Snyder
Yutetsu TAKATSUKASA
Yves Mathieu
diff --git a/docs/clang-format.txt b/docs/clang-format.txt
deleted file mode 100644
index 3a1876b64..000000000
--- a/docs/clang-format.txt
+++ /dev/null
@@ -1,159 +0,0 @@
-clang-format is used to standardize the indentation of the internal C++
-code.
-
-For the most part clang-format changes provide good consistency, the two
-main exceptions being the indentation of preprocessor directives, and
-tables of statements.
-
-Reformatting is generally performed only before other large changes are to
-be made to a file. The following files are not yet clang-format clean:
-
-clang-format -i include/verilated.h
-clang-format -i include/verilated_dpi.h
-clang-format -i include/verilated_fst_c.h
-clang-format -i include/verilated_heavy.h
-clang-format -i include/verilated_imp.h
-clang-format -i include/verilated_save.h
-clang-format -i include/verilated_sym_props.h
-clang-format -i include/verilated_unordered_set_map.h
-clang-format -i include/verilated_vcd_c.h
-clang-format -i include/verilatedos.h
-
-clang-format -i include/verilated.cpp
-clang-format -i include/verilated_cov.cpp
-clang-format -i include/verilated_dpi.cpp
-clang-format -i include/verilated_fst_c.cpp
-clang-format -i include/verilated_save.cpp
-clang-format -i include/verilated_threads.cpp
-clang-format -i include/verilated_vcd_c.cpp
-clang-format -i include/verilated_vpi.cpp
-
-clang-format -i src/V3Ast.h
-clang-format -i src/V3AstNodes.h
-clang-format -i src/V3EmitCBase.h
-clang-format -i src/V3Error.h
-clang-format -i src/V3File.h
-clang-format -i src/V3FileLine.h
-clang-format -i src/V3Global.h
-clang-format -i src/V3Graph.h
-clang-format -i src/V3GraphDfa.h
-clang-format -i src/V3GraphStream.h
-clang-format -i src/V3Hashed.h
-clang-format -i src/V3LanguageWords.h
-clang-format -i src/V3LinkDot.h
-clang-format -i src/V3List.h
-clang-format -i src/V3Number.h
-clang-format -i src/V3Options.h
-clang-format -i src/V3OrderGraph.h
-clang-format -i src/V3Os.h
-clang-format -i src/V3ParseImp.h
-clang-format -i src/V3ParseSym.h
-clang-format -i src/V3Partition.h
-clang-format -i src/V3PartitionGraph.h
-clang-format -i src/V3PreLex.h
-clang-format -i src/V3PreProc.h
-clang-format -i src/V3Scoreboard.h
-clang-format -i src/V3SenTree.h
-clang-format -i src/V3Simulate.h
-clang-format -i src/V3Stats.h
-clang-format -i src/V3String.h
-clang-format -i src/V3SymTable.h
-clang-format -i src/V3TSP.h
-clang-format -i src/V3Task.h
-clang-format -i src/V3WidthCommit.h
-
-clang-format -i src/V3Active.cpp
-clang-format -i src/V3ActiveTop.cpp
-clang-format -i src/V3Assert.cpp
-clang-format -i src/V3AssertPre.cpp
-clang-format -i src/V3Ast.cpp
-clang-format -i src/V3AstNodes.cpp
-clang-format -i src/V3Begin.cpp
-clang-format -i src/V3Branch.cpp
-clang-format -i src/V3Broken.cpp
-clang-format -i src/V3CCtors.cpp
-clang-format -i src/V3Case.cpp
-clang-format -i src/V3Cast.cpp
-clang-format -i src/V3Cdc.cpp
-clang-format -i src/V3Changed.cpp
-clang-format -i src/V3Clean.cpp
-clang-format -i src/V3Clock.cpp
-clang-format -i src/V3Combine.cpp
-clang-format -i src/V3Const.cpp
-clang-format -i src/V3Coverage.cpp
-clang-format -i src/V3CoverageJoin.cpp
-clang-format -i src/V3Dead.cpp
-clang-format -i src/V3Delayed.cpp
-clang-format -i src/V3Depth.cpp
-clang-format -i src/V3DepthBlock.cpp
-clang-format -i src/V3EmitC.cpp
-clang-format -i src/V3EmitCInlines.cpp
-clang-format -i src/V3EmitCMake.cpp
-clang-format -i src/V3EmitCSyms.cpp
-clang-format -i src/V3EmitMk.cpp
-clang-format -i src/V3EmitV.cpp
-clang-format -i src/V3EmitXml.cpp
-clang-format -i src/V3Error.cpp
-clang-format -i src/V3Expand.cpp
-clang-format -i src/V3File.cpp
-clang-format -i src/V3FileLine.cpp
-clang-format -i src/V3Gate.cpp
-clang-format -i src/V3GenClk.cpp
-clang-format -i src/V3Graph.cpp
-clang-format -i src/V3GraphAcyc.cpp
-clang-format -i src/V3GraphAlg.cpp
-clang-format -i src/V3GraphDfa.cpp
-clang-format -i src/V3GraphPathChecker.cpp
-clang-format -i src/V3GraphTest.cpp
-clang-format -i src/V3Hashed.cpp
-clang-format -i src/V3Inline.cpp
-clang-format -i src/V3Inst.cpp
-clang-format -i src/V3InstrCount.cpp
-clang-format -i src/V3Life.cpp
-clang-format -i src/V3LifePost.cpp
-clang-format -i src/V3LinkCells.cpp
-clang-format -i src/V3LinkDot.cpp
-clang-format -i src/V3LinkJump.cpp
-clang-format -i src/V3LinkLValue.cpp
-clang-format -i src/V3LinkLevel.cpp
-clang-format -i src/V3LinkParse.cpp
-clang-format -i src/V3LinkResolve.cpp
-clang-format -i src/V3Localize.cpp
-clang-format -i src/V3Name.cpp
-clang-format -i src/V3Number.cpp
-clang-format -i src/V3Number_test.cpp
-clang-format -i src/V3Options.cpp
-clang-format -i src/V3Order.cpp
-clang-format -i src/V3Os.cpp
-clang-format -i src/V3Param.cpp
-clang-format -i src/V3ParseGrammar.cpp
-clang-format -i src/V3ParseImp.cpp
-clang-format -i src/V3ParseLex.cpp
-clang-format -i src/V3Partition.cpp
-clang-format -i src/V3PreProc.cpp
-clang-format -i src/V3PreShell.cpp
-clang-format -i src/V3Premit.cpp
-clang-format -i src/V3ProtectLib.cpp
-clang-format -i src/V3Reloop.cpp
-clang-format -i src/V3Scope.cpp
-clang-format -i src/V3Scoreboard.cpp
-clang-format -i src/V3Slice.cpp
-clang-format -i src/V3Split.cpp
-clang-format -i src/V3SplitAs.cpp
-clang-format -i src/V3SplitVar.cpp
-clang-format -i src/V3Stats.cpp
-clang-format -i src/V3StatsReport.cpp
-clang-format -i src/V3String.cpp
-clang-format -i src/V3Subst.cpp
-clang-format -i src/V3TSP.cpp
-clang-format -i src/V3Table.cpp
-clang-format -i src/V3Task.cpp
-clang-format -i src/V3Trace.cpp
-clang-format -i src/V3TraceDecl.cpp
-clang-format -i src/V3Tristate.cpp
-clang-format -i src/V3Undriven.cpp
-clang-format -i src/V3Unknown.cpp
-clang-format -i src/V3Unroll.cpp
-clang-format -i src/V3Width.cpp
-clang-format -i src/V3WidthSel.cpp
-clang-format -i src/Verilator.cpp
diff --git a/docs/install.adoc b/docs/install.adoc
index 8add7f3c1..094661f3e 100644
--- a/docs/install.adoc
+++ b/docs/install.adoc
@@ -78,17 +78,7 @@ MSVC++.
=== Install Prerequisites
-To build Verilator you will need to install some standard packages:
-
- sudo apt-get install git
- sudo apt-get install autoconf
- sudo apt-get install flex bison
-
-The following are optional, but improve compilation speed:
-
- sudo apt-get install libgoogle-perftools-dev
-
-Additionally, to build or run Verilator you need these standard packages:
+To build or run Verilator you need these standard packages:
sudo apt-get install perl python3
sudo apt-get install make
@@ -96,9 +86,21 @@ Additionally, to build or run Verilator you need these standard packages:
sudo apt-get install libgz # Non-Ubuntu (ignore if gives error)
sudo apt-get install libfl2 libfl-dev zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
-Those developing Verilator may also want these (see internals.adoc):
+To build or run the following are optional but should be installed for
+good performance:
- sudo apt-get install gdb asciidoctor graphviz cmake
+ sudo apt-get install ccache # If present at build, needed for run
+ sudo apt-get install libgoogle-perftools-dev numactl
+
+To build Verilator you will need to install these packages; these do not
+need to be present to run Verilator:
+
+ sudo apt-get install git
+ sudo apt-get install autoconf flex bison
+
+Those developing Verilator itself may also want these (see internals.adoc):
+
+ sudo apt-get install gdb asciidoctor graphviz cmake clang-format
cpan install Pod::Perldoc
cpan install Unix::Processors
cpan install Parallel::Forker
diff --git a/docs/internals.adoc b/docs/internals.adoc
index eec37389c..0a11bc295 100644
--- a/docs/internals.adoc
+++ b/docs/internals.adoc
@@ -405,6 +405,15 @@ This sets indentation to the `cc-mode` defaults. (Verilator predates a
CC-mode change of several years ago which overrides the defaults with GNU
style indentation; the `c-set-style` undoes that.)
+* Use "mixedCapsSymbols" instead of "underlined_symbols".
+
+* Uas a "p" suffix on variables that are pointers, e.g. "nodep".
+
+* Comment every member variable.
+
+Indentation is automatically maintained with "make clang-format" (using
+clang-format version 10.0.0). For those manually formatting:
+
* Use 4 spaces per level, and no tabs.
* Use 2 spaces between the end of source and the beginning of a comment.
@@ -414,12 +423,6 @@ style indentation; the `c-set-style` undoes that.)
* No spaces before semicolons, nor between a function's name and open
parenthesis (only applies to functions; if/else has a following space).
-* Use "mixedCapsSymbols" instead of "underlined_symbols".
-
-* Uas a "p" suffix on variables that are pointers, e.g. "nodep".
-
-* Comment every member variable.
-
=== The `astgen` Script
Some of the code implementing passes is extremely repetitive, and must be
diff --git a/docs/xml.adoc b/docs/xml.adoc
index 3dabedc02..0189b44cf 100644
--- a/docs/xml.adoc
+++ b/docs/xml.adoc
@@ -21,7 +21,7 @@ parser.
== Structure
-The XML document is consists of 4 sections within the top level `verilator_xml`
+The XML document consists of 4 sections within the top level `verilator_xml`
element:
``...``::
diff --git a/examples/cmake_hello_c/Makefile b/examples/cmake_hello_c/Makefile
index 2e3120f65..03740f816 100644
--- a/examples/cmake_hello_c/Makefile
+++ b/examples/cmake_hello_c/Makefile
@@ -51,11 +51,11 @@ run:
@echo "-- Verilator CMake hello world example"
@echo
- @echo "-- CMake ----------------"
+ @echo "-- VERILATE ----------------"
mkdir -p build && cd build && cmake ..
@echo
- @echo "-- COMPILE -----------------"
+ @echo "-- BUILD -------------------"
cmake --build build
@echo
diff --git a/examples/cmake_hello_sc/Makefile b/examples/cmake_hello_sc/Makefile
index b63fe2d4b..c9405ce09 100644
--- a/examples/cmake_hello_sc/Makefile
+++ b/examples/cmake_hello_sc/Makefile
@@ -87,11 +87,11 @@ run:
@echo "-- Verilator CMake SystemC hello-world simple example"
@echo
- @echo "-- CMake ----------------"
+ @echo "-- VERILATE ----------------"
mkdir -p build && cd build && cmake ..
@echo
- @echo "-- COMPILE -----------------"
+ @echo "-- BUILD -------------------"
cmake --build build
@echo
diff --git a/examples/cmake_protect_lib/Makefile b/examples/cmake_protect_lib/Makefile
index 2e08b2a9a..6f43eab02 100644
--- a/examples/cmake_protect_lib/Makefile
+++ b/examples/cmake_protect_lib/Makefile
@@ -51,11 +51,11 @@ run:
@echo "-- Verilator CMake protect_lib example"
@echo
- @echo "-- CMake ----------------"
+ @echo "-- VERILATE ----------------"
mkdir -p build && cd build && cmake ..
@echo
- @echo "-- COMPILE -----------------"
+ @echo "-- BUILD -------------------"
cmake --build build
@echo
diff --git a/examples/cmake_tracing_c/Makefile b/examples/cmake_tracing_c/Makefile
index fe61cc730..14a518002 100644
--- a/examples/cmake_tracing_c/Makefile
+++ b/examples/cmake_tracing_c/Makefile
@@ -51,11 +51,11 @@ run:
@echo "-- Verilator CMake tracing example"
@echo
- @echo "-- CMake ----------------"
+ @echo "-- VERILATE ----------------"
mkdir -p build && cd build && cmake ..
@echo
- @echo "-- COMPILE -----------------"
+ @echo "-- BUILD -------------------"
cmake --build build
@echo
diff --git a/examples/cmake_tracing_sc/Makefile b/examples/cmake_tracing_sc/Makefile
index 6332ed2d5..fe59d8a16 100644
--- a/examples/cmake_tracing_sc/Makefile
+++ b/examples/cmake_tracing_sc/Makefile
@@ -87,11 +87,11 @@ run:
@echo "-- Verilator CMake SystemC tracing example"
@echo
- @echo "-- CMake ----------------"
+ @echo "-- VERILATE ----------------"
mkdir -p build && cd build && cmake ..
@echo
- @echo "-- COMPILE -----------------"
+ @echo "-- BUILD -------------------"
cmake --build build
@echo
diff --git a/examples/make_hello_c/Makefile b/examples/make_hello_c/Makefile
index 940c0bf25..2130e9756 100644
--- a/examples/make_hello_c/Makefile
+++ b/examples/make_hello_c/Makefile
@@ -36,10 +36,8 @@ endif
default:
@echo "-- Verilator hello-world simple example"
- @echo "-- VERILATE ----------------"
- $(VERILATOR) -cc --exe top.v sim_main.cpp
- @echo "-- COMPILE -----------------"
- $(MAKE) -j 4 -C obj_dir -f Vtop.mk
+ @echo "-- VERILATE & BUILD --------"
+ $(VERILATOR) -cc --exe --build -j top.v sim_main.cpp
@echo "-- RUN ---------------------"
obj_dir/Vtop
@echo "-- DONE --------------------"
diff --git a/examples/make_hello_sc/Makefile b/examples/make_hello_sc/Makefile
index dc074b90e..3a4340017 100644
--- a/examples/make_hello_sc/Makefile
+++ b/examples/make_hello_sc/Makefile
@@ -45,10 +45,8 @@ endif
run:
@echo "-- Verilator hello-world simple example"
- @echo "-- VERILATE ----------------"
- $(VERILATOR) -sc --exe top.v sc_main.cpp
- @echo "-- COMPILE -----------------"
- $(MAKE) -j 4 -C obj_dir -f Vtop.mk
+ @echo "-- VERILATE & COMPILE ------"
+ $(VERILATOR) -sc --exe --build -j top.v sc_main.cpp
@echo "-- RUN ---------------------"
obj_dir/Vtop
@echo "-- DONE --------------------"
diff --git a/examples/make_hello_sc/sc_main.cpp b/examples/make_hello_sc/sc_main.cpp
index 12848e35b..131527f5f 100644
--- a/examples/make_hello_sc/sc_main.cpp
+++ b/examples/make_hello_sc/sc_main.cpp
@@ -29,16 +29,16 @@ int sc_main(int argc, char* argv[]) {
Vtop* top = new Vtop("top");
// Initialize SC model
-#if (SYSTEMC_VERSION>=20070314)
- sc_start(1,SC_NS);
+#if (SYSTEMC_VERSION >= 20070314)
+ sc_start(1, SC_NS);
#else
sc_start(1);
#endif
// Simulate until $finish
while (!Verilated::gotFinish()) {
-#if (SYSTEMC_VERSION>=20070314)
- sc_start(1,SC_NS);
+#if (SYSTEMC_VERSION >= 20070314)
+ sc_start(1, SC_NS);
#else
sc_start(1);
#endif
diff --git a/examples/make_protect_lib/secret_impl.v b/examples/make_protect_lib/secret_impl.v
index fd8557af1..1e39257f5 100644
--- a/examples/make_protect_lib/secret_impl.v
+++ b/examples/make_protect_lib/secret_impl.v
@@ -6,14 +6,16 @@
// This module will be used as libsecret.a or libsecret.so without
// exposing the source.
-module secret_impl(
- input [31:0] a,
- input [31:0] b,
- output logic [31:0] x,
- input clk);
- logic [31:0] accum_q = 0;
- logic [31:0] secret_value = 9;
+module secret_impl
+ (
+ input [31:0] a,
+ input [31:0] b,
+ output logic [31:0] x,
+ input clk);
+
+ logic [31:0] accum_q = 0;
+ logic [31:0] secret_value = 9;
initial $display("%m: initialized");
diff --git a/examples/make_protect_lib/sim_main.cpp b/examples/make_protect_lib/sim_main.cpp
index 3244f0a69..e329019b5 100644
--- a/examples/make_protect_lib/sim_main.cpp
+++ b/examples/make_protect_lib/sim_main.cpp
@@ -17,9 +17,7 @@
#endif
vluint64_t main_time = 0;
-double sc_time_stamp() {
- return main_time;
-}
+double sc_time_stamp() { return main_time; }
int main(int argc, char** argv, char** env) {
if (0 && argc && argv && env) {}
@@ -35,7 +33,7 @@ int main(int argc, char** argv, char** env) {
// When tracing, the contents of the secret module will not be seen
VerilatedVcdC* tfp = NULL;
const char* flag = Verilated::commandArgsPlusMatch("trace");
- if (flag && 0==strcmp(flag, "+trace")) {
+ if (flag && 0 == strcmp(flag, "+trace")) {
Verilated::traceEverOn(true);
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
tfp = new VerilatedVcdC;
@@ -62,11 +60,15 @@ int main(int argc, char** argv, char** env) {
// Close trace if opened
#if VM_TRACE
- if (tfp) { tfp->close(); tfp = NULL; }
+ if (tfp) {
+ tfp->close();
+ tfp = NULL;
+ }
#endif
// Destroy model
- delete top; top = NULL;
+ delete top;
+ top = NULL;
// Fin
exit(0);
diff --git a/examples/make_tracing_c/Makefile b/examples/make_tracing_c/Makefile
index ba4b30bc3..bd043c697 100644
--- a/examples/make_tracing_c/Makefile
+++ b/examples/make_tracing_c/Makefile
@@ -68,11 +68,13 @@ run:
$(VERILATOR) $(VERILATOR_FLAGS) $(VERILATOR_INPUT)
@echo
- @echo "-- COMPILE -----------------"
-# To compile, we can either just do what Verilator asks,
-# or call a submakefile where we can override the rules ourselves
-# $(MAKE) -j 4 -C obj_dir -f Vtop.mk
- $(MAKE) -j 4 -C obj_dir -f ../Makefile_obj
+ @echo "-- BUILD -------------------"
+# To compile, we can either
+# 1. Pass --build to Verilator by editing VERILATOR_FLAGS above.
+# 2. Or, run the make rules Verilator does:
+# $(MAKE) -j -C obj_dir -f Vtop.mk
+# 3. Or, call a submakefile where we can override the rules ourselves:
+ $(MAKE) -j -C obj_dir -f ../Makefile_obj
@echo
@echo "-- RUN ---------------------"
diff --git a/examples/make_tracing_c/sim_main.cpp b/examples/make_tracing_c/sim_main.cpp
index 6ff878731..8da3fee7a 100644
--- a/examples/make_tracing_c/sim_main.cpp
+++ b/examples/make_tracing_c/sim_main.cpp
@@ -83,9 +83,9 @@ int main(int argc, char** argv, char** env) {
// Read outputs
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
- " -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
- main_time, top->clk, top->reset_l, top->in_quad,
- top->out_quad, top->out_wide[2], top->out_wide[1], top->out_wide[0]);
+ " -> oquad=%" VL_PRI64 "x owide=%x_%08x_%08x\n",
+ main_time, top->clk, top->reset_l, top->in_quad, top->out_quad, top->out_wide[2],
+ top->out_wide[1], top->out_wide[0]);
}
// Final model cleanup
@@ -98,7 +98,8 @@ int main(int argc, char** argv, char** env) {
#endif
// Destroy model
- delete top; top = NULL;
+ delete top;
+ top = NULL;
// Fin
exit(0);
diff --git a/examples/make_tracing_c/top.v b/examples/make_tracing_c/top.v
index a11027546..dbc852814 100644
--- a/examples/make_tracing_c/top.v
+++ b/examples/make_tracing_c/top.v
@@ -11,15 +11,15 @@
module top
(
// Declare some signals so we can see how I/O works
- input clk,
- input reset_l,
+ input clk,
+ input reset_l,
output wire [1:0] out_small,
output wire [39:0] out_quad,
output wire [69:0] out_wide,
- input [1:0] in_small,
- input [39:0] in_quad,
- input [69:0] in_wide
+ input [1:0] in_small,
+ input [39:0] in_quad,
+ input [69:0] in_wide
);
// Connect up the outputs, using some trivial logic
diff --git a/examples/make_tracing_sc/Makefile b/examples/make_tracing_sc/Makefile
index 4b91f5ddc..149d4238c 100644
--- a/examples/make_tracing_sc/Makefile
+++ b/examples/make_tracing_sc/Makefile
@@ -77,10 +77,12 @@ run:
@echo
@echo "-- COMPILE -----------------"
-# To compile, we can either just do what Verilator asks,
-# or call a submakefile where we can override the rules ourselves
-# $(MAKE) -j 4 -C obj_dir -f Vtop.mk
- $(MAKE) -j 4 -C obj_dir -f ../Makefile_obj
+# To compile, we can either
+# 1. Pass --build to Verilator by editing VERILATOR_FLAGS above.
+# 2. Or, run the make rules Verilator does:
+# $(MAKE) -j -C obj_dir -f Vtop.mk
+# 3. Or, call a submakefile where we can override the rules ourselves:
+ $(MAKE) -j -C obj_dir -f ../Makefile_obj
@echo
@echo "-- RUN ---------------------"
diff --git a/examples/make_tracing_sc/sc_main.cpp b/examples/make_tracing_sc/sc_main.cpp
index 31145a17f..8ec598d0b 100644
--- a/examples/make_tracing_sc/sc_main.cpp
+++ b/examples/make_tracing_sc/sc_main.cpp
@@ -45,19 +45,19 @@ int sc_main(int argc, char* argv[]) {
ios::sync_with_stdio();
// Defaults time
-#if (SYSTEMC_VERSION>20011000)
+#if (SYSTEMC_VERSION > 20011000)
#else
sc_time dut(1.0, sc_ns);
sc_set_default_time_unit(dut);
#endif
// Define clocks
-#if (SYSTEMC_VERSION>=20070314)
- sc_clock clk ("clk", 10,SC_NS, 0.5, 3,SC_NS, true);
- sc_clock fastclk ("fastclk", 2,SC_NS, 0.5, 2,SC_NS, true);
+#if (SYSTEMC_VERSION >= 20070314)
+ sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
+ sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
#else
- sc_clock clk ("clk", 10, 0.5, 3, true);
- sc_clock fastclk ("fastclk", 2, 0.5, 2, true);
+ sc_clock clk("clk", 10, 0.5, 3, true);
+ sc_clock fastclk("fastclk", 2, 0.5, 2, true);
#endif
// Define interconnect
@@ -72,15 +72,15 @@ int sc_main(int argc, char* argv[]) {
// Construct the Verilated model, from inside Vtop.h
Vtop* top = new Vtop("top");
// Attach signals to the model
- top->clk (clk);
- top->fastclk (fastclk);
- top->reset_l (reset_l);
- top->in_small (in_small);
- top->in_quad (in_quad);
- top->in_wide (in_wide);
- top->out_small (out_small);
- top->out_quad (out_quad);
- top->out_wide (out_wide);
+ top->clk(clk);
+ top->fastclk(fastclk);
+ top->reset_l(reset_l);
+ top->in_small(in_small);
+ top->in_quad(in_quad);
+ top->in_wide(in_wide);
+ top->out_small(out_small);
+ top->out_quad(out_quad);
+ top->out_wide(out_wide);
#if VM_TRACE
// Before any evaluation, need to know to calculate those signals only used for tracing
@@ -89,8 +89,8 @@ int sc_main(int argc, char* argv[]) {
// You must do one evaluation before enabling waves, in order to allow
// SystemC to interconnect everything for testing.
-#if (SYSTEMC_VERSION>=20070314)
- sc_start(1,SC_NS);
+#if (SYSTEMC_VERSION >= 20070314)
+ sc_start(1, SC_NS);
#else
sc_start(1);
#endif
@@ -100,7 +100,7 @@ int sc_main(int argc, char* argv[]) {
// and if at run time passed the +trace argument, turn on tracing
VerilatedVcdSc* tfp = NULL;
const char* flag = Verilated::commandArgsPlusMatch("trace");
- if (flag && 0==strcmp(flag, "+trace")) {
+ if (flag && 0 == strcmp(flag, "+trace")) {
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
tfp = new VerilatedVcdSc;
top->trace(tfp, 99); // Trace 99 levels of hierarchy
@@ -118,15 +118,15 @@ int sc_main(int argc, char* argv[]) {
#endif
// Apply inputs
- if (VL_TIME_Q() > 1 && VL_TIME_Q() < 10) {
+ if (sc_time_stamp() > sc_time(1, SC_NS) && sc_time_stamp() < sc_time(10, SC_NS)) {
reset_l = !1; // Assert reset
- } else if (VL_TIME_Q() > 1) {
+ } else {
reset_l = !0; // Deassert reset
}
// Simulate 1ns
-#if (SYSTEMC_VERSION>=20070314)
- sc_start(1,SC_NS);
+#if (SYSTEMC_VERSION >= 20070314)
+ sc_start(1, SC_NS);
#else
sc_start(1);
#endif
@@ -137,7 +137,10 @@ int sc_main(int argc, char* argv[]) {
// Close trace if opened
#if VM_TRACE
- if (tfp) { tfp->close(); tfp = NULL; }
+ if (tfp) {
+ tfp->close();
+ tfp = NULL;
+ }
#endif
// Coverage analysis (since test passed)
@@ -147,7 +150,8 @@ int sc_main(int argc, char* argv[]) {
#endif
// Destroy model
- delete top; top = NULL;
+ delete top;
+ top = NULL;
// Fin
return 0;
diff --git a/examples/make_tracing_sc/top.v b/examples/make_tracing_sc/top.v
index 534acb8e1..a31254951 100644
--- a/examples/make_tracing_sc/top.v
+++ b/examples/make_tracing_sc/top.v
@@ -11,16 +11,16 @@
module top
(
// Declare some signals so we can see how I/O works
- input clk,
- input fastclk,
- input reset_l,
+ input clk,
+ input fastclk,
+ input reset_l,
output wire [1:0] out_small,
output wire [39:0] out_quad,
output wire [69:0] out_wide,
- input [1:0] in_small,
- input [39:0] in_quad,
- input [69:0] in_wide
+ input [1:0] in_small,
+ input [39:0] in_quad,
+ input [69:0] in_wide
);
// Connect up the outputs, using some trivial logic
diff --git a/examples/xml_py/sub.v b/examples/xml_py/sub.v
index ba2eed35c..67b577285 100644
--- a/examples/xml_py/sub.v
+++ b/examples/xml_py/sub.v
@@ -8,7 +8,7 @@
module sub
#(parameter type TYPE_t = logic)
(
- input TYPE_t in,
+ input TYPE_t in,
output TYPE_t out
);
diff --git a/examples/xml_py/top.v b/examples/xml_py/top.v
index 405bf46c5..1106464f1 100644
--- a/examples/xml_py/top.v
+++ b/examples/xml_py/top.v
@@ -7,16 +7,16 @@
module top
(
- input clk,
- input fastclk,
- input reset_l,
+ input clk,
+ input fastclk,
+ input reset_l,
output wire [1:0] out_small,
output wire [39:0] out_quad,
output wire [69:0] out_wide,
- input [1:0] in_small,
- input [39:0] in_quad,
- input [69:0] in_wide
+ input [1:0] in_small,
+ input [39:0] in_quad,
+ input [69:0] in_wide
);
sub #(.TYPE_t(logic [1:0])) sub_small
diff --git a/include/verilated.cpp b/include/verilated.cpp
index 373082276..206e7335b 100644
--- a/include/verilated.cpp
+++ b/include/verilated.cpp
@@ -29,11 +29,14 @@
#include
#include
#include
+#include
#include // mkdir
+// clang-format off
#if defined(_WIN32) || defined(__MINGW32__)
# include // mkdir
#endif
+// clang-format on
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
@@ -42,13 +45,13 @@
typedef union {
// cppcheck-suppress unusedStructMember // Unused as is assertion
- char vluint8_incorrect[(sizeof(vluint8_t) == 1) ? 1:-1];
+ char vluint8_incorrect[(sizeof(vluint8_t) == 1) ? 1 : -1];
// cppcheck-suppress unusedStructMember // Unused as is assertion
- char vluint16_incorrect[(sizeof(vluint16_t) == 2) ? 1:-1];
+ char vluint16_incorrect[(sizeof(vluint16_t) == 2) ? 1 : -1];
// cppcheck-suppress unusedStructMember // Unused as is assertion
- char vluint32_incorrect[(sizeof(vluint32_t) == 4) ? 1:-1];
+ char vluint32_incorrect[(sizeof(vluint32_t) == 4) ? 1 : -1];
// cppcheck-suppress unusedStructMember // Unused as is assertion
- char vluint64_incorrect[(sizeof(vluint64_t) == 8) ? 1:-1];
+ char vluint64_incorrect[(sizeof(vluint64_t) == 8) ? 1 : -1];
} vl_static_checks_t;
//===========================================================================
@@ -99,8 +102,12 @@ void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
if (0 && hier) {}
Verilated::gotFinish(true);
- VL_PRINTF( // Not VL_PRINTF_MT, already on main thread
- "%%Error: %s:%d: %s\n", filename, linenum, msg);
+ if (filename && filename[0]) {
+ // Not VL_PRINTF_MT, already on main thread
+ VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
+ } else {
+ VL_PRINTF("%%Error: %s\n", msg);
+ }
Verilated::flushCall();
VL_PRINTF("Aborting...\n"); // Not VL_PRINTF_MT, already on main thread
@@ -114,7 +121,8 @@ void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool may
Verilated::errorCountInc();
if (maybe && Verilated::errorCount() < Verilated::errorLimit()) {
VL_PRINTF( // Not VL_PRINTF_MT, already on main thread
- "-Info: %s:%d: %s\n", filename, linenum, "Verilog $stop, ignored due to +verilator+error+limit");
+ "-Info: %s:%d: %s\n", filename, linenum,
+ "Verilog $stop, ignored due to +verilator+error+limit");
} else {
vl_stop(filename, linenum, hier);
}
@@ -126,9 +134,9 @@ void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool may
void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE {
#ifdef VL_THREADED
- VerilatedThreadMsgQueue::post(VerilatedMsg([=](){
- vl_finish(filename, linenum, hier);
- }));
+ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
+ vl_finish(filename, linenum, hier);
+ }));
#else
vl_finish(filename, linenum, hier);
#endif
@@ -136,9 +144,9 @@ void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAF
void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_SAFE {
#ifdef VL_THREADED
- VerilatedThreadMsgQueue::post(VerilatedMsg([=](){
- vl_stop_maybe(filename, linenum, hier, maybe);
- }));
+ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
+ vl_stop_maybe(filename, linenum, hier, maybe);
+ }));
#else
vl_stop_maybe(filename, linenum, hier, maybe);
#endif
@@ -146,9 +154,9 @@ void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe)
void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE {
#ifdef VL_THREADED
- VerilatedThreadMsgQueue::post(VerilatedMsg([=](){
- vl_fatal(filename, linenum, hier, msg);
- }));
+ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
+ vl_fatal(filename, linenum, hier, msg);
+ }));
#else
vl_fatal(filename, linenum, hier, msg);
#endif
@@ -163,12 +171,10 @@ std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
va_copy(aq, ap);
int len = VL_VSNPRINTF(NULL, 0, formatp, aq);
va_end(aq);
- if (VL_UNLIKELY(len < 1)) {
- return "";
- }
+ if (VL_UNLIKELY(len < 1)) return "";
- char* bufp = new char[len+1];
- VL_VSNPRINTF(bufp, len+1, formatp, ap);
+ char* bufp = new char[len + 1];
+ VL_VSNPRINTF(bufp, len + 1, formatp, ap);
std::string out = std::string(bufp, len);
delete[] bufp;
@@ -203,7 +209,8 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
va_start(ap, formatp);
std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap);
- // printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
+ // printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(),
+ // out.c_str());
// Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF
// from within the guts of the thread execution machinery (and it goes
@@ -217,9 +224,9 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
va_start(ap, formatp);
std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap);
- VerilatedThreadMsgQueue::post(VerilatedMsg([=](){
- VL_PRINTF("%s", out.c_str());
- }));
+ VerilatedThreadMsgQueue::post(VerilatedMsg([=]() { //
+ VL_PRINTF("%s", out.c_str());
+ }));
}
#endif
@@ -236,6 +243,8 @@ Verilated::Serialized::Serialized() {
s_errorLimit = 1;
s_randReset = 0;
s_randSeed = 0;
+ s_timeunit = -VL_TIME_UNIT; // Initial value until overriden by _Vconfigure
+ s_timeprecision = -VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
}
Verilated::NonSerialized::NonSerialized() {
@@ -245,10 +254,14 @@ Verilated::NonSerialized::NonSerialized() {
}
Verilated::NonSerialized::~NonSerialized() {
if (s_profThreadsFilenamep) {
- free(const_cast(s_profThreadsFilenamep)); s_profThreadsFilenamep=NULL;
+ VL_DO_CLEAR(free(const_cast(s_profThreadsFilenamep)),
+ s_profThreadsFilenamep = NULL);
}
}
+size_t Verilated::serialized2Size() VL_PURE { return sizeof(VerilatedImp::s_s.m_ser); }
+void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.m_ser; }
+
//===========================================================================
// Random -- Mostly called at init time, so not inline.
@@ -257,9 +270,9 @@ static vluint32_t vl_sys_rand32() VL_MT_UNSAFE {
// Used only to construct seed for Verilator's PNRG.
#if defined(_WIN32) && !defined(__CYGWIN__)
// Windows doesn't have lrand48(), although Cygwin does.
- return (rand()<<16) ^ rand();
+ return (rand() << 16) ^ rand();
#else
- return (lrand48()<<16) ^ lrand48();
+ return (lrand48() << 16) ^ lrand48();
#endif
}
@@ -291,22 +304,17 @@ vluint64_t vl_rand64() VL_MT_SAFE {
// Xoroshiro128+ algorithm
vluint64_t result = t_state[0] + t_state[1];
t_state[1] ^= t_state[0];
- t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9))
- ^ t_state[1] ^ (t_state[1] << 14));
+ t_state[0] = (((t_state[0] << 55) | (t_state[0] >> 9)) ^ t_state[1] ^ (t_state[1] << 14));
t_state[1] = (t_state[1] << 36) | (t_state[1] >> 28);
return result;
}
-IData VL_RANDOM_I(int obits) VL_MT_SAFE {
- return vl_rand64() & VL_MASK_I(obits);
-}
-QData VL_RANDOM_Q(int obits) VL_MT_SAFE {
- return vl_rand64() & VL_MASK_Q(obits);
-}
+IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
+QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
// VL_RANDOM_W currently unused as $random always 32 bits
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
- for (int i=0; i= 0; --i) {
- VL_PRINTF_MT("%08x ", iwp[i]);
- }
+ for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) VL_PRINTF_MT("%08x ", iwp[i]);
VL_PRINTF_MT("\n");
}
@@ -370,12 +376,12 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
// for debug see V3Number version
// Requires clean input
int words = VL_WORDS_I(lbits);
- for (int i=0; i= 0; --j) {
- vluint64_t unw64 = ((k<(lwp[j]));
+ for (int j = uw - 1; j >= 0; --j) {
+ vluint64_t unw64 = ((k << VL_ULL(32)) + static_cast(lwp[j]));
owp[j] = unw64 / static_cast(rwp[0]);
- k = unw64 - static_cast(owp[j])*static_cast(rwp[0]);
+ k = unw64 - static_cast(owp[j]) * static_cast(rwp[0]);
}
if (is_modulus) {
owp[0] = k;
- for (int i=1; i> 32 won't mask the value
- for (int i = vw-1; i>0; --i) {
- vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i-1] >> (32-s)));
+ for (int i = vw - 1; i > 0; --i) {
+ vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i - 1] >> (32 - s)));
}
vn[0] = rwp[0] << s;
// Copy and shift dividend by same amount; may set new upper word
- if (s) un[uw] = lwp[uw-1] >> (32-s);
- else un[uw] = 0;
- for (int i=uw-1; i>0; --i) {
- un[i] = (lwp[i] << s) | (shift_mask & (lwp[i-1] >> (32-s)));
+ if (s) {
+ un[uw] = lwp[uw - 1] >> (32 - s);
+ } else {
+ un[uw] = 0;
+ }
+ for (int i = uw - 1; i > 0; --i) {
+ un[i] = (lwp[i] << s) | (shift_mask & (lwp[i - 1] >> (32 - s)));
}
un[0] = lwp[0] << s;
// Main loop
for (int j = uw - vw; j >= 0; --j) {
// Estimate
- vluint64_t unw64 = (static_cast(un[j+vw])<(un[j+vw-1]));
- vluint64_t qhat = unw64 / static_cast(vn[vw-1]);
- vluint64_t rhat = unw64 - qhat*static_cast(vn[vw-1]);
+ vluint64_t unw64 = (static_cast(un[j + vw]) << VL_ULL(32)
+ | static_cast(un[j + vw - 1]));
+ vluint64_t qhat = unw64 / static_cast(vn[vw - 1]);
+ vluint64_t rhat = unw64 - qhat * static_cast(vn[vw - 1]);
- again:
+ again:
if (qhat >= VL_ULL(0x100000000)
- || ((qhat*vn[vw-2]) > ((rhat< ((rhat << VL_ULL(32)) + un[j + vw - 2]))) {
qhat = qhat - 1;
- rhat = rhat + vn[vw-1];
+ rhat = rhat + vn[vw - 1];
if (rhat < VL_ULL(0x100000000)) goto again;
}
vlsint64_t t = 0; // Must be signed
vluint64_t k = 0;
- for (int i=0; i> VL_ULL(32)) - (t >> VL_ULL(32));
}
- t = un[j+vw] - k;
- un[j+vw] = t;
+ t = un[j + vw] - k;
+ un[j + vw] = t;
owp[j] = qhat; // Save quotient digit
if (t < 0) {
// Over subtracted; correct by adding back
owp[j]--;
k = 0;
- for (int i=0; i(un[i+j]) + static_cast(vn[i]) + k;
- un[i+j] = t;
+ for (int i = 0; i < vw; ++i) {
+ t = static_cast(un[i + j]) + static_cast(vn[i]) + k;
+ un[i + j] = t;
k = t >> VL_ULL(32);
}
- un[j+vw] = un[j+vw] + k;
+ un[j + vw] = un[j + vw] + k;
}
}
if (is_modulus) { // modulus
// Need to reverse normalization on copy to output
- for (int i=0; i> s) | (shift_mask & (un[i+1] << (32-s)));
+ for (int i = 0; i < vw; ++i) {
+ owp[i] = (un[i] >> s) | (shift_mask & (un[i + 1] << (32 - s)));
}
- for (int i=vw; i0) { // power = power*power
+ for (int bit = 0; bit < rbits; bit++) {
+ if (bit > 0) { // power = power*power
VL_ASSIGN_W(obits, lastpowstore, powstore);
VL_MUL_W(VL_WORDS_I(obits), powstore, lastpowstore, lastpowstore);
}
@@ -497,18 +506,19 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits,
}
return owp;
}
-WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, QData rhs) VL_MT_SAFE {
- WData rhsw[VL_WQ_WORDS_E]; VL_SET_WQ(rhsw, rhs);
+WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
+ QData rhs) VL_MT_SAFE {
+ WData rhsw[VL_WQ_WORDS_E];
+ VL_SET_WQ(rhsw, rhs);
return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
}
QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE {
// Skip check for rhs == 0, as short-circuit doesn't save time
- if (VL_UNLIKELY(lhs==0)) return 0;
+ if (VL_UNLIKELY(lhs == 0)) return 0;
QData power = lhs;
QData out = VL_ULL(1);
- for (int bit=0; bit0) power = power*power;
+ for (int bit = 0; bit < rbits; ++bit) {
+ if (bit > 0) power = power * power;
if (VL_BITISSET_W(rwp, bit)) out *= power;
}
return out;
@@ -521,35 +531,45 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
int words = VL_WORDS_I(obits);
VL_ZERO_W(obits, owp);
EData lor = 0; // 0=all zeros, ~0=all ones, else mix
- for (int i=1; i < (words-1); ++i) {
- lor |= lwp[i];
- }
- lor |= ( (lwp[words-1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0);
- if (lor==0 && lwp[0]==0) { return owp; } // "X" so return 0
- else if (lor==0 && lwp[0]==1) { owp[0] = 1; return owp; } // 1
- else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1
- if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1
- else { owp[0] = 1; return owp; } // -1^even=1
+ for (int i = 1; i < (words - 1); ++i) { lor |= lwp[i]; }
+ lor |= ((lwp[words - 1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0);
+ if (lor == 0 && lwp[0] == 0) { // "X" so return 0
+ return owp;
+ } else if (lor == 0 && lwp[0] == 1) { // 1
+ owp[0] = 1;
+ return owp;
+ } else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1
+ if (rwp[0] & 1) { // -1^odd=-1
+ return VL_ALLONES_W(obits, owp);
+ } else { // -1^even=1
+ owp[0] = 1;
+ return owp;
+ }
}
return 0;
}
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
}
-WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, QData rhs,
+WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs,
bool lsign, bool rsign) VL_MT_SAFE {
- WData rhsw[VL_WQ_WORDS_E]; VL_SET_WQ(rhsw, rhs);
+ WData rhsw[VL_WQ_WORDS_E];
+ VL_SET_WQ(rhsw, rhs);
return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
}
-QData VL_POWSS_QQW(int obits, int, int rbits,
- QData lhs, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
+QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign,
+ bool rsign) VL_MT_SAFE {
// Skip check for rhs == 0, as short-circuit doesn't save time
if (rsign && VL_SIGN_W(rbits, rwp)) {
- if (lhs == 0) return 0; // "X"
- else if (lhs == 1) return 1;
- else if (lsign && lhs == VL_MASK_Q(obits)) { // -1
- if (rwp[0] & 1) return VL_MASK_Q(obits); // -1^odd=-1
- else return 1; // -1^even=1
+ if (lhs == 0) {
+ return 0; // "X"
+ } else if (lhs == 1) {
+ return 1;
+ } else if (lsign && lhs == VL_MASK_Q(obits)) { // -1
+ if (rwp[0] & 1) {
+ return VL_MASK_Q(obits); // -1^odd=-1
+ } else {
+ return 1; // -1^even=1
+ }
}
return 0;
}
@@ -561,19 +581,19 @@ QData VL_POWSS_QQW(int obits, int, int rbits,
/// Output a string representation of a wide number
std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
- int maxdecwidth = (width+3)*4/3;
+ int maxdecwidth = (width + 3) * 4 / 3;
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
- WData bcd[VL_VALUE_STRING_MAX_WIDTH/4+2];
+ WData bcd[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
VL_ZERO_RESET_W(maxdecwidth, bcd);
- WData tmp[VL_VALUE_STRING_MAX_WIDTH/4+2];
- WData tmp2[VL_VALUE_STRING_MAX_WIDTH/4+2];
- int from_bit = width-1;
+ WData tmp[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
+ WData tmp2[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
+ int from_bit = width - 1;
// Skip all leading zeros
- for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit);
+ for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit) {}
// Double-dabble algorithm
for (; from_bit >= 0; --from_bit) {
// Any digits >= 5 need an add 3 (via tmp)
- for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit+=4) {
+ for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit += 4) {
if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
VL_ZERO_RESET_W(maxdecwidth, tmp2);
tmp2[VL_BITWORD_E(nibble_bit)] |= VL_EUL(0x3) << VL_BITBIT_E(nibble_bit);
@@ -588,16 +608,41 @@ std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
}
std::string output;
- int lsb = (maxdecwidth-1) & ~3;
- for (; lsb>0; lsb-=4) { // Skip leading zeros
+ int lsb = (maxdecwidth - 1) & ~3;
+ for (; lsb > 0; lsb -= 4) { // Skip leading zeros
if (VL_BITRSHIFT_W(bcd, lsb) & 0xf) break;
}
- for (; lsb>=0; lsb-=4) {
+ for (; lsb >= 0; lsb -= 4) {
output += ('0' + (VL_BITRSHIFT_W(bcd, lsb) & 0xf)); // 0..9
}
return output;
}
+std::string _vl_vsformat_time(char* tmp, double ld, bool left, size_t width) {
+ // Double may lose precision, but sc_time_stamp has similar limit
+ std::string suffix = VerilatedImp::timeFormatSuffix();
+ int userUnits = VerilatedImp::timeFormatUnits(); // 0..-15
+ int fracDigits = VerilatedImp::timeFormatPrecision(); // 0..N
+ int prec = Verilated::timeprecision(); // 0..-15
+ int shift = prec - userUnits + fracDigits; // 0..-15
+ double shiftd = vl_time_multiplier(shift);
+ double scaled = ld * shiftd;
+ QData fracDiv = static_cast(vl_time_multiplier(fracDigits));
+ QData whole = static_cast(scaled) / fracDiv;
+ QData fraction = static_cast(scaled) % fracDiv;
+ int digits;
+ if (!fracDigits) {
+ digits = sprintf(tmp, "%" VL_PRI64 "u%s", whole, suffix.c_str());
+ } else {
+ digits = sprintf(tmp, "%" VL_PRI64 "u.%0*" VL_PRI64 "u%s", whole, fracDigits, fraction,
+ suffix.c_str());
+ }
+ int needmore = width - digits;
+ std::string padding;
+ if (needmore > 0) padding.append(needmore, ' '); // Pad with spaces
+ return left ? (tmp + padding) : (padding + tmp);
+}
+
// Do a va_arg returning a quad, assuming input argument is anything less than wide
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_IDATASIZE) ? va_arg(ap, IData) : va_arg(ap, QData))
@@ -610,14 +655,13 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
// 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 tmpf[VL_VALUE_STRING_MAX_WIDTH];
const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false;
bool widthSet = false;
bool left = false;
size_t width = 0;
for (const char* pos = formatp; *pos; ++pos) {
- if (!inPct && pos[0]=='%') {
+ if (!inPct && pos[0] == '%') {
pctp = pos;
inPct = true;
widthSet = false;
@@ -625,20 +669,19 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
} else if (!inPct) { // Normal text
// Fast-forward to next escape and add to output
const char* ep = pos;
- while (ep[0] && ep[0]!='%') ep++;
+ while (ep[0] && ep[0] != '%') ep++;
if (ep != pos) {
- output.append(pos, ep-pos);
- pos += ep-pos-1;
+ output.append(pos, ep - pos);
+ pos += ep - pos - 1;
}
} else { // Format character
inPct = false;
char fmt = pos[0];
switch (fmt) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
+ case '0' ... '9':
inPct = true; // Get more digits
widthSet = true;
- width = width*10 + (fmt - '0');
+ width = width * 10 + (fmt - '0');
break;
case '-':
left = true;
@@ -647,12 +690,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case '.':
inPct = true; // Get more digits
break;
- case '%':
+ case '%': //
output += '%';
break;
case 'N': { // "C" string with name of module, add . if needed
const char* cstrp = va_arg(ap, const char*);
- if (VL_LIKELY(*cstrp)) { output += cstrp; output += '.'; }
+ if (VL_LIKELY(*cstrp)) {
+ output += cstrp;
+ output += '.';
+ }
break;
}
case 'S': { // "C" string
@@ -677,19 +723,16 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
if (lbits) {} // UNUSED - always 64
switch (fmt) {
case '^': { // Realtime
- int digits = sprintf(tmp, "%g", d/VL_TIME_MULTIPLIER);
- int needmore = width-digits;
- if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces
- output += tmp;
+ if (!widthSet) width = VerilatedImp::timeFormatWidth();
+ output += _vl_vsformat_time(tmp, d, left, width);
break;
}
default: {
- strncpy(tmpf, pctp, pos-pctp+1);
- tmpf[pos-pctp+1] = '\0';
- sprintf(tmp, tmpf, d);
+ std::string fmt(pctp, pos - pctp + 1);
+ sprintf(tmp, fmt.c_str(), d);
output += tmp;
break;
- }
+ } //
break;
} // switch
break;
@@ -708,8 +751,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
lwp = va_arg(ap, WDataInP);
ld = lwp[0];
}
- int lsb=lbits-1;
- if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb;
+ int lsb = lbits - 1;
+ if (widthSet && width == 0) {
+ while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb;
+ }
switch (fmt) {
case 'c': {
IData charval = ld & 0xff;
@@ -718,10 +763,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
case 's': {
std::string field;
- for (; lsb>=0; --lsb) {
+ for (; lsb >= 0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
- field += (charval==0)?' ':charval;
+ field += (charval == 0) ? ' ' : charval;
}
std::string padding;
if (width > field.size()) padding.append(width - field.size(), ' ');
@@ -737,7 +782,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
append = tmp;
} else {
if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
- WData neg[VL_VALUE_STRING_MAX_WIDTH/4+2];
+ WData neg[VL_VALUE_STRING_MAX_WIDTH / 4 + 2];
VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp);
append = std::string("-") + VL_DECIMAL_NW(lbits, neg);
} else {
@@ -745,10 +790,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
digits = append.length();
}
- int needmore = width-digits;
+ int needmore = width - digits;
std::string padding;
- if (needmore>0) {
- if (pctp && pctp[0] && pctp[1]=='0') { // %0
+ if (needmore > 0) {
+ if (pctp && pctp[0] && pctp[1] == '0') { // %0
padding.append(needmore, '0'); // Pre-pad zero
} else {
padding.append(needmore, ' '); // Pre-pad spaces
@@ -767,10 +812,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
append = VL_DECIMAL_NW(lbits, lwp);
digits = append.length();
}
- int needmore = width-digits;
+ int needmore = width - digits;
std::string padding;
- if (needmore>0) {
- if (pctp && pctp[0] && pctp[1]=='0') { // %0
+ if (needmore > 0) {
+ if (pctp && pctp[0] && pctp[1] == '0') { // %0
padding.append(needmore, '0'); // Pre-pad zero
} else {
padding.append(needmore, ' '); // Pre-pad spaces
@@ -780,52 +825,37 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
break;
}
case 't': { // Time
- int digits;
- if (VL_TIME_MULTIPLIER==1) {
- digits=sprintf(tmp, "%" VL_PRI64 "u", ld);
- } else if (VL_TIME_MULTIPLIER==1000) {
- digits=sprintf(tmp, "%" VL_PRI64 "u.%03" VL_PRI64 "u",
- static_cast(ld/VL_TIME_MULTIPLIER),
- static_cast(ld%VL_TIME_MULTIPLIER));
- } else {
- VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER");
- }
- int needmore = width-digits;
- std::string padding;
- if (needmore>0) padding.append(needmore, ' '); // Pad with spaces
- output += left ? (tmp + padding) : (padding + tmp);
+ if (!widthSet) width = VerilatedImp::timeFormatWidth();
+ output += _vl_vsformat_time(tmp, static_cast(ld), left, width);
break;
}
case 'b':
- for (; lsb>=0; --lsb) {
- output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
- }
+ for (; lsb >= 0; --lsb) output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
break;
case 'o':
- for (; lsb>=0; --lsb) {
+ for (; lsb >= 0; --lsb) {
lsb = (lsb / 3) * 3; // Next digit
// Octal numbers may span more than one wide word,
// so we need to grab each bit separately and check for overrun
// Octal is rare, so we'll do it a slow simple way
- output += ('0'
- + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0)
- + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+1)) ? 2 : 0)
- + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
+ output += ('0' + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 0)) ? 1 : 0)
+ + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 1)) ? 2 : 0)
+ + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 2)) ? 4 : 0));
}
break;
case 'u': // Packed 2-state
- output.reserve(output.size() + 4*VL_WORDS_I(lbits));
- for (int i=0; i((lwp[i] ) & 0xff);
+ output.reserve(output.size() + 4 * VL_WORDS_I(lbits));
+ for (int i = 0; i < VL_WORDS_I(lbits); ++i) {
+ output += static_cast((lwp[i]) & 0xff);
output += static_cast((lwp[i] >> 8) & 0xff);
output += static_cast((lwp[i] >> 16) & 0xff);
output += static_cast((lwp[i] >> 24) & 0xff);
}
break;
case 'z': // Packed 4-state
- output.reserve(output.size() + 8*VL_WORDS_I(lbits));
- for (int i=0; i((lwp[i] ) & 0xff);
+ output.reserve(output.size() + 8 * VL_WORDS_I(lbits));
+ for (int i = 0; i < VL_WORDS_I(lbits); ++i) {
+ output += static_cast((lwp[i]) & 0xff);
output += static_cast((lwp[i] >> 8) & 0xff);
output += static_cast((lwp[i] >> 16) & 0xff);
output += static_cast((lwp[i] >> 24) & 0xff);
@@ -833,20 +863,23 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
break;
case 'v': // Strength; assume always strong
- for (lsb=lbits-1; lsb>=0; --lsb) {
- if (VL_BITRSHIFT_W(lwp, lsb) & 1) output += "St1 ";
- else output += "St0 ";
+ for (lsb = lbits - 1; lsb >= 0; --lsb) {
+ if (VL_BITRSHIFT_W(lwp, lsb) & 1) {
+ output += "St1 ";
+ } else {
+ output += "St0 ";
+ }
}
break;
case 'x':
- for (; lsb>=0; --lsb) {
+ for (; lsb >= 0; --lsb) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
output += "0123456789abcdef"[charval];
}
break;
default:
- std::string msg = std::string("Unknown _vl_vsformat code: ")+pos[0];
+ std::string msg = std::string("Unknown _vl_vsformat code: ") + pos[0];
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
break;
} // switch
@@ -856,16 +889,22 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
}
-static inline bool _vl_vsss_eof(FILE* fp, int& floc) VL_MT_SAFE {
- if (fp) return feof(fp) ? 1 : 0; // 1:0 to prevent MSVC++ warning
- else return (floc<0);
+static inline bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE {
+ if (fp) {
+ return feof(fp) ? 1 : 0; // 1:0 to prevent MSVC++ warning
+ } else {
+ return floc < 0;
+ }
}
static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
- if (fp) fgetc(fp);
- else floc -= 8;
+ if (fp) {
+ fgetc(fp);
+ } else {
+ floc -= 8;
+ }
}
-static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
- const std::string& fstr) VL_MT_SAFE {
+static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
+ const std::string& fstr) VL_MT_SAFE {
// Get a character without advancing
if (fp) {
int data = fgetc(fp);
@@ -876,17 +915,17 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
if (floc < 0) return EOF;
floc = floc & ~7; // Align to closest character
if (fromp == NULL) {
- return fstr[fstr.length()-1 - (floc>>3)];
+ return fstr[fstr.length() - 1 - (floc >> 3)];
} else {
return VL_BITRSHIFT_W(fromp, floc) & 0xff;
}
}
}
-static inline void _vl_vsss_skipspace(FILE* fp, int& floc,
- WDataInP fromp, const std::string& fstr) VL_MT_SAFE {
+static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp,
+ const std::string& fstr) VL_MT_SAFE {
while (true) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
- if (c==EOF || !isspace(c)) return;
+ if (c == EOF || !isspace(c)) return;
_vl_vsss_advance(fp, floc);
}
}
@@ -896,49 +935,49 @@ static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std:
char* cp = tmpp;
while (true) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
- if (c==EOF || isspace(c)) break;
- if (acceptp // String - allow anything
- && NULL==strchr(acceptp, c)) break;
+ if (c == EOF || isspace(c)) break;
+ if (acceptp && NULL == strchr(acceptp, c)) break; // String - allow anything
if (acceptp) c = tolower(c); // Non-strings we'll simplify
*cp++ = c;
_vl_vsss_advance(fp, floc);
}
*cp++ = '\0';
- //VL_DBG_MSGF(" _read got='"<>=1) {
+static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
+ IData ld) VL_MT_SAFE {
+ for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) {
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
}
}
-static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2,
- const char* strp,
+static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp,
size_t posstart, size_t posend) VL_MT_SAFE {
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
int lsb = 0;
- for (int i=0, pos = static_cast(posend)-1;
- i=static_cast(posstart); --pos) {
+ for (int i = 0, pos = static_cast(posend) - 1;
+ i < obits && pos >= static_cast(posstart); --pos) {
+ // clang-format off
switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': // FALLTHRU
case '0': lsb += baseLog2; break;
- case '1': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 1); lsb+=baseLog2; break;
- case '2': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 2); lsb+=baseLog2; break;
- case '3': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 3); lsb+=baseLog2; break;
- case '4': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 4); lsb+=baseLog2; break;
- case '5': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 5); lsb+=baseLog2; break;
- case '6': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 6); lsb+=baseLog2; break;
- case '7': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 7); lsb+=baseLog2; break;
- case '8': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 8); lsb+=baseLog2; break;
- case '9': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 9); lsb+=baseLog2; break;
- case 'a': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 10); lsb+=baseLog2; break;
- case 'b': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 11); lsb+=baseLog2; break;
- case 'c': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 12); lsb+=baseLog2; break;
- case 'd': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 13); lsb+=baseLog2; break;
- case 'e': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 14); lsb+=baseLog2; break;
- case 'f': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 15); lsb+=baseLog2; break;
+ case '1': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 1); lsb += baseLog2; break;
+ case '2': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 2); lsb += baseLog2; break;
+ case '3': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 3); lsb += baseLog2; break;
+ case '4': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 4); lsb += baseLog2; break;
+ case '5': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 5); lsb += baseLog2; break;
+ case '6': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 6); lsb += baseLog2; break;
+ case '7': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 7); lsb += baseLog2; break;
+ case '8': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 8); lsb += baseLog2; break;
+ case '9': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 9); lsb += baseLog2; break;
+ case 'a': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 10); lsb += baseLog2; break;
+ case 'b': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 11); lsb += baseLog2; break;
+ case 'c': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 12); lsb += baseLog2; break;
+ case 'd': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 13); lsb += baseLog2; break;
+ case 'e': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 14); lsb += baseLog2; break;
+ case 'f': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 15); lsb += baseLog2; break;
case '_': break;
}
+ // clang-format on
}
}
@@ -955,8 +994,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
bool inPct = false;
const char* pos = formatp;
for (; *pos && !_vl_vsss_eof(fp, floc); ++pos) {
- //VL_DBG_MSGF("_vlscan fmt='"< VL_QUADSIZE) {
- owp = va_arg(ap, WDataOutP);
- }
- for (int i=0; i VL_QUADSIZE) owp = va_arg(ap, WDataOutP);
+ for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
switch (fmt) {
case 'c': {
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
- if (c==EOF) goto done;
- else _vl_vsss_advance(fp, floc);
+ if (c == EOF) goto done;
+ _vl_vsss_advance(fp, floc);
owp[0] = c;
break;
}
@@ -999,10 +1038,11 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_skipspace(fp, floc, fromp, fstr);
_vl_vsss_read(fp, floc, fromp, fstr, tmp, NULL);
if (!tmp[0]) goto done;
- int lpos = (static_cast(strlen(tmp)))-1;
+ int lpos = (static_cast(strlen(tmp))) - 1;
int lsb = 0;
- for (int i=0; i=0; --lpos) {
- _vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]); lsb+=8;
+ for (int i = 0; i < obits && lpos >= 0; --lpos) {
+ _vl_vsss_setbit(owp, obits, lsb, 8, tmp[lpos]);
+ lsb += 8;
}
break;
}
@@ -1011,7 +1051,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_read(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
vlsint64_t ld;
- sscanf(tmp, "%30" VL_PRI64 "d",&ld);
+ sscanf(tmp, "%30" VL_PRI64 "d", &ld);
VL_SET_WQ(owp, ld);
break;
}
@@ -1022,7 +1062,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_read(fp, floc, fromp, fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done;
// cppcheck-suppress unusedStructMember // It's used
- union { double r; vlsint64_t ld; } u;
+ union {
+ double r;
+ vlsint64_t ld;
+ } u;
u.r = strtod(tmp, NULL);
VL_SET_WQ(owp, u.ld);
break;
@@ -1033,7 +1076,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_read(fp, floc, fromp, fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
QData ld;
- sscanf(tmp, "%30" VL_PRI64 "u",&ld);
+ sscanf(tmp, "%30" VL_PRI64 "u", &ld);
VL_SET_WQ(owp, ld);
break;
}
@@ -1059,7 +1102,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break;
}
default:
- std::string msg = std::string("Unknown _vl_vsscanf code: ")+pos[0];
+ std::string msg = std::string("Unknown _vl_vsscanf code: ") + pos[0];
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
break;
} // switch
@@ -1067,45 +1110,48 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
got++;
// Reload data if non-wide (if wide, we put it in the right place directly)
if (obits <= VL_BYTESIZE) {
- CData* p = va_arg(ap, CData*); *p = owp[0];
+ CData* p = va_arg(ap, CData*);
+ *p = owp[0];
} else if (obits <= VL_SHORTSIZE) {
- SData* p = va_arg(ap, SData*); *p = owp[0];
+ SData* p = va_arg(ap, SData*);
+ *p = owp[0];
} else if (obits <= VL_IDATASIZE) {
- IData* p = va_arg(ap, IData*); *p = owp[0];
+ IData* p = va_arg(ap, IData*);
+ *p = owp[0];
} else if (obits <= VL_QUADSIZE) {
- QData* p = va_arg(ap, QData*); *p = VL_SET_QW(owp);
+ QData* p = va_arg(ap, QData*);
+ *p = VL_SET_QW(owp);
}
}
} // switch
}
}
- done:
+done:
return got;
}
//===========================================================================
// File I/O
-FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE {
- return VerilatedImp::fdToFp(lhs);
-}
+FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE { return VerilatedImp::fdToFp(lhs); }
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE {
// See also VL_DATA_TO_STRING_NW
- int lsb=obits-1;
- bool start=true;
+ int lsb = obits - 1;
+ bool start = true;
char* destp = destoutp;
- for (; lsb>=0; --lsb) {
+ for (; lsb >= 0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
if (!start || charval) {
- *destp++ = (charval==0)?' ':charval;
+ *destp++ = (charval == 0) ? ' ' : charval;
start = false; // Drop leading 0s
}
}
*destp = '\0'; // Terminate
- // Drop trailing spaces
- if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0';
+ if (!start) { // Drop trailing spaces
+ while (isspace(*(destp - 1)) && destp > destoutp) *--destp = '\0';
+ }
}
void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
@@ -1114,8 +1160,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp)
char* op = reinterpret_cast(destp);
if (srclen > bytes) srclen = bytes; // Don't overflow destination
size_t i;
- for (i=0; i(memp))[entry];
if (shift == start_shift) { *datap = 0; }
- *datap |= ((static_cast(c) << static_cast(shift))
- & VL_MASK_Q(width));
+ *datap |= ((static_cast(c) << static_cast(shift)) & VL_MASK_Q(width));
} else {
WDataOutP datap = &(reinterpret_cast(memp))[entry * VL_WORDS_I(width)];
- if (shift == start_shift) { VL_ZERO_RESET_W(width, datap); }
+ if (shift == start_shift) VL_ZERO_RESET_W(width, datap);
datap[VL_BITWORD_E(shift)] |= (static_cast(c) << VL_BITBIT_E(shift));
}
// Prep for next
@@ -1380,7 +1438,8 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size,
}
IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
- WData lhsw[VL_WQ_WORDS_E]; VL_SET_WQ(lhsw, lhs);
+ WData lhsw[VL_WQ_WORDS_E];
+ VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
}
IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE {
@@ -1392,8 +1451,7 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP lhsp) VL_MT_SAFE {
IData VL_TESTPLUSARGS_I(const char* formatp) VL_MT_SAFE {
const std::string& match = VerilatedImp::argPlusMatch(formatp);
- if (match.empty()) return 0;
- else return 1;
+ return match.empty() ? 0 : 1;
}
IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE {
@@ -1402,7 +1460,7 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
bool done = false;
char fmt = ' ';
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
- if (!inPct && posp[0]=='%') {
+ if (!inPct && posp[0] == '%') {
inPct = true;
} else if (!inPct) { // Normal text
prefix += *posp;
@@ -1428,22 +1486,18 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
switch (tolower(fmt)) {
case 'd':
vlsint64_t lld;
- sscanf(dp, "%30" VL_PRI64 "d",&lld);
+ sscanf(dp, "%30" VL_PRI64 "d", &lld);
VL_SET_WQ(rwp, lld);
break;
- case 'b':
- _vl_vsss_based(rwp, rbits, 1, dp, 0, strlen(dp));
- break;
- case 'o':
- _vl_vsss_based(rwp, rbits, 3, dp, 0, strlen(dp));
- break;
+ case 'b': _vl_vsss_based(rwp, rbits, 1, dp, 0, strlen(dp)); break;
+ case 'o': _vl_vsss_based(rwp, rbits, 3, dp, 0, strlen(dp)); break;
case 'h': // FALLTHRU
- case 'x':
- _vl_vsss_based(rwp, rbits, 4, dp, 0, strlen(dp));
- break;
+ case 'x': _vl_vsss_based(rwp, rbits, 4, dp, 0, strlen(dp)); break;
case 's': // string/no conversion
- for (int i=0, lsb=0, posp=static_cast(strlen(dp))-1; i=0; --posp) {
- _vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]); lsb+=8;
+ for (int i = 0, lsb = 0, posp = static_cast(strlen(dp)) - 1; i < rbits && posp >= 0;
+ --posp) {
+ _vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]);
+ lsb += 8;
}
break;
case 'e': {
@@ -1475,7 +1529,7 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
bool inPct = false;
bool done = false;
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
- if (!inPct && posp[0]=='%') {
+ if (!inPct && posp[0] == '%') {
inPct = true;
} else if (!inPct) { // Normal text
prefix += *posp;
@@ -1485,7 +1539,7 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
prefix += *posp;
inPct = false;
break;
- default:
+ default: //
done = true;
break;
}
@@ -1502,43 +1556,31 @@ 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];
if (match.empty()) return NULL;
- strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
- VL_VALUE_STRING_MAX_WIDTH);
- outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
+ outstr[0] = '\0';
+ strncat(outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+"
+ VL_VALUE_STRING_MAX_WIDTH - 1);
return outstr;
}
//===========================================================================
// Heavy string functions
-std::string VL_TO_STRING(CData lhs) {
- return VL_SFORMATF_NX("'h%0x", 8, lhs);
-}
-std::string VL_TO_STRING(SData lhs) {
- return VL_SFORMATF_NX("'h%0x", 16, lhs);
-}
-std::string VL_TO_STRING(IData lhs) {
- return VL_SFORMATF_NX("'h%0x", 32, lhs);
-}
-std::string VL_TO_STRING(QData lhs) {
- return VL_SFORMATF_NX("'h%0x", 64, lhs);
-}
+std::string VL_TO_STRING(CData lhs) { return VL_SFORMATF_NX("'h%0x", 8, lhs); }
+std::string VL_TO_STRING(SData lhs) { return VL_SFORMATF_NX("'h%0x", 16, lhs); }
+std::string VL_TO_STRING(IData lhs) { return VL_SFORMATF_NX("'h%0x", 32, lhs); }
+std::string VL_TO_STRING(QData lhs) { return VL_SFORMATF_NX("'h%0x", 64, lhs); }
std::string VL_TO_STRING_W(int words, WDataInP obj) {
return VL_SFORMATF_NX("'h%0x", words * VL_EDATASIZE, obj);
}
std::string VL_TOLOWER_NN(const std::string& ld) VL_MT_SAFE {
std::string out = ld;
- for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
- *it = tolower(*it);
- }
+ for (std::string::iterator it = out.begin(); it != out.end(); ++it) *it = tolower(*it);
return out;
}
std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE {
std::string out = ld;
- for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
- *it = toupper(*it);
- }
+ for (std::string::iterator it = out.begin(); it != out.end(); ++it) *it = toupper(*it);
return out;
}
@@ -1546,15 +1588,15 @@ std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
// See also _VL_VINT_TO_STRING
char destout[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
int obits = lwords * VL_EDATASIZE;
- int lsb=obits-1;
- bool start=true;
+ int lsb = obits - 1;
+ bool start = true;
char* destp = destout;
int len = 0;
- for (; lsb>=0; --lsb) {
+ for (; lsb >= 0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
if (!start || charval) {
- *destp++ = (charval==0)?' ':charval;
+ *destp++ = (charval == 0) ? ' ' : charval;
len++;
start = false; // Drop leading 0s
}
@@ -1654,7 +1696,10 @@ VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData star
}
}
VlReadMem::~VlReadMem() {
- if (m_fp) { fclose(m_fp); m_fp = NULL; }
+ if (m_fp) {
+ fclose(m_fp);
+ m_fp = NULL;
+ }
}
bool VlReadMem::get(QData& addrr, std::string& valuer) {
if (VL_UNLIKELY(!m_fp)) return false;
@@ -1677,7 +1722,6 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
if (c == '_') continue; // Ignore _ e.g. inside a number
if (indata && !isxdigit(c) && c != 'x' && c != 'X') {
// printf("Got data @%lx = %s\n", m_addr, valuer.c_str());
- indata = false;
ungetc(c, m_fp);
addrr = m_addr;
++m_addr;
@@ -1685,7 +1729,8 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
}
// Parse line
if (c == '\n') {
- ++m_linenum; ignore_to_eol = false;
+ ++m_linenum;
+ ignore_to_eol = false;
reading_addr = false;
} else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') {
reading_addr = false;
@@ -1695,15 +1740,22 @@ bool VlReadMem::get(QData& addrr, std::string& valuer) {
ignore_to_cmt = false;
reading_addr = false;
} else if (!ignore_to_eol && !ignore_to_cmt) {
- if (lastc == '/' && c == '*') { ignore_to_cmt = true; }
- else if (lastc == '/' && c == '/') { ignore_to_eol = true; }
- else if (c == '/') {} // Part of /* or //
- else if (c == '#') { ignore_to_eol = true; }
- else if (c == '@') { reading_addr = true; m_addr = 0; }
+ if (lastc == '/' && c == '*') {
+ ignore_to_cmt = true;
+ } else if (lastc == '/' && c == '/') {
+ ignore_to_eol = true;
+ } else if (c == '/') { // Part of /* or //
+ } else if (c == '#') {
+ ignore_to_eol = true;
+ } else if (c == '@') {
+ reading_addr = true;
+ m_addr = 0;
+ }
// Check for hex or binary digits as file format requests
else if (isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) {
c = tolower(c);
- int value = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c-'a'+10)) : (c-'0'));
+ int value
+ = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
if (reading_addr) {
// Decode @ addresses
m_addr = (m_addr << 4) + value;
@@ -1756,7 +1808,7 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
& VL_MASK_Q(m_bits);
} else {
WDataOutP datap = reinterpret_cast(valuep);
- if (!innum) { VL_ZERO_RESET_W(m_bits, datap); }
+ if (!innum) VL_ZERO_RESET_W(m_bits, datap);
_VL_SHIFTL_INPLACE_W(m_bits, datap, static_cast(shift));
datap[0] |= value;
}
@@ -1786,7 +1838,10 @@ VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData st
}
}
VlWriteMem::~VlWriteMem() {
- if (m_fp) { fclose(m_fp); m_fp = NULL; }
+ if (m_fp) {
+ fclose(m_fp);
+ m_fp = NULL;
+ }
}
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
if (VL_UNLIKELY(!m_fp)) return;
@@ -1846,17 +1901,14 @@ void VL_READMEM_N(bool hex, // Hex format, else binary
QData start, // First array row address to read
QData end // Last row address to read
) VL_MT_SAFE {
- QData addr_max = array_lsb + depth - 1;
if (start < static_cast(array_lsb)) start = array_lsb;
- QData addr_end = end;
- if (addr_end > addr_max) addr_end = addr_max;
VlReadMem rmem(hex, bits, filename, start, end);
if (VL_UNLIKELY(!rmem.isOpen())) return;
while (true) {
QData addr;
std::string value;
- if (rmem.get(addr /*ref*/, value/*ref*/)) {
+ if (rmem.get(addr /*ref*/, value /*ref*/)) {
if (VL_UNLIKELY(addr < static_cast(array_lsb)
|| addr >= static_cast(array_lsb + depth))) {
VL_FATAL_MT(filename.c_str(), rmem.linenum(), "",
@@ -1876,8 +1928,8 @@ void VL_READMEM_N(bool hex, // Hex format, else binary
QData* datap = &(reinterpret_cast(memp))[entry];
rmem.setData(datap, value);
} else {
- WDataOutP datap = &(reinterpret_cast(memp))
- [ entry*VL_WORDS_I(bits) ];
+ WDataOutP datap
+ = &(reinterpret_cast(memp))[entry * VL_WORDS_I(bits)];
rmem.setData(datap, value);
}
}
@@ -1935,7 +1987,10 @@ int VL_TIME_STR_CONVERT(const char* strp) {
int scale = 0;
if (!strp) return 0;
if (*strp++ != '1') return 0;
- while (*strp == '0') { scale++; strp++; }
+ while (*strp == '0') {
+ scale++;
+ strp++;
+ }
switch (*strp++) {
case 's': break;
case 'm': scale -= 3; break;
@@ -1949,6 +2004,69 @@ int VL_TIME_STR_CONVERT(const char* strp) {
if (*strp) return 0;
return scale;
}
+static const char* vl_time_str(int scale) {
+ static const char* const names[]
+ = {"1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns",
+ "10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs"};
+ if (scale < 0) scale = -scale;
+ if (VL_UNLIKELY(scale > 15)) scale = 0;
+ return names[scale];
+}
+double vl_time_multiplier(int scale) {
+ // Return timescale multipler -15 to +15
+ // For speed, this does not check for illegal values
+ static double pow10[] = {1.0,
+ 10.0,
+ 100.0,
+ 1000.0,
+ 10000.0,
+ 100000.0,
+ 1000000.0,
+ 10000000.0,
+ 100000000.0,
+ 1000000000.0,
+ 10000000000.0,
+ 100000000000.0,
+ 1000000000000.0,
+ 10000000000000.0,
+ 100000000000000.0,
+ 1000000000000000.0};
+ static double neg10[] = {1.0,
+ 0.1,
+ 0.01,
+ 0.001,
+ 0.0001,
+ 0.00001,
+ 0.000001,
+ 0.0000001,
+ 0.00000001,
+ 0.000000001,
+ 0.0000000001,
+ 0.00000000001,
+ 0.000000000001,
+ 0.0000000000001,
+ 0.00000000000001,
+ 0.000000000000001};
+ if (scale < 0) {
+ return neg10[-scale];
+ } else {
+ return pow10[scale];
+ }
+}
+const char* Verilated::timeunitString() VL_MT_SAFE { return vl_time_str(timeunit()); }
+const char* Verilated::timeprecisionString() VL_MT_SAFE { return vl_time_str(timeprecision()); }
+
+void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp) VL_MT_SAFE {
+ VL_PRINTF_MT("Time scale of %s is %s / %s\n", namep, timeunitp,
+ Verilated::timeprecisionString());
+}
+void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
+ int width) VL_MT_SAFE {
+ VerilatedImp::timeFormatUnits(units);
+ VerilatedImp::timeFormatPrecision(precision);
+ VerilatedImp::timeFormatSuffix(suffix);
+ VerilatedImp::timeFormatWidth(width);
+}
//===========================================================================
// Verilated:: Methods
@@ -1956,13 +2074,15 @@ int VL_TIME_STR_CONVERT(const char* strp) {
Verilated::ThreadLocal::ThreadLocal()
:
#ifdef VL_THREADED
- t_mtaskId(0),
- t_endOfEvalReqd(0),
+ t_mtaskId(0)
+ , t_endOfEvalReqd(0)
+ ,
#endif
- t_dpiScopep(NULL), t_dpiFilename(0), t_dpiLineno(0) {
-}
-Verilated::ThreadLocal::~ThreadLocal() {
+ t_dpiScopep(NULL)
+ , t_dpiFilename(0)
+ , t_dpiLineno(0) {
}
+Verilated::ThreadLocal::~ThreadLocal() {}
void Verilated::debug(int level) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
@@ -2014,6 +2134,43 @@ void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_fatalOnVpiError = flag;
}
+void Verilated::timeunit(int value) VL_MT_SAFE {
+ if (value < 0) value = -value; // Stored as 0..15
+ VerilatedLockGuard lock(m_mutex);
+ s_s.s_timeunit = value;
+}
+void Verilated::timeprecision(int value) VL_MT_SAFE {
+ if (value < 0) value = -value; // Stored as 0..15
+ VerilatedLockGuard lock(m_mutex);
+ s_s.s_timeprecision = value;
+#ifdef SYSTEMC_VERSION
+ sc_time sc_res = sc_get_time_resolution();
+ int sc_prec = 99;
+ if (sc_res == sc_time(1, SC_SEC)) {
+ sc_prec = 0;
+ } else if (sc_res == sc_time(1, SC_MS)) {
+ sc_prec = 3;
+ } else if (sc_res == sc_time(1, SC_US)) {
+ sc_prec = 6;
+ } else if (sc_res == sc_time(1, SC_NS)) {
+ sc_prec = 9;
+ } else if (sc_res == sc_time(1, SC_PS)) {
+ sc_prec = 12;
+ } else if (sc_res == sc_time(1, SC_FS)) {
+ sc_prec = 15;
+ }
+ if (value != sc_prec) {
+ std::ostringstream msg;
+ msg << "SystemC's sc_set_time_resolution is 10^-" << sc_prec
+ << ", which does not match Verilog timeprecision 10^-" << value
+ << ". Suggest use 'sc_set_time_resolution(" << vl_time_str(value)
+ << ")', or Verilator '--timescale-override " << vl_time_str(sc_prec) << "/"
+ << vl_time_str(sc_prec) << "'";
+ std::string msgs = msg.str();
+ VL_FATAL_MT("", 0, "", msgs.c_str());
+ }
+#endif
+}
void Verilated::profThreadsStart(vluint64_t flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_ns.s_profThreadsStart = flag;
@@ -2028,15 +2185,14 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
s_ns.s_profThreadsFilenamep = strdup(flagp);
}
-
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 = NULL;
- static VL_THREAD_LOCAL size_t len = 0;
- size_t newlen = strlen(n1)+strlen(n2)+strlen(delimiter)+1;
+ static VL_THREAD_LOCAL size_t len = 0;
+ size_t newlen = strlen(n1) + strlen(n2) + strlen(delimiter) + 1;
if (!strp || newlen > len) {
- if (strp) delete [] strp;
+ if (strp) delete[] strp;
strp = new char[newlen];
len = newlen;
}
@@ -2048,9 +2204,10 @@ const char* Verilated::catName(const char* n1, const char* n2, const char* delim
void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
- if (s_flushCb == cb) {} // Ok - don't duplicate
- else if (!s_flushCb) { s_flushCb=cb; }
- else { // LCOV_EXCL_LINE
+ if (s_flushCb == cb) { // Ok - don't duplicate
+ } else if (!s_flushCb) {
+ s_flushCb = cb;
+ } else { // LCOV_EXCL_LINE
// Someday we may allow multiple callbacks ala atexit(), but until then
VL_FATAL_MT("unknown", 0, "", // LCOV_EXCL_LINE
"Verilated::flushCb called twice with different callbacks");
@@ -2064,12 +2221,8 @@ void Verilated::flushCall() VL_MT_SAFE {
fflush(stdout);
}
-const char* Verilated::productName() VL_PURE {
- return VERILATOR_PRODUCT;
-}
-const char* Verilated::productVersion() VL_PURE {
- return VERILATOR_VERSION;
-}
+const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; }
+const char* Verilated::productVersion() VL_PURE { return VERILATOR_VERSION; }
void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
VerilatedLockGuard lock(s_args.m_argMutex);
@@ -2082,17 +2235,23 @@ 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];
if (match.empty()) return "";
- strncpy(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH);
- outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
+ outstr[0] = '\0';
+ strncat(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH - 1);
return outstr;
}
+void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
+ // Slowpath - Called only on error
+ VL_FATAL_MT(filename, linenum, "", "Null pointer dereferenced");
+ VL_UNREACHABLE
+}
+
void Verilated::overWidthError(const char* signame) VL_MT_SAFE {
// Slowpath - Called only when signal sets too high of a bit
- std::string msg = (std::string("Testbench C set input '")
- + signame
+ std::string msg = (std::string("Testbench C set input '") + signame
+ "' to value that overflows what the signal's width can fit");
VL_FATAL_MT("unknown", 0, "", msg.c_str());
+ VL_UNREACHABLE
}
void Verilated::mkdir(const char* dirname) VL_MT_UNSAFE {
@@ -2110,13 +2269,9 @@ void Verilated::quiesce() VL_MT_SAFE {
#endif
}
-void Verilated::internalsDump() VL_MT_SAFE {
- VerilatedImp::internalsDump();
-}
+void Verilated::internalsDump() VL_MT_SAFE { VerilatedImp::internalsDump(); }
-void Verilated::scopesDump() VL_MT_SAFE {
- VerilatedImp::scopesDump();
-}
+void Verilated::scopesDump() VL_MT_SAFE { VerilatedImp::scopesDump(); }
const VerilatedScope* Verilated::scopeFind(const char* namep) VL_MT_SAFE {
return VerilatedImp::scopeFind(namep);
@@ -2145,12 +2300,26 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
//===========================================================================
// VerilatedImp:: Methods
+std::string VerilatedImp::timeFormatSuffix() VL_MT_SAFE {
+ VerilatedLockGuard lock(s_s.m_sergMutex);
+ return s_s.m_serg.m_timeFormatSuffix;
+}
+void VerilatedImp::timeFormatSuffix(const std::string& value) VL_MT_SAFE {
+ VerilatedLockGuard lock(s_s.m_sergMutex);
+ s_s.m_serg.m_timeFormatSuffix = value;
+}
+void VerilatedImp::timeFormatUnits(int value) VL_MT_SAFE { s_s.m_ser.m_timeFormatUnits = value; }
+void VerilatedImp::timeFormatPrecision(int value) VL_MT_SAFE {
+ s_s.m_ser.m_timeFormatPrecision = value;
+}
+void VerilatedImp::timeFormatWidth(int value) VL_MT_SAFE { s_s.m_ser.m_timeFormatWidth = value; }
+
void VerilatedImp::internalsDump() VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_argMutex);
VL_PRINTF_MT("internalsDump:\n");
versionDump();
VL_PRINTF_MT(" Argv:");
- for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
+ for (ArgVec::const_iterator it = s_s.m_argVec.begin(); it != s_s.m_argVec.end(); ++it) {
VL_PRINTF_MT(" %s", it->c_str());
}
VL_PRINTF_MT("\n");
@@ -2159,8 +2328,7 @@ void VerilatedImp::internalsDump() VL_MT_SAFE {
userDump();
}
void VerilatedImp::versionDump() VL_MT_SAFE {
- VL_PRINTF_MT(" Version: %s %s\n",
- Verilated::productName(), Verilated::productVersion());
+ VL_PRINTF_MT(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
}
void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
@@ -2174,7 +2342,7 @@ void VerilatedImp::commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m
}
void VerilatedImp::commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex) {
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
- for (int i=0; i m_udims || dim > 3)) return NULL;
+ if (VL_UNLIKELY(dim <= 0 || dim > m_udims || dim > 3)) return NULL;
if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return NULL;
int indxAdj = indx - low(dim);
vluint8_t* bytep = reinterpret_cast(datap);
// If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
size_t slicesz = entSize();
- for (int d=dim+1; d<=m_udims; ++d) slicesz *= elements(d);
- bytep += indxAdj*slicesz;
+ for (int d = dim + 1; d <= m_udims; ++d) slicesz *= elements(d);
+ bytep += indxAdj * slicesz;
return bytep;
}
@@ -2322,20 +2476,21 @@ VerilatedScope::VerilatedScope() {
VerilatedScope::~VerilatedScope() {
// Memory cleanup - not called during normal operation
VerilatedImp::scopeErase(this);
- if (m_namep) { delete [] m_namep; m_namep = NULL; }
- if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; }
- if (m_varsp) { delete m_varsp; m_varsp = NULL; }
+ if (m_namep) VL_DO_CLEAR(delete[] m_namep, m_namep = NULL);
+ if (m_callbacksp) VL_DO_CLEAR(delete[] m_callbacksp, m_callbacksp = NULL);
+ if (m_varsp) VL_DO_CLEAR(delete m_varsp, m_varsp = NULL);
m_funcnumMax = 0; // Force callback table to empty
}
-void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp,
- const char* suffixp, const char* identifier,
+void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
+ const char* identifier, vlsint8_t timeunit,
const Type type) VL_MT_UNSAFE {
// Slowpath - called once/scope at construction
// We don't want the space and reference-count access overhead of strings.
m_symsp = symsp;
m_type = type;
- char* namep = new char[strlen(prefixp)+strlen(suffixp)+2];
+ m_timeunit = timeunit;
+ char* namep = new char[strlen(prefixp) + strlen(suffixp) + 2];
strcpy(namep, prefixp);
if (*prefixp && *suffixp) strcat(namep, ".");
strcat(namep, suffixp);
@@ -2351,15 +2506,15 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_
if (!finalize) {
// Need two passes so we know array size to create
// Alternative is to dynamically stretch the array, which is more code, and slower.
- if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
+ if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum + 1; }
} else {
if (VL_UNCOVERABLE(funcnum >= m_funcnumMax)) {
VL_FATAL_MT(__FILE__, __LINE__, "", // LCOV_EXCL_LINE
"Internal: Bad funcnum vs. pre-finalize maximum");
}
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
- m_callbacksp = new void* [m_funcnumMax];
- memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
+ m_callbacksp = new void*[m_funcnumMax];
+ memset(m_callbacksp, 0, m_funcnumMax * sizeof(void*));
}
m_callbacksp[funcnum] = cb;
}
@@ -2377,21 +2532,21 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
va_list ap;
va_start(ap, dims);
- for (int i=0; i=1 && i<=3) {
- var.m_unpacked[i-1].m_left = msb;
- var.m_unpacked[i-1].m_right = lsb;
+ } else if (i >= 1 && i <= 3) {
+ var.m_unpacked[i - 1].m_left = msb;
+ var.m_unpacked[i - 1].m_right = lsb;
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
- VL_FATAL_MT(__FILE__, __LINE__, "",
- (std::string("Unsupported multi-dimensional public varInsert: ")
- + namep).c_str());
+ VL_FATAL_MT(
+ __FILE__, __LINE__, "",
+ (std::string("Unsupported multi-dimensional public varInsert: ") + namep).c_str());
}
}
va_end(ap);
@@ -2403,9 +2558,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTINIT {
if (VL_LIKELY(m_varsp)) {
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
- if (VL_LIKELY(it != m_varsp->end())) {
- return &(it->second);
- }
+ if (VL_LIKELY(it != m_varsp->end())) return &(it->second);
}
return NULL;
}
@@ -2421,25 +2574,23 @@ void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
void* VerilatedScope::exportFindError(int funcnum) const {
// Slowpath - Called only when find has failed
- std::string msg = (std::string("Testbench C called '")
- +VerilatedImp::exportName(funcnum)
- +"' but this DPI export function exists only in other scopes, not scope '"
- +name()+"'");
+ std::string msg = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum)
+ + "' but this DPI export function exists only in other scopes, not scope '"
+ + name() + "'");
VL_FATAL_MT("unknown", 0, "", msg.c_str());
return NULL;
}
void VerilatedScope::scopeDump() const {
VL_PRINTF_MT(" SCOPE %p: %s\n", this, name());
- for (int i=0; ivarsp()) {
- for (VerilatedVarNameMap::const_iterator it = varsp->begin();
- it != varsp->end(); ++it) {
+ for (VerilatedVarNameMap::const_iterator it = varsp->begin(); it != varsp->end(); ++it) {
VL_PRINTF_MT(" VAR %p: %s\n", &(it->second), it->first);
}
}
@@ -2454,7 +2605,8 @@ void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) {
#if defined(VL_THREADED) && defined(VL_DEBUG)
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
- VL_FATAL_MT(__FILE__, __LINE__, "", "Routine called that is single threaded, but called from"
+ VL_FATAL_MT(__FILE__, __LINE__, "",
+ "Routine called that is single threaded, but called from"
" a different thread then the expected constructing thread");
}
#endif
diff --git a/include/verilated.h b/include/verilated.h
index 2aed894a1..06a70c978 100644
--- a/include/verilated.h
+++ b/include/verilated.h
@@ -23,7 +23,11 @@
#ifndef _VERILATED_H_
#define _VERILATED_H_ 1 ///< Header Guard
+// clang-format off
#include "verilatedos.h"
+#if VM_SC
+# include "verilated_sc.h" // Get SYSTEMC_VERSION and time declarations
+#endif
#include
#include
@@ -42,19 +46,29 @@
// Allow user to specify their own include file
#ifdef VL_VERILATED_INCLUDE
+// cppcheck-suppress preprocessorErrorDirective
# include VL_VERILATED_INCLUDE
#endif
+// clang-format on
//=============================================================================
// Switches
+// clang-format off
#if VM_TRACE // Verilator tracing requested
# define WAVES 1 // Set backward compatibility flag
#endif
+// Version check
+#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION < 20111121)
+# warning "Verilator soon requires SystemC 2.3.*; see manual for deprecated other versions."
+#endif
+// clang-format on
+
//=========================================================================
// Basic types
+// clang-format off
// P // Packed data of bit type (C/S/I/Q/W)
typedef vluint8_t CData; ///< Verilated pack data, 1-8 bits
typedef vluint16_t SData; ///< Verilated pack data, 9-16 bits
@@ -65,6 +79,7 @@ typedef EData WData; ///< Verilated pack data, >64 bits, as an array
// float F // No typedef needed; Verilator uses float
// double D // No typedef needed; Verilator uses double
// string N // No typedef needed; Verilator uses string
+// clang-format on
typedef const WData* WDataInP; ///< Array input to a function
typedef WData* WDataOutP; ///< Array output from a function
@@ -84,27 +99,27 @@ class VerilatedFst;
class VerilatedFstC;
enum VerilatedVarType {
- VLVT_UNKNOWN=0,
- VLVT_PTR, // Pointer to something
- VLVT_UINT8, // AKA CData
- VLVT_UINT16, // AKA SData
- VLVT_UINT32, // AKA IData
- VLVT_UINT64, // AKA QData
- VLVT_WDATA, // AKA WData
- VLVT_STRING // C++ string
+ VLVT_UNKNOWN = 0,
+ VLVT_PTR, // Pointer to something
+ VLVT_UINT8, // AKA CData
+ VLVT_UINT16, // AKA SData
+ VLVT_UINT32, // AKA IData
+ VLVT_UINT64, // AKA QData
+ VLVT_WDATA, // AKA WData
+ VLVT_STRING // C++ string
};
enum VerilatedVarFlags {
- VLVD_0 = 0, // None
- VLVD_IN = 1, // == vpiInput
- VLVD_OUT = 2, // == vpiOutput
- VLVD_INOUT = 3, // == vpiInOut
- VLVD_NODIR = 5, // == vpiNoDirection
+ VLVD_0 = 0, // None
+ VLVD_IN = 1, // == vpiInput
+ VLVD_OUT = 2, // == vpiOutput
+ VLVD_INOUT = 3, // == vpiInOut
+ VLVD_NODIR = 5, // == vpiNoDirection
VLVF_MASK_DIR = 7, // Bit mask for above directions
// Flags
- VLVF_PUB_RD = (1<<8), // Public readable
- VLVF_PUB_RW = (1<<9), // Public writable
- VLVF_DPI_CLAY = (1<<10) // DPI compatible C standard layout
+ VLVF_PUB_RD = (1 << 8), // Public readable
+ VLVF_PUB_RW = (1 << 9), // Public writable
+ VLVF_DPI_CLAY = (1 << 10) // DPI compatible C standard layout
};
//=========================================================================
@@ -119,9 +134,9 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
/// Mutex, wrapped to allow -fthread_safety checks
class VL_CAPABILITY("mutex") VerilatedMutex {
- private:
+private:
std::mutex m_mutex; // Mutex
- public:
+public:
VerilatedMutex() {}
~VerilatedMutex() {}
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
@@ -146,16 +161,16 @@ class VL_CAPABILITY("mutex") VerilatedMutex {
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
class VL_SCOPED_CAPABILITY VerilatedLockGuard {
VL_UNCOPYABLE(VerilatedLockGuard);
- private:
+
+private:
VerilatedMutex& m_mutexr;
- public:
+
+public:
explicit VerilatedLockGuard(VerilatedMutex& mutexr) VL_ACQUIRE(mutexr)
: m_mutexr(mutexr) {
m_mutexr.lock();
}
- ~VerilatedLockGuard() VL_RELEASE() {
- m_mutexr.unlock();
- }
+ ~VerilatedLockGuard() VL_RELEASE() { m_mutexr.unlock(); }
void lock() VL_ACQUIRE() { m_mutexr.lock(); }
void unlock() VL_RELEASE() { m_mutexr.unlock(); }
};
@@ -172,6 +187,7 @@ public:
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
class VerilatedLockGuard {
VL_UNCOPYABLE(VerilatedLockGuard);
+
public:
explicit VerilatedLockGuard(VerilatedMutex&) {}
~VerilatedLockGuard() {}
@@ -220,6 +236,7 @@ class VerilatedScope;
class VerilatedModule {
VL_UNCOPYABLE(VerilatedModule);
+
private:
const char* m_namep; ///< Module name
public:
@@ -231,55 +248,56 @@ public:
//=========================================================================
// Declare nets
-#ifndef VL_SIG
-# define VL_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits
-# define VL_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits
-# define VL_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits
-# define VL_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits
-# define VL_SIGW(name, msb,lsb, words) WData name[words] ///< Declare signal, 65+ bits
-# define VL_IN8(name, msb,lsb) CData name ///< Declare input signal, 1-8 bits
-# define VL_IN16(name, msb,lsb) SData name ///< Declare input signal, 9-16 bits
-# define VL_IN64(name, msb,lsb) QData name ///< Declare input signal, 33-64 bits
-# define VL_IN(name, msb,lsb) IData name ///< Declare input signal, 17-32 bits
-# define VL_INW(name, msb,lsb, words) WData name[words] ///< Declare input signal, 65+ bits
-# define VL_INOUT8(name, msb,lsb) CData name ///< Declare bidir signal, 1-8 bits
-# define VL_INOUT16(name, msb,lsb) SData name ///< Declare bidir signal, 9-16 bits
-# define VL_INOUT64(name, msb,lsb) QData name ///< Declare bidir signal, 33-64 bits
-# define VL_INOUT(name, msb,lsb) IData name ///< Declare bidir signal, 17-32 bits
-# define VL_INOUTW(name, msb,lsb, words) WData name[words] ///< Declare bidir signal, 65+ bits
-# define VL_OUT8(name, msb,lsb) CData name ///< Declare output signal, 1-8 bits
-# define VL_OUT16(name, msb,lsb) SData name ///< Declare output signal, 9-16 bits
-# define VL_OUT64(name, msb,lsb) QData name ///< Declare output signal, 33-64bits
-# define VL_OUT(name, msb,lsb) IData name ///< Declare output signal, 17-32 bits
-# define VL_OUTW(name, msb,lsb, words) WData name[words] ///< Declare output signal, 65+ bits
+#define VL_SIG8(name, msb, lsb) CData name ///< Declare signal, 1-8 bits
+#define VL_SIG16(name, msb, lsb) SData name ///< Declare signal, 9-16 bits
+#define VL_SIG64(name, msb, lsb) QData name ///< Declare signal, 33-64 bits
+#define VL_SIG(name, msb, lsb) IData name ///< Declare signal, 17-32 bits
+#define VL_SIGW(name, msb, lsb, words) WData name[words] ///< Declare signal, 65+ bits
+#define VL_IN8(name, msb, lsb) CData name ///< Declare input signal, 1-8 bits
+#define VL_IN16(name, msb, lsb) SData name ///< Declare input signal, 9-16 bits
+#define VL_IN64(name, msb, lsb) QData name ///< Declare input signal, 33-64 bits
+#define VL_IN(name, msb, lsb) IData name ///< Declare input signal, 17-32 bits
+#define VL_INW(name, msb, lsb, words) WData name[words] ///< Declare input signal, 65+ bits
+#define VL_INOUT8(name, msb, lsb) CData name ///< Declare bidir signal, 1-8 bits
+#define VL_INOUT16(name, msb, lsb) SData name ///< Declare bidir signal, 9-16 bits
+#define VL_INOUT64(name, msb, lsb) QData name ///< Declare bidir signal, 33-64 bits
+#define VL_INOUT(name, msb, lsb) IData name ///< Declare bidir signal, 17-32 bits
+#define VL_INOUTW(name, msb, lsb, words) WData name[words] ///< Declare bidir signal, 65+ bits
+#define VL_OUT8(name, msb, lsb) CData name ///< Declare output signal, 1-8 bits
+#define VL_OUT16(name, msb, lsb) SData name ///< Declare output signal, 9-16 bits
+#define VL_OUT64(name, msb, lsb) QData name ///< Declare output signal, 33-64bits
+#define VL_OUT(name, msb, lsb) IData name ///< Declare output signal, 17-32 bits
+#define VL_OUTW(name, msb, lsb, words) WData name[words] ///< Declare output signal, 65+ bits
-# define VL_PIN_NOP(instname,pin,port) ///< Connect a pin, ala SP_PIN
-# define VL_CELL(instname,type) ///< Declare a cell, ala SP_CELL
+#define VL_PIN_NOP(instname, pin, port) ///< Connect a pin, ala SP_PIN
+#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 : public VerilatedModule
/// Constructor, ala SC_CTOR
-# define VL_CTOR(modname) modname(const char* __VCname="")
+#define VL_CTOR(modname) modname(const char* __VCname = "")
/// Constructor declaration for C++, ala SP_CTOR_IMPL
-# define VL_CTOR_IMP(modname) modname::modname(const char* __VCname) : VerilatedModule(__VCname)
+#define VL_CTOR_IMP(modname) \
+ modname::modname(const char* __VCname) \
+ : VerilatedModule(__VCname)
/// Constructor declaration for SystemC, ala SP_CTOR_IMPL
-# define VL_SC_CTOR_IMP(modname) modname::modname(sc_module_name)
-
-#endif
+#define VL_SC_CTOR_IMP(modname) modname::modname(sc_module_name)
//=========================================================================
// Functions overridable by user defines
// (Internals however must use VL_PRINTF_MT, which calls these.)
+// clang-format off
#ifndef VL_PRINTF
-# define VL_PRINTF printf ///< Print ala printf, called from main thread; may redefine if desired
+# define VL_PRINTF printf ///< Print ala printf, called from main thread; redefine if desired
#endif
#ifndef VL_VPRINTF
-# define VL_VPRINTF vprintf ///< Print ala vprintf, called from main thread; may redefine if desired
+# define VL_VPRINTF vprintf ///< Print ala vprintf, called from main thread; redefine if desired
#endif
+// clang-format on
//===========================================================================
/// Verilator symbol table base class
@@ -300,30 +318,33 @@ public: // But for internal use only
class VerilatedScope {
public:
typedef enum {
- SCOPE_MODULE, SCOPE_OTHER
+ SCOPE_MODULE,
+ SCOPE_OTHER
} Type; // Type of a scope, currently module is only interesting
private:
// Fastpath:
- VerilatedSyms* m_symsp; ///< Symbol table
- void** m_callbacksp; ///< Callback table pointer (Fastpath)
- int m_funcnumMax; ///< Maxium function number stored (Fastpath)
+ VerilatedSyms* m_symsp; ///< Symbol table
+ void** m_callbacksp; ///< Callback table pointer (Fastpath)
+ int m_funcnumMax; ///< Maxium function number stored (Fastpath)
// 4 bytes padding (on -m64), for rent.
- VerilatedVarNameMap* m_varsp; ///< Variable map
- const char* m_namep; ///< Scope name (Slowpath)
- const char* m_identifierp; ///< Identifier of scope (with escapes removed)
- Type m_type; ///< Type of the scope
+ VerilatedVarNameMap* m_varsp; ///< Variable map
+ const char* m_namep; ///< Scope name (Slowpath)
+ const char* m_identifierp; ///< Identifier of scope (with escapes removed)
+ vlsint8_t m_timeunit; ///< Timeunit in negative power-of-10
+ Type m_type; ///< Type of the scope
public: // But internals only - called from VerilatedModule's
VerilatedScope();
~VerilatedScope();
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
- const char* identifier, const Type type) VL_MT_UNSAFE;
+ const char* identifier, vlsint8_t timeunit, const Type type) VL_MT_UNSAFE;
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
- void varInsert(int finalize, const char* namep, void* datap,
- VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE;
+ void varInsert(int finalize, const char* namep, void* datap, VerilatedVarType vltype,
+ int vlflags, int dims, ...) VL_MT_UNSAFE;
// ACCESSORS
const char* name() const { return m_namep; }
const char* identifier() const { return m_identifierp; }
+ vlsint8_t timeunit() const { return m_timeunit; }
inline VerilatedSyms* symsp() const { return m_symsp; }
VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT;
VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; }
@@ -359,12 +380,14 @@ class Verilated {
static struct Serialized { // All these members serialized/deserialized
// Fast path
- int s_debug; ///< See accessors... only when VL_DEBUG set
- bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
- bool s_gotFinish; ///< A $finish statement executed
- bool s_assertOn; ///< Assertions are enabled
- bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
+ int s_debug; ///< See accessors... only when VL_DEBUG set
+ bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
+ bool s_gotFinish; ///< A $finish statement executed
+ bool s_assertOn; ///< Assertions are enabled
+ bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
// Slow path
+ unsigned s_timeunit : 4; ///< Time unit as 0..15
+ unsigned s_timeprecision : 4; ///< Time precision as 0..15
int s_errorCount; ///< Number of errors
int s_errorLimit; ///< Stop on error number
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
@@ -390,7 +413,9 @@ class Verilated {
VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED
int argc;
const char** argv;
- CommandArgValues() : argc(0), argv(NULL) {}
+ CommandArgValues()
+ : argc(0)
+ , argv(NULL) {}
~CommandArgValues() {}
} s_args;
@@ -433,12 +458,14 @@ public:
/// changing the level (no mutex)
static inline int debug() VL_MT_SAFE { return s_s.s_debug; }
#else
- static inline int debug() VL_PURE { return 0; } ///< Return constant 0 debug level, so C++'s optimizer rips up
+ /// Return constant 0 debug level, so C++'s optimizer rips up
+ static inline int debug() VL_PURE { return 0; }
#endif
/// Enable calculation of unused signals
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
static bool calcUnusedSigs() VL_MT_SAFE { ///< Return calcUnusedSigs value
- return s_s.s_calcUnusedSigs; }
+ return s_s.s_calcUnusedSigs;
+ }
/// Current number of errors/assertions
static void errorCount(int val) VL_MT_SAFE;
static void errorCountInc() VL_MT_SAFE;
@@ -459,6 +486,13 @@ public:
/// Enable/disable vpi fatal
static void fatalOnVpiError(bool flag) VL_MT_SAFE;
static bool fatalOnVpiError() VL_MT_SAFE { return s_s.s_fatalOnVpiError; }
+ /// Time handling
+ static int timeunit() VL_MT_SAFE { return -s_s.s_timeunit; }
+ static const char* timeunitString() VL_MT_SAFE;
+ static void timeunit(int value) VL_MT_SAFE;
+ static int timeprecision() VL_MT_SAFE { return -s_s.s_timeprecision; }
+ static const char* timeprecisionString() VL_MT_SAFE;
+ static void timeprecision(int value) VL_MT_SAFE;
/// --prof-threads related settings
static void profThreadsStart(vluint64_t flag) VL_MT_SAFE;
static vluint64_t profThreadsStart() VL_MT_SAFE { return s_ns.s_profThreadsStart; }
@@ -476,7 +510,8 @@ public:
/// This should be called before the first model is created.
static void commandArgs(int argc, const char** argv) VL_MT_SAFE;
static void commandArgs(int argc, char** argv) VL_MT_SAFE {
- commandArgs(argc, const_cast(argv)); }
+ commandArgs(argc, const_cast(argv));
+ }
static void commandArgsAdd(int argc, const char** argv);
static CommandArgValues* getCommandArgs() VL_MT_SAFE { return &s_args; }
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
@@ -510,7 +545,8 @@ public:
const char* delimiter = "."); // Returns static data
// Internal: Throw signal assertion
- static void overWidthError(const char* signame) VL_MT_SAFE;
+ static void nullPointerError(const char* filename, int linenum) VL_ATTR_NORETURN VL_MT_SAFE;
+ static void overWidthError(const char* signame) VL_ATTR_NORETURN VL_MT_SAFE;
// Internal: Find scope
static const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE;
@@ -519,16 +555,22 @@ public:
// Internal: Get and set DPI context
static const VerilatedScope* dpiScope() VL_MT_SAFE { return t_s.t_dpiScopep; }
static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep = scopep; }
- static void dpiContext(const VerilatedScope* scopep, const char* filenamep, int lineno) VL_MT_SAFE {
- t_s.t_dpiScopep = scopep; t_s.t_dpiFilename = filenamep; t_s.t_dpiLineno = lineno; }
+ static void dpiContext(const VerilatedScope* scopep, const char* filenamep,
+ int lineno) VL_MT_SAFE {
+ t_s.t_dpiScopep = scopep;
+ t_s.t_dpiFilename = filenamep;
+ t_s.t_dpiLineno = lineno;
+ }
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = NULL; }
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != NULL; }
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
static int exportFuncNum(const char* namep) VL_MT_SAFE;
- static size_t serializedSize() VL_PURE { return sizeof(s_s); }
- static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
+ static size_t serialized1Size() VL_PURE { return sizeof(s_s); }
+ static void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
+ static size_t serialized2Size() VL_PURE;
+ static void* serialized2Ptr() VL_MT_UNSAFE;
#ifdef VL_THREADED
/// Set the mtaskId, called when an mtask starts
static void mtaskId(vluint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
@@ -576,8 +618,7 @@ extern void vl_stop(const char* filename, int linenum, const char* hier);
/// User code may wish to replace this function, to do so, define VL_USER_FATAL.
/// This code does not have to be thread safe.
/// Verilator internal code must call VL_FINISH_MT instead, which eventually calls this.
-extern void vl_fatal(const char* filename, int linenum, const char* hier,
- const char* msg);
+extern void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg);
//=========================================================================
// Extern functions -- Slow path
@@ -591,12 +632,15 @@ extern void VL_STOP_MT(const char* filename, int linenum, const char* hier,
extern void VL_FATAL_MT(const char* filename, int linenum, const char* hier,
const char* msg) VL_MT_SAFE;
+// clang-format off
/// Print a string, multithread safe. Eventually VL_PRINTF will get called.
#ifdef VL_THREADED
extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
#else
# define VL_PRINTF_MT VL_PRINTF // The following parens will take care of themselves
#endif
+// clang-format on
+
/// Print a debug message from internals with standard prefix, with printf style format
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
@@ -608,16 +652,23 @@ extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a sign
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
-extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal (slow - else use VL_ZERO_W)
+/// Zero reset a signal (slow - else use VL_ZERO_W)
+extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp);
#if VL_THREADED
/// Return high-precision counter for profiling, or 0x0 if not available
-inline QData VL_RDTSC_Q() { vluint64_t val; VL_RDTSC(val); return val; }
+inline QData VL_RDTSC_Q() {
+ vluint64_t val;
+ VL_RDTSC(val);
+ return val;
+}
#endif
+extern void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp) VL_MT_SAFE;
+
/// Math
-extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp,
- WDataInP lwp, WDataInP rwp, bool is_modulus);
+extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
+ bool is_modulus);
/// File I/O
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
@@ -626,12 +677,13 @@ extern IData VL_FOPEN_S(const char* filenamep, const char* modep);
extern IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode);
extern IData VL_FOPEN_QI(QData filename, IData mode);
inline IData VL_FOPEN_II(IData filename, IData mode) VL_MT_SAFE {
- return VL_FOPEN_QI(filename, mode); }
+ return VL_FOPEN_QI(filename, mode);
+}
extern void VL_FCLOSE_I(IData fdi);
-extern IData VL_FREAD_I(int width, int array_lsb, int array_size,
- void* memp, IData fpi, IData start, IData count);
+extern IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi,
+ IData start, IData count);
extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
@@ -658,41 +710,64 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
// Base macros
/// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
-#define VL_BITISSET_I(data,bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit)))
-#define VL_BITISSET_Q(data,bit) ((data) & (VL_ULL(1) << VL_BITBIT_Q(bit)))
-#define VL_BITISSET_E(data,bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
-#define VL_BITISSET_W(data,bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
-#define VL_BITISSETLIMIT_W(data,width,bit) (((bit) < (width)) && VL_BITISSET_W(data,bit))
+#define VL_BITISSET_I(data, bit) ((data) & (VL_UL(1) << VL_BITBIT_I(bit)))
+#define VL_BITISSET_Q(data, bit) ((data) & (VL_ULL(1) << VL_BITBIT_Q(bit)))
+#define VL_BITISSET_E(data, bit) ((data) & (VL_EUL(1) << VL_BITBIT_E(bit)))
+#define VL_BITISSET_W(data, bit) ((data)[VL_BITWORD_E(bit)] & (VL_EUL(1) << VL_BITBIT_E(bit)))
+#define VL_BITISSETLIMIT_W(data, width, bit) (((bit) < (width)) && VL_BITISSET_W(data, bit))
/// Shift appropriate word by bit. Does not account for wrapping between two words
-#define VL_BITRSHIFT_W(data,bit) ((data)[VL_BITWORD_E(bit)] >> VL_BITBIT_E(bit))
+#define VL_BITRSHIFT_W(data, bit) ((data)[VL_BITWORD_E(bit)] >> VL_BITBIT_E(bit))
/// Create two 32-bit words from quadword
/// WData is always at least 2 words; does not clean upper bits
-#define VL_SET_WQ(owp,data) { (owp)[0] = static_cast(data); \
- (owp)[1] = static_cast((data) >> VL_EDATASIZE); }
-#define VL_SET_WI(owp,data) { (owp)[0] = static_cast(data); (owp)[1] = 0; }
+#define VL_SET_WQ(owp, data) \
+ { \
+ (owp)[0] = static_cast(data); \
+ (owp)[1] = static_cast((data) >> VL_EDATASIZE); \
+ }
+#define VL_SET_WI(owp, data) \
+ { \
+ (owp)[0] = static_cast(data); \
+ (owp)[1] = 0; \
+ }
#define VL_SET_QW(lwp) \
- ( (static_cast((lwp)[0])) \
- | (static_cast((lwp)[1]) << (static_cast(VL_EDATASIZE)) ))
-#define _VL_SET_QII(ld,rd) ((static_cast(ld)<(rd))
+ ((static_cast((lwp)[0])) \
+ | (static_cast((lwp)[1]) << (static_cast(VL_EDATASIZE))))
+#define _VL_SET_QII(ld, rd) ((static_cast(ld) << VL_ULL(32)) | static_cast(rd))
/// Return FILE* from IData
-extern FILE* VL_CVT_I_FP(IData lhs);
+extern FILE* VL_CVT_I_FP(IData lhs);
+// clang-format off
// Use a union to avoid cast-to-different-size warnings
/// Return void* from QData
-static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
- union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
+static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
+ union { void* fp; QData q; } u;
+ 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; u.q=0; u.fp=fp; return u.q; }
+static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
+ union { void* fp; QData q; } u;
+ u.q = 0;
+ u.fp = fp;
+ return u.q;
+}
/// Return double from QData (bits, not numerically)
static inline double VL_CVT_D_Q(QData lhs) VL_PURE {
- union { double d; QData q; } u; u.q=lhs; return u.d; }
+ union { double d; QData q; } u;
+ u.q = lhs;
+ return u.d;
+}
/// Return QData from double (bits, not numerically)
-static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
- union { double d; QData q; } u; u.d=lhs; return u.q; }
+static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
+ union { double d; QData q; } u;
+ u.d = lhs;
+ return u.q;
+}
+// clang-format on
+
/// Return double from QData (numeric)
static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
return static_cast(static_cast(lhs));
@@ -704,19 +779,21 @@ static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input)
-#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1)))
-#define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1)))
-#define VL_SIGN_E(nbits,lhs) ((lhs) >> VL_BITBIT_E((nbits) - VL_EUL(1)))
-#define VL_SIGN_W(nbits,rwp) \
- ((rwp)[VL_BITWORD_E((nbits) - VL_EUL(1))] >> VL_BITBIT_E((nbits) - VL_EUL(1)))
+#define VL_SIGN_I(nbits, lhs) ((lhs) >> VL_BITBIT_I((nbits)-VL_UL(1)))
+#define VL_SIGN_Q(nbits, lhs) ((lhs) >> VL_BITBIT_Q((nbits)-VL_ULL(1)))
+#define VL_SIGN_E(nbits, lhs) ((lhs) >> VL_BITBIT_E((nbits)-VL_EUL(1)))
+#define VL_SIGN_W(nbits, rwp) \
+ ((rwp)[VL_BITWORD_E((nbits)-VL_EUL(1))] >> VL_BITBIT_E((nbits)-VL_EUL(1)))
#define VL_SIGNONES_E(nbits, lhs) (-(VL_SIGN_E(nbits, lhs)))
// Sign bit extended up to MSB, doesn't include unsigned portion
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE {
- return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
+ return (-((lhs) & (VL_UL(1) << (lbits - 1))));
+}
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE {
- return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
+ return (-((lhs) & (VL_ULL(1) << (lbits - 1))));
+}
// Debugging prints
extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
@@ -726,48 +803,70 @@ extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
extern int VL_TIME_STR_CONVERT(const char* strp) VL_PURE;
+// These are deprecated and used only to establish the default precision/units.
+// Use Verilator timescale-override for better control.
+// clang-format off
#ifndef VL_TIME_PRECISION
# ifdef VL_TIME_PRECISION_STR
# define VL_TIME_PRECISION VL_TIME_STR_CONVERT(VL_STRINGIFY(VL_TIME_PRECISION_STR))
# else
-# define VL_TIME_PRECISION (-12) ///< Timescale units only for for VPI return - picoseconds
+# define VL_TIME_PRECISION (-12) ///< Timescale default units if not in Verilog - picoseconds
# endif
#endif
#ifndef VL_TIME_UNIT
# ifdef VL_TIME_UNIT_STR
# define VL_TIME_UNIT VL_TIME_STR_CONVERT(VL_STRINGIFY(VL_TIME_PRECISION_STR))
# else
-# define VL_TIME_UNIT (-12) ///< Timescale units only for for VPI return - picoseconds
+# define VL_TIME_UNIT (-12) ///< Timescale default units if not in Verilog - picoseconds
# endif
#endif
-#ifndef VL_TIME_MULTIPLIER
-# define VL_TIME_MULTIPLIER 1
-#endif
/// Return current simulation time
-#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
-# define VL_TIME_I() (static_cast(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
-# define VL_TIME_Q() (static_cast(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
-# define VL_TIME_D() (static_cast(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
-#else
-# define VL_TIME_I() (static_cast(sc_time_stamp()*VL_TIME_MULTIPLIER))
-# define VL_TIME_Q() (static_cast(sc_time_stamp()*VL_TIME_MULTIPLIER))
-# define VL_TIME_D() (static_cast(sc_time_stamp()*VL_TIME_MULTIPLIER))
-extern double sc_time_stamp();
+#if defined(SYSTEMC_VERSION)
+# if SYSTEMC_VERSION > 20011000
+// Already defined: extern sc_time sc_time_stamp();
+inline vluint64_t vl_time_stamp64() { return sc_time_stamp().value(); }
+# else // Before SystemC changed to integral time representation
+// Already defined: extern double sc_time_stamp();
+inline vluint64_t vl_time_stamp64() { return static_cast(sc_time_stamp()); }
+# endif
+#else // Non-SystemC
+# ifdef VL_TIME_STAMP64
+extern vluint64_t vl_time_stamp64();
+# else
+extern double sc_time_stamp(); // Verilator 4.032 and newer
+inline vluint64_t vl_time_stamp64() { return static_cast(sc_time_stamp()); }
+# endif
#endif
+#define VL_TIME_I() (static_cast(vl_time_stamp64()))
+#define VL_TIME_Q() (static_cast(vl_time_stamp64()))
+#define VL_TIME_D() (static_cast(vl_time_stamp64()))
+
+/// Time scaled from 1-per-precision into a module's time units ("Unit"-ed, not "United")
+// Optimized assuming scale is always constant.
+// Can't use multiply in Q flavor, as might lose precision
+#define VL_TIME_UNITED_Q(scale) (VL_TIME_Q() / static_cast(scale))
+#define VL_TIME_UNITED_D(scale) (VL_TIME_D() * (1.0 / (scale)))
+/// Time imported from units to time precision
+double vl_time_multiplier(int scale);
+
/// Evaluate expression if debug enabled
#ifdef VL_DEBUG
-# define VL_DEBUG_IF(text) {if (VL_UNLIKELY(Verilated::debug())) {text}}
+# define VL_DEBUG_IF(text) \
+ do { \
+ if (VL_UNLIKELY(Verilated::debug())) {text} \
+ } while (false)
#else
-# define VL_DEBUG_IF(text)
+// We intentionally do not compile the text to improve compile speed
+# define VL_DEBUG_IF(text) do {} while (false)
#endif
/// Collect coverage analysis for this line
#ifndef SP_AUTO_COVER3
# define SP_AUTO_COVER3(what,file,line)
#endif
-
+// clang-format on
//=========================================================================
// Functional macros/routines
@@ -783,31 +882,31 @@ extern double sc_time_stamp();
// Output clean
// EMIT_RULE: VL_CLEAN: oclean=clean; obits=lbits;
-#define VL_CLEAN_II(obits,lbits,lhs) ((lhs) & VL_MASK_I(obits))
-#define VL_CLEAN_QQ(obits,lbits,lhs) ((lhs) & VL_MASK_Q(obits))
+#define VL_CLEAN_II(obits, lbits, lhs) ((lhs)&VL_MASK_I(obits))
+#define VL_CLEAN_QQ(obits, lbits, lhs) ((lhs)&VL_MASK_Q(obits))
// EMIT_RULE: VL_ASSIGNCLEAN: oclean=clean; obits==lbits;
-#define VL_ASSIGNCLEAN_W(obits,owp,lwp) VL_CLEAN_WW((obits), (obits), (owp), (lwp))
+#define VL_ASSIGNCLEAN_W(obits, owp, lwp) VL_CLEAN_WW((obits), (obits), (owp), (lwp))
static inline WDataOutP _VL_CLEAN_INPLACE_W(int obits, WDataOutP owp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
- owp[words-1] &= VL_MASK_E(obits);
+ owp[words - 1] &= VL_MASK_E(obits);
return owp;
}
static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
- for (int i=0; (i < (words-1)); ++i) owp[i] = lwp[i];
- owp[words-1] = lwp[words-1] & VL_MASK_E(obits);
+ for (int i = 0; (i < (words - 1)); ++i) owp[i] = lwp[i];
+ owp[words - 1] = lwp[words - 1] & VL_MASK_E(obits);
return owp;
}
static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
- for (int i=0; i < words; ++i) owp[i] = 0;
+ for (int i = 0; i < words; ++i) owp[i] = 0;
return owp;
}
static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < (words - 1); ++i) owp[i] = ~VL_EUL(0);
- owp[words-1] = VL_MASK_E(obits);
+ owp[words - 1] = VL_MASK_E(obits);
return owp;
}
@@ -816,25 +915,22 @@ static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) VL_MT_SAFE {
// Note: If a ASSIGN isn't clean, use VL_ASSIGNCLEAN instead to do the same thing.
static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
- for (int i=0; i < words; ++i) owp[i] = lwp[i];
+ for (int i = 0; i < words; ++i) owp[i] = lwp[i];
return owp;
}
// EMIT_RULE: VL_ASSIGNBIT: rclean=clean;
static inline void VL_ASSIGNBIT_II(int, int bit, CData& lhsr, IData rhs) VL_PURE {
- lhsr = ((lhsr & ~(VL_UL(1)<(rhs) << VL_BITBIT_Q(bit)));
}
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) VL_MT_SAFE {
@@ -865,71 +961,87 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF
// Copying verilog format to systemc integers and bit vectors.
// Get a SystemC variable
-#define VL_ASSIGN_ISI(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits), (obits), (svar).read()); }
-#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits), (obits), (svar).read()); }
+#define VL_ASSIGN_ISI(obits, vvar, svar) \
+ { (vvar) = VL_CLEAN_II((obits), (obits), (svar).read()); }
+#define VL_ASSIGN_QSQ(obits, vvar, svar) \
+ { (vvar) = VL_CLEAN_QQ((obits), (obits), (svar).read()); }
-#define VL_ASSIGN_ISW(obits,od,svar) { \
- (od) = ((svar).read().get_word(0)) & VL_MASK_I(obits); \
+#define VL_ASSIGN_ISW(obits, od, svar) \
+ { (od) = ((svar).read().get_word(0)) & VL_MASK_I(obits); }
+#define VL_ASSIGN_QSW(obits, od, svar) \
+ { \
+ (od) = ((static_cast((svar).read().get_word(1))) << VL_IDATASIZE \
+ | (svar).read().get_word(0)) \
+ & VL_MASK_Q(obits); \
}
-#define VL_ASSIGN_QSW(obits,od,svar) { \
- (od) = ((static_cast((svar).read().get_word(1)))< _butemp = (svar).read(); \
- for (int i=0; i < words; ++i) { \
- int msb = ((i + 1) * VL_IDATASIZE) - 1; \
- msb = (msb >= (obits)) ? ((obits)-1) : msb; \
- (owp)[i] = _butemp.range(msb, i * VL_IDATASIZE).to_uint(); \
- } \
- (owp)[words-1] &= VL_MASK_E(obits); \
+#define VL_ASSIGN_ISU(obits, vvar, svar) \
+ { (vvar) = VL_CLEAN_II((obits), (obits), (svar).read().to_uint()); }
+#define VL_ASSIGN_QSU(obits, vvar, svar) \
+ { (vvar) = VL_CLEAN_QQ((obits), (obits), (svar).read().to_uint64()); }
+#define VL_ASSIGN_WSB(obits, owp, svar) \
+ { \
+ int words = VL_WORDS_I(obits); \
+ sc_biguint<(obits)> _butemp = (svar).read(); \
+ for (int i = 0; i < words; ++i) { \
+ int msb = ((i + 1) * VL_IDATASIZE) - 1; \
+ msb = (msb >= (obits)) ? ((obits)-1) : msb; \
+ (owp)[i] = _butemp.range(msb, i * VL_IDATASIZE).to_uint(); \
+ } \
+ (owp)[words - 1] &= VL_MASK_E(obits); \
}
// Copying verilog format from systemc integers and bit vectors.
// Set a SystemC variable
-#define VL_ASSIGN_SII(obits,svar,vvar) { (svar).write(vvar); }
-#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
+#define VL_ASSIGN_SII(obits, svar, vvar) \
+ { (svar).write(vvar); }
+#define VL_ASSIGN_SQQ(obits, svar, vvar) \
+ { (svar).write(vvar); }
-#define VL_ASSIGN_SWI(obits,svar,rd) { \
- sc_bv<(obits)> _bvtemp; \
- _bvtemp.set_word(0, (rd)); \
- (svar).write(_bvtemp); \
+#define VL_ASSIGN_SWI(obits, svar, rd) \
+ { \
+ sc_bv<(obits)> _bvtemp; \
+ _bvtemp.set_word(0, (rd)); \
+ (svar).write(_bvtemp); \
}
-#define VL_ASSIGN_SWQ(obits,svar,rd) { \
- sc_bv<(obits)> _bvtemp; \
- _bvtemp.set_word(0, static_cast(rd)); \
- _bvtemp.set_word(1, static_cast((rd) >> VL_IDATASIZE)); \
- (svar).write(_bvtemp); \
+#define VL_ASSIGN_SWQ(obits, svar, rd) \
+ { \
+ sc_bv<(obits)> _bvtemp; \
+ _bvtemp.set_word(0, static_cast(rd)); \
+ _bvtemp.set_word(1, static_cast((rd) >> VL_IDATASIZE)); \
+ (svar).write(_bvtemp); \
}
-#define VL_ASSIGN_SWW(obits,svar,rwp) { \
- sc_bv<(obits)> _bvtemp; \
- for (int i=0; i < VL_WORDS_I(obits); ++i) _bvtemp.set_word(i, (rwp)[i]); \
- (svar).write(_bvtemp); \
+#define VL_ASSIGN_SWW(obits, svar, rwp) \
+ { \
+ sc_bv<(obits)> _bvtemp; \
+ for (int i = 0; i < VL_WORDS_I(obits); ++i) _bvtemp.set_word(i, (rwp)[i]); \
+ (svar).write(_bvtemp); \
}
-#define VL_ASSIGN_SUI(obits,svar,rd) { (svar).write(rd); }
-#define VL_ASSIGN_SUQ(obits,svar,rd) { (svar).write(rd); }
-#define VL_ASSIGN_SBI(obits,svar,rd) { (svar).write(rd); }
-#define VL_ASSIGN_SBQ(obits,svar,rd) { (svar).write(rd); }
-#define VL_ASSIGN_SBW(obits,svar,rwp) { \
- sc_biguint<(obits)> _butemp; \
- for (int i=0; i < VL_WORDS_I(obits); ++i) { \
- int msb = ((i + 1) * VL_IDATASIZE) - 1; \
- msb = (msb >= (obits)) ? ((obits)-1) : msb; \
- _butemp.range(msb, i * VL_IDATASIZE) = (rwp)[i]; \
- } \
- (svar).write(_butemp); \
+#define VL_ASSIGN_SUI(obits, svar, rd) \
+ { (svar).write(rd); }
+#define VL_ASSIGN_SUQ(obits, svar, rd) \
+ { (svar).write(rd); }
+#define VL_ASSIGN_SBI(obits, svar, rd) \
+ { (svar).write(rd); }
+#define VL_ASSIGN_SBQ(obits, svar, rd) \
+ { (svar).write(rd); }
+#define VL_ASSIGN_SBW(obits, svar, rwp) \
+ { \
+ sc_biguint<(obits)> _butemp; \
+ for (int i = 0; i < VL_WORDS_I(obits); ++i) { \
+ int msb = ((i + 1) * VL_IDATASIZE) - 1; \
+ msb = (msb >= (obits)) ? ((obits)-1) : msb; \
+ _butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \
+ } \
+ (svar).write(_butemp); \
}
//===================================================================
@@ -939,9 +1051,9 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) VL_MT_SAF
// Right must be clean because otherwise size increase would pick up bad bits
// EMIT_RULE: VL_EXTEND: oclean=clean; rclean==clean;
-#define VL_EXTEND_II(obits,lbits,lhs) ((lhs))
-#define VL_EXTEND_QI(obits,lbits,lhs) (static_cast(lhs))
-#define VL_EXTEND_QQ(obits,lbits,lhs) ((lhs))
+#define VL_EXTEND_II(obits, lbits, lhs) ((lhs))
+#define VL_EXTEND_QI(obits, lbits, lhs) (static_cast(lhs))
+#define VL_EXTEND_QQ(obits, lbits, lhs) ((lhs))
static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) VL_MT_SAFE {
// Note for extracts that obits != lbits
@@ -954,7 +1066,8 @@ static inline WDataOutP VL_EXTEND_WQ(int obits, int, WDataOutP owp, QData ld) VL
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return owp;
}
-static inline WDataOutP VL_EXTEND_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
+static inline WDataOutP VL_EXTEND_WW(int obits, int lbits, WDataOutP owp,
+ WDataInP lwp) VL_MT_SAFE {
for (int i = 0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (int i = VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return owp;
@@ -965,7 +1078,7 @@ static inline WDataOutP VL_EXTEND_WW(int obits, int lbits, WDataOutP owp, WDataI
static inline IData VL_EXTENDS_II(int, int lbits, IData lhs) VL_PURE {
return VL_EXTENDSIGN_I(lbits, lhs) | lhs;
}
-static inline QData VL_EXTENDS_QI(int, int lbits, QData lhs/*Q_as_need_extended*/) VL_PURE {
+static inline QData VL_EXTENDS_QI(int, int lbits, QData lhs /*Q_as_need_extended*/) VL_PURE {
return VL_EXTENDSIGN_Q(lbits, lhs) | lhs;
}
static inline QData VL_EXTENDS_QQ(int, int lbits, QData lhs) VL_PURE {
@@ -985,8 +1098,9 @@ static inline WDataOutP VL_EXTENDS_WQ(int obits, int lbits, WDataOutP owp, QData
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return owp;
}
-static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
- for (int i = 0; i < VL_WORDS_I(lbits)-1; ++i) owp[i] = lwp[i];
+static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp,
+ WDataInP lwp) VL_MT_SAFE {
+ for (int i = 0; i < VL_WORDS_I(lbits) - 1; ++i) owp[i] = lwp[i];
int lmsw = VL_WORDS_I(lbits) - 1;
EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]);
owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_E(lbits));
@@ -998,36 +1112,37 @@ static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WData
// REDUCTION OPERATORS
// EMIT_RULE: VL_REDAND: oclean=clean; lclean==clean; obits=1;
-#define VL_REDAND_II(obits,lbits,lhs) ((lhs) == VL_MASK_I(lbits))
-#define VL_REDAND_IQ(obits,lbits,lhs) ((lhs) == VL_MASK_Q(lbits))
+#define VL_REDAND_II(obits, lbits, lhs) ((lhs) == VL_MASK_I(lbits))
+#define VL_REDAND_IQ(obits, lbits, lhs) ((lhs) == VL_MASK_Q(lbits))
static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits);
EData combine = lwp[0];
for (int i = 1; i < words - 1; ++i) combine &= lwp[i];
- combine &= ~VL_MASK_E(lbits) | lwp[words-1];
- return ((~combine)==0);
+ combine &= ~VL_MASK_E(lbits) | lwp[words - 1];
+ return ((~combine) == 0);
}
// EMIT_RULE: VL_REDOR: oclean=clean; lclean==clean; obits=1;
-#define VL_REDOR_I(lhs) ((lhs)!=0)
-#define VL_REDOR_Q(lhs) ((lhs)!=0)
+#define VL_REDOR_I(lhs) ((lhs) != 0)
+#define VL_REDOR_Q(lhs) ((lhs) != 0)
static inline IData VL_REDOR_W(int words, WDataInP lwp) VL_MT_SAFE {
EData equal = 0;
- for (int i=0; i < words; ++i) equal |= lwp[i];
+ for (int i = 0; i < words; ++i) equal |= lwp[i];
return (equal != 0);
}
// EMIT_RULE: VL_REDXOR: oclean=dirty; obits=1;
static inline IData VL_REDXOR_2(IData r) VL_PURE {
// Experiments show VL_REDXOR_2 is faster than __builtin_parityl
- r=(r^(r>>1));
+ r = (r ^ (r >> 1));
return r;
}
static inline IData VL_REDXOR_4(IData r) VL_PURE {
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
return __builtin_parityl(r);
#else
- r=(r^(r>>1)); r=(r^(r>>2));
+ r = (r ^ (r >> 1));
+ r = (r ^ (r >> 2));
return r;
#endif
}
@@ -1035,7 +1150,9 @@ static inline IData VL_REDXOR_8(IData r) VL_PURE {
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
return __builtin_parityl(r);
#else
- r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4));
+ r = (r ^ (r >> 1));
+ r = (r ^ (r >> 2));
+ r = (r ^ (r >> 4));
return r;
#endif
}
@@ -1043,7 +1160,10 @@ static inline IData VL_REDXOR_16(IData r) VL_PURE {
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
return __builtin_parityl(r);
#else
- r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8));
+ r = (r ^ (r >> 1));
+ r = (r ^ (r >> 2));
+ r = (r ^ (r >> 4));
+ r = (r ^ (r >> 8));
return r;
#endif
}
@@ -1051,7 +1171,11 @@ static inline IData VL_REDXOR_32(IData r) VL_PURE {
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
return __builtin_parityl(r);
#else
- r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
+ r = (r ^ (r >> 1));
+ r = (r ^ (r >> 2));
+ r = (r ^ (r >> 4));
+ r = (r ^ (r >> 8));
+ r = (r ^ (r >> 16));
return r;
#endif
}
@@ -1059,13 +1183,18 @@ static inline IData VL_REDXOR_64(QData r) VL_PURE {
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
return __builtin_parityll(r);
#else
- r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16)); r=(r^(r>>32));
+ r = (r ^ (r >> 1));
+ r = (r ^ (r >> 2));
+ r = (r ^ (r >> 4));
+ r = (r ^ (r >> 8));
+ r = (r ^ (r >> 16));
+ r = (r ^ (r >> 32));
return static_cast(r);
#endif
}
static inline IData VL_REDXOR_W(int words, WDataInP lwp) VL_MT_SAFE {
EData r = lwp[0];
- for (int i=1; i < words; ++i) r ^= lwp[i];
+ for (int i = 1; i < words; ++i) r ^= lwp[i];
return VL_REDXOR_32(r);
}
@@ -1073,13 +1202,13 @@ static inline IData VL_REDXOR_W(int words, WDataInP lwp) VL_MT_SAFE {
static inline IData VL_COUNTONES_I(IData lhs) VL_PURE {
// This is faster than __builtin_popcountl
IData r = lhs - ((lhs >> 1) & 033333333333) - ((lhs >> 2) & 011111111111);
- r = (r + (r>>3)) & 030707070707;
- r = (r + (r>>6));
- r = (r + (r>>12) + (r>>24)) & 077;
+ r = (r + (r >> 3)) & 030707070707;
+ r = (r + (r >> 6));
+ r = (r + (r >> 12) + (r >> 24)) & 077;
return r;
}
static inline IData VL_COUNTONES_Q(QData lhs) VL_PURE {
- return VL_COUNTONES_I(static_cast(lhs)) + VL_COUNTONES_I(static_cast(lhs>>32));
+ return VL_COUNTONES_I(static_cast(lhs)) + VL_COUNTONES_I(static_cast(lhs >> 32));
}
#define VL_COUNTONES_E VL_COUNTONES_I
static inline IData VL_COUNTONES_W(int words, WDataInP lwp) VL_MT_SAFE {
@@ -1089,36 +1218,32 @@ static inline IData VL_COUNTONES_W(int words, WDataInP lwp) VL_MT_SAFE {
}
static inline IData VL_ONEHOT_I(IData lhs) VL_PURE {
- return (((lhs & (lhs-1))==0) & (lhs!=0));
+ return (((lhs & (lhs - 1)) == 0) & (lhs != 0));
}
static inline IData VL_ONEHOT_Q(QData lhs) VL_PURE {
- return (((lhs & (lhs-1))==0) & (lhs!=0));
+ return (((lhs & (lhs - 1)) == 0) & (lhs != 0));
}
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) VL_MT_SAFE {
EData one = 0;
- for (int i=0; (i < words); ++i) {
+ for (int i = 0; (i < words); ++i) {
if (lwp[i]) {
if (one) return 0;
one = 1;
- if (lwp[i] & (lwp[i]-1)) return 0;
+ if (lwp[i] & (lwp[i] - 1)) return 0;
}
}
return one;
}
-static inline IData VL_ONEHOT0_I(IData lhs) VL_PURE {
- return ((lhs & (lhs-1))==0);
-}
-static inline IData VL_ONEHOT0_Q(QData lhs) VL_PURE {
- return ((lhs & (lhs-1))==0);
-}
+static inline IData VL_ONEHOT0_I(IData lhs) VL_PURE { return ((lhs & (lhs - 1)) == 0); }
+static inline IData VL_ONEHOT0_Q(QData lhs) VL_PURE { return ((lhs & (lhs - 1)) == 0); }
static inline IData VL_ONEHOT0_W(int words, WDataInP lwp) VL_MT_SAFE {
bool one = false;
- for (int i=0; (i < words); ++i) {
+ for (int i = 0; (i < words); ++i) {
if (lwp[i]) {
if (one) return 0;
one = true;
- if (lwp[i] & (lwp[i]-1)) return 0;
+ if (lwp[i] & (lwp[i] - 1)) return 0;
}
}
return 1;
@@ -1129,19 +1254,19 @@ static inline IData VL_CLOG2_I(IData lhs) VL_PURE {
if (VL_UNLIKELY(!lhs)) return 0;
lhs--;
int shifts = 0;
- for (; lhs!=0; ++shifts) lhs = lhs >> 1;
+ for (; lhs != 0; ++shifts) lhs = lhs >> 1;
return shifts;
}
static inline IData VL_CLOG2_Q(QData lhs) VL_PURE {
if (VL_UNLIKELY(!lhs)) return 0;
lhs--;
int shifts = 0;
- for (; lhs!=0; ++shifts) lhs = lhs >> VL_ULL(1);
+ for (; lhs != 0; ++shifts) lhs = lhs >> VL_ULL(1);
return shifts;
}
static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE {
EData adjust = (VL_COUNTONES_W(words, lwp) == 1) ? 0 : 1;
- for (int i=words-1; i>=0; --i) {
+ for (int i = words - 1; i >= 0; --i) {
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) {
@@ -1156,12 +1281,10 @@ static inline IData VL_CLOG2_W(int words, WDataInP lwp) VL_MT_SAFE {
static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) VL_MT_SAFE {
// MSB set bit plus one; similar to FLS. 0=value is zero
- for (int i=words-1; i>=0; --i) {
+ for (int i = words - 1; i >= 0; --i) {
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
for (int bit = VL_EDATASIZE - 1; bit >= 0; --bit) {
- if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) {
- return i * VL_EDATASIZE + bit + 1;
- }
+ if (VL_UNLIKELY(VL_BITISSET_E(lwp[i], bit))) { return i * VL_EDATASIZE + bit + 1; }
}
// Can't get here - one bit must be set
}
@@ -1174,33 +1297,34 @@ static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) VL_MT_SAFE {
// EMIT_RULE: VL_AND: oclean=lclean||rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_AND_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; (i < words); ++i) owp[i] = (lwp[i] & rwp[i]);
+ for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] & rwp[i]);
return owp;
}
// EMIT_RULE: VL_OR: oclean=lclean&&rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_OR_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; (i < words); ++i) owp[i] = (lwp[i] | rwp[i]);
+ for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] | rwp[i]);
return owp;
}
// EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits;
static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
IData od = 0;
- for (int i=0; (i < words); ++i) od |= (lwp[i] ^ rwp[i]);
- return(od);
+ for (int i = 0; (i < words); ++i) od |= (lwp[i] ^ rwp[i]);
+ return od;
}
// EMIT_RULE: VL_XOR: oclean=lclean&&rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_XOR_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
+ for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
return owp;
}
// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits;
-static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]);
+static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp, WDataInP lwp,
+ WDataInP rwp) VL_MT_SAFE {
+ for (int i = 0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]);
return owp;
}
// EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits;
static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
- for (int i=0; i < words; ++i) owp[i] = ~(lwp[i]);
+ for (int i = 0; i < words; ++i) owp[i] = ~(lwp[i]);
return owp;
}
@@ -1213,32 +1337,32 @@ static inline WDataOutP VL_NOT_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_S
// EMIT_RULE: VL_GT: oclean=clean; lclean==clean; rclean==clean; obits=1; lbits==rbits;
// EMIT_RULE: VL_GTE: oclean=clean; lclean==clean; rclean==clean; obits=1; lbits==rbits;
// EMIT_RULE: VL_LTE: oclean=clean; lclean==clean; rclean==clean; obits=1; lbits==rbits;
-#define VL_NEQ_W(words,lwp,rwp) (!VL_EQ_W(words,lwp,rwp))
-#define VL_LT_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)<0)
-#define VL_LTE_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)<=0)
-#define VL_GT_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)>0)
-#define VL_GTE_W(words,lwp,rwp) (_VL_CMP_W(words,lwp,rwp)>=0)
+#define VL_NEQ_W(words, lwp, rwp) (!VL_EQ_W(words, lwp, rwp))
+#define VL_LT_W(words, lwp, rwp) (_VL_CMP_W(words, lwp, rwp) < 0)
+#define VL_LTE_W(words, lwp, rwp) (_VL_CMP_W(words, lwp, rwp) <= 0)
+#define VL_GT_W(words, lwp, rwp) (_VL_CMP_W(words, lwp, rwp) > 0)
+#define VL_GTE_W(words, lwp, rwp) (_VL_CMP_W(words, lwp, rwp) >= 0)
// Output clean, AND MUST BE CLEAN
static inline IData VL_EQ_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
EData nequal = 0;
- for (int i=0; (i < words); ++i) nequal |= (lwp[i] ^ rwp[i]);
- return (nequal==0);
+ for (int i = 0; (i < words); ++i) nequal |= (lwp[i] ^ rwp[i]);
+ return (nequal == 0);
}
// Internal usage
static inline int _VL_CMP_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=words-1; i>=0; --i) {
+ for (int i = words - 1; i >= 0; --i) {
if (lwp[i] > rwp[i]) return 1;
if (lwp[i] < rwp[i]) return -1;
}
- return(0); // ==
+ return 0; // ==
}
-#define VL_LTS_IWW(obits,lbits,rbbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<0)
-#define VL_LTES_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<=0)
-#define VL_GTS_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)>0)
-#define VL_GTES_IWW(obits,lbits,rbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)>=0)
+#define VL_LTS_IWW(obits, lbits, rbbits, lwp, rwp) (_VL_CMPS_W(lbits, lwp, rwp) < 0)
+#define VL_LTES_IWW(obits, lbits, rbits, lwp, rwp) (_VL_CMPS_W(lbits, lwp, rwp) <= 0)
+#define VL_GTS_IWW(obits, lbits, rbits, lwp, rwp) (_VL_CMPS_W(lbits, lwp, rwp) > 0)
+#define VL_GTES_IWW(obits, lbits, rbits, lwp, rwp) (_VL_CMPS_W(lbits, lwp, rwp) >= 0)
static inline IData VL_GTS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
// For lbits==32, this becomes just a single instruction, otherwise ~5.
@@ -1288,29 +1412,22 @@ static inline IData VL_LTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PU
static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits);
- int i = words-1;
+ int i = words - 1;
// We need to flip sense if negative comparison
EData lsign = VL_SIGN_E(lbits, lwp[i]);
EData rsign = VL_SIGN_E(lbits, rwp[i]);
- if (!lsign && rsign) return 1; // + > -
+ if (!lsign && rsign) return 1; // + > -
if (lsign && !rsign) return -1; // - < +
- for (; i>=0; --i) {
+ for (; i >= 0; --i) {
if (lwp[i] > rwp[i]) return 1;
if (lwp[i] < rwp[i]) return -1;
}
- return(0); // ==
+ return 0; // ==
}
//=========================================================================
// Math
-// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
-// we can't just
-//# define VL_NEGATE_I(data) (-(data))
-static inline IData VL_NEGATE_I(IData data) VL_PURE { return -data; }
-static inline QData VL_NEGATE_Q(QData data) VL_PURE { return -data; }
-static inline EData VL_NEGATE_E(EData data) VL_PURE { return -data; }
-
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
EData carry = 1;
for (int i = 0; i < words; ++i) {
@@ -1331,12 +1448,12 @@ static void VL_NEGATE_INPLACE_W(int words, WDataOutP owp_lwp) VL_MT_SAFE {
// EMIT_RULE: VL_MUL: oclean=dirty; lclean==clean; rclean==clean;
// EMIT_RULE: VL_DIV: oclean=dirty; lclean==clean; rclean==clean;
// EMIT_RULE: VL_MODDIV: oclean=dirty; lclean==clean; rclean==clean;
-#define VL_DIV_III(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)/(rhs))
-#define VL_DIV_QQQ(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)/(rhs))
-#define VL_DIV_WWW(lbits,owp,lwp,rwp) (_vl_moddiv_w(lbits,owp,lwp,rwp,0))
-#define VL_MODDIV_III(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)%(rhs))
-#define VL_MODDIV_QQQ(lbits,lhs,rhs) (((rhs)==0)?0:(lhs)%(rhs))
-#define VL_MODDIV_WWW(lbits,owp,lwp,rwp) (_vl_moddiv_w(lbits,owp,lwp,rwp,1))
+#define VL_DIV_III(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) / (rhs))
+#define VL_DIV_QQQ(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) / (rhs))
+#define VL_DIV_WWW(lbits, owp, lwp, rwp) (_vl_moddiv_w(lbits, owp, lwp, rwp, 0))
+#define VL_MODDIV_III(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) % (rhs))
+#define VL_MODDIV_QQQ(lbits, lhs, rhs) (((rhs) == 0) ? 0 : (lhs) % (rhs))
+#define VL_MODDIV_WWW(lbits, owp, lwp, rwp) (_vl_moddiv_w(lbits, owp, lwp, rwp, 1))
static inline WDataOutP VL_ADD_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
QData carry = 0;
@@ -1363,11 +1480,11 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp, WDataInP lwp, WDataIn
}
static inline WDataOutP VL_MUL_W(int words, WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; i(lwp[lword]) * static_cast(rwp[rword]);
- for (int qword=lword+rword; qword(owp[qword]);
owp[qword] = (mul & VL_ULL(0xffffffff));
mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff);
@@ -1389,8 +1506,8 @@ static inline QData VL_MULS_QQQ(int, int lbits, int, QData lhs, QData rhs) VL_PU
return lhs_signed * rhs_signed;
}
-static inline WDataOutP VL_MULS_WWW(int, int lbits, int,
- WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
+static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP lwp,
+ WDataInP rwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits);
// cppcheck-suppress variableScope
WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
@@ -1529,51 +1646,60 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDa
WDataOutP VL_POW_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs);
QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp);
-#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
- VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
-#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
- VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
-#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) \
- VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
-#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
- VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
-#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) \
- VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
+#define VL_POWSS_IIQ(obits, lbits, rbits, lhs, rhs, lsign, rsign) \
+ VL_POWSS_QQQ(obits, lbits, rbits, lhs, rhs, lsign, rsign)
+#define VL_POWSS_IIQ(obits, lbits, rbits, lhs, rhs, lsign, rsign) \
+ VL_POWSS_QQQ(obits, lbits, rbits, lhs, rhs, lsign, rsign)
+#define VL_POWSS_IIW(obits, lbits, rbits, lhs, rwp, lsign, rsign) \
+ VL_POWSS_QQW(obits, lbits, rbits, lhs, rwp, lsign, rsign)
+#define VL_POWSS_QQI(obits, lbits, rbits, lhs, rhs, lsign, rsign) \
+ VL_POWSS_QQQ(obits, lbits, rbits, lhs, rhs, lsign, rsign)
+#define VL_POWSS_WWI(obits, lbits, rbits, owp, lwp, rhs, lsign, rsign) \
+ VL_POWSS_WWQ(obits, lbits, rbits, owp, lwp, rhs, lsign, rsign)
-static inline IData VL_POWSS_III(int obits, int, int rbits,
- IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
+static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign,
+ bool rsign) VL_MT_SAFE {
if (VL_UNLIKELY(rhs == 0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
- if (lhs == 0) return 0; // "X"
- else if (lhs == 1) return 1;
- else if (lsign && lhs == VL_MASK_I(obits)) { // -1
- if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
- else return 1; // -1^even=1
+ if (lhs == 0) {
+ return 0; // "X"
+ } else if (lhs == 1) {
+ return 1;
+ } else if (lsign && lhs == VL_MASK_I(obits)) { // -1
+ if (rhs & 1) {
+ return VL_MASK_I(obits); // -1^odd=-1
+ } else {
+ return 1; // -1^even=1
+ }
}
return 0;
}
return VL_POW_III(obits, rbits, rbits, lhs, rhs);
}
-static inline QData VL_POWSS_QQQ(int obits, int, int rbits,
- QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
+static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign,
+ bool rsign) VL_MT_SAFE {
if (VL_UNLIKELY(rhs == 0)) return 1;
if (rsign && VL_SIGN_Q(rbits, rhs)) {
- if (lhs == 0) return 0; // "X"
- else if (lhs == 1) return 1;
- else if (lsign && lhs == VL_MASK_Q(obits)) { // -1
- if (rhs & 1) return VL_MASK_Q(obits); // -1^odd=-1
- else return 1; // -1^even=1
+ if (lhs == 0) {
+ return 0; // "X"
+ } else if (lhs == 1) {
+ return 1;
+ } else if (lsign && lhs == VL_MASK_Q(obits)) { // -1
+ if (rhs & 1) {
+ return VL_MASK_Q(obits); // -1^odd=-1
+ } else {
+ return 1; // -1^even=1
+ }
}
return 0;
}
return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs);
}
-WDataOutP VL_POWSS_WWW(int obits, int, int rbits,
- WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
-WDataOutP VL_POWSS_WWQ(int obits, int, int rbits,
- WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
-QData VL_POWSS_QQW(int obits, int, int rbits,
- QData lhs, WDataInP rwp, bool lsign, bool rsign);
+WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
+ bool lsign, bool rsign);
+WDataOutP VL_POWSS_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs,
+ bool lsign, bool rsign);
+QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign);
//===================================================================
// Concat/replication
@@ -1628,29 +1754,23 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
int words = VL_WORDS_I(hbit - lbit + 1);
if (hoffset == VL_SIZEBITS_E && loffset == 0) {
// Fast and common case, word based insertion
- for (int i=0; i> nbitsonright;
EData od = (d & ~linsmask) | (owp[oword] & linsmask);
@@ -1675,19 +1795,21 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
}
}
-static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit) VL_MT_SAFE {
- WData lwp[VL_WQ_WORDS_E]; VL_SET_WQ(lwp, ld);
+static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit,
+ int lbit) VL_MT_SAFE {
+ WData lwp[VL_WQ_WORDS_E];
+ VL_SET_WQ(lwp, ld);
_VL_INSERT_WW(obits, owp, lwp, hbit, lbit);
}
// EMIT_RULE: VL_REPLICATE: oclean=clean>width32, dirty<=width32; lclean=clean; rclean==clean;
// RHS MUST BE CLEAN CONSTANT.
-#define VL_REPLICATE_IOI(obits,lbits,rbits, ld, rep) (-(ld)) // Iff lbits==1
-#define VL_REPLICATE_QOI(obits,lbits,rbits, ld, rep) (-(static_cast(ld))) // Iff lbits==1
+#define VL_REPLICATE_IOI(obits, lbits, rbits, ld, rep) (-(ld)) // Iff lbits==1
+#define VL_REPLICATE_QOI(obits, lbits, rbits, ld, rep) (-(static_cast(ld))) // Iff lbits==1
static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) VL_PURE {
IData returndata = ld;
- for (unsigned i=1; i < rep; ++i){
+ for (unsigned i = 1; i < rep; ++i) {
returndata = returndata << lbits;
returndata |= ld;
}
@@ -1695,33 +1817,33 @@ static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) V
}
static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) VL_PURE {
QData returndata = ld;
- for (unsigned i=1; i < rep; ++i){
+ for (unsigned i = 1; i < rep; ++i) {
returndata = returndata << lbits;
returndata |= static_cast(ld);
}
return returndata;
}
-static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int,
- WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
+static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld,
+ IData rep) VL_MT_SAFE {
owp[0] = ld;
- for (unsigned i=1; i < rep; ++i){
- _VL_INSERT_WI(obits, owp, ld, i*lbits+lbits-1, i*lbits);
+ for (unsigned i = 1; i < rep; ++i) {
+ _VL_INSERT_WI(obits, owp, ld, i * lbits + lbits - 1, i * lbits);
}
return owp;
}
-static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int,
- WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
+static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld,
+ IData rep) VL_MT_SAFE {
VL_SET_WQ(owp, ld);
- for (unsigned i=1; i < rep; ++i){
- _VL_INSERT_WQ(obits, owp, ld, i*lbits+lbits-1, i*lbits);
+ for (unsigned i = 1; i < rep; ++i) {
+ _VL_INSERT_WQ(obits, owp, ld, i * lbits + lbits - 1, i * lbits);
}
return owp;
}
-static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int,
- WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
- for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
- for (unsigned i=1; i < rep; ++i){
- _VL_INSERT_WW(obits, owp, lwp, i*lbits+lbits-1, i*lbits);
+static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp,
+ IData rep) VL_MT_SAFE {
+ for (int i = 0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
+ for (unsigned i = 1; i < rep; ++i) {
+ _VL_INSERT_WW(obits, owp, lwp, i * lbits + lbits - 1, i * lbits);
}
return owp;
}
@@ -1758,20 +1880,11 @@ static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_UL(1) << rd_log2) - lbitsRem));
}
switch (rd_log2) {
- case 0:
- ret = ((ret >> 1) & VL_UL(0x55555555))
- | ((ret & VL_UL(0x55555555)) << 1); // FALLTHRU
- case 1:
- ret = ((ret >> 2) & VL_UL(0x33333333))
- | ((ret & VL_UL(0x33333333)) << 2); // FALLTHRU
- case 2:
- ret = ((ret >> 4) & VL_UL(0x0f0f0f0f))
- | ((ret & VL_UL(0x0f0f0f0f)) << 4); // FALLTHRU
- case 3:
- ret = ((ret >> 8) & VL_UL(0x00ff00ff))
- | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
- case 4:
- ret = ((ret >> 16) | (ret << 16));
+ case 0: ret = ((ret >> 1) & VL_UL(0x55555555)) | ((ret & VL_UL(0x55555555)) << 1); // FALLTHRU
+ case 1: ret = ((ret >> 2) & VL_UL(0x33333333)) | ((ret & VL_UL(0x33333333)) << 2); // FALLTHRU
+ case 2: ret = ((ret >> 4) & VL_UL(0x0f0f0f0f)) | ((ret & VL_UL(0x0f0f0f0f)) << 4); // FALLTHRU
+ case 3: ret = ((ret >> 8) & VL_UL(0x00ff00ff)) | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
+ case 4: ret = ((ret >> 16) | (ret << 16));
}
return ret >> (VL_IDATASIZE - lbits);
}
@@ -1786,23 +1899,22 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_ULL(1) << rd_log2) - lbitsRem));
}
switch (rd_log2) {
- case 0:
- ret = (((ret >> 1) & VL_ULL(0x5555555555555555))
- | ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU
- case 1:
- ret = (((ret >> 2) & VL_ULL(0x3333333333333333))
- | ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU
- case 2:
- ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f))
- | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU
- case 3:
- ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff))
- | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU
- case 4:
- ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff))
- | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU
- case 5:
- ret = ((ret >> 32) | (ret << 32));
+ case 0:
+ ret = (((ret >> 1) & VL_ULL(0x5555555555555555))
+ | ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU
+ case 1:
+ ret = (((ret >> 2) & VL_ULL(0x3333333333333333))
+ | ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU
+ case 2:
+ ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f))
+ | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU
+ case 3:
+ ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff))
+ | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU
+ case 4:
+ ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff))
+ | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU
+ case 5: ret = ((ret >> 32) | (ret << 32));
}
return ret >> (VL_QUADSIZE - lbits);
}
@@ -1824,23 +1936,23 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) VL_P
QData ret = 0;
// Slice size should never exceed the lhs width
QData mask = VL_MASK_Q(rd);
- for (int istart=0; istart 0 ? ostart : 0;
ret |= ((ld >> istart) & mask) << ostart;
}
return ret;
}
-static inline WDataOutP VL_STREAML_WWI(int, int lbits, int,
- WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
+static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp,
+ IData rd) VL_MT_SAFE {
VL_ZERO_W(lbits, owp);
// Slice size should never exceed the lhs width
int ssize = (rd < static_cast(lbits)) ? rd : (static_cast(lbits));
- for (int istart=0; istart 0 ? ostart : 0;
- for (int sbit=0; sbit(ld)<<(rbits) | static_cast(rd))
-#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) \
- (static_cast(ld)<<(rbits) | static_cast(rd))
-#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) \
- (static_cast(ld)<<(rbits) | static_cast(rd))
-#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) \
- (static_cast(ld)<<(rbits) | static_cast(rd))
-#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) \
- (static_cast(ld)<<(rbits) | static_cast(rd))
+#define VL_CONCAT_III(obits, lbits, rbits, ld, rd) \
+ (static_cast(ld) << (rbits) | static_cast(rd))
+#define VL_CONCAT_QII(obits, lbits, rbits, ld, rd) \
+ (static_cast(ld) << (rbits) | static_cast(rd))
+#define VL_CONCAT_QIQ(obits, lbits, rbits, ld, rd) \
+ (static_cast(ld) << (rbits) | static_cast(rd))
+#define VL_CONCAT_QQI(obits, lbits, rbits, ld, rd) \
+ (static_cast(ld) << (rbits) | static_cast(rd))
+#define VL_CONCAT_QQQ(obits, lbits, rbits, ld, rd) \
+ (static_cast(ld) << (rbits) | static_cast(rd))
-static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits,
- WDataOutP owp, IData ld, IData rd) VL_MT_SAFE {
+static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits, WDataOutP owp, IData ld,
+ IData rd) VL_MT_SAFE {
owp[0] = rd;
- for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits);
+ for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WI(obits, owp, ld, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
+static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
+ IData rd) VL_MT_SAFE {
owp[0] = rd;
- for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits);
+ for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WW(obits, owp, lwp, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits,
- WDataOutP owp, IData ld, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
- for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits);
+static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits, WDataOutP owp, IData ld,
+ WDataInP rwp) VL_MT_SAFE {
+ for (int i = 0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
+ for (int i = VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WI(obits, owp, ld, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits,
- WDataOutP owp, IData ld, QData rd) VL_MT_SAFE {
+static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits, WDataOutP owp, IData ld,
+ QData rd) VL_MT_SAFE {
VL_SET_WQ(owp, rd);
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WI(obits, owp, ld, rbits+lbits-1, rbits);
+ _VL_INSERT_WI(obits, owp, ld, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits,
- WDataOutP owp, QData ld, IData rd) VL_MT_SAFE {
+static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits, WDataOutP owp, QData ld,
+ IData rd) VL_MT_SAFE {
owp[0] = rd;
- for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits);
+ for (int i = 1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WQ(obits, owp, ld, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits,
- WDataOutP owp, QData ld, QData rd) VL_MT_SAFE {
+static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits, WDataOutP owp, QData ld,
+ QData rd) VL_MT_SAFE {
VL_SET_WQ(owp, rd);
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits);
+ _VL_INSERT_WQ(obits, owp, ld, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE {
+static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
+ QData rd) VL_MT_SAFE {
VL_SET_WQ(owp, rd);
for (int i = VL_WQ_WORDS_E; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits);
+ _VL_INSERT_WW(obits, owp, lwp, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits,
- WDataOutP owp, QData ld, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
- for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WQ(obits, owp, ld, rbits+lbits-1, rbits);
+static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits, WDataOutP owp, QData ld,
+ WDataInP rwp) VL_MT_SAFE {
+ for (int i = 0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
+ for (int i = VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WQ(obits, owp, ld, rbits + lbits - 1, rbits);
return owp;
}
-static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
- for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WW(obits, owp, lwp, rbits+lbits-1, rbits);
+static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
+ WDataInP rwp) VL_MT_SAFE {
+ for (int i = 0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
+ for (int i = VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WW(obits, owp, lwp, rbits + lbits - 1, rbits);
return owp;
}
@@ -1934,37 +2046,39 @@ static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits,
// Static shift, used by internal functions
// The output is the same as the input - it overlaps!
-static inline void _VL_SHIFTL_INPLACE_W(int obits, WDataOutP iowp, IData rd/*1 or 4*/) VL_MT_SAFE {
+static inline void _VL_SHIFTL_INPLACE_W(int obits, WDataOutP iowp,
+ IData rd /*1 or 4*/) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
EData linsmask = VL_MASK_E(rd);
- for (int i=words-1; i>=1; --i) {
- iowp[i] = ((iowp[i]<> (VL_EDATASIZE - rd)) & linsmask);
+ for (int i = words - 1; i >= 1; --i) {
+ iowp[i]
+ = ((iowp[i] << rd) & ~linsmask) | ((iowp[i - 1] >> (VL_EDATASIZE - rd)) & linsmask);
}
- iowp[0] = ((iowp[0]<= static_cast(obits)) { // rd may be huge with MSB set
- for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- } else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
- for (int i=0; i < word_shift; ++i) owp[i] = 0;
- for (int i=word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i-word_shift];
+ for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ } else if (bit_shift == 0) { // Aligned word shift (<<0,<<32,<<64 etc)
+ for (int i = 0; i < word_shift; ++i) owp[i] = 0;
+ for (int i = word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i - word_shift];
} else {
- for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- _VL_INSERT_WW(obits, owp, lwp, obits-1, rd);
+ for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ _VL_INSERT_WW(obits, owp, lwp, obits - 1, rd);
}
return owp;
}
-static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
- for (int i=1; i < VL_WORDS_I(rbits); ++i) {
+static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
+ WDataInP rwp) VL_MT_SAFE {
+ for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
}
@@ -1972,64 +2086,63 @@ static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits,
return VL_SHIFTL_WWI(obits, lbits, 32, owp, lwp, rwp[0]);
}
static inline IData VL_SHIFTL_IIW(int obits, int, int rbits, IData lhs, WDataInP rwp) VL_MT_SAFE {
- for (int i=1; i < VL_WORDS_I(rbits); ++i) {
+ for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
- return VL_CLEAN_II(obits, obits, lhs<>32 or more
return 0;
}
}
// Above checks rwp[1]==0 so not needed in below shift
- return VL_CLEAN_QQ(obits, obits, lhs<<(static_cast(rwp[0])));
+ return VL_CLEAN_QQ(obits, obits, lhs << (static_cast(rwp[0])));
}
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
// Important: Unlike most other funcs, the shift might well be a computed
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
-static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int,
- WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
+static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int, WDataOutP owp, WDataInP lwp,
+ IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_E(rd); // Maybe 0
int bit_shift = VL_BITBIT_E(rd);
if (rd >= static_cast(obits)) { // rd may be huge with MSB set
- for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
- } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
- int copy_words = (VL_WORDS_I(obits)-word_shift);
- for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
- for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
+ } else if (bit_shift == 0) { // Aligned word shift (>>0,>>32,>>64 etc)
+ int copy_words = (VL_WORDS_I(obits) - word_shift);
+ for (int i = 0; i < copy_words; ++i) owp[i] = lwp[i + word_shift];
+ for (int i = copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
} else {
int loffset = rd & VL_SIZEBITS_E;
int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
// Middle words
- int words = VL_WORDS_I(obits-rd);
- for (int i=0; i>loffset;
- int upperword = i+word_shift+1;
- if (upperword < VL_WORDS_I(obits)) {
- owp[i] |= lwp[upperword]<< nbitsonright;
- }
+ int words = VL_WORDS_I(obits - rd);
+ for (int i = 0; i < words; ++i) {
+ owp[i] = lwp[i + word_shift] >> loffset;
+ int upperword = i + word_shift + 1;
+ if (upperword < VL_WORDS_I(obits)) owp[i] |= lwp[upperword] << nbitsonright;
}
- for (int i=words; i>32 or more
return VL_ZERO_W(obits, owp);
}
}
return VL_SHIFTR_WWI(obits, lbits, 32, owp, lwp, rwp[0]);
}
-static inline WDataOutP VL_SHIFTR_WWQ(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE {
- WData rwp[VL_WQ_WORDS_E]; VL_SET_WQ(rwp, rd);
+static inline WDataOutP VL_SHIFTR_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp,
+ QData rd) VL_MT_SAFE {
+ WData rwp[VL_WQ_WORDS_E];
+ VL_SET_WQ(rwp, rd);
return VL_SHIFTR_WWW(obits, lbits, rbits, owp, lwp, rwp);
}
@@ -2057,31 +2170,30 @@ static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData r
// IEEE says signed if output signed, but bit position from lbits;
// must use lbits for sign; lbits might != obits,
// an EXTEND(SHIFTRS(...)) can became a SHIFTRS(...) within same 32/64 bit word length
- IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
+ IData sign = -(lhs >> (lbits - 1)); // ffff_ffff if negative
IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past"
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits, obits, signext));
}
static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) VL_PURE {
- QData sign = -(lhs >> (lbits-1));
+ QData sign = -(lhs >> (lbits - 1));
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits, obits, signext));
}
-static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits,
- QData lhs, IData rhs) VL_PURE {
+static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) VL_PURE {
return static_cast(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
}
-static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
- WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
+static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp,
+ IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_E(rd);
int bit_shift = VL_BITBIT_E(rd);
- int lmsw = VL_WORDS_I(obits)-1;
+ int lmsw = VL_WORDS_I(obits) - 1;
EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]);
if (rd >= static_cast(obits)) { // Shifting past end, sign in all of lbits
- for (int i=0; i <= lmsw; ++i) owp[i] = sign;
+ for (int i = 0; i <= lmsw; ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_E(lbits);
- } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
- int copy_words = (VL_WORDS_I(obits)-word_shift);
- for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
+ } else if (bit_shift == 0) { // Aligned word shift (>>0,>>32,>>64 etc)
+ int copy_words = (VL_WORDS_I(obits) - word_shift);
+ for (int i = 0; i < copy_words; ++i) owp[i] = lwp[i + word_shift];
if (copy_words >= 0) owp[copy_words - 1] |= ~VL_MASK_E(obits) & sign;
for (int i = copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_E(lbits);
@@ -2089,13 +2201,11 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
int loffset = rd & VL_SIZEBITS_E;
int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword (know loffset!=0)
// Middle words
- int words = VL_WORDS_I(obits-rd);
- for (int i=0; i>loffset;
- int upperword = i+word_shift+1;
- if (upperword < VL_WORDS_I(obits)) {
- owp[i] |= lwp[upperword]<< nbitsonright;
- }
+ int words = VL_WORDS_I(obits - rd);
+ for (int i = 0; i < words; ++i) {
+ owp[i] = lwp[i + word_shift] >> loffset;
+ int upperword = i + word_shift + 1;
+ if (upperword < VL_WORDS_I(obits)) owp[i] |= lwp[upperword] << nbitsonright;
}
if (words) owp[words - 1] |= sign & ~VL_MASK_E(obits - loffset);
for (int i = words; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
@@ -2103,12 +2213,10 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
}
return owp;
}
-static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
+static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits, WDataOutP owp,
+ WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
EData overshift = 0; // Huge shift 1>>32 or more
- for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
- overshift |= rwp[i];
- }
+ for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
if (VL_UNLIKELY(overshift)) {
int lmsw = VL_WORDS_I(obits) - 1;
EData sign = VL_SIGNONES_E(lbits, lwp[lmsw]);
@@ -2118,41 +2226,40 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
}
return VL_SHIFTRS_WWI(obits, lbits, 32, owp, lwp, rwp[0]);
}
-static inline WDataOutP VL_SHIFTRS_WWQ(int obits, int lbits, int rbits,
- WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE {
- WData rwp[VL_WQ_WORDS_E]; VL_SET_WQ(rwp, rd);
+static inline WDataOutP VL_SHIFTRS_WWQ(int obits, int lbits, int rbits, WDataOutP owp,
+ WDataInP lwp, QData rd) VL_MT_SAFE {
+ WData rwp[VL_WQ_WORDS_E];
+ VL_SET_WQ(rwp, rd);
return VL_SHIFTRS_WWW(obits, lbits, rbits, owp, lwp, rwp);
}
-static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits,
- IData lhs, WDataInP rwp) VL_MT_SAFE {
+static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, IData lhs,
+ WDataInP rwp) VL_MT_SAFE {
EData overshift = 0; // Huge shift 1>>32 or more
- for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
- overshift |= rwp[i];
- }
+ for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
if (VL_UNLIKELY(overshift)) {
- IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
+ IData sign = -(lhs >> (lbits - 1)); // ffff_ffff if negative
return VL_CLEAN_II(obits, obits, sign);
}
return VL_SHIFTRS_III(obits, lbits, 32, lhs, rwp[0]);
}
-static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits,
- QData lhs, WDataInP rwp) VL_MT_SAFE {
+static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, QData lhs,
+ WDataInP rwp) VL_MT_SAFE {
EData overshift = 0; // Huge shift 1>>32 or more
- for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
- overshift |= rwp[i];
- }
+ for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
if (VL_UNLIKELY(overshift)) {
- QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
+ QData sign = -(lhs >> (lbits - 1)); // ffff_ffff if negative
return VL_CLEAN_QQ(obits, obits, sign);
}
return VL_SHIFTRS_QQI(obits, lbits, 32, lhs, rwp[0]);
}
static inline IData VL_SHIFTRS_IIQ(int obits, int lbits, int rbits, IData lhs, QData rhs) VL_PURE {
- WData rwp[VL_WQ_WORDS_E]; VL_SET_WQ(rwp, rhs);
+ WData rwp[VL_WQ_WORDS_E];
+ VL_SET_WQ(rwp, rhs);
return VL_SHIFTRS_IIW(obits, lbits, rbits, lhs, rwp);
}
static inline QData VL_SHIFTRS_QQQ(int obits, int lbits, int rbits, QData lhs, QData rhs) VL_PURE {
- WData rwp[VL_WQ_WORDS_E]; VL_SET_WQ(rwp, rhs);
+ WData rwp[VL_WQ_WORDS_E];
+ VL_SET_WQ(rwp, rhs);
return VL_SHIFTRS_QQW(obits, lbits, rbits, lhs, rwp);
}
@@ -2160,10 +2267,10 @@ static inline QData VL_SHIFTRS_QQQ(int obits, int lbits, int rbits, QData lhs, Q
// Bit selection
// EMIT_RULE: VL_BITSEL: oclean=dirty; rclean==clean;
-#define VL_BITSEL_IIII(obits,lbits,rbits,zbits,lhs,rhs) ((lhs)>>(rhs))
-#define VL_BITSEL_QIII(obits,lbits,rbits,zbits,lhs,rhs) ((lhs)>>(rhs))
-#define VL_BITSEL_QQII(obits,lbits,rbits,zbits,lhs,rhs) ((lhs)>>(rhs))
-#define VL_BITSEL_IQII(obits,lbits,rbits,zbits,lhs,rhs) (static_cast((lhs)>>(rhs)))
+#define VL_BITSEL_IIII(obits, lbits, rbits, zbits, lhs, rhs) ((lhs) >> (rhs))
+#define VL_BITSEL_QIII(obits, lbits, rbits, zbits, lhs, rhs) ((lhs) >> (rhs))
+#define VL_BITSEL_QQII(obits, lbits, rbits, zbits, lhs, rhs) ((lhs) >> (rhs))
+#define VL_BITSEL_IQII(obits, lbits, rbits, zbits, lhs, rhs) (static_cast((lhs) >> (rhs)))
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) VL_MT_SAFE {
int word = VL_BITWORD_E(rd);
@@ -2177,29 +2284,29 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
// EMIT_RULE: VL_RANGE: oclean=lclean; out=dirty
// &