mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 16:44:11 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8108b97050 | ||
|
|
a1c3491dea | ||
|
|
8bba96a84e | ||
|
|
6cd9b25a53 | ||
|
|
0431b1909c | ||
|
|
907665e2e8 | ||
|
|
61e8836fbd | ||
|
|
0e921b5dff | ||
|
|
7ef37d6e17 | ||
|
|
dce227684a | ||
|
|
158e112752 | ||
|
|
ec992c7f5e | ||
|
|
e7d63c7644 | ||
|
|
6464e8fee6 | ||
|
|
047d66a657 | ||
|
|
55c23360d9 | ||
|
|
c378d32c85 | ||
|
|
3d9540c58c | ||
|
|
39724eb916 | ||
|
|
48dddd4ae7 | ||
|
|
9c00fd10de | ||
|
|
9309d0b00f | ||
|
|
038b5d32a3 | ||
|
|
706920ba19 | ||
|
|
39492a0726 | ||
|
|
df1170fea9 | ||
|
|
f0e1d204fa | ||
|
|
8ece0a8a5f | ||
|
|
1373b81e7c | ||
|
|
d3601dd561 | ||
|
|
f685cf1d0c | ||
|
|
d5fcf0c153 | ||
|
|
5f9810070d | ||
|
|
923efa004b | ||
|
|
869e8eab3c | ||
|
|
b51d197117 | ||
|
|
e4f0a8952c | ||
|
|
072ee425f4 | ||
|
|
a4c2819be2 | ||
|
|
2a274f9c19 | ||
|
|
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 |
@@ -12,6 +12,7 @@
|
||||
*.pdf
|
||||
/Makefile
|
||||
README
|
||||
TAGS
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.status
|
||||
|
||||
@@ -3,6 +3,87 @@ 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.842 2012/11/03
|
||||
|
||||
**** Add -x-initial-edge, bug570. [Jeremy Bennett]
|
||||
|
||||
**** Fix parameter pins interspersed with cells broke in 3.840. [Bernard Deadman]
|
||||
|
||||
**** Fix large shift error on large shift constants. [David Welch]
|
||||
|
||||
**** Fix $display mangling on GCC 4.7 and speed up, msg927, bug373, bug574. [R Diez]
|
||||
|
||||
**** Fix array of struct references giving false error, bug566. [Julius Baxter]
|
||||
|
||||
**** Fix missing var access functions when no DPI, bug572. [Amir Gonnen]
|
||||
|
||||
**** Fix name collision on unnamed blocks, bug567. [Chandan Egbert]
|
||||
|
||||
**** Fix name collision on task inputs, bug569. [Chandan Egbert]
|
||||
|
||||
|
||||
* Verilator 3.841 2012/09/03
|
||||
|
||||
*** Add --savable to support model save/restore. [Jeremy Bennett]
|
||||
|
||||
*** Support '{} assignment pattern on structures, part of bug355.
|
||||
|
||||
**** Fix double-deep parameter cell WIDTHs, bug541. [Hiroki Honda]
|
||||
|
||||
**** Fix imports under multiple instantiated cells, bug542. [Alex Solomatnikov]
|
||||
|
||||
**** Fix defparam in generate broke in 3.840, bug543. [Alex Solomatnikov]
|
||||
|
||||
**** Fix duplicate begin error broke in 3.840, bug548. [Alex Solomatnikov]
|
||||
|
||||
**** Fix triangle symbol resolution error broke in 3.840, bug550. [Ted Campbell]
|
||||
|
||||
|
||||
* 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
|
||||
|
||||
|
||||
@@ -36,3 +36,5 @@ nodist/
|
||||
/vc_hdrs.h$
|
||||
/csrc/
|
||||
doxygen-doc/.*
|
||||
TAGS
|
||||
.*~
|
||||
|
||||
+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)
|
||||
|
||||
+220
-64
@@ -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
|
||||
@@ -302,6 +303,7 @@ descriptions in the next sections for more information.
|
||||
--private Debugging; see docs
|
||||
--psl Enable PSL parsing
|
||||
--public Debugging; see docs
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
--sp Create SystemPerl output
|
||||
--stats Create statistics file
|
||||
@@ -324,7 +326,8 @@ descriptions in the next sections for more information.
|
||||
-Wno-lint Disable all lint warnings
|
||||
-Wno-style Disable all style warnings
|
||||
-Wno-fatal Disable fatal exit on warnings
|
||||
-x-assign <mode> Initially assign Xs to this value
|
||||
--x-assign <mode> Initially assign Xs to this value
|
||||
--x-initial-edge Enable initial X->0 and X->1 edge triggers
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
|
||||
@@ -357,13 +360,16 @@ with the --exe option.
|
||||
Enable all assertions, includes enabling the --psl flag. (If psl is not
|
||||
desired, but other assertions are, use --assert --nopsl.)
|
||||
|
||||
See also --x-assign; setting "--x-assign unique" may be desirable.
|
||||
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
|
||||
and/or "--x-initial-edge" may be desirable.
|
||||
|
||||
=item --autoflush
|
||||
|
||||
After every $display or $fdisplay, flush the output stream. This insures
|
||||
that messages will appear immediately but may reduce performance. Defaults
|
||||
off, which will buffer output as provided by the normal C stdio calls.
|
||||
that messages will appear immediately but may reduce performance; for best
|
||||
performance call "fflush(stdout)" occasionally in the main C loop.
|
||||
Defaults off, which will buffer output as provided by the normal C stdio
|
||||
calls.
|
||||
|
||||
=item --bbox-sys
|
||||
|
||||
@@ -427,6 +433,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 +532,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 +544,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
|
||||
|
||||
@@ -807,6 +821,27 @@ inlining. This will also turn off inlining as if all modules had a
|
||||
/*verilator public_module*/, unless the module specifically enabled it with
|
||||
/*verilator inline_module*/.
|
||||
|
||||
=item --savable
|
||||
|
||||
Enable including save and restore functions in the generated model.
|
||||
|
||||
The user code must create a VerilatedSerialize or VerilatedDeserialze
|
||||
object then calling the << or >> operators on the generated model and any
|
||||
other data the process needs saved/restored. For example:
|
||||
|
||||
void save_model(const char* filenamep) {
|
||||
VerilatedSave os;
|
||||
os.open(filenamep);
|
||||
os << main_time; // user code must save the timestamp, etc
|
||||
os << *topp;
|
||||
}
|
||||
void restore_model(const char* filenamep) {
|
||||
VerilatedRestore os;
|
||||
os.open(filenamep);
|
||||
os >> main_time;
|
||||
os >> *topp;
|
||||
}
|
||||
|
||||
=item --sc
|
||||
|
||||
Specifies SystemC output mode; see also --cc and -sp.
|
||||
@@ -928,8 +963,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 +974,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,37 +995,72 @@ 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
|
||||
=item --x-assign 0
|
||||
|
||||
=item -x-assign 1
|
||||
=item --x-assign 1
|
||||
|
||||
=item -x-assign fast (default)
|
||||
=item --x-assign fast (default)
|
||||
|
||||
=item -x-assign unique
|
||||
=item --x-assign unique
|
||||
|
||||
Controls the two-state value that is replaced when an assignment to X is
|
||||
encountered. -x-assign=fast, the default, converts all Xs to whatever is
|
||||
best for performance. -x-assign=0 converts all Xs to 0s, and is also fast.
|
||||
-x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
|
||||
likely to find reset bugs as active high logic will fire. -x-assign=unique
|
||||
encountered. --x-assign=fast, the default, converts all Xs to whatever is
|
||||
best for performance. --x-assign=0 converts all Xs to 0s, and is also fast.
|
||||
--x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
|
||||
likely to find reset bugs as active high logic will fire. --x-assign=unique
|
||||
will call a function to determine the value, this allows randomization of
|
||||
all Xs to find reset bugs and is the slowest, but safest for finding reset
|
||||
bugs in code.
|
||||
|
||||
If using -x-assign unique, you may want to seed your random number
|
||||
If using --x-assign unique, you may want to seed your random number
|
||||
generator such that each regression run gets a different randomization
|
||||
sequence. Use the system's srand48() or for Windows srand() function to do
|
||||
this. You'll probably also want to print any seeds selected, and code to
|
||||
enable rerunning with that same seed so you can reproduce bugs.
|
||||
|
||||
B<Note.> This option applies only to variables which are explicitly assigned
|
||||
to X in the Verilog source code. Initial values of clocks are set to 0 unless
|
||||
--x-initial-edge is specified. Initial values of all other state holding
|
||||
variables are set as though --x-assign unique had been specified.
|
||||
|
||||
=item --x-initial-edge
|
||||
|
||||
Enables emulation of event driven simulators which generally trigger an
|
||||
edge on a transition from X to 1 (C<posedge>) or X to 0 (C<negedge>). Thus
|
||||
the following code, where C<rst_n> is uninitialized would set C<res_n> to
|
||||
C<1'b1> when C<rst_n> is first set to zero:
|
||||
|
||||
reg res_n = 1'b0;
|
||||
|
||||
always @(negedge rst_n) begin
|
||||
if (rst_n == 1'b0) begin
|
||||
res_n <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
In Verilator, by default, uninitialized clocks are given a value of zero,
|
||||
so the above C<always> block would not trigger.
|
||||
|
||||
While it is not good practice, there are some designs that rely on X
|
||||
E<rarr> 0 triggering a C<negedge>, particularly in reset sequences. Using
|
||||
--x-initial-edge with Verilator will replicate this behaviour. It will also
|
||||
ensure that X E<rarr> 1 triggers a C<posedge>.
|
||||
|
||||
B<Note.> Some users have reported that using this option can affect
|
||||
convergence, and that it may be necessary to use --converge-limit to
|
||||
increase the number of convergence iterations. This may be another
|
||||
indication of problems with the modelled design that should be addressed.
|
||||
|
||||
=item -y I<dir>
|
||||
|
||||
Add the directory to the list of directories that should be searched for
|
||||
@@ -1026,6 +1096,7 @@ We'll compile this example into C++.
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Vour* top = new Vour;
|
||||
while (!Verilated::gotFinish()) { top->eval(); }
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@@ -1093,6 +1164,7 @@ This is an example similar to the above, but using SystemPerl.
|
||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@@ -1126,6 +1198,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
|
||||
|
||||
@@ -1146,9 +1221,9 @@ the test_sp directory in the distribution for an example.
|
||||
|
||||
=head1 BENCHMARKING & OPTIMIZATION
|
||||
|
||||
For best performance, run Verilator with the "-O3 -x-assign=fast
|
||||
For best performance, run Verilator with the "-O3 --x-assign=fast
|
||||
--noassert" flags. The -O3 flag will require longer compile times, and
|
||||
-x-assign=fast may increase the risk of reset bugs in trade for
|
||||
--x-assign=fast may increase the risk of reset bugs in trade for
|
||||
performance; see the above documentation for these flags.
|
||||
|
||||
Minor Verilog code changes can also give big wins. You should not have any
|
||||
@@ -1163,8 +1238,10 @@ C++ compiler and size of your CPU's caches.
|
||||
By default, the lib/verilated.mk file has optimization turned off. This is
|
||||
for the benefit of new users, as it improves compile times at the cost of
|
||||
runtimes. To add optimization as the default, set one of three variables,
|
||||
OPT, OPT_FAST, or OPT_SLOW in lib/verilated.mk. Or, just for one run, pass
|
||||
them on the command line to make:
|
||||
OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
|
||||
-LDFLAGS option on the verilator command line to pass the flags directly to
|
||||
the compiler or linker. Or, just for one run, pass them on the command
|
||||
line to make:
|
||||
|
||||
make OPT_FAST="-O2" -f Vour.mk Vour__ALL.a
|
||||
|
||||
@@ -1175,7 +1252,9 @@ rarely, yet take a long time to compile with optimization on. OPT
|
||||
specifies overall optimization and affects all compiles, including those
|
||||
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
|
||||
with "-static". Nearly the same results can be had with much better
|
||||
compile times with OPT_FAST="-O1 -fstrict-aliasing".
|
||||
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
|
||||
such as "-O3" may help, but gcc compile times may be excessive under O3 on
|
||||
even medium sized designs.
|
||||
|
||||
Unfortunately, using the optimizer with SystemC files can result in
|
||||
compiles taking several minutes. (The SystemC libraries have many little
|
||||
@@ -1189,6 +1268,11 @@ If you will be running many simulations on a single compile, investigate
|
||||
feedback driven compilation. With GCC, using -fprofile-arcs, then
|
||||
-fbranch-probabilities will yield another 15% or so.
|
||||
|
||||
Modern compilers also support link-time optimization (LTO), which can help
|
||||
especially if you link in DPI code. To enable LTO on GCC, pass "-flto" in
|
||||
both compilation and link. Note LTO may cause excessive compile times on
|
||||
large designs.
|
||||
|
||||
You may uncover further tuning possibilities by profiling the Verilog code.
|
||||
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
|
||||
either oprofile or gprof to see where in the C++ code the time is spent.
|
||||
@@ -1279,7 +1363,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
|
||||
|
||||
@@ -1388,6 +1472,7 @@ example:
|
||||
|
||||
top->final(); // Done simulating
|
||||
// // (Though this example doesn't get here)
|
||||
delete top;
|
||||
}
|
||||
|
||||
Note signals are read and written as member variables of the lower module.
|
||||
@@ -1734,8 +1819,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 +2290,71 @@ 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.
|
||||
|
||||
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.
|
||||
|
||||
B<Note.> --x-assign applies to variables explicitly initialized or assigned to
|
||||
X. Unititialized clocks are initialized to zero, while all other state holding
|
||||
variables are initialized to a random value.
|
||||
|
||||
Event driven simulators will generally trigger an edge on a transition from X
|
||||
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
||||
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
|
||||
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
||||
runs with and without this switch will find such problems.
|
||||
|
||||
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.
|
||||
|
||||
=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.
|
||||
|
||||
@@ -2351,6 +2458,12 @@ Increment/decrement can only be used as standalone statements or in for
|
||||
loops. They cannot be used as side effect operators inside more complicate
|
||||
expressions ("a = b++;").
|
||||
|
||||
=item '{} operator
|
||||
|
||||
Assignment patterns with order based, default, constant integer (array) or
|
||||
member identifier (struct/union) keys are supported. Data type keys and
|
||||
keys which are computed from a constant expression are not supported.
|
||||
|
||||
=item cast operator
|
||||
|
||||
Casting is supported only between simple scalar types, signed and unsigned,
|
||||
@@ -2712,6 +2825,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 +2871,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 +3534,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 +3599,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.
|
||||
@@ -3502,9 +3656,11 @@ Major concepts by Paul Wasson and Duane Galbi.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>
|
||||
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>,
|
||||
|
||||
And internals.txt in the distribution.
|
||||
L<verilator --help> which is the source for this document,
|
||||
|
||||
and internals.txt in the distribution.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
+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;
|
||||
|
||||
+4
-1
@@ -4,7 +4,9 @@
|
||||
# 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],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.842 2012-11-03])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
|
||||
@@ -128,6 +130,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.
|
||||
|
||||
+29
-14
@@ -33,14 +33,10 @@
|
||||
// Global variables
|
||||
|
||||
// Slow path variables
|
||||
int Verilated::s_randReset = 0;
|
||||
VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||
|
||||
// Keep below together in one cache line
|
||||
int Verilated::s_debug = 0;
|
||||
bool Verilated::s_calcUnusedSigs = false;
|
||||
bool Verilated::s_gotFinish = false;
|
||||
bool Verilated::s_assertOn = true;
|
||||
Verilated::Serialized Verilated::s_s;
|
||||
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
||||
VL_THREAD int Verilated::t_dpiLineno = 0;
|
||||
@@ -81,6 +77,17 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// Overall class init
|
||||
|
||||
Verilated::Serialized::Serialized() {
|
||||
s_randReset = 0;
|
||||
s_debug = 0;
|
||||
s_calcUnusedSigs = false;
|
||||
s_gotFinish = false;
|
||||
s_assertOn = true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Random reset -- Only called at init time, so don't inline.
|
||||
|
||||
@@ -301,7 +308,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
const char *ep = pos;
|
||||
while (ep[0] && ep[0]!='%') ep++;
|
||||
if (ep != pos) {
|
||||
output += string(pos, ep-pos);
|
||||
output.append(pos, ep-pos);
|
||||
pos += ep-pos-1;
|
||||
}
|
||||
} else { // Format character
|
||||
@@ -346,9 +353,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
QData ld = 0;
|
||||
WData qlwp[2];
|
||||
WDataInP lwp;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
WData qlwp[2];
|
||||
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||
VL_SET_WQ(qlwp,ld);
|
||||
lwp = qlwp;
|
||||
@@ -750,9 +757,10 @@ void VL_FCLOSE_I(IData fdi) {
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -760,9 +768,10 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
}
|
||||
|
||||
string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -770,9 +779,10 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -781,12 +791,13 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -949,13 +960,13 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
|
||||
}
|
||||
|
||||
IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
string match = VerilatedImp::argPlusMatch(formatp);
|
||||
const string& match = VerilatedImp::argPlusMatch(formatp);
|
||||
if (match == "") return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
if (match == "") return 0;
|
||||
VL_ZERO_RESET_W(rbits, rwp);
|
||||
@@ -991,7 +1002,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
||||
}
|
||||
|
||||
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match == "") return NULL;
|
||||
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
|
||||
@@ -1056,6 +1067,10 @@ void Verilated::commandArgs(int argc, const char** argv) {
|
||||
VerilatedImp::commandArgs(argc,argv);
|
||||
}
|
||||
|
||||
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
||||
return VerilatedImp::argPlusMatch(prefixp).c_str();
|
||||
}
|
||||
|
||||
void Verilated::scopesDump() {
|
||||
VerilatedImp::scopesDump();
|
||||
}
|
||||
|
||||
+23
-16
@@ -219,14 +219,18 @@ struct Verilated {
|
||||
// MEMBERS
|
||||
private:
|
||||
// Slow path variables
|
||||
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
static VerilatedVoidCb s_flushCb; ///< Flush callback function
|
||||
|
||||
// Fast path
|
||||
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||
static bool s_gotFinish; ///< A $finish statement executed
|
||||
static bool s_assertOn; ///< Assertions are enabled
|
||||
static struct Serialized { // All these members serialized/deserialized
|
||||
// Slow path
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
// Fast path
|
||||
int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||
bool s_gotFinish; ///< A $finish statement executed
|
||||
bool s_assertOn; ///< Assertions are enabled
|
||||
Serialized();
|
||||
} s_s;
|
||||
|
||||
static VL_THREAD const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
||||
@@ -241,29 +245,29 @@ public:
|
||||
/// 0 = Set to zeros
|
||||
/// 1 = Set all bits to one
|
||||
/// 2 = Randomize all bits
|
||||
static void randReset(int val) { s_randReset=val; }
|
||||
static int randReset() { return s_randReset; } ///< Return randReset value
|
||||
static void randReset(int val) { s_s.s_randReset=val; }
|
||||
static int randReset() { return s_s.s_randReset; } ///< Return randReset value
|
||||
|
||||
/// Enable debug of internal verilated code
|
||||
static inline void debug(int level) { s_debug = level; }
|
||||
static inline void debug(int level) { s_s.s_debug = level; }
|
||||
#ifdef VL_DEBUG
|
||||
static inline int debug() { return s_debug; } ///< Return debug value
|
||||
static inline int debug() { return s_s.s_debug; } ///< Return debug value
|
||||
#else
|
||||
static inline int debug() { return 0; } ///< Constant 0 debug, so C++'s optimizer rips up
|
||||
#endif
|
||||
/// Enable calculation of unused signals
|
||||
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
||||
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
static void calcUnusedSigs(bool flag) { s_s.s_calcUnusedSigs=flag; }
|
||||
static bool calcUnusedSigs() { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
/// Did the simulation $finish?
|
||||
static void gotFinish(bool flag) { s_gotFinish=flag; }
|
||||
static bool gotFinish() { return s_gotFinish; } ///< Return if got a $finish
|
||||
static void gotFinish(bool flag) { s_s.s_gotFinish=flag; }
|
||||
static bool gotFinish() { return s_s.s_gotFinish; } ///< Return if got a $finish
|
||||
/// Allow traces to at some point be enabled (disables some optimizations)
|
||||
static void traceEverOn(bool flag) {
|
||||
if (flag) { calcUnusedSigs(flag); }
|
||||
}
|
||||
/// Enable/disable assertions
|
||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
||||
static bool assertOn() { return s_assertOn; }
|
||||
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
|
||||
static bool assertOn() { return s_s.s_assertOn; }
|
||||
/// Flush callback for VCD waves
|
||||
static void flushCb(VerilatedVoidCb cb);
|
||||
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
|
||||
@@ -271,6 +275,7 @@ public:
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||
|
||||
/// For debugging, print text list of all scope names with
|
||||
/// dpiImport/Export context. This function may change in future
|
||||
@@ -292,6 +297,8 @@ public:
|
||||
static const char* dpiFilenamep() { return t_dpiFilename; }
|
||||
static int dpiLineno() { return t_dpiLineno; }
|
||||
static int exportFuncNum(const char* namep);
|
||||
static size_t serializedSize() { return sizeof(s_s); }
|
||||
static void* serializedPtr() { return &s_s; }
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
`define _VERILATED_V_ 1
|
||||
|
||||
// Hide verilator pragmas from other tools
|
||||
`ifdef verilator `else
|
||||
`ifdef VERILATOR `else
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ class VerilatedImp {
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
|
||||
ArgVec m_argVec; ///< Argument list
|
||||
// Nothing here is save-restored; users expected to re-register appropriately
|
||||
|
||||
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
||||
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2012 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief C++ Tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_save.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
// CONSTANTS
|
||||
static const char* VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
|
||||
static const char* VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Searalization
|
||||
|
||||
bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t size) {
|
||||
bufferCheck();
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
vluint8_t miss = 0;
|
||||
while (size--) {
|
||||
miss |= (*dp++ ^ *m_cp++);
|
||||
}
|
||||
return (miss!=0);
|
||||
}
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
string msg = (string)"Can't deserialize save-restore file as was made from different model";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
|
||||
void VerilatedSerialize::header() {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_HEADER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR));
|
||||
|
||||
// Verilated doesn't do it itself, as if we're not using save/restore
|
||||
// it doesn't need to compile this stuff in
|
||||
os.write(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::header() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
string msg = (string)"Can't deserialize; file has wrong header signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedSerialize::trailer() {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_TRAILER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR));
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::trailer() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Opening/Closing
|
||||
|
||||
void VerilatedSave::open (const char* filenamep) {
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltSave: opening save file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
m_fd = ::open (filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
m_cp = m_bufp;
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedRestore::open (const char* filenamep) {
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltRestore: opening restore file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
m_fd = ::open (filenamep, O_CREAT|O_RDONLY|O_LARGEFILE
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
m_cp = m_bufp;
|
||||
m_endp = m_bufp;
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedSave::close () {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
void VerilatedRestore::close () {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Buffer management
|
||||
|
||||
void VerilatedSave::flush() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
vluint8_t* wp = m_bufp;
|
||||
while (1) {
|
||||
ssize_t remaining = (m_cp - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::write (m_fd, wp, remaining);
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
}
|
||||
|
||||
void VerilatedRestore::fill() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||
vluint8_t* rp = m_bufp;
|
||||
for (vluint8_t* sp=m_cp; rp < m_endp;) *rp++ = *sp++; // Overlaps
|
||||
m_endp = m_bufp + (m_endp - m_cp);
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
while (1) {
|
||||
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::read (m_fd, m_endp, remaining);
|
||||
if (got>0) {
|
||||
m_endp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
} else { // got==0, EOF
|
||||
// Fill buffer from here to end with NULLs so reader's don't need to check eof each character.
|
||||
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Serialization of types
|
||||
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2012-2012 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Save-restore serialization of verilated modules
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef _VERILATED_SAVE_C_H_
|
||||
#define _VERILATED_SAVE_C_H_ 1
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialBase - internal base class for common code between VerilatedSerialize and VerilatedDeserialize
|
||||
|
||||
class VerilatedSerialBase {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
string m_filename;
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
// CREATORS
|
||||
VerilatedSerialBase() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
virtual ~VerilatedSerialBase() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
|
||||
class VerilatedSerialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSerialize() {}
|
||||
virtual ~VerilatedSerialize() { close(); }
|
||||
// METHODS
|
||||
VerilatedSerialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
inline VerilatedSerialize& write (const void* __restrict datap, size_t size) {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *m_cp++ = *dp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedDeserial - load structures from a stream representation
|
||||
|
||||
class VerilatedDeserialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
virtual void fill() = 0;
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedDeserialize() {}
|
||||
virtual ~VerilatedDeserialize() { close(); }
|
||||
// METHODS
|
||||
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *dp++ = *m_cp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
// Read a datum and compare with expected value
|
||||
bool readDiffers (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (vluint64_t data) { return readAssert(&data, sizeof(data)); }
|
||||
VerilatedDeserialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
|
||||
fill();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSave - serialize to a file
|
||||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSave() {}
|
||||
virtual ~VerilatedSave() { close(); }
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedRestore - deserialize from a file
|
||||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedRestore() {}
|
||||
virtual ~VerilatedRestore() { close(); }
|
||||
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush() {}
|
||||
virtual void fill();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint64_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs){
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint32_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint16_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint8_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, bool& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, bool& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, double& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, double& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
|
||||
vluint32_t len=rhs.length();
|
||||
os<<len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
||||
vluint32_t len;
|
||||
os>>len;
|
||||
rhs.resize(len);
|
||||
return os.read((void*)rhs.data(), len);
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
virtual const char* name() { return m_varp->name(); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
out = string(m_scopep->name())+"."+name();
|
||||
return out.c_str();
|
||||
}
|
||||
@@ -207,7 +207,7 @@ public:
|
||||
virtual ~VerilatedVpioVarIndex() {}
|
||||
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
out = string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
return out.c_str();
|
||||
|
||||
@@ -78,8 +78,12 @@
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
# endif
|
||||
# define VL_STATIC_OR_THREAD ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
#else
|
||||
# define VL_THREAD ///< Storage class for thread-local storage
|
||||
# define VL_STATIC_OR_THREAD static ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -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
|
||||
|
||||
+285
-46
@@ -14,32 +14,6 @@ the first for reference for developers and debugging problems.
|
||||
|
||||
See also the Verilator internals presentation at http://www.veripool.org.
|
||||
|
||||
=head1 ADDING A NEW FEATURE
|
||||
|
||||
Generally what would you do to add a new feature?
|
||||
|
||||
=over 4
|
||||
|
||||
File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see TESTING Below.
|
||||
|
||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
||||
|
||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||
file which you can examine to see if the parsing worked. See also the
|
||||
sections below on debugging.
|
||||
|
||||
Modify the later visitor functions to process the new feature as needed.
|
||||
|
||||
=back
|
||||
|
||||
=head1 CODE FLOWS
|
||||
|
||||
=head2 Verilator Flow
|
||||
@@ -93,6 +67,10 @@ Verilator finally writes the C++ modules.
|
||||
|
||||
=head2 Key Classes Used in the Verilator Flow
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<AstNode>
|
||||
|
||||
The AST is represented at the top level by the class C<AstNode>. This abstract
|
||||
class has derived classes for the individual components (e.g. C<AstGenerate>
|
||||
for a generate block) or groups of components (e.g. C<AstNodeFTask> for
|
||||
@@ -119,11 +97,64 @@ are at the top of the tree.
|
||||
By convention, each function/method uses the variable C<nodep> as a pointer
|
||||
to the C<AstNode> currently being processed.
|
||||
|
||||
=item C<AstNVistor>
|
||||
|
||||
The passes are implemented by AST visitor classes (see L</Visitor
|
||||
Functions>). These are implemented by subclasses of the abstract class,
|
||||
C<AstNVisitor>. Each pass creates an instance of the visitor class, which
|
||||
in turn implements a method to perform the pass.
|
||||
|
||||
=item C<V3Graph>
|
||||
|
||||
A number of passes use graph algorithms, and the class C<V3Graph> is provided
|
||||
to represent those graphs. Graphs are directed, and algorithms are provided to
|
||||
manipulate the graphs and to output them in I<GraphViz> dot format (see
|
||||
L<http://www.graphviz.org/>). C<V3Graph.h> provides documentation of this
|
||||
class.
|
||||
|
||||
=item C<V3GraphVertex>
|
||||
|
||||
This is the base class for vertices in a graph. Vertices have an associated
|
||||
C<fanout>, C<color> and C<rank>, which may be used in algorithms for ordering
|
||||
the graph. A generic C<user>/C<userp> member variable is also provided.
|
||||
|
||||
Virtual methods are provided to specify the name, color, shape and style to be
|
||||
used in dot output. Typically users provided derived classes from
|
||||
C<V3GraphVertex> which will reimplement these methods.
|
||||
|
||||
Iterators are provided to access in and out edges. Typically these are used in
|
||||
the form:
|
||||
|
||||
for (V3GraphEdge *edgep = vertexp->inBeginp();
|
||||
edgep;
|
||||
edgep = edgep->inNextp()) {
|
||||
|
||||
=item C<V3GraphEdge>
|
||||
|
||||
This is the base class for directed edges between pairs of vertices. Edges
|
||||
have an associated C<weight> and may also be made C<cutable>. A generic
|
||||
C<user>/C<userp> member variable is also provided.
|
||||
|
||||
Accessors, C<fromp> and C<top> return the "from" and "to" vertices
|
||||
respectively.
|
||||
|
||||
Virtual methods are provided to specify the label, color and style to be
|
||||
used in dot output. Typically users provided derived classes from
|
||||
C<V3GraphEdge> which will reimplement these methods.
|
||||
|
||||
=item C<V3GraphAlg>
|
||||
|
||||
This is the base class for graph algorithms. It implements a C<bool> method,
|
||||
C<followEdge> which algorithms can use to decide whether an edge is
|
||||
followed. This method returns true if the graph edge has weight greater than
|
||||
one and a user function, C<edgeFuncp> (supplied in the constructor) returns
|
||||
C<true>.
|
||||
|
||||
A number of predefined derived algorithm classes and access methods are
|
||||
provided and documented in C<V3GraphAlg.cpp>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Verilated Flow
|
||||
|
||||
The evaluation loop outputted by Verilator is designed to allow a single
|
||||
@@ -178,16 +209,15 @@ TREEOP macro.
|
||||
|
||||
The original C++ source code is transformed into C++ code in the C<obj_opt>
|
||||
and C<obj_dbg> sub-directories (the former for the optimized version of
|
||||
verilator, the latter for the debug version). So for example C<V3Const.cpp>
|
||||
Verilator, the latter for the debug version). So for example C<V3Const.cpp>
|
||||
into C<V3Const__gen.cpp>.
|
||||
|
||||
=head2 Visitor Functions
|
||||
|
||||
The verilator uses the I<Visitor> design pattern to implement its
|
||||
refinement and optimization passes. This allows separation of the pass
|
||||
algorithm from the AST on which it operates. Wikipedia provides an
|
||||
introduction to the concept at
|
||||
L<http://en.wikipedia.org/wiki/Visitor_pattern>.
|
||||
Verilator uses the I<Visitor> design pattern to implement its refinement
|
||||
and optimization passes. This allows separation of the pass algorithm from
|
||||
the AST on which it operates. Wikipedia provides an introduction to the
|
||||
concept at L<http://en.wikipedia.org/wiki/Visitor_pattern>.
|
||||
|
||||
As noted above, all visitors are derived classes of C<AstNvisitor>. All
|
||||
derived classes of C<AstNode> implement the C<accept> method, which takes
|
||||
@@ -336,10 +366,78 @@ 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
|
||||
|
||||
It is important to add tests for failures as well as success (for example to
|
||||
check that an error message is correctly triggered).
|
||||
|
||||
Tests that fail should by convenition have the suffix C<_bad> in their name,
|
||||
and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
|
||||
appropriate.
|
||||
|
||||
Developers will also want to configure with two extra flags:
|
||||
|
||||
=over 4
|
||||
|
||||
=item --enable-ccwarn
|
||||
|
||||
Causes the build to stop on warnings as well as errors. A good way to
|
||||
ensure no sloppy code gets added, however it can be painful when it comes
|
||||
to testing, since third party code used in the tests (e.g. SystemC) may not
|
||||
be warning free.
|
||||
|
||||
=item --enable-longtests
|
||||
|
||||
In addition to the standard C, SystemC and SystemPerl tests also run the
|
||||
tests in the C<test_vcs>, C<test_verilated> and C<test_regress> directories
|
||||
when using I<make test>. This is disabled by default as SystemC/SystemPerl
|
||||
installation problems would otherwise falsely indicate a Verilator problem.
|
||||
|
||||
=back
|
||||
|
||||
When enabling the long tests, some additional PERL modules are needed, which
|
||||
you can install using cpan.
|
||||
|
||||
cpan install Unix::Processors
|
||||
|
||||
There are some traps to avoid when running regression tests
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The regression tests will assume that you have a version of SystemPerl to
|
||||
match. Typically if working on Verilator from git, also use SystemPerl from
|
||||
git.
|
||||
|
||||
=item *
|
||||
|
||||
When checking the MANIFEST, the test will barf on unexpected code in the
|
||||
Verilator tree. So make sure to keep any such code outside the tree.
|
||||
|
||||
=item *
|
||||
|
||||
Not all Linux systems install Perldoc by default. This is needed for the
|
||||
I<--help> option to Verilator, and also for regression testing. This can be
|
||||
installed using cpan:
|
||||
|
||||
cpan install Pod::Perldoc
|
||||
|
||||
Many Linux systems also offer a standard package for this. Red
|
||||
Hat/Fedora/Centos offer I<perl-Pod-Perldoc>, while Debian/Ubuntu/Linux Mint
|
||||
offer I<perl-doc>.
|
||||
|
||||
=item *
|
||||
|
||||
Running regression may exhaust resources on some Linux systems, particularly
|
||||
file handles and user processes. Increase these to respectively 16,384 and
|
||||
4,096. The method of doing this is system dependent, but on Fedora Linux it
|
||||
would require editing the C</etc/security/limits.conf> file as root.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DEBUGGING
|
||||
|
||||
@@ -369,13 +467,16 @@ 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
|
||||
|
||||
The following summarizes the above example dump, with more detail on each
|
||||
field in the section below.
|
||||
|
||||
"1:2:" indicates the hierarchy of the C<VAR> is the C<op2p> pointer under
|
||||
the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
|
||||
|
||||
@@ -384,13 +485,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 +501,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>.
|
||||
|
||||
=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
|
||||
@@ -406,7 +599,7 @@ under gdb and break when an error is hit or the program is about to exit.
|
||||
You can also use --debug --gdbbt to just backtrace and then exit gdb. To
|
||||
debug the Verilated executable, use --gdbsim.
|
||||
|
||||
If you wish to start verilator under GDB (or another debugger), then you
|
||||
If you wish to start Verilator under GDB (or another debugger), then you
|
||||
can use --debug and look at the underlying invocation of verilator_dgb. For
|
||||
example
|
||||
|
||||
@@ -439,8 +632,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
|
||||
@@ -454,6 +649,50 @@ backtrace. You will typically see a frame sequence something like
|
||||
visit()
|
||||
...
|
||||
|
||||
=head1 ADDING A NEW FEATURE
|
||||
|
||||
Generally what would you do to add a new feature?
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
=item 2.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see L<TESTING>.
|
||||
|
||||
=item 3.
|
||||
|
||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
=item 4.
|
||||
|
||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
||||
|
||||
=back
|
||||
|
||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||
file which you can examine to see if the parsing worked. See also the
|
||||
sections above on debugging.
|
||||
|
||||
Modify the later visitor functions to process the new feature as needed.
|
||||
|
||||
=head2 Adding a new pass
|
||||
|
||||
For more substantial changes you may need to add a new pass. The simplest way
|
||||
to do this is to copy the C<.cpp> and C<.h> files from an existing
|
||||
pass. You'll need to add a call into your pass from the C<process()> function
|
||||
in C<src/verilator.cpp>.
|
||||
|
||||
To get your pass to build you'll need to add its binary filename to the list
|
||||
in C<src/Makefile_obj.in> and reconfigure.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
@@ -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::
|
||||
|
||||
+1
-1
@@ -198,7 +198,6 @@ RAW_OBJS = \
|
||||
V3Inst.o \
|
||||
V3Life.o \
|
||||
V3LifePost.o \
|
||||
V3Link.o \
|
||||
V3LinkCells.o \
|
||||
V3LinkDot.o \
|
||||
V3LinkJump.o \
|
||||
@@ -220,6 +219,7 @@ RAW_OBJS = \
|
||||
V3SplitAs.o \
|
||||
V3Stats.o \
|
||||
V3StatsReport.o \
|
||||
V3String.o \
|
||||
V3Subst.o \
|
||||
V3Table.o \
|
||||
V3Task.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);
|
||||
|
||||
+506
-218
File diff suppressed because it is too large
Load Diff
+7
-13
@@ -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
|
||||
@@ -136,32 +134,27 @@ private:
|
||||
if (m_unnamedScope=="") m_unnamedScope = ident;
|
||||
else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
|
||||
// Create CellInline for dotted var resolution
|
||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||
m_unnamedScope, "__BEGIN__");
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
if (!m_ftaskp) {
|
||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||
m_unnamedScope, "__BEGIN__");
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@@ -193,6 +186,7 @@ private:
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
// Similar code in V3Inline
|
||||
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
||||
if (m_namedScope != "") {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
|
||||
@@ -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
|
||||
|
||||
+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
|
||||
@@ -85,7 +83,7 @@ private:
|
||||
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
|
||||
AstVar* varp = vscp->varp();
|
||||
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
|
||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->name());
|
||||
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
|
||||
m_modp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||
|
||||
@@ -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
-3
@@ -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
|
||||
@@ -27,6 +25,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Config.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -91,7 +90,7 @@ class V3ConfigIgnores {
|
||||
it = m_ignFiles.find(filename);
|
||||
// Make new list for this file of all matches
|
||||
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
|
||||
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
if (VString::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
|
||||
it->second.insert(*lit);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+115
-13
@@ -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,6 +29,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3EmitC.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
@@ -487,7 +486,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 +623,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");
|
||||
@@ -843,6 +843,7 @@ class EmitCImp : EmitCStmts {
|
||||
void emitCoverageDecl(AstNodeModule* modp);
|
||||
void emitCoverageImp(AstNodeModule* modp);
|
||||
void emitDestructorImp(AstNodeModule* modp);
|
||||
void emitSavableImp(AstNodeModule* modp);
|
||||
void emitTextSection(AstType type);
|
||||
void emitIntFuncDecls(AstNodeModule* modp);
|
||||
// High level
|
||||
@@ -1192,11 +1193,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 +1288,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);
|
||||
}
|
||||
@@ -1367,7 +1368,16 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
if (zeroit) {
|
||||
puts(" = 0;\n");
|
||||
// We want to force an initial edge on uninitialized clocks (from 'X' to
|
||||
// whatever the first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash with any initial
|
||||
// block settings. Clocks are always BIT datatypes, so zeroit is true.
|
||||
if (v3Global.opt.xInitialEdge()
|
||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||
puts(" = 1;\n");
|
||||
} else {
|
||||
puts(" = 0;\n");
|
||||
}
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
@@ -1437,7 +1447,7 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
|
||||
// compatible, and have a common wrapper.
|
||||
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
|
||||
puts( "const char* hierp, const char* pagep, const char* commentp) {\n");
|
||||
puts( "static uint32_t fake_zero_count = 0;\n");
|
||||
puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant
|
||||
puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin
|
||||
puts( "*countp = 0;\n");
|
||||
puts( "SP_COVER_INSERT(countp,");
|
||||
@@ -1460,6 +1470,79 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) {
|
||||
puts("}\n");
|
||||
}
|
||||
|
||||
void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("\n// Savable\n");
|
||||
for (int de=0; de<2; ++de) {
|
||||
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
|
||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||
string writeread = de ? "read" : "write";
|
||||
string op = de ? ">>" : "<<";
|
||||
puts("void "+modClassName(modp)+"::"+funcname+"("+classname+"& os) {\n");
|
||||
// Place a computed checksum to insure proper structure save/restore formatting
|
||||
// OK if this hash includes some things we won't dump, since just looking for loading the wrong model
|
||||
VHashFnv hash;
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
hash.hash(varp->name());
|
||||
hash.hash(varp->dtypep()->width());
|
||||
}
|
||||
}
|
||||
ofp()->printf( "vluint64_t __Vcheckval = VL_ULL(0x%" VL_PRI64 "x);\n",
|
||||
hash.value());
|
||||
if (de) {
|
||||
puts("os.readAssert(__Vcheckval);\n");
|
||||
} else {
|
||||
puts("os<<__Vcheckval;\n");
|
||||
}
|
||||
|
||||
// Save all members
|
||||
if (v3Global.opt.inhibitSim()) puts("os"+op+"__Vm_inhibitSim;\n");
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
if (varp->isIO() && modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.
|
||||
}
|
||||
else if (varp->isParam()) {}
|
||||
else if (varp->isStatic() && varp->isConst()) {}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
|
||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
if (varp->basicp() && (varp->basicp()->keyword() == AstBasicDTypeKwd::STRING
|
||||
|| !varp->basicp()->isWide())) {
|
||||
puts("os"+op+varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(";\n");
|
||||
} else {
|
||||
puts("os."+writeread+"(&"+varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(",sizeof("+varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts("));\n");
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modp->isTop()) { // Save the children
|
||||
puts( "__VlSymsp->"+funcname+"(os);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
|
||||
// Need implementation here. Be careful of alignment code; needs to be uniquified
|
||||
// with module name to avoid multiple symbols.
|
||||
@@ -1558,7 +1641,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 +1661,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");
|
||||
@@ -1674,8 +1759,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
} else {
|
||||
puts("#include \"verilated.h\"\n");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
puts("#include \"verilated_save.h\"\n");
|
||||
}
|
||||
if (v3Global.opt.coverage()) {
|
||||
puts("#include \"SpCoverage.h\"\n");
|
||||
if (v3Global.opt.savable()) v3error("--coverage and --savable not supported together");
|
||||
}
|
||||
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||
@@ -1841,10 +1930,22 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
puts("static void traceFull ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||
puts("static void traceChg ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||
puts("} VL_ATTR_ALIGNED(128);\n");
|
||||
puts("\n");
|
||||
|
||||
// Save/restore
|
||||
if (v3Global.opt.savable() && modp->isTop()) {
|
||||
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vserialize(os); return os;}\n");
|
||||
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vdeserialize(os); return os;}\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// finish up h-file
|
||||
if (!optSystemPerl()) {
|
||||
puts("#endif /*guard*/\n");
|
||||
@@ -1892,6 +1993,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
emitCtorImp(modp);
|
||||
emitConfigureImp(modp);
|
||||
emitDestructorImp(modp);
|
||||
emitSavableImp(modp);
|
||||
emitCoverageImp(modp);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+32
-7
@@ -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
|
||||
@@ -117,8 +115,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
AstScope* scopep = it->first; AstNodeModule* smodp = it->second;
|
||||
for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
|
||||
AstNodeModule* modp = it->first;
|
||||
AstVar* varp = it->second;
|
||||
if (modp == smodp) {
|
||||
AstVar* varp = it->second;
|
||||
// Need to split the module + var name into the original-ish full scope and variable name under that scope.
|
||||
// The module instance name is included later, when we know the scopes this module is under
|
||||
string whole = scopep->name()+"__DOT__"+varp->name();
|
||||
@@ -206,7 +204,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->isSigUserRdPublic()) {
|
||||
if (nodep->isSigUserRdPublic()
|
||||
&& !nodep->isParam()) { // The VPI functions require a pointer to allow modification, but parameters are constants
|
||||
m_modVars.push_back(make_pair(m_modp, nodep));
|
||||
}
|
||||
}
|
||||
@@ -341,8 +340,13 @@ void EmitCSyms::emitSymHdr() {
|
||||
puts("\n// METHODS\n");
|
||||
puts("inline const char* name() { return __Vm_namep; }\n");
|
||||
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
}
|
||||
puts("\n");
|
||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||
puts("\n");
|
||||
puts("#endif /*guard*/\n");
|
||||
}
|
||||
|
||||
@@ -462,8 +466,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();
|
||||
}
|
||||
@@ -500,7 +504,28 @@ void EmitCSyms::emitSymImp() {
|
||||
}
|
||||
|
||||
puts("}\n");
|
||||
puts("\n");
|
||||
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("\n");
|
||||
for (int de=0; de<2; ++de) {
|
||||
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
|
||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||
string op = de ? ">>" : "<<";
|
||||
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
|
||||
puts( "// LOCAL STATE\n");
|
||||
// __Vm_namep presumably already correct
|
||||
puts( "os"+op+"__Vm_activity;\n");
|
||||
puts( "os"+op+"__Vm_didInit;\n");
|
||||
puts( "// SUBCELL STATE\n");
|
||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (!modp->isTop()) {
|
||||
puts( scopep->nameDotless()+"."+funcname+"(os);\n");
|
||||
}
|
||||
}
|
||||
puts("}\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
+3
-2
@@ -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
|
||||
@@ -82,6 +80,9 @@ public:
|
||||
if (v3Global.dpi()) {
|
||||
putMakeClassEntry(of, "verilated_dpi.cpp");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
putMakeClassEntry(of, "verilated_save.cpp");
|
||||
}
|
||||
if (v3Global.opt.systemPerl()) {
|
||||
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-4
@@ -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
|
||||
@@ -31,6 +29,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3EmitXml.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
@@ -66,12 +65,12 @@ class EmitXmlFileVisitor : public EmitCBaseVisitor {
|
||||
|
||||
// XML methods
|
||||
void outputTag(AstNode* nodep, string tag) {
|
||||
if (tag=="") tag = V3Options::downcase(nodep->typeName());
|
||||
if (tag=="") tag = VString::downcase(nodep->typeName());
|
||||
puts("<"+tag+" "+nodep->fileline()->xml());
|
||||
if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); }
|
||||
}
|
||||
void outputChildrenEnd(AstNode* nodep, string tag) {
|
||||
if (tag=="") tag = V3Options::downcase(nodep->typeName());
|
||||
if (tag=="") tag = VString::downcase(nodep->typeName());
|
||||
if (nodep->op1p() || nodep->op2p() || nodep->op3p() || nodep->op4p()) {
|
||||
puts(">\n");
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+5
-7
@@ -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
|
||||
@@ -277,10 +275,10 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
||||
|
||||
// Header
|
||||
*logp<<"digraph v3graph {\n";
|
||||
*logp<<"\trankdir="<<dotRankDir()<<"\n";
|
||||
*logp<<"\t//size="<<"\"7.5,10\""<<"\n";
|
||||
*logp<<"\tnTITLE\t[fontsize=20 label=\""<<filename<<"\", shape=box, style=bold, color=black];\n";
|
||||
*logp<<"\n";
|
||||
*logp<<"\tgraph\t[label=\""<<filename<<"\",\n";
|
||||
*logp<<"\t\t labelloc=t, labeljust=l,\n";
|
||||
*logp<<"\t\t //size="<<"\"7.5,10\","<<"\n";
|
||||
*logp<<"\t\t rankdir="<<dotRankDir()<<"];\n";
|
||||
|
||||
// List of all possible subgraphs
|
||||
typedef multimap<string,V3GraphVertex*> SubgraphMmap;
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user