mirror of
https://github.com/verilator/verilator.git
synced 2026-10-04 17:13:40 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4d5a20670 | ||
|
|
6339159b04 | ||
|
|
aec019991c | ||
|
|
33e6a17747 | ||
|
|
ecf508ec23 | ||
|
|
a5bcfc0509 | ||
|
|
1899096ff4 | ||
|
|
6e219f5831 | ||
|
|
de1bb5aeb6 | ||
|
|
b52d94273c | ||
|
|
e655c85489 | ||
|
|
dee7210231 | ||
|
|
cbd073ed08 | ||
|
|
09ebc0c163 | ||
|
|
d2ede75c71 | ||
|
|
3e03fef3e3 | ||
|
|
0f583f4b33 | ||
|
|
f175db74a5 | ||
|
|
8d5e37a413 | ||
|
|
8b9b7178a2 | ||
|
|
a2f49063e2 | ||
|
|
f3f34baa73 | ||
|
|
abe9ecd225 | ||
|
|
67409af38d | ||
|
|
b7d1c34aa6 | ||
|
|
92809b95c9 | ||
|
|
b18690cbe2 | ||
|
|
96155365b2 | ||
|
|
3e5067feb1 | ||
|
|
3ec687a0cf | ||
|
|
365034d7dd | ||
|
|
09aa9f87d8 | ||
|
|
97963fb8c9 | ||
|
|
ee1643ce39 | ||
|
|
a82cdcfe48 | ||
|
|
1b439703ff | ||
|
|
4cc5943f90 | ||
|
|
5fad666678 | ||
|
|
e12bf35996 | ||
|
|
d34fccec22 | ||
|
|
429437f1b9 | ||
|
|
c6e7d87960 | ||
|
|
716320f3ca | ||
|
|
1d12b47cb8 | ||
|
|
1bc1ee9e08 | ||
|
|
53f50463bc | ||
|
|
7ab91e660f | ||
|
|
2f0e230522 | ||
|
|
280f674ce9 | ||
|
|
a92c66d512 | ||
|
|
c45eedcb02 | ||
|
|
a9a49345ba | ||
|
|
8d960a2eb9 | ||
|
|
3e623b8959 | ||
|
|
1b1991d53d | ||
|
|
6d0f39d841 | ||
|
|
3087501b6c | ||
|
|
b429319bc0 | ||
|
|
247e855dbf | ||
|
|
1aec645510 | ||
|
|
3ea2038d3d | ||
|
|
942cb5e87e | ||
|
|
37a3a7cdce | ||
|
|
435a27b66a | ||
|
|
b31a7cdcbf | ||
|
|
ac61548e6a | ||
|
|
f5ace0f72a | ||
|
|
e498b73933 | ||
|
|
ff69bdbc6f | ||
|
|
0c1e184cb7 | ||
|
|
e97541dcbc | ||
|
|
7b3eb22865 | ||
|
|
d55f065ce2 | ||
|
|
86af244636 | ||
|
|
2c9e2b2e3c | ||
|
|
33c8bf886e | ||
|
|
ef71a089a6 | ||
|
|
5fc98cce0d | ||
|
|
b9101c3d6a | ||
|
|
6aab0f627c | ||
|
|
6b97673d0a | ||
|
|
5d8c1ce84e | ||
|
|
33c9591a4b | ||
|
|
87e8736823 | ||
|
|
c0da16bfcd | ||
|
|
a4ddc5b3ac | ||
|
|
91e4010039 | ||
|
|
486b6580d8 | ||
|
|
9c4ef27d49 | ||
|
|
33577eaa68 | ||
|
|
d5e19661bd | ||
|
|
799afac05b | ||
|
|
3ba36dc30c | ||
|
|
641024c235 | ||
|
|
d9598db117 | ||
|
|
2e4da07a15 | ||
|
|
40f4411b69 | ||
|
|
c75de0f37c | ||
|
|
74c4c1bf44 | ||
|
|
60a637921c | ||
|
|
22312b3c9c | ||
|
|
2e26e44538 | ||
|
|
24e79ecc68 | ||
|
|
5b532a1812 | ||
|
|
f3867d7f80 | ||
|
|
fb90e47e70 | ||
|
|
68046244dd | ||
|
|
b1507060ad | ||
|
|
ffbd595d88 | ||
|
|
ed5bc1e69c | ||
|
|
9734931f67 | ||
|
|
0048b04540 | ||
|
|
c361932fe2 | ||
|
|
2d8feabe54 | ||
|
|
1b511dd130 | ||
|
|
52024f4d80 | ||
|
|
735fa6287f | ||
|
|
7eb407fe2b | ||
|
|
897d5c58b3 | ||
|
|
dc9086512b |
@@ -3,6 +3,51 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.840 2012/07/31 Beta
|
||||
|
||||
** Rewrote tristate handling; supports tri0, tri1, tristate bit selects,
|
||||
concatenates and pullup/pulldowns, bug395, bug56, bug54, bug51.
|
||||
[Alex Solomatnikov, Lane Brooks, et al]
|
||||
|
||||
** Support packed structures and unions, bug181.
|
||||
Note this was a major internal change that may lead to some instability.
|
||||
|
||||
*** Support tri0 and tri1, bug462. [Alex Solomatnikov]
|
||||
|
||||
*** Support nmos and pmos, bug488. [Alex Solomatnikov]
|
||||
|
||||
*** Add INITIALDLY warning on initial assignments, bug478. [Alex Solomatnikov]
|
||||
|
||||
*** Add PINMISSING and PINNOCONNECT lint checks.
|
||||
|
||||
*** Add --converge-limit option.
|
||||
|
||||
*** Fix generate operators not short circuiting, bug413. [by Jeremy Bennett]
|
||||
|
||||
*** Fix parameters not supported in constant functions, bug474. [Alex Solomatnikov]
|
||||
|
||||
**** Fix duplicate warnings/errors, bug516. [Alex Solomatnikov]
|
||||
|
||||
**** Fix signed extending biops with WIDTH warning off, bug511. [Junji Hashimoto]
|
||||
|
||||
**** Fix ITOD internal error on real conversions, bug491. [Alex Solomatnikov]
|
||||
|
||||
**** Fix input and real loosing real data type, bug501. [Alex Solomatnikov]
|
||||
|
||||
**** Fix imports causing symbol table error, bug490. [Alex Solomatnikov]
|
||||
|
||||
**** Fix newlines in radix values, bug507. [Walter Lavino]
|
||||
|
||||
**** Fix loop error message to report line, bug513. [Jeremy Bennett]
|
||||
|
||||
**** Fix false UNUSED warning on file system calls.
|
||||
|
||||
**** Fix GCC 4.7.0 compile warnings, bug530. [Jeremy Bennett]
|
||||
|
||||
**** Fix svdpi.h compile error on Apple OS.
|
||||
|
||||
**** Fix compile error under git submodules, bug534. [Aurelien Francillon]
|
||||
|
||||
|
||||
* Verilator 3.833 2012/04/15
|
||||
|
||||
|
||||
+2
-2
@@ -457,8 +457,8 @@ distclean maintainer-clean::
|
||||
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
|
||||
rm -f include/verilated.mk
|
||||
|
||||
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/[a-z]*.in \
|
||||
${srcdir}/[a-z]*.in ${srcdir}/*.pod
|
||||
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
||||
${srcdir}/*.in ${srcdir}/*.pod
|
||||
|
||||
TAGS: $(TAGFILES)
|
||||
etags $(TAGFILES)
|
||||
|
||||
+108
-44
@@ -174,10 +174,10 @@ sub run {
|
||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 255) {
|
||||
if (($status & 255) == 8 || ($status & 255) == 11) { # SIGFPA or SIGSEGV
|
||||
if ($status & 127) {
|
||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} elsif (($status & 255) == 6) { # SIGABRT
|
||||
} elsif (($status & 127) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} else {
|
||||
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
@@ -250,6 +250,7 @@ descriptions in the next sections for more information.
|
||||
--cc Create C++ output
|
||||
--cdc Clock domain crossing analysis
|
||||
--compiler <compiler-name> Tune for specified C++ compiler
|
||||
--converge-limit <loops> Tune convergence settle time
|
||||
--coverage Enable all coverage
|
||||
--coverage-line Enable line coverage
|
||||
--coverage-toggle Enable toggle coverage
|
||||
@@ -427,6 +428,11 @@ functions to avoid error C1061.
|
||||
|
||||
=back
|
||||
|
||||
=item --converge-limit <loops>
|
||||
|
||||
Rarely needed. Specifies the maximum number of runtime iterations before
|
||||
creating a model failed to converge error. Defaults to 100.
|
||||
|
||||
=item --coverage
|
||||
|
||||
Enables all forms of coverage, alias for "--coverage-line --coverage-toggle
|
||||
@@ -521,7 +527,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
|
||||
=item --debugi-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set internal debugging level globally
|
||||
or on the specified source file to the specified level.
|
||||
to the specified debug level (1-10) or set the specified source file to the
|
||||
specified level. Higher levels produce more detailed messages (plain
|
||||
C<--debug> is equivalent to C<--debugi 4>).
|
||||
|
||||
=item +define+I<var>+I<value>
|
||||
|
||||
@@ -531,9 +539,10 @@ standard across Verilog tools while -D is an alias for GCC compatibility.
|
||||
=item --dump-tree
|
||||
|
||||
Rarely needed. Enable writing .tree debug files with dumping level 3,
|
||||
which dumps the standard critical stages. --dump-tree is enabled
|
||||
automatically with --debug, so "--debug --no-dump-tree" may be useful if
|
||||
the dump files are large and not desired.
|
||||
which dumps the standard critical stages. For details on the format see
|
||||
the Verilator Internals manual. --dump-tree is enabled automatically with
|
||||
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
|
||||
large and not desired.
|
||||
|
||||
=item --dump-treei
|
||||
|
||||
@@ -928,8 +937,8 @@ Disable the specified warning message.
|
||||
Disable all lint related warning messages, and all style warnings. This is
|
||||
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
|
||||
-Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN
|
||||
-Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus
|
||||
the list shown for Wno-style.
|
||||
-Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
|
||||
-Wno-WIDTH" plus the list shown for Wno-style.
|
||||
|
||||
It is strongly recommended you cleanup your code rather than using this
|
||||
option, it is only intended to be use when running test-cases of code
|
||||
@@ -939,8 +948,8 @@ received from third parties.
|
||||
|
||||
Disable all code style related warning messages (note by default they are
|
||||
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
|
||||
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
|
||||
-Wno-VARHIDDEN".
|
||||
-Wno-INCABSPATH -Wno-PINNOCONNECT -Wno-SYNCASYNCNET -Wno-UNDRIVEN
|
||||
-Wno-UNUSED -Wno-VARHIDDEN".
|
||||
|
||||
=item -Wno-fatal
|
||||
|
||||
@@ -960,13 +969,14 @@ Enable all lint related warning messages (note by default they are already
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
|
||||
-Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
|
||||
-Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
-Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
|
||||
=item -Wwarn-style
|
||||
|
||||
Enable all code style related warning messages. This is equivalent to
|
||||
"-Wwarn ASSIGNDLY -Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH
|
||||
-Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
|
||||
-Wwarn-PINNOCONNECT -Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED
|
||||
-Wwarn-VARHIDDEN".
|
||||
|
||||
=item -x-assign 0
|
||||
|
||||
@@ -1126,6 +1136,9 @@ And link with SystemC. Note your path to the libraries may vary,
|
||||
depending on the operating system.
|
||||
|
||||
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
|
||||
# Might be needed if SystemC 2.3.0
|
||||
export SYSTEMC_CXX_FLAGS=-pthread
|
||||
|
||||
g++ -L$SYSTEMC_LIBDIR ../sc_main.o Vour__ALL*.o verilated.o \
|
||||
-o Vour -lsystemc
|
||||
|
||||
@@ -1279,7 +1292,7 @@ was compiled).
|
||||
=item SYSTEMC_CXX_FLAGS
|
||||
|
||||
Specifies additional flags that are required to be passed to GCC when
|
||||
building the SystemC model.
|
||||
building the SystemC model. System 2.3.0 may need this set to "-pthread".
|
||||
|
||||
=item SYSTEMC_INCLUDE
|
||||
|
||||
@@ -1734,8 +1747,8 @@ Verilator supports ==? and !=? operators, ++ and -- in some contexts,
|
||||
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
|
||||
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
|
||||
const, do-while, enum, export, final, import, int, logic, longint, package,
|
||||
program, shortint, time, typedef, var, void, priority case/if, and unique
|
||||
case/if.
|
||||
program, shortint, struct, time, typedef, union, var, void, priority
|
||||
case/if, and unique case/if.
|
||||
|
||||
It also supports .name and .* interconnection.
|
||||
|
||||
@@ -2205,49 +2218,59 @@ Verilator is optimized for edge sensitive (flop based) designs. It will
|
||||
attempt to do the correct thing for latches, but most performance
|
||||
optimizations will be disabled around the latch.
|
||||
|
||||
=head2 Structures and Unions
|
||||
|
||||
Verilator only presently supports packed structs and packed unions. Rand
|
||||
and randc tags on members are simply ignored. All structures and unions
|
||||
are represented as a single vector, which means that generating one member
|
||||
of a structure from blocking, and another from non-blocking assignments is
|
||||
unsupported.
|
||||
|
||||
=head2 Time
|
||||
|
||||
All delays (#) are ignored, as they are in synthesis.
|
||||
|
||||
=head2 Two State
|
||||
=head2 Unknown states
|
||||
|
||||
Verilator is a two state simulator, not a four state simulator. However, it
|
||||
has two features which uncover most initialization bugs (including many that
|
||||
a four state simulator will miss.)
|
||||
|
||||
First, assigning a variable to a X will actually assign the variable to a
|
||||
random value (see the -x-assign 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.
|
||||
Verilator is mostly a two state simulator, not a four state simulator.
|
||||
However, it has two features which uncover most initialization bugs
|
||||
(including many that a four state simulator will miss.)
|
||||
|
||||
Identity comparisons (=== or !==) are converted to standard ==/!== when
|
||||
neither side is a constant. This may make the expression result differ
|
||||
from a four state simulator.
|
||||
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.
|
||||
|
||||
All variables are initialized using a function. By running several
|
||||
random simulation runs you can determine that reset is working correctly.
|
||||
On the first run, the function initializes variables to zero. On the
|
||||
second, have it initialize variables to one. On the third and following
|
||||
runs have it initialize them randomly. If the results match, reset works.
|
||||
(Note this is what the hardware will really do.) In practice, just setting
|
||||
all variables to one at startup finds most problems.
|
||||
Assigning a variable to a X will actually assign the variable to a random
|
||||
value (see the -x-assign 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 are randomly initialized using a function. By running
|
||||
several random simulation runs you can determine that reset is working
|
||||
correctly. On the first run, the function initializes variables to zero.
|
||||
On the second, have it initialize variables to one. On the third and
|
||||
following runs have it initialize them randomly. If the results match,
|
||||
reset works. (Note this is what the hardware will really do.) In
|
||||
practice, just setting all variables to one at startup finds most problems.
|
||||
|
||||
=head2 Tri/Inout
|
||||
|
||||
Verilator converts some simple tristate structures into two state. An assignment
|
||||
of the form:
|
||||
Verilator converts some simple tristate structures into two state. Pullup,
|
||||
pulldown, bufif0, bufif1, notif0, notif1, pmos, nmos, tri0 and tri1 are
|
||||
also supported. Simple comparisons with === 1'bz are also supported.
|
||||
|
||||
An assignment of the form:
|
||||
|
||||
inout driver;
|
||||
wire driver = (enable) ? output_value : 1'bz;
|
||||
|
||||
Will be converted to
|
||||
|
||||
input driver__in; // Value being driven in from "external" drivers
|
||||
output driver__en; // True if driven from this module
|
||||
output driver__enout; // Value being driven from this module
|
||||
input driver; // Value being driven in from "external" drivers
|
||||
output driver__en; // True if driven from this module
|
||||
output driver__out; // Value being driven from this module
|
||||
|
||||
Pullup, pulldown, bufif0, bufif1, notif0, notif1 are also supported.
|
||||
External logic will be needed to combine these signals with any external
|
||||
drivers.
|
||||
|
||||
@@ -2712,6 +2735,15 @@ command line to specify the top include source directory.
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item INITIALDLY
|
||||
|
||||
Warns that you have a delayed assignment inside of an initial or final
|
||||
block. If this message is suppressed, Verilator will convert this to a
|
||||
non-delayed assignment. See also the COMBDLY warning.
|
||||
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item LITENDIAN
|
||||
|
||||
Warns that a vector is declared with little endian bit numbering
|
||||
@@ -2749,6 +2781,23 @@ not really needed. The best solution is to insure that each module is in a
|
||||
unique file by the same name. Otherwise, make sure all library files are
|
||||
read in as libraries with -v, instead of automatically with -y.
|
||||
|
||||
=item PINMISSING
|
||||
|
||||
Warns that a module has a pin which is not mentioned in a cell
|
||||
instantiation. If a pin is not missing it should still be specified on the
|
||||
cell declaration with a empty connection,using "(.pin_name())".
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item PINNOCONNECT
|
||||
|
||||
Warns that a cell instantiation has a pin which is not connected to another
|
||||
signal.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item REALCVT
|
||||
|
||||
Warns that a real number is being implicitly rounded to an integer, with
|
||||
@@ -3395,12 +3444,27 @@ follows:
|
||||
cp -p t/t_EXAMPLE.pl t/t_BUG.pl
|
||||
cp -p t/t_EXAMPLE.v t/t_BUG.v
|
||||
|
||||
There are many hits on how to write a good test in the driver.pl
|
||||
documentation which can be seen by running:
|
||||
|
||||
cd $VERILATOR_ROOT # Need the original distribution kit
|
||||
test_regress/driver.pl --help
|
||||
|
||||
Edit t/t_BUG.pl to suit your example; you can do anything you want in the
|
||||
Verilog code there; just make sure it retains the single clk input and no
|
||||
outputs. Now, the following should fail:
|
||||
|
||||
cd $VERILATOR_ROOT # Need the original distribution kit
|
||||
cd test_regress
|
||||
t/t_BUG.pl
|
||||
t/t_BUG.pl # Run on Verilator
|
||||
t/t_BUG.pl --debug # Run on Verilator, passing --debug to Verilator
|
||||
t/t_BUG.pl --vcs # Run on a commercial simulator
|
||||
t/t_BUG.pl --nc|--iv|--ghdl # Likewise on other simulators
|
||||
|
||||
The test driver accepts a number of options, many of which mirror the main
|
||||
Verilator option. For example the previous test could have been run with
|
||||
debugging enabled. The full set of test options can be seen by running
|
||||
driver.pl --help as shown above.
|
||||
|
||||
Finally, report the bug using the bug tracker at
|
||||
L<http://www.veripool.org/verilator>. The bug will become publicly
|
||||
@@ -3445,9 +3509,9 @@ Many people have provided ideas and other assistance with Verilator.
|
||||
|
||||
The major corporate sponsors of Verilator, by providing significant
|
||||
contributions of time or funds include include Cavium Networks, Compaq
|
||||
Corporation, Digital Equipment Corporation, Embecosm Ltd., Intel
|
||||
Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip Designs
|
||||
Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
|
||||
Corporation, Digital Equipment Corporation, Embecosm Ltd., Hicamp Systems,
|
||||
Intel Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip
|
||||
Designs Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
|
||||
|
||||
The people who have contributed major functionality are Byron Bradley,
|
||||
Jeremy Bennett, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder.
|
||||
|
||||
+62
-4
@@ -14,6 +14,19 @@ use vars qw ($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
# Old version 1 dump nodes with no dtypep's
|
||||
our %Ver1_Non_Dtyped = map {$_ => 1} qw(
|
||||
ACTIVE ALWAYS ALWAYSPOST ALWAYSPUBLIC ATTROF BEGIN BREAK CASE CASEITEM
|
||||
CCALL CELL CELLINLINE CFILE CFUNC CHANGEDET CLOCKING COMMENT CONTINUE
|
||||
COVERDECL COVERINC COVERTOGGLE CRETURN CSTMT DEFPARAM DISABLE DISPLAY DOT
|
||||
DPIEXPORT FCLOSE FFLUSH FINAL FINISH FOPEN GENCASE GENERATE GENFOR GENIF
|
||||
IF IMPLICIT INITARRAY INITIAL JUMPGO JUMPLABEL MODULE NETLIST
|
||||
NOTFOUNDMODULE PACKAGE PACKAGEIMPORT PARSEREF PIN PORT PRAGMA PRIMITIVE
|
||||
PSLASSERT PSLCOVER PSLDEFCLOCK PULL RANGE READMEM REPEAT RETURN SCCTOR
|
||||
SCDTOR SCHDR SCIMP SCIMPHDR SCINT SCOPE SELBIT SELEXTRACT SELMINUS
|
||||
SELPLUS SENGATE SENITEM SENTREE SFORMAT SFORMATF STOP SYSIGNORE SYSTEMT
|
||||
TASK TASKREF TEXT TOPSCOPE TYPEDEFFWD TYPETABLE UCSTMT UDPTABLE
|
||||
UDPTABLELINE UNTILSTABLE VASSERT WHILE );
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
@@ -79,27 +92,72 @@ sub diff_file {
|
||||
my $a = shift;
|
||||
my $b = shift;
|
||||
# Compare the two tree files
|
||||
my $tmp_a = "/tmp/$$.a";
|
||||
my $tmp_b = "/tmp/$$.b";
|
||||
(my $short_a = $a) =~ s/[^a-zA-Z0-9.]+/_/g;
|
||||
(my $short_b = $b) =~ s/[^a-zA-Z0-9.]+/_/g;
|
||||
my $tmp_a = "/tmp/${$}_${short_a}.a";
|
||||
my $tmp_b = "/tmp/${$}_${short_b}.b";
|
||||
|
||||
filter ($a, $tmp_a);
|
||||
filter ($b, $tmp_b);
|
||||
my $vera = version_from($a);
|
||||
my $verb = version_from($b);
|
||||
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|
||||
|| ($vera >= 0x3900 && $verb < 0x3900));
|
||||
|
||||
filter ($a, $tmp_a, $verCvt);
|
||||
filter ($b, $tmp_b, $verCvt);
|
||||
system("diff -u $tmp_a $tmp_b");
|
||||
unlink $tmp_a;
|
||||
unlink $tmp_b;
|
||||
}
|
||||
|
||||
sub version_from {
|
||||
my $fn = shift;
|
||||
# Return dump format
|
||||
my $f1 = IO::File->new ($fn) or die "%Error: $! $fn,";
|
||||
while (defined (my $line=$f1->getline())) {
|
||||
last if $. > 10;
|
||||
return hex $1 if $line =~ /\(format (0x[0-9.]+)\)/;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
sub filter {
|
||||
my $fn1 = shift;
|
||||
my $fn2 = shift;
|
||||
my $verCvt = shift;
|
||||
# Remove hex numbers before diffing
|
||||
my $f1 = IO::File->new ($fn1) or die "%Error: $! $fn1,";
|
||||
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
|
||||
while (defined (my $line=$f1->getline())) {
|
||||
same_line:
|
||||
next if $line =~ / This=/;
|
||||
$line =~ s/0x[a-f0-9]+/0x/g;
|
||||
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
||||
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
||||
if ($verCvt) {
|
||||
next if $line =~ /^ NETLIST/;
|
||||
$line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format
|
||||
# # Below Ver1_Non_Dtyped may replace above further
|
||||
if ($line =~ /: ([A-Z]+) /) {
|
||||
my $type = $1;
|
||||
next if $type =~ 'DTYPE';
|
||||
if ($type eq 'TYPETABLE' || $type eq 'RANGE') {
|
||||
$line =~ /^(\s+\S+:) /; my $prefix = $1;
|
||||
while (defined ($line=$f1->getline())) {
|
||||
next if $line =~ /^\s+[a-z]/; # Table body
|
||||
next if $line =~ /^${prefix}[0-9]:/;
|
||||
goto same_line;
|
||||
}
|
||||
next;
|
||||
}
|
||||
if ($Ver1_Non_Dtyped{$type}) {
|
||||
$line =~ s! w[0-9]+!!g;
|
||||
}
|
||||
}
|
||||
$line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format
|
||||
$line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format
|
||||
$line =~ s! s?w0$! NoW!g; # OLD: no width -> common format
|
||||
$line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format
|
||||
}
|
||||
print $f2 $line;
|
||||
}
|
||||
$f1->close;
|
||||
|
||||
+2
-1
@@ -4,7 +4,7 @@
|
||||
# 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.
|
||||
|
||||
AC_INIT([Verilator],[3.833 2012-04-15])
|
||||
AC_INIT([Verilator],[3.840 2012-07-31])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
|
||||
@@ -128,6 +128,7 @@ _MY_CXX_CHECK_OPT(-Wno-sign-compare)
|
||||
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
# Checks for library functions.
|
||||
|
||||
@@ -27,6 +27,8 @@ typedef signed __int32 int32_t;
|
||||
typedef signed __int8 int8_t;
|
||||
#elif defined(__MINGW32__)
|
||||
#include <stdint.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <stdint.h>
|
||||
#elif defined(__linux)
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
|
||||
+107
-13
@@ -336,10 +336,10 @@ AST.
|
||||
|
||||
=head1 TESTING
|
||||
|
||||
To write a test see notes in the forum and in the verilator.txt manual.
|
||||
To write a test see the BUGS section of the Verilator primary manual, and
|
||||
the documentation in:
|
||||
|
||||
Note you can run the regression tests in parallel; see the
|
||||
test_regress/driver.pl script -j flag.
|
||||
test_regress/t/driver.pl --help
|
||||
|
||||
=head1 DEBUGGING
|
||||
|
||||
@@ -369,10 +369,10 @@ viewers let us know; ZGRViewer isn't great for large graphs.
|
||||
Tree files are dumps of the AST Tree and are produced between every major
|
||||
algorithmic stage. An example:
|
||||
|
||||
NETLIST 0x90fb00 <e1> {a0} w0
|
||||
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
|
||||
NETLIST 0x90fb00 <e1> {a0}
|
||||
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -384,13 +384,14 @@ the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
|
||||
"0x91a780" is the address of this node.
|
||||
|
||||
"<e74>" means the 74th edit to the netlist was the last modification to
|
||||
this node. A trailing # indicates this node changed since the last tree
|
||||
dump was made. You can gdb break on this edit; see below.
|
||||
this node.
|
||||
|
||||
"{a22}" indicates this node is related to line 22 in the source filename
|
||||
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
|
||||
"a", where "a" is the first file read, "z" the 26th, and "aa" the 27th.
|
||||
|
||||
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
|
||||
"@dt=0x..." indicates the address of the data type this node contains.
|
||||
|
||||
"w32" indicates the width is 32 bits.
|
||||
|
||||
"out_wide" is the name of the node, in this case the name of the variable.
|
||||
|
||||
@@ -399,6 +400,97 @@ variable is an output.
|
||||
|
||||
=back
|
||||
|
||||
In more detail the following fields are dumped common to all nodes. They
|
||||
are produced by the C<AstNode::dump()> method:
|
||||
|
||||
=over 4
|
||||
|
||||
=item Tree Hierarchy
|
||||
|
||||
The dump lines begin with numbers and colons to indicate the child node
|
||||
hierarchy. As noted above in L</Key Classes Used in the Verilator Flow>,
|
||||
C<AstNode> has lists of items at the same level in the AST, connected by
|
||||
the C<nextp()> and C<prevp()> pointers. These appear as nodes at the same
|
||||
level. For example after inlining:
|
||||
|
||||
NETLIST 0x929c1c8 <e1> {a0} w0
|
||||
1: MODULE 0x92bac80 <e3144> {e14} w0 TOP_t L1 [P]
|
||||
1:1: CELLINLINE 0x92bab18 <e3686#> {e14} w0 v -> t
|
||||
1:1: CELLINLINE 0x92bc1d8 <e3688#> {e24} w0 v__DOT__i_test_gen -> test_gen
|
||||
...
|
||||
1: MODULE 0x92b9bb0 <e503> {e47} w0 test_gen L3
|
||||
...
|
||||
|
||||
=item AstNode type
|
||||
|
||||
The textual name of this node AST type (always in capitals). Many of these
|
||||
correspond directly to Verilog entities (for example C<MODULE> and
|
||||
C<TASK>), but others are internal to Verialtor (for example C<NETLIST> and
|
||||
C<BASICDTYPE>).
|
||||
|
||||
=item Address of the node
|
||||
|
||||
A hexadecimal address of the node in memory. Useful for examining with the
|
||||
debugger.
|
||||
|
||||
=item Last edit number
|
||||
|
||||
Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
|
||||
of the last edit to modify this node. The trailing C<#> indicates the node
|
||||
has been edited since the last tree dump (which typically means in the last
|
||||
refinement or optimization pass). GDB can watch for this, see L</Debugging
|
||||
with GDB> below.
|
||||
|
||||
=item Source file and line
|
||||
|
||||
Of the form C<< {xxnnnn} >>, where C{xx} is the filename letter (or
|
||||
letters) and C<nnnn> is the line number within that file. The first file is
|
||||
C<a>, the 26th is C<z>, the 27th is C<aa> and so on.
|
||||
|
||||
=item User pointers
|
||||
|
||||
Shows the value of the node's user1p...user5p, if non-NULL.
|
||||
|
||||
=item Data type
|
||||
|
||||
Many nodes have an explicit data type. "@dt=0x..." indicates the address
|
||||
of the data type (AstNodeDType) this node uses.
|
||||
|
||||
If a data type is present and is numberic, it then prints the width of the
|
||||
item. This field is a squence of flag characters and width data as follows:
|
||||
|
||||
C<s> if the node is signed.
|
||||
|
||||
C<d> if the node is a double (i.e a floating point entity).
|
||||
|
||||
C<w> always present, indicating this is the width field.
|
||||
|
||||
C<u> if the node is unsized.
|
||||
|
||||
C</nnnn> if the node is unsized, where C<nnnn> is the minimum width.
|
||||
|
||||
=item Name of the entity represented by the node if it exists
|
||||
|
||||
For example for a C<VAR> it is the name of the variable.
|
||||
|
||||
=back
|
||||
|
||||
Many nodes follow these fields with additional node specific
|
||||
information. Thus the C<VARREF> node will print either C<[LV]> or C<[RV]>
|
||||
to indicate a left value or right value, followed by the node of the
|
||||
variable being referred to. For example:
|
||||
|
||||
1:2:1:1: VARREF 0x92c2598 <e509> {e24} w0 clk [RV] <- VAR 0x92a2e90 <e79> {e18} w0 clk [I] INPUT
|
||||
|
||||
In general, examine the C<dump()> method in C<V3AstNodes.cpp> of the node
|
||||
type in question to determine additional fields that may be printed.
|
||||
|
||||
The C<MODULE> has a list of C<CELLINLINE> nodes referred to by its
|
||||
C<op1p()> pointer, connected by C<nextp()> and C<prevp()> pointers.
|
||||
|
||||
Similarly the C<NETLIST> has a list of modules referred to by its C<op1p()>
|
||||
pointer.
|
||||
|
||||
=head2 Debugging with GDB
|
||||
|
||||
The test_regress/driver.pl script accepts --debug --gdb to start Verilator
|
||||
@@ -439,8 +531,10 @@ what made a <e####> line in the tree dumps):
|
||||
|
||||
To print a node:
|
||||
|
||||
call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
|
||||
call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
|
||||
pn nodep
|
||||
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
|
||||
pnt nodep
|
||||
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
|
||||
|
||||
When GDB halts, it is useful to understand that the backtrace will commonly
|
||||
show the iterator functions between each invocation of C<visit> in the
|
||||
|
||||
@@ -18,3 +18,17 @@ end
|
||||
document pnt
|
||||
Verilator: Print AstNode NODEP's tree
|
||||
end
|
||||
|
||||
define dtf
|
||||
call AstNode::dumpTreeFileGdb(0)
|
||||
end
|
||||
document dtf
|
||||
Verilator: Dump AstNode tree to file
|
||||
end
|
||||
|
||||
define watchedit
|
||||
watch AstNode::s_editCntGbl==$arg0
|
||||
end
|
||||
document watchedit
|
||||
Verilator: Create watch on where a edit number is made
|
||||
end
|
||||
|
||||
+4
-2
@@ -65,12 +65,14 @@ dbg: ../verilator_bin_dbg
|
||||
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||
|
||||
prefiles::
|
||||
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
prefiles:: config_rev.h
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
|
||||
config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
else
|
||||
config_rev.h: ${srcdir}/config_rev.pl
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
endif
|
||||
|
||||
maintainer-copy::
|
||||
|
||||
@@ -198,7 +198,6 @@ RAW_OBJS = \
|
||||
V3Inst.o \
|
||||
V3Life.o \
|
||||
V3LifePost.o \
|
||||
V3Link.o \
|
||||
V3LinkCells.o \
|
||||
V3LinkDot.o \
|
||||
V3LinkJump.o \
|
||||
|
||||
+17
-11
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -164,16 +162,22 @@ public:
|
||||
// Active AssignDly replacement functions
|
||||
|
||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
public:
|
||||
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL };
|
||||
private:
|
||||
bool m_combo; // Combo logic
|
||||
CheckType m_check; // Combo logic or other
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
||||
if (m_combo) {
|
||||
if (m_check != CT_SEQ) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
if (m_check == CT_INITIAL) {
|
||||
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
|
||||
} else {
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
}
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
@@ -182,7 +186,7 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssign* nodep, AstNUser*) {
|
||||
if (!m_combo) {
|
||||
if (m_check == CT_SEQ) {
|
||||
AstNode* las = m_assignp;
|
||||
m_assignp = nodep;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
@@ -191,7 +195,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
AstVar* varp=nodep->varp();
|
||||
if (!m_combo
|
||||
if (m_check == CT_SEQ
|
||||
&& m_assignp
|
||||
&& !varp->isUsedLoopIdx() // Ignore loop indicies
|
||||
&& !varp->isTemp()
|
||||
@@ -213,9 +217,9 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveDlyVisitor(AstNode* nodep, bool combo) {
|
||||
ActiveDlyVisitor(AstNode* nodep, CheckType check) {
|
||||
m_alwaysp = nodep;
|
||||
m_combo = combo;
|
||||
m_check = check;
|
||||
m_assignp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -252,6 +256,7 @@ private:
|
||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||
// Relink to IACTIVE, unless already under it
|
||||
UINFO(4," INITIAL "<<nodep<<endl);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
@@ -284,6 +289,7 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
return;
|
||||
}
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
if (!m_scopeFinalp) {
|
||||
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep());
|
||||
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
@@ -354,10 +360,10 @@ private:
|
||||
|
||||
// Warn and/or convert any delayed assignments
|
||||
if (combo && !sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, true);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
|
||||
}
|
||||
else if (!combo && sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, false);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+1
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -178,7 +176,7 @@ private:
|
||||
// VISITORS //========== Case assertions
|
||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->user1Inc()) {
|
||||
if (!nodep->user1SetOnce()) {
|
||||
bool has_default=false;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
if (itemp->isDefault()) has_default=true;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+77
-22
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -53,6 +51,9 @@ bool AstUser3InUse::s_userBusy=false;
|
||||
bool AstUser4InUse::s_userBusy=false;
|
||||
bool AstUser5InUse::s_userBusy=false;
|
||||
|
||||
int AstNodeDType::s_uniqueNum = 0;
|
||||
|
||||
|
||||
//######################################################################
|
||||
// V3AstType
|
||||
|
||||
@@ -72,14 +73,12 @@ void AstNode::init() {
|
||||
m_op3p = NULL;
|
||||
m_op4p = NULL;
|
||||
m_iterpp = NULL;
|
||||
m_dtypep = NULL;
|
||||
m_clonep = NULL;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_numeric = (int)AstNumeric::UNSIGNED;
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_width = 0;
|
||||
m_widthMin = 0;
|
||||
m_user1p = NULL;
|
||||
m_user1Cnt = 0;
|
||||
m_user2p = NULL;
|
||||
@@ -229,15 +228,6 @@ string AstNode::quoteName(const string& namein) {
|
||||
return out;
|
||||
}
|
||||
|
||||
int AstNode::widthPow2() const {
|
||||
// I.e. width 30 returns 32, width 32 returns 32.
|
||||
uint32_t width = this->width();
|
||||
for (int p2=30; p2>=0; p2--) {
|
||||
if (width > (1UL<<p2)) return (1UL<<(p2+1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Insertion
|
||||
|
||||
@@ -768,13 +758,16 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
||||
// Future versions of this function may require the node to have a back to be iterated;
|
||||
// there's no lower level reason yet though the back must exist.
|
||||
AstNode* nodep=this;
|
||||
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
|
||||
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||
#endif
|
||||
while (nodep) {
|
||||
AstNode* niterp = nodep;
|
||||
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
||||
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||
niterp->m_iterpp = &niterp;
|
||||
niterp->accept(v, vup);
|
||||
// accept may do a replaceNode and change niterp on us...
|
||||
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
|
||||
if (!niterp) return;
|
||||
niterp->m_iterpp = NULL;
|
||||
if (VL_UNLIKELY(niterp!=nodep)) { // Edited it
|
||||
@@ -856,6 +849,9 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||
void AstNode::cloneRelinkTree() {
|
||||
if (!this) return;
|
||||
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
|
||||
if (m_dtypep && m_dtypep->clonep()) {
|
||||
m_dtypep = m_dtypep->clonep()->castNodeDType();
|
||||
}
|
||||
nodep->cloneRelink();
|
||||
nodep->m_op1p->cloneRelinkTree();
|
||||
nodep->m_op2p->cloneRelinkTree();
|
||||
@@ -876,8 +872,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
if (this==NULL && node2p==NULL) return true;
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->width() != node2p->width()
|
||||
|| this->numeric() != node2p->numeric()
|
||||
|| this->dtypep() != node2p->dtypep()
|
||||
|| !this->same(node2p)) {
|
||||
return false;
|
||||
}
|
||||
@@ -954,15 +949,19 @@ void AstNode::dumpGdb() { // For GDB only
|
||||
dumpGdbHeader();
|
||||
cout<<" "; dump(cout); cout<<endl;
|
||||
}
|
||||
void AstNode::dumpGdbHeader() const { // For GDB only
|
||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
||||
dumpPtrs(cout);
|
||||
cout<<" Fileline = "<<fileline()<<endl;
|
||||
}
|
||||
void AstNode::dumpTreeGdb() { // For GDB only
|
||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
||||
dumpGdbHeader();
|
||||
dumpTree(cout);
|
||||
}
|
||||
void AstNode::dumpGdbHeader() const { // For GDB only
|
||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
||||
dumpPtrs(cout);
|
||||
cout<<" Fileline = "<<fileline()<<endl;
|
||||
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
|
||||
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree",98);
|
||||
v3Global.rootp()->dumpTreeFile(filename);
|
||||
}
|
||||
|
||||
void AstNode::dumpPtrs(ostream& os) const {
|
||||
@@ -1011,9 +1010,10 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
|
||||
void AstNode::dumpTreeFile(const string& filename, bool append) {
|
||||
if (v3Global.opt.dumpTree()) {
|
||||
{ // Write log & close
|
||||
UINFO(2,"Dumping "<<filename<<endl);
|
||||
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||
if (editCountGbl()==editCountLast()
|
||||
&& !(v3Global.opt.dumpTree()>=9)) {
|
||||
@@ -1049,6 +1049,61 @@ void AstNode::v3errorEnd(ostringstream& str) const {
|
||||
}
|
||||
}
|
||||
|
||||
string AstNode::warnMore() const {
|
||||
if (this) return this->fileline()->warnMore();
|
||||
else return V3Error::warnMore();
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Data type conversion
|
||||
|
||||
void AstNode::dtypeChgSigned(bool flag) {
|
||||
if (!dtypep()) this->v3fatalSrc("No dtype when changing to (un)signed");
|
||||
dtypeChgWidthSigned(dtypep()->width(), dtypep()->widthMin(),
|
||||
flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||
}
|
||||
void AstNode::dtypeChgWidth(int width, int widthMin) {
|
||||
if (!dtypep()) this->v3fatalSrc("No dtype when changing width"); // Use ChgWidthSigned(...UNSIGNED) otherwise
|
||||
dtypeChgWidthSigned(width, widthMin, dtypep()->numeric());
|
||||
}
|
||||
|
||||
void AstNode::dtypeChgWidthSigned(int width, int widthMin, bool issigned) {
|
||||
AstNumeric numeric = issigned ? AstNumeric::SIGNED : AstNumeric::UNSIGNED;
|
||||
if (!dtypep()) {
|
||||
// We allow dtypep() to be null, as before/during widthing dtypes are not resolved
|
||||
dtypeSetLogicSized(width, widthMin, numeric);
|
||||
} else {
|
||||
if (width==dtypep()->width()
|
||||
&& widthMin==dtypep()->widthMin()
|
||||
&& numeric==dtypep()->numeric()) return; // Correct already
|
||||
// FUTURE: We may be pointing at a two state data type, and this may
|
||||
// convert it to logic. Since the AstVar remains correct, we
|
||||
// work OK but this assumption may break in the future.
|
||||
// Note we can't just clone and do a widthForce, as if it's a BasicDType
|
||||
// the msb() indications etc will be incorrect.
|
||||
dtypeSetLogicSized(width, widthMin, numeric);
|
||||
}
|
||||
}
|
||||
|
||||
AstNodeDType* AstNode::findBasicDType(AstBasicDTypeKwd kwd) const {
|
||||
// For 'simple' types we use the global directory. These are all unsized.
|
||||
// More advanced types land under the module/task/etc
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findBasicDType(fileline(), kwd);
|
||||
}
|
||||
AstNodeDType* AstNode::findBitDType(int width, int widthMin, AstNumeric numeric) const {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, width, widthMin, numeric);
|
||||
}
|
||||
AstNodeDType* AstNode::findLogicDType(int width, int widthMin, AstNumeric numeric) const {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric);
|
||||
}
|
||||
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
|
||||
return v3Global.rootp()->typeTablep()
|
||||
->findInsertSameDType(nodep);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// AstNVisitor
|
||||
|
||||
|
||||
+263
-63
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -61,28 +59,40 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
enum VSignedState {
|
||||
// This can't be in the fancy class as the lexer union will get upset
|
||||
signedst_UNSIGNED=0, signedst_SIGNED=1, signedst_NOSIGN=2
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstNumeric {
|
||||
public:
|
||||
enum en {
|
||||
UNSIGNED,
|
||||
SIGNED,
|
||||
DOUBLE
|
||||
// Limited to 2 bits, unless change V3Ast's packing function
|
||||
NOSIGN,
|
||||
_ENUM_MAX // Leave last
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"UNSIGNED","SIGNED","DOUBLE"
|
||||
"UNSIGNED","SIGNED","NOSIGN"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () : m_e(UNSIGNED) {}
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
inline AstNumeric (VSignedState signst) {
|
||||
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
|
||||
else if (signst==signedst_SIGNED) m_e=SIGNED;
|
||||
else m_e=NOSIGN;
|
||||
}
|
||||
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
inline bool isDouble() const { return m_e==DOUBLE; }
|
||||
inline bool isSigned() const { return m_e==SIGNED; }
|
||||
inline bool isUnsigned() const { return m_e==UNSIGNED; }
|
||||
inline bool isNosign() const { return m_e==NOSIGN; }
|
||||
// No isUnsigned() as it's ambiguous if NOSIGN should be included or not.
|
||||
};
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
||||
@@ -211,6 +221,8 @@ public:
|
||||
ILLEGAL,
|
||||
EXPR_BITS, // V3Const converts to constant
|
||||
//
|
||||
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
//
|
||||
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked
|
||||
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
|
||||
@@ -225,8 +237,8 @@ public:
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"%E-AT", "EXPR_BITS", "VAR_BASE",
|
||||
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"%E-AT", "EXPR_BITS", "MEMBER_BASE",
|
||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||
};
|
||||
@@ -253,6 +265,8 @@ public:
|
||||
STRING,
|
||||
// Internal types for mid-steps
|
||||
SCOPEPTR, CHARPTR,
|
||||
// Unsigned and two state; fundamental types
|
||||
UINT32, UINT64,
|
||||
// Internal types, eliminated after parsing
|
||||
LOGIC_IMPLICIT,
|
||||
// Leave last
|
||||
@@ -266,6 +280,7 @@ public:
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
"VerilatedScope*", "char*",
|
||||
"IData", "QData",
|
||||
"LOGIC_IMPLICIT",
|
||||
" MAX"
|
||||
};
|
||||
@@ -278,7 +293,8 @@ public:
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
"dpiScope", "const char*",
|
||||
"",
|
||||
"IData", "QData",
|
||||
"svLogic", // Though shouldn't be needed
|
||||
" MAX"
|
||||
};
|
||||
return names[m_e];
|
||||
@@ -307,11 +323,18 @@ public:
|
||||
case STRING: return 64; // opaque // Just the pointer, for today
|
||||
case SCOPEPTR: return 0; // opaque
|
||||
case CHARPTR: return 0; // opaque
|
||||
case UINT32: return 32;
|
||||
case UINT64: return 64;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
bool isSigned() const {
|
||||
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER;
|
||||
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER
|
||||
|| m_e==DOUBLE || m_e==FLOAT;
|
||||
}
|
||||
bool isUnsigned() const {
|
||||
return m_e==CHANDLE || m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR
|
||||
|| m_e==UINT32 || m_e==UINT64;
|
||||
}
|
||||
bool isFourstate() const {
|
||||
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
|
||||
@@ -320,6 +343,10 @@ public:
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isIntNumeric() const { // Enum increment supported
|
||||
return (m_e==BIT || m_e==BYTE || m_e==INT || m_e==INTEGER || m_e==LOGIC
|
||||
|| m_e==LONGINT || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64);
|
||||
}
|
||||
bool isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
@@ -342,13 +369,6 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
enum AstSignedState {
|
||||
// This can't be in the fancy class as the lexer union will get upset
|
||||
signedst_NOSIGNED=0, signedst_UNSIGNED=1, signedst_SIGNED=2
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstVarType {
|
||||
public:
|
||||
enum en {
|
||||
@@ -365,6 +385,8 @@ public:
|
||||
WIRE,
|
||||
IMPLICITWIRE,
|
||||
TRIWIRE,
|
||||
TRI0,
|
||||
TRI1,
|
||||
PORT, // Temp type used in parser only
|
||||
BLOCKTEMP,
|
||||
MODULETEMP,
|
||||
@@ -380,9 +402,16 @@ public:
|
||||
static const char* names[] = {
|
||||
"?","GPARAM","LPARAM","GENVAR",
|
||||
"VAR","INPUT","OUTPUT","INOUT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE","TRIWIRE","PORT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE",
|
||||
"TRIWIRE","TRI0","TRI1",
|
||||
"PORT",
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
|
||||
return names[m_e]; }
|
||||
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE
|
||||
|| m_e==TRIWIRE
|
||||
|| m_e==TRI0 || m_e==TRI1
|
||||
|| m_e==SUPPLY0 || m_e==SUPPLY1
|
||||
|| m_e==VAR); }
|
||||
};
|
||||
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
||||
@@ -473,10 +502,11 @@ class AstParseRefExp {
|
||||
public:
|
||||
enum en {
|
||||
PX_NONE, // Used in V3LinkParse only
|
||||
PX_VAR_MEM,
|
||||
PX_VAR_ANY,
|
||||
PX_TASK,
|
||||
PX_FUNC
|
||||
PX_TEXT, // Unknown ID component
|
||||
PX_PREDOT, // Module name or misc component above var/task/func/member
|
||||
PX_VAR_MEM, // Variable that must be a memory
|
||||
PX_VAR_ANY, // Variable/structure member
|
||||
PX_FTASK // Task/Function (AstParse::ftaskrefp() will be set)
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstParseRefExp() : m_e(PX_NONE) {}
|
||||
@@ -485,7 +515,7 @@ public:
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"","VAR_MEM","VAR_ANY","TASK","FUNC"};
|
||||
"","TEXT","PREDOT","VAR_MEM","VAR_ANY","FTASK"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -493,6 +523,83 @@ public:
|
||||
inline bool operator== (AstParseRefExp::en lhs, AstParseRefExp rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstParseRefExp rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
// VNumRange - Structure containing numberic range information
|
||||
// See also AstRange, which is a symbolic version of this
|
||||
|
||||
struct VNumRange {
|
||||
int m_msb; // MSB, MSB always >= LSB
|
||||
int m_lsb; // LSB
|
||||
union {
|
||||
int mu_flags;
|
||||
struct {
|
||||
bool m_ranged:1; // Has a range
|
||||
bool m_littleEndian:1; // Bit vector is little endian
|
||||
};
|
||||
};
|
||||
inline bool operator== (const VNumRange& rhs) const {
|
||||
return m_msb == rhs.m_msb
|
||||
&& m_lsb == rhs.m_lsb
|
||||
&& mu_flags == rhs.mu_flags; }
|
||||
inline bool operator< (const VNumRange& rhs) const {
|
||||
if ( (m_msb < rhs.m_msb)) return true;
|
||||
if (!(m_msb == rhs.m_msb)) return false; // lhs > rhs
|
||||
if ( (m_lsb < rhs.m_lsb)) return true;
|
||||
if (!(m_lsb == rhs.m_lsb)) return false; // lhs > rhs
|
||||
if ( (mu_flags < rhs.mu_flags)) return true;
|
||||
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs
|
||||
return false;
|
||||
}
|
||||
//
|
||||
VNumRange() : m_msb(0), m_lsb(0), mu_flags(0) {}
|
||||
~VNumRange() {}
|
||||
// MEMBERS
|
||||
void init(int msb, int lsb, bool littleEndian) {
|
||||
m_msb=msb; m_lsb=lsb; mu_flags=0; m_ranged=true; m_littleEndian=littleEndian;
|
||||
}
|
||||
int msb() const { return m_msb; }
|
||||
int lsb() const { return m_lsb; }
|
||||
int left() const { return littleEndian()?lsb():msb(); } // How to show a declaration
|
||||
int right() const { return littleEndian()?msb():lsb(); }
|
||||
bool ranged() const { return m_ranged; }
|
||||
bool littleEndian() const { return m_littleEndian; }
|
||||
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
|
||||
{ return (!m_ranged || (m_lsb==0 && m_msb>=1 && !m_littleEndian)); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
struct VBasicTypeKey {
|
||||
int m_width; // From AstNodeDType: Bit width of operation
|
||||
int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation
|
||||
AstNumeric m_numeric; // From AstNodeDType: Node is signed
|
||||
AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
|
||||
VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
|
||||
inline bool operator== (const VBasicTypeKey& rhs) const {
|
||||
return m_width == rhs.m_width
|
||||
&& m_widthMin == rhs.m_widthMin
|
||||
&& m_numeric == rhs.m_numeric
|
||||
&& m_keyword == rhs.m_keyword
|
||||
&& m_nrange == rhs.m_nrange; }
|
||||
inline bool operator< (const VBasicTypeKey& rhs) const {
|
||||
if ( (m_width < rhs.m_width)) return true;
|
||||
if (!(m_width == rhs.m_width)) return false; // lhs > rhs
|
||||
if ( (m_widthMin < rhs.m_widthMin)) return true;
|
||||
if (!(m_widthMin == rhs.m_widthMin)) return false; // lhs > rhs
|
||||
if ( (m_numeric < rhs.m_numeric)) return true;
|
||||
if (!(m_numeric == rhs.m_numeric)) return false; // lhs > rhs
|
||||
if ( (m_keyword < rhs.m_keyword)) return true;
|
||||
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
|
||||
if ( (m_nrange < rhs.m_nrange)) return true;
|
||||
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
|
||||
return false; }
|
||||
VBasicTypeKey(int width, int widthMin, AstNumeric numeric, AstBasicDTypeKwd kwd,
|
||||
VNumRange nrange)
|
||||
: m_width(width), m_widthMin(widthMin), m_numeric(numeric),
|
||||
m_keyword(kwd), m_nrange(nrange) {}
|
||||
~VBasicTypeKey() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// AstNUser - Generic pointer base class for AST User nodes.
|
||||
// - Also used to allow parameter passing up/down iterate calls
|
||||
@@ -502,13 +609,13 @@ class LinkVP;
|
||||
class OrderBlockNU;
|
||||
class OrderVarNU;
|
||||
class V3GraphVertex;
|
||||
class V3SymTable;
|
||||
class VSymEnt;
|
||||
struct AstNUser {
|
||||
AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p())
|
||||
// Casters
|
||||
WidthVP* c() { return ((WidthVP*)this); }
|
||||
LinkVP* castLinkVP() { return ((LinkVP*)this); }
|
||||
V3SymTable* castSymTable() { return ((V3SymTable*)this); }
|
||||
VSymEnt* castSymEnt() { return ((VSymEnt*)this); }
|
||||
AstNode* castNode() { return ((AstNode*)this); }
|
||||
OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); }
|
||||
OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); }
|
||||
@@ -738,18 +845,17 @@ class AstNode {
|
||||
static vluint64_t s_editCntGbl; // Global edit counter
|
||||
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
||||
|
||||
AstNodeDType* m_dtypep; // Data type of output or assignment (etc)
|
||||
|
||||
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
||||
int m_cloneCnt; // Mark of when userp was set
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// Attributes
|
||||
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
// // Space for more bools here
|
||||
|
||||
int m_width; // Bit width of operation
|
||||
int m_widthMin; // If unsized, bitwidth of minimum implementation
|
||||
// This member ordering both allows 64 bit alignment and puts associated data together
|
||||
AstNUser* m_user1p; // Pointer to any information the user iteration routine wants
|
||||
uint32_t m_user1Cnt; // Mark of when userp was set
|
||||
@@ -823,6 +929,7 @@ public:
|
||||
AstNode* op2p() const { return m_op2p; }
|
||||
AstNode* op3p() const { return m_op3p; }
|
||||
AstNode* op4p() const { return m_op4p; }
|
||||
AstNodeDType* dtypep() const { return m_dtypep; }
|
||||
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
||||
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
||||
bool brokeExists() const;
|
||||
@@ -863,25 +970,18 @@ public:
|
||||
string prettyTypeName() const; // "VARREF name" for error messages
|
||||
FileLine* fileline() const { return m_fileline; }
|
||||
void fileline(FileLine* fl) { m_fileline=fl; }
|
||||
int width() const { return m_width; }
|
||||
bool width1() const { return width()==1; }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
||||
int widthPow2() const;
|
||||
int widthInstrs() const { return isWide()?widthWords():1; }
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
|
||||
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
|
||||
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
|
||||
AstNumeric numeric() const { return AstNumeric(m_numeric); }
|
||||
bool isUnsigned() const { return numeric().isUnsigned(); }
|
||||
bool width1() const;
|
||||
int widthInstrs() const;
|
||||
void didWidth(bool flag) { m_didWidth=flag; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false;}
|
||||
void doingWidth(bool flag) { m_doingWidth=flag; }
|
||||
bool doingWidth() const { return m_doingWidth; }
|
||||
|
||||
//TODO stomp these width functions out, and call via dtypep() instead
|
||||
int width() const;
|
||||
int widthMin() const;
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
bool isDouble() const;
|
||||
@@ -896,6 +996,7 @@ public:
|
||||
int user1() const { return user1p()->castInt(); }
|
||||
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
||||
int user1Inc() { int v=user1(); user1(v+1); return v; }
|
||||
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
||||
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||
|
||||
AstNUser* user2p() const {
|
||||
@@ -905,6 +1006,7 @@ public:
|
||||
int user2() const { return user2p()->castInt(); }
|
||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
||||
int user2Inc() { int v=user2(); user2(v+1); return v; }
|
||||
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
|
||||
static void user2ClearTree() { AstUser2InUse::clear(); }
|
||||
|
||||
AstNUser* user3p() const {
|
||||
@@ -914,6 +1016,7 @@ public:
|
||||
int user3() const { return user3p()->castInt(); }
|
||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
||||
int user3Inc() { int v=user3(); user3(v+1); return v; }
|
||||
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
|
||||
static void user3ClearTree() { AstUser3InUse::clear(); }
|
||||
|
||||
AstNUser* user4p() const {
|
||||
@@ -923,6 +1026,7 @@ public:
|
||||
int user4() const { return user4p()->castInt(); }
|
||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
||||
int user4Inc() { int v=user4(); user4(v+1); return v; }
|
||||
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
|
||||
static void user4ClearTree() { AstUser4InUse::clear(); }
|
||||
|
||||
AstNUser* user5p() const {
|
||||
@@ -932,6 +1036,7 @@ public:
|
||||
int user5() const { return user5p()->castInt(); }
|
||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
||||
int user5Inc() { int v=user5(); user5(v+1); return v; }
|
||||
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
|
||||
static void user5ClearTree() { AstUser5InUse::clear(); }
|
||||
|
||||
vluint64_t editCount() const { return m_editCount; }
|
||||
@@ -949,17 +1054,33 @@ public:
|
||||
bool isAllOnesV(); // Verilog width rules apply
|
||||
|
||||
// METHODS - data type changes especially for initial creation
|
||||
void dtypeChgSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
|
||||
void dtypeSetBitSized(int widthf, int widthMinf, AstNumeric numericf) { numeric(numericf); width(widthf,widthMinf); }
|
||||
void dtypeSetLogicSized(int widthf, int widthMinf, AstNumeric numericf) { numeric(numericf); width(widthf,widthMinf); }
|
||||
void dtypeSetLogicBool() { numeric(AstNumeric::UNSIGNED); width(1,1); }
|
||||
void dtypeSetDouble() { numeric(AstNumeric::DOUBLE); }
|
||||
void dtypeSetSigned32() { numeric(AstNumeric::SIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
|
||||
void dtypeSetUInt32() { numeric(AstNumeric::UNSIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
|
||||
void dtypeSetUInt64() { numeric(AstNumeric::UNSIGNED); width(VL_QUADSIZE,VL_QUADSIZE); }
|
||||
void dtypep(AstNodeDType* nodep) { if (m_dtypep != nodep) { m_dtypep = nodep; editCountInc(); } }
|
||||
void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }}
|
||||
void dtypeChgSigned(bool flag=true);
|
||||
void dtypeChgWidth(int width, int widthMin);
|
||||
void dtypeChgWidthSigned(int width, int widthMin, bool issigned);
|
||||
void dtypeSetBitSized(int width, int widthMin, AstNumeric numeric) { dtypep(findBitDType(width,widthMin,numeric)); }
|
||||
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
|
||||
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
|
||||
void dtypeSetDouble() { dtypep(findDoubleDType()); }
|
||||
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
|
||||
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
|
||||
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
|
||||
|
||||
// Data type locators
|
||||
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
|
||||
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
|
||||
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
|
||||
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
|
||||
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
|
||||
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
|
||||
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
|
||||
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
|
||||
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
||||
|
||||
// METHODS - dump and error
|
||||
void v3errorEnd(ostringstream& str) const;
|
||||
string warnMore() const;
|
||||
virtual void dump(ostream& str=cout);
|
||||
void dumpGdb(); // For GDB only
|
||||
void dumpGdbHeader() const;
|
||||
@@ -987,9 +1108,11 @@ public:
|
||||
void checkTree(); // User Interface version
|
||||
void dumpPtrs(ostream& str=cout) const;
|
||||
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
|
||||
void dumpTreeGdb(); // For GDB only
|
||||
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTreeFile(const string& filename, bool append=false);
|
||||
static void dumpTreeFileGdb(const char* filenamep=NULL);
|
||||
|
||||
// METHODS - queries
|
||||
virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
|
||||
@@ -1003,6 +1126,7 @@ public:
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
||||
virtual bool same(AstNode* otherp) const { return true; }
|
||||
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
|
||||
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
|
||||
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
virtual bool broken() const { return false; }
|
||||
|
||||
@@ -1022,7 +1146,7 @@ public:
|
||||
// AstAlways* castAlways();
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& os, AstNode* rhs) { rhs->dump(os); return os;}
|
||||
inline ostream& operator<<(ostream& os, AstNode* rhs) { if (!rhs) os<<"NULL"; else rhs->dump(os); return os; }
|
||||
inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
||||
|
||||
//######################################################################
|
||||
@@ -1064,7 +1188,7 @@ struct AstNodeUniop : public AstNodeMath {
|
||||
// Unary math
|
||||
AstNodeUniop(FileLine* fl, AstNode* lhsp)
|
||||
: AstNodeMath(fl) {
|
||||
if (lhsp) widthSignedFrom(lhsp);
|
||||
dtypeFrom(lhsp);
|
||||
setOp1p(lhsp); }
|
||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
@@ -1144,8 +1268,8 @@ struct AstNodeBiComAsv : public AstNodeBiCom {
|
||||
struct AstNodeCond : public AstNodeTriop {
|
||||
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeTriop(fl, condp, expr1p, expr2p) {
|
||||
if (expr1p) widthSignedFrom(expr1p);
|
||||
else if (expr2p) widthSignedFrom(expr2p);
|
||||
if (expr1p) dtypeFrom(expr1p);
|
||||
else if (expr2p) dtypeFrom(expr2p);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeCond)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
||||
@@ -1197,7 +1321,7 @@ struct AstNodeAssign : public AstNodeStmt {
|
||||
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
: AstNodeStmt(fl) {
|
||||
setOp1p(rhsp); setOp2p(lhsp);
|
||||
if (lhsp) widthSignedFrom(lhsp);
|
||||
dtypeFrom(lhsp);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeAssign)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||
@@ -1345,20 +1469,89 @@ public:
|
||||
};
|
||||
|
||||
struct AstNodeDType : public AstNode {
|
||||
// Data type
|
||||
AstNodeDType(FileLine* fl) : AstNode(fl) {}
|
||||
private:
|
||||
// Ideally width() would migrate to BasicDType as that's where it makes sense,
|
||||
// but it's currently so prevalent in the code we leave it here.
|
||||
// Note the below members are included in AstTypeTable::Key lookups
|
||||
int m_width; // (also in AstTypeTable::Key) Bit width of operation
|
||||
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
|
||||
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
|
||||
// Other members
|
||||
bool m_generic; // Simple globally referenced type, don't garbage collect
|
||||
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
AstNodeDType(FileLine* fl) : AstNode(fl) {
|
||||
m_width=0; m_widthMin=0; m_generic=false;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeDType)
|
||||
// Accessors
|
||||
// ACCESSORS
|
||||
virtual void dump(ostream& str);
|
||||
virtual void dumpSmall(ostream& str);
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type
|
||||
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
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
|
||||
//
|
||||
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
||||
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
// For backward compatibility AstArrayDType and others inherit width and signing from the subDType/base type
|
||||
void widthFromSub(AstNodeDType* nodep) { m_width=nodep->m_width; m_widthMin=nodep->m_widthMin; m_numeric=nodep->m_numeric; }
|
||||
//
|
||||
int width() const { return m_width; }
|
||||
void numeric(AstNumeric flag) { m_numeric = flag; }
|
||||
bool isSigned() const { return m_numeric.isSigned(); }
|
||||
bool isNosign() const { return m_numeric.isNosign(); }
|
||||
AstNumeric numeric() const { return m_numeric; }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
||||
int widthPow2() const;
|
||||
void widthMinFromWidth() { m_widthMin = m_width; }
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
bool generic() const { return m_generic; }
|
||||
void generic(bool flag) { m_generic = flag; }
|
||||
AstNodeDType* dtypeDimensionp(int depth);
|
||||
pair<uint32_t,uint32_t> dimensions();
|
||||
uint32_t arrayElements(); // 1, or total multiplication of all dimensions
|
||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||
};
|
||||
|
||||
struct AstNodeClassDType : public AstNodeDType {
|
||||
private:
|
||||
// TYPES
|
||||
typedef map<string,AstMemberDType*> MemberNameMap;
|
||||
// MEMBERS
|
||||
bool m_packed;
|
||||
MemberNameMap m_members;
|
||||
public:
|
||||
AstNodeClassDType(FileLine* fl, AstNumeric numericUnpack)
|
||||
: AstNodeDType(fl) {
|
||||
// AstNumeric::NOSIGN overloaded to indicate not packed
|
||||
m_packed = (numericUnpack != AstNumeric::NOSIGN);
|
||||
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeClassDType)
|
||||
virtual bool broken() const;
|
||||
virtual void dump(ostream& str);
|
||||
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
||||
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
// op1 = members
|
||||
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
|
||||
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
||||
bool packed() const { return m_packed; }
|
||||
void clearCache() { m_members.clear(); }
|
||||
void repairMemberCache();
|
||||
AstMemberDType* findMember(const string& name) const {
|
||||
MemberNameMap::const_iterator it = m_members.find(name);
|
||||
return (it==m_members.end()) ? NULL : it->second;
|
||||
}
|
||||
};
|
||||
|
||||
struct AstNodeSel : public AstNodeBiop {
|
||||
@@ -1491,13 +1684,14 @@ private:
|
||||
bool m_modPublic:1; // Module has public references
|
||||
bool m_modTrace:1; // Tracing this module
|
||||
bool m_inLibrary:1; // From a library, no error if not used, never top level
|
||||
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
|
||||
int m_level; // 1=top module, 2=cell off top module, ...
|
||||
int m_varNum; // Incrementing variable number
|
||||
public:
|
||||
AstNodeModule(FileLine* fl, const string& name)
|
||||
: AstNode (fl)
|
||||
,m_name(name), m_origName(name)
|
||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false)
|
||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false)
|
||||
,m_level(0), m_varNum(0) { }
|
||||
ASTNODE_BASE_FUNCS(NodeModule)
|
||||
virtual void dump(ostream& str);
|
||||
@@ -1522,6 +1716,8 @@ public:
|
||||
bool modPublic() const { return m_modPublic; }
|
||||
void modTrace(bool flag) { m_modTrace = flag; }
|
||||
bool modTrace() const { return m_modTrace; }
|
||||
void dead(bool flag) { m_dead = flag; }
|
||||
bool dead() const { return m_dead; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -1535,8 +1731,12 @@ public:
|
||||
//######################################################################
|
||||
// Inline ACCESSORS
|
||||
|
||||
inline bool AstNode::isDouble() const { return numeric().isDouble(); }
|
||||
inline bool AstNode::isSigned() const { return numeric().isSigned(); }
|
||||
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
||||
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
||||
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
|
||||
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
||||
inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
|
||||
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
||||
|
||||
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
|
||||
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
|
||||
@@ -1544,6 +1744,6 @@ inline bool AstNode::isOne() { return (this->castConst() && this->castConst
|
||||
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
|
||||
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
|
||||
|
||||
inline void AstNodeVarRef::init() { if (m_varp) widthSignedFrom((AstNode*)m_varp); }
|
||||
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+254
-31
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -48,6 +46,28 @@ int AstNodeSel::bitConst() const {
|
||||
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
|
||||
}
|
||||
|
||||
void AstNodeClassDType::repairMemberCache() {
|
||||
clearCache();
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
|
||||
else m_members.insert(make_pair(itemp->name(), itemp));
|
||||
}
|
||||
}
|
||||
|
||||
bool AstNodeClassDType::broken() const {
|
||||
set<AstMemberDType*> exists;
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||
exists.insert(itemp);
|
||||
}
|
||||
for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) {
|
||||
if (exists.find(it->second) == exists.end()) {
|
||||
this->v3error("Internal: Structure member broken: "<<it->first);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int AstBasicDType::widthAlignBytes() const {
|
||||
if (width()<=8) return 1;
|
||||
else if (width()<=16) return 2;
|
||||
@@ -62,6 +82,22 @@ int AstBasicDType::widthTotalBytes() const {
|
||||
else return widthWords()*(VL_WORDSIZE/8);
|
||||
}
|
||||
|
||||
int AstNodeClassDType::widthTotalBytes() const {
|
||||
if (width()<=8) return 1;
|
||||
else if (width()<=16) return 2;
|
||||
else if (isQuad()) return 8;
|
||||
else return widthWords()*(VL_WORDSIZE/8);
|
||||
}
|
||||
|
||||
int AstNodeClassDType::widthAlignBytes() const {
|
||||
// Could do max across members but that would be slow,
|
||||
// instead intuit based on total structure size
|
||||
if (width()<=8) return 1;
|
||||
else if (width()<=16) return 2;
|
||||
else if (width()<=32) return 4;
|
||||
else return 8;
|
||||
}
|
||||
|
||||
bool AstVar::isSigPublic() const {
|
||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||
}
|
||||
@@ -75,16 +111,26 @@ bool AstVar::isScBv() const {
|
||||
}
|
||||
|
||||
void AstVar::combineType(AstVarType type) {
|
||||
// These flags get combined with the existing settings of the flags.
|
||||
// We don't test varType for certain types, instead set flags since
|
||||
// when we combine wires cross-hierarchy we need a union of all characteristics.
|
||||
if (type == AstVarType::SUPPLY0) type = AstVarType::WIRE;
|
||||
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
|
||||
m_varType=type; // For debugging prints only
|
||||
// These flags get combined with the existing settings of the flags.
|
||||
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
|
||||
m_input = true;
|
||||
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT)
|
||||
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
|
||||
m_output = true;
|
||||
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE)
|
||||
m_declOutput = true;
|
||||
}
|
||||
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE
|
||||
|| type==AstVarType::TRI0 || type==AstVarType::TRI1)
|
||||
m_tristate = true;
|
||||
if (type==AstVarType::TRI0)
|
||||
m_isPulldown = true;
|
||||
if (type==AstVarType::TRI1)
|
||||
m_isPullup = true;
|
||||
}
|
||||
|
||||
string AstVar::verilogKwd() const {
|
||||
@@ -277,6 +323,14 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
|
||||
if (adtypep->packed()) {
|
||||
if ((dim++) == dimension) {
|
||||
return adtypep;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
// Node no ->next in loop; use continue where necessary
|
||||
break;
|
||||
}
|
||||
@@ -318,6 +372,15 @@ pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
|
||||
return make_pair(packed, unpacked);
|
||||
}
|
||||
|
||||
int AstNodeDType::widthPow2() const {
|
||||
// I.e. width 30 returns 32, width 32 returns 32.
|
||||
uint32_t width = this->width();
|
||||
for (int p2=30; p2>=0; p2--) {
|
||||
if (width > (1UL<<p2)) return (1UL<<(p2+1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Special operators
|
||||
int AstArraySel::dimension(AstNode* nodep) {
|
||||
// How many dimensions is this reference from the base variable?
|
||||
@@ -337,7 +400,7 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable
|
||||
while (nodep) {
|
||||
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
||||
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
|
||||
// AstNodeSelPre stashes the associated variable under a ATTROF so it isn't constified
|
||||
// AstNodeSelPre stashes the associated variable under a ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
|
||||
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
|
||||
else if (nodep->castNodePreSel()) {
|
||||
if (nodep->castNodePreSel()->attrp()) {
|
||||
@@ -432,6 +495,87 @@ bool AstSenTree::hasCombo() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void AstTypeTable::clearCache() {
|
||||
// When we mass-change widthMin in V3WidthCommit, we need to correct the table.
|
||||
// Just clear out the maps; the search functions will be used to rebuild the map
|
||||
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
m_basicps[i] = NULL;
|
||||
}
|
||||
for (int isbit=0; isbit<_IDX0_MAX; ++isbit) {
|
||||
for (int numer=0; numer<AstNumeric::_ENUM_MAX; ++numer) {
|
||||
LogicMap& mapr = m_logicMap[isbit][numer];
|
||||
mapr.clear();
|
||||
}
|
||||
}
|
||||
m_detailedMap.clear();
|
||||
// Clear generic()'s so dead detection will work
|
||||
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
|
||||
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
|
||||
bdtypep->generic(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AstTypeTable::repairCache() {
|
||||
// After we mass-change widthMin in V3WidthCommit, we need to correct the table.
|
||||
clearCache();
|
||||
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
|
||||
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
|
||||
(void)findInsertSameDType(bdtypep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd) {
|
||||
if (m_basicps[kwd]) return m_basicps[kwd];
|
||||
//
|
||||
AstBasicDType* new1p = new AstBasicDType(fl, kwd);
|
||||
// Because the detailed map doesn't update this map,
|
||||
// check the detailed map for this same node
|
||||
// Also adds this new node to the detailed map
|
||||
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||
if (newp != new1p) new1p->deleteTree();
|
||||
else addTypesp(newp);
|
||||
//
|
||||
m_basicps[kwd] = newp;
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||
int width, int widthMin, AstNumeric numeric) {
|
||||
int idx = IDX0_LOGIC;
|
||||
if (kwd == AstBasicDTypeKwd::LOGIC) idx = IDX0_LOGIC;
|
||||
else if (kwd == AstBasicDTypeKwd::BIT) idx = IDX0_BIT;
|
||||
else fl->v3fatalSrc("Bad kwd for findLogicBitDType");
|
||||
pair<int,int> widths = make_pair(width,widthMin);
|
||||
LogicMap& mapr = m_logicMap[idx][(int)numeric];
|
||||
LogicMap::const_iterator it = mapr.find(widths);
|
||||
if (it != mapr.end()) return it->second;
|
||||
//
|
||||
AstBasicDType* new1p = new AstBasicDType(fl, AstBasicDTypeKwd::BIT, numeric, width, widthMin);
|
||||
// Because the detailed map doesn't update this map,
|
||||
// check the detailed map for this same node, and if found update this map
|
||||
// Also adds this new node to the detailed map
|
||||
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||
if (newp != new1p) new1p->deleteTree();
|
||||
else addTypesp(newp);
|
||||
//
|
||||
mapr.insert(make_pair(widths,newp));
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
||||
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
|
||||
nodep->keyword(), nodep->nrange());
|
||||
DetailedMap& mapr = m_detailedMap;
|
||||
DetailedMap::const_iterator it = mapr.find(key);
|
||||
if (it != mapr.end()) return it->second;
|
||||
mapr.insert(make_pair(key,nodep));
|
||||
nodep->generic(true);
|
||||
// No addTypesp; the upper function that called new() is responsible for adding
|
||||
return nodep;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Special walking tree inserters
|
||||
|
||||
@@ -502,11 +646,21 @@ void AstNode::dump(ostream& str) {
|
||||
//<<" "<<(void*)this->m_backp
|
||||
<<" <e"<<dec<<editCount()
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) str<<"/"<<widthMin();
|
||||
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}";
|
||||
if (user1p()) str<<" u1="<<(void*)user1p();
|
||||
if (user2p()) str<<" u2="<<(void*)user2p();
|
||||
if (user3p()) str<<" u3="<<(void*)user3p();
|
||||
if (user4p()) str<<" u4="<<(void*)user4p();
|
||||
if (user5p()) str<<" u5="<<(void*)user5p();
|
||||
if (hasDType()) {
|
||||
if (dtypep()==this) str<<" @dt="<<"this@";
|
||||
else str<<" @dt="<<(void*)dtypep()<<"@"; // Final @ so less likely to by accident think it's nodep
|
||||
if (AstNodeDType* dtp = dtypep()) {
|
||||
dtp->dumpSmall(str);
|
||||
}
|
||||
} else { // V3Broken will throw an error
|
||||
if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep();
|
||||
}
|
||||
if (name()!="") str<<" "<<AstNode::quoteName(name());
|
||||
}
|
||||
|
||||
@@ -526,7 +680,6 @@ void AstBasicDType::dump(ostream& str) {
|
||||
this->AstNodeDType::dump(str);
|
||||
str<<" kwd="<<keyword().ascii();
|
||||
if (isRanged() && !rangep()) str<<" range=["<<left()<<":"<<right()<<"]";
|
||||
if (implicit()) str<<" [IMPLICIT]";
|
||||
}
|
||||
void AstCCast::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -572,8 +725,87 @@ void AstRefDType::dump(ostream& str) {
|
||||
if (defp()) { str<<" -> "; defp()->dump(str); }
|
||||
else { str<<" -> UNLINKED"; }
|
||||
}
|
||||
void AstNodeClassDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packed()) str<<" [PACKED]";
|
||||
}
|
||||
void AstNodeDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (generic()) str<<" [GENERIC]";
|
||||
if (AstNodeDType* dtp = virtRefDTypep()) {
|
||||
str<<" refdt="<<(void*)(dtp);
|
||||
dtp->dumpSmall(str);
|
||||
}
|
||||
}
|
||||
void AstNodeDType::dumpSmall(ostream& str) {
|
||||
str<<"("
|
||||
<<(generic()?"G/":"")
|
||||
<<((isSigned()&&!isDouble())?"s":"")
|
||||
<<(isNosign()?"n":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) str<<"/"<<widthMin();
|
||||
str<<")";
|
||||
}
|
||||
void AstNodeModule::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" L"<<level();
|
||||
if (modPublic()) str<<" [P]";
|
||||
if (inLibrary()) str<<" [LIB]";
|
||||
if (dead()) str<<" [DEAD]";
|
||||
}
|
||||
void AstPackageImport::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> "<<packagep();
|
||||
}
|
||||
void AstTypeTable::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
if (AstBasicDType* subnodep=m_basicps[i]) {
|
||||
str<<endl; // Newline from caller, so newline first
|
||||
str<<"\t\t"<<setw(8)<<AstBasicDTypeKwd(i).ascii();
|
||||
str<<" -> ";
|
||||
subnodep->dump(str);
|
||||
}
|
||||
}
|
||||
for (int isbit=0; isbit<2; ++isbit) {
|
||||
for (int issigned=0; issigned<AstNumeric::_ENUM_MAX; ++issigned) {
|
||||
LogicMap& mapr = m_logicMap[isbit][issigned];
|
||||
for (LogicMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
|
||||
AstBasicDType* dtypep = it->second;
|
||||
str<<endl; // Newline from caller, so newline first
|
||||
stringstream nsstr;
|
||||
nsstr<<(isbit?"bw":"lw")
|
||||
<<it->first.first<<"/"<<it->first.second;
|
||||
str<<"\t\t"<<setw(8)<<nsstr.str();
|
||||
if (issigned) str<<" s"; else str<<" u";
|
||||
str<<" -> ";
|
||||
dtypep->dump(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
DetailedMap& mapr = m_detailedMap;
|
||||
for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
|
||||
AstBasicDType* dtypep = it->second;
|
||||
str<<endl; // Newline from caller, so newline first
|
||||
stringstream nsstr;
|
||||
str<<"\t\tdetailed -> ";
|
||||
dtypep->dump(str);
|
||||
}
|
||||
}
|
||||
// Note get newline from caller too.
|
||||
}
|
||||
|
||||
void AstVarScope::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (isCircular()) str<<" [CIRC]";
|
||||
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||
else { str<<" ->UNLINKED"; }
|
||||
}
|
||||
void AstVarXRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
str<<dotted()<<". - ";
|
||||
@@ -582,27 +814,9 @@ void AstVarXRef::dump(ostream& str) {
|
||||
else if (varp()) { varp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
}
|
||||
void AstNodeDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
}
|
||||
void AstNodeModule::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" L"<<level();
|
||||
if (modPublic()) str<<" [P]";
|
||||
if (inLibrary()) str<<" [LIB]";
|
||||
}
|
||||
void AstPackageImport::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> "<<packagep();
|
||||
}
|
||||
void AstVarScope::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (isCircular()) str<<" [CIRC]";
|
||||
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||
else { str<<" ->UNLINKED"; }
|
||||
}
|
||||
void AstVarRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
if (varScopep()) { varScopep()->dump(str); }
|
||||
@@ -619,6 +833,8 @@ void AstVar::dump(ostream& str) {
|
||||
else if (isOutput()) str<<" [O]";
|
||||
}
|
||||
if (isConst()) str<<" [CONST]";
|
||||
if (isPullup()) str<<" [PULLUP]";
|
||||
if (isPulldown()) str<<" [PULLDOWN]";
|
||||
if (isUsedClock()) str<<" [CLK]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
@@ -640,6 +856,11 @@ void AstSenItem::dump(ostream& str) {
|
||||
void AstParseRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" ["<<expect().ascii()<<"]";
|
||||
if (start()) str<<" [START]";
|
||||
}
|
||||
void AstDot::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (start()) str<<" [START]";
|
||||
}
|
||||
void AstActive::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -649,6 +870,7 @@ void AstActive::dump(ostream& str) {
|
||||
}
|
||||
void AstNodeFTaskRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
str<<" -> ";
|
||||
if (dotted()!="") { str<<dotted()<<". - "; }
|
||||
if (taskp()) { taskp()->dump(str); }
|
||||
@@ -665,7 +887,8 @@ void AstNodeFTask::dump(ostream& str) {
|
||||
void AstBegin::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (unnamed()) str<<" [UNNAMED]";
|
||||
if (hidden()) str<<" [HIDDEN]";
|
||||
if (generate()) str<<" [GEN]";
|
||||
if (genforp()) str<<" [GENFOR]";
|
||||
}
|
||||
void AstCoverDecl::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
|
||||
+467
-218
File diff suppressed because it is too large
Load Diff
+1
-10
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -144,24 +142,17 @@ private:
|
||||
|
||||
// Remap var names and replace lower Begins
|
||||
nodep->stmtsp()->iterateAndNext(*this);
|
||||
|
||||
if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier");
|
||||
}
|
||||
m_namedScope = oldScope;
|
||||
m_unnamedScope = oldUnnamed;
|
||||
|
||||
// Don't change var names of generate FOR() variables, but do recurse into a child FOR
|
||||
nodep->flatsp()->iterateAndNext(*this);
|
||||
|
||||
// Cleanup
|
||||
AstNode* addsp = NULL;
|
||||
if (AstNode* stmtsp = nodep->stmtsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
addsp = addsp->addNextNull(stmtsp);
|
||||
}
|
||||
if (AstNode* stmtsp = nodep->flatsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
addsp = addsp->addNextNull(stmtsp);
|
||||
}
|
||||
if (addsp) {
|
||||
nodep->replaceWith(addsp);
|
||||
} else {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+30
-11
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -58,7 +56,7 @@ public:
|
||||
// METHODS
|
||||
static void deleted(const AstNode* nodep) {
|
||||
// Called by operator delete on any node - only if VL_LEAK_CHECKS
|
||||
if (debug()) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
||||
if (debug()>=9) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
||||
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
|
||||
@@ -67,7 +65,7 @@ public:
|
||||
}
|
||||
static void addNewed(const AstNode* nodep) {
|
||||
// Called by operator new on any node - only if VL_LEAK_CHECKS
|
||||
if (debug()) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
||||
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
|
||||
@@ -148,7 +146,7 @@ public:
|
||||
&& (it->first->backp() ? backs==1 : backs==0)) {
|
||||
// Use only AstNode::dump instead of the virtual one, as there
|
||||
// may be varp() and other cross links that are bad.
|
||||
if (debug()) {
|
||||
if (v3Global.opt.debugCheck()) {
|
||||
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
||||
((AstNode*)(it->first))->AstNode::dump(cerr);
|
||||
cerr<<endl;
|
||||
@@ -207,9 +205,22 @@ private:
|
||||
if (nodep->broken()) {
|
||||
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)");
|
||||
}
|
||||
if (nodep->dtypep()) {
|
||||
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
else if (!nodep->dtypep()->castNodeDType()) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
}
|
||||
if (v3Global.assertDTypesResolved()) {
|
||||
if (!nodep->width() && nodep->castNodeMath()) {
|
||||
nodep->v3fatalSrc("Math node has no assigned width");
|
||||
if (nodep->hasDType()) {
|
||||
if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype on node with hasDType(): "<<nodep->prettyTypeName());
|
||||
} else {
|
||||
if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName());
|
||||
}
|
||||
if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed");
|
||||
if (AstNodeDType* dnodep = nodep->castNodeDType()) {
|
||||
if (dnodep->width() != dnodep->widthMin()
|
||||
&& v3Global.assertWidthsMatch()) {
|
||||
dnodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v3Global.assertWidthsMatch()) {
|
||||
@@ -233,10 +244,18 @@ public:
|
||||
|
||||
void V3Broken::brokenAll(AstNetlist* nodep) {
|
||||
//UINFO(9,__FUNCTION__<<": "<<endl);
|
||||
BrokenTable::prepForTree();
|
||||
BrokenMarkVisitor mvisitor (nodep);
|
||||
BrokenCheckVisitor cvisitor (nodep);
|
||||
BrokenTable::doneWithTree();
|
||||
static bool inBroken = false;
|
||||
if (inBroken) {
|
||||
// A error called by broken can recurse back into broken; avoid this
|
||||
UINFO(1,"Broken called under broken, skipping recursion.\n");
|
||||
} else {
|
||||
inBroken = true;
|
||||
BrokenTable::prepForTree();
|
||||
BrokenMarkVisitor mvisitor (nodep);
|
||||
BrokenCheckVisitor cvisitor (nodep);
|
||||
BrokenTable::doneWithTree();
|
||||
inBroken = false;
|
||||
}
|
||||
}
|
||||
|
||||
void V3Broken::addNewed(AstNode* nodep) {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+1
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -198,7 +196,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
// Defaults were moved to last in the caseitem list by V3Link
|
||||
// Defaults were moved to last in the caseitem list by V3LinkDot
|
||||
if (itemp->isDefault()) { // Case statement's default... Fill the table
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+3
-5
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -362,7 +360,7 @@ private:
|
||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
|
||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
||||
if (vertexp->user()>=m_userGeneration) return NULL; // Processed - prevent loop
|
||||
vertexp->user(m_userGeneration);
|
||||
|
||||
CdcEitherVertex* mark_outp = NULL;
|
||||
@@ -385,7 +383,7 @@ private:
|
||||
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
||||
eFromVertexp->asyncPath(true);
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
// Also ok if from flop, but partially trace the flop so more obvious to users
|
||||
if (vvertexp->fromFlop()) {
|
||||
@@ -393,7 +391,7 @@ private:
|
||||
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
|
||||
eFromVertexp->asyncPath(true);
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+4
-5
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -94,8 +92,9 @@ private:
|
||||
int lsb = isArray ? arrayp->lsb() : 0;
|
||||
if (isArray && ((msb - lsb + 1) > DETECTARRAY_MAX_INDEXES)) {
|
||||
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<<cvtToStr(DETECTARRAY_MAX_INDEXES)
|
||||
<<" array indexes (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
||||
vscp->v3warn(E_DETECTARRAY, "... Could recompile with DETECTARRAY_MAX_INDEXES increased to at least "<<cvtToStr(msb-lsb+1));
|
||||
<<" array indexes (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName()<<endl
|
||||
<<vscp->warnMore()
|
||||
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased to at least "<<cvtToStr(msb-lsb+1));
|
||||
} else if (!isArray
|
||||
&& !varp->dtypeSkipRefp()->castBasicDType()) {
|
||||
if (debug()) varp->dumpTree(cout,"-DETECTARRAY-");
|
||||
@@ -160,7 +159,7 @@ private:
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
if (nodep->isCircular()) {
|
||||
UINFO(8," CIRC "<<nodep<<endl);
|
||||
if (!nodep->user1Inc()) {
|
||||
if (!nodep->user1SetOnce()) {
|
||||
genChangeDet(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+20
-8
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -49,8 +47,10 @@ private:
|
||||
// Entire netlist:
|
||||
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN
|
||||
// AstNode::user2() -> bool. True indicates widthMin has been propagated
|
||||
// AstNodeDType::user3() -> AstNodeDType*. Alternative node with C size
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
|
||||
// TYPES
|
||||
enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
||||
@@ -71,16 +71,28 @@ private:
|
||||
else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE;
|
||||
else return nodep->widthWords()*VL_WORDSIZE;
|
||||
}
|
||||
void setCppWidth (AstNode* nodep, int width, int widthMin) {
|
||||
void setCppWidth (AstNode* nodep) {
|
||||
nodep->user2(true); // Don't resize it again
|
||||
nodep->width(width, widthMin);
|
||||
AstNodeDType* old_dtypep = nodep->dtypep();
|
||||
int width=cppWidth(nodep); // widthMin is unchanged
|
||||
if (old_dtypep->width() != width) {
|
||||
// Since any given dtype's cppWidth() is the same, we can just
|
||||
// remember one convertion for each, and reuse it
|
||||
if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNode()->castNodeDType()) {
|
||||
nodep->dtypep(new_dtypep);
|
||||
} else {
|
||||
nodep->dtypeChgWidth(width, nodep->widthMin());
|
||||
AstNodeDType* new_dtypep2 = nodep->dtypep();
|
||||
if (new_dtypep2 == old_dtypep) nodep->v3fatalSrc("Dtype didn't change when width changed");
|
||||
old_dtypep->user3p(new_dtypep2); // Remember for next time
|
||||
}
|
||||
}
|
||||
}
|
||||
void computeCppWidth (AstNode* nodep) {
|
||||
if (!nodep->user2()) {
|
||||
if (!nodep->user2() && nodep->hasDType()) {
|
||||
if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths!
|
||||
setCppWidth(nodep, nodep->width(), nodep->width()); // set widthMin anyways so can see it later
|
||||
} else {
|
||||
setCppWidth(nodep, cppWidth(nodep), nodep->widthMin());
|
||||
setCppWidth(nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +129,7 @@ private:
|
||||
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), mask),
|
||||
nodep);
|
||||
setCppWidth (cleanp, cppWidth(nodep), nodep->widthMin());
|
||||
cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS
|
||||
relinkHandle.relink(cleanp);
|
||||
}
|
||||
void insureClean(AstNode* nodep) {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+1
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2008-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -705,7 +703,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
if (debug()>=9) cout<<endl<<endl<<endl;
|
||||
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
||||
if (nodep->user4Inc()) return;
|
||||
if (nodep->user4SetOnce()) return;
|
||||
|
||||
clear();
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+134
-52
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -107,8 +105,10 @@ private:
|
||||
bool m_doNConst; // Enable non-constant-child simplifications
|
||||
bool m_doShort; // Remove expressions that short circuit
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
bool m_doGenerate; // Postpone width checking inside generate
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNode* m_scopep; // Current scope
|
||||
AstAttrOf* m_attrp; // Current attribute
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -173,13 +173,16 @@ private:
|
||||
return rnodep->lhsp()->castConst();
|
||||
}
|
||||
static bool operandAndOrSame(AstNode* nodep) {
|
||||
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
|
||||
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
|
||||
AstNodeBiop* np = nodep->castNodeBiop();
|
||||
AstNodeBiop* lp = np->lhsp()->castNodeBiop();
|
||||
AstNodeBiop* rp = np->rhsp()->castNodeBiop();
|
||||
return (lp && rp
|
||||
&& lp->width()==rp->width()
|
||||
&& lp->type()==rp->type()
|
||||
&& operandsSame(lp->lhsp(),rp->lhsp()));
|
||||
&& (operandsSame(lp->lhsp(),rp->lhsp())
|
||||
|| operandsSame(lp->rhsp(),rp->rhsp())));
|
||||
}
|
||||
static bool matchOrAndNot(AstNodeBiop* nodep) {
|
||||
// AstOr{$a, AstAnd{AstNot{$b}, $c}} if $a.width1, $a==$b => AstOr{$a,$c}
|
||||
@@ -368,6 +371,11 @@ private:
|
||||
// Extraction checks
|
||||
bool warnSelect(AstSel* nodep) {
|
||||
AstNode* basefromp = AstArraySel::baseFromp(nodep);
|
||||
if (m_doGenerate) {
|
||||
// Never checked yet
|
||||
V3Width::widthParamsEdit(nodep);
|
||||
nodep->iterateChildren(*this); // May need "constifying"
|
||||
}
|
||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||
AstVar* varp = varrefp->varp();
|
||||
if (!varp->dtypep()) varp->v3fatalSrc("Data type lost");
|
||||
@@ -404,7 +412,11 @@ private:
|
||||
return node1p->sameTree(node2p);
|
||||
}
|
||||
else if (node1p->castVarRef() && node2p->castVarRef()) {
|
||||
return node1p->sameTree(node2p);
|
||||
// Avoid comparing widthMin's, which results in lost optimization attempts
|
||||
// If cleanup sameTree to be smarter, this can be restored.
|
||||
//return node1p->sameTree(node2p);
|
||||
return node1p->castVarRef()->varp() == node2p->castVarRef()->varp()
|
||||
&& node1p->castVarRef()->lvalue() == node2p->castVarRef()->lvalue();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -442,7 +454,7 @@ private:
|
||||
oldp->v3fatalSrc("Already constant??\n");
|
||||
}
|
||||
AstNode* newp = new AstConst(oldp->fileline(), num);
|
||||
newp->widthSignedFrom(oldp);
|
||||
newp->dtypeFrom(oldp);
|
||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||
if (debug()>5) newp->dumpTree(cout," _new: ");
|
||||
oldp->replaceWith(newp);
|
||||
@@ -477,7 +489,7 @@ private:
|
||||
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), 0),
|
||||
checkp->unlinkFrBack());
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
@@ -524,10 +536,24 @@ private:
|
||||
void replaceWChild(AstNode* nodep, AstNode* childp) {
|
||||
// NODE(..., CHILD(...)) -> CHILD(...)
|
||||
childp->unlinkFrBackWithNext();
|
||||
childp->widthSignedFrom(nodep);
|
||||
childp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(childp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
//! Replace a ternary node with its RHS after iterating
|
||||
//! Used with short-circuting, where the RHS has not yet been iterated.
|
||||
void replaceWIteratedRhs(AstNodeTriop* nodep) {
|
||||
if (AstNode *rhsp = nodep->rhsp()) rhsp->iterateAndNext(*this);
|
||||
replaceWChild(nodep, nodep->rhsp()); // May have changed
|
||||
}
|
||||
|
||||
//! Replace a ternary node with its THS after iterating
|
||||
//! Used with short-circuting, where the THS has not yet been iterated.
|
||||
void replaceWIteratedThs(AstNodeTriop* nodep) {
|
||||
if (AstNode *thsp = nodep->thsp()) thsp->iterateAndNext(*this);
|
||||
replaceWChild(nodep, nodep->thsp()); // May have changed
|
||||
}
|
||||
void replaceWLhs(AstNodeUniop* nodep) {
|
||||
// Keep LHS, remove RHS
|
||||
replaceWChild(nodep, nodep->lhsp());
|
||||
@@ -584,7 +610,9 @@ private:
|
||||
//nodep->dumpTree(cout, " repAsvRUp_new: ");
|
||||
}
|
||||
void replaceAndOr (AstNodeBiop* nodep) {
|
||||
// Or(And(CONSTll,lr),And(CONSTrl==ll,rr)) -> And(CONSTll,Or(lr,rr))
|
||||
// OR (AND (CONSTll,lr), AND(CONSTrl==ll,rr)) -> AND (CONSTll, OR(lr,rr))
|
||||
// OR (AND (CONSTll,lr), AND(CONSTrl, rr=lr)) -> AND (OR(ll,rl), rr)
|
||||
// nodep ^lp ^llp ^lrp ^rp ^rlp ^rrp
|
||||
// (Or/And may also be reversed)
|
||||
AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop();
|
||||
AstNode* llp = lp->lhsp()->unlinkFrBack();
|
||||
@@ -593,12 +621,23 @@ private:
|
||||
AstNode* rlp = rp->lhsp()->unlinkFrBack();
|
||||
AstNode* rrp = rp->rhsp()->unlinkFrBack();
|
||||
nodep->replaceWith(lp);
|
||||
lp->lhsp(llp);
|
||||
lp->rhsp(nodep);
|
||||
nodep->lhsp(lrp);
|
||||
nodep->rhsp(rrp);
|
||||
rp->deleteTree();
|
||||
rlp->deleteTree();
|
||||
if (operandsSame(llp,rlp)) {
|
||||
lp->lhsp(llp);
|
||||
lp->rhsp(nodep);
|
||||
nodep->lhsp(lrp);
|
||||
nodep->rhsp(rrp);
|
||||
rp->deleteTree();
|
||||
rlp->deleteTree();
|
||||
} else if (operandsSame(lrp, rrp)) {
|
||||
lp->lhsp(nodep);
|
||||
lp->rhsp(rrp);
|
||||
nodep->lhsp(llp);
|
||||
nodep->rhsp(rlp);
|
||||
rp->deleteTree();
|
||||
lrp->deleteTree();
|
||||
} else {
|
||||
nodep->v3fatalSrc("replaceAndOr on something operandAndOrSame shouldn't have matched");
|
||||
}
|
||||
//nodep->dumpTree(cout, " repAndOr_new: ");
|
||||
}
|
||||
void replaceShiftSame (AstNodeBiop* nodep) {
|
||||
@@ -626,7 +665,7 @@ private:
|
||||
AstNode* newp = (nodep->castExtendS()
|
||||
? (new AstExtendS(nodep->fileline(), arg0p))->castNode()
|
||||
: (new AstExtend (nodep->fileline(), arg0p))->castNode());
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replacePowShift (AstNodeBiop* nodep) { // Pow or PowS
|
||||
@@ -635,8 +674,8 @@ private:
|
||||
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), 1),
|
||||
rhsp);
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->lhsp()->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
newp->lhsp()->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift
|
||||
@@ -645,7 +684,7 @@ private:
|
||||
AstNode* opp = nodep->rhsp()->unlinkFrBack();
|
||||
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), amount));
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift
|
||||
@@ -654,7 +693,7 @@ private:
|
||||
AstNode* opp = nodep->lhsp()->unlinkFrBack();
|
||||
AstShiftR* newp = new AstShiftR(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), amount));
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceShiftOp (AstNodeBiop* nodep) {
|
||||
@@ -714,11 +753,11 @@ private:
|
||||
newp = new AstShiftL(nodep->fileline(), ap,
|
||||
new AstConst(nodep->fileline(), newshift));
|
||||
}
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
newp = new AstAnd (nodep->fileline(),
|
||||
newp,
|
||||
new AstConst (nodep->fileline(), mask));
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
//newp->dumpTree(cout, " repShiftShift_new: ");
|
||||
newp->accept(*this); // Further reduce, either node may have more reductions.
|
||||
@@ -838,16 +877,14 @@ private:
|
||||
// Form ranges
|
||||
AstSel* sel1p = new AstSel(conp->fileline(), rhsp, lsb1, msb1-lsb1+1);
|
||||
AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2-lsb2+1);
|
||||
sel1p->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
// Make new assigns of same flavor as old one
|
||||
//*** Not cloneTree; just one node.
|
||||
AstNode* newp = NULL;
|
||||
if (!need_temp) {
|
||||
AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
||||
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn1ap->dtypeFrom(sel1p);
|
||||
asn2ap->dtypeFrom(sel2p);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
@@ -876,10 +913,10 @@ private:
|
||||
AstNodeAssign* asn2bp=nodep->cloneType
|
||||
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
|
||||
->castNodeAssign();
|
||||
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn1ap->dtypeFrom(temp1p);
|
||||
asn1bp->dtypeFrom(temp1p);
|
||||
asn2ap->dtypeFrom(temp2p);
|
||||
asn2bp->dtypeFrom(temp2p);
|
||||
// This order matters
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
@@ -925,7 +962,7 @@ private:
|
||||
AstAnd* newp = new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), val),
|
||||
fromp);
|
||||
newp->width(nodep->width(), nodep->width()); // widthMin no longer applicable
|
||||
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
||||
@@ -939,7 +976,7 @@ private:
|
||||
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
|
||||
<<nodep->prettyTypeName()<<endl
|
||||
<<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
|
||||
<<errorp->warnMore()<<"... Location of non-constant "
|
||||
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||
replaceZero(nodep); nodep=NULL;
|
||||
} else {
|
||||
@@ -1076,8 +1113,8 @@ private:
|
||||
// expression, not the potentially smaller lsb1p's width
|
||||
newlsbp = new AstAdd(lsb1p->fileline(),
|
||||
lsb2p, new AstExtend(lsb1p->fileline(), lsb1p));
|
||||
newlsbp->widthFrom(lsb2p); // Unsigned
|
||||
newlsbp->castAdd()->rhsp()->widthFrom(lsb2p); // Unsigned
|
||||
newlsbp->dtypeFrom(lsb2p); // Unsigned
|
||||
newlsbp->castAdd()->rhsp()->dtypeFrom(lsb2p);
|
||||
}
|
||||
AstSel* newp = new AstSel(nodep->fileline(),
|
||||
fromp,
|
||||
@@ -1137,7 +1174,7 @@ private:
|
||||
fromp,
|
||||
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||
widthp);
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
@@ -1155,7 +1192,7 @@ private:
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
fromp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceSelIntoUniop(AstSel* nodep) {
|
||||
@@ -1168,16 +1205,22 @@ private:
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
bilhsp, lsbp, widthp));
|
||||
fromp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
AstAttrOf* oldAttr = m_attrp;
|
||||
m_attrp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_attrp = oldAttr;
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
bool did=false;
|
||||
if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
|
||||
if (m_doV && nodep->varp()->hasSimpleInit() && !m_attrp) {
|
||||
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
|
||||
nodep->varp()->valuep()->iterateAndNext(*this);
|
||||
if (operandConst(nodep->varp()->valuep())
|
||||
@@ -1220,16 +1263,6 @@ private:
|
||||
// Not constant propagated (for today) because AstMath::isOpaque is set
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
// Don't iterate children, don't want to lose VarRef.
|
||||
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
|
||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
} else {
|
||||
nodep->v3fatalSrc("Missing ATTR type case");
|
||||
}
|
||||
}
|
||||
bool onlySenItemInSenTree(AstNodeSenItem* nodep) {
|
||||
// Only one if it's not in a list
|
||||
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||
@@ -1681,6 +1714,8 @@ private:
|
||||
// v--- *1* These ops are always first, as we warn before replacing
|
||||
// v--- *V* This op is a verilog op, only in m_doV mode
|
||||
// v--- *C* This op works on all constant children, allowed in m_doConst mode
|
||||
// v--- *S* This op specifies a type should use short-circuting of its lhs op
|
||||
|
||||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
@@ -1688,7 +1723,11 @@ private:
|
||||
// Zero on one side or the other
|
||||
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp.isZero, $rhsp, isTPure($rhsp)}", "replaceZero(nodep)"); // Can't use replaceZeroChkPure as we make this pattern in ChkPure
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstLogAnd {$lhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstLogOr {$lhsp.isOne}", "replaceNum(nodep, 1)");
|
||||
TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
|
||||
@@ -1742,6 +1781,9 @@ private:
|
||||
TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)");
|
||||
TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)");
|
||||
TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b
|
||||
@@ -1915,6 +1957,8 @@ private:
|
||||
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
// Conversions
|
||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstLogIf {$lhsp.isZero}", "replaceNum(nodep, 1)");
|
||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
||||
// Strings
|
||||
@@ -1948,6 +1992,7 @@ public:
|
||||
// Processing Mode Enum
|
||||
enum ProcMode {
|
||||
PROC_PARAMS,
|
||||
PROC_GENERATE,
|
||||
PROC_LIVE,
|
||||
PROC_V_WARN,
|
||||
PROC_V_NOWARN,
|
||||
@@ -1963,13 +2008,16 @@ public:
|
||||
m_doNConst = false;
|
||||
m_doShort = true; // Presently always done
|
||||
m_doV = false;
|
||||
m_doGenerate = false; // Inside generate conditionals
|
||||
m_warn = false;
|
||||
m_wremove = true; // Overridden in visitors
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_attrp = NULL;
|
||||
//
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
|
||||
case PROC_GENERATE: m_doV = true; m_doNConst = true; m_params = true; m_required = true; m_doGenerate = true; break;
|
||||
case PROC_LIVE: break;
|
||||
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
|
||||
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
|
||||
@@ -1988,12 +2036,46 @@ public:
|
||||
//######################################################################
|
||||
// Const class functions
|
||||
|
||||
//! Force this cell node's parameter list to become a constant
|
||||
//! @return Pointer to the edited node.
|
||||
AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
|
||||
// Resize even if the node already has a width, because burried in the treee we may
|
||||
// have a node we just created with signing, etc, that isn't sized yet.
|
||||
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
|
||||
ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
|
||||
// Resize even if the node already has a width, because buried in the tree
|
||||
// we may have a node we just created with signing, etc, that isn't sized yet.
|
||||
|
||||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthParamsEdit(nodep);
|
||||
ConstVisitor visitor(ConstVisitor::PROC_PARAMS);
|
||||
if (AstVar* varp=nodep->castVar()) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
// init value because we need widthing above to handle the var's type.
|
||||
if (varp->valuep()) visitor.mainAcceptEdit(varp->valuep());
|
||||
} else {
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
// Because we do edits, nodep links may get trashed and core dump this.
|
||||
//if (debug()>0) nodep->dumpTree(cout," forceConDONE: ");
|
||||
return nodep;
|
||||
}
|
||||
|
||||
//! Force this cell node's parameter list to become a constant inside generate.
|
||||
//! If we are inside a generated "if", "case" or "for", we don't want to
|
||||
//! trigger warnings when we deal with the width. It is possible that these
|
||||
//! are spurious, existing within sub-expressions that will not actually be
|
||||
//! generated. Since such occurrences, must be constant, in order to be
|
||||
//! someting a generate block can depend on, we can wait until later to do the
|
||||
//! width check.
|
||||
//! @return Pointer to the edited node.
|
||||
AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
|
||||
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
|
||||
// Resize even if the node already has a width, because buried in the tree
|
||||
// we may have a node we just created with signing, etc, that isn't sized
|
||||
// yet.
|
||||
|
||||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthGenerateParamsEdit(nodep);
|
||||
ConstVisitor visitor(ConstVisitor::PROC_GENERATE);
|
||||
if (AstVar* varp=nodep->castVar()) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
||||
+1
-4
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -31,9 +29,8 @@
|
||||
|
||||
class V3Const {
|
||||
public:
|
||||
// Force this cell node's parameter list to become a constant
|
||||
// Return new node that may have replaced nodep
|
||||
static AstNode* constifyParamsEdit(AstNode* nodep);
|
||||
static AstNode* constifyGenerateParamsEdit(AstNode* nodep);
|
||||
// Only do constant pushing, without removing dead logic
|
||||
static void constifyAllLive(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+40
-5
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -23,6 +21,8 @@
|
||||
// Remove any unreferenced modules
|
||||
// Remove any unreferenced variables
|
||||
//
|
||||
// TODO: A graph would make the process of circular and interlinked
|
||||
// dependencies easier to resolve.
|
||||
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
||||
// instead of needing as many visitors.
|
||||
//*************************************************************************
|
||||
@@ -74,6 +74,7 @@ private:
|
||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||
// AstVar::user1() -> int. Count of number of references
|
||||
// AstVarScope::user1() -> int. Count of number of references
|
||||
// AstNodeDType::user1() -> int. Count of number of references
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// TYPES
|
||||
@@ -84,6 +85,7 @@ private:
|
||||
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||
bool m_elimUserVars; // Allow removal of user's vars
|
||||
bool m_elimDTypes; // Allow removal of DTypes
|
||||
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||
|
||||
// METHODS
|
||||
@@ -92,7 +94,19 @@ private:
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
|
||||
void checkAll(AstNode* nodep) {
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc();
|
||||
}
|
||||
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
void checkDType(AstNodeDType* nodep) {
|
||||
if (!nodep->generic() // Don't remove generic types
|
||||
&& m_elimDTypes) { // dtypes stick around until post-widthing
|
||||
m_varEtcsp.push_back(nodep);
|
||||
}
|
||||
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
@@ -124,11 +138,17 @@ private:
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
checkAll(nodep);
|
||||
@@ -156,11 +176,13 @@ private:
|
||||
// Similar code in V3Life
|
||||
m_sideEffect = false;
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
checkAll(nodep);
|
||||
// Has to be direct assignment without any EXTRACTing.
|
||||
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
|
||||
if (varrefp && !m_sideEffect
|
||||
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||
checkAll(varrefp); // Must track reference to dtype()
|
||||
} else { // Track like any other statement
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
}
|
||||
@@ -226,14 +248,19 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
||||
m_elimUserVars = elimUserVars;
|
||||
m_elimDTypes = elimDTypes;
|
||||
m_sideEffect = false;
|
||||
// Prepare to remove some datatypes
|
||||
nodep->typeTablep()->clearCache();
|
||||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
deadCheckVar();
|
||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||
deadCheckMod();
|
||||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
}
|
||||
virtual ~DeadVisitor() {}
|
||||
};
|
||||
@@ -241,7 +268,15 @@ public:
|
||||
//######################################################################
|
||||
// Dead class functions
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep, bool elimUserVars) {
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, elimUserVars);
|
||||
DeadVisitor visitor (nodep, false, false);
|
||||
}
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true);
|
||||
}
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true);
|
||||
}
|
||||
|
||||
+5
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -31,8 +29,12 @@
|
||||
|
||||
class V3Dead {
|
||||
public:
|
||||
// Modules, no vars/dtypes
|
||||
static void deadifyModules(AstNetlist* nodep);
|
||||
// Modules, Data types
|
||||
static void deadifyDTypes(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void deadifyAll(AstNetlist* nodep, bool elimUserVars);
|
||||
static void deadifyAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+4
-6
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -133,7 +131,7 @@ private:
|
||||
} else {
|
||||
if (width==0) {
|
||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
|
||||
varp->widthSignedFrom(oldvarscp);
|
||||
varp->dtypeFrom(oldvarscp);
|
||||
} else { // Used for vset and dimensions, so can zero init
|
||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, VFlagBitPacked(), width);
|
||||
}
|
||||
@@ -158,9 +156,9 @@ private:
|
||||
if (oldactivep->sensesp() != m_activep->sensesp()) {
|
||||
if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
|
||||
&& !varrefp->varp()->user2()) {
|
||||
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName());
|
||||
varrefp->v3warn(MULTIDRIVEN,"... Location of first driving block");
|
||||
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
|
||||
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName()<<endl
|
||||
<<varrefp->warnMore()<<"... Location of first driving block"<<endl
|
||||
<<oldactivep->warnMore()<<"... Location of other driving block");
|
||||
varrefp->varp()->user2(true);
|
||||
}
|
||||
UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+11
-10
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -487,7 +485,7 @@ public:
|
||||
visit(nodep->castNodeUniop(), vup);
|
||||
} else {
|
||||
putbs("VL_REDXOR_");
|
||||
puts(cvtToStr(nodep->lhsp()->widthPow2()));
|
||||
puts(cvtToStr(nodep->lhsp()->dtypep()->widthPow2()));
|
||||
puts("(");
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(")");
|
||||
@@ -624,6 +622,7 @@ public:
|
||||
virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class
|
||||
virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class
|
||||
virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class
|
||||
virtual void visit(AstTypedef*, AstNUser*) {} // Nothing needed presently
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
|
||||
@@ -1192,11 +1191,11 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||
AstNode* argp = *elistp;
|
||||
if (!argp) {
|
||||
// expectDisplay() checks this first, so internal error if found here
|
||||
dispp->v3error("Internal: Missing arguments for $display format");
|
||||
dispp->v3error("Internal: Missing arguments for $display-like format");
|
||||
return;
|
||||
}
|
||||
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
||||
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any display arguments");
|
||||
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any $display-like arguments");
|
||||
}
|
||||
if (argp && argp->isWide()
|
||||
&& (fmtLetter=='d'||fmtLetter=='u')) {
|
||||
@@ -1287,17 +1286,17 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
case 'z':
|
||||
case 'l':
|
||||
case 'v':
|
||||
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
|
||||
nodep->v3error("Unsupported: $display-like format code: %"<<pos[0]);
|
||||
break;
|
||||
default:
|
||||
nodep->v3error("Unknown $display format code: %"<<pos[0]);
|
||||
nodep->v3error("Unknown $display-like format code: %"<<pos[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elistp != NULL) {
|
||||
// expectFormat also checks this, and should have found it first, so internal
|
||||
elistp->v3error("Internal: Extra arguments for $display format");
|
||||
elistp->v3error("Internal: Extra arguments for $display-like format");
|
||||
}
|
||||
displayEmit(nodep, isScan);
|
||||
}
|
||||
@@ -1558,7 +1557,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
#ifndef NEW_ORDERING
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||
puts("}\n");
|
||||
#endif
|
||||
puts("}\n");
|
||||
@@ -1577,7 +1577,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
#ifndef NEW_ORDERING
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
|
||||
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
|
||||
puts( "}\n");
|
||||
#endif
|
||||
puts("}\n");
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+2
-4
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -462,8 +460,8 @@ void EmitCSyms::emitSymImp() {
|
||||
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
|
||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
||||
bounds += " ,"; bounds += cvtToStr(adtypep->arrayp()->msbConst());
|
||||
bounds += ","; bounds += cvtToStr(adtypep->arrayp()->lsbConst());
|
||||
bounds += " ,"; bounds += cvtToStr(adtypep->msb());
|
||||
bounds += ","; bounds += cvtToStr(adtypep->lsb());
|
||||
dim++;
|
||||
dtypep = adtypep->subDTypep();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+20
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -384,6 +382,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
// %l lhsp - if appropriate
|
||||
// %r rhsp - if appropriate
|
||||
// %t thsp - if appropriate
|
||||
// %d dtypep - if appropriate
|
||||
// %k Potential line break
|
||||
bool inPct = false;
|
||||
putbs("");
|
||||
@@ -413,6 +412,11 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
else thsp->iterateAndNext(*this);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
if (!nodep->dtypep()) { nodep->v3fatalSrc("emitVerilog() references undef node"); }
|
||||
else nodep->dtypep()->iterateAndNext(*this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
nodep->v3fatalSrc("Unknown emitVerilog format code: %"<<pos[0]);
|
||||
break;
|
||||
@@ -495,7 +499,20 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
}
|
||||
virtual void visit(AstArrayDType* nodep, AstNUser*) {
|
||||
nodep->subDTypep()->iterateAndNext(*this);
|
||||
nodep->arrayp()->iterateAndNext(*this);
|
||||
nodep->rangep()->iterateAndNext(*this);
|
||||
}
|
||||
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
||||
puts(nodep->verilogKwd()+" ");
|
||||
if (nodep->packed()) puts("packed ");
|
||||
puts("\n");
|
||||
nodep->membersp()->iterateAndNext(*this);
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstMemberDType* nodep, AstNUser*) {
|
||||
nodep->subDTypep()->iterateAndNext(*this);
|
||||
puts(" ");
|
||||
puts(nodep->name());
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+66
-62
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -45,6 +43,7 @@ bool V3Error::s_errorSuppressed = false;
|
||||
bool V3Error::s_describedEachWarn[V3ErrorCode::_ENUM_MAX];
|
||||
bool V3Error::s_describedWarnings = false;
|
||||
bool V3Error::s_pretendError[V3ErrorCode::_ENUM_MAX];
|
||||
V3Error::MessagesSet V3Error::s_messages;
|
||||
|
||||
struct v3errorIniter {
|
||||
v3errorIniter() { V3Error::init(); }
|
||||
@@ -265,6 +264,14 @@ void FileLine::v3errorEnd(ostringstream& str) {
|
||||
}
|
||||
}
|
||||
|
||||
string FileLine::warnMore() const {
|
||||
if (this && m_lineno) {
|
||||
return V3Error::warnMore()+ascii()+": ";
|
||||
} else {
|
||||
return V3Error::warnMore();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
typedef set<FileLine*> FileLineCheckSet;
|
||||
FileLineCheckSet fileLineLeakChecks;
|
||||
@@ -301,7 +308,7 @@ void FileLine::deleteAllRemaining() {
|
||||
// Eventually the list will be empty and terminate the loop.
|
||||
}
|
||||
fileLineLeakChecks.clear();
|
||||
FileLineSingleton::clear();
|
||||
singleton().clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -370,7 +377,9 @@ bool V3Error::isError(V3ErrorCode code, bool supp) {
|
||||
else return false;
|
||||
}
|
||||
|
||||
string V3Error::msgPrefix(V3ErrorCode code, bool supp) {
|
||||
string V3Error::msgPrefix() {
|
||||
V3ErrorCode code=s_errorCode;
|
||||
bool supp=s_errorSuppressed;
|
||||
if (supp) return "-arning-suppressed: ";
|
||||
else if (code==V3ErrorCode::EC_INFO) return "-Info: ";
|
||||
else if (code==V3ErrorCode::EC_FATAL) return "%Error: ";
|
||||
@@ -395,18 +404,6 @@ void V3Error::vlAbort () {
|
||||
//======================================================================
|
||||
// Global Functions
|
||||
|
||||
string V3Error::v3sform (const char* format, ...) {
|
||||
static char msg[1000] = "";
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
vsprintf(msg,format,ap);
|
||||
va_end(ap);
|
||||
|
||||
string out = msg;
|
||||
return out;
|
||||
}
|
||||
|
||||
void V3Error::suppressThisWarning() {
|
||||
if (s_errorCode>=V3ErrorCode::EC_MIN) {
|
||||
V3Stats::addStatSum(string("Warnings, Suppressed ")+s_errorCode.ascii(), 1);
|
||||
@@ -414,63 +411,70 @@ void V3Error::suppressThisWarning() {
|
||||
}
|
||||
}
|
||||
|
||||
string V3Error::warnMore() {
|
||||
return msgPrefix();
|
||||
}
|
||||
|
||||
void V3Error::v3errorEnd (ostringstream& sstr) {
|
||||
#if defined(__COVERITY__) || defined(__cppcheck__)
|
||||
if (s_errorCode==V3ErrorCode::EC_FATAL) __coverity_panic__(x);
|
||||
#endif
|
||||
if (!s_errorSuppressed
|
||||
// Skip suppressed messages
|
||||
if (s_errorSuppressed
|
||||
// On debug, show only non default-off warning to prevent pages of warnings
|
||||
|| (debug() && !s_errorCode.defaultsOff())) {
|
||||
cerr<<msgPrefix()<<sstr.str();
|
||||
if (sstr.str()[sstr.str().length()-1] != '\n') {
|
||||
cerr<<endl;
|
||||
}
|
||||
if (!s_errorSuppressed && s_errorCode!=V3ErrorCode::EC_INFO) {
|
||||
if (!s_describedEachWarn[s_errorCode]
|
||||
&& !s_pretendError[s_errorCode]) {
|
||||
s_describedEachWarn[s_errorCode] = true;
|
||||
if (s_errorCode>=V3ErrorCode::EC_FIRST_WARN && !s_describedWarnings) {
|
||||
cerr<<msgPrefix()<<"Use \"/* verilator lint_off "<<s_errorCode.ascii()
|
||||
<<" */\" and lint_on around source to disable this message."<<endl;
|
||||
s_describedWarnings = true;
|
||||
}
|
||||
if (s_errorCode.dangerous()) {
|
||||
cerr<<msgPrefix()<<"*** See the manual before disabling this,"<<endl;
|
||||
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
||||
}
|
||||
&& (!debug() || s_errorCode.defaultsOff())) return;
|
||||
string msg = msgPrefix()+sstr.str();
|
||||
if (msg[msg.length()-1] != '\n') msg += '\n';
|
||||
// Suppress duplicates
|
||||
if (s_messages.find(msg) != s_messages.end()) return;
|
||||
s_messages.insert(msg);
|
||||
// Output
|
||||
cerr<<msg;
|
||||
if (!s_errorSuppressed && s_errorCode!=V3ErrorCode::EC_INFO) {
|
||||
if (!s_describedEachWarn[s_errorCode]
|
||||
&& !s_pretendError[s_errorCode]) {
|
||||
s_describedEachWarn[s_errorCode] = true;
|
||||
if (s_errorCode>=V3ErrorCode::EC_FIRST_WARN && !s_describedWarnings) {
|
||||
cerr<<msgPrefix()<<"Use \"/* verilator lint_off "<<s_errorCode.ascii()
|
||||
<<" */\" and lint_on around source to disable this message."<<endl;
|
||||
s_describedWarnings = true;
|
||||
}
|
||||
// If first warning is not the user's fault (internal/unsupported) then give the website
|
||||
// Not later warnings, as a internal may be caused by an earlier problem
|
||||
if (s_tellManual == 0) {
|
||||
if (s_errorCode.mentionManual()
|
||||
|| sstr.str().find("Unsupported") != string::npos) {
|
||||
s_tellManual = 1;
|
||||
} else {
|
||||
if (s_errorCode.dangerous()) {
|
||||
cerr<<msgPrefix()<<"*** See the manual before disabling this,"<<endl;
|
||||
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
||||
}
|
||||
}
|
||||
// If first warning is not the user's fault (internal/unsupported) then give the website
|
||||
// Not later warnings, as a internal may be caused by an earlier problem
|
||||
if (s_tellManual == 0) {
|
||||
if (s_errorCode.mentionManual()
|
||||
|| sstr.str().find("Unsupported") != string::npos) {
|
||||
s_tellManual = 1;
|
||||
} else {
|
||||
s_tellManual = 2;
|
||||
}
|
||||
}
|
||||
if (isError(s_errorCode, s_errorSuppressed)) incErrors();
|
||||
else incWarnings();
|
||||
if (s_errorCode==V3ErrorCode::EC_FATAL
|
||||
|| s_errorCode==V3ErrorCode::EC_FATALSRC) {
|
||||
static bool inFatal = false;
|
||||
if (!inFatal) {
|
||||
inFatal = true;
|
||||
if (s_tellManual==1) {
|
||||
cerr<<msgPrefix()<<"See the manual and http://www.veripool.org/verilator for more assistance."<<endl;
|
||||
s_tellManual = 2;
|
||||
}
|
||||
}
|
||||
if (isError(s_errorCode, s_errorSuppressed)) incErrors();
|
||||
else incWarnings();
|
||||
if (s_errorCode==V3ErrorCode::EC_FATAL
|
||||
|| s_errorCode==V3ErrorCode::EC_FATALSRC) {
|
||||
static bool inFatal = false;
|
||||
if (!inFatal) {
|
||||
inFatal = true;
|
||||
if (s_tellManual==1) {
|
||||
cerr<<msgPrefix()<<"See the manual and http://www.veripool.org/verilator for more assistance."<<endl;
|
||||
s_tellManual = 2;
|
||||
}
|
||||
#ifndef _V3ERROR_NO_GLOBAL_
|
||||
if (debug()) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
|
||||
V3Stats::statsFinalAll(v3Global.rootp());
|
||||
V3Stats::statsReport();
|
||||
}
|
||||
#endif
|
||||
if (debug()) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
|
||||
V3Stats::statsFinalAll(v3Global.rootp());
|
||||
V3Stats::statsReport();
|
||||
}
|
||||
|
||||
vlAbort();
|
||||
#endif
|
||||
}
|
||||
|
||||
vlAbort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-9
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -29,6 +27,7 @@
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
|
||||
//######################################################################
|
||||
@@ -76,9 +75,12 @@ public:
|
||||
IMPLICIT, // Implicit wire
|
||||
IMPURE, // Impure function not being inlined
|
||||
INCABSPATH, // Include has absolute path
|
||||
INITIALDLY, // Initial delayed statement
|
||||
LITENDIAN, // Little bit endian vector
|
||||
MODDUP, // Duplicate module
|
||||
MULTIDRIVEN, // Driven from multiple blocks
|
||||
PINMISSING, // Cell pin not specified
|
||||
PINNOCONNECT, // Cell pin not connected
|
||||
REALCVT, // Real conversion
|
||||
REDEFMACRO, // Redefining existing define macro
|
||||
SELRANGE, // Selection index out of range
|
||||
@@ -117,9 +119,11 @@ public:
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
|
||||
"COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||
"ENDLABEL", "GENCLK",
|
||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
|
||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
|
||||
"INCABSPATH", "INITIALDLY",
|
||||
"LITENDIAN", "MODDUP",
|
||||
"MULTIDRIVEN",
|
||||
"PINMISSING", "PINNOCONNECT",
|
||||
"REALCVT", "REDEFMACRO",
|
||||
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||
@@ -146,6 +150,7 @@ public:
|
||||
|| m_e==ENDLABEL
|
||||
|| m_e==IMPLICIT
|
||||
|| m_e==LITENDIAN
|
||||
|| m_e==PINMISSING
|
||||
|| m_e==REALCVT
|
||||
|| m_e==UNSIGNED
|
||||
|| m_e==WIDTH); }
|
||||
@@ -155,6 +160,7 @@ public:
|
||||
|| m_e==DEFPARAM
|
||||
|| m_e==DECLFILENAME
|
||||
|| m_e==INCABSPATH
|
||||
|| m_e==PINNOCONNECT
|
||||
|| m_e==SYNCASYNCNET
|
||||
|| m_e==UNDRIVEN
|
||||
|| m_e==UNUSED
|
||||
@@ -169,6 +175,9 @@ public:
|
||||
|
||||
class V3Error {
|
||||
// Base class for any object that wants debugging and error reporting
|
||||
|
||||
typedef set<string> MessagesSet;
|
||||
|
||||
private:
|
||||
static bool s_describedWarnings; // Told user how to disable warns
|
||||
static bool s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning
|
||||
@@ -180,6 +189,7 @@ class V3Error {
|
||||
static ostringstream s_errorStr; // Error string being formed
|
||||
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
||||
static bool s_errorSuppressed; // Error being formed should be suppressed
|
||||
static MessagesSet s_messages; // What errors we've outputted
|
||||
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
||||
|
||||
V3Error() { cerr<<("Static class"); abort(); }
|
||||
@@ -189,7 +199,7 @@ class V3Error {
|
||||
// ACCESSORS
|
||||
static void debugDefault(int level) { s_debugDefault = level; }
|
||||
static int debugDefault() { return s_debugDefault; }
|
||||
static string msgPrefix(V3ErrorCode code=s_errorCode, bool supp=s_errorSuppressed); // returns %Error/%Warn
|
||||
static string msgPrefix(); // returns %Error/%Warn
|
||||
static int errorCount() { return s_errCount; }
|
||||
static int warnCount() { return s_warnCount; }
|
||||
static int errorOrWarnCount() { return errorCount()+warnCount(); }
|
||||
@@ -202,15 +212,17 @@ class V3Error {
|
||||
static void suppressThisWarning(); // Suppress next %Warn if user has it off
|
||||
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
|
||||
static bool isError(V3ErrorCode code, bool supp);
|
||||
static string v3sform (const char* format, ...);
|
||||
static string lineStr (const char* filename, int lineno);
|
||||
static V3ErrorCode errorCode() { return s_errorCode; }
|
||||
|
||||
// When printing an error/warning, print prefix for multiline message
|
||||
static string warnMore();
|
||||
|
||||
// Internals for v3error()/v3fatal() macros only
|
||||
// Error end takes the string stream to output, be careful to seek() as needed
|
||||
static ostringstream& v3errorPrep (V3ErrorCode code) {
|
||||
s_errorStr.str(""); s_errorCode=code; s_errorSuppressed=false; return s_errorStr; }
|
||||
static ostringstream& v3errorStr () { return s_errorStr; }
|
||||
static void v3errorPrep(V3ErrorCode code) {
|
||||
s_errorStr.str(""); s_errorCode=code; s_errorSuppressed=false; }
|
||||
static ostringstream& v3errorStr() { return s_errorStr; }
|
||||
static void vlAbort();
|
||||
static void v3errorEnd(ostringstream& sstr); // static, but often overridden in classes.
|
||||
};
|
||||
@@ -221,7 +233,9 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
||||
|
||||
// These allow errors using << operators: v3error("foo"<<"bar");
|
||||
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||
#define v3warnCode(code,msg) v3errorEnd(((V3Error::v3errorPrep(code)<<msg),V3Error::v3errorStr()));
|
||||
// Note the commas are the comma operator, not separating arguments. These are needed to insure
|
||||
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
|
||||
#define v3warnCode(code,msg) v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
|
||||
#define v3warn(code,msg) v3warnCode(V3ErrorCode::code,msg)
|
||||
#define v3info(msg) v3warn(EC_INFO,msg)
|
||||
#define v3fatal(msg) v3warn(EC_FATAL,msg)
|
||||
@@ -368,6 +382,7 @@ public:
|
||||
|
||||
// OPERATORS
|
||||
void v3errorEnd(ostringstream& str);
|
||||
string warnMore() const;
|
||||
inline bool operator==(FileLine rhs) const {
|
||||
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
|
||||
}
|
||||
|
||||
+22
-24
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -127,13 +125,13 @@ private:
|
||||
new AstConst(nodep->fileline(), word));
|
||||
} else if (nodep->isQuad() && word==0) {
|
||||
AstNode* quadfromp = nodep->cloneTree(true);
|
||||
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
|
||||
quadfromp->dtypeSetBitSized(VL_QUADSIZE,quadfromp->widthMin(),AstNumeric::UNSIGNED);
|
||||
return new AstCCast (nodep->fileline(),
|
||||
quadfromp,
|
||||
VL_WORDSIZE);
|
||||
} else if (nodep->isQuad() && word==1) {
|
||||
AstNode* quadfromp = nodep->cloneTree(true);
|
||||
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
|
||||
quadfromp->dtypeSetBitSized(VL_QUADSIZE,quadfromp->widthMin(),AstNumeric::UNSIGNED);
|
||||
return new AstCCast (nodep->fileline(),
|
||||
new AstShiftR (nodep->fileline(),
|
||||
quadfromp,
|
||||
@@ -311,7 +309,7 @@ private:
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstExtend* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->isWide()) {
|
||||
// See under ASSIGN(EXTEND)
|
||||
@@ -320,7 +318,7 @@ private:
|
||||
AstNode* newp = lhsp;
|
||||
if (nodep->isQuad()) {
|
||||
if (lhsp->isQuad()) {
|
||||
lhsp->widthSignedFrom(nodep); // Just mark it, else nop
|
||||
lhsp->dtypeFrom(nodep); // Just mark it, else nop
|
||||
} else if (lhsp->isWide()) {
|
||||
nodep->v3fatalSrc("extending larger thing into smaller?");
|
||||
} else {
|
||||
@@ -331,7 +329,7 @@ private:
|
||||
if (lhsp->isQuad() || lhsp->isWide()) {
|
||||
nodep->v3fatalSrc("extending larger thing into smaller?");
|
||||
} else {
|
||||
lhsp->widthSignedFrom(nodep); // Just mark it, else nop
|
||||
lhsp->dtypeFrom(nodep); // Just mark it, else nop
|
||||
}
|
||||
}
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
@@ -350,7 +348,7 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
// Remember, Sel's may have non-integer rhs, so need to optimize for that!
|
||||
if (nodep->widthMin()!=(int)nodep->widthConst()) nodep->v3fatalSrc("Width mismatch");
|
||||
@@ -439,7 +437,7 @@ private:
|
||||
AstNode* newp = lowp;
|
||||
if (midp) newp = new AstOr (nodep->fileline(), midp, newp);
|
||||
if (hip) newp = new AstOr (nodep->fileline(), hip, newp);
|
||||
newp->widthFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
}
|
||||
else { // Long/Quad from Long/Quad
|
||||
@@ -451,11 +449,11 @@ private:
|
||||
fromp,
|
||||
dropCondBound(lsbp),
|
||||
nodep->width());
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
if (!nodep->isQuad() && fromp->isQuad()) {
|
||||
newp = new AstCCast (newp->fileline(), newp, nodep);
|
||||
}
|
||||
newp->widthSignedFrom(nodep);
|
||||
newp->dtypeFrom(nodep);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
}
|
||||
}
|
||||
@@ -647,7 +645,7 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit(AstConcat* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->isWide()) {
|
||||
// See under ASSIGN(WIDE)
|
||||
@@ -664,7 +662,7 @@ private:
|
||||
new AstConst (nodep->fileline(), rhsshift),
|
||||
nodep->width()),
|
||||
rhsp);
|
||||
newp->widthFrom(nodep); // Unsigned
|
||||
newp->dtypeFrom(nodep); // Unsigned
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
}
|
||||
}
|
||||
@@ -687,7 +685,7 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->isWide()) {
|
||||
// See under ASSIGN(WIDE)
|
||||
@@ -713,11 +711,11 @@ private:
|
||||
new AstConst (nodep->fileline(), rhsshift),
|
||||
nodep->width()),
|
||||
newp);
|
||||
newp->widthFrom(nodep); // Unsigned
|
||||
newp->dtypeFrom(nodep); // Unsigned
|
||||
}
|
||||
lhsp->deleteTree(); // Never used
|
||||
}
|
||||
newp->widthFrom(nodep); // Unsigned
|
||||
newp->dtypeFrom(nodep); // Unsigned
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
}
|
||||
}
|
||||
@@ -732,7 +730,7 @@ private:
|
||||
AstNode* newp;
|
||||
if (lhswidth==1) {
|
||||
newp = new AstNegate (nodep->fileline(), lhsp->cloneTree(true));
|
||||
newp->width(VL_WORDSIZE,VL_WORDSIZE);
|
||||
newp->dtypeSetLogicSized(VL_WORDSIZE,VL_WORDSIZE,AstNumeric::UNSIGNED); // Replicate always unsigned
|
||||
} else {
|
||||
newp = newAstWordSelClone (lhsp, w);
|
||||
for (unsigned repnum=1; repnum<times; repnum++) {
|
||||
@@ -748,7 +746,7 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit(AstChangeXor* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
UINFO(8," Wordize ChangeXor "<<nodep<<endl);
|
||||
// -> (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}}
|
||||
@@ -763,7 +761,7 @@ private:
|
||||
}
|
||||
|
||||
void visitEqNeq(AstNodeBiop* nodep) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8," Wordize EQ/NEQ "<<nodep<<endl);
|
||||
@@ -789,7 +787,7 @@ private:
|
||||
virtual void visit(AstNeq* nodep, AstNUser*) { visitEqNeq (nodep); }
|
||||
|
||||
virtual void visit(AstRedOr* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8," Wordize REDOR "<<nodep<<endl);
|
||||
@@ -813,7 +811,7 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedAnd* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8," Wordize REDAND "<<nodep<<endl);
|
||||
@@ -842,7 +840,7 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8," Wordize REDXOR "<<nodep<<endl);
|
||||
@@ -861,13 +859,13 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
m_stmtp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_stmtp = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
if (nodep->user1Inc()) return; // Process once
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
m_stmtp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
bool did = false;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+1
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -302,7 +300,7 @@ private:
|
||||
}
|
||||
bool readContentsFile(const string& filename, StrList& outl) {
|
||||
int fd = open (filename.c_str(), O_RDONLY);
|
||||
if (!fd) return false;
|
||||
if (fd<0) return false;
|
||||
m_readEof = false;
|
||||
readBlocks(fd, -1, outl);
|
||||
close(fd);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+3
-5
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -687,9 +685,9 @@ void GateVisitor::warnSignals() {
|
||||
&& !sp->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET)
|
||||
) {
|
||||
vscp->varp()->user2(true); // Warn only once per signal
|
||||
vscp->v3warn(SYNCASYNCNET,"Signal flopped as both synchronous and async: "<<vscp->prettyName());
|
||||
ap->v3warn(SYNCASYNCNET,"... Location of async usage");
|
||||
sp->v3warn(SYNCASYNCNET,"... Location of sync usage");
|
||||
vscp->v3warn(SYNCASYNCNET,"Signal flopped as both synchronous and async: "<<vscp->prettyName()<<endl
|
||||
<<ap->warnMore()<<"... Location of async usage"<<endl
|
||||
<<sp->warnMore()<<"... Location of sync usage"<<endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+3
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -63,9 +61,10 @@ public:
|
||||
m_needHInlines = false;
|
||||
m_needHeavy = false;
|
||||
m_dpi = false;
|
||||
m_rootp = makeNetlist();
|
||||
m_rootp = NULL; // created by makeInitNetlist() so static constructors run first
|
||||
}
|
||||
AstNetlist* makeNetlist();
|
||||
void boot() { UASSERT(!m_rootp,"call once"); m_rootp = makeNetlist(); }
|
||||
void clear();
|
||||
// ACCESSORS (general)
|
||||
AstNetlist* rootp() const { return m_rootp; }
|
||||
@@ -75,6 +74,7 @@ public:
|
||||
// METHODS
|
||||
void readFiles();
|
||||
void checkTree();
|
||||
static void dumpGlobalTree(const string& filename, int newNumber=0);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
|
||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
||||
|
||||
+1
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -346,5 +344,5 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
||||
*logp << "}\n";
|
||||
logp->close();
|
||||
|
||||
cout << "dot -Tps -o ~/a.ps "<<filename<<endl;
|
||||
cout << "dot -Tpdf -o ~/a.pdf "<<filename<<endl;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+19
-10
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -102,6 +100,7 @@ private:
|
||||
// GraphEdge::user() OrigEdgeList* Old graph edges
|
||||
// GraphVertex::user bool Detection of loops in simplifyDupIterate
|
||||
// MEMBERS
|
||||
V3Graph* m_origGraphp; // Original graph
|
||||
V3Graph m_breakGraph; // Graph with only breakable edges represented
|
||||
V3List<GraphAcycVertex*> m_work; // List of vertices with optimization work left
|
||||
vector<OrigEdgeList*> m_origEdgeDelp; // List of deletions to do when done
|
||||
@@ -183,7 +182,8 @@ private:
|
||||
avertexp->m_work.unlink(m_work, avertexp); }
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
GraphAcyc(V3EdgeFuncP edgeFuncp) {
|
||||
GraphAcyc(V3Graph* origGraphp, V3EdgeFuncP edgeFuncp) {
|
||||
m_origGraphp = origGraphp;
|
||||
m_origEdgeFuncp = edgeFuncp;
|
||||
}
|
||||
~GraphAcyc() {
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
}
|
||||
m_origEdgeDelp.clear();
|
||||
}
|
||||
void main(V3Graph* origGraphp);
|
||||
void main();
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@@ -340,7 +340,16 @@ void GraphAcyc::simplifyOut (GraphAcycVertex* avertexp) {
|
||||
for (V3GraphEdge* nextp, *inEdgep = avertexp->inBeginp(); inEdgep; inEdgep=nextp) {
|
||||
nextp = inEdgep->inNextp();
|
||||
V3GraphVertex* inVertexp = inEdgep->fromp();
|
||||
if (inVertexp == avertexp) v3fatalSrc("Non-cutable edge forms a loop "<<avertexp);
|
||||
if (inVertexp == avertexp) {
|
||||
if (debug()) v3error("Non-cutable edge forms a loop, vertex="<<avertexp);
|
||||
v3error("Circular logic when ordering code (non-cutable edge loop)");
|
||||
m_origGraphp->reportLoops(&V3GraphEdge::followNotCutable,
|
||||
avertexp->origVertexp()); // calls OrderGraph::loopsVertexCb
|
||||
// Things are unlikely to end well at this point,
|
||||
// but we'll try something to get to further errors...
|
||||
inEdgep->cutable(true);
|
||||
return;
|
||||
}
|
||||
// Make a new edge connecting the two vertices directly
|
||||
edgeFromEdge(inEdgep, inVertexp, outVertexp);
|
||||
// Remove old edge
|
||||
@@ -522,17 +531,17 @@ bool GraphAcyc::placeIterate(GraphAcycVertex* vertexp, uint32_t currentRank) {
|
||||
|
||||
//----- Main algorithm entry point
|
||||
|
||||
void GraphAcyc::main (V3Graph* origGraphp) {
|
||||
void GraphAcyc::main () {
|
||||
m_breakGraph.userClearEdges();
|
||||
|
||||
// Color based on possible loops
|
||||
origGraphp->stronglyConnected(m_origEdgeFuncp);
|
||||
m_origGraphp->stronglyConnected(m_origEdgeFuncp);
|
||||
|
||||
// Make a new graph with vertices that have only a single vertex
|
||||
// for each group of old vertices that are interconnected with unbreakable
|
||||
// edges (and thus can't represent loops - if we did the unbreakable
|
||||
// marking right, anyways)
|
||||
buildGraph (origGraphp);
|
||||
buildGraph (m_origGraphp);
|
||||
if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_pre");
|
||||
|
||||
// Perform simple optimizations before any cuttings
|
||||
@@ -559,7 +568,7 @@ void GraphAcyc::main (V3Graph* origGraphp) {
|
||||
|
||||
void V3Graph::acyclic(V3EdgeFuncP edgeFuncp) {
|
||||
UINFO(4, "Acyclic\n");
|
||||
GraphAcyc acyc (edgeFuncp);
|
||||
acyc.main(this);
|
||||
GraphAcyc acyc (this, edgeFuncp);
|
||||
acyc.main();
|
||||
UINFO(4, "Acyclic done\n");
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+3
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -74,7 +72,8 @@ private:
|
||||
if (m_lowerHash.isIllegal()) {
|
||||
nodep->v3fatalSrc("sameHash function undefined (returns 0) for node under CFunc.");
|
||||
}
|
||||
m_lowerHash = V3Hash(m_lowerHash, V3Hash(nodep->type()<<6 | nodep->width()));
|
||||
// For identical nodes, the type should be the same thus dtypep should be the same too
|
||||
m_lowerHash = V3Hash(m_lowerHash, V3Hash(nodep->type()<<6, V3Hash(nodep->dtypep())));
|
||||
// Now update m_lowerHash for our children's (and next children) contributions
|
||||
nodep->iterateChildren(*this);
|
||||
// Store the hash value
|
||||
@@ -189,3 +188,4 @@ V3Hashed::iterator V3Hashed::findDuplicate(AstNode* nodep) {
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
|
||||
+17
-8
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -31,7 +29,23 @@
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3Hashed {
|
||||
class VHashedBase {
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VHashedBase() {}
|
||||
~VHashedBase() {}
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3Hashed : public VHashedBase {
|
||||
// NODE STATE
|
||||
// AstNode::user4() -> V3Hash. Hash value of this node (hash of 0 is illegal)
|
||||
AstUser4InUse m_inuser4;
|
||||
@@ -55,11 +69,6 @@ public:
|
||||
iterator end() { return m_hashMmap.end(); }
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
void clear() { m_hashMmap.clear(); AstNode::user4ClearTree(); }
|
||||
void hashAndInsert(AstNode* nodep); // Hash the node, and insert into map
|
||||
bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical
|
||||
|
||||
+3
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -114,7 +112,8 @@ private:
|
||||
// we'll save work, and we can't call pinReconnectSimple in
|
||||
// this loop as it clone()s itself.
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
V3Inst::pinReconnectSimple(pinp, nodep, m_modp);
|
||||
if (!pinp->exprp()) continue;
|
||||
V3Inst::pinReconnectSimple(pinp, nodep, m_modp, false);
|
||||
}
|
||||
|
||||
// Clone original module
|
||||
@@ -130,6 +129,7 @@ private:
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
// Create assignments to the pins
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (!pinp->exprp()) continue;
|
||||
UINFO(6," Pin change from "<<pinp->modVarp()<<endl);
|
||||
// Make new signal; even though we'll optimize the interconnect, we
|
||||
// need an alias to trace correctly. If tracing is disabled, we'll
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
+25
-26
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -46,8 +44,6 @@ class InstVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Cleared each Cell:
|
||||
// AstVar::user1p() -> AstNode*. Expression connected to given pin
|
||||
// AstVarRef::user1p() -> bool. True if created senitem for parent's connected signal
|
||||
// AstPin::user1p() -> bool. True if created assignment already
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
@@ -75,10 +71,6 @@ private:
|
||||
m_cellp = nodep;
|
||||
//VV***** We reset user1p() on each cell!!!
|
||||
AstNode::user1ClearTree();
|
||||
// Collect pin expressions, so submod->varp->user1p() points to expression it connects to
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
pinp->modVarp()->user1p(pinp->exprp());
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
m_cellp = NULL;
|
||||
}
|
||||
@@ -86,22 +78,22 @@ private:
|
||||
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
|
||||
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
|
||||
UINFO(4," PIN "<<nodep<<endl);
|
||||
if (!nodep->exprp()) return; // No-connect
|
||||
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
|
||||
if (nodep->modVarp()->isOutOnly() && nodep->exprp()->castConst())
|
||||
nodep->v3error("Output port is connected to a constant pin, electrical short");
|
||||
// Use user1p on the PIN to indicate we created an assign for this pin
|
||||
if (!nodep->user1Inc()) {
|
||||
if (!nodep->user1SetOnce()) {
|
||||
// Simplify it
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp);
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
|
||||
// Make a ASSIGNW (expr, pin)
|
||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||
if (nodep->width() != nodep->modVarp()->width())
|
||||
if (exprp->width() != nodep->modVarp()->width())
|
||||
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
|
||||
if (nodep->modVarp()->isInout()) {
|
||||
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
|
||||
} else if (nodep->modVarp()->isOutput()) {
|
||||
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
|
||||
rhsp->widthSignedFrom(nodep);
|
||||
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
|
||||
m_modp->addStmtp(assp);
|
||||
} else if (nodep->modVarp()->isInput()) {
|
||||
@@ -194,6 +186,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstPin* nodep, AstNUser*) {
|
||||
// Any non-direct pins need reconnection with a part-select
|
||||
if (!nodep->exprp()) return; // No-connect
|
||||
if (m_cellRangep) {
|
||||
UINFO(4," PIN "<<nodep<<endl);
|
||||
int pinwidth = nodep->modVarp()->width();
|
||||
@@ -241,53 +234,59 @@ public:
|
||||
//######################################################################
|
||||
// Inst class functions
|
||||
|
||||
void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp) {
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
// If a pin connection is "simple" leave it as-is
|
||||
// Else create a intermediate wire to perform the interconnect
|
||||
// Return the new assignment, if one was made
|
||||
// Note this module calles cloneTree() via new AstVar
|
||||
AstVar* pinVarp = pinp->modVarp();
|
||||
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
|
||||
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
|
||||
AstBasicDType* connBasicp = NULL;
|
||||
AstAssignW* assignp = NULL;
|
||||
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
|
||||
//
|
||||
if (connectRefp
|
||||
if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
|
||||
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
|
||||
// Done. Same data type
|
||||
} else if (connBasicp
|
||||
} else if (!alwaysCvt
|
||||
&& connBasicp
|
||||
&& pinBasicp
|
||||
&& connBasicp->width() == pinBasicp->width()
|
||||
&& connBasicp->lsb() == pinBasicp->lsb()
|
||||
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
|
||||
&& pinp->width() == pinVarp->width()
|
||||
&& connBasicp->width() == pinVarp->width()
|
||||
&& 1) {
|
||||
// Done. One to one interconnect won't need a temporary variable.
|
||||
} else if (pinp->exprp()->castConst()) {
|
||||
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
|
||||
// Done. Constant.
|
||||
} else {
|
||||
// Make a new temp wire
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
|
||||
AstAssignW* assignp = NULL;
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
|
||||
string newvarname = ((pinVarp->isOutput() ? "__Vcellout__" : "__Vcellinp__")
|
||||
+cellp->name()+"__"+pinp->name());
|
||||
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||
modp->addStmtp(newvarp);
|
||||
// Important to add statement next to cell, in case there is a generate with same named cell
|
||||
cellp->addNextHere(newvarp);
|
||||
if (pinVarp->isInout()) {
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||
} else if (pinVarp->isOutput()) {
|
||||
// See also V3Inst
|
||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||
if (pinp->width() > rhsp->width()) {
|
||||
if (pinVarp->width() > rhsp->width()) {
|
||||
if (rhsp->isSigned()) {
|
||||
rhsp = new AstExtendS(pinp->fileline(), rhsp);
|
||||
} else {
|
||||
rhsp = new AstExtend (pinp->fileline(), rhsp);
|
||||
}
|
||||
} else if (pinp->width() < rhsp->width()) {
|
||||
rhsp = new AstSel (pinp->fileline(), rhsp, 0, pinp->width());
|
||||
} else if (pinVarp->width() < rhsp->width()) {
|
||||
rhsp = new AstSel (pinp->fileline(), rhsp, 0, pinVarp->width());
|
||||
}
|
||||
rhsp->widthSignedFrom(pinp);
|
||||
rhsp->dtypeFrom(pinVarp); // Need proper widthMin, which may differ from AstSel created above
|
||||
assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
|
||||
} else {
|
||||
@@ -298,11 +297,11 @@ void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* mod
|
||||
pinexprp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
||||
}
|
||||
pinp->widthSignedFrom(pinp->exprp());
|
||||
if (assignp) modp->addStmtp(assignp);
|
||||
if (assignp) cellp->addNextHere(assignp);
|
||||
//if (1||debug()) { pinp->dumpTree(cout," out:"); }
|
||||
//if (1||debug()) { assignp->dumpTree(cout," aout:"); }
|
||||
}
|
||||
return assignp;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
+2
-3
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
@@ -33,7 +31,8 @@ class V3Inst {
|
||||
public:
|
||||
static void instAll(AstNetlist* nodep);
|
||||
static void dearrayAll(AstNetlist* nodep);
|
||||
static void pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp);
|
||||
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp,
|
||||
bool forTristate, bool alwaysCvt=false);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user