mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44ce83cd8e | ||
|
|
c199930943 | ||
|
|
81fc1d48a6 | ||
|
|
f330f16bf6 | ||
|
|
10a6b566ef | ||
|
|
cff5485821 | ||
|
|
dcbdac1b81 | ||
|
|
a59777aa75 | ||
|
|
d82b9128d0 | ||
|
|
ab4f18c892 | ||
|
|
4480938b25 | ||
|
|
11a1b201a9 | ||
|
|
1a8b192e40 | ||
|
|
aee3a32354 | ||
|
|
35e9489f33 | ||
|
|
5c6d74cd80 | ||
|
|
8611ff230d | ||
|
|
8ef4097f00 | ||
|
|
fe684e8733 | ||
|
|
96f8bbd023 | ||
|
|
95ffcad12e | ||
|
|
ebed1a9000 | ||
|
|
2240f42bfa | ||
|
|
ac4f0da9ee | ||
|
|
559852f60b | ||
|
|
b0669f3aca | ||
|
|
00979ede14 | ||
|
|
13569ed98b | ||
|
|
809a6de9cd | ||
|
|
d65d8fda54 | ||
|
|
2076b0219d | ||
|
|
32f93a8a1e | ||
|
|
e28175108f | ||
|
|
b81295230a | ||
|
|
6ae7f7b152 | ||
|
|
03026b63b9 | ||
|
|
38e586fabe | ||
|
|
3d6e8e9eb0 | ||
|
|
df192f2b61 | ||
|
|
17ad59394f | ||
|
|
682c2a610f | ||
|
|
59782266b9 | ||
|
|
4885bcb93c | ||
|
|
d47d3b5162 | ||
|
|
99455a16bf | ||
|
|
a86e1953eb | ||
|
|
f63dfd7028 | ||
|
|
7a413a121d | ||
|
|
0f6b625db8 | ||
|
|
f134ac4f2f | ||
|
|
39eeda50c6 | ||
|
|
09ca4ce791 | ||
|
|
2ff22d9050 | ||
|
|
c726ad0142 | ||
|
|
0c0198cf55 | ||
|
|
d480c2f033 | ||
|
|
8ebe86e54b | ||
|
|
62af9dbed4 | ||
|
|
3eb0ff8aa0 | ||
|
|
ce5a70fbca | ||
|
|
c36d9a68f5 | ||
|
|
8c5aa21a11 | ||
|
|
47b5e36e60 | ||
|
|
a481638edb | ||
|
|
de7caad710 | ||
|
|
b1c14e485a | ||
|
|
66727670f9 | ||
|
|
b9322206d7 | ||
|
|
617424e04a | ||
|
|
e9c4ffa04e | ||
|
|
30c2e53f9e | ||
|
|
a250decfaa | ||
|
|
21a380def0 | ||
|
|
77e30d4920 | ||
|
|
98dcbc6b3e | ||
|
|
6ce81698e7 |
+42
-27
@@ -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]
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -127,6 +127,9 @@ private:
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDType2p()) {
|
||||
subnodep->user1Inc();
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
||||
+188
-163
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
Executable
+16
@@ -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;
|
||||
@@ -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
|
||||
Executable
+20
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
Executable
+18
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
Executable
+18
@@ -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;
|
||||
@@ -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
|
||||
Executable
+18
@@ -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;
|
||||
@@ -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
|
||||
Executable
+17
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
Executable
+18
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 *-*
|
||||
|
||||
@@ -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,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 *-*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -35,6 +35,10 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VL_PRINTF
|
||||
# define VL_PRINTF printf
|
||||
#endif
|
||||
|
||||
//======================================================================
|
||||
|
||||
void dpii_display_call(const char* c) {
|
||||
|
||||
@@ -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
|
||||
Executable
+19
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Executable
+19
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
Executable
+16
@@ -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;
|
||||
@@ -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
|
||||
Executable
+20
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
Executable
+20
@@ -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
Reference in New Issue
Block a user