Compare commits

...
76 Commits
Author SHA1 Message Date
Wilson Snyder 44ce83cd8e Version bump 2019-12-08 07:58:47 -05:00
Wilson Snyder c199930943 Commentary 2019-12-08 07:34:47 -05:00
Wilson Snyder 81fc1d48a6 Fix gate lvalue optimization error, bug831. 2019-12-07 16:49:11 -05:00
Wilson Snyder f330f16bf6 Internals: Additional debug dumps. 2019-12-07 16:41:34 -05:00
Wilson Snyder 10a6b566ef Fix error on unpacked concatenations, bug1627. 2019-12-07 15:53:34 -05:00
Driss Hafdi cff5485821 Tests: Unsupported test for bug1627.
Signed-off-by: Wilson Snyder <[email protected]>
2019-12-07 13:46:50 -05:00
Driss Hafdi dcbdac1b81 Tests: Unsupported test for bug1626.
Signed-off-by: Wilson Snyder <[email protected]>
2019-12-07 13:46:29 -05:00
Driss Hafdi a59777aa75 Tests: Unsupported test for bug1624.
Signed-off-by: Wilson Snyder <[email protected]>
2019-12-07 13:15:46 -05:00
Driss Hafdi d82b9128d0 Tests: Unsupported test for bug1623.
Signed-off-by: Wilson Snyder <[email protected]>
2019-12-07 12:59:00 -05:00
Driss Hafdi ab4f18c892 Tests: Unsupported test for bug1622.
Signed-off-by: Wilson Snyder <[email protected]>
2019-12-07 12:59:00 -05:00
Todd Strader 4480938b25 Fix interface reference tracing, bug1595. 2019-12-07 12:28:19 -05:00
Driss Hafdi 11a1b201a9 Tests: Unsupported on parameters in functions, bug1624. 2019-12-06 18:51:39 -05:00
Wilson Snyder 1a8b192e40 Unsupported on parameters in functions, bug1624. 2019-12-06 18:50:41 -05:00
Driss Hafdi aee3a32354 Added name to Contributors 2019-12-06 18:49:54 -05:00
Wilson Snyder 35e9489f33 Includes: Allow VCD trace of 64 bit array. 2019-12-05 22:25:30 -05:00
Wilson Snyder 5c6d74cd80 Fix assertion on dotted parameter arrayed function, bug1620. 2019-12-04 19:25:45 -05:00
Wilson Snyder 8611ff230d GTKWave: Merge from upstream. No functional change. 2019-12-04 05:31:38 -05:00
Wilson Snyder 8ef4097f00 Fix cppcheck warning. 2019-12-03 19:21:36 -05:00
Wilson Snyder fe684e8733 Allow redefining VL_PRINTF, bug1598. 2019-12-03 19:12:18 -05:00
Garrett Smith 96f8bbd023 Support float and shorts, bug1592, bug1619.
Signed-off-by: Wilson Snyder <[email protected]>
2019-12-03 18:26:22 -05:00
Wilson Snyder 95ffcad12e Fix t_queue crash on Trusty due to lifetime issue. 2019-12-03 07:18:59 -05:00
Wilson Snyder ebed1a9000 Fix 64-bit signed power with -1. 2019-12-03 06:58:38 -05:00
Wilson Snyder 2240f42bfa Fix 64-bit signed power with -1. 2019-12-03 06:26:17 -05:00
Wilson Snyder ac4f0da9ee Tests: Add output wire check. 2019-12-02 20:38:43 -05:00
Wilson Snyder 559852f60b Add error when number missing value. 2019-12-02 20:21:24 -05:00
Wilson Snyder b0669f3aca Fix false unused message on __Vemumtab, msg3180. 2019-12-02 19:03:33 -05:00
Todd Strader 00979ede14 Fix overly aggressive --protect-lib check 2019-12-02 08:33:44 -05:00
Todd Strader 13569ed98b Stop-gap CI email fix 2019-12-02 08:18:15 -05:00
Wilson Snyder 809a6de9cd Fix template brackets to avoid C++11, bug1617. 2019-12-02 06:19:33 -05:00
Wilson Snyder d65d8fda54 Optimize returns at end of functions. 2019-12-01 17:19:18 -05:00
Wilson Snyder 2076b0219d Fix labels on functions with returns, bug1614. 2019-12-01 17:19:03 -05:00
Wilson Snyder 32f93a8a1e Commentary, bug1615. 2019-12-01 12:43:41 -05:00
Wilson Snyder e28175108f Support queues (excluding {} notation and pattern assignments), bug545. 2019-12-01 12:35:49 -05:00
Wilson Snyder b81295230a Support associative arrays. 2019-12-01 11:52:48 -05:00
Wilson Snyder 6ae7f7b152 Last commit: Fix pattern mismatch crash. 2019-12-01 11:43:48 -05:00
Wilson Snyder 03026b63b9 Internals: Refactor huge pattern function. No functional change intended. 2019-12-01 11:03:53 -05:00
Wilson Snyder 38e586fabe Internals: Misc refectoring for assoc/queues. 2019-12-01 06:09:58 -05:00
Wilson Snyder 3d6e8e9eb0 Add -Wno-context.
Signed-off-by: Wilson Snyder <[email protected]>
2019-11-23 10:40:32 -05:00
Wilson Snyder df192f2b61 Support / with warning. 2019-11-23 09:16:06 -05:00
Wilson Snyder 17ad59394f Support shortreal as real, with a SHORTREAL warning. 2019-11-23 08:34:40 -05:00
Wilson Snyder 682c2a610f Fix $display("%p") to be closer to IEEE. 2019-11-21 19:29:46 -05:00
Wilson Snyder 59782266b9 Tests: Fix uninitalized data in t_vpi_time tests, bug1612. 2019-11-21 18:42:40 -05:00
Wilson Snyder 4885bcb93c Tests: Report core dumps on tests. 2019-11-21 18:42:40 -05:00
Todd Strader d47d3b5162 Fix CI typo 2019-11-21 08:31:18 -05:00
Wilson Snyder 99455a16bf Fix // in filenames, bug1610. 2019-11-20 21:23:03 -05:00
Wilson Snyder a86e1953eb Tests: Fix object order dependence, bug1611. 2019-11-20 06:57:39 -05:00
Matthew Ballance f63dfd7028 Fix VPI timed callbacks to be one-shot, pull5.
Signed-off-by: Matthew Ballance <[email protected]>
Signed-off-by: Wilson Snyder <[email protected]>
2019-11-19 22:44:33 -05:00
Matthew Ballance 7a413a121d Tests: Fix modelsim driver, pull 5.
Signed-off-by: Matthew Ballance <[email protected]>
Signed-off-by: Wilson Snyder <[email protected]>
2019-11-19 21:53:17 -05:00
Wilson Snyder 0f6b625db8 Fix hang on concat error, bug1608. 2019-11-19 19:23:40 -05:00
Wilson Snyder f134ac4f2f Black box some additional unsupported constructs. 2019-11-17 09:01:41 -05:00
Wilson Snyder 39eeda50c6 Internals: Rename MethodCall. No functional change. 2019-11-17 08:51:25 -05:00
Wilson Snyder 09ca4ce791 Internals: Assert proper AstArgs in place. 2019-11-17 08:43:04 -05:00
Wilson Snyder 2ff22d9050 Fix earlier +verilated+error+count to do all . 2019-11-17 08:12:39 -05:00
Wilson Snyder c726ad0142 Commentary 2019-11-17 07:53:30 -05:00
Wilson Snyder 0c0198cf55 Support string.toupper and string.tolower. 2019-11-17 05:05:09 -05:00
Wilson Snyder d480c2f033 Add +verilator+error+limit to see more assertion errors. 2019-11-16 18:25:47 -05:00
Wilson Snyder 8ebe86e54b Fix color assertion on empty if, bug1604. 2019-11-16 17:23:51 -05:00
Wilson Snyder 62af9dbed4 Fix member to method error messages. 2019-11-16 15:32:55 -05:00
Wilson Snyder 3eb0ff8aa0 Detect wrong number of args on method calls. 2019-11-16 15:18:57 -05:00
Wilson Snyder ce5a70fbca Internals: Split large method function. No functional change. 2019-11-16 14:40:45 -05:00
Wilson Snyder c36d9a68f5 Support $ungetc. 2019-11-16 12:55:10 -05:00
Wilson Snyder 8c5aa21a11 Support $rewind. 2019-11-16 12:21:35 -05:00
Wilson Snyder 47b5e36e60 Add -Wpedantic for compliance testing. 2019-11-16 11:59:21 -05:00
Wilson Snyder a481638edb Add error on redefining preprocessor directives. 2019-11-16 10:19:43 -05:00
Wilson Snyder de7caad710 Fix signed wildcard comparisons. 2019-11-16 09:58:01 -05:00
Wilson Snyder b1c14e485a Fix capital S signed numbers. 2019-11-16 09:39:41 -05:00
Wilson Snyder 66727670f9 Override gtkwave config in upstreamable way. No functional change. 2019-11-16 03:54:05 -05:00
Wilson Snyder b9322206d7 Update gtkwave files to latest 2019-11-16 03:44:51 -05:00
Wilson Snyder 617424e04a Internals: Fix cppcheck warning. No functional change. 2019-11-16 03:14:55 -05:00
Wilson Snyder e9c4ffa04e Fix for loop missing initializer, bug1605. 2019-11-15 18:24:55 -05:00
Todd Strader 30c2e53f9e Travis fixes 2019-11-14 17:54:57 -05:00
Sebastien Van Cauwenberghe a250decfaa Tests: Fix t_trace_cat when non-English sort. 2019-11-13 06:43:15 -05:00
Wilson Snyder 21a380def0 Rework variable emit to prep for other data types. 2019-11-12 21:52:25 -05:00
Wilson Snyder 77e30d4920 Internals: Remove dead code. No functional change. 2019-11-12 18:55:16 -05:00
Wilson Snyder 98dcbc6b3e Remove footprint comment when single threaded. 2019-11-11 22:21:37 -05:00
Wilson Snyder 6ce81698e7 devel release 2019-11-10 14:25:54 -05:00
178 changed files with 7098 additions and 1569 deletions
+42 -27
View File
@@ -4,15 +4,17 @@
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
language: cpp
version: ~> 1.0
os: linux
language: cpp
cache: ccache
env:
global:
- VERILATOR_CACHE=$HOME/verilator_cache
- VERILATOR_ROOT=$PWD
- VERILATOR_NUM_JOBS=$((`nproc` + 1))
- VERILATOR_NUM_JOBS=$(echo `nproc` + 1 | bc)
- VERILATOR_CONFIG_FLAGS="--enable-maintainer-mode --enable-longtests"
- OBJCACHE=ccache
@@ -23,7 +25,7 @@ cache:
before_install:
# Perl modules needed for testing
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker Bit::Vector
- sudo apt-get install gdb
- sudo apt-get install gdb gtkwave
before_script:
- bash -x ci/build_verilator.sh
after_script:
@@ -38,75 +40,79 @@ jobs:
- if: type != cron
stage: "Build Verilator"
name: Build Verilator
os: linux
compiler: gcc
script: echo "Done building Verilator"
# Non-cron build will just run on whatever linux flavor we get
- if: type != cron
stage: test
name: Dist test
os: linux
compiler: gcc
script: ci/test.sh dist
- if: type != cron
stage: test
name: Vlt test
os: linux
compiler: gcc
script: ci/test.sh vlt
- if: type != cron
stage: test
name: Vltmt test
os: linux
compiler: gcc
script: ci/test.sh vltmt
# Cron builds try different OS/compiler combinations
- if: type = cron
stage: "Build Verilator"
name: Build xenial gcc Verilator
os: xenial
os: linux
dist: xenial
compiler: gcc
script: echo "Done building Verilator"
- if: type = cron
stage: test
name: Xenail gcc dist test
os: xenial
name: Xenial gcc dist test
os: linux
dist: xenial
compiler: gcc
script: ci/test.sh dist
- if: type = cron
stage: test
name: Xenail gcc vlt test
os: xenial
name: Xenial gcc vlt test
os: linux
dist: xenial
compiler: gcc
script: ci/test.sh vlt
- if: type = cron
stage: test
name: Xenail gcc vltmt test
os: xenial
name: Xenial gcc vltmt test
os: linux
dist: xenial
compiler: gcc
script: ci/test.sh vltmt
- if: type = cron
stage: "Build Verilator"
name: Build xenial clang Verilator
os: xenial
os: linux
dist: xenial
compiler: clang
script: echo "Done building Verilator"
- if: type = cron
stage: test
name: Xenail clang dist test
os: xenial
name: Xenial clang dist test
os: linux
dist: xenial
compiler: clang
script: ci/test.sh dist
- if: type = cron
stage: test
name: Xenail clang vlt test
os: xenial
name: Xenial clang vlt test
os: linux
dist: xenial
compiler: clang
script: ci/test.sh vlt
- if: type = cron
stage: test
name: Xenail clang vltmt test
os: xenial
name: Xenial clang vltmt test
os: linux
dist: xenial
compiler: clang
script: ci/test.sh vltmt
# - if: type = cron
@@ -125,37 +131,46 @@ jobs:
# stage: test
# name: OSX gcc vlt test
# os: osx
# os: osx
# compiler: gcc
# script: ci/test.sh vlt
# - if: type = cron
# stage: test
# name: OSX gcc vltmt test
# os: osx
# os: osx
# compiler: gcc
# script: ci/test.sh vltmt
- if: type = cron
stage: "Build Verilator"
name: Build trusty gcc Verilator
os: trusty
os: linux
dist: trusty
compiler: gcc
script: echo "Done building Verilator"
- if: type = cron
stage: test
name: Trusty gcc dist test
os: trusty
os: linux
dist: trusty
compiler: gcc
script: ci/test.sh dist
- if: type = cron
stage: test
name: Trusty gcc vlt test
os: trusty
os: linux
dist: trusty
compiler: gcc
script: ci/test.sh vlt
- if: type = cron
stage: test
os: trusty
os: linux
dist: trusty
name: Trusty gcc vltmt test
compiler: gcc
script: ci/test.sh vltmt
notifications:
email:
if: repo = verilator/verilator
recipients:
- [email protected]
- [email protected]
+45
View File
@@ -2,6 +2,51 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.024 2019-12-08
** Support associative arrays (excluding [*] and pattern assignments), bug544.
** Support queues (excluding {} notation and pattern assignments), bug545.
*** Add +verilator+error+limit to see more assertion errors. [Peter Monsson]
*** Support string.toupper and string.tolower.
*** Support $rewind and $ungetc.
*** Support shortreal as real, with a SHORTREAL warning.
**** Add -Wpedantic and -Wno-context for compliance testing.
**** Add error on redefining preprocessor directives. [Piotr Binkowski]
**** Support $value$plusargs float and shorts, bug1592, bug1619. [Garrett Smith]
**** Fix gate lvalue optimization error, bug831. [Jonathon Donaldson, Driss Hafdi]
**** Fix color assertion on empty if, bug1604. [Andrew Holme]
**** Fix for loop missing initializer, bug1605. [Andrew Holme]
**** Fix hang on concat error, bug1608. [Bogdan Vukobratovic]
**** Fix VPI timed callbacks to be one-shot, pull5. [Matthew Ballance]
**** Fix // in filenames, bug1610. [Peter Nelson]
**** Fix $display("%p") to be closer to IEEE.
**** Fix labels on functions with returns, bug1614. [Mitch Hayenga]
**** Fix false unused message on __Vemumtab, msg3180. [Tobias Rosenkranz]
**** Fix assertion on dotted parameter arrayed function, bug1620. [Rich Porter]
**** Fix interface reference tracing, bug1595. [Todd Strader]
**** Fix error on unpacked concatenations, bug1627. [Driss Hafdi]
* Verilator 4.022 2019-11-10
** Add --protect-lib, bug1490. [Todd Strader]
+186 -126
View File
@@ -339,7 +339,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
-O<optimization-letter> Selectable optimizations
-o <executable> Name of final executable
--no-order-clock-delay Disable ordering clock enable assignments
--output-split <bytes> Split .cpp files into pieces
--output-split <statements> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .cpp functions
--output-split-ctrace <statements> Split tracing functions
-P Disable line numbers and blanks with -E
@@ -398,9 +398,11 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
-Werror-<message> Convert warnings to errors
-Wfuture-<message> Disable unknown message warnings
-Wno-<message> Disable warning
-Wno-context Disable source context on warnings
-Wno-fatal Disable fatal exit on warnings
-Wno-lint Disable all lint warnings
-Wno-style Disable all style warnings
-Wno-fatal Disable fatal exit on warnings
-Wpedantic Warn on compliance-test issues
--x-assign <mode> Assign non-initial Xs to this value
--x-initial <mode> Assign initial Xs to this value
--x-initial-edge Enable initial X->0 and X->1 edge triggers
@@ -408,8 +410,9 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--xml-output XML output filename
-y <dir> Directory to search for modules
This is a short summary of the arguments to run-time Verilated arguments.
detailed descriptions in L</"RUNTIME ARGUMENTS"> for more information.
This is a short summary of the arguments to simulation runtime Verilated
arguments. detailed descriptions in L</"SIMULATION RUNTIME ARGUMENTS"> for
more information.
+verilator+debug Enable debugging
+verilator+debugi+<value> Enable debugging at a level
@@ -511,10 +514,10 @@ calls.
=item --bbox-sys
Black box any unknown $system task or function calls. System tasks will be
simply NOPed, and system functions will be replaced by 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.
simply become no-operations, and system functions will be replaced by
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.
=item --bbox-unsup
@@ -794,8 +797,11 @@ will also go to standard out.
=item --error-limit I<value>
After this number of errors are encountered, exit. Warnings are not
counted in this limit. Defaults to 50.
After this number of errors are encountered during Verilator run, exit.
Warnings are not counted in this limit. Defaults to 50.
Does not affect simulation runtime errors, for those see
+verilator+error+limit.
=item --exe
@@ -916,8 +922,8 @@ Tune the inlining of modules. The default value of 2000 specifies that up
to 2000 new operations may be added to the model by inlining, if more than
this number of operations would result, the module is not inlined. Larger
values, or a value < 1 will inline everything, will lead to longer compile
times, but potentially faster runtimes. This setting is ignored for very
small modules; they will always be inlined, if allowed.
times, but potentially faster simulation runtimes. This setting is ignored
for very small modules; they will always be inlined, if allowed.
=item -LDFLAGS I<flags>
@@ -1060,7 +1066,7 @@ Rarely needed. Disables a bug fix for ordering of clock enables with
delayed assignments. This flag should only be used when suggested by the
developers.
=item --output-split I<bytes>
=item --output-split I<statements>
Enables splitting the output .cpp files into multiple outputs. When a C++
file exceeds the specified number of operations, a new file will be created
@@ -1072,6 +1078,9 @@ and the remaining files can be compiled on parallel machines. Using
design --output-split 20000 resulted in splitting into approximately
one-minute-compile chunks.
Typically when using this, make with VM_PARALLEL_BUILD=1, and use
I<ccache>.
=item --output-split-cfuncs I<statements>
Enables splitting functions in the output .cpp files into multiple
@@ -1170,9 +1179,10 @@ Verilator will record the start and end time of each macro-task across a
number of calls to eval. (What is a macro-task? See the Verilator internals
document.)
When profiling is enabled, the runtime will emit a blurb of profiling data
in non-human-friendly form. The C<verilator_gantt> script will transform
this into a nicer visual format and produce some related statistics.
When profiling is enabled, the simulation runtime will emit a blurb of
profiling data in non-human-friendly form. The C<verilator_gantt> script
will transform this into a nicer visual format and produce some related
statistics.
=item --protect-key I<key>
@@ -1201,9 +1211,10 @@ design information. This hashing uses the provided or default
Verilator will also create a {prefix}__idmap.xml file which contains the
mapping from the hashed identifiers back to the original identifiers. This
idmap file is to be kept private, and is to assist mapping any runtime
design assertions, coverage, or trace information, which will report the
hashed identifiers, back to the original design's identifier names.
idmap file is to be kept private, and is to assist mapping any simulation
runtime design assertions, coverage, or trace information, which will
report the hashed identifiers, back to the original design's identifier
names.
Using DPI imports/exports is allowed and generally relatively safe in terms
of information disclosed, which is limited to the DPI function prototyptes.
@@ -1406,14 +1417,14 @@ already visible.
The added signal will be a 32-bit value which will increment on each
coverage occurrence. Due to this, this option may greatly increase trace
file sizes and simulation time.
file sizes and simulation runtime.
=item --trace-depth I<levels>
Specify the number of levels deep to enable tracing, for example
--trace-level 1 to only see the top level's signals. Defaults to the
entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size.
improve simulation runtime and trace file size.
=item --trace-fst
@@ -1423,7 +1434,7 @@ 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 runtime but slower in total computes than
typically faster in simulation runtime but slower in total computes than
C<--trace-fst>. This overrides C<--trace> and C<--trace-fst>.
=item --trace-max-array I<depth>
@@ -1525,6 +1536,21 @@ Disable the specified warning message, or in some cases where noted here
disable an error. This will override any lint_on directives in the source,
i.e. the warning will still not be printed.
=item -Wno-context
Disable showing the suspected context of the warning message by quoting the
source text at the suspected location. This is used to appease tools which
process the error messages may get confused by lines from the original
source.
=item -Wno-fatal
When warnings are detected, print them, but do not exit the simulator.
Having warning messages in builds is sloppy. It is strongly recommended
you cleanup your code, use inline lint_off, or use -Wno-... flags rather
than using this option.
=item -Wno-lint
Disable all lint related warning messages, and all style warnings. This is
@@ -1545,13 +1571,12 @@ already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-IMPORTSTAR -Wno-INCABSPATH -Wno-PINCONNECTEMPTY -Wno-PINNOCONNECT
-Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED -Wno-VARHIDDEN".
=item -Wno-fatal
=item -Wpedantic
When warnings are detected, print them, but do not exit the simulator.
Having warning messages in builds is sloppy. It is strongly recommended
you cleanup your code, use inline lint_off, or use -Wno-... flags rather
than using this option.
Warn on any construct demanded by IEEE, and disable all Verilator
extensions that may interfere with IEEE compliance to the standard defined
with --language (etc). Similar to GCC's -Wpedantic. Rarely used, and
intended only for strict compliance tests.
=item -Wwarn-I<message>
@@ -1681,23 +1706,30 @@ are desired for error messages instead of relative filenames.
=back
=head1 RUNTIME ARGUMENTS
=head1 SIMULATION RUNTIME ARGUMENTS
The following are the arguments that may be passed to a Verilated
executable, provided that executable calls Verilated::commandArgs().
All runtime arguments begin with +verilator, so that the user's executable
may skip over all +verilator arguments when parsing its command line.
All simulation runtime arguments begin with +verilator, so that the user's
executable may skip over all +verilator arguments when parsing its command
line.
=over 4
=item +verilator+debug
Enable debugging. Equivalent to +verilator+debugi+4.
Enable simulation runtime debugging. Equivalent to +verilator+debugi+4.
=item +verilator+debugi+I<value>
Enable debugging at the provided level.
Enable simulation runtime debugging at the provided level.
=item +verilator+error+limit+I<value>
Set number of non-fatal errors (e.g. assertion failures) before exiting
simulation runtime. Also affects number of $stop calls needed before
exit. Defaults to 1.
=item +verilator+help
@@ -1705,20 +1737,20 @@ Display help and exit.
=item +verilator+prof+threads+file+I<filename>
When using --prof-threads, the filename to dump to. Defaults to
"profile_threads.dat".
When using --prof-threads at simulation runtime, the filename to dump to.
Defaults to "profile_threads.dat".
=item +verilator+prof+threads+start+I<value>
When using --prof-threads, 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.
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.
=item +verilator+prof+threads+window+I<value>
When using --prof-threads, after $time reaches
When using --prof-threads at simulation runtime, after $time reaches
+verilator+prof+threads+start, Verilator will warm up the profiling for
this number of eval() calls, then will capture the profiling of this number
of eval() calls. Defaults to 2, which makes sense for a
@@ -1727,14 +1759,15 @@ posedge eval() and one negedge eval().
=item +verilator+rand+reset+I<value>
When a model was Verilated using "-x-initial unique", sets the
initialization technique. 0 = Reset to zeros. 1 = Reset to all-ones. 2 =
Randomize. See L</"Unknown states">.
When a model was Verilated using "-x-initial unique", sets the simulation
runtime initialization technique. 0 = Reset to zeros. 1 = Reset to
all-ones. 2 = Randomize. See L</"Unknown states">.
=item +verilator+seed+I<value>
For $random and "-x-initial unique", set the random seed value. If zero or
not specified picks a value from the system random number generator.
For $random and "-x-initial unique", set the simulation runtime random seed
value. If zero or not specified picks a value from the system random
number generator.
=item +verilator+V
@@ -1915,7 +1948,7 @@ C++ compiler and size of your CPU's caches.
By default, the lib/verilated.mk file has optimization turned off. This is
for the benefit of new users, as it improves compile times at the cost of
runtimes. To add optimization as the default, set one of three variables,
simulation runtimes. To add optimization as the default, set one of three variables,
OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
-LDFLAGS option on the verilator command line to pass the flags directly to
the compiler or linker. Or, just for one run, pass them on the command
@@ -2037,7 +2070,7 @@ After running Make, the C++ compiler may produce the following:
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 runtime.
needed at simultion runtime.
=item OBJCACHE
@@ -2354,9 +2387,9 @@ some test-benches that expect immediate propagation.
Note the VPI by its specified implementation will always be much slower
than accessing the Verilator values by direct reference
(structure->module->signame), as the VPI accessors perform lookup in
functions at runtime requiring at best hundreds of instructions, while the
direct references are evaluated by the compiler and result in only a couple
of instructions.
functions at simulation runtime requiring at best hundreds of instructions,
while the direct references are evaluated by the compiler and result in
only a couple of instructions.
For signal callbacks to work the main loop of the program must call
VerilatedVpi::callValueCbs().
@@ -2828,8 +2861,8 @@ With the --assert switch, Verilator reads any "//synopsys full_case" or
When these synthesis directives are discovered, Verilator will either
formally prove the directive to be true, or failing that, will insert the
appropriate code to detect failing cases at runtime and print an "Assertion
failed" error message.
appropriate code to detect failing cases at simulation runtime and print an
"Assertion failed" error message.
Verilator likewise also asserts any "unique" or "priority" SystemVerilog
keywords on case statement, as well as "unique" on if statements.
@@ -3016,7 +3049,7 @@ appropriate --coverage flags are passed) after being disabled earlier with
=item /*verilator inline_module*/
Specifies the module the comment appears in may be inlined into any modules
that use this module. This is useful to speed up simulation time with some
that use this module. This is useful to speed up simulation runtime with some
small loss of trace visibility and modularity. Note signals under inlined
submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not
allow "." in signal names. When tracing such signals the tracing routines
@@ -3316,10 +3349,10 @@ from a four state simulator. An === comparison to X will always be false,
so that Verilog code which checks for uninitialized logic will not fire.
Assigning a variable to a X will actually assign the variable to a random
value (see the --x-assign switch and +verilator+rand+reset runtime switch.)
Thus if the value is actually used, the random value should cause
downstream errors. Integers also randomize, even though the Verilog 2001
specification says they initialize to zero.
value (see the --x-assign switch and +verilator+rand+reset simulation
runtime switch.) Thus if the value is actually used, the random value
should cause downstream errors. Integers also randomize, even though the
Verilog 2001 specification says they initialize to zero.
All variables, depending on --x-initial setting, are typically randomly
initialized using a function. By running several random simulation runs
@@ -3554,8 +3587,7 @@ MCDs, which includes the mode parameter to $fopen being mandatory.
=item $fscanf, $sscanf
Only integer formats are supported; %e, %f, %m, %r, %v, and %z are not
supported.
The formats %r, %v, and %z are not supported.
=item $fullskew, $hold, $nochange, $period, $recovery, $recrem, $removal,
$setup, $setuphold, $skew, $timeskew, $width
@@ -3849,7 +3881,7 @@ The solution is to break the loop, as described for UNOPTFLAT.
=item DIDNOTCONVERGE
Error at runtime when model did not properly settle.
Error at simulation runtime when model did not properly settle.
Verilator sometimes has to evaluate combinatorial logic multiple times,
usually around code where a UNOPTFLAT warning was issued, but disabled.
@@ -3867,9 +3899,9 @@ the time of issuing a UNOPTFLAT Verilator didn't know if they would
eventually converge and assumed the would.
Next, run Verilator with --prof-cfuncs. Run make on the generated files
with "CPP_FLAGS=-DVL_DEBUG", to allow enabling runtime debug messages.
Rerun the test. Now just before the convergence error you should see
additional output similar to this:
with "CPP_FLAGS=-DVL_DEBUG", to allow enabling simulation runtime debug
messages. Rerun the test. Now just before the convergence error you
should see additional output similar to this:
CHANGE: filename.v:1: b
CHANGE: filename.v:2: a
@@ -4038,7 +4070,7 @@ discarded.
Warns that the specified signal comes from multiple always blocks. This is
often unsupported by synthesis tools, and is considered bad style. It will
also cause longer runtimes due to reduced optimizations.
also cause longer simulation runtimes due to reduced optimizations.
Ignoring this warning will only slow simulations, it will simulate
correctly.
@@ -4142,6 +4174,17 @@ the access means the access out of bounds will never execute or be used.
...
if (seven != 7) out = vec[seven]; // Never will use vec[7]
=item SHORTREAL
Warns that Verilator does not support "shortreal" and they will be
automatically promoted to "real". The recommendation is to replace any
"shortreal" in the code with "real", as "shortreal" is not widely supported
across industry tools.
Ignoring this warning may make Verilator simulations differ from other
simulators, if the increased precision of real affects your model or DPI
calls.
=item STMTDLY
Warns that you have a statement with a delayed time in front of it, for
@@ -4216,7 +4259,8 @@ correctly.
=item UNOPT
Warns that due to some construct, optimization of the specified signal or
block is disabled. The construct should be cleaned up to improve runtime.
block is disabled. The construct should be cleaned up to improve
simulation runtime.
A less obvious case of this is when a module instantiates two submodules.
Inside submodule A, signal I is input and signal O is output. Likewise in
@@ -4234,7 +4278,7 @@ correctly.
Warns that due to some construct, optimization of the specified signal is
disabled. The signal specified includes a complete scope to the signal; it
may be only one particular usage of a multiply instantiated block. The
construct should be cleaned up to improve runtime; two times better
construct should be cleaned up to improve simulation runtime; two times better
performance may be possible by fixing these warnings.
Unlike the UNOPT warning, this occurs after netlist flattening, and
@@ -4295,10 +4339,11 @@ the requested number of threads.
One workaround is to request fewer threads with C<--threads>.
Another possible workaround is to allow more MTasks in the runtime, by
increasing the value of --threads-max-mtasks. More MTasks will result in
more communication and synchronization overhead at runtime; the scheduler
attempts to minimize the number of MTasks for this reason.
Another possible workaround is to allow more MTasks in the simulation
runtime, by increasing the value of --threads-max-mtasks. More MTasks will
result in more communication and synchronization overhead at simulation
runtime; the scheduler attempts to minimize the number of MTasks for this
reason.
Ignoring this warning will only slow simulations, it will simulate
correctly.
@@ -4337,7 +4382,7 @@ similar to the following:
1'b0};
The reduction AND and constant zeros mean the net will always be zero, so
won't use simulation time. The redundant leading and trailing zeros avoid
won't use simulation runtime. The redundant leading and trailing zeros avoid
syntax errors if there are no signals between them. The magic name
"unused" (-unused-regexp) is recognized by Verilator and suppresses
warnings; if using other lint tools, either teach to tool to ignore signals
@@ -4704,6 +4749,9 @@ test_regress/t/t_extend_class files show an example of how to do this.
=item How do I get faster build times?
When running make pass the make variable VM_PARALLEL_BUILDS=1 so that
builds occur in parallel.
Use a recent compiler. Newer compilers tend do be faster, with the
now relatively old GCC 3.0 to 3.3 being horrible.
@@ -4890,63 +4938,75 @@ Inc., picoChip Designs Ltd., Sun Microsystems Inc., Nauticus Networks Inc.,
and SiCortex Inc.
The people who have contributed major functionality are Byron Bradley,
Jeremy Bennett, Jie Xu, Lane Brooks, John Coiner, Duane Galbi, Paul Wasson,
and Wilson Snyder. Major testers included Jeff Dutton, Jonathon Donaldson,
Ralf Karge, David Hewson, Iztok Jeras, Wim Michiels, Alex Solomatnikov,
Sebastien Van Cauwenberghe, Gene Weber, and Clifford Wolf.
Jeremy Bennett, Lane Brooks, John Coiner, Duane Galbi, Todd Strader, Paul
Wasson, Jie Xu, and Wilson Snyder. Major testers included Jeff Dutton,
Jonathon Donaldson, Ralf Karge, David Hewson, Iztok Jeras, Wim Michiels,
Alex Solomatnikov, Sebastien Van Cauwenberghe, Gene Weber, and Clifford
Wolf.
Some of the people who have provided ideas and feedback for Verilator
include: Ahmed El-Mahmoudy, David Addison, Tariq B. Ahmad, Nikana
Anastasiadis, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad
Bagri, Andrew Bardsley, Matthew Barr, Geoff Barrett, Julius Baxter, Jeremy
Bennett, Michael Berman, Victor Besyakov, David Binderman, Johan Bjork,
David Black, Tymoteusz Blazejczyk, Daniel Bone, Gregg Bouchard, Christopher
Boumenot, Nick Bowler, Byron Bradley, Bryan Brady, Charlie Brej, J Briquet,
Lane Brooks, John Brownlee, Jeff Bush, Lawrence Butcher, Ted Campbell,
Chris Candler, Lauren Carlson, Donal Casey, Sebastien Van Cauwenberghe,
Terry Chen, Enzo Chi, Robert A. Clark, Allan Cochrane, John Coiner, Laurens
van Dam, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, John Demme,
Mike Denio, John Deroo, Philip Derrick, Joe DErrico, John Dickol, Ruben
Diez, Danny Ding, Ivan Djordjevic, Jonathon Donaldson, Sebastian Dressler,
Alex Duller, Jeff Dutton, Usuario Eda, Chandan Egbert, Joe Eiler, Ahmed
include: David Addison, Tariq B. Ahmad, Nikana Anastasiadis, Hans Van
Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad Bagri, Matthew Ballance,
Andrew Bardsley, Matthew Barr, Geoff Barrett, Julius Baxter, Jeremy
Bennett, Michael Berman, Victor Besyakov, David Binderman, Piotr Binkowski,
Johan Bjork, David Black, Tymoteusz Blazejczyk, Daniel Bone, Gregg
Bouchard, Christopher Boumenot, Nick Bowler, Byron Bradley, Bryan Brady,
Maarten De Braekeleer, Charlie Brej, J Briquet, Lane Brooks, John Brownlee,
Jeff Bush, Lawrence Butcher, Tony Bybell, Ted Campbell, Chris Candler,
Lauren Carlson, Donal Casey, Sebastien Van Cauwenberghe, Alex Chadwick,
Terry Chen, Yi-Chung Chen, Enzo Chi, Robert A. Clark, Allan Cochrane, John
Coiner, Gianfranco Costamagna, George Cuan, Joe DErrico, Lukasz Dalek,
Laurens van Dam, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, John
Demme, Mike Denio, John Deroo, Philip Derrick, John Dickol, Ruben Diez,
Danny Ding, Jacko Dirks, Ivan Djordjevic, Jonathon Donaldson, Leendert van
Doorn, Sebastian Dressler, Alex Duller, Jeff Dutton, Tomas Dzetkulic,
Usuario Eda, Charles Eddleston, Chandan Egbert, Joe Eiler, Ahmed
El-Mahmoudy, Trevor Elbourne, Robert Farrell, Eugen Fekete, Fabrizio
Ferrandi, Brian Flachs, Andrea Foletto, Bob Fredieu, Duane Galbi, Christian
Gelinek, Glen Gibb, Shankar Giri, Dan Gisselquist, Sam Gladstone, Amir
Gonnen, Chitlesh Goorah, Xuan Guo, Neil Hamilton, Jannis Harder, Junji
Hashimoto, Thomas Hawkins, Robert Henry, David Hewson, Jamey Hicks, Joel
Holdsworth, Hiroki Honda, Alex Hornung, David Horton, Jae Hossell, Alan
Hunter, James Hutchinson, Jamie Iles, Ben Jackson, Shareef Jalloq,
Krzysztof Jankowski, HyungKi Jeong, Iztok Jeras, James Johnson, Christophe
Joly, Franck Jullien, James Jung, Mike Kagen, Arthur Kahlich, Kaalia Kahn,
Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz,
Sol Katzman, Jonathan Kimmitt, Olof Kindgren, Dan Kirkham, Sobhan Klnv,
Gernot Koch, Soon Koh, Steve Kolecki, Brett Koonce, Wojciech Koszek, Varun
Koyyalagunta, David Kravitz, Roland Kruse, Sergey Kvachonok, Ed Lander,
Steve Lang, Stephane Laurent, Walter Lavino, Christian Leber, Igor Lesik,
John Li, Eivind Liland, Yu Sheng Lin, Charlie Lind, Andrew Ling, Paul Liu,
Derek Lockhart, Arthur Low, Stefan Ludwig, Dan Lussier, Fred Ma, Duraid
Madina, Julien Margetts, Mark Marshall, Alfonso Martinez, Yves Mathieu,
Patrick Maupin, Jason McMullan, Elliot Mednick, Wim Michiels, Miodrag
Milanovic, Wai Sum Mong, Sean Moore, Dennis Muhlestein, John Murphy,
Richard Myers, Dimitris Nalbantis, Bob Newgard, Cong Van Nguyen, Paul
Nitza, Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, James
Pallister, Brad Parker, Maciej Piechotka, David Pierce, Dominic Plunkett,
David Poole, Mike Popoloski, Rich Porter, Niranjan Prabhu, Usha
Priyadharshini, Mark Jackson Pulver, Prateek Puri, Marshal Qiao, Chris
Randall, Anton Rapp, Josh Redford, Odd Magne Reitan, Frederic Requin,
Alberto Del Rio, Oleg Rodionov, Paul Rolfe, Arjen Roodselaar, Jan Egil
Ruud, John Sanguinetti, Galen Seitz, Salman Sheikh, Mike Shinkarovsky,
Rafael Shirakawa, Jeffrey Short, Rodney Sinclair, Steven Slatter, Brian
Small, Wilson Snyder, Alex Solomatnikov, Wei Song, Art Stamness, John
Stevenson, Patrick Stewart, Rob Stoddard, Todd Strader, John Stroebel, Sven
Stucki, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu
Takatsukasa, Peter Tengstrand, Wesley Terpstra, Rui Terra, Stefan Thiede,
Gary Thomas, Kevin Thompson, Ian Thompson, Mike Thyer, Hans Tichelaar,
Steve Tong, Michael Tresidder, Holger Waechtler, Stefan Wallentowitz, Shawn
Wang, Paul Wasson, Greg Waters, Thomas Watts, Eugene Weber, David Welch,
Thomas J Whatson, Leon Wildman, Gerald Williams, Trevor Williams, Jeff
Winston, Joshua Wise, Clifford Wolf, Johan Wouters, Junyi Xi, Ding
Xiaoliang, Jie Xu, Mandy Xu, Luke Yang, and Amir Yazdanbakhsh.
Ferrandi, Udi Finkelstein, Brian Flachs, Andrea Foletto, Bob Fredieu, Duane
Galbi, Benjamin Gartner, Christian Gelinek, Peter Gerst, Glen Gibb, Shankar
Giri, Dan Gisselquist, Sam Gladstone, Amir Gonnen, Chitlesh Goorah, Sergi
Granell, Al Grant, Xuan Guo, Driss Hafdi, Neil Hamilton, Oyvind Harboe,
Jannis Harder, Junji Hashimoto, Thomas Hawkins, Mitch Hayenga, Robert
Henry, David Hewson, Jamey Hicks, Joel Holdsworth, Andrew Holme, Hiroki
Honda, Alex Hornung, David Horton, Jae Hossell, Alan Hunter, James
Hutchinson, Jamie Iles, Ben Jackson, Shareef Jalloq, Krzysztof Jankowski,
HyungKi Jeong, Iztok Jeras, James Johnson, Christophe Joly, Franck Jullien,
James Jung, Mike Kagen, Arthur Kahlich, Kaalia Kahn, Guy-Armand Kamendje,
Vasu Kandadi, Kanad Kanhere, Patricio Kaplan, Pieter Kapsenberg, Ralf
Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Olof Kindgren, Kevin
Kiningham, Dan Kirkham, Sobhan Klnv, Gernot Koch, Soon Koh, Steve Kolecki,
Brett Koonce, Will Korteland, Wojciech Koszek, Varun Koyyalagunta, David
Kravitz, Roland Kruse, Sergey Kvachonok, Ed Lander, Steve Lang, Stephane
Laurent, Walter Lavino, Christian Leber, Larry Lee, Igor Lesik, John Li,
Eivind Liland, Yu Sheng Lin, Charlie Lind, Andrew Ling, Paul Liu, Derek
Lockhart, Jake Longo, Arthur Low, Stefan Ludwig, Dan Lussier, Fred Ma,
Duraid Madina, Affe Mao, Julien Margetts, Mark Marshall, Alfonso Martinez,
Yves Mathieu, Patrick Maupin, Jason McMullan, Elliot Mednick, Wim Michiels,
Miodrag Milanovic, Wai Sum Mong, Peter Monsson, Sean Moore, Dennis
Muhlestein, John Murphy, Matt Myers, Richard Myers, Dimitris Nalbantis,
Peter Nelson, Bob Newgard, Cong Van Nguyen, Paul Nitza, Yossi Nivin, Pete
Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Aleksander Osman, James
Pallister, Brad Parker, Dan Petrisko, Maciej Piechotka, David Pierce,
Dominic Plunkett, David Poole, Mike Popoloski, Roman Popov, Rich Porter,
Niranjan Prabhu, Usha Priyadharshini, Mark Jackson Pulver, Prateek Puri,
Marshal Qiao, Danilo Ramos, Chris Randall, Anton Rapp, Josh Redford, Odd
Magne Reitan, Frederic Requin, Frederick Requin, Alberto Del Rio, Eric
Rippey, Oleg Rodionov, Paul Rolfe, Arjen Roodselaar, Tobias Rosenkranz, Jan
Egil Ruud, Denis Rystsov, John Sanguinetti, Galen Seitz, Salman Sheikh, Hao
Shi, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey Short, Anderson Ignacio
Da Silva, Rodney Sinclair, Steven Slatter, Brian Small, Garrett Smith,
Wilson Snyder, Stan Sokorac, Alex Solomatnikov, Wei Song, Art Stamness,
John Stevenson, Patrick Stewart, Rob Stoddard, Todd Strader, John Stroebel,
Sven Stucki, Howard Su, Emerson Suguimoto, Gene Sullivan, Renga
Sundararajan, Rupert Swarbrick, Yutetsu Takatsukasa, Peter Tengstrand,
Wesley Terpstra, Rui Terra, Stefan Thiede, Gary Thomas, Ian Thompson, Kevin
Thompson, Mike Thyer, Hans Tichelaar, Viktor Tomov, Steve Tong, Michael
Tresidder, Neil Turton, Bogdan Vukobratovic, Holger Waechtler, Philipp
Wagner, Stefan Wallentowitz, Shawn Wang, Paul Wasson, Greg Waters, Thomas
Watts, Eugene Weber, David Welch, Thomas J Whatson, Leon Wildman, Gerald
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Clifford Wolf, Johan
Wouters, Junyi Xi, Ding Xiaoliang, Jie Xu, Mandy Xu, Luke Yang, and Amir
Yazdanbakhsh.
Thanks to them, and all those we've missed including above, or wished to
remain anonymous.
+1 -1
View File
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[4.022 2019-11-10],
AC_INIT([Verilator],[4.024 2019-12-08],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file
+6 -1
View File
@@ -2,21 +2,26 @@ The contributors listed below have certified their Verilator contributions
under the Developer Certificate of Origin
(https://developercertificate.org/).
Please see the Verilator manual for additional contributors.
Please see the Verilator manual for 200+ additional contributors. Thanks to
all.
Ahmed El-Mahmoudy
Alex Chadwick
Chris Randall
Driss Hafdi
Eric Rippey
Garrett Smith
Gianfranco Costamagna
Howard Su
Iztok Jeras
Jeremy Bennett
John Coiner
Julien Margetts
Kanad Kanhere
Kevin Kiningham
Lukasz Dalek
Maarten De Braekeleer
Matthew Ballance
Mike Popoloski
Patrick Stewart
Philipp Wagner
+13
View File
@@ -25,7 +25,20 @@ endif
DOT = dot
PYTHON = python3
PYTHON_VERSION := $(shell ${PYTHON} --version 2>&1)
PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,${PYTHON_VERSION}))
PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL})
PYTHON_VERSION_MINOR := $(word 2,${PYTHON_VERSION_FULL})
PYTHON_GE_3_5 := $(shell [ ${PYTHON_VERSION_MAJOR} -eq 3 -a ${PYTHON_VERSION_MINOR} -ge 5 ] && echo true)
ifeq (${PYTHON_GE_3_5},true)
default: test
else
default: python_message
endif
python_message:
@echo "Found Python version ${PYTHON_VERSION}, but require >= 3.5"
test: \
test-vl_file_copy \
+66 -23
View File
@@ -37,13 +37,15 @@
*
*/
// Verilator: use hardcoded config file
//#include <config.h>
#include "fst_config.h"
#ifndef FST_CONFIG_INCLUDE
# define FST_CONFIG_INCLUDE <config.h>
#endif
#include FST_CONFIG_INCLUDE
#include "fstapi.h"
#include "fastlz.h"
#include "lz4.h"
#include <errno.h>
#ifndef HAVE_LIBPTHREAD
#undef FST_WRITER_PARALLEL
@@ -130,6 +132,16 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3
#include <sys/sysctl.h>
#endif
#ifdef __GNUC__
// Boolean expression more often true than false
#define FST_LIKELY(x) __builtin_expect(!!(x), 1)
// Boolean expression more often false than true
#define FST_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define FST_LIKELY(x) (!!(x))
#define FST_UNLIKELY(x) (!!(x))
#endif
#define FST_APIMESS "FSTAPI | "
/***********************/
@@ -954,6 +966,19 @@ fflush(xc->handle);
/*
* mmap functions
*/
static void fstWriterMmapSanity(void *pnt, const char *file, int line, const char *usage)
{
#if !defined(__CYGWIN__) && !defined(__MINGW32__)
if(pnt == MAP_FAILED)
{
fprintf(stderr, "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", usage, errno, file, line);
perror("Why");
pnt = NULL;
}
#endif
}
static void fstWriterCreateMmaps(struct fstWriterContext *xc)
{
off_t curpos = ftello(xc->handle);
@@ -976,12 +1001,20 @@ fflush(xc->handle);
if(!xc->valpos_mem)
{
fflush(xc->valpos_handle);
xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0);
errno = 0;
if(xc->maxhandle)
{
fstWriterMmapSanity(xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0), __FILE__, __LINE__, "xc->valpos_mem");
}
}
if(!xc->curval_mem)
{
fflush(xc->curval_handle);
xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0);
errno = 0;
if(xc->maxvalpos)
{
fstWriterMmapSanity(xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0), __FILE__, __LINE__, "xc->curval_handle");
}
}
}
@@ -1684,7 +1717,8 @@ fflush(xc->tchn_handle);
tlen = ftello(xc->tchn_handle);
fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0);
errno = 0;
fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0), __FILE__, __LINE__, "tmem");
if(tmem)
{
unsigned long destlen = tlen;
@@ -1876,7 +1910,7 @@ if(xc)
if(xc && !xc->already_in_close && !xc->already_in_flush)
{
unsigned char *tmem;
unsigned char *tmem = NULL;
off_t fixup_offs, tlen, hlen;
xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
@@ -1892,7 +1926,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush)
xc->skip_writing_section_hdr = 1;
if(!xc->size_limit_locked)
{
if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */
if(FST_UNLIKELY(xc->is_initial_time)) /* simulation time never advanced so mock up the changes as time zero ones */
{
fstHandle dupe_idx;
@@ -1914,7 +1948,12 @@ if(xc && !xc->already_in_close && !xc->already_in_flush)
/* write out geom section */
fflush(xc->geom_handle);
tlen = ftello(xc->geom_handle);
tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0);
errno = 0;
if(tlen)
{
fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0), __FILE__, __LINE__, "tmem");
}
if(tmem)
{
unsigned long destlen = tlen;
@@ -2022,14 +2061,18 @@ if(xc && !xc->already_in_close && !xc->already_in_flush)
{
int lz4_maxlen;
unsigned char *mem;
unsigned char *hmem;
unsigned char *hmem = NULL;
int packed_len;
fflush(xc->handle);
lz4_maxlen = LZ4_compressBound(xc->hier_file_len);
mem = (unsigned char *)malloc(lz4_maxlen);
hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0);
errno = 0;
if(xc->hier_file_len)
{
fstWriterMmapSanity(hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0), __FILE__, __LINE__, "hmem");
}
packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len);
fstMunmap(hmem, xc->hier_file_len);
@@ -2845,12 +2888,12 @@ const unsigned char *buf = (const unsigned char *)val;
uint32_t offs;
int len;
if((xc) && (handle <= xc->maxhandle))
if(FST_LIKELY((xc) && (handle <= xc->maxhandle)))
{
uint32_t fpos;
uint32_t *vm4ip;
if(!xc->valpos_mem)
if(FST_UNLIKELY(!xc->valpos_mem))
{
xc->vc_emitted = 1;
fstWriterCreateMmaps(xc);
@@ -2860,17 +2903,17 @@ if((xc) && (handle <= xc->maxhandle))
vm4ip = &(xc->valpos_mem[4*handle]);
len = vm4ip[1];
if(len) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */
if(FST_LIKELY(len)) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */
{
if(!xc->is_initial_time)
if(FST_LIKELY(!xc->is_initial_time))
{
fpos = xc->vchg_siz;
if((fpos + len + 10) > xc->vchg_alloc_siz)
if(FST_UNLIKELY((fpos + len + 10) > xc->vchg_alloc_siz))
{
xc->vchg_alloc_siz += (xc->fst_break_add_size + len); /* +len added in the case of extremely long vectors and small break add sizes */
xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
if(!xc->vchg_mem)
if(VL_UNLIKELY(!xc->vchg_mem))
{
fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChange, exiting.\n");
exit(255);
@@ -2961,12 +3004,12 @@ void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const v
struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
const unsigned char *buf = (const unsigned char *)val;
if((xc) && (handle <= xc->maxhandle))
if(FST_LIKELY((xc) && (handle <= xc->maxhandle)))
{
uint32_t fpos;
uint32_t *vm4ip;
if(!xc->valpos_mem)
if(FST_UNLIKELY(!xc->valpos_mem))
{
xc->vc_emitted = 1;
fstWriterCreateMmaps(xc);
@@ -2976,15 +3019,15 @@ if((xc) && (handle <= xc->maxhandle))
vm4ip = &(xc->valpos_mem[4*handle]);
/* there is no initial time dump for variable length value changes */
if(!vm4ip[1]) /* len of zero = variable length */
if(FST_LIKELY(!vm4ip[1])) /* len of zero = variable length */
{
fpos = xc->vchg_siz;
if((fpos + len + 10 + 5) > xc->vchg_alloc_siz)
if(FST_UNLIKELY((fpos + len + 10 + 5) > xc->vchg_alloc_siz))
{
xc->vchg_alloc_siz += (xc->fst_break_add_size + len + 5); /* +len added in the case of extremely long vectors and small break add sizes */
xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
if(!xc->vchg_mem)
if(FST_UNLIKELY(!xc->vchg_mem))
{
fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n");
exit(255);
@@ -3006,7 +3049,7 @@ unsigned int i;
int skip = 0;
if(xc)
{
if(xc->is_initial_time)
if(FST_UNLIKELY(xc->is_initial_time))
{
if(xc->size_limit_locked) /* this resets xc->is_initial_time to one */
{
+90 -16
View File
@@ -71,6 +71,8 @@ VerilatedImp VerilatedImp::s_s;
//===========================================================================
// User definable functions
// Note a TODO is a future version of the API will pass a structure so that
// the calling arguments allow for extension
#ifndef VL_USER_FINISH ///< Define this to override this function
void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
@@ -109,6 +111,18 @@ void vl_fatal(const char* filename, int linenum, const char* hier, const char* m
}
#endif
#ifndef VL_USER_STOP_MAYBE ///< Define this to override this function
void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_UNSAFE {
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");
} else {
vl_stop(filename, linenum, hier);
}
}
#endif
//===========================================================================
// Wrapper to call certain functions via messages when multithreaded
@@ -122,13 +136,13 @@ void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAF
#endif
}
void VL_STOP_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE {
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(filename, linenum, hier);
vl_stop_maybe(filename, linenum, hier, maybe);
}));
#else
vl_stop(filename, linenum, hier);
vl_stop_maybe(filename, linenum, hier, maybe);
#endif
}
@@ -215,13 +229,15 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
// Overall class init
Verilated::Serialized::Serialized() {
s_randReset = 0;
s_randSeed = 0;
s_debug = 0;
s_calcUnusedSigs = false;
s_gotFinish = false;
s_assertOn = true;
s_fatalOnVpiError = true; // retains old default behaviour
s_errorCount = 0;
s_errorLimit = 1;
s_randReset = 0;
s_randSeed = 0;
}
Verilated::NonSerialized::NonSerialized() {
@@ -529,10 +545,10 @@ 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_I(obits)) { // -1
if (rwp[0] & 1) return VL_MASK_I(obits); // -1^odd=-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;
@@ -1692,9 +1708,24 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
_vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]); lsb+=8;
}
break;
case 'e': // FALLTHRU - Unsupported
case 'f': // FALLTHRU - Unsupported
case 'g': // FALLTHRU - Unsupported
case 'e': {
double temp = 0.f;
sscanf(dp, "%le", &temp);
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
break;
}
case 'f': {
double temp = 0.f;
sscanf(dp, "%lf", &temp);
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
break;
}
case 'g': {
double temp = 0.f;
sscanf(dp, "%lg", &temp);
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
break;
}
default: // Other simulators simply return 0 in these cases and don't error out
return 0;
}
@@ -1740,7 +1771,35 @@ const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
}
//===========================================================================
// Heavy functions
// 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_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);
}
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);
}
return out;
}
std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
// See also _VL_VINT_TO_STRING
@@ -1802,6 +1861,18 @@ void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_calcUnusedSigs = flag;
}
void Verilated::errorCount(int val) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_errorCount = val;
}
void Verilated::errorCountInc() VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
++s_s.s_errorCount;
}
void Verilated::errorLimit(int val) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_errorLimit = val;
}
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_gotFinish = flag;
@@ -1829,19 +1900,19 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
}
const char* Verilated::catName(const char* n1, const char* n2) VL_MT_SAFE {
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
// Returns new'ed data
// Used by symbol table creation to make module names
static VL_THREAD_LOCAL char* strp = NULL;
static VL_THREAD_LOCAL size_t len = 0;
size_t newlen = strlen(n1)+strlen(n2)+2;
size_t newlen = strlen(n1)+strlen(n2)+strlen(delimiter)+1;
if (!strp || newlen > len) {
if (strp) delete [] strp;
strp = new char[newlen];
len = newlen;
}
strcpy(strp, n1);
if (*n1) strcat(strp, ".");
if (*n1) strcat(strp, delimiter);
strcat(strp, n2);
return strp;
}
@@ -1991,6 +2062,9 @@ void VerilatedImp::commandArgVl(const std::string& arg) {
else if (commandArgVlValue(arg, "+verilator+debugi+", value/*ref*/)) {
Verilated::debug(atoi(value.c_str()));
}
else if (commandArgVlValue(arg, "+verilator+error+limit+", value/*ref*/)) {
Verilated::errorLimit(atoi(value.c_str()));
}
else if (arg == "+verilator+help") {
versionDump();
VL_PRINTF_MT("For help, please see 'verilator --help'\n");
+28 -19
View File
@@ -44,6 +44,11 @@
# include <thread>
#endif
// Allow user to specify their own include file
#ifdef VL_VERILATED_INCLUDE
# include VL_VERILATED_INCLUDE
#endif
//=============================================================================
// Switches
@@ -221,13 +226,6 @@ public:
//=========================================================================
// Declare nets
#ifndef VL_ST_SIG
# define VL_ST_SIG8(name, msb,lsb) CData name ///< Declare signal, 1-8 bits
# define VL_ST_SIG16(name, msb,lsb) SData name ///< Declare signal, 9-16 bits
# define VL_ST_SIG64(name, msb,lsb) QData name ///< Declare signal, 33-64 bits
# define VL_ST_SIG(name, msb,lsb) IData name ///< Declare signal, 17-32 bits
# define VL_ST_SIGW(name,msb,lsb,words) WData name[words] ///< Declare signal, 65+ bits
#endif
#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
@@ -362,6 +360,8 @@ class Verilated {
bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
// Slow path
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
int s_randSeed; ///< Random seed: 0=random
Serialized();
@@ -434,6 +434,13 @@ public:
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
static bool calcUnusedSigs() VL_MT_SAFE { ///< Return calcUnusedSigs value
return s_s.s_calcUnusedSigs; }
/// Current number of errors/assertions
static void errorCount(int val) VL_MT_SAFE;
static void errorCountInc() VL_MT_SAFE;
static int errorCount() VL_MT_SAFE { return s_s.s_errorCount; }
/// Set number of errors/assertions before stop
static void errorLimit(int val) VL_MT_SAFE;
static int errorLimit() VL_MT_SAFE { return s_s.s_errorLimit; }
/// Did the simulation $finish?
static void gotFinish(bool flag) VL_MT_SAFE;
static bool gotFinish() VL_MT_SAFE { return s_s.s_gotFinish; } ///< Return if got a $finish
@@ -494,7 +501,8 @@ public:
public:
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
// Internal: Create a new module name by concatenating two strings
static const char* catName(const char* n1, const char* n2); // Returns static data
static const char* catName(const char* n1, const char* n2,
const char* delimiter="."); // Returns static data
// Internal: Throw signal assertion
static void overWidthError(const char* signame) VL_MT_SAFE;
@@ -572,7 +580,8 @@ extern void vl_fatal(const char* filename, int linenum, const char* hier,
/// Multithread safe wrapper for calls to $finish
extern void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE;
/// Multithread safe wrapper for calls to $stop
extern void VL_STOP_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE;
extern void VL_STOP_MT(const char* filename, int linenum, const char* hier,
bool maybe = true) VL_MT_SAFE;
/// Multithread safe wrapper to call for a couple of fatal messages
extern void VL_FATAL_MT(const char* filename, int linenum, const char* hier,
const char* msg) VL_MT_SAFE;
@@ -1516,11 +1525,11 @@ QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp);
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 (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 (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
}
@@ -1530,12 +1539,12 @@ static inline IData VL_POWSS_III(int obits, int, int rbits,
}
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_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
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
}
return 0;
-1
View File
@@ -48,7 +48,6 @@ VK_CPPFLAGS_ALWAYS += \
-MMD \
-I$(VERILATOR_ROOT)/include \
-I$(VERILATOR_ROOT)/include/vltstd \
-DVL_PRINTF=printf \
-DVM_COVERAGE=$(VM_COVERAGE) \
-DVM_SC=$(VM_SC) \
-DVM_TRACE=$(VM_TRACE) \
+1
View File
@@ -31,6 +31,7 @@
#endif
// Include the GTKWave implementation directly
#define FST_CONFIG_INCLUDE "fst_config.h"
#include "gtkwave/fastlz.c"
#include "gtkwave/fstapi.c"
#include "gtkwave/lz4.c"
+261
View File
@@ -30,8 +30,249 @@
#include "verilated.h"
#include <deque>
#include <map>
#include <string>
//===================================================================
// String formatters (required by below containers)
extern std::string VL_TO_STRING(CData obj);
extern std::string VL_TO_STRING(SData obj);
extern std::string VL_TO_STRING(IData obj);
extern std::string VL_TO_STRING(QData obj);
inline std::string VL_TO_STRING(const std::string& obj) { return "\""+obj+"\""; }
//===================================================================
// Verilog array container
// Similar to std::array<WData, N>, but:
// 1. Doesn't require C++11
// 2. Lighter weight, only methods needed by Verilator, to help compile time.
//
// This is only used when we need an upper-level container and so can't
// simply use a C style array (which is just a pointer).
template <std::size_t T_Words> class VlWide {
WData m_storage[T_Words];
public:
// Default constructor/destructor/copy are fine
const WData& at(size_t index) const { return m_storage[index]; }
WData& at(size_t index) { return m_storage[index]; }
WData* data() { return &m_storage[0]; }
const WData* data() const { return &m_storage[0]; }
bool operator<(const VlWide<T_Words>& rhs) const {
return VL_LT_W(T_Words, data(), rhs.data());
}
};
// Convert a C array to std::array reference by pointer magic, without copy.
// Data type (second argument) is so the function template can automatically generate.
template <std::size_t T_Words>
VlWide<T_Words>& VL_CVT_W_A(WDataInP inp, const VlWide<T_Words>&) {
return *((VlWide<T_Words>*)inp);
}
//===================================================================
// Verilog associative array container
// There are no multithreaded locks on this; the base variable must
// be protected by other means
//
template <class T_Key, class T_Value> class VlAssocArray {
private:
// TYPES
typedef std::map<T_Key, T_Value> Map;
public:
typedef typename Map::const_iterator const_iterator;
private:
// MEMBERS
Map m_map; // State of the assoc array
T_Value m_defaultValue; // Default value
public:
// CONSTRUCTORS
VlAssocArray() {
// m_defaultValue isn't defaulted. Caller's constructor must do it.
}
~VlAssocArray() {}
// Standard copy constructor works. Verilog: assoca = assocb
// METHODS
T_Value& atDefault() { return m_defaultValue; }
// Size of array. Verilog: function int size(), or int num()
int size() const { return m_map.size(); }
// Clear array. Verilog: function void delete([input index])
void clear() { m_map.clear(); }
void erase(const T_Key& index) { m_map.erase(index); }
// Return 0/1 if element exists. Verilog: function int exists(input index)
int exists(const T_Key& index) const { return m_map.find(index) != m_map.end(); }
// Return first element. Verilog: function int first(ref index);
int first(T_Key& indexr) const {
typename Map::const_iterator it = m_map.begin();
if (it == m_map.end()) return 0;
indexr = it->first;
return 1;
}
// Return last element. Verilog: function int last(ref index)
int last(T_Key& indexr) const {
typename Map::const_reverse_iterator it = m_map.rbegin();
if (it == m_map.rend()) return 0;
indexr = it->first;
return 1;
}
// Return next element. Verilog: function int next(ref index)
int next(T_Key& indexr) const {
typename Map::const_iterator it = m_map.find(indexr);
if (VL_UNLIKELY(it == m_map.end())) return 0;
it++;
if (VL_UNLIKELY(it == m_map.end())) return 0;
indexr = it->first;
return 1;
}
// Return prev element. Verilog: function int prev(ref index)
int prev(T_Key& indexr) const {
typename Map::const_iterator it = m_map.find(indexr);
if (VL_UNLIKELY(it == m_map.end())) return 0;
if (VL_UNLIKELY(it == m_map.begin())) return 0;
--it;
indexr = it->first;
return 1;
}
// Setting. Verilog: assoc[index] = v
// Can't just overload operator[] or provide a "at" reference to set,
// because we need to be able to insert only when the value is set
T_Value& at(const T_Key& index) {
typename Map::iterator it = m_map.find(index);
if (it == m_map.end()) {
std::pair<typename Map::iterator, bool> pit
= m_map.insert(std::make_pair(index, m_defaultValue));
return pit.first->second;
}
return it->second;
}
// Accessing. Verilog: v = assoc[index]
const T_Value& at(const T_Key& index) const {
typename Map::iterator it = m_map.find(index);
if (it == m_map.end()) return m_defaultValue;
else return it->second;
}
// For save/restore
const_iterator begin() const { return m_map.begin(); }
const_iterator end() const { return m_map.end(); }
// Dumping. Verilog: str = $sformatf("%p", assoc)
std::string to_string() const {
std::string out = "'{";
std::string comma;
for (typename Map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
out += comma + VL_TO_STRING(it->first) + ":" + VL_TO_STRING(it->second);
comma = ", ";
}
// Default not printed - maybe random init data
return out + "} ";
}
};
template <class T_Key, class T_Value>
std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
return obj.to_string();
}
//===================================================================
// Verilog queue container
// There are no multithreaded locks on this; the base variable must
// be protected by other means
//
template <class T_Value> class VlQueue {
private:
// TYPES
typedef std::deque<T_Value> Deque;
public:
typedef typename Deque::const_iterator const_iterator;
private:
// MEMBERS
Deque m_deque; // State of the assoc array
T_Value m_defaultValue; // Default value
public:
// CONSTRUCTORS
VlQueue() {
// m_defaultValue isn't defaulted. Caller's constructor must do it.
}
~VlQueue() {}
// Standard copy constructor works. Verilog: assoca = assocb
// METHODS
T_Value& atDefault() { return m_defaultValue; }
// Size. Verilog: function int size(), or int num()
int size() const { return m_deque.size(); }
// Clear array. Verilog: function void delete([input index])
void clear() { m_deque.clear(); }
void erase(size_t index) { if (VL_LIKELY(index < m_deque.size())) m_deque.erase(index); }
// function void q.push_front(value)
void push_front(const T_Value& value) { m_deque.push_front(value); }
// function void q.push_back(value)
void push_back(const T_Value& value) { m_deque.push_back(value); }
// function value_t q.pop_front();
T_Value pop_front() {
if (m_deque.empty()) return m_defaultValue;
T_Value v = m_deque.front(); m_deque.pop_front(); return v;
}
// function value_t q.pop_back();
T_Value pop_back() {
if (m_deque.empty()) return m_defaultValue;
T_Value v = m_deque.back(); m_deque.pop_back(); return v;
}
// Setting. Verilog: assoc[index] = v
// Can't just overload operator[] or provide a "at" reference to set,
// because we need to be able to insert only when the value is set
T_Value& at(size_t index) {
static T_Value s_throwAway;
if (VL_UNLIKELY(index >= m_deque.size())) {
s_throwAway = atDefault();
return s_throwAway;
}
else return m_deque[index];
}
// Accessing. Verilog: v = assoc[index]
const T_Value& at(size_t index) const {
static T_Value s_throwAway;
if (VL_UNLIKELY(index >= m_deque.size())) return atDefault();
else return m_deque[index];
}
// function void q.insert(index, value);
void insert(size_t index, const T_Value& value) {
if (VL_UNLIKELY(index >= m_deque.size())) return;
m_deque[index] = value;
}
// For save/restore
const_iterator begin() const { return m_deque.begin(); }
const_iterator end() const { return m_deque.end(); }
// Dumping. Verilog: str = $sformatf("%p", assoc)
std::string to_string() const {
std::string out = "'{";
std::string comma;
for (typename Deque::const_iterator it = m_deque.begin(); it != m_deque.end(); ++it) {
out += comma + VL_TO_STRING(*it);
comma = ", ";
}
return out + "} ";
}
};
template <class T_Value>
std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
return obj.to_string();
}
//======================================================================
// Conversion functions
@@ -61,6 +302,8 @@ inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits,
}
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
extern std::string VL_TOLOWER_NN(const std::string& ld);
extern std::string VL_TOUPPER_NN(const std::string& ld);
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
@@ -75,6 +318,18 @@ extern void VL_SFORMAT_X(int obits_ignored, std::string& output,
const char* formatp, ...) VL_MT_SAFE;
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE;
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, CData& rdr) VL_MT_SAFE {
WData rwp[2]; // WData must always be at least 2
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = rwp[0];
return got;
}
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, SData& rdr) VL_MT_SAFE {
WData rwp[2]; // WData must always be at least 2
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = rwp[0];
return got;
}
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE {
WData rwp[2]; // WData must always be at least 2
IData got = VL_VALUEPLUSARGS_INW(rbits, ld, rwp);
@@ -87,6 +342,12 @@ inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr)
if (got) rdr = VL_SET_QW(rwp);
return got;
}
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, double& rdr) VL_MT_SAFE {
WData rwp[2];
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = VL_CVT_D_Q(VL_SET_QW(rwp));
return got;
}
extern IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE;
#endif // Guard
+2 -2
View File
@@ -409,7 +409,7 @@ public: // But only for verilated*.cpp
static void fdDelete(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;
VerilatedLockGuard lock(s_s.m_fdMutex);
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
if (VL_UNLIKELY(!(fdi & (VL_ULL(1) << 31)) || idx >= s_s.m_fdps.size())) return;
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
s_s.m_fdps[idx] = NULL;
s_s.m_fdFree.push_back(idx);
@@ -417,7 +417,7 @@ public: // But only for verilated*.cpp
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;
VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
if (VL_UNLIKELY(!(fdi & (VL_ULL(1) << 31)) || idx >= s_s.m_fdps.size())) return NULL;
return s_s.m_fdps[idx];
}
};
+29
View File
@@ -23,6 +23,7 @@
#define _VERILATED_SAVE_C_H_ 1
#include "verilatedos.h"
#include "verilated_heavy.h"
#include <string>
@@ -247,5 +248,33 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& r
rhs.resize(len);
return os.read((void*)rhs.data(), len);
}
template <class T_Key, class T_Value>
VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Value>& rhs) {
os << rhs.atDefault();
vluint32_t len = rhs.size();
os << len;
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin();
it != rhs.end(); ++it) {
T_Key index = it->first; // Copy to get around const_iterator
T_Value value = it->second;
os << index << value;
}
return os;
}
template <class T_Key, class T_Value>
VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VlAssocArray<T_Key, T_Value>& rhs) {
os >> rhs.atDefault();
vluint32_t len = 0;
os >> len;
rhs.clear();
for (vluint32_t i = 0; i < len; ++i) {
T_Key index;
T_Value value;
os >> index;
os >> value;
rhs.at(index) = value;
}
return os;
}
#endif // Guard
+14 -4
View File
@@ -708,9 +708,12 @@ void VerilatedVcd::flush_all() VL_MT_UNSAFE_ONE {
//======================================================================
#ifdef VERILATED_VCD_TEST
#include <iostream>
vluint32_t v1, v2, s1, s2[3];
vluint32_t tri96[3];
vluint32_t tri96__tri[3];
vluint64_t quad96[2];
vluint8_t ch;
vluint64_t timestamp = 1;
double doub = 0;
@@ -734,6 +737,8 @@ void vcdInit(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
// Note need to add 6 for next code.
vcdp->declDouble (0x1c, "doub",-1);
// Note need to add 2 for next code.
vcdp->declArray(0x1e, "q2",-1, 95, 0);
// Note need to add 4 for next code.
}
void vcdFull(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
@@ -746,6 +751,7 @@ void vcdFull(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
vcdp->fullTriBus (0x12, tri96[0]&0x1f, tri96__tri[0]&0x1f, 5);
vcdp->fullTriArray(0x16, tri96, tri96__tri, 96);
vcdp->fullDouble(0x1c, doub);
vcdp->fullArray(0x1e, &quad96[0], 96);
}
void vcdChange(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
@@ -758,15 +764,17 @@ void vcdChange(VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
vcdp->chgTriBus (0x12, tri96[0]&0x1f, tri96__tri[0]&0x1f, 5);
vcdp->chgTriArray (0x16, tri96, tri96__tri, 96);
vcdp->chgDouble (0x1c, doub);
vcdp->chgArray(0x1e, &quad96[0], 96);
}
main() {
cout<<"test: O_LARGEFILE="<<O_LARGEFILE<<endl;
std::cout << "test: O_LARGEFILE=" << O_LARGEFILE << std::endl;
v1 = v2 = s1 = 0;
s2[0] = s2[1] = s2[2] = 0;
tri96[2] = tri96[1] = tri96[0] = 0;
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0;
quad96[1] = quad96[0] = 0;
ch = 0;
doub = 0;
{
@@ -778,11 +786,13 @@ main() {
v1 = 0xfff;
tri96[2] = 4; tri96[1] = 2; tri96[0] = 1;
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0; // Still tri
quad96[1] = 0xffffffff ; quad96[0] = 0;
doub = 1.5;
vcdp->dump(timestamp++);
v2 = 0x1;
s2[1] = 2;
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = 0; // enable w/o data change
quad96[1] = 0 ; quad96[0] = ~0;
doub = -1.66e13;
vcdp->dump(timestamp++);
ch = 2;
@@ -791,8 +801,8 @@ main() {
vcdp->dump(timestamp++);
vcdp->dump(timestamp++);
# ifdef VERILATED_VCD_TEST_64BIT
vluint64_t bytesPerDump = 15ULL;
for (vluint64_t i=0; i<((1ULL<<32) / bytesPerDump); i++) {
vluint64_t bytesPerDump = VL_ULL(15);
for (vluint64_t i = 0; i < ((VL_ULL(1) << 32) / bytesPerDump); i++) {
v1 = i;
vcdp->dump(timestamp++);
}
@@ -804,5 +814,5 @@ main() {
//********************************************************************
// Local Variables:
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && c++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && c++ -DVERILATED_VCD_TEST ../include/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
// End:
+30 -11
View File
@@ -231,20 +231,31 @@ public:
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval;
*m_writep++='b';
for (int bit=bits-1; bit>=0; --bit) {
*m_writep++=((newval&(1ULL<<bit))?'1':'0');
*m_writep++ = ((newval & (VL_ULL(1) << bit)) ? '1' : '0');
}
*m_writep++=' '; printCode(code); *m_writep++='\n';
bufferCheck();
}
void fullArray(vluint32_t code, const vluint32_t* newval, int bits) {
for (int word=0; word<(((bits-1)/32)+1); ++word) {
m_sigs_oldvalp[code+word] = newval[word];
for (int word = 0; word < (((bits - 1) / 32) + 1); ++word) {
m_sigs_oldvalp[code + word] = newval[word];
}
*m_writep++='b';
for (int bit=bits-1; bit>=0; --bit) {
*m_writep++=((newval[(bit/32)]&(1L<<(bit&0x1f)))?'1':'0');
*m_writep++ = 'b';
for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = ((newval[(bit / 32)] & (1L << (bit & 0x1f))) ? '1' : '0');
}
*m_writep++=' '; printCode(code); *m_writep++='\n';
*m_writep ++= ' '; printCode(code); *m_writep ++= '\n';
bufferCheck();
}
void fullArray(vluint32_t code, const vluint64_t* newval, int bits) {
for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) {
m_sigs_oldvalp[code + word] = newval[word];
}
*m_writep ++= 'b';
for (int bit = bits - 1; bit >= 0; --bit) {
*m_writep++ = ((newval[(bit / 64)] & (VL_ULL(1) << (bit & 0x3f))) ? '1' : '0');
}
*m_writep ++= ' '; printCode(code); *m_writep ++= '\n';
bufferCheck();
}
void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
@@ -272,8 +283,8 @@ public:
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code+1]))) = newtri;
*m_writep++='b';
for (int bit=bits-1; bit>=0; --bit) {
*m_writep++ = "01zz"[((newval >> bit)&1ULL)
| (((newtri >> bit)&1ULL)<<1ULL)];
*m_writep++ = "01zz"[((newval >> bit) & VL_ULL(1))
| (((newtri >> bit) & VL_ULL(1)) << VL_ULL(1))];
}
*m_writep++=' '; printCode(code); *m_writep++='\n';
bufferCheck();
@@ -337,7 +348,7 @@ public:
inline void chgQuad(vluint32_t code, const vluint64_t newval, int bits) {
vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) ^ newval;
if (VL_UNLIKELY(diff)) {
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
if (VL_UNLIKELY(bits == 64 || (diff & ((VL_ULL(1) << bits) - 1)))) {
fullQuad(code, newval, bits);
}
}
@@ -350,6 +361,14 @@ public:
}
}
}
inline void chgArray(vluint32_t code, const vluint64_t* newval, int bits) {
for (int word = 0; word < (((bits - 1) / 64) + 1); ++word) {
if (VL_UNLIKELY(m_sigs_oldvalp[code + word] ^ newval[word])) {
fullArray(code, newval, bits);
return;
}
}
}
inline void chgTriBit(vluint32_t code, const vluint32_t newval,
const vluint32_t newtri) {
vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval)
@@ -377,7 +396,7 @@ public:
vluint64_t diff = ( ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) ^ newval)
| ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code+1]))) ^ newtri));
if (VL_UNLIKELY(diff)) {
if (VL_UNLIKELY(bits == 64 || (diff & ((1ULL << bits) - 1)))) {
if (VL_UNLIKELY(bits == 64 || (diff & ((VL_ULL(1) << bits) - 1)))) {
fullTriQuad(code, newval, newtri, bits);
}
}
+3 -1
View File
@@ -416,7 +416,9 @@ public:
for (VpioTimedCbs::iterator it=s_s.m_timedCbs.begin(); it!=s_s.m_timedCbs.end(); ) {
if (VL_UNLIKELY(it->first <= time)) {
VerilatedVpioCb* vop = it->second;
++it; // iterator may be deleted by callback
VpioTimedCbs::iterator last_it = it;
++it; // Timed callbacks are one-shot
s_s.m_timedCbs.erase(last_it);
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n", vop););
(vop->cb_rtnp()) (vop->cb_datap());
}
+1 -1
View File
@@ -94,7 +94,7 @@ private:
AstDisplayType::DT_ERROR, message, NULL, NULL);
AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop(nodep->fileline()));
bodysp->addNext(new AstStop(nodep->fileline(), true));
return bodysp;
}
+13
View File
@@ -94,6 +94,15 @@ void AstNode::init() {
m_user5Cnt = 0;
}
AstNode* AstNode::abovep() const {
// m_headtailp only valid at beginning or end of list
// Avoid supporting at other locations as would require walking
// list which is likely to cause performance issues.
UASSERT_OBJ(!m_nextp || firstAbovep(), this, "abovep() not allowed when in midlist");
const AstNode* firstp = firstAbovep() ? this : m_headtailp;
return firstp->backp();
}
string AstNode::encodeName(const string& namein) {
// Encode signal name raw from parser, then not called again on same signal
string out;
@@ -1199,6 +1208,10 @@ AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
return v3Global.rootp()->typeTablep()
->findInsertSameDType(nodep);
}
AstNodeDType* AstNode::findVoidDType() const {
return v3Global.rootp()->typeTablep()
->findVoidDType(fileline());
}
//######################################################################
// AstNVisitor
+5
View File
@@ -1243,6 +1243,7 @@ public:
const char* typeName() const { return type().ascii(); } // See also prettyTypeName
AstNode* nextp() const { return m_nextp; }
AstNode* backp() const { return m_backp; }
AstNode* abovep() const; // Parent node above, only when no nextp() as otherwise slow
AstNode* op1p() const { return m_op1p; }
AstNode* op2p() const { return m_op2p; }
AstNode* op3p() const { return m_op3p; }
@@ -1421,6 +1422,7 @@ public:
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
void dtypeSetVoid() { dtypep(findVoidDType()); }
// Data type locators
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
@@ -1429,6 +1431,7 @@ public:
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
AstNodeDType* findVoidDType() const;
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
AstNodeDType* findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const;
@@ -1914,6 +1917,8 @@ public:
virtual bool maybePointedTo() const { return true; }
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
virtual AstNodeDType* virtRefDType2p() const { return NULL; } // Iff has a non-null second dtypep, as generic node function
virtual void virtRefDType2p(AstNodeDType* nodep) { } // Iff has second dtype, set as generic node function
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
virtual AstNodeDType* subDTypep() const { return NULL; } // Iff has a non-null subDTypep(), as generic node function
virtual bool isFourstate() const;
+138 -58
View File
@@ -226,72 +226,131 @@ string AstVar::verilogKwd() const {
}
}
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
class AstVar::VlArgTypeRecursed {
public:
string m_oref; // To output, reference part before name, "&"
string m_osuffix; // To output, suffixed after name, "[3]"
string m_oprefix; // To output, prefixed before name, "Foo_t"
void clear() {
m_oref.clear();
m_osuffix.clear();
m_oprefix.clear();
}
string refParen(const string& name) {
return m_oref.empty() ? name : "("+m_oref+" "+name+")";
}
};
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc) const {
UASSERT_OBJ(!forReturn, this,
"Internal data is never passed as return, but as first argument");
string otype;
AstBasicDType* bdtypep = basicp();
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
otype += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
otype += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "float";
} else if (strtype) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "std::string";
} else if (widthMin() <= 8) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "CData";
} else if (widthMin() <= 16) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "SData";
} else if (widthMin() <= VL_WORDSIZE) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "IData";
} else if (isQuad()) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "QData";
} else if (isWide()) {
if (forFunc && isReadOnly()) otype += "const ";
otype += "WData"; // []'s added later
}
string ostatic;
if (isStatic() && namespc.empty()) ostatic = "static ";
VlArgTypeRecursed info = vlArgTypeRecurse(forFunc, dtypep(), false);
bool mayparen = false; // Need paren, to handle building "(& name)[2]"
string oname;
if (isDpiOpenArray()
|| (isWide() && !strtype)
|| (forFunc && (isWritable()
|| direction()==VDirection::REF
|| direction()==VDirection::CONSTREF
|| (strtype && isNonOutput())))) {
oname += "&";
mayparen = true;
if (named) {
oname += " ";
if (!namespc.empty()) oname += namespc+"::";
oname += VIdProtect::protectIf(name(), protect());
}
if (named) oname += " "+VIdProtect::protectIf(name(), protect());
return ostatic + info.m_oprefix + info.refParen(oname) + info.m_osuffix;
}
string oarray;
if (isDpiOpenArray() || direction().isRefOrConstRef()) {
for (AstNodeDType* dtp=dtypep(); dtp; ) {
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstUnpackArrayDType* adtypep = VN_CAST(dtp, UnpackArrayDType)) {
if (mayparen) { oname = " ("+oname+")"; mayparen = false; }
oarray += "["+cvtToStr(adtypep->declRange().elements())+"]";
dtp = adtypep->subDTypep();
} else break;
AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDType* dtypep,
bool arrayed) const {
dtypep = dtypep->skipRefp();
if (const AstAssocArrayDType* adtypep = VN_CAST_CONST(dtypep, AssocArrayDType)) {
VlArgTypeRecursed key = vlArgTypeRecurse(forFunc, adtypep->keyDTypep(), true);
VlArgTypeRecursed sub = vlArgTypeRecurse(forFunc, adtypep->subDTypep(), true);
string out = "VlAssocArray<";
out += key.m_oprefix;
if (!key.m_osuffix.empty() || !key.m_oref.empty()) {
out += " " + key.m_osuffix + key.m_oref;
}
out += ", ";
out += sub.m_oprefix;
if (!sub.m_osuffix.empty() || !sub.m_oref.empty()) {
out += " " + sub.m_osuffix + sub.m_oref;
}
out += "> ";
VlArgTypeRecursed info;
info.m_oprefix = out;
return info;
} else if (const AstQueueDType* adtypep = VN_CAST_CONST(dtypep, QueueDType)) {
VlArgTypeRecursed sub = vlArgTypeRecurse(forFunc, adtypep->subDTypep(), true);
VlArgTypeRecursed info;
string out = "VlQueue<" + sub.m_oprefix;
if (!sub.m_osuffix.empty() || !sub.m_oref.empty()) {
out += " " + sub.m_osuffix + sub.m_oref;
}
out += "> ";
info.m_oprefix = out;
return info;
} else if (const AstUnpackArrayDType* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) {
VlArgTypeRecursed info = vlArgTypeRecurse(forFunc, adtypep->subDTypep(), arrayed);
info.m_osuffix = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + info.m_osuffix;
return info;
} else if (const AstBasicDType* bdtypep = dtypep->basicp()) {
string otype;
string oarray;
bool strtype = bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::STRING;
string bitvec;
if (bdtypep && !bdtypep->isOpaque() && !v3Global.opt.protectIds()) {
// We don't print msb()/lsb() as multidim packed would require recursion,
// and may confuse users as C++ data is stored always with bit 0 used
bitvec += "/*"+cvtToStr(dtypep->width()-1)+":0*/";
}
if ((forFunc && isReadOnly())
|| bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR
|| bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) otype += "const ";
if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) {
otype += "char*";
} else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) {
otype += "VerilatedScope*";
} else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::DOUBLE) {
otype += "double";
} else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::FLOAT) {
otype += "float";
} else if (strtype) {
otype += "std::string";
} else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width
otype += "CData"+bitvec;
} else if (dtypep->widthMin() <= 16) {
otype += "SData"+bitvec;
} else if (dtypep->widthMin() <= VL_WORDSIZE) {
otype += "IData"+bitvec;
} else if (dtypep->isQuad()) {
otype += "QData"+bitvec;
} else if (dtypep->isWide()) {
if (arrayed) {
otype += "VlWide<"+cvtToStr(dtypep->widthWords())+"> ";
} else {
otype += "WData"+bitvec; // []'s added later
oarray += "["+cvtToStr(dtypep->widthWords())+"]";
}
}
string oref;
if (isDpiOpenArray()
|| (forFunc && (isWritable()
|| direction() == VDirection::REF
|| direction() == VDirection::CONSTREF
|| (strtype && isNonOutput())))) {
oref = "&";
}
VlArgTypeRecursed info;
info.m_oprefix = otype;
info.m_osuffix = oarray;
info.m_oref = oref;
//UINFO(9, "vlArgRec "<<"oprefix="<<info.m_oprefix<<" osuffix="<<info.m_osuffix
// <<" oref="<<info.m_oref<<" "<<dtypep);
return info;
} else {
v3fatalSrc("Unknown data type in var type emitter: "<<dtypep->prettyName());
}
if (isWide() && !strtype) {
if (mayparen) { oname = " ("+oname+")"; mayparen = false; }
oarray += "["+cvtToStr(widthWords())+"]";
}
if (mayparen) { }
return otype+oname+oarray;
}
string AstVar::vlEnumType() const {
@@ -712,6 +771,15 @@ void AstTypeTable::repairCache() {
}
}
AstVoidDType* AstTypeTable::findVoidDType(FileLine* fl) {
if (VL_UNLIKELY(!m_voidp)) {
AstVoidDType* newp = new AstVoidDType(fl);
addTypesp(newp);
m_voidp = newp;
}
return m_voidp;
}
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd) {
if (m_basicps[kwd]) return m_basicps[kwd];
//
@@ -1047,10 +1115,22 @@ void AstTypeTable::dump(std::ostream& str) const {
}
// Note get newline from caller too.
}
void AstAssocArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"[assoc-"<<(void*)keyDTypep()<<"]";
}
void AstQueueDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"[queue]";
}
void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"[]";
}
void AstVoidDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"void";
}
void AstVarScope::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isCircular()) str<<" [CIRC]";
+319 -10
View File
@@ -184,6 +184,35 @@ public:
virtual bool same(const AstNode* samep) const { return true; }
};
class AstAssocRange : public AstNodeRange {
// Associative array range specification
// Only for early parsing - becomes AstAssocDType
public:
explicit AstAssocRange(FileLine* fl, AstNodeDType* dtp)
: AstNodeRange(fl) {
setOp1p(dtp);
}
ASTNODE_NODE_FUNCS(AssocRange)
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNodeDType* keyDTypep() const { return VN_CAST(op1p(), NodeDType); }
};
class AstQueueRange : public AstNodeRange {
// Queue range specification
// Only for early parsing - becomes AstQueueDType
public:
explicit AstQueueRange(FileLine* fl)
: AstNodeRange(fl) {}
ASTNODE_NODE_FUNCS(QueueRange)
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
};
class AstUnsizedRange : public AstNodeRange {
// Unsized range specification, for open arrays
public:
@@ -333,6 +362,65 @@ public:
void name(const string& flag) { m_name = flag; }
};
class AstAssocArrayDType : public AstNodeDType {
// Associative array data type, ie "[some_dtype]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: DTYPE (the key, which remains here as a pointer)
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
AstNodeDType* m_keyDTypep; // Keys of this type (after widthing)
public:
AstAssocArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeDType* keyDtp)
: AstNodeDType(fl) {
childDTypep(dtp); // Only for parser
keyChildDTypep(keyDtp); // Only for parser
refDTypep(NULL);
keyDTypep(NULL);
dtypep(NULL); // V3Width will resolve
}
ASTNODE_NODE_FUNCS(AssocArrayDType)
virtual const char* broken() const {
BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep())));
BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists())
|| (!m_keyDTypep && childDTypep())));
return NULL; }
virtual void cloneRelink() {
if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); }
if (m_keyDTypep && m_keyDTypep->clonep()) { m_keyDTypep = m_keyDTypep->clonep(); } }
virtual bool same(const AstNode* samep) const {
const AstAssocArrayDType* asamep = static_cast<const AstAssocArrayDType*>(samep);
return (subDTypep() == asamep->subDTypep()
&& keyDTypep() == asamep->keyDTypep()); }
virtual bool similarDType(AstNodeDType* samep) const {
const AstAssocArrayDType* asamep = static_cast<const AstAssocArrayDType*>(samep);
return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
}
virtual void dumpSmall(std::ostream& str) const;
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
virtual AstNodeDType* virtRefDType2p() const { return m_keyDTypep; }
virtual void virtRefDType2p(AstNodeDType* nodep) { keyDTypep(nodep); }
//
AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); }
void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; }
AstNodeDType* keyChildDTypep() const { return VN_CAST(op2p(), NodeDType); } // op1 = Range of variable
void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); }
// METHODS
virtual AstBasicDType* basicp() const { return NULL; } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
};
class AstPackArrayDType : public AstNodeArrayDType {
// Packed array data type, ie "some_dtype [2:0] var_name"
// Children: DTYPE (moved to refDTypep() in V3Width)
@@ -642,6 +730,50 @@ public:
bool isModport() { return !m_modportName.empty(); }
};
class AstQueueDType : public AstNodeDType {
// Queue array data type, ie "[ $ ]"
// Children: DTYPE (moved to refDTypep() in V3Width)
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
public:
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
: AstNodeDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(NULL);
dtypep(NULL); // V3Width will resolve
}
ASTNODE_NODE_FUNCS(QueueDType)
virtual const char* broken() const {
BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep())));
return NULL; }
virtual void cloneRelink() {
if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } }
virtual bool same(const AstNode* samep) const {
const AstQueueDType* asamep = static_cast<const AstQueueDType*>(samep);
return (subDTypep() == asamep->subDTypep()); }
virtual bool similarDType(AstNodeDType* samep) const {
const AstQueueDType* asamep = static_cast<const AstQueueDType*>(samep);
return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
}
virtual void dumpSmall(std::ostream& str) const;
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
// METHODS
virtual AstBasicDType* basicp() const { return NULL; }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
};
class AstRefDType : public AstNodeDType {
private:
AstNodeDType* m_refDTypep; // data type pointed to, BELOW the AstTypedef
@@ -774,6 +906,28 @@ public:
void lsb(int lsb) { m_lsb = lsb; }
};
class AstVoidDType : public AstNodeDType {
// For e.g. a function returning void
public:
AstVoidDType(FileLine* fl)
: AstNodeDType(fl) { dtypep(this); }
ASTNODE_NODE_FUNCS(VoidDType)
virtual void dumpSmall(std::ostream& str) const;
virtual bool hasDType() const { return true; }
virtual bool maybePointedTo() const { return true; }
virtual AstNodeDType* subDTypep() const { return NULL; }
virtual AstNodeDType* virtRefDTypep() const { return NULL; }
virtual void virtRefDTypep(AstNodeDType* nodep) { }
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
virtual AstBasicDType* basicp() const { return NULL; }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return 1; }
virtual int widthTotalBytes() const { return 1; }
virtual V3Hash sameHash() const { return V3Hash(); }
};
class AstEnumItem : public AstNode {
private:
string m_name;
@@ -927,6 +1081,40 @@ public:
static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences?
};
class AstAssocSel : public AstNodeSel {
// Parents: math|stmt
// Children: varref|arraysel, math
private:
void init(AstNode* fromp) {
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) {
// Strip off array to find what array references
dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep());
}
}
public:
AstAssocSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
: AstNodeSel(fl, fromp, bitp) {
init(fromp);
}
ASTNODE_NODE_FUNCS(AssocSel)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) {
return new AstAssocSel(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
V3ERROR_NA; }
virtual string emitVerilog() { return "%k(%l%f[%r])"; }
virtual string emitC() { return "%li%k[%ri]"; }
virtual bool cleanOut() const { return true; }
virtual bool cleanLhs() const { return false; }
virtual bool cleanRhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
virtual bool sizeMattersRhs() const { return false; }
virtual bool isGateOptimizable() const { return true; } // esp for V3Const::ifSameAssign
virtual bool isPredictOptimizable() const { return false; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
virtual int instrCount() const { return widthInstrs(); }
};
class AstWordSel : public AstNodeSel {
// Select a single word from a multi-word wide value
public:
@@ -1114,25 +1302,25 @@ public:
void fromp(AstNode* nodep) { setOp1p(nodep); }
};
class AstMethodSel : public AstNode {
class AstMethodCall : public AstNode {
// A reference to a member task (or function)
// We do not support generic member calls yet, so this is only enough to
// make built-in methods work
private:
string m_name; // Name of variable
string m_name; // Name of method
public:
AstMethodSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, AstNode* pinsp)
AstMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, AstNode* pinsp)
: AstNode(fl), m_name(name) {
setOp1p(fromp);
dtypep(NULL); // V3Width will resolve
addNOp2p(pinsp);
}
AstMethodSel(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
AstMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
: AstNode(fl), m_name(name) {
setOp1p(fromp);
addNOp2p(pinsp);
}
ASTNODE_NODE_FUNCS(MethodSel)
ASTNODE_NODE_FUNCS(MethodCall)
virtual string name() const { return m_name; } // * = Var name
virtual void name(const string& name) { m_name = name; }
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
@@ -1141,6 +1329,45 @@ public:
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
};
class AstCMethodCall : public AstNodeStmt {
// A reference to a "C" hardocded member task (or function)
// PARENTS: stmt/math
// Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal.
private:
string m_name; // Name of method
bool m_pure; // Pure optimizable
bool m_statement; // Is a statement (AstNodeMath-like) versus AstNodeStmt-like
public:
AstCMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
AstNode* pinsp)
: AstNodeStmt(fl), m_name(name), m_pure(false), m_statement(false) {
setOp1p(fromp);
dtypep(NULL); // V3Width will resolve
addNOp2p(pinsp);
}
AstCMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
: AstNodeStmt(fl), m_name(name), m_statement(false) {
setOp1p(fromp);
addNOp2p(pinsp);
}
ASTNODE_NODE_FUNCS(CMethodCall)
virtual string name() const { return m_name; } // * = Var name
virtual bool hasDType() const { return true; }
virtual void name(const string& name) { m_name = name; }
virtual V3Hash sameHash() const { return V3Hash(m_name); }
virtual bool same(const AstNode* samep) const {
const AstCMethodCall* asamep = static_cast<const AstCMethodCall*>(samep);
return (m_name == asamep->m_name); }
virtual bool isStatement() const { return m_statement; }
virtual bool isPure() const { return m_pure; }
void pure(bool flag) { m_pure = flag; }
void makeStatement() { m_statement = true; dtypeSetVoid(); }
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
void fromp(AstNode* nodep) { setOp1p(nodep); }
AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
};
class AstVar : public AstNode {
// A variable (in/out/wire/reg/param) inside a module
private:
@@ -1271,7 +1498,7 @@ public:
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
// Return Verilator internal type for argument: CData, SData, IData, WData
string vlArgType(bool named, bool forReturn, bool forFunc) const;
string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc="") const;
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
string vlPropInit() const; // Return VerilatorVarProps initializer
@@ -1410,6 +1637,10 @@ public:
void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); }
const MTaskIdSet& mtaskIds() const { return m_mtaskIds; }
string mtasksString() const;
private:
class VlArgTypeRecursed;
VlArgTypeRecursed vlArgTypeRecurse(bool forFunc, const AstNodeDType* dtypep,
bool arrayed) const;
};
class AstDefParam : public AstNode {
@@ -1829,6 +2060,17 @@ public:
AstNode* varsp() const { return op1p(); } // op1 = List of Vars
};
class AstIntfRef : public AstNode {
// An interface reference
private:
string m_name; // Name of the reference
public:
AstIntfRef(FileLine* fl, const string& name)
: AstNode(fl), m_name(name) { }
virtual string name() const { return m_name; }
ASTNODE_NODE_FUNCS(IntfRef)
};
class AstCell : public AstNode {
// A instantiation cell or interface call (don't know which until link)
private:
@@ -1865,9 +2107,11 @@ public:
AstPin* pinsp() const { return VN_CAST(op1p(), Pin); } // op1 = List of cell ports
AstPin* paramsp() const { return VN_CAST(op2p(), Pin); } // op2 = List of parameter #(##) values
AstRange* rangep() const { return VN_CAST(op3p(), Range); } // op3 = Range of arrayed instants (NULL=not ranged)
AstIntfRef* intfRefp() const { return VN_CAST(op4p(), IntfRef); } // op4 = List of interface references
AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated
void addPinsp(AstPin* nodep) { addOp1p(nodep); }
void addParamsp(AstPin* nodep) { addOp2p(nodep); }
void addIntfRefp(AstIntfRef* nodep) { addOp4p(nodep); }
void modp(AstNodeModule* nodep) { m_modp = nodep; }
bool hasIfaceVar() const { return m_hasIfaceVar; }
void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; }
@@ -2073,6 +2317,16 @@ public:
AstNode* rhsp() const { return op2p(); }
};
class AstUnbounded : public AstNode {
// A $ in the parser, used for unbounded and queues
public:
AstUnbounded(FileLine* fl)
: AstNode(fl) {}
ASTNODE_NODE_FUNCS(Unbounded)
virtual string emitVerilog() { return "$"; }
virtual string emitC() { V3ERROR_NA; return ""; }
};
//######################################################################
class AstTask : public AstNodeFTask {
@@ -3580,8 +3834,9 @@ public:
};
class AstStop : public AstNodeStmt {
bool m_maybe; // Maybe stop, maybe not based on error count
public:
explicit AstStop(FileLine* fl)
explicit AstStop(FileLine* fl, bool maybe)
: AstNodeStmt(fl) {}
ASTNODE_NODE_FUNCS(Stop)
virtual bool isGateOptimizable() const { return false; }
@@ -3625,13 +3880,16 @@ private:
AstVarType m_varType; // Type of variable (for localparam vs. param)
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
VDirection m_declDirection; // Declared direction input/output etc
bool m_isScoped; // Uses run-time scope (for interfaces)
public:
AstTraceDecl(FileLine* fl, const string& showname,
AstVar* varp, // For input/output state etc
AstNode* valuep,
const VNumRange& bitRange, const VNumRange& arrayRange)
const VNumRange& bitRange, const VNumRange& arrayRange,
bool isScoped)
: AstNodeStmt(fl)
, m_showname(showname), m_bitRange(bitRange), m_arrayRange(arrayRange) {
, m_showname(showname), m_bitRange(bitRange), m_arrayRange(arrayRange)
, m_isScoped(isScoped) {
dtypeFrom(valuep);
m_code = 0;
m_codeInc = ((arrayRange.ranged() ? arrayRange.elements() : 1)
@@ -3656,6 +3914,7 @@ public:
AstVarType varType() const { return m_varType; }
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
VDirection declDirection() const { return m_declDirection; }
bool isScoped() const { return m_isScoped; }
};
class AstTraceInc : public AstNodeStmt {
@@ -4331,6 +4590,28 @@ public:
AstNode* filep() const { return lhsp(); }
};
class AstFUngetC : public AstNodeBiop {
public:
AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FUngetC)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) {
return new AstFUngetC(this->fileline(), lhsp, rhsp); }
virtual string emitVerilog() { return "%f$ungetc(%r, %l)"; }
// Non-existent filehandle returns EOF
virtual string emitC() { return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
virtual bool sizeMattersRhs() const { return false; }
virtual int instrCount() const { return widthInstrs() * 64; }
virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering
AstNode* filep() const { return lhsp(); }
AstNode* charp() const { return rhsp(); }
};
class AstNodeSystemUniop : public AstNodeUniop {
public:
AstNodeSystemUniop(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
@@ -4503,6 +4784,32 @@ public:
virtual string emitVerilog() { return "%f$atanh(%l)"; }
virtual string emitC() { return "atanh(%li)"; }
};
class AstToLowerN : public AstNodeUniop {
// string.tolower()
public:
AstToLowerN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetString(); }
ASTNODE_NODE_FUNCS(ToLowerN)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToLowerN(lhs); }
virtual string emitVerilog() { return "%l.tolower()"; }
virtual string emitC() { return "VL_TOLOWER_NN(%li)"; }
virtual bool cleanOut() const { return true; }
virtual bool cleanLhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
};
class AstToUpperN : public AstNodeUniop {
// string.toupper()
public:
AstToUpperN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetString(); }
ASTNODE_NODE_FUNCS(ToUpperN)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToUpperN(lhs); }
virtual string emitVerilog() { return "%l.toupper()"; }
virtual string emitC() { return "VL_TOUPPER_NN(%li)"; }
virtual bool cleanOut() const { return true; }
virtual bool cleanLhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
};
//======================================================================
// Binary ops
@@ -6281,17 +6588,19 @@ public:
class AstTypeTable : public AstNode {
// Container for hash of standard data types
// Children: NODEDTYPEs
AstVoidDType* m_voidp;
AstBasicDType* m_basicps[AstBasicDTypeKwd::_ENUM_MAX];
//
typedef std::map<VBasicTypeKey,AstBasicDType*> DetailedMap;
DetailedMap m_detailedMap;
public:
explicit AstTypeTable(FileLine* fl) : AstNode(fl) {
explicit AstTypeTable(FileLine* fl) : AstNode(fl), m_voidp(NULL) {
for (int i=0; i<AstBasicDTypeKwd::_ENUM_MAX; ++i) m_basicps[i] = NULL;
}
ASTNODE_NODE_FUNCS(TypeTable)
AstNodeDType* typesp() const { return VN_CAST(op1p(), NodeDType);} // op1 = List of dtypes
void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); }
AstVoidDType* findVoidDType(FileLine* fl);
AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd);
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
int width, int widthMin, AstNumeric numeric);
+13 -1
View File
@@ -87,7 +87,10 @@ private:
void computeCppWidth(AstNode* nodep) {
if (!nodep->user2() && nodep->hasDType()) {
if (VN_IS(nodep, Var) || VN_IS(nodep, NodeDType) // Don't want to change variable widths!
|| VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) { // Or arrays
|| VN_IS(nodep->dtypep()->skipRefp(), AssocArrayDType) // Or arrays
|| VN_IS(nodep->dtypep()->skipRefp(), QueueDType)
|| VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)
|| VN_IS(nodep->dtypep()->skipRefp(), VoidDType)) {
} else {
setCppWidth(nodep);
}
@@ -276,6 +279,15 @@ private:
insureCleanAndNext(nodep->argsp());
setClean(nodep, true);
}
virtual void visit(AstCMethodCall* nodep) {
iterateChildren(nodep);
insureCleanAndNext(nodep->pinsp());
setClean(nodep, true);
}
virtual void visit(AstIntfRef* nodep) {
iterateChildren(nodep);
setClean(nodep, true); // generates a string, so not relevant
}
//--------------------
// Default: Just iterate
+14 -1
View File
@@ -2180,7 +2180,20 @@ private:
virtual void visit(AstJumpGo* nodep) {
iterateChildren(nodep);
m_hasJumpGo = true;
if (m_doExpensive) { nodep->labelp()->user4(true); }
if (m_doExpensive) {
// If last statement in a jump label we have JumpLabel(...., JumpGo)
// Often caused by "return" in a Verilog function. The Go is pointless, remove.
if (!nodep->nextp()) {
if (AstJumpLabel* aboveLabelp = VN_CAST(nodep->abovep(), JumpLabel)) {
if (aboveLabelp == nodep->labelp()) {
UINFO(4, "JUMPGO => last remove "<<nodep<<endl);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
return;
}
}
}
nodep->labelp()->user4(true);
}
}
virtual void visit(AstJumpLabel* nodep) {
+3
View File
@@ -127,6 +127,9 @@ private:
if (AstNode* subnodep = nodep->virtRefDTypep()) {
subnodep->user1Inc();
}
if (AstNode* subnodep = nodep->virtRefDType2p()) {
subnodep->user1Inc();
}
}
// VISITORS
+188 -163
View File
@@ -51,6 +51,7 @@ private:
bool m_suppressSemi;
AstVarRef* m_wideTempRefp; // Variable that _WW macros should be setting
VarVec m_ctorVarsVec; // All variables in constructor order
int m_labelNum; // Next label number
int m_splitSize; // # of cfunc nodes placed into output file
int m_splitFilenum; // File number being created, 0 = primary
@@ -110,7 +111,9 @@ public:
string newVarCmt = varp->mtasksString();
if (*curVarCmtp != newVarCmt) {
*curVarCmtp = newVarCmt;
puts("// Begin mtask footprint "+*curVarCmtp+"\n");
if (v3Global.opt.threads()) {
puts("// Begin mtask footprint "+*curVarCmtp+"\n");
}
}
}
void emitTypedefs(AstNode* firstp) {
@@ -189,7 +192,9 @@ public:
} else if (nodep->isWide()
&& VN_IS(nodep->lhsp(), VarRef)
&& !VN_IS(nodep->rhsp(), CMath)
&& !VN_IS(nodep->rhsp(), CMethodCall)
&& !VN_IS(nodep->rhsp(), VarRef)
&& !VN_IS(nodep->rhsp(), AssocSel)
&& !VN_IS(nodep->rhsp(), ArraySel)) {
// Wide functions assign into the array directly, don't need separate assign statement
m_wideTempRefp = VN_CAST(nodep->lhsp(), VarRef);
@@ -213,6 +218,27 @@ public:
}
virtual void visit(AstAlwaysPublic*) {
}
virtual void visit(AstAssocSel* nodep) {
iterateAndNextNull(nodep->fromp());
putbs(".at(");
AstAssocArrayDType* adtypep = VN_CAST(nodep->fromp()->dtypep(), AssocArrayDType);
UASSERT_OBJ(adtypep, nodep, "Associative select on non-associative type");
if (adtypep->keyDTypep()->isWide()) {
// Container class must take non-C-array (pointer) argument, so convert
putbs("VL_CVT_W_A(");
iterateAndNextNull(nodep->bitp());
puts(", ");
iterateAndNextNull(nodep->fromp());
putbs(".atDefault()"); // Not accessed; only to get the proper type of values
puts(")");
} else {
iterateAndNextNull(nodep->bitp());
}
puts(")");
if (nodep->dtypep()->isWide()) {
puts(".data()"); // Access returned std::array as C array
}
}
virtual void visit(AstCCall* nodep) {
puts(nodep->hiernameProtect());
puts(nodep->funcp()->nameProtect());
@@ -231,6 +257,27 @@ public:
puts(");\n");
}
}
virtual void visit(AstCMethodCall* nodep) {
iterate(nodep->fromp());
puts(".");
puts(nodep->nameProtect());
puts("(");
bool comma = false;
for (AstNode* subnodep = nodep->pinsp(); subnodep; subnodep = subnodep->nextp()) {
if (comma) puts(", ");
iterate(subnodep);
comma = true;
}
puts(")");
// Some are statements some are math.
if (nodep->isStatement()) puts(";\n");
UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType),
nodep, "Statement of non-void data type");
}
virtual void visit(AstIntfRef* nodep) {
putsQuoted(VIdProtect::protectWordsIf(AstNode::vcdName(nodep->name()),
nodep->protect()));
}
virtual void visit(AstNodeCase* nodep) {
// In V3Case...
nodep->v3fatalSrc("Case statements should have been reduced out");
@@ -495,7 +542,8 @@ public:
puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n");
}
virtual void visit(AstJumpLabel* nodep) {
puts("{\n");
nodep->labelNum(++m_labelNum);
puts("{\n"); // Make it visually obvious label jumps outside these
iterateAndNextNull(nodep->stmtsp());
puts("}\n");
puts("__Vlabel"+cvtToStr(nodep->labelNum())+": ;\n");
@@ -530,7 +578,8 @@ public:
putsQuoted(protect(nodep->fileline()->filename()));
puts(", ");
puts(cvtToStr(nodep->fileline()->lineno()));
puts(", \"\");\n");
puts(", \"\"");
puts(");\n");
}
virtual void visit(AstFinish* nodep) {
puts("VL_FINISH_MT(");
@@ -871,6 +920,7 @@ public:
void init() {
m_suppressSemi = false;
m_wideTempRefp = NULL;
m_labelNum = 0;
m_splitSize = 0;
m_splitFilenum = 0;
}
@@ -1261,7 +1311,107 @@ class EmitCImp : EmitCStmts {
// METHODS
// Low level
void emitVarReset(AstVar* varp);
void emitVarReset(AstVar* varp) {
AstNodeDType* dtypep = varp->dtypep()->skipRefp();
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
} else if (varp->isParam()) {
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
// If a simple CONST value we initialize it using an enum
// If an ARRAYINIT we initialize it using an initial block similar to a signal
//puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n");
} else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) {
if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
if (initarp->defaultp()) {
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi=0;");
puts(" for (; __Vi<"+cvtToStr(adtypep->elementsConst()));
puts("; ++__Vi) {\n");
emitSetVarConstant(varp->nameProtect()+"[__Vi]",
VN_CAST(initarp->defaultp(), Const));
puts("}}\n");
}
const AstInitArray::KeyItemMap& mapr = initarp->map();
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
it != mapr.end(); ++it) {
AstNode* valuep = it->second->valuep();
emitSetVarConstant(varp->nameProtect()
+"["+cvtToStr(it->first)+"]",
VN_CAST(valuep, Const));
}
} else {
varp->v3fatalSrc("InitArray under non-arrayed var");
}
} else {
puts(emitVarResetRecurse(varp, dtypep, 0, ""));
}
}
string emitVarResetRecurse(AstVar* varp, AstNodeDType* dtypep, int depth, string suffix) {
dtypep = dtypep->skipRefp();
AstBasicDType* basicp = dtypep->basicp();
// Returns string to do resetting, empty to do nothing (which caller should handle)
if (AstAssocArrayDType* adtypep = VN_CAST(dtypep, AssocArrayDType)) {
string cvtarray = (adtypep->subDTypep()->isWide() ? ".data()" : ""); // Access std::array as C array
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1,
".atDefault()" + cvtarray);
}
else if (AstQueueDType* adtypep = VN_CAST(dtypep, QueueDType)) {
return emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, ".atDefault()");
}
else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
UASSERT_OBJ(adtypep->msb() >= adtypep->lsb(), varp,
"Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(depth);
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
string pre = ("{ int "+ivar+"="+cvtToStr(0)+";"
+" for (; "+ivar+"<"+cvtToStr(adtypep->elementsConst())
+"; ++"+ivar+") {\n");
string below = emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, suffix+"["+ivar+"]");
string post = "}}\n";
return below.empty() ? "" : pre + below + post;
}
else if (basicp && basicp->keyword() == AstBasicDTypeKwd::STRING) {
// String's constructor deals with it
return "";
}
else if (basicp) {
bool zeroit = (varp->attrFileDescr() // Zero so we don't core dump if never $fopen
|| (basicp && basicp->isZeroInit())
|| (v3Global.opt.underlineZero()
&& !varp->name().empty() && varp->name()[0] == '_')
|| (v3Global.opt.xInitial() == "fast"
|| v3Global.opt.xInitial() == "0"));
splitSizeInc(1);
if (dtypep->isWide()) { // Handle unpacked; not basicp->isWide
string out;
if (zeroit) out += "VL_ZERO_RESET_W(";
else out += "VL_RAND_RESET_W(";
out += cvtToStr(dtypep->widthMin());
out += ", "+varp->nameProtect()+suffix+");\n";
return out;
} else {
string out = varp->nameProtect() + suffix;
// If --x-initial-edge is set, we want to force an initial
// edge on uninitialized clocks (from 'X' to whatever the
// first value is). Since the class is instantiated before
// initial blocks are evaluated, this should not clash
// with any initial block settings.
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
out += " = 0;\n";
} else {
out += " = VL_RAND_RESET_";
out += dtypep->charIQWN();
out += "("+ cvtToStr(dtypep->widthMin())+");\n";
}
return out;
}
}
else {
v3fatalSrc("Unknown node type in reset generator: "<<varp->prettyTypeName());
}
return "";
}
void emitCellCtors(AstNodeModule* modp);
void emitSensitives();
// Medium level
@@ -1275,7 +1425,6 @@ class EmitCImp : EmitCStmts {
void emitIntFuncDecls(AstNodeModule* modp);
// High level
void emitImp(AstNodeModule* modp);
void emitStaticDecl(AstNodeModule* modp);
void emitSettleLoop(const std::string& eval_call, bool initial);
void emitWrapEval(AstNodeModule* modp);
void emitMTaskState();
@@ -1301,72 +1450,35 @@ public:
void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
AstBasicDType* basicp = nodep->basicp();
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
if (nodep->isIO()) {
if (nodep->isSc()) {
m_ctorVarsVec.push_back(nodep);
if (nodep->attrScClocked() && nodep->isReadOnly()) {
puts("sc_in_clk ");
} else {
if (nodep->isInoutish()) puts("sc_inout<");
else if (nodep->isWritable()) puts("sc_out<");
else if (nodep->isNonOutput()) puts("sc_in<");
else nodep->v3fatalSrc("Unknown type");
puts(nodep->scType());
puts("> ");
}
puts(nodep->nameProtect());
emitDeclArrayBrackets(nodep);
puts(";\n");
} else if (basicp && basicp->isOpaque()) {
// strings and other fundamental c types; no VL_ macro can be used
puts(nodep->vlArgType(true, false, false));
emitDeclArrayBrackets(nodep);
puts(";\n");
} else { // C++ signals
if (nodep->isInoutish()) puts("VL_INOUT");
else if (nodep->isWritable()) puts("VL_OUT");
else if (nodep->isNonOutput()) puts("VL_IN");
if (nodep->isIO() && nodep->isSc()) {
UASSERT_OBJ(basicp, nodep, "Unimplemented: Outputting this data type");
m_ctorVarsVec.push_back(nodep);
if (nodep->attrScClocked() && nodep->isReadOnly()) {
puts("sc_in_clk ");
} else {
if (nodep->isInoutish()) puts("sc_inout<");
else if (nodep->isWritable()) puts("sc_out<");
else if (nodep->isNonOutput()) puts("sc_in<");
else nodep->v3fatalSrc("Unknown type");
if (nodep->isQuad()) puts("64");
else if (nodep->widthMin() <= 8) puts("8");
else if (nodep->widthMin() <= 16) puts("16");
else if (nodep->isWide()) puts("W");
puts("("+nodep->nameProtect());
emitDeclArrayBrackets(nodep);
// If it's a packed struct/array then nodep->width is the whole
// thing, msb/lsb is just lowest dimension
puts(","+cvtToStr(basicp->lsb()+nodep->width()-1)
+","+cvtToStr(basicp->lsb()));
if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords()));
puts(");\n");
puts(nodep->scType());
puts("> ");
}
} else if (basicp && basicp->isOpaque()) {
// strings and other fundamental c types
puts(nodep->vlArgType(true, false, false));
puts(nodep->nameProtect());
emitDeclArrayBrackets(nodep);
puts(";\n");
} else {
// Arrays need a small alignment, but may need different padding after.
// For example three VL_SIG8's needs alignment 1 but size 3.
if (nodep->isStatic() && prefixIfImp=="") puts("static ");
if (nodep->isStatic()) puts("VL_ST_"); else puts("VL_");
if (nodep->widthMin() <= 8) {
puts("SIG8(");
} else if (nodep->widthMin() <= 16) {
puts("SIG16(");
} else if (nodep->isQuad()) {
puts("SIG64(");
} else if (!nodep->isWide()) {
puts("SIG(");
} else {
puts("SIGW(");
}
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
puts(nodep->nameProtect());
} else if (nodep->isIO() && basicp && !basicp->isOpaque()) {
if (nodep->isInoutish()) puts("VL_INOUT");
else if (nodep->isWritable()) puts("VL_OUT");
else if (nodep->isNonOutput()) puts("VL_IN");
else nodep->v3fatalSrc("Unknown type");
if (nodep->isQuad()) puts("64");
else if (nodep->widthMin() <= 8) puts("8");
else if (nodep->widthMin() <= 16) puts("16");
else if (nodep->isWide()) puts("W");
puts("("+nodep->nameProtect());
emitDeclArrayBrackets(nodep);
// If it's a packed struct/array then nodep->width is the whole
// thing, msb/lsb is just lowest dimension
@@ -1374,6 +1486,10 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
+","+cvtToStr(basicp->lsb()));
if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords()));
puts(");\n");
} else {
// strings and other fundamental c types
puts(nodep->vlArgType(true, false, false, prefixIfImp));
puts(";\n");
}
}
@@ -1729,94 +1845,6 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
//######################################################################
// Internal EmitC
void EmitCImp::emitVarReset(AstVar* varp) {
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
} else if (varp->isParam()) {
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
// If a simple CONST value we initialize it using an enum
// If an ARRAYINIT we initialize it using an initial block similar to a signal
//puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n");
}
else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) {
if (AstUnpackArrayDType* arrayp = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType)) {
if (initarp->defaultp()) {
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi=0;");
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
puts("; ++__Vi) {\n");
emitSetVarConstant(varp->nameProtect()+"[__Vi]",
VN_CAST(initarp->defaultp(), Const));
puts("}}\n");
}
const AstInitArray::KeyItemMap& mapr = initarp->map();
for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin();
it != mapr.end(); ++it) {
AstNode* valuep = it->second->valuep();
emitSetVarConstant(varp->nameProtect()
+"["+cvtToStr(it->first)+"]",
VN_CAST(valuep, Const));
}
} else {
varp->v3fatalSrc("InitArray under non-arrayed var");
}
}
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
// Constructor deals with it
}
else {
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType);
arrayp;
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
int vecnum = vects++;
UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp,
"Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
puts("; ++"+ivar+") {\n");
}
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|| (varp->basicp() && varp->basicp()->isZeroInit())
|| (v3Global.opt.underlineZero()
&& !varp->name().empty() && varp->name()[0]=='_')
|| (v3Global.opt.xInitial() == "fast" || v3Global.opt.xInitial() == "0"));
if (varp->isWide()) {
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
// there should be a initial statement. (Different from verilator2.)
if (zeroit) puts("VL_ZERO_RESET_W(");
else puts("VL_RAND_RESET_W(");
puts(cvtToStr(varp->widthMin()));
puts(",");
puts(varp->nameProtect());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts(");\n");
} else {
puts(varp->nameProtect());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
// If --x-initial-edge is set, we want to force an initial
// edge on uninitialized clocks (from 'X' to whatever the
// first value is). Since the class is instantiated before
// initial blocks are evaluated, this should not clash
// with any initial block settings.
if (zeroit || (v3Global.opt.xInitialEdge() && varp->isUsedClock())) {
puts(" = 0;\n");
} else {
puts(" = VL_RAND_RESET_");
emitIQW(varp);
puts("(");
puts(cvtToStr(varp->widthMin()));
puts(");\n");
}
}
for (int v=0; v<vects; ++v) puts( "}}\n");
}
splitSizeInc(1);
}
void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
if (v3Global.opt.coverage()) {
ofp()->putsPrivate(true);
@@ -2047,13 +2075,6 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
}
}
void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
// Need implementation here. Be careful of alignment code; needs to be uniquified
// with module name to avoid multiple symbols.
//emitVarList(modp->stmtsp(), EVL_FUNC_ALL, modp->name());
puts(""); // NOP for cppcheck, otherwise const function
}
void EmitCImp::emitTextSection(AstType type) {
int last_line = -999;
for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
@@ -2756,7 +2777,6 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
if (m_fast && splitFilenum()==0) {
emitTextSection(AstType::atScImp);
emitStaticDecl(modp);
}
if (m_slow && splitFilenum()==0) {
@@ -2770,7 +2790,6 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
if (m_fast && splitFilenum()==0) {
if (modp->isTop()) {
emitStaticDecl(modp);
puts("\n//--------------------\n");
puts("\n");
emitWrapEval(modp);
@@ -2975,7 +2994,13 @@ class EmitCTrace : EmitCStmts {
puts("(c+"+cvtToStr(nodep->code()));
if (nodep->arrayRange().ranged()) puts("+i*"+cvtToStr(nodep->widthWords()));
puts(",");
if (nodep->isScoped()) {
puts("Verilated::catName(scopep,");
}
putsQuoted(VIdProtect::protectWordsIf(nodep->showname(), nodep->protect()));
if (nodep->isScoped()) {
puts(",\" \")");
}
// Direction
if (v3Global.opt.traceFormat().fstFlavor()) {
puts(","+cvtToStr(enumNum));
+8
View File
@@ -46,6 +46,14 @@ class EmitCInlines : EmitCBaseVisitor {
v3Global.needHeavy(true);
}
}
virtual void visit(AstAssocArrayDType* nodep) {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstQueueDType* nodep) {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstValuePlusArgs* nodep) {
v3Global.needHeavy(true);
iterateChildren(nodep);
-7
View File
@@ -93,7 +93,6 @@ class EmitCSyms : EmitCBaseVisitor {
ScopeNameHierarchy m_vpiScopeHierarchy; // The actual hierarchy of scopes
V3LanguageWords m_words; // Reserved word detector
int m_coverBins; // Coverage bin number
int m_labelNum; // Next label number
bool m_dpiHdrOnly; // Only emit the DPI header
int m_numStmts; // Number of statements output
int m_funcNum; // CFunc split function number
@@ -272,7 +271,6 @@ class EmitCSyms : EmitCBaseVisitor {
virtual void visit(AstNodeModule* nodep) {
nameCheck(nodep);
m_modp = nodep;
m_labelNum = 0;
iterateChildren(nodep);
m_modp = NULL;
}
@@ -331,10 +329,6 @@ class EmitCSyms : EmitCBaseVisitor {
nodep->binNum(m_coverBins++);
}
}
virtual void visit(AstJumpLabel* nodep) {
nodep->labelNum(++m_labelNum);
iterateChildren(nodep);
}
virtual void visit(AstCFunc* nodep) {
nameCheck(nodep);
if (nodep->dpiImport() || nodep->dpiExportWrapper()) {
@@ -359,7 +353,6 @@ public:
m_funcp = NULL;
m_modp = NULL;
m_coverBins = 0;
m_labelNum = 0;
m_numStmts = 0;
m_funcNum = 0;
m_ofpBase = NULL;
+2 -1
View File
@@ -100,6 +100,7 @@ public:
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro
SELRANGE, // Selection index out of range
SHORTREAL, // Shortreal not supported
STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word
SYNCASYNCNET, // Mixed sync + async reset
@@ -151,7 +152,7 @@ public:
"MULTIDRIVEN", "MULTITOP",
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
"REALCVT", "REDEFMACRO",
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"SELRANGE", "SHORTREAL", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSIGNED", "UNUSED",
+18 -5
View File
@@ -175,12 +175,15 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) {
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
// Grab linenumber
bool fail = false;
const char* ln = textp;
while (*textp && !isspace(*textp)) textp++;
if (isdigit(*ln)) {
lineno(atoi(ln));
}
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
} else fail = true;
while (*textp && (isspace(*textp))) textp++;
if (*textp != '"') fail = true;
while (*textp && (isspace(*textp) || *textp == '"')) textp++;
// Grab filename
const char* fn = textp;
@@ -189,12 +192,21 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) {
string strfn = fn;
strfn = strfn.substr(0, textp-fn);
filename(strfn);
}
} else fail = true;
// Grab level
while (*textp && (isspace(*textp) || *textp=='"')) textp++;
if (isdigit(*textp)) enterExitRef = atoi(textp);
else enterExitRef = 0;
if (isdigit(*textp)) {
enterExitRef = atoi(textp);
if (enterExitRef >= 3) fail = true;
} else {
enterExitRef = 0;
fail = true;
}
if (fail && v3Global.opt.pedantic()) {
v3error("`line was not properly formed with '`line number \"filename\" level'\n");
}
//printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str());
}
@@ -367,6 +379,7 @@ string FileLine::prettySource() const {
string FileLine::warnContext(bool secondary) const {
V3Error::errorContexted(true);
if (!v3Global.opt.context()) return "";
string out = "";
if (firstLineno()==lastLineno() && firstColumn()) {
string sourceLine = prettySource();
+39 -21
View File
@@ -61,9 +61,13 @@ class GateLogicVertex;
class GateVarVertex;
class GateGraphBaseVisitor {
public:
virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu=VNUser(0)) = 0;
virtual VNUser visit(GateVarVertex* vertexp, VNUser vu=VNUser(0)) = 0;
V3Graph* m_graphp; // Graph this class is visiting
GateGraphBaseVisitor(V3Graph* graphp)
: m_graphp(graphp) {}
virtual ~GateGraphBaseVisitor() {}
virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu = VNUser(0)) = 0;
virtual VNUser visit(GateVarVertex* vertexp, VNUser vu = VNUser(0)) = 0;
VL_DEBUG_FUNC; // Declare debug()
};
//######################################################################
@@ -172,7 +176,7 @@ public:
virtual ~GateLogicVertex() {}
// ACCESSORS
virtual string name() const { return (cvtToHex(m_nodep)+"@"+scopep()->prettyName()); }
virtual string dotColor() const { return "yellow"; }
virtual string dotColor() const { return "purple"; }
virtual FileLine* fileline() const { return nodep()->fileline(); }
AstNode* nodep() const { return m_nodep; }
AstActive* activep() const { return m_activep; }
@@ -400,8 +404,14 @@ private:
// Then propagate more complicated equations
optimizeSignals(true);
// Remove redundant logic
if (v3Global.opt.oDedupe()) dedupe();
if (v3Global.opt.oAssemble()) mergeAssigns();
if (v3Global.opt.oDedupe()) {
dedupe();
if (debug() >= 6) m_graph.dumpDotFilePrefixed("gate_dedup");
}
if (v3Global.opt.oAssemble()) {
mergeAssigns();
if (debug() >= 6) m_graph.dumpDotFilePrefixed("gate_assm");
}
// Consumption warnings
consumedMark();
m_graph.dumpDotFilePrefixed("gate_opt");
@@ -870,7 +880,7 @@ private:
// However a VARREF should point to the original as it's otherwise confusing
// to throw warnings that point to a PIN rather than where the pin us used.
if (VN_IS(substp, VarRef)) substp->fileline(nodep->fileline());
// Make the substp an rvalue like nodep. This facilitate the hashing in dedupe.
// Make the substp an rvalue like nodep. This facilitates the hashing in dedupe.
if (AstNodeVarRef* varrefp = VN_CAST(substp, NodeVarRef)) varrefp->lvalue(false);
hashReplace(nodep, substp);
nodep->replaceWith(substp);
@@ -885,6 +895,9 @@ public:
virtual ~GateElimVisitor() {}
GateElimVisitor(AstNode* nodep, AstVarScope* varscp, AstNode* replaceTreep,
GateDedupeVarVisitor* varVisp) {
UINFO(9, " elimvisitor " << nodep << endl);
UINFO(9, " elim varscp " << varscp << endl);
UINFO(9, " elim repce " << replaceTreep << endl);
m_didReplace = false;
m_elimVarScp = varscp;
m_replaceTreep = replaceTreep;
@@ -1178,10 +1191,18 @@ private:
GateLogicVertex* consumeVertexp
= dynamic_cast<GateLogicVertex*>(outedgep->top());
AstNode* consumerp = consumeVertexp->nodep();
GateElimVisitor elimVisitor(consumerp, vvertexp->varScp(), dupVarRefp, &m_varVisitor);
m_graphp->dumpDotFilePrefixed("gate_preelim");
UINFO(9, "elim src vtx"<<lvertexp<<" node "<<lvertexp->nodep()<<endl);
UINFO(9, "elim cons vtx"<<consumeVertexp<<" node "<<consumerp<<endl);
UINFO(9, "elim var vtx "<<vvertexp<<" node "<<vvertexp->varScp()<<endl);
UINFO(9, "replace with "<<dupVarRefp<<endl);
if (lvertexp == consumeVertexp) {
UINFO(9, "skipping as self-recirculates\n");
} else {
GateElimVisitor elimVisitor(consumerp, vvertexp->varScp(), dupVarRefp, &m_varVisitor);
}
outedgep = outedgep->relinkFromp(dupVvertexp);
}
// Propagate attributes
dupVvertexp->propagateAttrClocksFrom(vvertexp);
// Remove inputs links
@@ -1211,7 +1232,7 @@ private:
if (lvertexp->dedupable() && consumerVvertexpp->dedupable()) {
AstNode* nodep = lvertexp->nodep();
AstVarScope* consumerVarScopep = consumerVvertexpp->varScp();
// TODO: Doing a simple pointer comparison of activep won't work
// TODO: Doing a simple pointer comparison of activep won't work
// optimally for statements under generated clocks. Statements under
// different generated clocks will never compare as equal, even if the
// generated clocks are deduped into one clock.
@@ -1222,12 +1243,10 @@ private:
}
public:
GateDedupeGraphVisitor() {
m_depth = 0;
}
void dedupeTree(GateVarVertex* vvertexp) {
vvertexp->accept(*this);
}
explicit GateDedupeGraphVisitor(V3Graph* graphp)
: GateGraphBaseVisitor(graphp)
, m_depth(0) {}
void dedupeTree(GateVarVertex* vvertexp) { vvertexp->accept(*this); }
VDouble0 numDeduped() { return m_numDeduped; }
};
@@ -1235,7 +1254,7 @@ public:
void GateVisitor::dedupe() {
AstNode::user2ClearTree();
GateDedupeGraphVisitor deduper;
GateDedupeGraphVisitor deduper(&m_graph);
// Traverse starting from each of the clocks
UINFO(9,"Gate dedupe() clocks:\n");
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
@@ -1267,7 +1286,6 @@ private:
AstNodeAssign* m_assignp;
AstActive* m_activep;
GateLogicVertex* m_logicvp;
V3Graph* m_graphp;
VDouble0 m_numMergedAssigns; // Statistic tracking
@@ -1367,7 +1385,8 @@ private:
}
public:
explicit GateMergeAssignsGraphVisitor(V3Graph* graphp) {
explicit GateMergeAssignsGraphVisitor(V3Graph* graphp)
: GateGraphBaseVisitor(graphp) {
m_assignp = NULL;
m_activep = NULL;
m_logicvp = NULL;
@@ -1469,7 +1488,6 @@ class GateClkDecompGraphVisitor : public GateGraphBaseVisitor {
private:
// NODE STATE
// AstVarScope::user2p -> bool: already visited
V3Graph* m_graphp;
int m_seen_clk_vectors;
AstVarScope* m_clk_vsp;
GateVarVertex* m_clk_vvertexp;
@@ -1551,8 +1569,8 @@ private:
}
public:
explicit GateClkDecompGraphVisitor(V3Graph* graphp) {
m_graphp = graphp;
explicit GateClkDecompGraphVisitor(V3Graph* graphp)
: GateGraphBaseVisitor(graphp) {
m_seen_clk_vectors = 0;
m_clk_vsp = NULL;
m_clk_vvertexp = NULL;
+106
View File
@@ -613,6 +613,109 @@ public:
}
};
//######################################################################
// Track interface references under the Cell they reference
class InlineIntfRefVisitor : public AstNVisitor {
private:
// NODE STATE
// AstVar::user1p() // AstCell which this Var points to
AstUser2InUse m_inuser2;
string m_scope; // Scope name
// METHODS
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNetlist* nodep) {
iterateChildren(nodep);
}
virtual void visit(AstModule* nodep) {
if (nodep->isTop()) {
iterateChildren(nodep);
}
}
virtual void visit(AstCell* nodep) {
string oldScope = m_scope;
if (m_scope.empty()) {
m_scope = nodep->name();
} else {
m_scope += "__DOT__" + nodep->name();
}
if (AstModule* modp = VN_CAST(nodep->modp(), Module)) {
// Pass Cell pointers down to the next module
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) {
AstVar* varp = pinp->modVarp();
AstVarRef* varrefp = VN_CAST(pinp->exprp(), VarRef);
if (!varrefp) continue;
AstVar* fromVarp = varrefp->varp();
AstIfaceRefDType* irdtp = VN_CAST(fromVarp->dtypep(), IfaceRefDType);
if (!irdtp) continue;
AstCell* cellp;
if ((cellp = VN_CAST(fromVarp->user1p(), Cell))
|| (cellp = irdtp->cellp())) {
varp->user1p(cellp);
string alias = m_scope + "__DOT__" + pinp->name();
cellp->addIntfRefp(new AstIntfRef(pinp->fileline(), alias));
}
}
iterateChildren(modp);
} else if (VN_IS(nodep->modp(), Iface)) {
nodep->addIntfRefp(new AstIntfRef(nodep->fileline(), m_scope));
// No need to iterate on interface cells
}
m_scope = oldScope;
}
virtual void visit(AstAssignVarScope* nodep) {
// Reference
AstVarRef* reflp = VN_CAST(nodep->lhsp(), VarRef);
// What the reference refers to
AstVarRef* refrp = VN_CAST(nodep->rhsp(), VarRef);
if (!(reflp && refrp)) return;
AstVar* varlp = reflp->varp();
AstVar* varrp = refrp->varp();
if (!(varlp && varrp)) return;
AstCell* cellp = VN_CAST(varrp->user1p(), Cell);
if (!cellp) {
AstIfaceRefDType* irdtp = VN_CAST(varrp->dtypep(), IfaceRefDType);
if (!irdtp) return;
cellp = irdtp->cellp();
}
if (!cellp) return;
string alias;
if (!m_scope.empty()) alias = m_scope + "__DOT__";
alias += varlp->name();
cellp->addIntfRefp(new AstIntfRef(varlp->fileline(), alias));
}
//--------------------
virtual void visit(AstNodeMath*) {} // Accelerate
virtual void visit(AstNodeStmt*) {} // Accelerate
virtual void visit(AstNode* nodep) {
iterateChildren(nodep);
}
public:
// CONSTRUCTORS
explicit InlineIntfRefVisitor(AstNode* nodep) {
iterate(nodep);
}
virtual ~InlineIntfRefVisitor() {
}
};
//######################################################################
// Inline class functions
@@ -637,5 +740,8 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
}
}
{
InlineIntfRefVisitor crvisitor (nodep);
}
V3Global::dumpCheckGlobalTree("inline", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+13 -5
View File
@@ -983,6 +983,11 @@ class LinkDotFindVisitor : public AstNVisitor {
// Var: Remember its name for later resolution
UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?");
iterateChildren(nodep);
if (m_ftaskp && nodep->isParam()) {
nodep->v3error("Unsupported: Parameters in functions."); // Big3 unsupported too
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
return;
}
if (!m_statep->forScopeCreation()) {
// Find under either a task or the module's vars
VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name());
@@ -1942,7 +1947,9 @@ private:
// m_curSymp is symbol table of outer expression
// m_ds.m_dotSymp is symbol table relative to "."'s above now
UASSERT_OBJ(m_ds.m_dotSymp, nodep, "NULL lookup symbol table");
UASSERT_OBJ(m_statep->forPrimary(), nodep, "ParseRefs should no longer exist");
// Generally resolved during Primay, but might be at param time under AstUnlinkedRef
UASSERT_OBJ(m_statep->forPrimary() || m_statep->forPrearray(),
nodep, "ParseRefs should no longer exist");
DotStates lastStates = m_ds;
bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
if (start) {
@@ -1954,7 +1961,8 @@ private:
AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
AstNode* newp = new AstMemberSel(nodep->fileline(), varEtcp,
VFlagChildDType(), nodep->name());
nodep->replaceWith(newp);
if (m_ds.m_dotErr) nodep->unlinkFrBack(); // Avoid circular node loop on errors
else nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
}
else {
@@ -2264,7 +2272,7 @@ private:
// EnumItemRef may be under a dot. Should already be resolved.
iterateChildren(nodep);
}
virtual void visit(AstMethodSel* nodep) {
virtual void visit(AstMethodCall* nodep) {
// Created here so should already be resolved.
DotStates lastStates = m_ds;
{
@@ -2312,8 +2320,8 @@ private:
AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
AstNode* argsp = NULL;
if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext();
AstNode* newp = new AstMethodSel(nodep->fileline(), varEtcp,
VFlagChildDType(), nodep->name(), argsp);
AstNode* newp = new AstMethodCall(nodep->fileline(), varEtcp,
VFlagChildDType(), nodep->name(), argsp);
nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
return;
+8
View File
@@ -149,6 +149,14 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFUngetC* nodep) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
iterateAndNextNull(nodep->filep());
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstSScanF* nodep) {
bool last_setRefLvalue = m_setRefLvalue;
{
+29 -8
View File
@@ -110,13 +110,12 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
bool unbased = false;
char base = '\0';
if (value_startp != sourcep) { // Has a '
char widthn[100]; char* wp=&widthn[0];
const char* cp=sourcep;
string widthn;
const char* cp = sourcep;
for (; *cp; cp++) {
if (*cp == '\'') { cp++ ; break; }
if (*cp != '_') *wp++ = *cp;
if (*cp != '_') widthn += *cp;
}
*wp++ = '\0';
while (*cp == '_') cp++;
if (*cp && tolower(*cp)=='s') {
cp++; isSigned(true);
@@ -124,13 +123,13 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
if (*cp) { base=*cp; cp++; }
value_startp = cp;
if (atoi(widthn)) {
if (atoi(widthn) < 0 || atoi(widthn) > MAX_WIDTH) {
if (atoi(widthn.c_str())) {
if (atoi(widthn.c_str()) < 0 || atoi(widthn.c_str()) > MAX_WIDTH) {
// atoi might convert large number to negative, so can't tell which
v3error("Unsupported: Width of number exceeds implementation limit: "<<sourcep);
width(MAX_WIDTH, true);
} else {
width(atoi(widthn), true);
width(atoi(widthn.c_str()), true);
}
}
} else {
@@ -138,7 +137,7 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
base = 'd';
}
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
for (int i = 0; i < words(); ++i) m_value[i] = m_valueX[i] = 0;
// Special SystemVerilog unsized constructs
if (base == '0') {
@@ -162,6 +161,9 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
// Ignore leading blanks
while (*value_startp=='_' || isspace(*value_startp)) value_startp++;
if (!*value_startp && !m_autoExtend) {
v3error("Number is missing value digits: "<<sourcep);
}
int obit = 0; // Start at LSB
if (tolower(base) == 'd') {
@@ -2074,6 +2076,25 @@ V3Number& V3Number::opReplN(const V3Number& lhs, uint32_t rhsval) {
}
return setString(out);
}
V3Number& V3Number::opToLowerN(const V3Number& lhs) {
NUM_ASSERT_OP_ARGS1(lhs);
NUM_ASSERT_STRING_ARGS1(lhs);
std::string out = lhs.toString();
for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
*it = tolower(*it);
}
return setString(out);
}
V3Number& V3Number::opToUpperN(const V3Number& lhs) {
NUM_ASSERT_OP_ARGS1(lhs);
NUM_ASSERT_STRING_ARGS1(lhs);
std::string out = lhs.toString();
for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
*it = toupper(*it);
}
return setString(out);
}
V3Number& V3Number::opEqN(const V3Number& lhs, const V3Number& rhs) {
NUM_ASSERT_OP_ARGS2(lhs, rhs);
NUM_ASSERT_STRING_ARGS2(lhs, rhs);
+2
View File
@@ -288,6 +288,8 @@ public:
V3Number& opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval);
V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width);
V3Number& opSelInto (const V3Number& lhs, int lsbval, int width);
V3Number& opToLowerN(const V3Number& lhs);
V3Number& opToUpperN(const V3Number& lhs);
V3Number& opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s);
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
+14 -6
View File
@@ -796,6 +796,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-trace-underscore", flag/*ref*/)) { m_traceUnderscore = flag; }
else if ( onoff (sw, "-underline-zero", flag/*ref*/)) { m_underlineZero = flag; } // Undocumented, old Verilator-2
else if ( onoff (sw, "-vpi", flag/*ref*/)) { m_vpi = flag; }
else if ( onoff (sw, "-Wpedantic", flag/*ref*/)) { m_pedantic = flag; }
else if ( onoff (sw, "-x-initial-edge", flag/*ref*/)) { m_xInitialEdge = flag; }
else if ( onoff (sw, "-xml-only", flag/*ref*/)) { m_xmlOnly = flag; } // Undocumented, still experimental
// Optimization
@@ -1049,16 +1050,19 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
addFuture(msg);
}
else if (!strncmp (sw, "-Wno-", 5)) {
if (!strcmp(sw, "-Wno-lint")) {
if (!strcmp(sw, "-Wno-context")) {
m_context = false;
}
else if (!strcmp(sw, "-Wno-fatal")) {
V3Error::warnFatal(false);
}
else if (!strcmp(sw, "-Wno-lint")) {
FileLine::globalWarnLintOff(true);
FileLine::globalWarnStyleOff(true);
}
else if (!strcmp(sw, "-Wno-style")) {
FileLine::globalWarnStyleOff(true);
}
else if (!strcmp(sw, "-Wno-fatal")) {
V3Error::warnFatal(false);
}
else {
string msg = sw+strlen("-Wno-");
if (!(FileLine::globalWarnOff(msg, true))) {
@@ -1246,13 +1250,15 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
// Strip simple comments
string oline;
// cppcheck-suppress StlMissingComparison
for (string::const_iterator pos = line.begin(); pos != line.end(); ++pos) {
char lastch = ' ';
for (string::const_iterator pos = line.begin(); pos != line.end(); lastch = *pos++) {
if (inCmt) {
if (*pos=='*' && *(pos+1)=='/') {
inCmt = false;
++pos;
}
} else if (*pos=='/' && *(pos+1)=='/') {
} else if (*pos=='/' && *(pos+1)=='/'
&& (pos == line.begin() || isspace(lastch))) { // But allow /file//path
break; // Ignore to EOL
} else if (*pos=='/' && *(pos+1)=='*') {
inCmt = true;
@@ -1434,6 +1440,7 @@ V3Options::V3Options() {
m_bboxUnsup = false;
m_cdc = false;
m_cmake = false;
m_context = true;
m_coverageLine = false;
m_coverageToggle = false;
m_coverageUnderscore = false;
@@ -1456,6 +1463,7 @@ V3Options::V3Options() {
m_makePhony = false;
m_orderClockDly = true;
m_outFormatOk = false;
m_pedantic = false;
m_pinsBv = 65;
m_pinsScUint = false;
m_pinsScBigUint = false;
+4
View File
@@ -142,6 +142,7 @@ class V3Options {
bool m_bboxUnsup; // main switch: --bbox-unsup
bool m_cdc; // main switch: --cdc
bool m_cmake; // main switch: --make cmake
bool m_context; // main switch: --Wcontext
bool m_coverageLine; // main switch: --coverage-block
bool m_coverageToggle;// main switch: --coverage-toggle
bool m_coverageUnderscore;// main switch: --coverage-underscore
@@ -163,6 +164,7 @@ class V3Options {
bool m_gmake; // main switch: --make gmake
bool m_orderClockDly;// main switch: --order-clock-delay
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
bool m_pedantic; // main switch: --Wpedantic
bool m_pinsScUint; // main switch: --pins-sc-uint
bool m_pinsScBigUint;// main switch: --pins-sc-biguint
bool m_pinsUint8; // main switch: --pins-uint8
@@ -319,6 +321,7 @@ class V3Options {
bool bboxUnsup() const { return m_bboxUnsup; }
bool cdc() const { return m_cdc; }
bool cmake() const { return m_cmake; }
bool context() const { return m_context; }
bool coverage() const { return m_coverageLine || m_coverageToggle || m_coverageUser; }
bool coverageLine() const { return m_coverageLine; }
bool coverageToggle() const { return m_coverageToggle; }
@@ -348,6 +351,7 @@ class V3Options {
bool orderClockDly() const { return m_orderClockDly; }
bool outFormatOk() const { return m_outFormatOk; }
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
bool pedantic() const { return m_pedantic; }
bool pinsScUint() const { return m_pinsScUint; }
bool pinsScBigUint() const { return m_pinsScBigUint; }
bool pinsUint8() const { return m_pinsUint8; }
+19 -7
View File
@@ -113,17 +113,29 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep,
AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange);
if (prevp) nrangep->unlinkFrBack();
AstRange* rangep = VN_CAST(nrangep, Range);
if (!rangep) {
UASSERT_OBJ(VN_IS(nrangep, UnsizedRange), nrangep,
"Expected range or unsized range");
arrayp = new AstUnsizedArrayDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
} else if (isPacked) {
if (rangep && isPacked) {
arrayp = new AstPackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else {
} else if (rangep) {
if (VN_IS(rangep->leftp(), Unbounded)
|| VN_IS(rangep->rightp(), Unbounded)) {
rangep->v3error("Unsupported: Bounded queues. Suggest use unbounded.");
}
arrayp = new AstUnpackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else if (VN_IS(nrangep, UnsizedRange)) {
arrayp = new AstUnsizedArrayDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
} else if (VN_IS(nrangep, AssocRange)) {
AstAssocRange* arangep = VN_CAST(nrangep, AssocRange);
AstNodeDType* keyp = arangep->keyDTypep(); keyp->unlinkFrBack();
arrayp = new AstAssocArrayDType
(nrangep->fileline(), VFlagChildDType(), arrayp, keyp);
} else if (VN_IS(nrangep, QueueRange)) {
arrayp = new AstQueueDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
} else {
UASSERT_OBJ(0, nrangep, "Expected range or unsized range");
}
nrangep = prevp;
}
+16 -10
View File
@@ -24,6 +24,7 @@
#include "V3Error.h"
#include "V3Global.h"
#include "V3File.h"
#include "V3LanguageWords.h"
#include "V3PreLex.h"
#include "V3PreProc.h"
#include "V3PreShell.h"
@@ -337,18 +338,23 @@ FileLine* V3PreProcImp::defFileline(const string& name) {
void V3PreProcImp::define(FileLine* fl, const string& name, const string& value,
const string& params, bool cmdline) {
UINFO(4,"DEFINE '"<<name<<"' as '"<<value<<"' params '"<<params<<"'"<<endl);
if (defExists(name)) {
if (!(defValue(name)==value && defParams(name)==params)) { // Duplicate defs are OK
fl->v3warn(REDEFMACRO, "Redefining existing define: '"<<name<<"', with different value: "
<<value<<(params=="" ? "":" ")<<params);
defFileline(name)->v3warn(REDEFMACRO, "Previous definition is here, with value: "
<<defValue(name)
<<(defParams(name)=="" ? "":" ")
<<defParams(name));
if (!V3LanguageWords::isKeyword(string("`") + name).empty()) {
fl->v3error("Attempting to define built-in directive: '`"<<name<<"' (IEEE 2017 22.5.1)");
} else {
if (defExists(name)) {
if (!(defValue(name) == value
&& defParams(name) == params)) { // Duplicate defs are OK
fl->v3warn(REDEFMACRO, "Redefining existing define: '"<<name<<"', with different value: "
<<value<<(params=="" ? "":" ")<<params);
defFileline(name)->v3warn(REDEFMACRO, "Previous definition is here, with value: "
<< defValue(name)
<< (defParams(name).empty() ? "" : " ")
<< defParams(name));
}
undef(name);
}
undef(name);
m_defines.insert(make_pair(name, VDefine(fl, value, params, cmdline)));
}
m_defines.insert(make_pair(name, VDefine(fl, value, params, cmdline)));
}
string V3PreProcImp::removeDefines(const string& text) {
+12 -1
View File
@@ -349,6 +349,16 @@ private:
}
checkNode(nodep);
}
virtual void visit(AstAssocSel* nodep) {
iterateAndNextNull(nodep->fromp());
{ // Only the 'from' is part of the assignment LHS
bool prevAssign = m_assignLhs;
m_assignLhs = false;
iterateAndNextNull(nodep->bitp());
m_assignLhs = prevAssign;
}
checkNode(nodep);
}
virtual void visit(AstConst* nodep) {
iterateChildren(nodep); checkNode(nodep);
}
@@ -388,7 +398,8 @@ private:
// Any strings sent to a display must be var of string data type,
// to avoid passing a pointer to a temporary.
for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) {
if (expp->dtypep()->basicp()->isString()
if (expp->dtypep()->basicp()
&& expp->dtypep()->basicp()->isString()
&& !VN_IS(expp, VarRef)) {
createDeepTemp(expp, true);
}
+8 -2
View File
@@ -65,6 +65,7 @@ class ProtectVisitor : public AstNVisitor {
AstTextBlock* m_cIgnoreParamsp; // Combo ignore parameter list
string m_libName;
string m_topName;
bool m_foundTop; // Have seen the top module
// VISITORS
virtual void visit(AstNetlist* nodep) {
@@ -78,7 +79,11 @@ class ProtectVisitor : public AstNVisitor {
}
virtual void visit(AstNodeModule* nodep) {
UASSERT_OBJ(!nodep->nextp(), nodep, "Multiple root modules");
if (!nodep->isTop()) {
return;
} else {
UASSERT_OBJ(!m_foundTop, nodep, "Multiple root modules");
}
FileLine* fl = nodep->fileline();
createSvFile(fl);
createCppFile(fl);
@@ -88,6 +93,7 @@ class ProtectVisitor : public AstNVisitor {
V3Hash hash = V3Hashed::uncachedHash(m_cfilep);
m_hashValuep->addText(fl, cvtToStr(hash.fullValue())+";\n");
m_cHashValuep->addText(fl, cvtToStr(hash.fullValue())+";\n");
m_foundTop = true;
}
void addComment(AstTextBlock* txtp, FileLine* fl, const string& comment) {
@@ -439,7 +445,7 @@ class ProtectVisitor : public AstNVisitor {
m_comboAssignsp(NULL), m_cHashValuep(NULL), m_cComboParamsp(NULL), m_cComboInsp(NULL),
m_cComboOutsp(NULL), m_cSeqParamsp(NULL), m_cSeqClksp(NULL), m_cSeqOutsp(NULL),
m_cIgnoreParamsp(NULL), m_libName(v3Global.opt.protectLib()),
m_topName(v3Global.opt.prefix())
m_topName(v3Global.opt.prefix()), m_foundTop(false)
{
iterate(nodep);
}
+1
View File
@@ -162,6 +162,7 @@ private:
// Of a constant index
AstConst* lbitp = VN_CAST(lselp->bitp(), Const);
if (!lbitp) { mergeEnd(); return; }
if (lbitp->width() > 32) { mergeEnd(); return; } // Assoc arrays can do this
uint32_t index = lbitp->toUInt();
// Of variable
AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef);
+17 -17
View File
@@ -110,11 +110,7 @@ protected:
// Do not make accessor for nodep(), It may change due to
// reordering a lower block, but we don't repair it
virtual string name() const {
if (m_nodep->name() == "") {
return cvtToHex(m_nodep);
} else {
return m_nodep->name();
}
return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName();
}
virtual FileLine* fileline() const { return nodep()->fileline(); }
public:
@@ -655,18 +651,12 @@ public:
const ColorSet& colors() const { return m_colors; }
const ColorSet& colors(AstNodeIf* nodep) const {
IfColorMap::const_iterator it = m_ifColors.find(nodep);
UASSERT_OBJ(it != m_ifColors.end(), nodep, "Unknown node in split color() map");
UASSERT_OBJ(it != m_ifColors.end(), nodep, "Node missing from split color() map");
return it->second;
}
protected:
virtual void visit(AstNodeIf* nodep) {
m_ifStack.push_back(nodep);
iterateChildren(nodep);
m_ifStack.pop_back();
}
virtual void visit(AstNode* nodep) {
private:
void trackNode(AstNode* nodep) {
if (nodep->user3p()) {
SplitLogicVertex* vertexp = reinterpret_cast<SplitLogicVertex*>(nodep->user3p());
uint32_t color = vertexp->color();
@@ -679,6 +669,17 @@ protected:
m_ifColors[*it].insert(color);
}
}
}
protected:
virtual void visit(AstNodeIf* nodep) {
m_ifStack.push_back(nodep);
trackNode(nodep);
iterateChildren(nodep);
m_ifStack.pop_back();
}
virtual void visit(AstNode* nodep) {
trackNode(nodep);
iterateChildren(nodep);
}
@@ -944,15 +945,14 @@ protected:
}
}
if (debug()>=9) {
m_graph.dumpDotFilePrefixed("splitg_nodup", false);
}
if (debug()>=9) m_graph.dumpDotFilePrefixed("splitg_nodup", false);
// Weak coloring to determine what needs to remain grouped
// in a single always. This follows all edges excluding:
// - those we pruned above
// - PostEdges, which are done later
m_graph.weaklyConnected(&SplitEdge::followScoreboard);
if (debug()>=9) m_graph.dumpDotFilePrefixed("splitg_colored", false);
}
virtual void visit(AstAlways* nodep) {
+58 -30
View File
@@ -52,7 +52,7 @@ private:
AstVarScope* m_traVscp; // Signal being trace constructed
AstNode* m_traValuep; // Signal being traced's value to trace in it
string m_traShowname; // Signal being traced's component name
string m_ifShowname; // Interface reference being traced's scope name
bool m_interface; // Currently tracing an interface
VDouble0 m_statSigs; // Statistic tracking
VDouble0 m_statIgnSigs; // Statistic tracking
@@ -83,25 +83,32 @@ private:
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
funcp->slow(slow);
funcp->argTypes(EmitCBaseVisitor::symClassVar()+", "+v3Global.opt.traceClassBase()+"* vcdp, uint32_t code");
string argTypes(EmitCBaseVisitor::symClassVar()+", "+v3Global.opt.traceClassBase()
+"* vcdp, uint32_t code");
if (m_interface) argTypes += ", const char* scopep";
funcp->argTypes(argTypes);
funcp->funcType(type);
funcp->symProlog(true);
m_scopetopp->addActivep(funcp);
UINFO(5," Newfunc "<<funcp<<endl);
return funcp;
}
void callCFuncSub(AstCFunc* basep, AstCFunc* funcp, AstIntfRef* irp) {
AstCCall* callp = new AstCCall(funcp->fileline(), funcp);
callp->argTypes("vlSymsp, vcdp, code");
if (irp) callp->addArgsp(irp->unlinkFrBack());
basep->addStmtsp(callp);
}
AstCFunc* newCFuncSub(AstCFunc* basep) {
string name = basep->name()+"__"+cvtToStr(++m_funcNum);
AstCFunc* funcp = NULL;
if (basep->funcType()==AstCFuncType::TRACE_INIT) {
if (basep->funcType()==AstCFuncType::TRACE_INIT
|| basep->funcType()==AstCFuncType::TRACE_INIT_SUB) {
funcp = newCFunc(AstCFuncType::TRACE_INIT_SUB, name, basep->slow());
} else {
basep->v3fatalSrc("Strange base function type");
}
// cppcheck-suppress nullPointer // above fatal prevents it
AstCCall* callp = new AstCCall(funcp->fileline(), funcp);
callp->argTypes("vlSymsp, vcdp, code");
basep->addStmtsp(callp);
if (!m_interface) callCFuncSub(basep, funcp, NULL);
return funcp;
}
void addTraceDecl(const VNumRange& arrayRange,
@@ -112,10 +119,10 @@ private:
else if (bdtypep) bitRange = bdtypep->nrange();
AstTraceDecl* declp = new AstTraceDecl(m_traVscp->fileline(), m_traShowname,
m_traVscp->varp(), m_traValuep,
bitRange, arrayRange);
bitRange, arrayRange, m_interface);
UINFO(9,"Decl "<<declp<<endl);
if (m_initSubStmts && v3Global.opt.outputSplitCTrace()
if (!m_interface && v3Global.opt.outputSplitCTrace()
&& m_initSubStmts > v3Global.opt.outputSplitCTrace()) {
m_initSubFuncp = newCFuncSub(m_initFuncp);
m_initSubStmts = 0;
@@ -147,6 +154,44 @@ private:
// And find variables
iterateChildren(nodep);
}
virtual void visit(AstScope* nodep) {
AstCell* cellp = VN_CAST(nodep->aboveCellp(), Cell);
if (cellp && VN_IS(cellp->modp(), Iface)) {
AstCFunc* origSubFunc = m_initSubFuncp;
int origSubStmts = m_initSubStmts;
{
m_interface = true;
m_initSubFuncp = newCFuncSub(origSubFunc);
string scopeName = nodep->prettyName();
size_t lastDot = scopeName.find_last_of('.');
UASSERT_OBJ(lastDot != string::npos, nodep,
"Expected an interface scope name to have at least one dot");
scopeName = scopeName.substr(0, lastDot+1);
size_t scopeLen = scopeName.length();
AstIntfRef* nextIrp = cellp->intfRefp();
// While instead of for loop because interface references will
// be unlinked as we go
while (nextIrp) {
AstIntfRef* irp = nextIrp;
nextIrp = VN_CAST(irp->nextp(), IntfRef);
string irpName = irp->prettyName();
if (scopeLen > irpName.length()) continue;
string intfScopeName = irpName.substr(0, scopeLen);
if (scopeName != intfScopeName) continue;
callCFuncSub(origSubFunc, m_initSubFuncp, irp);
++origSubStmts;
}
iterateChildren(nodep);
}
m_initSubFuncp = origSubFunc;
m_initSubStmts = origSubStmts;
m_interface = false;
} else {
iterateChildren(nodep);
}
}
virtual void visit(AstVarScope* nodep) {
iterateChildren(nodep);
// Prefilter - things that get through this if will either get
@@ -161,11 +206,11 @@ private:
// Compute show name
// This code assumes SPTRACEVCDC_VERSION >= 1330;
// it uses spaces to separate hierarchy components.
if (m_ifShowname.empty()) {
if (m_interface) {
m_traShowname = AstNode::vcdName(varp->name());
} else {
m_traShowname = AstNode::vcdName(scopep->name() + " " + varp->name());
if (m_traShowname.substr(0, 4) == "TOP ") m_traShowname.replace(0, 4, "");
} else {
m_traShowname = AstNode::vcdName(m_ifShowname + " " + varp->name());
}
UASSERT_OBJ(m_initSubFuncp, nodep, "NULL");
@@ -200,24 +245,6 @@ private:
iterate(nodep->subDTypep()->skipRefp());
}
}
virtual void visit(AstIfaceRefDType* nodep) {
if (m_traVscp && nodep->ifacep()) {
// Stash the signal state because we're going to go through another VARSCOPE
AstVarScope* traVscp = m_traVscp;
AstNode* traValuep = m_traValuep;
{
m_traVscp = NULL;
m_traValuep = NULL;
m_ifShowname = m_traShowname;
m_traShowname = "";
iterate(nodep->ifacep());
m_traShowname = m_ifShowname;
m_ifShowname = "";
}
m_traVscp = traVscp;
m_traValuep = traValuep;
}
}
virtual void visit(AstUnpackArrayDType* nodep) {
// Note more specific dtypes above
if (m_traVscp) {
@@ -346,6 +373,7 @@ public:
m_funcNum = 0;
m_traVscp = NULL;
m_traValuep = NULL;
m_interface = false;
iterate(nodep);
}
virtual ~TraceDeclVisitor() {
+3 -1
View File
@@ -292,6 +292,9 @@ private:
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->usedWhole();
}
if (nodep->valuep()) {
entryp->drivenWhole();
}
}
// Discover variables used in bit definitions, etc
iterateChildren(nodep);
@@ -372,7 +375,6 @@ private:
{
m_inProcAssign = true;
iterateChildren(nodep);
m_inProcAssign = false;
}
m_inProcAssign = prevProc;
}
+5 -1
View File
@@ -277,7 +277,7 @@ private:
if (initp) {
initp->unlinkFrBack(); // Always a single statement; nextp() may be nodep
// Don't add to list, we do it once, and setting loop index isn't
// needed as we're constant propagating it
// needed if we have > 1 loop, as we're constant propagating it
}
if (precondsp) {
precondsp->unlinkFrBackWithNext();
@@ -352,6 +352,10 @@ private:
}
}
}
if (!newbodysp) { // initp might have effects after the loop
newbodysp = initp; // Maybe NULL
initp = NULL;
}
// Replace the FOR()
if (newbodysp) nodep->replaceWith(newbodysp);
else nodep->unlinkFrBack();
+731 -395
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -151,6 +151,7 @@ private:
if (nodep->numeric().isNosign()) nodep->numeric(AstNumeric::UNSIGNED);
iterateChildren(nodep);
nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep()));
nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p()));
}
virtual void visit(AstNodePreSel* nodep) { // LCOV_EXCL_LINE
// This check could go anywhere after V3Param
+22
View File
@@ -91,6 +91,10 @@ private:
if (const AstNodeArrayDType* adtypep = VN_CAST(ddtypep, NodeArrayDType)) {
fromRange = adtypep->declRange();
}
else if (const AstAssocArrayDType* adtypep = VN_CAST(ddtypep, AssocArrayDType)) {
}
else if (const AstQueueDType* adtypep = VN_CAST(ddtypep, QueueDType)) {
}
else if (const AstNodeClassDType* adtypep = VN_CAST(ddtypep, NodeClassDType)) {
fromRange = adtypep->declRange();
}
@@ -246,6 +250,24 @@ private:
if (debug()>=9) newp->dumpTree(cout, "--SELBTn: ");
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
}
else if (AstAssocArrayDType* adtypep = VN_CAST(ddtypep, AssocArrayDType)) {
// SELBIT(array, index) -> ASSOCSEL(array, index)
AstNode* subp = rhsp;
AstAssocSel* newp = new AstAssocSel(nodep->fileline(),
fromp, subp);
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
if (debug()>=9) newp->dumpTree(cout, "--SELBTn: ");
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
}
else if (AstQueueDType* adtypep = VN_CAST(ddtypep, QueueDType)) {
// SELBIT(array, index) -> CMETHODCALL(queue, "at", index)
AstNode* subp = rhsp;
AstCMethodCall* newp = new AstCMethodCall(nodep->fileline(),
fromp, "at", subp);
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference
if (debug()>=9) newp->dumpTree(cout, "--SELBTq: ");
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
}
else if (VN_IS(ddtypep, BasicDType)) {
// SELBIT(range, index) -> SEL(array, index, 1)
AstSel* newp = new AstSel(nodep->fileline(),
+11 -6
View File
@@ -118,11 +118,11 @@ id [a-zA-Z_][a-zA-Z0-9_$]*
escid \\[^ \t\f\r\n]+
word [a-zA-Z0-9_]+
/* verilog numbers, constructed to not match the ' that begins a '( or '{ */
vnum1 [0-9]*?['']s?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]*
vnum2 [0-9]*?['']s?[01xXzZ]
vnum3 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]?[ \t\n]*[A-Fa-f0-9xXzZ_?]+
vnum4 [0-9][_0-9]*[ \t\n]*['']s?[bcodhBCODH]
vnum5 [0-9][_0-9]*[ \t\n]*['']s
vnum1 [0-9]*?[''][sS]?[bcodhBCODH][ \t\n]*[A-Fa-f0-9xXzZ_?]*
vnum2 [0-9]*?[''][sS]?[01xXzZ]
vnum3 [0-9][_0-9]*[ \t\n]*[''][sS]?[bcodhBCODH]?[ \t\n]*[A-Fa-f0-9xXzZ_?]+
vnum4 [0-9][_0-9]*[ \t\n]*[''][sS]?[bcodhBCODH]
vnum5 [0-9][_0-9]*[ \t\n]*[''][sS]
vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
%%
@@ -163,6 +163,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$atan2" { FL; return yD_ATAN2; }
"$atanh" { FL; return yD_ATANH; }
"$bitstoreal" { FL; return yD_BITSTOREAL; }
"$bitstoshortreal" { FL; return yD_BITSTOSHORTREAL; }
"$ceil" { FL; return yD_CEIL; }
"$cos" { FL; return yD_COS; }
"$cosh" { FL; return yD_COSH; }
@@ -200,11 +201,13 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$recovery" { FL; return yaTIMINGSPEC; }
"$recrem" { FL; return yaTIMINGSPEC; }
"$removal" { FL; return yaTIMINGSPEC; }
"$rewind" { FL; return yD_REWIND; }
"$rtoi" { FL; return yD_RTOI; }
"$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yaTIMINGSPEC; }
"$sformat" { FL; return yD_SFORMAT; }
"$sformatf" { FL; return yD_SFORMATF; }
"$shortrealtobits" { FL; return yD_SHORTREALTOBITS; }
"$sin" { FL; return yD_SIN; }
"$sinh" { FL; return yD_SINH; }
"$skew" { FL; return yaTIMINGSPEC; }
@@ -219,6 +222,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
"$time" { FL; return yD_TIME; }
"$timeskew" { FL; return yaTIMINGSPEC; }
"$ungetc" { FL; return yD_UNGETC; }
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
"$width" { FL; return yaTIMINGSPEC; }
"$write" { FL; return yD_WRITE; }
@@ -453,7 +457,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"return" { FL; return yRETURN; }
"shortint" { FL; return ySHORTINT; }
"shortreal" { FL; return ySHORTREAL; }
"static" { FL; return ySTATIC; }
"static" { FL; return ySTATIC__ETC; }
"string" { FL; return ySTRING; }
"struct" { FL; return ySTRUCT; }
"timeprecision" { FL; return yTIMEPRECISION; }
@@ -1023,6 +1027,7 @@ void V3ParseImp::lexToken() {
}
else if (token == yGLOBAL__LEX) {
if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
else if (v3Global.opt.pedantic()) token = yGLOBAL__ETC;
// Avoid 2009 "global" conflicting with old code when we can
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); }
}
+35 -21
View File
@@ -106,7 +106,7 @@ public:
}
AstDisplay* createDisplayError(FileLine* fileline) {
AstDisplay* nodep = new AstDisplay(fileline,AstDisplayType::DT_ERROR, "", NULL,NULL);
nodep->addNext(new AstStop(fileline));
nodep->addNext(new AstStop(fileline, true));
return nodep;
}
AstNode* createGatePin(AstNode* exprp) {
@@ -224,6 +224,10 @@ static void ERRSVKWD(FileLine* fileline, const string& tokname) {
: ""));
}
static void UNSUPREAL(FileLine* fileline) {
fileline->v3warn(SHORTREAL, "Unsupported: shortreal being promoted to real (suggest use real instead)");
}
//======================================================================
class AstSenTree;
@@ -383,6 +387,7 @@ class AstSenTree;
%token<fl> yGENERATE "generate"
%token<fl> yGENVAR "genvar"
%token<fl> yGLOBAL__CLOCKING "global-then-clocking"
%token<fl> yGLOBAL__ETC "global"
%token<fl> yGLOBAL__LEX "global-in-lex"
%token<fl> yIF "if"
%token<fl> yIFF "iff"
@@ -445,7 +450,7 @@ class AstSenTree;
%token<fl> ySIGNED "signed"
%token<fl> ySPECIFY "specify"
%token<fl> ySPECPARAM "specparam"
%token<fl> ySTATIC "static"
%token<fl> ySTATIC__ETC "static"
%token<fl> ySTRING "string"
%token<fl> ySTRUCT "struct"
%token<fl> ySUPPLY0 "supply0"
@@ -492,6 +497,7 @@ class AstSenTree;
%token<fl> yD_ATANH "$atanh"
%token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_BITSTOSHORTREAL "$bitstoshortreal"
%token<fl> yD_C "$c"
%token<fl> yD_CEIL "$ceil"
%token<fl> yD_CLOG2 "$clog2"
@@ -537,10 +543,12 @@ class AstSenTree;
%token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_REWIND "$rewind"
%token<fl> yD_RIGHT "$right"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SFORMATF "$sformatf"
%token<fl> yD_SHORTREALTOBITS "$shortrealtobits"
%token<fl> yD_SIGNED "$signed"
%token<fl> yD_SIN "$sin"
%token<fl> yD_SINH "$sinh"
@@ -555,6 +563,7 @@ class AstSenTree;
%token<fl> yD_TANH "$tanh"
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_UNGETC "$ungetc"
%token<fl> yD_UNIT "$unit"
%token<fl> yD_UNPACKED_DIMENSIONS "$unpacked_dimensions"
%token<fl> yD_UNSIGNED "$unsigned"
@@ -1422,8 +1431,7 @@ integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
non_integer_type<bdtypep>: // ==IEEE: non_integer_type
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| ySHORTREAL { BBUNSUP($1, "Unsupported: shortreal (use real instead)");
$$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); UNSUPREAL($1); }
;
signingE<signstate>: // IEEE: signing - plus empty
@@ -1617,13 +1625,15 @@ variable_dimension<rangep>: // ==IEEE: variable_dimension
'[' ']' { $$ = new AstUnsizedRange($1); }
// // IEEE: unpacked_dimension
| anyrange { $$ = $1; }
| '[' constExpr ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstSub($1, $2, new AstConst($1, 1))); }
| '[' constExpr ']' { if (VN_IS($2, Unbounded)) { $2->deleteTree(); $$ = new AstQueueRange($1); }
else { $$ = new AstRange($1, new AstConst($1, 0),
new AstSub($1, $2, new AstConst($1, 1))); } }
// // IEEE: associative_dimension
//UNSUP '[' data_type ']' { UNSUP }
//UNSUP yP_BRASTAR ']' { UNSUP }
//UNSUP '[' '*' ']' { UNSUP }
| '[' data_type ']' { $$ = new AstAssocRange($1, $2); }
| yP_BRASTAR ']' { $$ = NULL; v3error("Unsupported: [*] wildcard associative arrays"); }
| '[' '*' ']' { $$ = NULL; v3error("Unsupported: [*] wildcard associative arrays"); }
// // IEEE: queue_dimension
// // '[' '$' ']' -- $ is part of expr
// // '[' '$' ']' -- $ is part of expr, see '[' constExpr ']'
// // '[' '$' ':' expr ']' -- anyrange:expr:$
;
@@ -1747,7 +1757,7 @@ type_declaration<nodep>: // ==IEEE: type_declaration
yTYPEDEF data_type idAny variable_dimensionListE dtypeAttrListE ';'
/**/ { $$ = new AstTypedef($<fl>3, *$3, $5, VFlagChildDType(), GRAMMARP->createArray($2,$4,false));
SYMP->reinsert($$); PARSEP->tagNodep($$); }
//UNSUP yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; $1->v3error("Unsupported: SystemVerilog 2005 typedef in this context"); } //UNSUP
| yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; BBUNSUP($1, "Unsupported: SystemVerilog 2005 typedef in this context"); }
// // Combines into above "data_type id" rule
// // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned
| yTYPEDEF id ';' { $$ = NULL; $$ = new AstTypedefFwd($<fl>2, *$2); SYMP->reinsert($$); PARSEP->tagNodep($$); }
@@ -2729,6 +2739,7 @@ patternKey<nodep>: // IEEE: merge structure_pattern_key, array_pattern_key, ass
yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
| yaID__ETC { $$ = new AstText($<fl>1,*$1); }
| strAsInt { $$ = $1; }
;
assignment_pattern<patternp>: // ==IEEE: assignment_pattern
@@ -2847,8 +2858,8 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); }
| yD_FINISH parenE { $$ = new AstFinish($1); }
| yD_FINISH '(' expr ')' { $$ = new AstFinish($1); DEL($3); }
| yD_STOP parenE { $$ = new AstStop($1); }
| yD_STOP '(' expr ')' { $$ = new AstStop($1); DEL($3); }
| yD_STOP parenE { $$ = new AstStop($1, false); }
| yD_STOP '(' expr ')' { $$ = new AstStop($1, false); DEL($3); }
//
| yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
| yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
@@ -2865,10 +2876,10 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, NULL); }
| yD_WARNING '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, $3); }
| yD_ERROR parenE { $$ = GRAMMARP->createDisplayError($1); }
| yD_ERROR '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, NULL, $3); $$->addNext(new AstStop($1)); }
| yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1)); DEL($3); }
| yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, $5); $$->addNext(new AstStop($1)); DEL($3); }
| yD_ERROR '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, NULL, $3); $$->addNext(new AstStop($1, true)); }
| yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); }
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); DEL($3); }
| yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, $5); $$->addNext(new AstStop($1, false)); DEL($3); }
//
| yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
@@ -2909,6 +2920,7 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_BITS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
| yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
| yD_BITSTOSHORTREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); UNSUPREAL($1); }
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COS '(' expr ')' { $$ = new AstCosD($1,$3); }
@@ -2951,10 +2963,12 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_RANDOM parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
| yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); }
| yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); }
| yD_RIGHT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); }
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); }
| yD_SHORTREALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); UNSUPREAL($1); }
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_SIN '(' expr ')' { $$ = new AstSinD($1,$3); }
| yD_SINH '(' expr ')' { $$ = new AstSinhD($1,$3); }
@@ -2967,6 +2981,7 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); }
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
| yD_TIME parenE { $$ = new AstTime($1); }
| yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first
| yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
| yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1,$3,$5); }
@@ -3045,7 +3060,7 @@ lifetimeE: // IEEE: [lifetime]
lifetime: // ==IEEE: lifetime
// // Note lifetime used by members is instead under memberQual
ySTATIC { $1->v3error("Unsupported: Static in this context"); }
ySTATIC__ETC { BBUNSUP($1, "Unsupported: Static in this context"); }
| yAUTOMATIC { }
;
@@ -3349,10 +3364,9 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// // IEEE: sequence_method_call
// // Indistinguishable from function_subroutine_call:method_call
//
| '$' { $$ = new AstConst($<fl>1, AstConst::LogicFalse());
$<fl>1->v3error("Unsupported: $ expression"); }
| '$' { $$ = new AstUnbounded($<fl>1); }
| yNULL { $$ = new AstConst($1, AstConst::LogicFalse());
$<fl>1->v3error("Unsupported: null expression"); }
BBUNSUP($<fl>1, "Unsupported: null expression"); }
// // IEEE: yTHIS
// // See exprScope
//
@@ -3366,7 +3380,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// // IEEE: cond_predicate - here to avoid reduce problems
// // Note expr includes cond_pattern
| ~l~expr yP_ANDANDAND ~r~expr { $$ = new AstConst($2, AstConst::LogicFalse());
$<fl>2->v3error("Unsupported: &&& expression"); }
BBUNSUP($<fl>2, "Unsupported: &&& expression"); }
//
// // IEEE: cond_pattern - here to avoid reduce problems
// // "expr yMATCHES pattern"
+15 -3
View File
@@ -110,7 +110,7 @@ if (! GetOptions(
"atsim|athdl!"=> sub { $opt_scenarios{atsim} = $_[1]; },
"dist!" => sub { $opt_scenarios{dist} = $_[1]; },
"ghdl!" => sub { $opt_scenarios{ghdl} = $_[1]; },
"iverilog!" => sub { $opt_scenarios{iverilog} = $_[1]; },
"iv!" => sub { $opt_scenarios{iv} = $_[1]; },
"ms!" => sub { $opt_scenarios{ms} = $_[1]; },
"nc!" => sub { $opt_scenarios{nc} = $_[1]; },
"vlt!" => sub { $opt_scenarios{vlt} = $_[1]; },
@@ -585,6 +585,7 @@ sub new {
ms => 0,
ms_flags => [split(/\s+/,("-sv -work $self->{obj_dir}/work"))],
ms_flags2 => [], # Overridden in some sim files
ms_pli => 1, # need to use pli
ms_run_flags => [split(/\s+/,"-lib $self->{obj_dir}/work -c -do 'run -all;quit' ")],
# XSim
xsim => 0,
@@ -1152,11 +1153,16 @@ sub execute {
);
}
elsif ($param{ms}) {
my @pli_opt=();
if ($param{ms_pli}) {
unshift @pli_opt, "-pli $self->{obj_dir}/libvpi.so";
}
$self->_run(logfile=>"$self->{obj_dir}/ms_sim.log",
fails=>$param{fails},
cmd=>["echo q | ".$run_env.($ENV{VERILATOR_MODELSIM}||"vsim"),
@{$param{ms_run_flags}},
@{$param{all_run_flags}},
@{pli_opt},
(" top")
],
%param,
@@ -1455,7 +1461,13 @@ sub _run {
autoflush STDOUT 1;
autoflush STDERR 1;
system "$command";
exit($? ? 10 : 0); # $?<<8 misses coredumps
my $status = $?;
if (($status & 127) == 4 # SIGILL
|| ($status & 127) == 8 # SIGFPA
|| ($status & 127) == 11) { # SIGSEGV
$Self->error("Exec failed with core dump");
}
exit($? ? 10 : 0); # $?>>8 misses coredumps
}
waitpid($pid,0);
$status = $? || 0;
@@ -1466,7 +1478,7 @@ sub _run {
if (!$param{fails} && $status) {
my $firstline = "";
if (my $fh = IO::File->new("<$param{logfile}")) {
$firstline = $fh->getline;
$firstline = $fh->getline || '';
chomp $firstline;
}
$self->error("Exec of $param{cmd}[0] failed: $firstline\n");
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
);
ok(1);
1;
+63
View File
@@ -0,0 +1,63 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
//bug1604
module t (/*AUTOARG*/
// Outputs
two,
// Inputs
clk, aresetn, ten
);
input wire clk;
input wire aresetn;
input reg [9:0] ten;
output reg [1:0] two;
// Passes with this
//output reg [1:0] rx;
//output reg [1:0] ry;
function [1:0] func
(
input [1:0] p0_x,
input [1:0] p0_y,
input [1:0] p1_x,
input [1:0] p1_y,
input [1:0] sel);
reg [1:0] rx;
reg [1:0] ry;
`ifdef NOT_DEF
// This way works
rx = sel == 2'b10 ? p1_x : p0_x;
ry = sel == 2'b10 ? p1_y : p0_y;
`else
// This way fails to compile
if (sel == 2'b10) begin
rx = p1_x;
ry = p1_y;
end
else begin
rx = p0_x;
ry = p0_y;
end
`endif
// Note rx and ry are unused
//func = rx | ry; // Also passes
func = 0;
endfunction
always @(*) begin
two = func(
ten[8 +: 2],
ten[6 +: 2],
ten[4 +: 2],
ten[2 +: 2],
ten[0 +: 2]);
end
endmodule
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;
+104
View File
@@ -0,0 +1,104 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checkg(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%g' exp='%g'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
integer i;
always @ (posedge clk) begin
cyc <= cyc + 1;
begin
// Type
typedef bit [3:0] nibble_t;
string a [nibble_t];
string b [nibble_t];
nibble_t k;
string v;
a[4'd3] = "fooed";
a[4'd2] = "bared";
i = a.num(); `checkh(i, 2);
i = a.size; `checkh(i, 2); // Also checks no parens
v = a[4'd3]; `checks(v, "fooed");
v = a[4'd2]; `checks(v, "bared");
i = a.exists(4'd0); `checkh(i, 0);
i = a.exists(4'd2); `checkh(i, 1);
i = a.first(k); `checkh(i, 1); `checks(k, 4'd2);
i = a.next(k); `checkh(i, 1); `checks(k, 4'd3);
i = a.next(k); `checkh(i, 0);
i = a.last(k); `checkh(i, 1); `checks(k, 4'd3);
i = a.prev(k); `checkh(i, 1); `checks(k, 4'd2);
i = a.prev(k); `checkh(i, 0);
v = $sformatf("%p", a); `checks(v, "'{'h2:\"bared\", 'h3:\"fooed\"} ");
a.delete(4'd2);
i = a.size(); `checkh(i, 1);
b = a; // Copy assignment
i = b.size(); `checkh(i, 1);
end
begin
// Strings
string a [string];
string k;
string v;
a["foo"] = "fooed";
a["bar"] = "bared";
i = a.num(); `checkh(i, 2);
i = a.size(); `checkh(i, 2);
v = a["foo"]; `checks(v, "fooed");
v = a["bar"]; `checks(v, "bared");
i = a.exists("baz"); `checkh(i, 0);
i = a.exists("bar"); `checkh(i, 1);
i = a.first(k); `checkh(i, 1); `checks(k, "bar");
i = a.next(k); `checkh(i, 1); `checks(k, "foo");
i = a.next(k); `checkh(i, 0);
i = a.last(k); `checkh(i, 1); `checks(k, "foo");
i = a.prev(k); `checkh(i, 1); `checks(k, "bar");
i = a.prev(k); `checkh(i, 0);
v = $sformatf("%p", a["foo"]); `checks(v, "\"fooed\"");
v = $sformatf("%p", a); `checks(v, "'{\"bar\":\"bared\", \"foo\":\"fooed\"} ");
a.delete("bar");
i = a.size(); `checkh(i, 1);
a.delete();
i = a.size(); `checkh(i, 0);
i = a.first(k); `checkh(i, 0);
i = a.last(k); `checkh(i, 0);
// Patterns & default
`ifndef VERILATOR // Unsupported: Pattern assignment
a = '{ "f": "fooed", "b": "bared", default: "defaulted" };
i = a.size(); `checkh(i, 2); // Default doesn't count
v = a["f"]; `checks(v, "fooed");
v = a["b"]; `checks(v, "bared");
v = a["NEXISTS"]; `checks(v, "defaulted");
`endif
end
begin
// Wide-wides - need special array container classes, ick.
logic [91:2] a [ logic [65:1] ];
a[~65'hfe] = ~ 90'hfee;
`checkh(a[~65'hfe], ~ 90'hfee);
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+37
View File
@@ -0,0 +1,37 @@
%Error: t/t_assoc_meth_bad.v:13: The 1 arguments passed to .num method does not match its requiring 0 arguments
: ... In instance t
v = a.num("badarg");
^~~
%Error: t/t_assoc_meth_bad.v:14: The 1 arguments passed to .size method does not match its requiring 0 arguments
: ... In instance t
v = a.size("badarg");
^~~~
%Error: t/t_assoc_meth_bad.v:15: The 0 arguments passed to .exists method does not match its requiring 1 arguments
: ... In instance t
v = a.exists();
^~~~~~
%Error: t/t_assoc_meth_bad.v:16: The 2 arguments passed to .exists method does not match its requiring 1 arguments
: ... In instance t
v = a.exists(k, "bad2");
^~~~~~
%Error: t/t_assoc_meth_bad.v:17: The 0 arguments passed to .first method does not match its requiring 1 arguments
: ... In instance t
v = a.first();
^~~~~
%Error: t/t_assoc_meth_bad.v:18: The 2 arguments passed to .next method does not match its requiring 1 arguments
: ... In instance t
v = a.next(k, "bad2");
^~~~
%Error: t/t_assoc_meth_bad.v:19: The 0 arguments passed to .last method does not match its requiring 1 arguments
: ... In instance t
v = a.last();
^~~~
%Error: t/t_assoc_meth_bad.v:20: The 2 arguments passed to .prev method does not match its requiring 1 arguments
: ... In instance t
v = a.prev(k, "bad2");
^~~~
%Error: t/t_assoc_meth_bad.v:21: The 2 arguments passed to .delete method does not match its requiring 0 to 1 arguments
: ... In instance t
a.delete(k, "bad2");
^~~~~~
%Error: Exiting due to
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
+23
View File
@@ -0,0 +1,23 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t (/*AUTOARG*/);
initial begin
string a [string];
string k;
string v;
v = a.num("badarg");
v = a.size("badarg");
v = a.exists(); // Bad
v = a.exists(k, "bad2");
v = a.first(); // Bad
v = a.next(k, "bad2"); // Bad
v = a.last(); // Bad
v = a.prev(k, "bad2"); // Bad
a.delete(k, "bad2");
end
endmodule
+5
View File
@@ -0,0 +1,5 @@
%Error: t/t_assoc_pattern_unsup.v:18: Unsupported: Assignment pattern applies against non struct/union: ASSOCARRAYDTYPE
: ... In instance t
a = '{ "f": "fooed", "b": "bared", default: "defaulted" };
^~
%Error: Exiting due to
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
+27
View File
@@ -0,0 +1,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checkg(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%g' exp='%g'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
module t (/*AUTOARG*/);
initial begin
int i;
string a [string];
string k;
string v;
a = '{ "f": "fooed", "b": "bared", default: "defaulted" };
i = a.size(); `checkh(i, 2); // Default doesn't count
v = a["f"]; `checks(v, "fooed");
v = a["b"]; `checks(v, "bared");
v = a["NEXISTS"]; `checks(v, "defaulted");
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
@@ -0,0 +1,2 @@
%Error: Unsupported: [*] wildcard associative arrays
%Error: Exiting due to
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
+49
View File
@@ -0,0 +1,49 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`define checkg(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%g' exp='%g'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
integer i;
always @ (posedge clk) begin
cyc <= cyc + 1;
begin
// Wildcard
string a [*];
int k;
string v;
a[32'd1234] = "fooed";
a[4'd3] = "bared";
i = a.num(); `checkh(i, 2);
i = a.size(); `checkh(i, 2);
v = a[32'd1234]; `checks(v, "fooed");
v = a[4'd3]; `checks(v, "bared");
i = a.exists("baz"); `checkh(i, 0);
i = a.exists(4'd3); `checkh(i, 1);
i = a.first(k); `checkh(i, 1); `checks(k, 4'd3);
i = a.next(k); `checkh(i, 1); `checks(k, 32'd1234);
i = a.next(k); `checkh(i, 0);
i = a.last(k); `checkh(i, 1); `checks(k, 32'd1234);
i = a.prev(k); `checkh(i, 1); `checks(k, 4'd3);
i = a.prev(k); `checkh(i, 0);
a.delete(4'd3);
i = a.size(); `checkh(i, 1);
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
verilator_flags2 => ['-Wall -Wno-DECLFILENAME --coverage-line'],
);
ok(1);
1;
+51
View File
@@ -0,0 +1,51 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t
(/*AUTOARG*/
// Outputs
someOutput,
// Inputs
clk, reset_l, InOne, InTwo
);
input clk;
input reset_l;
input InOne, InTwo;
output logic someOutput;
typedef enum {
STATE_ONE,
STATE_TWO,
STATE_THREE,
STATE_FOUR
} some_state_t;
some_state_t some_FSM;
always_ff @ (posedge clk or negedge reset_l) begin
if(!reset_l)
some_FSM <= some_FSM.first;
else begin
unique case (some_FSM)
STATE_ONE, STATE_TWO, STATE_THREE: begin
if(InOne & InTwo)
some_FSM <= some_FSM.next;
else if(InOne)
some_FSM <= some_FSM;
else
some_FSM <= some_FSM.first;
end
default: begin
some_FSM <= STATE_ONE;
end
endcase
end
end
always_comb begin
someOutput = (some_FSM == STATE_FOUR);
end
endmodule
+14
View File
@@ -0,0 +1,14 @@
%Error: t/t_concat_link_bad.v:24: Syntax Error: Not expecting REPLICATE under a DOT in dotted expression
assign bar_s = {foo_s, foo_s}.f1;
^
%Error: t/t_concat_link_bad.v:24: Syntax Error: Not expecting CONCAT under a REPLICATE in dotted expression
assign bar_s = {foo_s, foo_s}.f1;
^
%Error: t/t_concat_link_bad.v:24: Syntax Error: Not expecting CONST under a REPLICATE in dotted expression
assign bar_s = {foo_s, foo_s}.f1;
^
%Warning-IMPLICIT: t/t_concat_link_bad.v:24: Signal definition not found, creating implicitly: 'bar_s'
assign bar_s = {foo_s, foo_s}.f1;
^~~~~
... Use "/* verilator lint_off IMPLICIT */" and lint_on around source to disable this message.
%Error: Exiting due to
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
+26
View File
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Use this file as a template for submitting bugs, etc.
// This module takes a single clock input, and should either
// $write("*-* All Finished *-*\n");
// $finish;
// on success, or $stop.
//
// The code as shown applies a random vector to the Test
// module, then calculates a CRC on the Test module's outputs.
//
// **If you do not wish for your code to be released to the public
// please note it here, otherwise:**
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by ____YOUR_NAME_HERE____.
module t (/*AUTOARG*/);
typedef logic [3:0] foo_t;
foo_t foo_s;
assign bar_s = {foo_s, foo_s}.f1;
endmodule
+2 -2
View File
@@ -32,8 +32,8 @@
[0] %c=m %0c=m
[0] %v=St0 St0 St0 St0 St0 St1 St1 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St1 St0 St0 %v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 <
[0] %V=St0 St0 St0 St0 St0 St1 St1 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St1 St0 St0 %V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 <
[0] %p='hc %0p='hc %p='habbbbcccc %0p='habbbbcccc %p='habc1234567812345678 %0p='habc1234567812345678
[0] %P='hc %0P='hc %P='habbbbcccc %0P='habbbbcccc %P='habc1234567812345678 %0P='habc1234567812345678
[0] %p= 12 %0p='hc %p= 46099320012 %0p='habbbbcccc %p= 50692964483019020981880 %0p='habc1234567812345678
[0] %P= 12 %0P='hc %P= 46099320012 %0P='habbbbcccc %P= 50692964483019020981880 %0P='habc1234567812345678
[0] %P="sv-str"
[0] %u=dcba %0u=dcba
[0] %U=dcba %0U=dcba
+15 -15
View File
@@ -1,22 +1,22 @@
[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00 p=0
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00 p=0
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00 p=0
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00 p=1
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00 p=1
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00 p=1
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01 p=0.1
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01 p=0.1
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01 p=0.1
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15 p=1.2345e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15 p=1.2345e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15 p=1.2345e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15 p=2.579e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15 p=2.579e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15 p=2.579e+15
r8= 3 n1=1 n2=0.1
n1=1 n2=0.1 r8= 3
+15 -15
View File
@@ -13,25 +13,25 @@ module t;
initial begin
// Display formatting
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e p=%p", $time, n0,n0,n0,n0,n0);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e p=%p", $time, n0,n0,n0,n0,n0);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e p=%p", $time, n0,n0,n0,n0,n0);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e p=%p", $time, n1,n1,n1,n1,n1);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e p=%p", $time, n1,n1,n1,n1,n1);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e p=%p", $time, n1,n1,n1,n1,n1);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e p=%p", $time, n2,n2,n2,n2,n2);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e p=%p", $time, n2,n2,n2,n2,n2);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e p=%p", $time, n2,n2,n2,n2,n2);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e p=%p", $time, n3,n3,n3,n3,n3);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e p=%p", $time, n3,n3,n3,n3,n3);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e p=%p", $time, n3,n3,n3,n3,n3);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e p=%p", $time, n4,n4,n4,n4,n4);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e p=%p", $time, n4,n4,n4,n4,n4);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e p=%p", $time, n4,n4,n4,n4,n4);
$display;
$display("r8=%d n1=%g n2=%g", r8, n1, n2);
$display("n1=%g n2=%g r8=%d", n1, n2, r8);
+6 -6
View File
@@ -1,8 +1,8 @@
[0] lp %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228
[0] ln %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348
[0] qp %x=001bbbbcccc %x=001bbbbcccc %o=00067356746314 %b=00000000110111011101110111100110011001100 %0d=7444614348 %d= 7444614348
[0] qn %x=101bbbbcccc %x=101bbbbcccc %o=20067356746314 %b=10000000110111011101110111100110011001100 %0d=-1092067013428 %d=-1092067013428
[0] wp %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000
[0] wn %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000
[0] lp %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228 %p= 769228 %0p='hbbccc
[0] ln %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348 %p=1817804 %0p='h1bbccc
[0] qp %x=001bbbbcccc %x=001bbbbcccc %o=00067356746314 %b=00000000110111011101110111100110011001100 %0d=7444614348 %d= 7444614348 %p= 7444614348 %0p='h1bbbbcccc
[0] qn %x=101bbbbcccc %x=101bbbbcccc %o=20067356746314 %b=10000000110111011101110111100110011001100 %0d=-1092067013428 %d=-1092067013428 %p=1106956242124 %0p='h101bbbbcccc
[0] wp %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000 %p= 3469299654322568844920 %0p='hbc1234567812345678
[0] wn %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000 %p= 3469299655422080472696 %0p='hbc1234577812345678
*-* All Finished *-*
+12 -12
View File
@@ -13,18 +13,18 @@ module t;
initial begin
// Display formatting
$display("[%0t] lp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
longp, longp, longp, longp, longp, longp);
$display("[%0t] ln %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
longn, longn, longn, longn, longn, longn);
$display("[%0t] qp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
quadp, quadp, quadp, quadp, quadp, quadp);
$display("[%0t] qn %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
quadn, quadn, quadn, quadn, quadn, quadn);
$display("[%0t] wp %%x=%x %%x=%x %%o=%o %%b=%b", $time,
widep, widep, widep, widep);
$display("[%0t] wn %%x=%x %%x=%x %%o=%o %%b=%b", $time,
widen, widen, widen, widen);
$display("[%0t] lp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d %%p=%p %%0p=%0p",
$time, longp, longp, longp, longp, longp, longp, longp, longp);
$display("[%0t] ln %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d %%p=%p %%0p=%0p",
$time, longn, longn, longn, longn, longn, longn, longn, longn);
$display("[%0t] qp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d %%p=%p %%0p=%0p",
$time, quadp, quadp, quadp, quadp, quadp, quadp, quadp, quadp);
$display("[%0t] qn %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d %%p=%p %%0p=%0p",
$time, quadn, quadn, quadn, quadn, quadn, quadn, quadn, quadn);
$display("[%0t] wp %%x=%x %%x=%x %%o=%o %%b=%b %%p=%p %%0p=%0p",
$time, widep, widep, widep, widep, widep, widep);
$display("[%0t] wn %%x=%x %%x=%x %%o=%o %%b=%b %%p=%p %%0p=%0p",
$time, widen, widen, widen, widen, widen, widen);
$display;
$write("*-* All Finished *-*\n");
$finish;
+1 -1
View File
@@ -1,3 +1,3 @@
default: [0.000] 0t time [ 0.000] No0 time
default: [10.000] 0t time [ 10.000] No0 time p= 10000 0p='h2710
*-* All Finished *-*
+28 -16
View File
@@ -5,23 +5,35 @@
`timescale 1ns/1ns
module t;
initial begin
// Display formatting
$write; // Check missing arguments work
$write("default: [%0t] 0t time [%t] No0 time\n",$time,$time);
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
always @ (posedge clk) begin
if ($time >= 10) begin
// Display formatting
$write; // Check missing arguments work
$write("default: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
`ifndef verilator // Unsupported
$timeformat(-9, 0, "", 0);
$write("-9,0,,0: [%0t] 0t time [%t] No0 time\n",$time,$time);
$timeformat(-9, 0, "", 10);
$write("-9,0,,10: [%0t] 0t time [%t] No0 time\n",$time,$time);
$timeformat(-9, 0, "ns", 5);
$write("-9,0,ns,5: [%0t] 0t time [%t] No0 time\n",$time,$time);
$timeformat(-9, 3, "ns", 8);
$write("-9,3,ns,8: [%0t] 0t time [%t] No0 time\n",$time,$time);
$timeformat(-9, 0, "", 0);
$write("-9,0,,0: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat(-9, 0, "", 10);
$write("-9,0,,10: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat(-9, 0, "ns", 5);
$write("-9,0,ns,5: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat(-9, 3, "ns", 8);
$write("-9,3,ns,8: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
`endif
$write("\n");
$write("*-* All Finished *-*\n");
$finish;
$write("\n");
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+4
View File
@@ -35,6 +35,10 @@ extern "C" {
}
#endif
#ifndef VL_PRINTF
# define VL_PRINTF printf
#endif
//======================================================================
void dpii_display_call(const char* c) {
+6
View File
@@ -0,0 +1,6 @@
%Warning-WIDTH: t/t_flag_context_bad.v:8: Operator ASSIGNW expects 3 bits on the Assign RHS, but Assign RHS's CONST '5'h1f' generates 5 bits.
: ... In instance t
... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.
%Warning-UNUSED: t/t_flag_context_bad.v:8: Signal is not used: 'foo'
: ... In instance t
%Error: Exiting due to
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt => 1);
lint(
verilator_flags2 => ["-Wall -Wno-DECLFILENAME -Wno-context"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
+10
View File
@@ -0,0 +1,10 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t (/*AUTOARG*/);
wire [2:0] foo = 5'b11111;
endmodule
+2 -1
View File
@@ -1,6 +1,7 @@
// Test that environment substitutions work
-f $VERILATOR_ROOT/test_regress/t/t_flag_f__2.vc
// Env var with .v file, and parens
${VERILATOR_ROOT}/test_regress/t/t_flag_f__3.v
// Double slash below is intentional, as allowed in other tools
${VERILATOR_ROOT}/test_regress/t//t_flag_f__3.v
// Test -f
-F $VERILATOR_ROOT/test_regress/t/tsub/t_flag_f_tsub.vc
+4
View File
@@ -0,0 +1,4 @@
%Error: t/t_flag_wpedantic_bad.v:7: syntax error, unexpected global, expecting IDENTIFIER or do or final
reg global;
^
%Error: Exiting due to
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(vlt => 1);
lint(
verilator_flags2 => ["-Wpedantic"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
+8
View File
@@ -0,0 +1,8 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t (/*AUTOARG*/);
reg global;
endmodule
+7
View File
@@ -94,6 +94,13 @@ module t (/*AUTOARG*/
for (; ; ++i) begin ++loops; break; end
if (loops !== 1) $stop;
//
// bug1605
i = 1;
for (i=20; 0; ) ;
if (i != 20) $stop;
for (i=30; i<10; i++) ;
if (i != 30) $stop;
//
$write("*-* All Finished *-*\n");
$finish;
end
+13
View File
@@ -12,6 +12,9 @@ module t (/*AUTOARG*/
ma ma0 ();
initial t.ma0.u_b[0].f(1);
initial t.ma0.u_b[0].f(clk);
global_mod #(32'hf00d) global_cell ();
global_mod #(32'hf22d) global_cell2 ();
@@ -138,3 +141,13 @@ module mc ();
mc.checkName (mc.getName(1'b0));
end
endmodule
module b;
function void f(bit v);
$display("%m");
endfunction : f;
endmodule : b
bind ma b u_b[0:1];
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
);
ok(1);
1;
+27
View File
@@ -0,0 +1,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
function automatic integer min(input integer a, input integer b);
return (a < b) ? a : b;
endfunction
module t
#(parameter A=16, parameter B=8)
(/*AUTOARG*/
// Outputs
c,
// Inputs
a, b
);
input [A-1:0] a;
input [B-1:0] b;
output logic [min(A,B)-1:0] c;
always_comb
for (int i = 0; i < min(A,B); i++)
assign c[i] = a[i] | b[i];
endmodule
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;
+65
View File
@@ -0,0 +1,65 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Driss Hafdi.
module t (/*AUTOARG*/
// Inputs
clk, rst
);
input clk;
input rst;
logic [2:0] ctrl_inc_single;
logic [2:0] ctrl_inc_double;
logic [2:0] cnt_single;
always_ff @(posedge clk) begin
if (rst) begin
cnt_single <= '0;
end
else if (ctrl_inc_single != '0 && cnt_single != '1) begin
cnt_single <= cnt_single + 1'd1;
end
end
logic [2:0] cnt_double;
always_ff @(posedge clk) begin
if (rst) begin
cnt_double <= '0;
end
else if (ctrl_inc_double != '0 && cnt_double != '1) begin
cnt_double <= cnt_double + 1'd1;
end
end
always_comb ctrl_inc_single = '0;
always_comb ctrl_inc_double = '0;
testMod test_i (.data_i(cnt_single));
testMod test_j (.data_i(cnt_double));
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
module testMod
(input wire [2:0] data_i);
typedef logic [63:0] time_t;
time_t [2:0] last_transition;
genvar b;
generate
for (b = 0; b <= 2; b++) begin : gen_trans
always_ff @(posedge data_i[b] or negedge data_i[b]) begin
last_transition[b] <= $time;
end
end
endgenerate
endmodule
+4 -18
View File
@@ -22,34 +22,20 @@ module t (/*AUTOARG*/
ifc itop();
sub c1 (.isub(itop),
.i_value(cyc));
sub2 c2 (.isub2(itop),
.i_value(cyc));
always @(*) itop.hidden_from_isub = cyc + 1;
.i_value(4));
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc==20) begin
if (itop.value != 20) $stop;
if (itop.hidden_from_isub != 21) $stop;
if (itop.value != 4) $stop;
itop.hidden_from_isub = 20;
if (itop.hidden_from_isub != 20) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module sub2
(
ifc.out_modport isub2,
input integer i_value
);
sub c3 (.isub(isub2),
.i_value(i_value));
endmodule
module sub
`ifdef NANSI // bug868
(
@@ -1,183 +0,0 @@
$version Generated by VerilatedVcd $end
$date Thu Nov 7 18:07:03 2019
$end
$timescale 1ns $end
$scope module top $end
$var wire 1 & clk $end
$scope module t $end
$var wire 1 & clk $end
$var wire 32 # cyc [31:0] $end
$scope module c1 $end
$var wire 32 # i_value [31:0] $end
$scope module isub $end
$var wire 32 $ hidden_from_isub [31:0] $end
$var wire 32 % value [31:0] $end
$upscope $end
$upscope $end
$scope module c2 $end
$var wire 32 # i_value [31:0] $end
$scope module c3 $end
$var wire 32 # i_value [31:0] $end
$scope module isub $end
$var wire 32 $ hidden_from_isub [31:0] $end
$var wire 32 % value [31:0] $end
$upscope $end
$upscope $end
$scope module isub2 $end
$var wire 32 $ hidden_from_isub [31:0] $end
$var wire 32 % value [31:0] $end
$upscope $end
$upscope $end
$scope module itop $end
$var wire 32 $ hidden_from_isub [31:0] $end
$var wire 32 % value [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
b00000000000000000000000000000001 #
b00000000000000000000000000000010 $
b00000000000000000000000000000001 %
0&
#10
b00000000000000000000000000000010 #
b00000000000000000000000000000011 $
b00000000000000000000000000000010 %
1&
#15
0&
#20
b00000000000000000000000000000011 #
b00000000000000000000000000000100 $
b00000000000000000000000000000011 %
1&
#25
0&
#30
b00000000000000000000000000000100 #
b00000000000000000000000000000101 $
b00000000000000000000000000000100 %
1&
#35
0&
#40
b00000000000000000000000000000101 #
b00000000000000000000000000000110 $
b00000000000000000000000000000101 %
1&
#45
0&
#50
b00000000000000000000000000000110 #
b00000000000000000000000000000111 $
b00000000000000000000000000000110 %
1&
#55
0&
#60
b00000000000000000000000000000111 #
b00000000000000000000000000001000 $
b00000000000000000000000000000111 %
1&
#65
0&
#70
b00000000000000000000000000001000 #
b00000000000000000000000000001001 $
b00000000000000000000000000001000 %
1&
#75
0&
#80
b00000000000000000000000000001001 #
b00000000000000000000000000001010 $
b00000000000000000000000000001001 %
1&
#85
0&
#90
b00000000000000000000000000001010 #
b00000000000000000000000000001011 $
b00000000000000000000000000001010 %
1&
#95
0&
#100
b00000000000000000000000000001011 #
b00000000000000000000000000001100 $
b00000000000000000000000000001011 %
1&
#105
0&
#110
b00000000000000000000000000001100 #
b00000000000000000000000000001101 $
b00000000000000000000000000001100 %
1&
#115
0&
#120
b00000000000000000000000000001101 #
b00000000000000000000000000001110 $
b00000000000000000000000000001101 %
1&
#125
0&
#130
b00000000000000000000000000001110 #
b00000000000000000000000000001111 $
b00000000000000000000000000001110 %
1&
#135
0&
#140
b00000000000000000000000000001111 #
b00000000000000000000000000010000 $
b00000000000000000000000000001111 %
1&
#145
0&
#150
b00000000000000000000000000010000 #
b00000000000000000000000000010001 $
b00000000000000000000000000010000 %
1&
#155
0&
#160
b00000000000000000000000000010001 #
b00000000000000000000000000010010 $
b00000000000000000000000000010001 %
1&
#165
0&
#170
b00000000000000000000000000010010 #
b00000000000000000000000000010011 $
b00000000000000000000000000010010 %
1&
#175
0&
#180
b00000000000000000000000000010011 #
b00000000000000000000000000010100 $
b00000000000000000000000000010011 %
1&
#185
0&
#190
b00000000000000000000000000010100 #
b00000000000000000000000000010101 $
b00000000000000000000000000010100 %
1&
#195
0&
#200
b00000000000000000000000000010101 #
b00000000000000000000000000010110 $
b00000000000000000000000000010101 %
1&
@@ -19,8 +19,5 @@ execute(
check_finished => 1,
);
vcd_identical($Self->trace_filename,
$Self->{golden_filename});
ok(1);
1;
@@ -1,186 +0,0 @@
$date
Fri Nov 8 06:41:16 2019
$end
$version
fstWriter
$end
$timescale
1ns
$end
$scope module top $end
$var wire 1 ! clk $end
$scope module t $end
$var wire 1 ! clk $end
$var integer 32 " cyc $end
$scope module c1 $end
$scope module isub $end
$var integer 32 # hidden_from_isub $end
$var integer 32 $ value $end
$upscope $end
$var wire 32 " i_value $end
$upscope $end
$scope module c2 $end
$scope module isub2 $end
$var integer 32 # hidden_from_isub $end
$var integer 32 $ value $end
$upscope $end
$var wire 32 " i_value $end
$scope module c3 $end
$scope module isub $end
$var integer 32 # hidden_from_isub $end
$var integer 32 $ value $end
$upscope $end
$var wire 32 " i_value $end
$upscope $end
$upscope $end
$scope module itop $end
$var integer 32 # hidden_from_isub $end
$var integer 32 $ value $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
b00000000000000000000000000000001 "
b00000000000000000000000000000010 #
b00000000000000000000000000000001 $
#10
b00000000000000000000000000000010 $
b00000000000000000000000000000011 #
b00000000000000000000000000000010 "
1!
#15
0!
#20
1!
b00000000000000000000000000000011 "
b00000000000000000000000000000100 #
b00000000000000000000000000000011 $
#25
0!
#30
1!
b00000000000000000000000000000100 $
b00000000000000000000000000000101 #
b00000000000000000000000000000100 "
#35
0!
#40
1!
b00000000000000000000000000000101 "
b00000000000000000000000000000110 #
b00000000000000000000000000000101 $
#45
0!
#50
1!
b00000000000000000000000000000110 $
b00000000000000000000000000000111 #
b00000000000000000000000000000110 "
#55
0!
#60
1!
b00000000000000000000000000000111 "
b00000000000000000000000000001000 #
b00000000000000000000000000000111 $
#65
0!
#70
1!
b00000000000000000000000000001000 $
b00000000000000000000000000001001 #
b00000000000000000000000000001000 "
#75
0!
#80
1!
b00000000000000000000000000001001 "
b00000000000000000000000000001010 #
b00000000000000000000000000001001 $
#85
0!
#90
1!
b00000000000000000000000000001010 $
b00000000000000000000000000001011 #
b00000000000000000000000000001010 "
#95
0!
#100
1!
b00000000000000000000000000001011 "
b00000000000000000000000000001100 #
b00000000000000000000000000001011 $
#105
0!
#110
1!
b00000000000000000000000000001100 $
b00000000000000000000000000001101 #
b00000000000000000000000000001100 "
#115
0!
#120
1!
b00000000000000000000000000001101 "
b00000000000000000000000000001110 #
b00000000000000000000000000001101 $
#125
0!
#130
1!
b00000000000000000000000000001110 $
b00000000000000000000000000001111 #
b00000000000000000000000000001110 "
#135
0!
#140
1!
b00000000000000000000000000001111 "
b00000000000000000000000000010000 #
b00000000000000000000000000001111 $
#145
0!
#150
1!
b00000000000000000000000000010000 $
b00000000000000000000000000010001 #
b00000000000000000000000000010000 "
#155
0!
#160
1!
b00000000000000000000000000010001 "
b00000000000000000000000000010010 #
b00000000000000000000000000010001 $
#165
0!
#170
1!
b00000000000000000000000000010010 $
b00000000000000000000000000010011 #
b00000000000000000000000000010010 "
#175
0!
#180
1!
b00000000000000000000000000010011 "
b00000000000000000000000000010100 #
b00000000000000000000000000010011 $
#185
0!
#190
1!
b00000000000000000000000000010100 $
b00000000000000000000000000010101 #
b00000000000000000000000000010100 "
#195
0!
#200
1!
b00000000000000000000000000010101 "
b00000000000000000000000000010110 #
b00000000000000000000000000010101 $
@@ -0,0 +1,12 @@
#Expecting something along the line of:
%Error: t/t_interface_modport_dir_bad.v:36: Attempt to drive input-only modport: 'data'
: ... In instance t.source_i.source_i
ctrl.data <= ~ctrl.data;
^~~~
%Error: Exiting due to 1 error(s)
%Error: t/t_interface_modport_dir_bad.v:37: Attempt to drive input-only modport: 'valid'
: ... In instance t.source_i.source_i
ctrl.valid<= ~ctrl.valid;
^~~~
%Error: Exiting due to 1 error(s)
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt_all} and unsupported("Verilator unsupported, bug1622");
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;
@@ -0,0 +1,74 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Driss Hafdi
interface validData
(
input wire clk,
input wire rst
);
logic data;
logic valid;
modport sink
(
input data, valid, clk, rst
);
modport source
(
input clk, rst,
output data, valid
);
endinterface
module sinkMod
(
validData.sink ctrl,
output logic valid_data
);
always_ff @(posedge ctrl.clk) begin
if (ctrl.valid) valid_data <= ctrl.data;
end
endmodule
module sourceMod
(
validData.source ctrl
);
always_ff @(posedge ctrl.clk) begin
ctrl.data <= ~ctrl.data;
ctrl.valid <= ~ctrl.valid;
end
endmodule
module parentSourceMod
(
validData.sink ctrl
);
sourceMod source_i (.ctrl);
endmodule
module t (/*AUTOARG*/
// Outputs
data,
// Inputs
clk, rst
);
input clk;
input rst;
output logic data;
validData ctrl(.clk, .rst);
sinkMod sink_i (.ctrl, .valid_data(data));
parentSourceMod source_i (.ctrl);
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt_all} and unsupported("Verilator unsupported, bug1626");
scenarios(simulator => 1);
compile(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

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