Compare commits

...
120 Commits
Author SHA1 Message Date
Wilson Snyder b4d5a20670 Version bump 2012-07-31 18:09:00 -04:00
Wilson Snyder 6339159b04 MAJOR: Support packed structures and unions, bug181. 2012-07-29 10:16:20 -04:00
Wilson Snyder aec019991c Tests: Misc fixes from struct branch. 2012-07-28 14:05:30 -04:00
Wilson Snyder 33e6a17747 Internals: Look at tree state instead of back for AstAttr. No functional change. 2012-07-28 10:52:29 -04:00
Wilson Snyder ecf508ec23 Fix replicate verilog dump being backwards 2012-07-28 08:25:27 -04:00
Wilson Snyder a5bcfc0509 Tests: Rename t_structure 2012-07-27 21:14:13 -04:00
Wilson Snyder 1899096ff4 Internals: Width debug and null print check 2012-07-27 21:12:06 -04:00
Wilson Snyder 6e219f5831 Internals: Rework V3WidthSel func for non-vars. No functional change intended. 2012-07-25 07:26:41 -04:00
Jeremy Bennett de1bb5aeb6 Tests: fix driver.pl not tracing time 0, bug536.
Signed-off-by: Wilson Snyder <[email protected]>
2012-07-24 18:48:51 -04:00
Wilson Snyder b52d94273c Internals: Move variable referencing into LinkDot in support of structs. 2012-07-24 06:26:35 -04:00
Wilson Snyder e655c85489 Internals: findBit etc can be const. No functional change. 2012-07-23 21:29:53 -04:00
Wilson Snyder dee7210231 Debug: add GDB dtf function to dump tree to file 2012-07-23 20:21:04 -04:00
Wilson Snyder cbd073ed08 Commentary: pthread 2012-07-23 10:12:43 -04:00
Wilson Snyder 09ebc0c163 Internals: Fix 0x tree debug suffix. Misc merges from struct. No functional change. 2012-07-22 22:48:39 -04:00
Wilson Snyder d2ede75c71 Fix compile error under git submodules, bug534. 2012-07-22 19:51:14 -04:00
Wilson Snyder 3e03fef3e3 Tests: Add t_var_notfound_bad 2012-07-22 09:09:53 -04:00
Wilson Snyder 0f583f4b33 Internals: Remove dead varref code, part of last change. 2012-07-21 21:23:57 -04:00
Wilson Snyder f175db74a5 Internals: Rework implicit handling to make room for ParseRef vs. VarRef 2012-07-21 21:18:07 -04:00
Wilson Snyder 8d5e37a413 Internals: Move trace check up. No functional change. 2012-07-21 20:33:24 -04:00
Wilson Snyder 8b9b7178a2 Internals: MAJOR CHANGE. Combine V3Link and V3LinkDot stages for structures.
Functionality should be similar, but may introduce instability in resolving variables/cells.
Final merge from dot.
2012-07-21 17:12:42 -04:00
Wilson Snyder a2f49063e2 Internals: Rename LinkDot methods. Merge from dot. No functional change 2012-07-21 09:27:57 -04:00
Wilson Snyder f3f34baa73 debug: Avoid identical skip in driver debug 2012-07-21 09:16:19 -04:00
Wilson Snyder abe9ecd225 Internals: Move AstBegin code below GenFor. No functional change. 2012-07-21 07:28:39 -04:00
Wilson Snyder 67409af38d Fix valgrind uninitialized bits. 2012-07-19 22:26:15 -04:00
Wilson Snyder b7d1c34aa6 Internals: Add more sym table debug, renames. Merge from dot. No functional change 2012-07-19 21:18:39 -04:00
Wilson Snyder 92809b95c9 driver: Sort results. Merge from dot. 2012-07-19 21:02:36 -04:00
Wilson Snyder b18690cbe2 Linking renames. Merge from dot. No functional change. 2012-07-17 21:29:10 -04:00
Wilson Snyder 96155365b2 Fix GCC 4.7.0 compile warnings, bug530. 2012-07-15 12:27:36 -04:00
Wilson Snyder 3e5067feb1 Fix svdpi.h for apple. 2012-07-15 11:33:27 -04:00
Wilson Snyder 3ec687a0cf Internals: Merge from struct branch, rework LinkDot symbol table. No functional change intended. 2012-06-20 06:13:28 -04:00
Wilson Snyder 365034d7dd Internals: Merge from struct branch, rename SymTable calls. No functional change intended. 2012-06-20 06:09:07 -04:00
Wilson Snyder 09aa9f87d8 Internals: Move initial resolution to V3LinkParse. No functional change intended. 2012-06-13 23:08:45 -04:00
Wilson Snyder 97963fb8c9 Internals: Move DECLFILENAME code to LinkCells. 2012-06-13 22:18:12 -04:00
Wilson Snyder ee1643ce39 Fix false UNUSED warning on file system calls. 2012-06-03 08:20:12 -04:00
Wilson Snyder a82cdcfe48 Add --converge-limit option. 2012-05-31 18:56:31 -04:00
Wilson Snyder 1b439703ff Fix leak issues, bug521 2012-05-30 23:17:55 -04:00
Wilson Snyder 4cc5943f90 Leak fix - Null sense item shouldn't disable event 2012-05-30 23:15:25 -04:00
Wilson Snyder 5fad666678 Fix +: and -: memory leak. 2012-05-29 23:16:13 -04:00
Wilson Snyder e12bf35996 Fix leak check compile and run, bug521. 2012-05-29 22:59:17 -04:00
Wilson Snyder d34fccec22 Internals: Remove typedefFwd earlier to simplify Link 2012-05-28 10:23:47 -04:00
Wilson Snyder 429437f1b9 Internals: Reorder code. No functional change. 2012-05-28 09:19:51 -04:00
Wilson Snyder c6e7d87960 Commentary - Remove author lines as amany contributors now 2012-05-24 19:19:48 -04:00
Wilson Snyder 716320f3ca Extra debug check 2012-05-24 19:15:28 -04:00
Wilson Snyder 1d12b47cb8 Fix internal readWholefile error check, bug518. 2012-05-22 10:20:35 -04:00
Wilson Snyder 1bc1ee9e08 Fix duplicate warnings/errors, bug516. 2012-05-21 21:31:52 -04:00
Wilson Snyder 53f50463bc Internals: Add warnMore() for all continued messages. 2012-05-21 21:24:17 -04:00
Jeremy Bennett 7ab91e660f Tests: Add t_sv_enum_type_methods, bug515.
Signed-off-by: Wilson Snyder <[email protected]>
2012-05-21 18:39:45 -04:00
Wilson Snyder 2f0e230522 Tests: New struct tests. Merge from branch. 2012-05-16 22:27:59 -04:00
Wilson Snyder 280f674ce9 Fix signed extending biops with WIDTH warning off, bug511. 2012-05-16 22:18:52 -04:00
Wilson Snyder a92c66d512 Internals: Pass expected dtype in width. No functional change intended. 2012-05-16 20:58:15 -04:00
Wilson Snyder c45eedcb02 Tests: New t_inst_signed test 2012-05-16 20:21:02 -04:00
Wilson Snyder a9a49345ba Fix loop error message to report line, bug513. 2012-05-16 19:31:24 -04:00
Wilson Snyder 8d960a2eb9 Tests: Add t_sv_cpu, bug473. By Jeremy Bennett. 2012-05-16 18:38:01 -04:00
Wilson Snyder 3e623b8959 Fix GCC 4.6.3 warning 2012-05-15 19:28:07 -04:00
Wilson Snyder 1b1991d53d Fix output with select hitting tristate, bug514. 2012-05-15 19:26:20 -04:00
Wilson Snyder 6d0f39d841 Fix sign-extension underneath boolean operators. (In theory shouldn't matter, since comparing to zero.) 2012-05-11 18:26:45 -04:00
Wilson Snyder 3087501b6c Tests: file_grep prints failing expected value when possible. 2012-05-11 18:24:49 -04:00
Wilson Snyder b429319bc0 Portability fixes for gcc 4.6.3 2012-05-10 22:04:53 -04:00
Wilson Snyder 247e855dbf Fix not showing internal error when no coredump. 2012-05-10 21:58:02 -04:00
Wilson Snyder 1aec645510 Internals: Fix dead parameter calls. No functional change. 2012-05-09 23:06:43 -04:00
Wilson Snyder 3ea2038d3d Internals: Fix dead parameter calls. No functional change. 2012-05-09 23:04:20 -04:00
Wilson Snyder 942cb5e87e Internals: Make findDtype functions use this. No functional change. 2012-05-09 22:12:57 -04:00
Wilson Snyder 37a3a7cdce Fix tristate bug512, broken with tristate commit. 2012-05-09 20:34:15 -04:00
Wilson Snyder 435a27b66a Tristate: Major rework to support Z tieoffs, bug499, bug510. 2012-05-08 21:53:22 -04:00
Wilson Snyder b31a7cdcbf Internals: Fix uninitialized m_alhs 2012-05-08 20:05:43 -04:00
Wilson Snyder ac61548e6a Optimize tristate structure OR(AND(x,y),AND(z,y)). 2012-05-08 19:20:23 -04:00
Wilson Snyder f5ace0f72a Tests: Add bug508, bug509 examples 2012-05-08 17:41:42 -04:00
Wilson Snyder e498b73933 Internals: Misc tristate merges. Pins renamed but... No functional change intended. 2012-05-07 23:43:19 -04:00
Wilson Snyder ff69bdbc6f Debug: Add @ to end of dtype to avoid miscutting 2012-05-07 19:01:45 -04:00
Wilson Snyder 0c1e184cb7 Fix newlines in radix values, bug507. 2012-05-07 08:58:29 -04:00
Wilson Snyder e97541dcbc Internals: Minor tristate changes from branch. No functional change. 2012-05-06 16:52:08 -04:00
Wilson Snyder 7b3eb22865 Fix compile warning 2012-05-06 14:05:56 -04:00
Wilson Snyder d55f065ce2 Internals: Tristate join AND/OR visitor pull setter. No functional change 2012-05-05 15:04:33 -04:00
Wilson Snyder 86af244636 Internals: Tristate common pull setter. No functional change 2012-05-05 15:03:00 -04:00
Wilson Snyder 2c9e2b2e3c Internals: Common insert function in tristate. No functional change. 2012-05-05 14:55:35 -04:00
Wilson Snyder 33c8bf886e Debug: Assume PDF output for dot. 2012-05-05 14:50:11 -04:00
Wilson Snyder ef71a089a6 Internals: Spacing. No functional change 2012-05-05 14:49:43 -04:00
Wilson Snyder 5fc98cce0d Fix parameters not supported in constant functions, bug474. 2012-05-03 21:59:47 -04:00
Wilson Snyder b9101c3d6a Better message for display-like format warnings, bug500. 2012-05-02 21:04:50 -04:00
Wilson Snyder 6aab0f627c Fix input and real loosing real data type, bug501. 2012-05-02 20:53:38 -04:00
Wilson Snyder 6b97673d0a Internals: Fix dtype() dead code drop on assign varrefs 2012-05-02 20:53:19 -04:00
Wilson Snyder 5d8c1ce84e Internals: Avoid broken recusion 2012-05-02 20:52:10 -04:00
Wilson Snyder 33c9591a4b Internals: Move widthPow2. No functional change. 2012-04-29 11:34:25 -04:00
Wilson Snyder 87e8736823 IMPORTANT: Major internal changes for supporting complex data types.
Adds dtype() to every node, keep global table of dtypes and remove duplicates.
Final merge from dtype branch.
2012-04-29 10:14:13 -04:00
Wilson Snyder c0da16bfcd Internals: Create dtypeFrom. Merge from dtype. No functional change. 2012-04-29 09:42:17 -04:00
Wilson Snyder a4ddc5b3ac Internals: Create user1SetOnce(). No functional change. 2012-04-29 08:55:33 -04:00
Wilson Snyder 91e4010039 Internals: Rename AstRefDType subDTypep. Merge from dtype. No functional change. 2012-04-29 08:38:53 -04:00
Wilson Snyder 486b6580d8 Internals: Rename VSignedState. Merge from dtype. No functional change. 2012-04-29 08:30:02 -04:00
Wilson Snyder 9c4ef27d49 Internals: Cleanup dead function names. Merge from dtype. No functional change. 2012-04-29 08:24:32 -04:00
Wilson Snyder 33577eaa68 Tests: Less sensitivity to XML change 2012-04-29 08:23:24 -04:00
Wilson Snyder d5e19661bd Debug: Tree compare between versions; merge from dtype branch. No functional change. 2012-04-28 13:00:44 -04:00
Wilson Snyder 799afac05b Internals: V3Hashed cleanups; merge from dtype branch. No functional change. 2012-04-28 12:33:51 -04:00
Wilson Snyder 3ba36dc30c Debugging: Show tree file writes, commentary 2012-04-28 12:22:38 -04:00
Wilson Snyder 641024c235 Fix generated inouts with duplicated modules, bug498. 2012-04-27 19:41:13 -04:00
Wilson Snyder d9598db117 Internals: In debug dumps, show user pointers 2012-04-27 19:01:08 -04:00
Wilson Snyder 2e4da07a15 Fix ITOD internal error on real conversions, bug491. 2012-04-26 22:30:22 -04:00
Wilson Snyder 40f4411b69 Fix tristate connection to unconnected input, bug494, bug495. 2012-04-26 21:11:48 -04:00
Wilson Snyder c75de0f37c Add INITIALDLY warning on initial assignments, bug478. 2012-04-26 20:40:13 -04:00
Wilson Snyder 74c4c1bf44 Internals: Pass unconnected pins through structures. No functional change intended. 2012-04-26 19:01:11 -04:00
Wilson Snyder 60a637921c Add PINMISSING and PINNOCONNECT lint checks. 2012-04-26 18:46:44 -04:00
Wilson Snyder 22312b3c9c Internals: Remove dead code. No functional change intended. 2012-04-26 18:42:02 -04:00
Wilson Snyder 2e26e44538 Commentary, bug497. Merge from Bennett. 2012-04-26 07:10:49 -04:00
Wilson Snyder 24e79ecc68 Fix coredump on constant connect 2012-04-25 22:51:31 -04:00
Wilson Snyder 5b532a1812 Fix generate if, broke in earlier committ, bug492. Merge from Bennett. 2012-04-25 18:17:10 -04:00
Wilson Snyder f3867d7f80 Fix imports causing symbol table error, bug490. 2012-04-24 21:21:26 -04:00
Wilson Snyder fb90e47e70 Tests: Add t_udp_noname, bug468 2012-04-24 20:43:15 -04:00
Wilson Snyder 68046244dd Fix 'output tri0' 2001 declaration; Var characteristics must be attributes 2012-04-24 07:45:02 -04:00
Wilson Snyder b1507060ad Fix output with tri1, but489 2012-04-24 07:12:51 -04:00
Wilson Snyder ffbd595d88 Support nmos and pmos, bug488. 2012-04-23 20:13:07 -04:00
Wilson Snyder ed5bc1e69c Internals: Rename arrayp to rangep(). No functional change intended. 2012-04-22 19:18:51 -04:00
Wilson Snyder 9734931f67 IMPORTANT: Rewrite tristate handling, tri0, tri1, etc. 2012-04-21 21:45:28 -04:00
Wilson Snyder 0048b04540 Merge from Tristate branch, part 1 of 2. No functional change intended 2012-04-21 19:30:08 -04:00
Wilson Snyder c361932fe2 Commentary: Test documentation, bug486. Merge from Bennett. 2012-04-21 12:58:46 -04:00
Wilson Snyder 2d8feabe54 Fix generate operators not short circuiting, bug413. Merge from Jeremy Bennett. 2012-04-19 22:53:52 -04:00
Wilson Snyder 1b511dd130 Internals: Add opLogIf(f). No functional change. Merge from Jeremy Bennet. 2012-04-19 21:02:08 -04:00
Wilson Snyder 52024f4d80 Makefile: Correct tag file selection. Merge from Jeremy Bennet. 2012-04-19 21:00:58 -04:00
Wilson Snyder 735fa6287f Fix linking suppressing duplicate var and block name errors 2012-04-19 20:51:21 -04:00
Wilson Snyder 7eb407fe2b driver.pl: Add --no-verilation option 2012-04-16 20:28:24 -04:00
Wilson Snyder 897d5c58b3 Devel version 2012-04-16 20:20:58 -04:00
Wilson Snyder dc9086512b Doxygen logo and commentary 2012-04-16 07:31:27 -04:00
320 changed files with 10257 additions and 3762 deletions
+45
View File
@@ -3,6 +3,51 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.840 2012/07/31 Beta
** Rewrote tristate handling; supports tri0, tri1, tristate bit selects,
concatenates and pullup/pulldowns, bug395, bug56, bug54, bug51.
[Alex Solomatnikov, Lane Brooks, et al]
** Support packed structures and unions, bug181.
Note this was a major internal change that may lead to some instability.
*** Support tri0 and tri1, bug462. [Alex Solomatnikov]
*** Support nmos and pmos, bug488. [Alex Solomatnikov]
*** Add INITIALDLY warning on initial assignments, bug478. [Alex Solomatnikov]
*** Add PINMISSING and PINNOCONNECT lint checks.
*** Add --converge-limit option.
*** Fix generate operators not short circuiting, bug413. [by Jeremy Bennett]
*** Fix parameters not supported in constant functions, bug474. [Alex Solomatnikov]
**** Fix duplicate warnings/errors, bug516. [Alex Solomatnikov]
**** Fix signed extending biops with WIDTH warning off, bug511. [Junji Hashimoto]
**** Fix ITOD internal error on real conversions, bug491. [Alex Solomatnikov]
**** Fix input and real loosing real data type, bug501. [Alex Solomatnikov]
**** Fix imports causing symbol table error, bug490. [Alex Solomatnikov]
**** Fix newlines in radix values, bug507. [Walter Lavino]
**** Fix loop error message to report line, bug513. [Jeremy Bennett]
**** Fix false UNUSED warning on file system calls.
**** Fix GCC 4.7.0 compile warnings, bug530. [Jeremy Bennett]
**** Fix svdpi.h compile error on Apple OS.
**** Fix compile error under git submodules, bug534. [Aurelien Francillon]
* Verilator 3.833 2012/04/15
+2 -2
View File
@@ -457,8 +457,8 @@ distclean maintainer-clean::
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
rm -f include/verilated.mk
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/[a-z]*.in \
${srcdir}/[a-z]*.in ${srcdir}/*.pod
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
${srcdir}/*.in ${srcdir}/*.pod
TAGS: $(TAGFILES)
etags $(TAGFILES)
+108 -44
View File
@@ -174,10 +174,10 @@ sub run {
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n";
}
if ($status & 255) {
if (($status & 255) == 8 || ($status & 255) == 11) { # SIGFPA or SIGSEGV
if ($status & 127) {
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 255) == 6) { # SIGABRT
} elsif (($status & 127) == 6) { # SIGABRT
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
} else {
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
@@ -250,6 +250,7 @@ descriptions in the next sections for more information.
--cc Create C++ output
--cdc Clock domain crossing analysis
--compiler <compiler-name> Tune for specified C++ compiler
--converge-limit <loops> Tune convergence settle time
--coverage Enable all coverage
--coverage-line Enable line coverage
--coverage-toggle Enable toggle coverage
@@ -427,6 +428,11 @@ functions to avoid error C1061.
=back
=item --converge-limit <loops>
Rarely needed. Specifies the maximum number of runtime iterations before
creating a model failed to converge error. Defaults to 100.
=item --coverage
Enables all forms of coverage, alias for "--coverage-line --coverage-toggle
@@ -521,7 +527,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally
or on the specified source file to the specified level.
to the specified debug level (1-10) or set the specified source file to the
specified level. Higher levels produce more detailed messages (plain
C<--debug> is equivalent to C<--debugi 4>).
=item +define+I<var>+I<value>
@@ -531,9 +539,10 @@ standard across Verilog tools while -D is an alias for GCC compatibility.
=item --dump-tree
Rarely needed. Enable writing .tree debug files with dumping level 3,
which dumps the standard critical stages. --dump-tree is enabled
automatically with --debug, so "--debug --no-dump-tree" may be useful if
the dump files are large and not desired.
which dumps the standard critical stages. For details on the format see
the Verilator Internals manual. --dump-tree is enabled automatically with
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
large and not desired.
=item --dump-treei
@@ -928,8 +937,8 @@ Disable the specified warning message.
Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
-Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN
-Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus
the list shown for Wno-style.
-Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
-Wno-WIDTH" plus the list shown for Wno-style.
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
@@ -939,8 +948,8 @@ received from third parties.
Disable all code style related warning messages (note by default they are
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
-Wno-VARHIDDEN".
-Wno-INCABSPATH -Wno-PINNOCONNECT -Wno-SYNCASYNCNET -Wno-UNDRIVEN
-Wno-UNUSED -Wno-VARHIDDEN".
=item -Wno-fatal
@@ -960,13 +969,14 @@ Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
-Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
-Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style
Enable all code style related warning messages. This is equivalent to
"-Wwarn ASSIGNDLY -Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH
-Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
-Wwarn-PINNOCONNECT -Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED
-Wwarn-VARHIDDEN".
=item -x-assign 0
@@ -1126,6 +1136,9 @@ And link with SystemC. Note your path to the libraries may vary,
depending on the operating system.
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
# Might be needed if SystemC 2.3.0
export SYSTEMC_CXX_FLAGS=-pthread
g++ -L$SYSTEMC_LIBDIR ../sc_main.o Vour__ALL*.o verilated.o \
-o Vour -lsystemc
@@ -1279,7 +1292,7 @@ was compiled).
=item SYSTEMC_CXX_FLAGS
Specifies additional flags that are required to be passed to GCC when
building the SystemC model.
building the SystemC model. System 2.3.0 may need this set to "-pthread".
=item SYSTEMC_INCLUDE
@@ -1734,8 +1747,8 @@ Verilator supports ==? and !=? operators, ++ and -- in some contexts,
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
const, do-while, enum, export, final, import, int, logic, longint, package,
program, shortint, time, typedef, var, void, priority case/if, and unique
case/if.
program, shortint, struct, time, typedef, union, var, void, priority
case/if, and unique case/if.
It also supports .name and .* interconnection.
@@ -2205,49 +2218,59 @@ Verilator is optimized for edge sensitive (flop based) designs. It will
attempt to do the correct thing for latches, but most performance
optimizations will be disabled around the latch.
=head2 Structures and Unions
Verilator only presently supports packed structs and packed unions. Rand
and randc tags on members are simply ignored. All structures and unions
are represented as a single vector, which means that generating one member
of a structure from blocking, and another from non-blocking assignments is
unsupported.
=head2 Time
All delays (#) are ignored, as they are in synthesis.
=head2 Two State
=head2 Unknown states
Verilator is a two state simulator, not a four state simulator. However, it
has two features which uncover most initialization bugs (including many that
a four state simulator will miss.)
First, assigning a variable to a X will actually assign the variable to a
random value (see the -x-assign switch.) Thus if the value is actually
used, the random value should cause downstream errors. Integers also
randomize, even though the Verilog 2001 specification says they initialize
to zero.
Verilator is mostly a two state simulator, not a four state simulator.
However, it has two features which uncover most initialization bugs
(including many that a four state simulator will miss.)
Identity comparisons (=== or !==) are converted to standard ==/!== when
neither side is a constant. This may make the expression result differ
from a four state simulator.
from a four state simulator. An === comparison to X will always be false,
so that Verilog code which checks for uninitialized logic will not fire.
All variables are initialized using a function. By running several
random simulation runs you can determine that reset is working correctly.
On the first run, the function initializes variables to zero. On the
second, have it initialize variables to one. On the third and following
runs have it initialize them randomly. If the results match, reset works.
(Note this is what the hardware will really do.) In practice, just setting
all variables to one at startup finds most problems.
Assigning a variable to a X will actually assign the variable to a random
value (see the -x-assign switch.) Thus if the value is actually used, the
random value should cause downstream errors. Integers also randomize, even
though the Verilog 2001 specification says they initialize to zero.
All variables are randomly initialized using a function. By running
several random simulation runs you can determine that reset is working
correctly. On the first run, the function initializes variables to zero.
On the second, have it initialize variables to one. On the third and
following runs have it initialize them randomly. If the results match,
reset works. (Note this is what the hardware will really do.) In
practice, just setting all variables to one at startup finds most problems.
=head2 Tri/Inout
Verilator converts some simple tristate structures into two state. An assignment
of the form:
Verilator converts some simple tristate structures into two state. Pullup,
pulldown, bufif0, bufif1, notif0, notif1, pmos, nmos, tri0 and tri1 are
also supported. Simple comparisons with === 1'bz are also supported.
An assignment of the form:
inout driver;
wire driver = (enable) ? output_value : 1'bz;
Will be converted to
input driver__in; // Value being driven in from "external" drivers
output driver__en; // True if driven from this module
output driver__enout; // Value being driven from this module
input driver; // Value being driven in from "external" drivers
output driver__en; // True if driven from this module
output driver__out; // Value being driven from this module
Pullup, pulldown, bufif0, bufif1, notif0, notif1 are also supported.
External logic will be needed to combine these signals with any external
drivers.
@@ -2712,6 +2735,15 @@ command line to specify the top include source directory.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item INITIALDLY
Warns that you have a delayed assignment inside of an initial or final
block. If this message is suppressed, Verilator will convert this to a
non-delayed assignment. See also the COMBDLY warning.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item LITENDIAN
Warns that a vector is declared with little endian bit numbering
@@ -2749,6 +2781,23 @@ not really needed. The best solution is to insure that each module is in a
unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y.
=item PINMISSING
Warns that a module has a pin which is not mentioned in a cell
instantiation. If a pin is not missing it should still be specified on the
cell declaration with a empty connection,using "(.pin_name())".
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item PINNOCONNECT
Warns that a cell instantiation has a pin which is not connected to another
signal.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item REALCVT
Warns that a real number is being implicitly rounded to an integer, with
@@ -3395,12 +3444,27 @@ follows:
cp -p t/t_EXAMPLE.pl t/t_BUG.pl
cp -p t/t_EXAMPLE.v t/t_BUG.v
There are many hits on how to write a good test in the driver.pl
documentation which can be seen by running:
cd $VERILATOR_ROOT # Need the original distribution kit
test_regress/driver.pl --help
Edit t/t_BUG.pl to suit your example; you can do anything you want in the
Verilog code there; just make sure it retains the single clk input and no
outputs. Now, the following should fail:
cd $VERILATOR_ROOT # Need the original distribution kit
cd test_regress
t/t_BUG.pl
t/t_BUG.pl # Run on Verilator
t/t_BUG.pl --debug # Run on Verilator, passing --debug to Verilator
t/t_BUG.pl --vcs # Run on a commercial simulator
t/t_BUG.pl --nc|--iv|--ghdl # Likewise on other simulators
The test driver accepts a number of options, many of which mirror the main
Verilator option. For example the previous test could have been run with
debugging enabled. The full set of test options can be seen by running
driver.pl --help as shown above.
Finally, report the bug using the bug tracker at
L<http://www.veripool.org/verilator>. The bug will become publicly
@@ -3445,9 +3509,9 @@ Many people have provided ideas and other assistance with Verilator.
The major corporate sponsors of Verilator, by providing significant
contributions of time or funds include include Cavium Networks, Compaq
Corporation, Digital Equipment Corporation, Embecosm Ltd., Intel
Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip Designs
Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
Corporation, Digital Equipment Corporation, Embecosm Ltd., Hicamp Systems,
Intel Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip
Designs Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
The people who have contributed major functionality are Byron Bradley,
Jeremy Bennett, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder.
+62 -4
View File
@@ -14,6 +14,19 @@ use vars qw ($Debug);
#======================================================================
# Old version 1 dump nodes with no dtypep's
our %Ver1_Non_Dtyped = map {$_ => 1} qw(
ACTIVE ALWAYS ALWAYSPOST ALWAYSPUBLIC ATTROF BEGIN BREAK CASE CASEITEM
CCALL CELL CELLINLINE CFILE CFUNC CHANGEDET CLOCKING COMMENT CONTINUE
COVERDECL COVERINC COVERTOGGLE CRETURN CSTMT DEFPARAM DISABLE DISPLAY DOT
DPIEXPORT FCLOSE FFLUSH FINAL FINISH FOPEN GENCASE GENERATE GENFOR GENIF
IF IMPLICIT INITARRAY INITIAL JUMPGO JUMPLABEL MODULE NETLIST
NOTFOUNDMODULE PACKAGE PACKAGEIMPORT PARSEREF PIN PORT PRAGMA PRIMITIVE
PSLASSERT PSLCOVER PSLDEFCLOCK PULL RANGE READMEM REPEAT RETURN SCCTOR
SCDTOR SCHDR SCIMP SCIMPHDR SCINT SCOPE SELBIT SELEXTRACT SELMINUS
SELPLUS SENGATE SENITEM SENTREE SFORMAT SFORMATF STOP SYSIGNORE SYSTEMT
TASK TASKREF TEXT TOPSCOPE TYPEDEFFWD TYPETABLE UCSTMT UDPTABLE
UDPTABLELINE UNTILSTABLE VASSERT WHILE );
#======================================================================
# main
@@ -79,27 +92,72 @@ sub diff_file {
my $a = shift;
my $b = shift;
# Compare the two tree files
my $tmp_a = "/tmp/$$.a";
my $tmp_b = "/tmp/$$.b";
(my $short_a = $a) =~ s/[^a-zA-Z0-9.]+/_/g;
(my $short_b = $b) =~ s/[^a-zA-Z0-9.]+/_/g;
my $tmp_a = "/tmp/${$}_${short_a}.a";
my $tmp_b = "/tmp/${$}_${short_b}.b";
filter ($a, $tmp_a);
filter ($b, $tmp_b);
my $vera = version_from($a);
my $verb = version_from($b);
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|| ($vera >= 0x3900 && $verb < 0x3900));
filter ($a, $tmp_a, $verCvt);
filter ($b, $tmp_b, $verCvt);
system("diff -u $tmp_a $tmp_b");
unlink $tmp_a;
unlink $tmp_b;
}
sub version_from {
my $fn = shift;
# Return dump format
my $f1 = IO::File->new ($fn) or die "%Error: $! $fn,";
while (defined (my $line=$f1->getline())) {
last if $. > 10;
return hex $1 if $line =~ /\(format (0x[0-9.]+)\)/;
}
return 1.0;
}
sub filter {
my $fn1 = shift;
my $fn2 = shift;
my $verCvt = shift;
# Remove hex numbers before diffing
my $f1 = IO::File->new ($fn1) or die "%Error: $! $fn1,";
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
while (defined (my $line=$f1->getline())) {
same_line:
next if $line =~ / This=/;
$line =~ s/0x[a-f0-9]+/0x/g;
$line =~ s/<e[0-9]+\#?>/<e>/g;
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
if ($verCvt) {
next if $line =~ /^ NETLIST/;
$line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format
# # Below Ver1_Non_Dtyped may replace above further
if ($line =~ /: ([A-Z]+) /) {
my $type = $1;
next if $type =~ 'DTYPE';
if ($type eq 'TYPETABLE' || $type eq 'RANGE') {
$line =~ /^(\s+\S+:) /; my $prefix = $1;
while (defined ($line=$f1->getline())) {
next if $line =~ /^\s+[a-z]/; # Table body
next if $line =~ /^${prefix}[0-9]:/;
goto same_line;
}
next;
}
if ($Ver1_Non_Dtyped{$type}) {
$line =~ s! w[0-9]+!!g;
}
}
$line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format
$line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format
$line =~ s! s?w0$! NoW!g; # OLD: no width -> common format
$line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format
}
print $f2 $line;
}
$f1->close;
+2 -1
View File
@@ -4,7 +4,7 @@
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
AC_INIT([Verilator],[3.833 2012-04-15])
AC_INIT([Verilator],[3.840 2012-07-31])
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
@@ -128,6 +128,7 @@ _MY_CXX_CHECK_OPT(-Wno-sign-compare)
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Checks for library functions.
+2
View File
@@ -27,6 +27,8 @@ typedef signed __int32 int32_t;
typedef signed __int8 int8_t;
#elif defined(__MINGW32__)
#include <stdint.h>
#elif defined(__APPLE__)
#include <stdint.h>
#elif defined(__linux)
#include <inttypes.h>
#else
+107 -13
View File
@@ -336,10 +336,10 @@ AST.
=head1 TESTING
To write a test see notes in the forum and in the verilator.txt manual.
To write a test see the BUGS section of the Verilator primary manual, and
the documentation in:
Note you can run the regression tests in parallel; see the
test_regress/driver.pl script -j flag.
test_regress/t/driver.pl --help
=head1 DEBUGGING
@@ -369,10 +369,10 @@ viewers let us know; ZGRViewer isn't great for large graphs.
Tree files are dumps of the AST Tree and are produced between every major
algorithmic stage. An example:
NETLIST 0x90fb00 <e1> {a0} w0
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
NETLIST 0x90fb00 <e1> {a0}
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
=over 4
@@ -384,13 +384,14 @@ the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
"0x91a780" is the address of this node.
"<e74>" means the 74th edit to the netlist was the last modification to
this node. A trailing # indicates this node changed since the last tree
dump was made. You can gdb break on this edit; see below.
this node.
"{a22}" indicates this node is related to line 22 in the source filename
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
"a", where "a" is the first file read, "z" the 26th, and "aa" the 27th.
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
"@dt=0x..." indicates the address of the data type this node contains.
"w32" indicates the width is 32 bits.
"out_wide" is the name of the node, in this case the name of the variable.
@@ -399,6 +400,97 @@ variable is an output.
=back
In more detail the following fields are dumped common to all nodes. They
are produced by the C<AstNode::dump()> method:
=over 4
=item Tree Hierarchy
The dump lines begin with numbers and colons to indicate the child node
hierarchy. As noted above in L</Key Classes Used in the Verilator Flow>,
C<AstNode> has lists of items at the same level in the AST, connected by
the C<nextp()> and C<prevp()> pointers. These appear as nodes at the same
level. For example after inlining:
NETLIST 0x929c1c8 <e1> {a0} w0
1: MODULE 0x92bac80 <e3144> {e14} w0 TOP_t L1 [P]
1:1: CELLINLINE 0x92bab18 <e3686#> {e14} w0 v -> t
1:1: CELLINLINE 0x92bc1d8 <e3688#> {e24} w0 v__DOT__i_test_gen -> test_gen
...
1: MODULE 0x92b9bb0 <e503> {e47} w0 test_gen L3
...
=item AstNode type
The textual name of this node AST type (always in capitals). Many of these
correspond directly to Verilog entities (for example C<MODULE> and
C<TASK>), but others are internal to Verialtor (for example C<NETLIST> and
C<BASICDTYPE>).
=item Address of the node
A hexadecimal address of the node in memory. Useful for examining with the
debugger.
=item Last edit number
Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
of the last edit to modify this node. The trailing C<#> indicates the node
has been edited since the last tree dump (which typically means in the last
refinement or optimization pass). GDB can watch for this, see L</Debugging
with GDB> below.
=item Source file and line
Of the form C<< {xxnnnn} >>, where C{xx} is the filename letter (or
letters) and C<nnnn> is the line number within that file. The first file is
C<a>, the 26th is C<z>, the 27th is C<aa> and so on.
=item User pointers
Shows the value of the node's user1p...user5p, if non-NULL.
=item Data type
Many nodes have an explicit data type. "@dt=0x..." indicates the address
of the data type (AstNodeDType) this node uses.
If a data type is present and is numberic, it then prints the width of the
item. This field is a squence of flag characters and width data as follows:
C<s> if the node is signed.
C<d> if the node is a double (i.e a floating point entity).
C<w> always present, indicating this is the width field.
C<u> if the node is unsized.
C</nnnn> if the node is unsized, where C<nnnn> is the minimum width.
=item Name of the entity represented by the node if it exists
For example for a C<VAR> it is the name of the variable.
=back
Many nodes follow these fields with additional node specific
information. Thus the C<VARREF> node will print either C<[LV]> or C<[RV]>
to indicate a left value or right value, followed by the node of the
variable being referred to. For example:
1:2:1:1: VARREF 0x92c2598 <e509> {e24} w0 clk [RV] <- VAR 0x92a2e90 <e79> {e18} w0 clk [I] INPUT
In general, examine the C<dump()> method in C<V3AstNodes.cpp> of the node
type in question to determine additional fields that may be printed.
The C<MODULE> has a list of C<CELLINLINE> nodes referred to by its
C<op1p()> pointer, connected by C<nextp()> and C<prevp()> pointers.
Similarly the C<NETLIST> has a list of modules referred to by its C<op1p()>
pointer.
=head2 Debugging with GDB
The test_regress/driver.pl script accepts --debug --gdb to start Verilator
@@ -439,8 +531,10 @@ what made a <e####> line in the tree dumps):
To print a node:
call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
pn nodep
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
pnt nodep
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
When GDB halts, it is useful to understand that the backtrace will commonly
show the iterator functions between each invocation of C<visit> in the
+14
View File
@@ -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
View File
@@ -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
View File
@@ -198,7 +198,6 @@ RAW_OBJS = \
V3Inst.o \
V3Life.o \
V3LifePost.o \
V3Link.o \
V3LinkCells.o \
V3LinkDot.o \
V3LinkJump.o \
+17 -11
View File
@@ -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*) {
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-2
View File
@@ -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
-2
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -48,6 +46,28 @@ int AstNodeSel::bitConst() const {
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
}
void AstNodeClassDType::repairMemberCache() {
clearCache();
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
else m_members.insert(make_pair(itemp->name(), itemp));
}
}
bool AstNodeClassDType::broken() const {
set<AstMemberDType*> exists;
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
exists.insert(itemp);
}
for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) {
if (exists.find(it->second) == exists.end()) {
this->v3error("Internal: Structure member broken: "<<it->first);
return true;
}
}
return false;
}
int AstBasicDType::widthAlignBytes() const {
if (width()<=8) return 1;
else if (width()<=16) return 2;
@@ -62,6 +82,22 @@ int AstBasicDType::widthTotalBytes() const {
else return widthWords()*(VL_WORDSIZE/8);
}
int AstNodeClassDType::widthTotalBytes() const {
if (width()<=8) return 1;
else if (width()<=16) return 2;
else if (isQuad()) return 8;
else return widthWords()*(VL_WORDSIZE/8);
}
int AstNodeClassDType::widthAlignBytes() const {
// Could do max across members but that would be slow,
// instead intuit based on total structure size
if (width()<=8) return 1;
else if (width()<=16) return 2;
else if (width()<=32) return 4;
else return 8;
}
bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
}
@@ -75,16 +111,26 @@ bool AstVar::isScBv() const {
}
void AstVar::combineType(AstVarType type) {
// These flags get combined with the existing settings of the flags.
// We don't test varType for certain types, instead set flags since
// when we combine wires cross-hierarchy we need a union of all characteristics.
if (type == AstVarType::SUPPLY0) type = AstVarType::WIRE;
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
m_varType=type; // For debugging prints only
// These flags get combined with the existing settings of the flags.
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
m_input = true;
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT)
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
m_output = true;
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE)
m_declOutput = true;
}
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE
|| type==AstVarType::TRI0 || type==AstVarType::TRI1)
m_tristate = true;
if (type==AstVarType::TRI0)
m_isPulldown = true;
if (type==AstVarType::TRI1)
m_isPullup = true;
}
string AstVar::verilogKwd() const {
@@ -277,6 +323,14 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
}
return NULL;
}
else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
if (adtypep->packed()) {
if ((dim++) == dimension) {
return adtypep;
}
}
return NULL;
}
// Node no ->next in loop; use continue where necessary
break;
}
@@ -318,6 +372,15 @@ pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
return make_pair(packed, unpacked);
}
int AstNodeDType::widthPow2() const {
// I.e. width 30 returns 32, width 32 returns 32.
uint32_t width = this->width();
for (int p2=30; p2>=0; p2--) {
if (width > (1UL<<p2)) return (1UL<<(p2+1));
}
return 1;
}
// Special operators
int AstArraySel::dimension(AstNode* nodep) {
// How many dimensions is this reference from the base variable?
@@ -337,7 +400,7 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable
while (nodep) {
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
// AstNodeSelPre stashes the associated variable under a ATTROF so it isn't constified
// AstNodeSelPre stashes the associated variable under a ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
else if (nodep->castNodePreSel()) {
if (nodep->castNodePreSel()->attrp()) {
@@ -432,6 +495,87 @@ bool AstSenTree::hasCombo() {
return false;
}
void AstTypeTable::clearCache() {
// When we mass-change widthMin in V3WidthCommit, we need to correct the table.
// Just clear out the maps; the search functions will be used to rebuild the map
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
m_basicps[i] = NULL;
}
for (int isbit=0; isbit<_IDX0_MAX; ++isbit) {
for (int numer=0; numer<AstNumeric::_ENUM_MAX; ++numer) {
LogicMap& mapr = m_logicMap[isbit][numer];
mapr.clear();
}
}
m_detailedMap.clear();
// Clear generic()'s so dead detection will work
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
bdtypep->generic(false);
}
}
}
void AstTypeTable::repairCache() {
// After we mass-change widthMin in V3WidthCommit, we need to correct the table.
clearCache();
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
(void)findInsertSameDType(bdtypep);
}
}
}
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd) {
if (m_basicps[kwd]) return m_basicps[kwd];
//
AstBasicDType* new1p = new AstBasicDType(fl, kwd);
// Because the detailed map doesn't update this map,
// check the detailed map for this same node
// Also adds this new node to the detailed map
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
else addTypesp(newp);
//
m_basicps[kwd] = newp;
return newp;
}
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
int width, int widthMin, AstNumeric numeric) {
int idx = IDX0_LOGIC;
if (kwd == AstBasicDTypeKwd::LOGIC) idx = IDX0_LOGIC;
else if (kwd == AstBasicDTypeKwd::BIT) idx = IDX0_BIT;
else fl->v3fatalSrc("Bad kwd for findLogicBitDType");
pair<int,int> widths = make_pair(width,widthMin);
LogicMap& mapr = m_logicMap[idx][(int)numeric];
LogicMap::const_iterator it = mapr.find(widths);
if (it != mapr.end()) return it->second;
//
AstBasicDType* new1p = new AstBasicDType(fl, AstBasicDTypeKwd::BIT, numeric, width, widthMin);
// Because the detailed map doesn't update this map,
// check the detailed map for this same node, and if found update this map
// Also adds this new node to the detailed map
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
else addTypesp(newp);
//
mapr.insert(make_pair(widths,newp));
return newp;
}
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
nodep->keyword(), nodep->nrange());
DetailedMap& mapr = m_detailedMap;
DetailedMap::const_iterator it = mapr.find(key);
if (it != mapr.end()) return it->second;
mapr.insert(make_pair(key,nodep));
nodep->generic(true);
// No addTypesp; the upper function that called new() is responsible for adding
return nodep;
}
//======================================================================
// Special walking tree inserters
@@ -502,11 +646,21 @@ void AstNode::dump(ostream& str) {
//<<" "<<(void*)this->m_backp
<<" <e"<<dec<<editCount()
<<((editCount()>=editCountLast())?"#>":">")
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) str<<"/"<<widthMin();
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}";
if (user1p()) str<<" u1="<<(void*)user1p();
if (user2p()) str<<" u2="<<(void*)user2p();
if (user3p()) str<<" u3="<<(void*)user3p();
if (user4p()) str<<" u4="<<(void*)user4p();
if (user5p()) str<<" u5="<<(void*)user5p();
if (hasDType()) {
if (dtypep()==this) str<<" @dt="<<"this@";
else str<<" @dt="<<(void*)dtypep()<<"@"; // Final @ so less likely to by accident think it's nodep
if (AstNodeDType* dtp = dtypep()) {
dtp->dumpSmall(str);
}
} else { // V3Broken will throw an error
if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep();
}
if (name()!="") str<<" "<<AstNode::quoteName(name());
}
@@ -526,7 +680,6 @@ void AstBasicDType::dump(ostream& str) {
this->AstNodeDType::dump(str);
str<<" kwd="<<keyword().ascii();
if (isRanged() && !rangep()) str<<" range=["<<left()<<":"<<right()<<"]";
if (implicit()) str<<" [IMPLICIT]";
}
void AstCCast::dump(ostream& str) {
this->AstNode::dump(str);
@@ -572,8 +725,87 @@ void AstRefDType::dump(ostream& str) {
if (defp()) { str<<" -> "; defp()->dump(str); }
else { str<<" -> UNLINKED"; }
}
void AstNodeClassDType::dump(ostream& str) {
this->AstNode::dump(str);
if (packed()) str<<" [PACKED]";
}
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
if (generic()) str<<" [GENERIC]";
if (AstNodeDType* dtp = virtRefDTypep()) {
str<<" refdt="<<(void*)(dtp);
dtp->dumpSmall(str);
}
}
void AstNodeDType::dumpSmall(ostream& str) {
str<<"("
<<(generic()?"G/":"")
<<((isSigned()&&!isDouble())?"s":"")
<<(isNosign()?"n":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) str<<"/"<<widthMin();
str<<")";
}
void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str);
str<<" L"<<level();
if (modPublic()) str<<" [P]";
if (inLibrary()) str<<" [LIB]";
if (dead()) str<<" [DEAD]";
}
void AstPackageImport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
}
void AstTypeTable::dump(ostream& str) {
this->AstNode::dump(str);
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
if (AstBasicDType* subnodep=m_basicps[i]) {
str<<endl; // Newline from caller, so newline first
str<<"\t\t"<<setw(8)<<AstBasicDTypeKwd(i).ascii();
str<<" -> ";
subnodep->dump(str);
}
}
for (int isbit=0; isbit<2; ++isbit) {
for (int issigned=0; issigned<AstNumeric::_ENUM_MAX; ++issigned) {
LogicMap& mapr = m_logicMap[isbit][issigned];
for (LogicMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
AstBasicDType* dtypep = it->second;
str<<endl; // Newline from caller, so newline first
stringstream nsstr;
nsstr<<(isbit?"bw":"lw")
<<it->first.first<<"/"<<it->first.second;
str<<"\t\t"<<setw(8)<<nsstr.str();
if (issigned) str<<" s"; else str<<" u";
str<<" -> ";
dtypep->dump(str);
}
}
}
{
DetailedMap& mapr = m_detailedMap;
for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
AstBasicDType* dtypep = it->second;
str<<endl; // Newline from caller, so newline first
stringstream nsstr;
str<<"\t\tdetailed -> ";
dtypep->dump(str);
}
}
// Note get newline from caller too.
}
void AstVarScope::dump(ostream& str) {
this->AstNode::dump(str);
if (isCircular()) str<<" [CIRC]";
if (varp()) { str<<" -> "; varp()->dump(str); }
else { str<<" ->UNLINKED"; }
}
void AstVarXRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
str<<dotted()<<". - ";
@@ -582,27 +814,9 @@ void AstVarXRef::dump(ostream& str) {
else if (varp()) { varp()->dump(str); }
else { str<<"UNLINKED"; }
}
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
}
void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str);
str<<" L"<<level();
if (modPublic()) str<<" [P]";
if (inLibrary()) str<<" [LIB]";
}
void AstPackageImport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
}
void AstVarScope::dump(ostream& str) {
this->AstNode::dump(str);
if (isCircular()) str<<" [CIRC]";
if (varp()) { str<<" -> "; varp()->dump(str); }
else { str<<" ->UNLINKED"; }
}
void AstVarRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
if (varScopep()) { varScopep()->dump(str); }
@@ -619,6 +833,8 @@ void AstVar::dump(ostream& str) {
else if (isOutput()) str<<" [O]";
}
if (isConst()) str<<" [CONST]";
if (isPullup()) str<<" [PULLUP]";
if (isPulldown()) str<<" [PULLDOWN]";
if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]";
@@ -640,6 +856,11 @@ void AstSenItem::dump(ostream& str) {
void AstParseRef::dump(ostream& str) {
this->AstNode::dump(str);
str<<" ["<<expect().ascii()<<"]";
if (start()) str<<" [START]";
}
void AstDot::dump(ostream& str) {
this->AstNode::dump(str);
if (start()) str<<" [START]";
}
void AstActive::dump(ostream& str) {
this->AstNode::dump(str);
@@ -649,6 +870,7 @@ void AstActive::dump(ostream& str) {
}
void AstNodeFTaskRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
str<<" -> ";
if (dotted()!="") { str<<dotted()<<". - "; }
if (taskp()) { taskp()->dump(str); }
@@ -665,7 +887,8 @@ void AstNodeFTask::dump(ostream& str) {
void AstBegin::dump(ostream& str) {
this->AstNode::dump(str);
if (unnamed()) str<<" [UNNAMED]";
if (hidden()) str<<" [HIDDEN]";
if (generate()) str<<" [GEN]";
if (genforp()) str<<" [GENFOR]";
}
void AstCoverDecl::dump(ostream& str) {
this->AstNode::dump(str);
+467 -218
View File
File diff suppressed because it is too large Load Diff
+1 -10
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -144,24 +142,17 @@ private:
// Remap var names and replace lower Begins
nodep->stmtsp()->iterateAndNext(*this);
if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier");
}
m_namedScope = oldScope;
m_unnamedScope = oldUnnamed;
// Don't change var names of generate FOR() variables, but do recurse into a child FOR
nodep->flatsp()->iterateAndNext(*this);
// Cleanup
AstNode* addsp = NULL;
if (AstNode* stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = addsp->addNextNull(stmtsp);
}
if (AstNode* stmtsp = nodep->flatsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = addsp->addNextNull(stmtsp);
}
if (addsp) {
nodep->replaceWith(addsp);
} else {
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
-2
View File
@@ -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
View File
@@ -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;
-2
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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;
}
}
-2
View File
@@ -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
View File
@@ -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);
}
}
-2
View File
@@ -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
View File
@@ -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) {
-2
View File
@@ -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
View File
@@ -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();
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+11 -10
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -487,7 +485,7 @@ public:
visit(nodep->castNodeUniop(), vup);
} else {
putbs("VL_REDXOR_");
puts(cvtToStr(nodep->lhsp()->widthPow2()));
puts(cvtToStr(nodep->lhsp()->dtypep()->widthPow2()));
puts("(");
nodep->lhsp()->iterateAndNext(*this);
puts(")");
@@ -624,6 +622,7 @@ public:
virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTypedef*, AstNUser*) {} // Nothing needed presently
// Default
virtual void visit(AstNode* nodep, AstNUser*) {
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
@@ -1192,11 +1191,11 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
AstNode* argp = *elistp;
if (!argp) {
// expectDisplay() checks this first, so internal error if found here
dispp->v3error("Internal: Missing arguments for $display format");
dispp->v3error("Internal: Missing arguments for $display-like format");
return;
}
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any display arguments");
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any $display-like arguments");
}
if (argp && argp->isWide()
&& (fmtLetter=='d'||fmtLetter=='u')) {
@@ -1287,17 +1286,17 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
case 'z':
case 'l':
case 'v':
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
nodep->v3error("Unsupported: $display-like format code: %"<<pos[0]);
break;
default:
nodep->v3error("Unknown $display format code: %"<<pos[0]);
nodep->v3error("Unknown $display-like format code: %"<<pos[0]);
break;
}
}
}
if (elistp != NULL) {
// expectFormat also checks this, and should have found it first, so internal
elistp->v3error("Internal: Extra arguments for $display format");
elistp->v3error("Internal: Extra arguments for $display-like format");
}
displayEmit(nodep, isScan);
}
@@ -1558,7 +1557,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts( "_eval(vlSymsp);\n");
#ifndef NEW_ORDERING
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts("}\n");
#endif
puts("}\n");
@@ -1577,7 +1577,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts( "_eval(vlSymsp);\n");
#ifndef NEW_ORDERING
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "}\n");
#endif
puts("}\n");
-2
View File
@@ -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
View File
@@ -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
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+2 -4
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -462,8 +460,8 @@ void EmitCSyms::emitSymImp() {
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
bounds += " ,"; bounds += cvtToStr(adtypep->arrayp()->msbConst());
bounds += ","; bounds += cvtToStr(adtypep->arrayp()->lsbConst());
bounds += " ,"; bounds += cvtToStr(adtypep->msb());
bounds += ","; bounds += cvtToStr(adtypep->lsb());
dim++;
dtypep = adtypep->subDTypep();
}
-2
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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()); }
-2
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-2
View File
@@ -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
View File
@@ -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);
-2
View File
@@ -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
View File
@@ -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);
}
}
}
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -63,9 +61,10 @@ public:
m_needHInlines = false;
m_needHeavy = false;
m_dpi = false;
m_rootp = makeNetlist();
m_rootp = NULL; // created by makeInitNetlist() so static constructors run first
}
AstNetlist* makeNetlist();
void boot() { UASSERT(!m_rootp,"call once"); m_rootp = makeNetlist(); }
void clear();
// ACCESSORS (general)
AstNetlist* rootp() const { return m_rootp; }
@@ -75,6 +74,7 @@ public:
// METHODS
void readFiles();
void checkTree();
static void dumpGlobalTree(const string& filename, int newNumber=0);
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
string debugFilename(const string& nameComment, int newNumber=0) {
+1 -3
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -346,5 +344,5 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
*logp << "}\n";
logp->close();
cout << "dot -Tps -o ~/a.ps "<<filename<<endl;
cout << "dot -Tpdf -o ~/a.pdf "<<filename<<endl;
}
-2
View File
@@ -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
View File
@@ -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");
}
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -74,7 +72,8 @@ private:
if (m_lowerHash.isIllegal()) {
nodep->v3fatalSrc("sameHash function undefined (returns 0) for node under CFunc.");
}
m_lowerHash = V3Hash(m_lowerHash, V3Hash(nodep->type()<<6 | nodep->width()));
// For identical nodes, the type should be the same thus dtypep should be the same too
m_lowerHash = V3Hash(m_lowerHash, V3Hash(nodep->type()<<6, V3Hash(nodep->dtypep())));
// Now update m_lowerHash for our children's (and next children) contributions
nodep->iterateChildren(*this);
// Store the hash value
@@ -189,3 +188,4 @@ V3Hashed::iterator V3Hashed::findDuplicate(AstNode* nodep) {
}
return end();
}
+17 -8
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
@@ -31,7 +29,23 @@
//============================================================================
class V3Hashed {
class VHashedBase {
public:
// CONSTRUCTORS
VHashedBase() {}
~VHashedBase() {}
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
};
//============================================================================
class V3Hashed : public VHashedBase {
// NODE STATE
// AstNode::user4() -> V3Hash. Hash value of this node (hash of 0 is illegal)
AstUser4InUse m_inuser4;
@@ -55,11 +69,6 @@ public:
iterator end() { return m_hashMmap.end(); }
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void clear() { m_hashMmap.clear(); AstNode::user4ClearTree(); }
void hashAndInsert(AstNode* nodep); // Hash the node, and insert into map
bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical
+3 -3
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -114,7 +112,8 @@ private:
// we'll save work, and we can't call pinReconnectSimple in
// this loop as it clone()s itself.
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
V3Inst::pinReconnectSimple(pinp, nodep, m_modp);
if (!pinp->exprp()) continue;
V3Inst::pinReconnectSimple(pinp, nodep, m_modp, false);
}
// Clone original module
@@ -130,6 +129,7 @@ private:
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
// Create assignments to the pins
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (!pinp->exprp()) continue;
UINFO(6," Pin change from "<<pinp->modVarp()<<endl);
// Make new signal; even though we'll optimize the interconnect, we
// need an alias to trace correctly. If tracing is disabled, we'll
-2
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+25 -26
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -46,8 +44,6 @@ class InstVisitor : public AstNVisitor {
private:
// NODE STATE
// Cleared each Cell:
// AstVar::user1p() -> AstNode*. Expression connected to given pin
// AstVarRef::user1p() -> bool. True if created senitem for parent's connected signal
// AstPin::user1p() -> bool. True if created assignment already
AstUser1InUse m_inuser1;
@@ -75,10 +71,6 @@ private:
m_cellp = nodep;
//VV***** We reset user1p() on each cell!!!
AstNode::user1ClearTree();
// Collect pin expressions, so submod->varp->user1p() points to expression it connects to
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
pinp->modVarp()->user1p(pinp->exprp());
}
nodep->iterateChildren(*this);
m_cellp = NULL;
}
@@ -86,22 +78,22 @@ private:
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
UINFO(4," PIN "<<nodep<<endl);
if (!nodep->exprp()) return; // No-connect
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
if (nodep->modVarp()->isOutOnly() && nodep->exprp()->castConst())
nodep->v3error("Output port is connected to a constant pin, electrical short");
// Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1Inc()) {
if (!nodep->user1SetOnce()) {
// Simplify it
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp);
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
// Make a ASSIGNW (expr, pin)
AstNode* exprp = nodep->exprp()->cloneTree(false);
if (nodep->width() != nodep->modVarp()->width())
if (exprp->width() != nodep->modVarp()->width())
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
if (nodep->modVarp()->isInout()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isOutput()) {
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
rhsp->widthSignedFrom(nodep);
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
m_modp->addStmtp(assp);
} else if (nodep->modVarp()->isInput()) {
@@ -194,6 +186,7 @@ private:
}
virtual void visit(AstPin* nodep, AstNUser*) {
// Any non-direct pins need reconnection with a part-select
if (!nodep->exprp()) return; // No-connect
if (m_cellRangep) {
UINFO(4," PIN "<<nodep<<endl);
int pinwidth = nodep->modVarp()->width();
@@ -241,53 +234,59 @@ public:
//######################################################################
// Inst class functions
void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp) {
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
bool forTristate, bool alwaysCvt) {
// If a pin connection is "simple" leave it as-is
// Else create a intermediate wire to perform the interconnect
// Return the new assignment, if one was made
// Note this module calles cloneTree() via new AstVar
AstVar* pinVarp = pinp->modVarp();
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
AstBasicDType* connBasicp = NULL;
AstAssignW* assignp = NULL;
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
//
if (connectRefp
if (!alwaysCvt
&& connectRefp
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
// Done. Same data type
} else if (connBasicp
} else if (!alwaysCvt
&& connBasicp
&& pinBasicp
&& connBasicp->width() == pinBasicp->width()
&& connBasicp->lsb() == pinBasicp->lsb()
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
&& pinp->width() == pinVarp->width()
&& connBasicp->width() == pinVarp->width()
&& 1) {
// Done. One to one interconnect won't need a temporary variable.
} else if (pinp->exprp()->castConst()) {
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
// Done. Constant.
} else {
// Make a new temp wire
//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
AstAssignW* assignp = NULL;
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
string newvarname = ((pinVarp->isOutput() ? "__Vcellout__" : "__Vcellinp__")
+cellp->name()+"__"+pinp->name());
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
modp->addStmtp(newvarp);
// Important to add statement next to cell, in case there is a generate with same named cell
cellp->addNextHere(newvarp);
if (pinVarp->isInout()) {
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
} else if (pinVarp->isOutput()) {
// See also V3Inst
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
if (pinp->width() > rhsp->width()) {
if (pinVarp->width() > rhsp->width()) {
if (rhsp->isSigned()) {
rhsp = new AstExtendS(pinp->fileline(), rhsp);
} else {
rhsp = new AstExtend (pinp->fileline(), rhsp);
}
} else if (pinp->width() < rhsp->width()) {
rhsp = new AstSel (pinp->fileline(), rhsp, 0, pinp->width());
} else if (pinVarp->width() < rhsp->width()) {
rhsp = new AstSel (pinp->fileline(), rhsp, 0, pinVarp->width());
}
rhsp->widthSignedFrom(pinp);
rhsp->dtypeFrom(pinVarp); // Need proper widthMin, which may differ from AstSel created above
assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsp);
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
} else {
@@ -298,11 +297,11 @@ void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* mod
pinexprp);
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
}
pinp->widthSignedFrom(pinp->exprp());
if (assignp) modp->addStmtp(assignp);
if (assignp) cellp->addNextHere(assignp);
//if (1||debug()) { pinp->dumpTree(cout," out:"); }
//if (1||debug()) { assignp->dumpTree(cout," aout:"); }
}
return assignp;
}
//######################################################################
+2 -3
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -33,7 +31,8 @@ class V3Inst {
public:
static void instAll(AstNetlist* nodep);
static void dearrayAll(AstNetlist* nodep);
static void pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp);
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp,
bool forTristate, bool alwaysCvt=false);
};
#endif // Guard
-2
View File
@@ -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
-2
View File
@@ -4,8 +4,6 @@
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can

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