Compare commits

...
166 Commits
Author SHA1 Message Date
Wilson Snyder f4a5aa2e94 Version bump 2017-04-02 08:43:53 -04:00
Wilson Snyder bdd54eed1c Commentary 2017-04-02 08:39:33 -04:00
Wilson Snyder c6a20a72f2 Turn off parser debug in optimized build, msg2203 2017-03-31 17:46:15 -04:00
Wilson Snyder d7a54b3632 Fix nested structure parameter selects, bug1150. 2017-03-30 19:05:55 -04:00
Wilson Snyder be6a3d0f10 Fix wreal not handling continuous assign, bug1150. 2017-03-30 18:32:37 -04:00
Wilson Snyder e9125a3a22 Fix error on parameters with dotted references, bug1146. 2017-03-28 19:55:20 -04:00
Wilson Snyder c27a60658f Add error on duplicate pattern assignments, bug1145. 2017-03-23 18:15:03 -04:00
Wilson Snyder 8f2bc6e028 Patch to fix for bug1135. 2017-03-22 17:34:47 -04:00
Wilson Snyder a6b78cbbee Fix error on improperly widthed default function, bug984. 2017-03-21 19:27:42 -04:00
Wilson Snyder 182a7076fd Fix missing error on interface size mismatch, bug1143. 2017-03-21 19:19:28 -04:00
Wilson Snyder 17a9b22dce Fix cell ranges without colons. 2017-03-21 19:17:15 -04:00
Wilson Snyder f190d12802 Internals: Avoid coredump debugging bug1135. 2017-03-21 18:22:32 -04:00
Wilson Snyder b12dd526f9 Fix calling sformatf to display, and elab , bug1139. 2017-03-17 18:40:16 -04:00
Wilson Snyder 473d555dc1 Fix ugly interface-to-non-interface errors, bug1112. 2017-03-17 18:35:53 -04:00
Wilson Snyder fa9208ccdd Fix ugly interface-to-non-interface errors, bug1112. 2017-03-17 18:33:49 -04:00
Wilson Snyder 4aa088eb2f Fix realpath compile issue on MSVC++, bug1141. 2017-03-15 20:08:19 -04:00
Wilson Snyder 8f8147d646 Fix internal error on interface arrays, bug1135. 2017-03-15 20:03:53 -04:00
Wilson Snyder e637dd2390 Fix internal error on initializing parameter array, bug1131. 2017-03-06 07:20:30 -05:00
Wilson Snyder c90960fc88 Fix LDFLAGS and CFLAGS not preserving order, bug1130. 2017-02-13 18:11:40 -05:00
Wilson Snyder da86a1c9f2 Fix previous commit warning 2017-02-13 18:11:22 -05:00
Wilson Snyder 0adb789238 Add --relative-includes. 2017-02-09 18:33:18 -05:00
Wilson Snyder 15082a178b Add -FI option to force includes,msg2146. 2017-02-09 07:44:36 -05:00
Wilson Snyder 4a0db26c36 Commentary 2017-02-04 13:53:08 -05:00
Wilson Snyder ad3ea636d5 Fix 2009 localparam syntax, msg2139. 2017-01-26 22:41:32 -05:00
Wilson Snyder 6a238b0514 devel release 2017-01-26 22:41:05 -05:00
Wilson Snyder e6d7e7e329 Version bump 2017-01-15 12:13:13 -05:00
Wilson Snyder f942aba855 Support old-style (), bug467. 2017-01-09 19:19:21 -05:00
Wilson Snyder 2f34132275 Fix bad code when tracing array of structs, bug1122. 2017-01-06 18:44:37 -05:00
Wilson Snyder 663b2be065 Tests: bug1104, unsupported. 2016-12-21 21:00:40 -05:00
Wilson Snyder a1e4d676c3 Fix parsing sensitivity with &&, bug934. 2016-12-21 18:23:14 -05:00
Wilson Snyder 6f28d21207 With --bbox-unsup, suppress desassign and mixed edges, bug1120. 2016-12-21 17:43:19 -05:00
Wilson Snyder 9f115e056e Commentary 2016-12-21 17:21:44 -05:00
Wilson Snyder 8352ba4af4 Commentary, bug1116 2016-12-03 15:01:55 -05:00
Wilson Snyder 9b06310cbe Fix internal error on unique casez with --assert, bug1117. 2016-12-03 14:49:51 -05:00
Wilson Snyder 77fe33e57f Fix internal error on double-for loop unrolling, bug1044. 2016-11-29 20:40:58 -05:00
Wilson Snyder df58eb9bc7 Commentary 2016-11-27 16:37:51 -05:00
Wilson Snyder 2d0084308d Internals: Convert AstNUser to non-pointer to avoid NULL call. No functional change intended. 2016-11-27 09:40:12 -05:00
Wilson Snyder 7efa40966a Internals: Remove second argument to visitors. No functional change intended. 2016-11-27 08:11:38 -05:00
Wilson Snyder 6d644dc764 Internals: V3Width now iterates like others, replacing arg passing. No functional change intended. 2016-11-25 16:48:36 -05:00
Wilson Snyder b0de0b1176 devel release 2016-11-25 10:55:28 -05:00
Wilson Snyder c72d473e96 Version bump 2016-11-25 10:35:45 -05:00
Wilson Snyder c8a91bd46f Commentary 2016-11-18 21:42:06 -05:00
Wilson Snyder 498f19a6a1 Use VERILATOR_INCLUDE in generated files to allow relocation. 2016-11-18 21:13:56 -05:00
Wilson Snyder c7a2138ece Commentary 2016-11-18 20:31:41 -05:00
Wilson Snyder 4078902543 Compiling: Fix flexfix adding new warning back in flex 2.5.35 2016-11-18 19:40:39 -05:00
Wilson Snyder 9e38ed9a39 configure: Better prune unknwon gcc -Wno- flags. 2016-11-18 19:27:29 -05:00
Wilson Snyder 183cabc77d Internals: Have cloning return node's type to avoid casts. No functional change. 2016-11-08 21:16:22 -05:00
Wilson Snyder b582e481c6 Commentary in Makefile.in 2016-11-08 18:12:05 -05:00
Wilson Snyder ad39931e87 Internals: Cleanup uses of accept in V3Width. No functional change. 2016-11-07 19:14:45 -05:00
Wilson Snyder 1ae22e1365 Internals: Cleanup some casts. No functional change. 2016-11-06 11:39:09 -05:00
Wilson Snyder b748ddfe06 Fix flex 2.6.2 bug, bug1103. 2016-11-06 08:14:05 -05:00
Wilson Snyder e52f5f1b63 Internals: Remove extraneous castNode() calls. No functional change. 2016-11-05 10:06:43 -04:00
Wilson Snyder bda4b326ab Internals: Use mixed case for AstType enums. No functional change. 2016-11-05 09:47:56 -04:00
Wilson Snyder 70ddf32719 Fix error on referencing variable in parent, bug1099. 2016-11-05 08:37:18 -04:00
Stefan Wallentowitz 3edba7b662 Fix type parameters with low optimization, bug1101.
Signed-off-by: Wilson Snyder <[email protected]>
2016-11-04 22:58:21 -04:00
Wilson Snyder f74ef650ac Honor --output-split on coverage constructors, bug1098. 2016-10-23 14:27:57 -04:00
Wilson Snyder f093c3d78b Fix error on bad interface name, bug1097. 2016-10-22 08:05:27 -04:00
Wilson Snyder d933f33bdb devel release 2016-10-14 19:51:30 -04:00
Wilson Snyder 813d62005d Version bump 2016-10-14 19:42:18 -04:00
Wilson Snyder 411de9bddf Commentary. 2016-09-30 18:16:56 -04:00
Wilson Snyder bd28945374 Untabify 2016-09-30 18:14:42 -04:00
Wilson Snyder 1e4c3751e1 Support foreach, bug1078. 2016-09-19 22:00:13 -04:00
Wilson Snyder 5b6f47cd0f If VM_PARALLEL_BUILDS=1, use OPT_FAST and OPT_SLOW. 2016-09-19 19:31:09 -04:00
Wilson Snyder bec8c5bf4c Commentary 2016-09-19 17:55:43 -04:00
Johan Bjork 15495bb200 Improve Verilation performance on trace duplicates, msg2017.
Signed-off-by: Wilson Snyder <[email protected]>
2016-09-19 17:54:42 -04:00
Wilson Snyder 999f278971 Fix concats with wide width, bug1088 continued. 2016-09-16 18:54:28 -04:00
Wilson Snyder 7ca1d35a4e New test. 2016-09-16 18:15:32 -04:00
Wilson Snyder 2117fe414e Fix error on wide numbers that represent shifts, bug1088. 2016-09-14 20:27:20 -04:00
Wilson Snyder 7d8c51181d With --no-decoration also shrink output code indents. 2016-09-13 22:53:09 -04:00
Wilson Snyder c30211cb27 Add --no-decoration to remove output comments, msg2015. 2016-09-13 22:28:07 -04:00
Johan Bjork 901da118e5 Internals: Move prettyName invocation to after option checks in trace and coverage
Signed-off-by: Wilson Snyder <[email protected]>
2016-09-12 21:52:40 -04:00
Wilson Snyder f11757e43a Fix error on wide shift, msg2005. 2016-09-12 18:31:45 -04:00
Wilson Snyder 3f143317a6 Add error on DPI functions > 32 bits, msg1995. 2016-09-10 08:14:17 -04:00
Wilson Snyder 45d7312dfc Improve Verilation performance on internal strings, msg1975. 2016-09-08 22:04:14 -04:00
Wilson Snyder 26774eb045 Fix error on wide numbers that represent small msb/lsb, msg1991. 2016-09-08 21:30:35 -04:00
Wilson Snyder 6789d247e2 Fix SystemC compiles with VPI, bug1081. 2016-08-23 18:05:29 -04:00
Johan Bjork 462bc3d707 Clean up disabled tests for bugs already fixed.
Signed-off-by: Wilson Snyder <[email protected]>
2016-08-23 06:45:25 -04:00
Wilson Snyder e1755ea6a8 devel release 2016-07-30 10:18:52 -04:00
Wilson Snyder b4a7e4697e Version bump 2016-07-30 10:10:35 -04:00
Wilson Snyder cd61b1d045 Usage check. 2016-07-30 10:05:55 -04:00
Wilson Snyder 24dc36ba4c Fix comparison of unpacked arrays, bug1071. 2016-07-23 16:58:30 -04:00
Wilson Snyder e8e4f1777d Internals: Add cloneType method. Unused - for next checkin. 2016-07-23 16:54:36 -04:00
Wilson Snyder ae38a26af3 Internals: Cleanup some slice code. No functional change. 2016-07-21 23:07:22 -04:00
Wilson Snyder 8ee94dd7aa Tests: Smaller verilated test. 2016-07-21 23:03:54 -04:00
Wilson Snyder e741a29d36 Commentary 2016-07-13 22:51:40 -04:00
Wilson Snyder be1d275151 Fix Ubuntu 16.04 test failures. 2016-07-12 21:43:16 -04:00
David Horton 31c9e26e2e Fix compiler warning in GCC 6.
Signed-off-by: Wilson Snyder <[email protected]>
2016-07-09 04:09:34 -04:00
Wilson Snyder 20ed1ada03 Spelling fixes. 2016-07-09 03:31:22 -04:00
Wilson Snyder 891214fa72 Fix enum values of 11-16 bits wide using .next/.prev, bug1062. 2016-06-15 22:46:34 -04:00
Wilson Snyder e819e285e2 Fix false warnings on non-power-2 enums using .next/.prev. 2016-06-15 20:13:52 -04:00
Wilson Snyder 171c175e54 devel release 2016-05-18 21:15:33 -04:00
Wilson Snyder 675cbce8cb Version bump 2016-05-18 21:10:56 -04:00
Wilson Snyder 4f1398f773 Add commandArgsAdd, msg1890. 2016-05-16 22:04:21 -04:00
Wilson Snyder ae89e399a3 Fix to string, msg1890. 2016-05-16 21:57:49 -04:00
Wilson Snyder 2c9716c64c Try 2. Fix core dump on Arch Linux/GCC 6.1.1, bug1058. 2016-05-16 21:40:49 -04:00
Wilson Snyder bc58245abf Fix core dump on Arch Linux/GCC 6.1.1, bug1058. 2016-05-14 17:56:04 -04:00
Johan Bjork 8c4aa8517e Fix --output-split of constructors, bug1035.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-12 07:19:02 -04:00
Johan Bjork c0b7a54bb9 Fix removal of empty packages, modules and cells, bug1034.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-11 21:44:55 -04:00
Wilson Snyder 6b32bb635d Change --l2-name default to remove 'v' naming. 2016-05-07 14:10:33 -04:00
Wilson Snyder 691de22ae3 Add --l2-name option for controlling 'v' naming, bug1050. 2016-05-07 14:01:02 -04:00
Wilson Snyder e64b2d3372 Internals: user#inc now has optional increment value. 2016-05-06 22:26:15 -04:00
Johan Bjork e190af9d87 Avoid extra clean ANDs after CCalls.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-06 21:18:48 -04:00
Johan Bjork 8d14463b18 Fix emitting public enumerations.
Signed-off-by: Wilson Snyder <[email protected]>
2016-05-05 22:48:53 -04:00
Wilson Snyder 04977ef721 Internals: Show clocker in debug dumps. Part of bug1009. 2016-05-05 22:40:19 -04:00
Wilson Snyder d84e6875c5 Test case 2016-04-06 19:18:59 -04:00
Wilson Snyder 80678ae7bc Fix clang 3.8.0 warnings. 2016-03-31 22:26:49 -04:00
Stefan Wallentowitz 482bdab0e0 Support command-line -G/+pvalue param overrides, bug1045.
Signed-off-by: Wilson Snyder <[email protected]>
2016-03-24 19:14:15 -04:00
Stefan Wallentowitz b2623b9841 Internals: Add success parameter to parseDouble. No functional change intended.
Signed-off-by: Wilson Snyder <[email protected]>
2016-03-23 07:48:32 -04:00
Wilson Snyder 9ae40d64f0 Support parameter type, bug376. 2016-03-14 21:51:31 -04:00
Wilson Snyder cef097b7b7 Internals: Refactoring prep for parameter type branch. No functional change intended. 2016-03-12 20:54:52 -05:00
Wilson Snyder b840334ad2 devel release 2016-03-01 19:14:04 -05:00
Wilson Snyder acff683e8e Version bump 2016-03-01 19:12:14 -05:00
Stefan Wallentowitz c5332de86d Support SV strings to readmemh, bug1040.
Signed-off-by: Wilson Snyder <[email protected]>
2016-03-01 18:57:15 -05:00
Wilson Snyder 90ecf14a0a Fix pattern assignment width propagation, bug1037. 2016-02-21 23:00:21 -05:00
Wilson Snyder 4945282369 Fix slicing mix of big and little-endian, bug1033. 2016-02-09 22:16:12 -05:00
Wilson Snyder ca532d23f0 Suppress null compares to avoid compile errors until bug1030 fixed 2016-02-08 22:16:05 -05:00
Wilson Snyder a509b6a21c Internals: Fix compares to null, ongoing part of bug1030. No functional change intended. 2016-02-08 22:15:44 -05:00
Wilson Snyder 46229473cb Fix crash on very deep function trees, bug1028. 2016-02-04 20:47:55 -05:00
Johan Bjork 65be2448dc Fix elaboration-time display warnings, bug1032.
Signed-off-by: Wilson Snyder <[email protected]>
2016-02-04 18:38:59 -05:00
Johan Bjork be74806044 Fix read-after-free error detected by valgrind, bug1031.
Signed-off-by: Wilson Snyder <[email protected]>
2016-02-04 18:34:08 -05:00
Wilson Snyder b488666c1e Fix cppcheck 1.71 issues. No functional change intended. 2016-02-04 18:30:21 -05:00
Wilson Snyder d1acaea611 Internals: Fix compares to null, ongoing part of bug1030. No functional change intended. 2016-02-03 20:44:31 -05:00
Wilson Snyder db6e5ce7cf Internals: Misc code cleanups. No functional change. 2016-02-03 20:43:05 -05:00
Wilson Snyder d56179df17 Internals: Fix compares to null, part of bug1030. No functional change intended. 2016-02-02 21:02:00 -05:00
Wilson Snyder 850100c9c2 Fix compares to null, part of bug1030. 2016-02-02 19:35:44 -05:00
Wilson Snyder 0725999f0a flexfix: Match Verilog-perl fix for new gcc. 2016-02-02 19:32:17 -05:00
Johan Bjork cb2d8259f2 Fix stats and debug print, bug1029
Signed-off-by: Wilson Snyder <[email protected]>
2016-01-28 22:20:31 -05:00
Johan Bjork 61a1f3d817 Support inlining interfaces, bug1018.
Signed-off-by: Wilson Snyder <[email protected]>
2016-01-21 19:11:53 -05:00
Johan Bjork 63f111b7f3 Fix unrolling complicated for-loop bounds, bug677.
Signed-off-by: Wilson Snyder <[email protected]>
2016-01-21 19:00:19 -05:00
Wilson Snyder e061eb3003 Fix using short parameter names on negative params, bug1022. 2016-01-20 22:09:11 -05:00
Johan Bjork 29daa58222 Fix stats file containing multiple unroll entries, bug1020.
Signed-off-by: Wilson Snyder <[email protected]>
2016-01-06 20:53:48 -05:00
Johan Bjork 340cc02171 Avoid dynamic_cast for classes with no children, bug1021.
Signed-off-by: Wilson Snyder <[email protected]>
2016-01-06 20:47:44 -05:00
Wilson Snyder b738d1960a Copyright year update 2016-01-06 20:36:41 -05:00
Wilson Snyder 38f5b780d7 devel release 2016-01-06 20:33:25 -05:00
Wilson Snyder fa9dac29e8 Version bump 2015-12-19 10:26:14 -05:00
Wilson Snyder afc432042f Fix ternary operation with unpacked array, bug1017. 2015-12-18 18:02:25 -05:00
Wilson Snyder 21cb29baf0 Fix arrayed instances to unpacked of same size, bug1015. Fix slices of unpacked arrays with non-zero LSBs. 2015-12-15 22:37:49 -05:00
Wilson Snyder e8b5001cfe Fix model restore crash, bug1013. 2015-12-14 19:58:22 -05:00
Wilson Snyder 849c1e46a2 Fix constant propagation, bug1012. 2015-12-08 22:22:42 -05:00
Wilson Snyder ebad6cde36 Fix error instead of warning on large concat, msg1768. 2015-12-08 21:25:43 -05:00
Johan Bjork f920b3945e Fix dotted generated array error, bug1005.
Signed-off-by: Wilson Snyder <[email protected]>
2015-12-05 19:58:58 -05:00
Wilson Snyder 178028a70a Commentary; part of last commit 2015-12-05 19:45:45 -05:00
Todd Strader 5e54d3e41a Fix interface inside generate, bug1001, bug1003.
Signed-off-by: Wilson Snyder <[email protected]>
2015-12-05 19:39:40 -05:00
Wilson Snyder f0af8726e3 Internals: Fix some spacing. No functional change. 2015-12-05 17:12:03 -05:00
Todd Strader 57f2fe77ea Fix cell [#] to mean # cells.
Signed-off-by: Wilson Snyder <[email protected]>
2015-12-01 18:23:11 -05:00
Todd Strader d56ca25089 Tests: Fix false hidden module warning.
Signed-off-by: Wilson Snyder <[email protected]>
2015-12-01 18:17:26 -05:00
Wilson Snyder d39ce17dea Makefiles: Turn off make built-in suffixes. 2015-11-28 17:33:01 -05:00
Johan Bjork 373a68ec8b Fix dtype indexing into arrays, bug1007.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-24 21:34:07 -05:00
Johan Bjork 5613758ee3 Fix array slicing of non-const indexes, bug1006.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-24 21:28:04 -05:00
Johan Bjork 2102f86909 Fix genvar constant propagation, bug1003.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-22 21:16:13 -05:00
Wilson Snyder d5ea785de7 Commentary; last commit was bug1004 2015-11-22 21:13:16 -05:00
Johan Bjork 9edd28d2ed Fix genvar constant propagation from package, bug1003.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-22 20:46:26 -05:00
Wilson Snyder 7698af5178 Tests 2015-11-14 20:53:36 -05:00
Wilson Snyder 52ae451f5c Fix interface inside generate, bug998. 2015-11-14 09:06:09 -05:00
Wilson Snyder 9254443cd4 Fix casts under generates, bug999. 2015-11-12 22:29:42 -05:00
Johan Bjork 4e4bc7b90f Fix constant function assigned to packed structs, bug997.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-11 20:49:45 -05:00
Johan Bjork c7e0f2e196 Fix function calls on arrayed interface, bug994.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-11 20:40:24 -05:00
Wilson Snyder acabaab6ac Internals: Avoid tristate coredump. 2015-11-11 20:37:52 -05:00
Wilson Snyder b0a249f338 Fix display %u, %v, %p, %z, bug989. 2015-11-10 21:12:15 -05:00
Wilson Snyder 0cb5d5cc5a Internals: Upgrade some C strings to C++ 2015-11-10 18:59:48 -05:00
Wilson Snyder 9208c87f91 Tests: Better upper-case display formats. 2015-11-10 07:09:53 -05:00
Johan Bjork 0081ce4a75 Fix size-changing cast on packed struct, bug993.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-06 19:12:17 -05:00
Todd Strader 7850f49963 Fix t_scope_map --verbose test, bug955.
Signed-off-by: Wilson Snyder <[email protected]>
2015-11-06 18:58:48 -05:00
Wilson Snyder c72ee41142 Add z to param values to avoid conflicts. 2015-11-05 07:00:04 -05:00
Wilson Snyder bf5dee955d Fix real parameters causing bad module names, bug992. 2015-11-04 22:01:21 -05:00
Wilson Snyder 3df23a148a devel release 2015-11-01 08:20:17 -05:00
476 changed files with 10143 additions and 3994 deletions
+184 -4
View File
@@ -1,7 +1,187 @@
Revision history for Verilator Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. Thanks!
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.902 2017-04-02
** Add -FI option to force includes,msg2146. [Amir Gonnen]
** Add --relative-includes. [Rob Stoddard]
*** Add error on duplicate pattern assignments, bug1145. [Johan Bjork]
**** Fix error on improperly widthed default function, bug984. [Todd Strader]
**** Fix 2009 localparam syntax, msg2139. [Galen Seitz]
**** Fix ugly interface-to-non-interface errors, bug1112. [Johan Bjork]
**** Fix LDFLAGS and CFLAGS not preserving order, bug1130. [Olof Kindgren]
**** Fix internal error on initializing parameter array, bug1131. [Jie Xu]
**** Fix internal error on interface arrays, bug1135. [John Stevenson]
**** Fix calling sformatf to display, and elab $displays, bug1139. [Johan Bjork]
**** Fix realpath compile issue on MSVC++, bug1141. [Miodrag Milanovic]
**** Fix missing error on interface size mismatch, bug1143. [Johan Bjork]
**** Fix error on parameters with dotted references, bug1146. [Johan Bjork]
**** Fix wreal not handling continuous assign, bug1150. [J Briquet]
**** Fix nested structure parameter selects, bug1150. [J Briquet]
* Verilator 3.900 2017-01-15
** Internal code changes for improved compatibility and performance.
*** Support old-style $display($time), bug467. [John Demme]
**** With --bbox-unsup, suppress desassign and mixed edges, bug1120. [Galen Seitz]
**** Fix parsing sensitivity with &&, bug934. [Luke Yang]
**** Fix internal error on double-for loop unrolling, bug1044. [Jan Egil Ruud]
**** Fix internal error on unique casez with --assert, bug1117. [Enzo Chi]
**** Fix bad code when tracing array of structs, bug1122. [Andrew Bardsley]
* Verilator 3.890 2016-11-25
*** Honor --output-split on coverage constructors, bug1098. [Johan Bjork]
**** Fix various issues when making outside of the kit.
**** Fix flex 2.6.2 bug, bug1103. [Sergey Kvachonok]
**** Fix error on bad interface name, bug1097. [Todd Strader]
**** Fix error on referencing variable in parent, bug1099. [Ian Thompson]
**** Fix type parameters with low optimization, bug1101. [Stefan Wallentowitz]
* Verilator 3.888 2016-10-14
** Support foreach, bug1078. [Xuan Guo]
*** Add --no-decoration to remove output comments, msg2015. [Frederic Requin]
*** If VM_PARALLEL_BUILDS=1, use OPT_FAST and OPT_SLOW. [Frederic Requin]
Set VM_DEFAULT_RULES=0 for old behavior.
**** Add error on DPI functions > 32 bits, msg1995. [Elliot Mednick]
**** Fix SystemC compiles with VPI, bug1081. [Arthur Kahlich]
**** Fix error on wide numbers that represent shifts, msg1991, bug1088. [Mandy Xu]
**** Improve Verilation performance on internal strings, msg1975. [Johan Bjork]
**** Improve Verilation performance on trace duplicates, bug1090. [Johan Bjork]
* Verilator 3.886 2016-07-30
**** Fix enum values of 11-16 bits wide using .next/.prev, bug1062. [Brian Flachs]
**** Fix false warnings on non-power-2 enums using .next/.prev.
**** Fix comparison of unpacked arrays, bug1071. [Andrew Bardsley]
**** Fix compiler warning in GCC 6. [David Horton]
* Verilator 3.884 2016-05-18
** Support parameter type, bug376. [Alan Hunter, et al]
** Support command-line -G/+pvalue param overrides, bug1045. [Stefan Wallentowitz]
*** The default l2 scope name is now the same as the top-level module, bug1050.
Use "--l2-name v" for the historical behavior.
*** Add --l2-name option for controlling "v" naming.
**** Fix --output-split of constructors, bug1035. [Johan Bjork]
**** Fix removal of empty packages, modules and cells, bug1034. [Johan Bjork]
**** Fix core dump on Arch Linux/GCC 6.1.1, bug1058. [Jannis Harder]
**** Fix $value$plusargs to string, msg1890. [Frederic Requin]
* Verilator 3.882 2016-03-01
**** Internal Verilation-time performance enhancements, bug1021. [Johan Bjork]
**** Support inlining interfaces, bug1018. [Johan Bjork]
**** Support SV strings to readmemh, bug1040. [Stefan Wallentowitz]
**** Fix unrolling complicated for-loop bounds, bug677. [Johan Bjork]
**** Fix stats file containing multiple unroll entries, bug1020. [Johan Bjork]
**** Fix using short parameter names on negative params, bug1022. [Duraid Madina]
**** Fix read-after-free error, bug1031. [Johan Bjork]
**** Fix elaboration-time display warnings, bug1032. [Johan Bjork]
**** Fix crash on very deep function trees, bug1028. [Jonathan Kimmitt]
**** Fix slicing mix of big and little-endian, bug1033. [Geoff Barrett]
**** Fix pattern assignment width propagation, bug1037. [Johan Bjork]
* Verilator 3.880 2015-12-19
*** Support display %u, %v, %p, %z, bug989. [Johan Bjork]
**** Fix real parameters causing bad module names, bug992. [Johan Bjork]
**** Fix size-changing cast on packed struct, bug993. [Johan Bjork]
**** Fix function calls on arrayed interface, bug994. [Johan Bjork]
**** Fix arrayed interfaces, bug879, bug1001. [Todd Strader]
**** Fix constant function assigned to packed structs, bug997. [Johan Bjork]
**** Fix interface inside generate, bug998. [Johan Bjork]
**** Fix $signed casts under generates, bug999. [Clifford Wolf]
**** Fix genvar constant propagation, bug1003. [Johan Bjork]
**** Fix parameter constant propagation from package, bug1004. [Johan Bjork]
**** Fix array slicing of non-const indexes, bug1006. [Johan Bjork]
**** Fix dotted generated array error, bug1005. [Jeff Bush, Johan Bjork]
**** Fix error instead of warning on large concat, msg1768. [Paul Rolfe]
**** Fix $bitstoreal constant propagation, bug1012. [Jonathan Kimmitt]
**** Fix model restore crash, bug1013. [Jason McMullan]
**** Fix arrayed instances to unpacked of same size, bug1015. [Varun Koyyalagunta]
**** Fix slices of unpacked arrays with non-zero LSBs.
**** Fix ternary operation with unpacked array, bug1017. [Varun Koyyalagunta].
* Verilator 3.878 2015-11-01 * Verilator 3.878 2015-11-01
@@ -2640,12 +2820,12 @@ of input ports exists for tracing.
This uses outline mode in Emacs. See C-h m [M-x describe-mode]. This uses outline mode in Emacs. See C-h m [M-x describe-mode].
Copyright 2001-2015 by Wilson Snyder. This program is free software; you Copyright 2001-2017 by Wilson Snyder. This program is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
Local variables: Local variables:
mode: outline mode: outline
paragraph-separate: "[ \f\n]*$" paragraph-separate: "[ \f\n]*$"
end: end:
+9 -6
View File
@@ -7,7 +7,7 @@
# #
#***************************************************************************** #*****************************************************************************
# #
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can # Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -42,9 +42,6 @@
# reconstructed with this Makefile. This typically includes # reconstructed with this Makefile. This typically includes
# everything deleted by distclean, plus more: C source files # everything deleted by distclean, plus more: C source files
# produced by Bison, tags tables, info files, and so on. # produced by Bison, tags tables, info files, and so on.
#
# make extraclean
# Still more severe - delete backup and autosave files, too.
#### Start of system configuration section. #### #### Start of system configuration section. ####
@@ -71,7 +68,7 @@ exec_prefix = @exec_prefix@
# Directory in which to install scripts. # Directory in which to install scripts.
bindir = @bindir@ bindir = @bindir@
# Directory in which to install scripts. # Directory in which to install manpages.
mandir = @mandir@ mandir = @mandir@
# Directory in which to install library files. # Directory in which to install library files.
@@ -100,6 +97,8 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
#### End of system configuration section. #### #### End of system configuration section. ####
###################################################################### ######################################################################
.SUFFIXES:
SHELL = /bin/sh SHELL = /bin/sh
SUBDIRS = src test_verilated test_c test_sc test_regress SUBDIRS = src test_verilated test_c test_sc test_regress
@@ -133,6 +132,8 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
test_verilated/vgen*.pl \ test_verilated/vgen*.pl \
test_regress/t/t*/*.sv* \ test_regress/t/t*/*.sv* \
test_regress/t/t*/*.v* \ test_regress/t/t*/*.v* \
test_regress/t/t*/*/*.sv* \
test_regress/t/t*/*/*.v* \
test_regress/t/*.cpp \ test_regress/t/*.cpp \
test_regress/t/*.h \ test_regress/t/*.h \
test_regress/t/*.dat \ test_regress/t/*.dat \
@@ -271,6 +272,7 @@ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg verilator_coverage
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_profcfunc.1 VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_profcfunc.1
VL_INST_INC_BLDDIR_FILES = \ VL_INST_INC_BLDDIR_FILES = \
include/verilated_config.h \
include/verilated.mk \ include/verilated.mk \
# Files under srcdir, instead of build time # Files under srcdir, instead of build time
@@ -298,7 +300,8 @@ installbin:
# So important we use $< so VPATH is searched # So important we use $< so VPATH is searched
installman: $(VL_INST_MAN_FILES) installman: $(VL_INST_MAN_FILES)
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1 $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
for p in $^ ; do \ cd $(srcdir) \
; for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \ $(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
done done
+1 -1
View File
@@ -11,7 +11,7 @@ This is the Verilator package README file.
http://www.veripool.org/verilator http://www.veripool.org/verilator
This package is Copyright 2003-2015 by Wilson Snyder. (Report bugs to This package is Copyright 2003-2017 by Wilson Snyder. (Report bugs to
L<http://www.veripool.org/>.) L<http://www.veripool.org/>.)
Verilator is free software; you can redistribute it and/or modify it under Verilator is free software; you can redistribute it and/or modify it under
+1 -1
View File
@@ -1,6 +1,6 @@
// DESCRIPTION: Verilator: List of To Do issues. // DESCRIPTION: Verilator: List of To Do issues.
// //
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can // Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+290 -173
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0; if 0;
###################################################################### ######################################################################
# #
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you # Copyright 2003-2017 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -19,8 +19,8 @@ require 5.006_001;
use warnings; use warnings;
BEGIN { BEGIN {
if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) { if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) {
# Magic to allow author testing of perl packages in local directory # Magic to allow author testing of perl packages in local directory
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT}; require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
} }
} }
@@ -54,22 +54,33 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
# We sneak a look at the flags so we can do some pre-environment checks # We sneak a look at the flags so we can do some pre-environment checks
# All flags will hit verilator... # All flags will hit verilator...
foreach my $sw (@ARGV) { foreach my $sw (@ARGV) {
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!; # Some special treatment for parameters to allow verilog literals for numbers
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
# If there is a single quote in the parameter put it double quotes ,
# else just put it in double quotes
if ($sw =~ m![\']!) {
$sw = "\"$sw\"";
} else {
$sw = "'$sw'";
}
} else {
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
}
push @Opt_Verilator_Sw, $sw; push @Opt_Verilator_Sw, $sw;
} }
Getopt::Long::config ("no_auto_abbrev","pass_through"); Getopt::Long::config ("no_auto_abbrev","pass_through");
if (! GetOptions ( if (! GetOptions (
# Major operating modes # Major operating modes
"help" => \&usage, "help" => \&usage,
"debug:s" => \&debug, "debug:s" => \&debug,
# "version!" => \&version, # Also passthru'ed # "version!" => \&version, # Also passthru'ed
# Switches # Switches
"gdb!" => \$opt_gdb, "gdb!" => \$opt_gdb,
"gdbbt!" => \$opt_gdbbt, "gdbbt!" => \$opt_gdbbt,
# Additional parameters # Additional parameters
"<>" => sub {}, # Ignored "<>" => sub {}, # Ignored
)) { )) {
pod2usage(-exitstatus=>2, -verbose=>0); pod2usage(-exitstatus=>2, -verbose=>0);
} }
@@ -81,22 +92,22 @@ if ($opt_gdbbt && !gdb_works()) {
if ($opt_gdb) { if ($opt_gdb) {
# Generic GDB interactive # Generic GDB interactive
run (("gdb"||$ENV{VERILATOR_GDB}) run (("gdb"||$ENV{VERILATOR_GDB})
." ".verilator_bin() ." ".verilator_bin()
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'" ." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
." -ex 'set width 0'" ." -ex 'set width 0'"
." -ex 'bt'"); ." -ex 'bt'");
} elsif ($opt_gdbbt && $Debug) { } elsif ($opt_gdbbt && $Debug) {
# Run under GDB to get gdbbt # Run under GDB to get gdbbt
run ("gdb" run ("gdb"
." ".verilator_bin() ." ".verilator_bin()
." --batch --quiet --return-child-result" ." --batch --quiet --return-child-result"
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'" ." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
." -ex 'set width 0'" ." -ex 'set width 0'"
." -ex 'bt'"); ." -ex 'bt'");
} else { } else {
# Normal, non gdb # Normal, non gdb
run (verilator_bin() run (verilator_bin()
." ".join(' ',@Opt_Verilator_Sw)); ." ".join(' ',@Opt_Verilator_Sw));
} }
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@@ -119,23 +130,23 @@ sub verilator_bin {
my $bin = ""; my $bin = "";
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path # Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
my $basename = ($ENV{VERILATOR_BIN} my $basename = ($ENV{VERILATOR_BIN}
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin")); || ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
if (defined($ENV{VERILATOR_ROOT})) { if (defined($ENV{VERILATOR_ROOT})) {
my $dir = $ENV{VERILATOR_ROOT}; my $dir = $ENV{VERILATOR_ROOT};
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
$bin = "$dir/bin/$basename"; $bin = "$dir/bin/$basename";
} else { } else {
$bin = "$dir/$basename"; # From pointing to kit directory $bin = "$dir/$basename"; # From pointing to kit directory
} }
} else { } else {
if (-x "$RealBin/$basename") { if (-x "$RealBin/$basename") {
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed $bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
} else { } else {
$bin = $basename; # Find in PATH $bin = $basename; # Find in PATH
} }
# Note we don't look under bin/$basename which would be right if running # Note we don't look under bin/$basename which would be right if running
# in the kit dir. Running that would likely break, since # in the kit dir. Running that would likely break, since
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files. # VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
} }
return $bin; return $bin;
} }
@@ -147,10 +158,10 @@ sub verilator_bin {
sub gdb_works { sub gdb_works {
$! = undef; # Cleanup -x $! = undef; # Cleanup -x
system("gdb /bin/echo" system("gdb /bin/echo"
." --batch-silent --quiet --return-child-result" ." --batch-silent --quiet --return-child-result"
." -ex 'run -n'" # `echo -n` ." -ex 'run -n'" # `echo -n`
." -ex 'set width 0'" ." -ex 'set width 0'"
." -ex 'bt'"); ." -ex 'bt'");
my $status = $?; my $status = $?;
return $status==0; return $status==0;
} }
@@ -163,23 +174,23 @@ sub run {
system($command); system($command);
my $status = $?; my $status = $?;
if ($status) { if ($status) {
if ($! =~ /no such file or directory/i) { if ($! =~ /no such file or directory/i) {
warn "%Error: verilator: Misinstalled, or VERILATOR_ROOT might need to be in environment\n"; warn "%Error: verilator: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
} }
if ($Debug) { # For easy rerunning if ($Debug) { # For easy rerunning
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n"; warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n"; warn "%Error: $command\n";
} }
if ($status & 127) { if ($status & 127) {
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug; warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 127) == 6) { # SIGABRT } elsif (($status & 127) == 6) { # SIGABRT
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug; warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
} else { } else {
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug; warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
} }
} }
die "%Error: Command Failed $command\n"; die "%Error: Command Failed $command\n";
} }
} }
@@ -198,9 +209,9 @@ Verilator - Convert Verilog code to C++/SystemC
verilator --help verilator --help
verilator --version verilator --version
verilator --cc [options] [top_level.v]... [opt_c_files.cpp/c/cc/a/o/so] verilator --cc [options] [source_files.v]... [opt_c_files.cpp/c/cc/a/o/so]
verilator --sc [options] [top_level.v]... [opt_c_files.cpp/c/cc/a/o/so] verilator --sc [options] [source_files.v]... [opt_c_files.cpp/c/cc/a/o/so]
verilator --lint-only [top_level.v]... verilator --lint-only [source_files.v]...
=head1 DESCRIPTION =head1 DESCRIPTION
@@ -228,7 +239,7 @@ To get started, jump down to "EXAMPLE C++ EXECUTION".
This is a short summary of the arguments to Verilator. See the detailed This is a short summary of the arguments to Verilator. See the detailed
descriptions in the next sections for more information. descriptions in the next sections for more information.
{file.v} Verilog top level filenames {file.v} Verilog package, module and top module filenames
{file.c/cc/cpp} Optional C++ files to compile in {file.c/cc/cpp} Optional C++ files to compile in
{file.a/o/so} Optional C++ files to link in {file.a/o/so} Optional C++ files to link in
@@ -269,6 +280,8 @@ descriptions in the next sections for more information.
--exe Link to create executable --exe Link to create executable
-F <file> Parse options from a file, relatively -F <file> Parse options from a file, relatively
-f <file> Parse options from a file -f <file> Parse options from a file
-FI <file> Force include of a file
-G<name>=<value> Overwrite toplevel parameter
--gdb Run Verilator under GDB interactively --gdb Run Verilator under GDB interactively
--gdbbt Run Verilator under GDB for backtrace --gdbbt Run Verilator under GDB for backtrace
--help Display this help --help Display this help
@@ -279,6 +292,7 @@ descriptions in the next sections for more information.
--inline-mult <value> Tune module inlining --inline-mult <value> Tune module inlining
-LDFLAGS <flags> Linker pre-object flags for makefile -LDFLAGS <flags> Linker pre-object flags for makefile
-LDLIBS <flags> Linker library flags for makefile -LDLIBS <flags> Linker library flags for makefile
--l2-name <value> Verilog scope name of the top module
--language <lang> Default language standard to parse --language <lang> Default language standard to parse
+libext+<ext>+[ext]... Extensions for finding modules +libext+<ext>+[ext]... Extensions for finding modules
--lint-only Lint, but do not make output --lint-only Lint, but do not make output
@@ -287,6 +301,7 @@ descriptions in the next sections for more information.
--Mdir <directory> Name of output object directory --Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes --mod-prefix <topname> Name to prepend to lower classes
--no-clk <signal-name> Prevent marking specified signal as clock --no-clk <signal-name> Prevent marking specified signal as clock
--no-decoration Disable comments and symbol decorations
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs --no-pins64 Don't use vluint64_t's for 33-64 bit sigs
--no-skip-identical Disable skipping identical output --no-skip-identical Disable skipping identical output
+notimingchecks Ignored +notimingchecks Ignored
@@ -308,8 +323,10 @@ descriptions in the next sections for more information.
--profile-cfuncs Name functions for profiling --profile-cfuncs Name functions for profiling
--private Debugging; see docs --private Debugging; see docs
--public Debugging; see docs --public Debugging; see docs
-pvalue+<name>=<value> Overwrite toplevel parameter
--relative-includes Resolve includes relative to current file
--report-unoptflat Extra diagnostics for UNOPTFLAT --report-unoptflat Extra diagnostics for UNOPTFLAT
--savable Enable model save-restore --savable Enable model save-restore
--sc Create SystemC output --sc Create SystemC output
--stats Create statistics file --stats Create statistics file
--stats-vars Provide statistics on variables --stats-vars Provide statistics on variables
@@ -429,9 +446,10 @@ calls.
=item --bbox-unsup =item --bbox-unsup
Black box some unsupported language features, currently UDP tables and the Black box some unsupported language features, currently UDP tables, the
cmos and tran gate primitives. This may enable linting the rest of the cmos and tran gate primitives, deassign statements, and mixed edge errors.
design even when unsupported constructs are present. This may enable linting the rest of the design even when unsupported
constructs are present.
=item --bin I<filename> =item --bin I<filename>
@@ -479,7 +497,7 @@ RTL file to mark the signal directly.
=item --compiler I<compiler-name> =item --compiler I<compiler-name>
Enables tunings and work-arounds for the specified C++ compiler. Enables tunings and workarounds for the specified C++ compiler.
=over 4 =over 4
@@ -592,8 +610,8 @@ alias for GCC compatibility.
=item --debug =item --debug
Select the debug built image of Verilator (if available), and enable more Select the debug built image of Verilator (if available), and enable more
internal assertions (equivelent to C<--debug-check>), debugging messages internal assertions (equivalent to C<--debug-check>), debugging messages
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent (equivalent to C<--debugi 4>), and intermediate form dump files (equivalent
to C<--dump-treei 3>). to C<--dump-treei 3>).
=item --debug-check =item --debug-check
@@ -688,6 +706,43 @@ The file may contain // comments which are ignored to the end of the line.
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
variable. variable.
=item -FI <file>
Force include of the specified C++ header file. All generated C++ files
will insert a #include of the specified file before any other includes. The
specified file might be used to contain define prototypes of custom
VL_VPRINTF functions, and may need to include verilatedos.h as this file is
included before any other standard includes.
=item -GI<name>=I<value>
Overwrites the given parameter of the toplevel module. The value is limited
to basic data literals:
=over 4
=item Verilog integer literals
The standard verilog integer literals are supported, so values like 32'h8,
2'b00, 4 etc. are allowed. Care must be taken that the single quote (I') is
properly escaped in an interactive shell, e.g., as -GWIDTH=8\'hx.
=item C integer literals
It is also possible to use C integer notation, including hexadecimal (0x..),
octal (0..) or binary (0b..) notation.
=item Double literals
Double literals must contain a dot (.) and/or an exponent (e).
=item Strings
String must in double quotes ("). On the command line it is required to escape
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
=back
=item --gdb =item --gdb
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
@@ -743,9 +798,19 @@ called LDLIBS as that's the Makefile variable it controls. (In Make,
LDFLAGS is before the first object, LDLIBS after. -L libraries need to be LDFLAGS is before the first object, LDLIBS after. -L libraries need to be
in the Make variable LDLIBS, not LDFLAGS.) in the Make variable LDLIBS, not LDFLAGS.)
=item --l2-name I<value>
Instead of using the module name when showing Verilog scope, use the name
provided. This allows simplifying some Verilator-embedded modeling
methodologies. Default is an l2-name matching the top module. The default
before 3.884 was "--l2-name v"
For example, the program "module t; initial $display("%m"); endmodule" will
show by default "t". With "--l2-name v" it will print "v".
=item --language I<value> =item --language I<value>
A synonym for C<--default-langauge>, for compatibility with other tools and A synonym for C<--default-language>, for compatibility with other tools and
earlier versions of Verilator. earlier versions of Verilator.
=item +libext+I<ext>+I<ext>... =item +libext+I<ext>+I<ext>...
@@ -790,6 +855,13 @@ the same as --prefix.
Prevent the specified signal from being marked as clock. See C<--clk>. Prevent the specified signal from being marked as clock. See C<--clk>.
=item --no-decoration
When creating output Verilated code, minimize comments, whitespace, symbol
names and other decorative items, at the cost of greatly reduced
readability. This may assist C++ compile times. This will not typically
change the ultimate model's performance, but may in some cases.
=item --no-pins64 =item --no-pins64
Backward compatible alias for "--pins-bv 33". Backward compatible alias for "--pins-bv 33".
@@ -873,9 +945,10 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
wide should use sc_bv's instead of uint32/vluint64_t's. The default is wide should use sc_bv's instead of uint32/vluint64_t's. The default is
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv "--pins-bv 65", and the value must be less than or equal to 65. Versions
33". The more sc_bv is used, the worse for performance. Use the before Verilator 3.671 defaulted to "--pins-bv 33". The more sc_bv is
"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv. used, the worse for performance. Use the "/*verilator sc_bv*/" attribute
to select specific ports to be sc_bv.
=item --pins-sc-uint =item --pins-sc-uint
@@ -946,6 +1019,17 @@ inlining. This will also turn off inlining as if all modules had a
/*verilator public_module*/, unless the module specifically enabled it with /*verilator public_module*/, unless the module specifically enabled it with
/*verilator inline_module*/. /*verilator inline_module*/.
=item -pvalue+I<name>=I<value>
Overwrites the given parameter(s) of the toplevel module. See -G for a
detailed description.
=item --relative-includes
When a file references an include file, resolve the filename relative to
the path of the referencing file, instead of relative to the current
directory.
=item --report-unoptflat =item --report-unoptflat
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
@@ -1269,7 +1353,7 @@ We'll compile this example into C++.
#include "Vour.h" #include "Vour.h"
#include "verilated.h" #include "verilated.h"
int main(int argc, char **argv, char **env) { int main(int argc, char **argv, char **env) {
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
Vour* top = new Vour; Vour* top = new Vour;
while (!Verilated::gotFinish()) { top->eval(); } while (!Verilated::gotFinish()) { top->eval(); }
delete top; delete top;
@@ -1277,9 +1361,15 @@ We'll compile this example into C++.
} }
EOF EOF
If you installed Verilator from sources, or a tarball, but not as part of See the README in the source kit for various ways to install or point to
your operating system (as an RPM), first you need to point to the kit: Verilator binaries. In brief, if you are running Verilator that came from
your operating system (as an RPM), or did a "make install" to place
Verilator into your default path, you do not need anything special in your
environment, and should not have VERILATOR_ROOT set. However, if you
installed Verilator from sources and want to run Verilator out of where you
compiled Verilator, you need to point to the kit:
# See above; don't do this if using an OS-distributed Verilator
export VERILATOR_ROOT=/path/to/where/verilator/was/installed export VERILATOR_ROOT=/path/to/where/verilator/was/installed
export PATH=$VERILATOR_ROOT/bin:$PATH export PATH=$VERILATOR_ROOT/bin:$PATH
@@ -1294,8 +1384,7 @@ section below for descriptions of some of the files that were created.
We then can compile it We then can compile it
cd obj_dir make -j -C obj_dir -f Vour.mk Vour
make -j -f Vour.mk Vour
(Verilator included a default compile rule and link rule, since we used (Verilator included a default compile rule and link rule, since we used
--exe and passed a .cpp file on the Verilator command line. You can also --exe and passed a .cpp file on the Verilator command line. You can also
@@ -1303,7 +1392,6 @@ write your own compile rules, as we'll show in the SYSTEMC section.)
And now we run it And now we run it
cd ..
obj_dir/Vour obj_dir/Vour
And we get as output And we get as output
@@ -1312,8 +1400,9 @@ And we get as output
- our.v:2: Verilog $finish - our.v:2: Verilog $finish
Really, you're better off writing a Makefile to do all this for you. Then, Really, you're better off writing a Makefile to do all this for you. Then,
when your source changes it will automatically run all of these steps. See when your source changes it will automatically run all of these steps; to
the test_c directory in the distribution for an example. aid this Verilator can create a makefile dependency file. See the test_c
directory in the distribution for an example.
=head1 EXAMPLE SYSTEMC EXECUTION =head1 EXAMPLE SYSTEMC EXECUTION
@@ -1334,20 +1423,26 @@ This is an example similar to the above, but using SystemC.
cat <<EOF >sc_main.cpp cat <<EOF >sc_main.cpp
#include "Vour.h" #include "Vour.h"
int sc_main(int argc, char **argv) { int sc_main(int argc, char **argv) {
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
sc_clock clk ("clk",10, 0.5, 3, true); sc_clock clk ("clk",10, 0.5, 3, true);
Vour* top; Vour* top;
top = new Vour("top"); // SP_CELL (top, Vour); top = new Vour("top"); // SP_CELL (top, Vour);
top->clk(clk); // SP_PIN (top, clk, clk); top->clk(clk); // SP_PIN (top, clk, clk);
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); } while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
delete top; delete top;
exit(0); exit(0);
} }
EOF EOF
If you installed Verilator from sources, or a tarball, but not as part of See the README in the source kit for various ways to install or point to
your operating system (as an RPM), first you need to point to the kit: Verilator binaries. In brief, if you are running Verilator that came from
your operating system (as an RPM), or did a "make install" to place
Verilator into your default path, you do not need anything special in your
environment, and should not have VERILATOR_ROOT set. However, if you
installed Verilator from sources and want to run Verilator out of where you
compiled Verilator, you need to point to the kit:
# See above; don't do this if using an OS-distributed Verilator
export VERILATOR_ROOT=/path/to/where/verilator/was/installed export VERILATOR_ROOT=/path/to/where/verilator/was/installed
export PATH=$VERILATOR_ROOT/bin:$PATH export PATH=$VERILATOR_ROOT/bin:$PATH
@@ -1357,6 +1452,7 @@ Now we run Verilator on our little example.
We then can compile it We then can compile it
cd obj_dir
make -j -f Vour.mk Vour__ALL.a make -j -f Vour.mk Vour__ALL.a
make -j -f Vour.mk ../sc_main.o verilated.o make -j -f Vour.mk ../sc_main.o verilated.o
@@ -1462,42 +1558,42 @@ All output files are placed in the output directory name specified with the
Verilator creates the following files in the output directory: Verilator creates the following files in the output directory:
{prefix}.mk // Make include file for compiling {prefix}.mk // Make include file for compiling
{prefix}_classes.mk // Make include file with class names {prefix}_classes.mk // Make include file with class names
For -cc and -sc mode, it also creates: For -cc and -sc mode, it also creates:
{prefix}.cpp // Top level C++ file {prefix}.cpp // Top level C++ file
{prefix}.h // Top level header {prefix}.h // Top level header
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files {prefix}{each_verilog_module}.cpp // Lower level internal C++ files
{prefix}{each_verilog_module}.h // Lower level internal header files {prefix}{each_verilog_module}.h // Lower level internal header files
In certain optimization modes, it also creates: In certain optimization modes, it also creates:
{prefix}__Dpi.h // DPI import and export declarations {prefix}__Dpi.h // DPI import and export declarations
{prefix}__Inlines.h // Inline support functions {prefix}__Inlines.h // Inline support functions
{prefix}__Slow.cpp // Constructors and infrequent routines {prefix}__Slow.cpp // Constructors and infrequent routines
{prefix}__Syms.cpp // Global symbol table C++ {prefix}__Syms.cpp // Global symbol table C++
{prefix}__Syms.h // Global symbol table header {prefix}__Syms.h // Global symbol table header
{prefix}__Trace.cpp // Wave file generation code (--trace) {prefix}__Trace.cpp // Wave file generation code (--trace)
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc) {prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
{prefix}__stats.txt // Statistics (--stats) {prefix}__stats.txt // Statistics (--stats)
It also creates internal files that can be mostly ignored: It also creates internal files that can be mostly ignored:
{each_verilog_module}.vpp // Post-processed verilog (--debug) {each_verilog_module}.vpp // Post-processed verilog (--debug)
{prefix}.flags_vbin // Verilator dependencies {prefix}.flags_vbin // Verilator dependencies
{prefix}.flags_vpp // Pre-processor dependencies {prefix}.flags_vpp // Pre-processor dependencies
{prefix}__verFiles.dat // Timestamps for skip-identical {prefix}__verFiles.dat // Timestamps for skip-identical
{prefix}{misc}.d // Make dependencies (-MMD) {prefix}{misc}.d // Make dependencies (-MMD)
{prefix}{misc}.dot // Debugging graph files (--debug) {prefix}{misc}.dot // Debugging graph files (--debug)
{prefix}{misc}.tree // Debugging files (--debug) {prefix}{misc}.tree // Debugging files (--debug)
After running Make, the C++ compiler should produce the following: After running Make, the C++ compiler should produce the following:
{prefix} // Final executable (w/--exe argument) {prefix} // Final executable (w/--exe argument)
{prefix}__ALL.a // Library of all Verilated objects {prefix}__ALL.a // Library of all Verilated objects
{prefix}{misc}.o // Intermediate objects {prefix}{misc}.o // Intermediate objects
=head1 ENVIRONMENT =head1 ENVIRONMENT
@@ -1592,46 +1688,47 @@ simulation executable.
The user must write the top level of the simulation. Here's a simple The user must write the top level of the simulation. Here's a simple
example: example:
#include <verilated.h> // Defines common routines #include <verilated.h> // Defines common routines
#include "Vtop.h" // From Verilating "top.v" #include <iostream> // Need std::cout
#include "Vtop.h" // From Verilating "top.v"
Vtop *top; // Instantiation of module Vtop *top; // Instantiation of module
vluint64_t main_time = 0; // Current simulation time vluint64_t main_time = 0; // Current simulation time
// This is a 64-bit integer to reduce wrap over issues and // This is a 64-bit integer to reduce wrap over issues and
// allow modulus. You can also use a double, if you wish. // allow modulus. You can also use a double, if you wish.
double sc_time_stamp () { // Called by $time in Verilog double sc_time_stamp () { // Called by $time in Verilog
return main_time; // converts to double, to match return main_time; // converts to double, to match
// what SystemC does // what SystemC does
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv); // Remember args Verilated::commandArgs(argc, argv); // Remember args
top = new Vtop; // Create instance top = new Vtop; // Create instance
top->reset_l = 0; // Set some inputs top->reset_l = 0; // Set some inputs
while (!Verilated::gotFinish()) { while (!Verilated::gotFinish()) {
if (main_time > 10) { if (main_time > 10) {
top->reset_l = 1; // Deassert reset top->reset_l = 1; // Deassert reset
} }
if ((main_time % 10) == 1) { if ((main_time % 10) == 1) {
top->clk = 1; // Toggle clock top->clk = 1; // Toggle clock
} }
if ((main_time % 10) == 6) { if ((main_time % 10) == 6) {
top->clk = 0; top->clk = 0;
} }
top->eval(); // Evaluate model top->eval(); // Evaluate model
cout << top->out << endl; // Read a output cout << top->out << endl; // Read a output
main_time++; // Time passes... main_time++; // Time passes...
} }
top->final(); // Done simulating top->final(); // Done simulating
// // (Though this example doesn't get here) // // (Though this example doesn't get here)
delete top; delete top;
} }
Note signals are read and written as member variables of the lower module. Note signals are read and written as member variables of the lower module.
You call the eval() method to evaluate the model. When the simulation is You call the eval() method to evaluate the model. When the simulation is
@@ -1847,7 +1944,7 @@ accesses the above would be:
if (!vh1) { error... } if (!vh1) { error... }
const char* name = vpi_get_str(vpiName, vh1); const char* name = vpi_get_str(vpiName, vh1);
printf("Module name: %s\n"); // Prints "readme" printf("Module name: %s\n"); // Prints "readme"
s_vpi_value v; s_vpi_value v;
v.format = vpiIntVal; v.format = vpiIntVal;
vpi_get_value(vh1, &v); vpi_get_value(vh1, &v);
@@ -1861,8 +1958,8 @@ VerilatedVpi::callValueCbs().
... ...
while (time passes) { while (time passes) {
... ...
topp->eval(); topp->eval();
VerilatedVpi::callValueCbs(); VerilatedVpi::callValueCbs();
} }
@@ -1906,10 +2003,10 @@ underneath NC:
cd obj_dir cd obj_dir
ncsc_run \ ncsc_run \
sc_main.cpp \ sc_main.cpp \
Vour__ALLcls.cpp \ Vour__ALLcls.cpp \
Vour__ALLsup.cpp \ Vour__ALLsup.cpp \
verilated.cpp verilated.cpp
For larger designs you'll want to automate this using makefiles, which pull For larger designs you'll want to automate this using makefiles, which pull
the names of the .cpp files to compile in from the make variables generated the names of the .cpp files to compile in from the make variables generated
@@ -1961,8 +2058,9 @@ numbers (or all lines if omitted).
With lint_off using '*' will override any lint_on directives in the source, With lint_off using '*' will override any lint_on directives in the source,
i.e. the warning will still not be printed. i.e. the warning will still not be printed.
If the -msg is omitted, all lint warnings are enabled/disabled. This will If the -msg is omitted, all lint warnings (see list in -Wno-lint) are
override all later lint warning enables for the specified region. enabled/disabled. This will override all later lint warning enables for
the specified region.
=item tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]] =item tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
@@ -2303,6 +2401,14 @@ reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself. be pure; they cannot reference any variables outside the task itself.
=item /*verilator public*/ (parameter)
Used after a parameter declaration to indicate the emitted C code should
have the parameter values visible. Due to C++ language restrictions, this
may only be used on 64-bit or narrower integral enumerations.
parameter [2:0] PARAM /*verilator public*/ = 2'b0;
=item /*verilator public*/ (typedef enum) =item /*verilator public*/ (typedef enum)
Used after an enum typedef declaration to indicate the emitted C code Used after an enum typedef declaration to indicate the emitted C code
@@ -2426,16 +2532,24 @@ such as $stop, $finish and $display. That is, you cannot use hierarchical
references, events or similar features of the Verilog language. It also references, events or similar features of the Verilog language. It also
simulates as Synopsys's Design Compiler would; namely a block of the form: simulates as Synopsys's Design Compiler would; namely a block of the form:
always @ (x) y = x & z; always @ (x) y = x & z;
This will recompute y when there is even a potential for change in x or a This will recompute y when there is even a potential for change in x or a
change in z, that is when the flops computing x or z evaluate (which is change in z, that is when the flops computing x or z evaluate (which is
what Design Compiler will synthesize.) A compliant simulator would only what Design Compiler will synthesize.) A compliant simulator would only
calculate y if x changes. Use verilog-mode's /*AS*/ or Verilog 2001's calculate y if x changes. Use Verilog-Mode's /*AS*/ or Verilog 2001's
always @* to reduce missing activity items. Avoid putting $displays in always @* to reduce missing activity items. Avoid putting $displays in
combo blocks, as they may print multiple times when not desired, even on combo blocks, as they may print multiple times when not desired, even on
compliant simulators as event ordering is not specified. compliant simulators as event ordering is not specified.
=head2 Signal Naming
To avoid conflicts with C symbol naming, any character in a signal name
that is not alphanumeric nor a single underscore will be replaced by __0hh
where hh is the hex code of the character. To avoid conflicts with
Verilator's internal symbols, any double underscore are replaced with
___05F (5F is the hex code of an underscore.)
=head2 Bind =head2 Bind
Verilator only supports "bind" to a target module name, not an instance Verilator only supports "bind" to a target module name, not an instance
@@ -2514,7 +2628,7 @@ variables are initialized to a random value.
Event driven simulators will generally trigger an edge on a transition from X Event driven simulators will generally trigger an edge on a transition from X
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
are initialized to zero, Verilator will not trigger an initial negedge. Some are initialized to zero, Verilator will not trigger an initial negedge. Some
code (particulary for reset) may rely on X->0 triggering an edge. Verilator code (particularly for reset) may rely on X->0 triggering an edge. Verilator
provides a switch (see --x-initial-edge) to enable this behavior. Comparing provides a switch (see --x-initial-edge) to enable this behavior. Comparing
runs with and without this switch will find such problems. runs with and without this switch will find such problems.
@@ -2567,7 +2681,7 @@ clock_enable*/ attribute.
=head2 Ranges must be big-bit-endian =head2 Ranges must be big-bit-endian
Bit ranges must be numbered with the MSB being numbered greater or the same Bit ranges must be numbered with the MSB being numbered greater or the same
as the LSB. Little-bit-endian busses [0:15] are not supported as they as the LSB. Little-bit-endian buses [0:15] are not supported as they
aren't easily made compatible with C++. aren't easily made compatible with C++.
=head2 Gate Primitives =head2 Gate Primitives
@@ -2766,13 +2880,17 @@ when displaying all times, model wide.
=head1 ERRORS AND WARNINGS =head1 ERRORS AND WARNINGS
Warnings may be disabled in two ways. First, when the warning is Warnings may be disabled in three ways. First, when the warning is
printed it will include a warning code. Simply surround the offending printed it will include a warning code. Simply surround the offending
line with a warn_off/warn_on pair: line with a warn_off/warn_on pair:
// verilator lint_off UNSIGNED // verilator lint_off UNSIGNED
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop; if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
// verilator lint_on UNSIGNED // verilator lint_on UNSIGNED
Second, warnings may be disabled using a configuration file with a lint_off
command. This is useful when a script is suppressing warnings and the
Verilog source should not be changed.
Warnings may also be globally disabled by invoking Verilator with the Warnings may also be globally disabled by invoking Verilator with the
C<-Wno-I<warning>> switch. This should be avoided, as it removes all C<-Wno-I<warning>> switch. This should be avoided, as it removes all
@@ -2836,13 +2954,12 @@ Simply use a different register for the flop:
always @* foo[0] = foo_flopped[0]; always @* foo[0] = foo_flopped[0];
always @* foo[1] = ... always @* foo[1] = ...
This is good coding practice anyways.
It is also possible to disable this error when one of the assignments is It is also possible to disable this error when one of the assignments is
inside a public task. inside a public task.
Ignoring this warning may make Verilator simulations differ from other This is not illegal in SystemVerilog, but a violation of good coding
simulators. practice. Verilator reports this as an error, because ignoring this warning
may make Verilator simulations differ from other simulators.
=item BLKSEQ =item BLKSEQ
@@ -2866,10 +2983,10 @@ were used, the simulator would have to copy large arrays every cycle. (In
smaller loops, loop unrolling allows the delayed assignment to work, though smaller loops, loop unrolling allows the delayed assignment to work, though
it's a bit slower than a non-delayed assignment.) Here's an example it's a bit slower than a non-delayed assignment.) Here's an example
always @ (posedge clk) always @ (posedge clk)
if (~reset_l) begin if (~reset_l) begin
for (i=0; i<`ARRAY_SIZE; i++) begin for (i=0; i<`ARRAY_SIZE; i++) begin
array[i] = 0; // Non-delayed for verilator array[i] = 0; // Non-delayed for verilator
end end
This message is only seen on large or complicated loops because Verilator This message is only seen on large or complicated loops because Verilator
@@ -3327,9 +3444,9 @@ A recommended style for unused nets is to put at the bottom of a file code
similar to the following: similar to the following:
wire _unused_ok = &{1'b0, wire _unused_ok = &{1'b0,
sig_not_used_a, sig_not_used_a,
sig_not_used_yet_b, // To be fixed sig_not_used_yet_b, // To be fixed
1'b0}; 1'b0};
The reduction AND and constant zeros mean the net will always be zero, so The reduction AND and constant zeros mean the net will always be zero, so
won't use simulation time. The redundant leading and trailing zeros avoid won't use simulation time. The redundant leading and trailing zeros avoid
@@ -3366,11 +3483,11 @@ unwidthed. Verilator considers zero to be any width needed.
Concatenate leading zeros when doing arithmetic. In the statement Concatenate leading zeros when doing arithmetic. In the statement
wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0]; wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0];
The best fix, which clarifies intent and will also make all tools happy is: The best fix, which clarifies intent and will also make all tools happy is:
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]}; wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
Ignoring this warning will only suppress the lint check, it will simulate Ignoring this warning will only suppress the lint check, it will simulate
correctly. correctly.
@@ -3568,7 +3685,7 @@ trace file if you want all data to land in the same output file.
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd"); tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
... ...
sc_start(1); sc_start(1);
... ...
tfp->close(); tfp->close();
} }
@@ -3915,7 +4032,7 @@ Thanks to them, and all those we've missed including above.
The latest version is available from L<http://www.veripool.org/>. The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0. License Version 2.0.
+2 -2
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0; if 0;
###################################################################### ######################################################################
# #
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you # Copyright 2003-2017 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -271,7 +271,7 @@ Specifies a module search directory.
The latest version is available from L<http://www.veripool.org/>. The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0. License Version 2.0.
+1 -1
View File
@@ -235,7 +235,7 @@ Do not show differences in line numbering.
The latest version is available from L<http://www.veripool.org/verilator>. The latest version is available from L<http://www.veripool.org/verilator>.
Copyright 2005-2015 by Wilson Snyder. This package is free software; you can Copyright 2005-2017 by Wilson Snyder. This package is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser 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. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0; if 0;
# DESCRIPTION: Print include statements for each ARGV # DESCRIPTION: Print include statements for each ARGV
# #
# Copyright 2003-2015 by Wilson Snyder. This package is free software; you can # Copyright 2003-2017 by Wilson Snyder. This package is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser # 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. # General Public License Version 3 or the Perl Artistic License Version 2.0.
###################################################################### ######################################################################
+1 -1
View File
@@ -222,7 +222,7 @@ Displays this message and program version and exits.
The latest version is available from L<http://www.veripool.org/>. The latest version is available from L<http://www.veripool.org/>.
Copyright 2007-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2007-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser 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. General Public License Version 3 or the Perl Artistic License Version 2.0.
+17 -3
View File
@@ -1,12 +1,12 @@
# DESCRIPTION: Process this file with autoconf to produce a configure script. # DESCRIPTION: Process this file with autoconf to produce a configure script.
# #
# Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can # Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser # 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. # General Public License Version 3 or the Perl Artistic License Version 2.0.
#AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel]) #AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.878 2015-11-01]) AC_INIT([Verilator],[3.902 2017-04-02])
# When releasing, also update header of Changes file # When releasing, also update header of Changes file
AC_CONFIG_HEADER(src/config_build.h) AC_CONFIG_HEADER(src/config_build.h)
@@ -15,7 +15,7 @@ AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk incl
AC_MSG_RESULT([configuring for $PACKAGE_STRING]) AC_MSG_RESULT([configuring for $PACKAGE_STRING])
# Special Substitutions - CFG_WITH_DEFENV # Special Substitutions - CFG_WITH_DEFENV
AC_MSG_CHECKING(whether to disable hardcoded paths) AC_MSG_CHECKING(whether to use hardcoded paths)
AC_ARG_ENABLE([defenv], AC_ARG_ENABLE([defenv],
[AS_HELP_STRING([--disable-defenv], [AS_HELP_STRING([--disable-defenv],
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])], [disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
@@ -120,6 +120,18 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
fi fi
fi], fi],
[_my_result=no]) [_my_result=no])
# GCC is annoying, trying to be helpful, it postpones unknown -Wno-
# options if there's no error We want to see them regardless, so try
# forcing an error and see if we get a gcc warning
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[an_error "intentional-error-for-test.h"
]],[])],
[], # Ignore ok exit
[if test -s conftest.err; then
if grep -e "$2" conftest.err >/dev/null; then
_my_result=no
fi
fi])
AC_MSG_RESULT($_my_result) AC_MSG_RESULT($_my_result)
if test "$_my_result" = "yes" ; then if test "$_my_result" = "yes" ; then
$1="$$1 $2" $1="$$1 $2"
@@ -130,7 +142,9 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
# Flags for compiling Verilator internals including parser # Flags for compiling Verilator internals including parser
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks)
AC_SUBST(CFG_CXXFLAGS_SRC) AC_SUBST(CFG_CXXFLAGS_SRC)
# Flags for compiling Verilator parser # Flags for compiling Verilator parser
+118 -79
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -374,7 +374,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
} else { } else {
lwp = va_arg(ap,WDataInP); lwp = va_arg(ap,WDataInP);
ld = lwp[0]; ld = lwp[0];
if (fmt == 'u' || fmt == 'd') fmt = 'x'; // Not supported, but show something if (fmt == 'd' || fmt == '#') fmt = 'x'; // Not supported, but show something
} }
int lsb=lbits-1; int lsb=lbits-1;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--; if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
@@ -404,7 +404,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += tmp; output += tmp;
break; break;
} }
case 'u': { // Unsigned decimal case '#': { // Unsigned decimal
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld); int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
int needmore = width-digits; int needmore = width-digits;
if (needmore>0) { if (needmore>0) {
@@ -438,6 +438,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0'; output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
} }
break; break;
break;
case 'o': case 'o':
for (; lsb>=0; lsb--) { for (; lsb>=0; lsb--) {
lsb = (lsb / 3) * 3; // Next digit lsb = (lsb / 3) * 3; // Next digit
@@ -450,6 +451,28 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0)); + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
} }
break; break;
case 'u': // Packed 2-state
output.reserve(output.size() + 4*VL_WORDS_I(lbits));
for (int i=0; i<VL_WORDS_I(lbits); i++) {
output += (char)((lwp[i] >> 0) & 0xff);
output += (char)((lwp[i] >> 8) & 0xff);
output += (char)((lwp[i] >> 16) & 0xff);
output += (char)((lwp[i] >> 24) & 0xff);
}
case 'z': // Packed 4-state
output.reserve(output.size() + 8*VL_WORDS_I(lbits));
for (int i=0; i<VL_WORDS_I(lbits); i++) {
output += (char)((lwp[i] >> 0) & 0xff);
output += (char)((lwp[i] >> 8) & 0xff);
output += (char)((lwp[i] >> 16) & 0xff);
output += (char)((lwp[i] >> 24) & 0xff);
output += "\0\0\0\0"; // No tristate
}
case 'v': // Strength; assume always strong
for (lsb=lbits-1; lsb>=0; lsb--) {
if ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) output += "St1 ";
else output += "St0 ";
}
case 'x': case 'x':
for (; lsb>=0; lsb--) { for (; lsb>=0; lsb--) {
lsb = (lsb / 4) * 4; // Next digit lsb = (lsb / 4) * 4; // Next digit
@@ -627,13 +650,14 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_skipspace(fp,floc,fromp,fstr); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
// cppcheck-suppress unusedStructMember // It's used
union { double r; vlsint64_t ld; } u; union { double r; vlsint64_t ld; } u;
u.r = strtod(tmp, NULL); u.r = strtod(tmp, NULL);
VL_SET_WQ(owp,u.ld); VL_SET_WQ(owp,u.ld);
break; break;
} }
case 't': // FALLTHRU // Time case 't': // FALLTHRU // Time
case 'u': { // Unsigned decimal case '#': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp,fstr); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
@@ -932,11 +956,18 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilenamep, void* memp, IData start, IData end) { WDataInP ofilenamep, void* memp, IData start, IData end) {
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep); _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
FILE* fp = fopen(ofilenamez, "r"); string ofilenames(ofilenamez);
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
}
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const string& ofilenamep, void* memp, IData start, IData end) {
if (fnwords) {}
FILE* fp = fopen(ofilenamep.c_str(), "r");
if (VL_UNLIKELY(!fp)) { if (VL_UNLIKELY(!fp)) {
// We don't report the Verilog source filename as it slow to have to pass it down // We don't report the Verilog source filename as it slow to have to pass it down
vl_fatal (ofilenamez, 0, "", "$readmem file not found"); vl_fatal (ofilenamep.c_str(), 0, "", "$readmem file not found");
return; return;
} }
// Prep for reading // Prep for reading
IData addr = start; IData addr = start;
@@ -951,81 +982,81 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
// We process a character at a time, as then we don't need to deal // We process a character at a time, as then we don't need to deal
// with changing buffer sizes dynamically, etc. // with changing buffer sizes dynamically, etc.
while (1) { while (1) {
int c = fgetc(fp); int c = fgetc(fp);
if (VL_UNLIKELY(c==EOF)) break; if (VL_UNLIKELY(c==EOF)) break;
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc); //printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; } if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; } else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
// Skip // comments and detect /* comments // Skip // comments and detect /* comments
else if (ignore_to_cmt && lastc=='*' && c=='/') { else if (ignore_to_cmt && lastc=='*' && c=='/') {
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false; ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
} else if (!ignore_to_eol && !ignore_to_cmt) { } else if (!ignore_to_eol && !ignore_to_cmt) {
if (lastc=='/' && c=='*') { ignore_to_cmt = true; } if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
else if (lastc=='/' && c=='/') { ignore_to_eol = true; } else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
else if (c=='/') {} // Part of /* or // else if (c=='/') {} // Part of /* or //
else if (c=='_') {} else if (c=='_') {}
else if (c=='@') { reading_addr = true; innum=false; needinc=false; } else if (c=='@') { reading_addr = true; innum=false; needinc=false; }
// Check for hex or binary digits as file format requests // Check for hex or binary digits as file format requests
else if (isxdigit(c)) { else if (isxdigit(c)) {
c = tolower(c); c = tolower(c);
int value = (c >= 'a' ? (c-'a'+10) : (c-'0')); int value = (c >= 'a' ? (c-'a'+10) : (c-'0'));
if (!innum) { // Prep for next number if (!innum) { // Prep for next number
if (needinc) { addr++; needinc=false; } if (needinc) { addr++; needinc=false; }
} }
if (reading_addr) { if (reading_addr) {
// Decode @ addresses // Decode @ addresses
if (!innum) addr=0; if (!innum) addr=0;
addr = (addr<<4) + value; addr = (addr<<4) + value;
} else { } else {
needinc = true; needinc = true;
//printf(" Value width=%d @%x = %c\n", width, addr, c); //printf(" Value width=%d @%x = %c\n", width, addr, c);
if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) { if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) {
vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array"); vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array");
} else { } else {
int entry = addr - array_lsb; int entry = addr - array_lsb;
QData shift = hex ? VL_ULL(4) : VL_ULL(1); QData shift = hex ? VL_ULL(4) : VL_ULL(1);
// Shift value in // Shift value in
if (width<=8) { if (width<=8) {
CData* datap = &((CData*)(memp))[entry]; CData* datap = &((CData*)(memp))[entry];
if (!innum) { *datap = 0; } if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width); *datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width<=16) { } else if (width<=16) {
SData* datap = &((SData*)(memp))[entry]; SData* datap = &((SData*)(memp))[entry];
if (!innum) { *datap = 0; } if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width); *datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width<=VL_WORDSIZE) { } else if (width<=VL_WORDSIZE) {
IData* datap = &((IData*)(memp))[entry]; IData* datap = &((IData*)(memp))[entry];
if (!innum) { *datap = 0; } if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width); *datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width<=VL_QUADSIZE) { } else if (width<=VL_QUADSIZE) {
QData* datap = &((QData*)(memp))[entry]; QData* datap = &((QData*)(memp))[entry];
if (!innum) { *datap = 0; } if (!innum) { *datap = 0; }
*datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width); *datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width);
} else { } else {
WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ]; WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ];
if (!innum) { VL_ZERO_RESET_W(width, datap); } if (!innum) { VL_ZERO_RESET_W(width, datap); }
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift); _VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
datap[0] |= value; datap[0] |= value;
} }
if (VL_UNLIKELY(value>=(1<<shift))) { if (VL_UNLIKELY(value>=(1<<shift))) {
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters"); vl_fatal (ofilenamep.c_str(), linenum, "", "$readmemb (binary) file contains hex characters");
} }
} }
} }
innum = true; innum = true;
} }
else { else {
vl_fatal (ofilenamez, linenum, "", "$readmem file syntax error"); vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file syntax error");
} }
} }
lastc = c; lastc = c;
} }
if (needinc) { addr++; needinc=false; } if (needinc) { addr++; needinc=false; }
// Final checks // Final checks
fclose(fp); fclose(fp);
if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) { if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address"); vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file ended before specified ending-address");
} }
} }
@@ -1046,6 +1077,14 @@ IData VL_TESTPLUSARGS_I(const char* formatp) {
else return 1; else return 1;
} }
IData VL_VALUEPLUSARGS_IN(int, const char* prefixp, char, string& ldr) {
const string& match = VerilatedImp::argPlusMatch(prefixp);
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
if (match == "") return 0;
ldr = string(dp);
return 1;
}
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) { IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
const string& match = VerilatedImp::argPlusMatch(prefixp); const string& match = VerilatedImp::argPlusMatch(prefixp);
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp); const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
@@ -1187,7 +1226,7 @@ VerilatedModule::VerilatedModule(const char* namep)
} }
VerilatedModule::~VerilatedModule() { VerilatedModule::~VerilatedModule() {
if (m_namep) free((void*)m_namep); m_namep=NULL; if (m_namep) { free((void*)m_namep); m_namep=NULL; }
} }
//====================================================================== //======================================================================
@@ -1301,7 +1340,7 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const {
return NULL; return NULL;
} }
void* VerilatedScope::exportFindNullError(int funcnum) const { void* VerilatedScope::exportFindNullError(int funcnum) {
// Slowpath - Called only when find has failed // Slowpath - Called only when find has failed
string msg = (string("Testbench C called '") string msg = (string("Testbench C called '")
+VerilatedImp::exportName(funcnum) +VerilatedImp::exportName(funcnum)
+9 -8
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -201,16 +201,16 @@ public: // But internals only - called from VerilatedModule's
inline VerilatedSyms* symsp() const { return m_symsp; } inline VerilatedSyms* symsp() const { return m_symsp; }
VerilatedVar* varFind(const char* namep) const; VerilatedVar* varFind(const char* namep) const;
VerilatedVarNameMap* varsp() const { return m_varsp; } VerilatedVarNameMap* varsp() const { return m_varsp; }
void* exportFindError(int funcnum) const;
void* exportFindNullError(int funcnum) const;
void scopeDump() const; void scopeDump() const;
inline void* exportFind(int funcnum) const { void* exportFindError(int funcnum) const;
if (VL_UNLIKELY(!this)) return exportFindNullError(funcnum); static void* exportFindNullError(int funcnum);
if (VL_LIKELY(funcnum < m_funcnumMax)) { static inline void* exportFind(const VerilatedScope* scopep, int funcnum) {
if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum);
if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) {
// m_callbacksp must be declared, as Max'es are > 0 // m_callbacksp must be declared, as Max'es are > 0
return m_callbacksp[funcnum]; return scopep->m_callbacksp[funcnum];
} else { } else {
return exportFindError(funcnum); return scopep->exportFindError(funcnum);
} }
} }
}; };
@@ -288,6 +288,7 @@ public:
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs /// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
static void commandArgs(int argc, const char** argv); static void commandArgs(int argc, const char** argv);
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); } static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
static void commandArgsAdd(int argc, const char** argv);
static CommandArgValues* getCommandArgs() {return &s_args;} static CommandArgValues* getCommandArgs() {return &s_args;}
/// Match plusargs with a given prefix. Returns static char* valid only for a single call /// Match plusargs with a given prefix. Returns static char* valid only for a single call
static const char* commandArgsPlusMatch(const char* prefixp); static const char* commandArgsPlusMatch(const char* prefixp);
+16 -16
View File
@@ -2,7 +2,7 @@
###################################################################### ######################################################################
# DESCRIPTION: Makefile commands for all verilated target files # DESCRIPTION: Makefile commands for all verilated target files
# #
# Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can # Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser # 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. # General Public License Version 3 or the Perl Artistic License Version 2.0.
###################################################################### ######################################################################
@@ -43,8 +43,9 @@ VK_CPPFLAGS_ALWAYS += \
-I$(VERILATOR_ROOT)/include \ -I$(VERILATOR_ROOT)/include \
-I$(VERILATOR_ROOT)/include/vltstd \ -I$(VERILATOR_ROOT)/include/vltstd \
-DVL_PRINTF=printf \ -DVL_PRINTF=printf \
-DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \ -DVM_COVERAGE=$(VM_COVERAGE) \
-DVM_SC=$(VM_SC) \
-DVM_TRACE=$(VM_TRACE) \
$(CFG_CXXFLAGS_NO_UNUSED) \ $(CFG_CXXFLAGS_NO_UNUSED) \
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
@@ -123,19 +124,10 @@ else
preproc: preproc:
endif endif
#######################################################################
##### SystemC w/o SystemPerl builds
ifeq ($(VM_SC),1)
LIBS += -lm -lstdc++
endif
####################################################################### #######################################################################
##### C/H builds ##### C/H builds
ifeq ($(VM_PCLI),1) LIBS += -lm -lstdc++
LIBS += -lm -lstdc++
endif
####################################################################### #######################################################################
# Overall Objects Linking # Overall Objects Linking
@@ -171,16 +163,24 @@ $(VM_PREFIX)__ALL.a: $(VK_OBJS)
###################################################################### ######################################################################
### Compile rules ### Compile rules
#Default rule embedded in make: (Not defined so user makefiles can override it) ifneq ($(VM_DEFAULT_RULES),0)
#.cpp.o:
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
$(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp $(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $< $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
$(VM_PREFIX)__ALLcls.o: $(VM_PREFIX)__ALLcls.cpp $(VM_PREFIX)__ALLcls.o: $(VM_PREFIX)__ALLcls.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $< $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
$(VM_PREFIX)%__Slow.o: $(VM_PREFIX)%__Slow.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
$(VM_PREFIX)%.o: $(VM_PREFIX)%.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
endif
#Default rule embedded in make:
#.cpp.o:
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
###################################################################### ######################################################################
### Debugging ### Debugging
+1 -1
View File
@@ -4,7 +4,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can // Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+4 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can // Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -61,8 +61,11 @@ inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs
} }
extern IData VL_FOPEN_NI(const string& filename, IData mode); extern IData VL_FOPEN_NI(const string& filename, IData mode);
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const string& ofilename, void* memp, IData start, IData end);
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...); extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...); extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
extern string VL_SFORMATF_NX(const char* formatp, ...); extern string VL_SFORMATF_NX(const char* formatp, ...);
extern IData VL_VALUEPLUSARGS_IN(int rbits, const char* prefixp, char fmt, string& ldr);
#endif // Guard #endif // Guard
+6 -2
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can // Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -92,7 +92,11 @@ public: // But only for verilated*.cpp
// METHODS - arguments // METHODS - arguments
static void commandArgs(int argc, const char** argv) { static void commandArgs(int argc, const char** argv) {
s_s.m_argVec.clear(); s_s.m_argVec.clear(); // Always clear
commandArgsAdd(argc, argv);
}
static void commandArgsAdd(int argc, const char** argv) {
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]); for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
} }
+2 -2
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -201,7 +201,7 @@ void VerilatedRestore::fill() {
if (VL_UNLIKELY(!isOpen())) return; if (VL_UNLIKELY(!isOpen())) return;
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed) // Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
vluint8_t* rp = m_bufp; vluint8_t* rp = m_bufp;
for (vluint8_t* sp=m_cp; rp < m_endp;) *rp++ = *sp++; // Overlaps for (vluint8_t* sp=m_cp; sp < m_endp;) *rp++ = *sp++; // Overlaps
m_endp = m_bufp + (m_endp - m_cp); m_endp = m_bufp + (m_endp - m_cp);
m_cp = m_bufp; // Reset buffer m_cp = m_bufp; // Reset buffer
// Read into buffer starting at m_endp // Read into buffer starting at m_endp
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2012-2015 by Wilson Snyder. This program is free software; // Copyright 2012-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can // Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2015 by Wilson Snyder. This program is free software; // Copyright 2001-2017 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
+4 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can // Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -26,6 +26,9 @@
//========================================================================= //=========================================================================
#if VM_SC
# include "verilated_sc.h"
#endif
#include "verilated.h" #include "verilated.h"
#include "verilated_vpi.h" #include "verilated_vpi.h"
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can // Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -785,7 +785,7 @@ in C<src/Makefile_obj.in> and reconfigure.
The latest version is available from L<http://www.veripool.org/>. The latest version is available from L<http://www.veripool.org/>.
Copyright 2008-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2008-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser 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. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you # Copyright 2007-2017 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you # Copyright 2007-2017 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+1 -1
View File
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser 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. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser 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. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you # Copyright 2007-2017 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+3 -2
View File
@@ -115,7 +115,8 @@ sub write_verilog {
sub cleanenv { sub cleanenv {
foreach my $var (keys %ENV) { foreach my $var (keys %ENV) {
if ($var eq "VERILATOR_ROOT") { if ($var eq "VERILATOR_ROOT"
|| $var eq "VERILATOR_INCLUDE") {
print "unset $var # Was '$ENV{$var}'\n"; print "unset $var # Was '$ENV{$var}'\n";
delete $ENV{$var} delete $ENV{$var}
} }
@@ -183,7 +184,7 @@ Runs a specific test stage (see the script).
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2009-2015 by Wilson Snyder. This package is free software; you Copyright 2009-2017 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2015 by Wilson Snyder. This package is free software; you Copyright 2005-2017 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2007-2015 by Wilson Snyder. This package is free software; you Copyright 2007-2017 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2015 by Wilson Snyder. This package is free software; you Copyright 2005-2017 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2015 by Wilson Snyder. This package is free software; you Copyright 2005-2017 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser 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. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,6 +1,6 @@
# DESCRIPTION: Verilator: GDB startup file with useful defines # DESCRIPTION: Verilator: GDB startup file with useful defines
# #
# Copyright 2012-2015 by Wilson Snyder. This program is free software; you can # Copyright 2012-2017 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+3 -1
View File
@@ -7,7 +7,7 @@
# #
#***************************************************************************** #*****************************************************************************
# #
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can # Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -46,6 +46,8 @@ obj_opt:
obj_dbg: obj_dbg:
mkdir $@ mkdir $@
.SUFFIXES:
.PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg .PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
opt: ../verilator_bin opt: ../verilator_bin
+7 -2
View File
@@ -7,7 +7,7 @@
# #
#***************************************************************************** #*****************************************************************************
# #
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can # Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -99,6 +99,8 @@ CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
#CPPFLAGS += -pedantic-errors #CPPFLAGS += -pedantic-errors
else
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
endif endif
CPPFLAGSWALL = $(CPPFLAGS) CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER) CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
@@ -164,6 +166,7 @@ RAW_OBJS = \
V3Begin.o \ V3Begin.o \
V3Branch.o \ V3Branch.o \
V3Broken.o \ V3Broken.o \
V3CCtors.o \
V3Case.o \ V3Case.o \
V3Cast.o \ V3Cast.o \
V3Cdc.o \ V3Cdc.o \
@@ -299,7 +302,7 @@ serial:: V3Ast__gen_classes.h V3ParseBison.c
serial_vlcov:: vlcovgen.d serial_vlcov:: vlcovgen.d
vlcovgen.d: $(VLCOVGEN) $(srcdir)/include/verilated_cov_key.h vlcovgen.d: $(VLCOVGEN) $(srcdir)/../include/verilated_cov_key.h
$(PERL) $(VLCOVGEN) --srcdir $(srcdir) $(PERL) $(VLCOVGEN) --srcdir $(srcdir)
touch $@ touch $@
@@ -327,6 +330,8 @@ V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX) V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
$(PERL) $(FLEXFIX) V3PreLex <$< >$@ $(PERL) $(FLEXFIX) V3PreLex <$< >$@
.SUFFIXES:
###################################################################### ######################################################################
###################################################################### ######################################################################
+26 -24
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -73,7 +73,7 @@ private:
m_scopep->addActivep(nodep); m_scopep->addActivep(nodep);
} }
// VISITORS // VISITORS
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep) {
m_scopep = nodep; m_scopep = nodep;
m_iActivep = NULL; m_iActivep = NULL;
m_cActivep = NULL; m_cActivep = NULL;
@@ -81,15 +81,15 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Don't clear scopep, the namer persists beyond this visit // Don't clear scopep, the namer persists beyond this visit
} }
virtual void visit(AstSenTree* nodep, AstNUser*) { virtual void visit(AstSenTree* nodep) {
// Simplify sensitivity list // Simplify sensitivity list
V3Const::constifyExpensiveEdit(nodep); VL_DANGLING(nodep); V3Const::constifyExpensiveEdit(nodep); VL_DANGLING(nodep);
} }
// Empty visitors, speed things up // Empty visitors, speed things up
virtual void visit(AstNodeStmt* nodep, AstNUser*) { } virtual void visit(AstNodeStmt* nodep) { }
//-------------------- //--------------------
// Default // Default
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
// Default: Just iterate // Default: Just iterate
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -169,7 +169,7 @@ private:
AstNode* m_alwaysp; // Always we're under AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign AstNode* m_assignp; // In assign
// VISITORS // VISITORS
virtual void visit(AstAssignDly* nodep, AstNUser*) { virtual void visit(AstAssignDly* nodep) {
if (m_check != CT_SEQ) { if (m_check != CT_SEQ) {
// Convert to a non-delayed assignment // Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl); UINFO(5," ASSIGNDLY "<<nodep<<endl);
@@ -187,7 +187,7 @@ private:
nodep->deleteTree(); VL_DANGLING(nodep); nodep->deleteTree(); VL_DANGLING(nodep);
} }
} }
virtual void visit(AstAssign* nodep, AstNUser*) { virtual void visit(AstAssign* nodep) {
if (m_check == CT_SEQ) { if (m_check == CT_SEQ) {
AstNode* las = m_assignp; AstNode* las = m_assignp;
m_assignp = nodep; m_assignp = nodep;
@@ -195,7 +195,7 @@ private:
m_assignp = las; m_assignp = las;
} }
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
AstVar* varp=nodep->varp(); AstVar* varp=nodep->varp();
if (m_check == CT_SEQ if (m_check == CT_SEQ
&& m_assignp && m_assignp
@@ -214,7 +214,7 @@ private:
} }
} }
//-------------------- //--------------------
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -244,7 +244,7 @@ private:
bool m_itemSequent; // Found a SenItem sequential bool m_itemSequent; // Found a SenItem sequential
// VISITORS // VISITORS
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep) {
// Create required actives and add to scope // Create required actives and add to scope
UINFO(4," SCOPE "<<nodep<<endl); UINFO(4," SCOPE "<<nodep<<endl);
// Clear last scope's names, and collect this scope's existing names // Clear last scope's names, and collect this scope's existing names
@@ -252,10 +252,10 @@ private:
m_scopeFinalp = NULL; m_scopeFinalp = NULL;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstActive* nodep, AstNUser*) { virtual void visit(AstActive* nodep) {
// Actives are being formed, so we can ignore any already made // Actives are being formed, so we can ignore any already made
} }
virtual void visit(AstInitial* nodep, AstNUser*) { virtual void visit(AstInitial* nodep) {
// Relink to IACTIVE, unless already under it // Relink to IACTIVE, unless already under it
UINFO(4," INITIAL "<<nodep<<endl); UINFO(4," INITIAL "<<nodep<<endl);
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL); ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
@@ -263,28 +263,28 @@ private:
nodep->unlinkFrBack(); nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep); wantactivep->addStmtsp(nodep);
} }
virtual void visit(AstAssignAlias* nodep, AstNUser*) { virtual void visit(AstAssignAlias* nodep) {
// Relink to CACTIVE, unless already under it // Relink to CACTIVE, unless already under it
UINFO(4," ASSIGNW "<<nodep<<endl); UINFO(4," ASSIGNW "<<nodep<<endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline()); AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack(); nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep); wantactivep->addStmtsp(nodep);
} }
virtual void visit(AstAssignW* nodep, AstNUser*) { virtual void visit(AstAssignW* nodep) {
// Relink to CACTIVE, unless already under it // Relink to CACTIVE, unless already under it
UINFO(4," ASSIGNW "<<nodep<<endl); UINFO(4," ASSIGNW "<<nodep<<endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline()); AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack(); nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep); wantactivep->addStmtsp(nodep);
} }
virtual void visit(AstCoverToggle* nodep, AstNUser*) { virtual void visit(AstCoverToggle* nodep) {
// Relink to CACTIVE, unless already under it // Relink to CACTIVE, unless already under it
UINFO(4," COVERTOGGLE "<<nodep<<endl); UINFO(4," COVERTOGGLE "<<nodep<<endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline()); AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack(); nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep); wantactivep->addStmtsp(nodep);
} }
virtual void visit(AstFinal* nodep, AstNUser*) { virtual void visit(AstFinal* nodep) {
// Relink to CFUNC for the final // Relink to CFUNC for the final
UINFO(4," FINAL "<<nodep<<endl); UINFO(4," FINAL "<<nodep<<endl);
if (!nodep->bodysp()) { // Empty, Kill it. if (!nodep->bodysp()) { // Empty, Kill it.
@@ -329,7 +329,9 @@ private:
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*) if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
if (combo && sequent) { if (combo && sequent) {
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list"); if (!v3Global.opt.bboxUnsup()) {
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
}
sequent = false; sequent = false;
} }
@@ -370,7 +372,7 @@ private:
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ); ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
} }
} }
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep) {
// Move always to appropriate ACTIVE based on its sense list // Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl); UINFO(4," ALW "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: "); //if (debug()>=9) nodep->dumpTree(cout," Alw: ");
@@ -382,13 +384,13 @@ private:
} }
visitAlways(nodep, nodep->sensesp(), nodep->keyword()); visitAlways(nodep, nodep->sensesp(), nodep->keyword());
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { virtual void visit(AstAlwaysPublic* nodep) {
// Move always to appropriate ACTIVE based on its sense list // Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl); UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: "); //if (debug()>=9) nodep->dumpTree(cout," Alw: ");
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS); visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
} }
virtual void visit(AstSenGate* nodep, AstNUser*) { virtual void visit(AstSenGate* nodep) {
AstSenItem* subitemp = nodep->sensesp(); AstSenItem* subitemp = nodep->sensesp();
if (subitemp->edgeType() != AstEdgeType::ET_ANYEDGE if (subitemp->edgeType() != AstEdgeType::ET_ANYEDGE
&& subitemp->edgeType() != AstEdgeType::ET_POSEDGE && subitemp->edgeType() != AstEdgeType::ET_POSEDGE
@@ -397,7 +399,7 @@ private:
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstSenItem* nodep, AstNUser*) { virtual void visit(AstSenItem* nodep) {
if (nodep->edgeType() == AstEdgeType::ET_ANYEDGE) { if (nodep->edgeType() == AstEdgeType::ET_ANYEDGE) {
m_itemCombo = true; m_itemCombo = true;
// Delete the sensitivity // Delete the sensitivity
@@ -413,10 +415,10 @@ private:
} }
// Empty visitors, speed things up // Empty visitors, speed things up
virtual void visit(AstNodeMath* nodep, AstNUser*) {} virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstVarScope* nodep, AstNUser*) {} virtual void visit(AstVarScope* nodep) {}
//-------------------- //--------------------
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+13 -13
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -65,19 +65,19 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstTopScope* nodep, AstNUser*) { virtual void visit(AstTopScope* nodep) {
m_topscopep = nodep; m_topscopep = nodep;
m_finder.main(m_topscopep); m_finder.main(m_topscopep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_topscopep = NULL; m_topscopep = NULL;
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
// Create required actives and add to module // Create required actives and add to module
// We can start ordering at a module, or a scope // We can start ordering at a module, or a scope
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstActive* nodep, AstNUser*) { virtual void visit(AstActive* nodep) {
UINFO(4," ACTIVE "<<nodep<<endl); UINFO(4," ACTIVE "<<nodep<<endl);
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change! V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
AstSenTree* sensesp = nodep->sensesp(); AstSenTree* sensesp = nodep->sensesp();
@@ -120,29 +120,29 @@ private:
// No need to do statements under it, they're already moved. // No need to do statements under it, they're already moved.
//nodep->iterateChildren(*this); //nodep->iterateChildren(*this);
} }
virtual void visit(AstInitial* nodep, AstNUser*) { virtual void visit(AstInitial* nodep) {
nodep->v3fatalSrc("Node should have been under ACTIVE"); nodep->v3fatalSrc("Node should have been under ACTIVE");
} }
virtual void visit(AstAssignAlias* nodep, AstNUser*) { virtual void visit(AstAssignAlias* nodep) {
nodep->v3fatalSrc("Node should have been under ACTIVE"); nodep->v3fatalSrc("Node should have been under ACTIVE");
} }
virtual void visit(AstAssignW* nodep, AstNUser*) { virtual void visit(AstAssignW* nodep) {
nodep->v3fatalSrc("Node should have been under ACTIVE"); nodep->v3fatalSrc("Node should have been under ACTIVE");
} }
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep) {
nodep->v3fatalSrc("Node should have been under ACTIVE"); nodep->v3fatalSrc("Node should have been under ACTIVE");
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { virtual void visit(AstAlwaysPublic* nodep) {
nodep->v3fatalSrc("Node should have been under ACTIVE"); nodep->v3fatalSrc("Node should have been under ACTIVE");
} }
virtual void visit(AstFinal* nodep, AstNUser*) { virtual void visit(AstFinal* nodep) {
nodep->v3fatalSrc("Node should have been deleted"); nodep->v3fatalSrc("Node should have been deleted");
} }
// Empty visitors, speed things up // Empty visitors, speed things up
virtual void visit(AstNodeMath* nodep, AstNUser*) {} virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstVarScope* nodep, AstNUser*) {} virtual void visit(AstVarScope* nodep) {}
//-------------------- //--------------------
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+33 -16
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can // Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -163,7 +163,7 @@ private:
pushDeletep(nodep); VL_DANGLING(nodep); pushDeletep(nodep); VL_DANGLING(nodep);
} }
virtual void visit(AstIf* nodep, AstNUser*) { virtual void visit(AstIf* nodep) {
if (nodep->user1SetOnce()) return; if (nodep->user1SetOnce()) return;
if (nodep->uniquePragma() || nodep->unique0Pragma()) { if (nodep->uniquePragma() || nodep->unique0Pragma()) {
AstNodeIf* ifp = nodep; AstNodeIf* ifp = nodep;
@@ -205,8 +205,8 @@ private:
// Note: if this ends with an 'else', then we don't need to validate that one of the // Note: if this ends with an 'else', then we don't need to validate that one of the
// predicates evaluates to true. // predicates evaluates to true.
AstNode* ohot = ((allow_none || hasDefaultElse) AstNode* ohot = ((allow_none || hasDefaultElse)
? (new AstOneHot0(nodep->fileline(), propp))->castNode() ? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: (new AstOneHot (nodep->fileline(), propp))->castNode()); : static_cast<AstNode*>(new AstOneHot (nodep->fileline(), propp)));
AstIf* checkifp = new AstIf (nodep->fileline(), AstIf* checkifp = new AstIf (nodep->fileline(),
new AstLogNot (nodep->fileline(), ohot), new AstLogNot (nodep->fileline(), ohot),
newFireAssert(nodep, "'unique if' statement violated"), newFireAssert(nodep, "'unique if' statement violated"),
@@ -220,7 +220,7 @@ private:
} }
// VISITORS //========== Case assertions // VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) { virtual void visit(AstCase* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->user1SetOnce()) { if (!nodep->user1SetOnce()) {
bool has_default=false; bool has_default=false;
@@ -245,17 +245,34 @@ private:
AstNode* propp = NULL; AstNode* propp = NULL;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
AstNode* onep = new AstEq(icondp->fileline(), AstNode* onep;
nodep->exprp()->cloneTree(false), AstConst* iconstp = icondp->castConst();
icondp->cloneTree(false)); if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
AstNode* and1p = new AstAnd(itemp->fileline(), nodep->exprp()->cloneTree(false),
new AstConst(itemp->fileline(), nummask));
AstNode* and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
onep = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else {
onep = AstEq::newTyped(icondp->fileline(),
nodep->exprp()->cloneTree(false),
icondp->cloneTree(false));
}
if (propp) propp = new AstConcat(icondp->fileline(), onep, propp); if (propp) propp = new AstConcat(icondp->fileline(), onep, propp);
else propp = onep; else propp = onep;
} }
} }
bool allow_none = has_default || nodep->unique0Pragma(); bool allow_none = has_default || nodep->unique0Pragma();
AstNode* ohot = (allow_none AstNode* ohot = (allow_none
? (new AstOneHot0(nodep->fileline(), propp))->castNode() ? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
: (new AstOneHot (nodep->fileline(), propp))->castNode()); : static_cast<AstNode*>(new AstOneHot (nodep->fileline(), propp)));
AstIf* ifp = new AstIf (nodep->fileline(), AstIf* ifp = new AstIf (nodep->fileline(),
new AstLogNot (nodep->fileline(), ohot), new AstLogNot (nodep->fileline(), ohot),
newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"), newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"),
@@ -268,7 +285,7 @@ private:
} }
// VISITORS //========== Statements // VISITORS //========== Statements
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstDisplay* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Replace the special types with standard text // Replace the special types with standard text
if (nodep->displayType()==AstDisplayType::DT_INFO) { if (nodep->displayType()==AstDisplayType::DT_INFO) {
@@ -281,27 +298,27 @@ private:
} }
} }
virtual void visit(AstPslCover* nodep, AstNUser*) { virtual void visit(AstPslCover* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name()); if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep); nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep);
++m_statAsCover; ++m_statAsCover;
} }
virtual void visit(AstVAssert* nodep, AstNUser*) { virtual void visit(AstVAssert* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newVAssertion(nodep, nodep->propp()); VL_DANGLING(nodep); newVAssertion(nodep, nodep->propp()); VL_DANGLING(nodep);
++m_statAsSV; ++m_statAsSV;
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
// //
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Reset defaults // Reset defaults
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstBegin* nodep, AstNUser*) { virtual void visit(AstBegin* nodep) {
// This code is needed rather than a visitor in V3Begin, // This code is needed rather than a visitor in V3Begin,
// because V3Assert is called before V3Begin // because V3Assert is called before V3Begin
AstBegin* lastp = m_beginp; AstBegin* lastp = m_beginp;
@@ -312,7 +329,7 @@ private:
m_beginp = lastp; m_beginp = lastp;
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can // Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+6 -6
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can // Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -73,7 +73,7 @@ private:
} }
// VISITORS //========== Statements // VISITORS //========== Statements
virtual void visit(AstClocking* nodep, AstNUser*) { virtual void visit(AstClocking* nodep) {
UINFO(8," CLOCKING"<<nodep<<endl); UINFO(8," CLOCKING"<<nodep<<endl);
// Store the new default clock, reset on new module // Store the new default clock, reset on new module
m_seniDefaultp = nodep->sensesp(); m_seniDefaultp = nodep->sensesp();
@@ -86,14 +86,14 @@ private:
pushDeletep(nodep); VL_DANGLING(nodep); pushDeletep(nodep); VL_DANGLING(nodep);
} }
virtual void visit(AstPslCover* nodep, AstNUser*) { virtual void visit(AstPslCover* nodep) {
if (nodep->sentreep()) return; // Already processed if (nodep->sentreep()) return; // Already processed
clearAssertInfo(); clearAssertInfo();
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->sentreep(newSenTree(nodep)); nodep->sentreep(newSenTree(nodep));
clearAssertInfo(); clearAssertInfo();
} }
virtual void visit(AstPslClocked* nodep, AstNUser*) { virtual void visit(AstPslClocked* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_senip) { if (m_senip) {
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion"); nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
@@ -111,12 +111,12 @@ private:
nodep->replaceWith(blockp); nodep->replaceWith(blockp);
pushDeletep(nodep); VL_DANGLING(nodep); pushDeletep(nodep); VL_DANGLING(nodep);
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Reset defaults // Reset defaults
m_seniDefaultp = NULL; m_seniDefaultp = NULL;
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can // Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+149 -144
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -80,30 +80,30 @@ void AstNode::init() {
// Attributes // Attributes
m_didWidth = false; m_didWidth = false;
m_doingWidth = false; m_doingWidth = false;
m_user1p = NULL; m_user1u = VNUser(0);
m_user1Cnt = 0; m_user1Cnt = 0;
m_user2p = NULL; m_user2u = VNUser(0);
m_user2Cnt = 0; m_user2Cnt = 0;
m_user3p = NULL; m_user3u = VNUser(0);
m_user3Cnt = 0; m_user3Cnt = 0;
m_user4p = NULL; m_user4u = VNUser(0);
m_user4Cnt = 0; m_user4Cnt = 0;
m_user5p = NULL; m_user5u = VNUser(0);
m_user5Cnt = 0; m_user5Cnt = 0;
} }
string AstNode::encodeName(const string& namein) { string AstNode::encodeName(const string& namein) {
// Encode signal name raw from parser, then not called again on same signal // Encode signal name raw from parser, then not called again on same signal
const char* start = namein.c_str();
string out; string out;
for (const char* pos = start; *pos; pos++) { for (string::const_iterator pos = namein.begin(); pos!=namein.end(); ++pos) {
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers if ((pos==namein.begin()) ? isalpha(pos[0]) // digits can't lead identifiers
: isalnum(pos[0])) { : isalnum(pos[0])) {
out += pos[0]; out += pos[0];
} else if (pos[0]=='_') { } else if (pos[0]=='_') {
if (pos[1]=='_') { if (pos[1]=='_') {
out += "_"; out += "__05F"; // hex(_) = 0x5F out += "_"; out += "__05F"; // hex(_) = 0x5F
pos++; ++pos;
if (pos==namein.end()) break;
} else { } else {
out += pos[0]; out += pos[0];
} }
@@ -166,44 +166,53 @@ string AstNode::vcdName(const string& namein) {
} }
string AstNode::prettyName(const string& namein) { string AstNode::prettyName(const string& namein) {
// This function is somewhat hot, so we short-circuit some compares
string pretty; string pretty;
pretty = ""; pretty = "";
pretty.reserve(namein.length());
for (const char* pos = namein.c_str(); *pos; ) { for (const char* pos = namein.c_str(); *pos; ) {
if (0==strncmp(pos,"__BRA__",7)) { if (pos[0]=='-' && pos[1]=='>') { // ->
pretty += "[";
pos += 7;
}
else if (0==strncmp(pos,"__KET__",7)) {
pretty += "]";
pos += 7;
}
else if (0==strncmp(pos,"__DOT__",7)) {
pretty += ".";
pos += 7;
}
else if (0==strncmp(pos,"->",2)) {
pretty += "."; pretty += ".";
pos += 2; pos += 2;
continue;
} }
else if (0==strncmp(pos,"__PVT__",7)) { if (pos[0]=='_' && pos[1]=='_') { // Short-circuit
pretty += ""; if (0==strncmp(pos,"__BRA__",7)) {
pos += 7; pretty += "[";
} pos += 7;
else if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0' continue;
&& isxdigit(pos[3]) && isxdigit(pos[4])) { }
char value = 0; if (0==strncmp(pos,"__KET__",7)) {
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10)); pretty += "]";
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10)); pos += 7;
pretty += value; continue;
pos += 5; }
} if (0==strncmp(pos,"__DOT__",7)) {
else { pretty += ".";
pretty += pos[0]; pos += 7;
pos++; continue;
}
if (0==strncmp(pos,"__PVT__",7)) {
pretty += "";
pos += 7;
continue;
}
if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0'
&& isxdigit(pos[3]) && isxdigit(pos[4])) {
char value = 0;
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10));
pretty += value;
pos += 5;
continue;
}
} }
// Default
pretty += pos[0];
++pos;
} }
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,""); if (pretty[0]=='T' && pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,""); if (pretty[0]=='T' && pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
return pretty; return pretty;
} }
@@ -235,20 +244,20 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
#endif #endif
} }
AstNode* AstNode::addNext(AstNode* newp) { AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) {
// Add to m_nextp, returns this // Add to m_nextp, returns this
UASSERT(newp,"Null item passed to addNext\n"); UDEBUGONLY(if (!newp) nodep->v3fatalSrc("Null item passed to addNext"););
this->debugTreeChange("-addNextThs: ", __LINE__, false); nodep->debugTreeChange("-addNextThs: ", __LINE__, false);
newp->debugTreeChange("-addNextNew: ", __LINE__, true); newp->debugTreeChange("-addNextNew: ", __LINE__, true);
if (this == NULL) { if (!nodep) { // verilog.y and lots of other places assume this
return (newp); return (newp);
} else { } else {
// Find end of old list // Find end of old list
AstNode* oldtailp = this; AstNode* oldtailp = nodep;
if (oldtailp->m_nextp) { if (oldtailp->m_nextp) {
if (oldtailp->m_headtailp) { if (oldtailp->m_headtailp) {
oldtailp = oldtailp->m_headtailp; // This=beginning of list, jump to end oldtailp = oldtailp->m_headtailp; // This=beginning of list, jump to end
UASSERT(!oldtailp->m_nextp, "Node had next, but headtail says it shouldn't"); UDEBUGONLY(if (oldtailp->m_nextp) nodep->v3fatalSrc("Node had next, but headtail says it shouldn't"););
} else { } else {
// Though inefficent, we are occasionally passed a addNext in the middle of a list. // Though inefficent, we are occasionally passed a addNext in the middle of a list.
while (oldtailp->m_nextp != NULL) oldtailp = oldtailp->m_nextp; while (oldtailp->m_nextp != NULL) oldtailp = oldtailp->m_nextp;
@@ -267,21 +276,21 @@ AstNode* AstNode::addNext(AstNode* newp) {
newp->editCountInc(); newp->editCountInc();
if (oldtailp->m_iterpp) *(oldtailp->m_iterpp) = newp; // Iterate on new item if (oldtailp->m_iterpp) *(oldtailp->m_iterpp) = newp; // Iterate on new item
} }
this->debugTreeChange("-addNextOut:", __LINE__, true); nodep->debugTreeChange("-addNextOut:", __LINE__, true);
return this; return nodep;
} }
AstNode* AstNode::addNextNull(AstNode* newp) { AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) {
if (!newp) return this; if (!newp) return nodep;
return addNext(newp); return addNext(nodep, newp);
} }
void AstNode::addNextHere(AstNode* newp) { void AstNode::addNextHere(AstNode* newp) {
// Add to m_nextp on exact node passed, not at the end. // Add to m_nextp on exact node passed, not at the end.
// This could be at head, tail, or both (single) // This could be at head, tail, or both (single)
// New could be head of single node, or list // New could be head of single node, or list
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
UASSERT(newp,"Null item passed to addNext"); UASSERT(newp,"Null item passed to addNext");
UASSERT(this,"Null base node");
UASSERT(newp->backp()==NULL,"New node (back) already assigned?"); UASSERT(newp->backp()==NULL,"New node (back) already assigned?");
this->debugTreeChange("-addHereThs: ", __LINE__, false); this->debugTreeChange("-addHereThs: ", __LINE__, false);
newp->debugTreeChange("-addHereNew: ", __LINE__, true); newp->debugTreeChange("-addHereNew: ", __LINE__, true);
@@ -605,12 +614,12 @@ void AstNode::swapWith (AstNode* bp) {
// Clone // Clone
AstNode* AstNode::cloneTreeIter() { AstNode* AstNode::cloneTreeIter() {
if (!this) return NULL; // private: Clone single node and children
AstNode* newp = this->clone(); AstNode* newp = this->clone();
newp->op1p(this->m_op1p->cloneTreeIterList()); if (this->m_op1p) newp->op1p(this->m_op1p->cloneTreeIterList());
newp->op2p(this->m_op2p->cloneTreeIterList()); if (this->m_op2p) newp->op2p(this->m_op2p->cloneTreeIterList());
newp->op3p(this->m_op3p->cloneTreeIterList()); if (this->m_op3p) newp->op3p(this->m_op3p->cloneTreeIterList());
newp->op4p(this->m_op4p->cloneTreeIterList()); if (this->m_op4p) newp->op4p(this->m_op4p->cloneTreeIterList());
newp->m_iterpp = NULL; newp->m_iterpp = NULL;
newp->clonep(this); // Save pointers to/from both to simplify relinking. newp->clonep(this); // Save pointers to/from both to simplify relinking.
this->clonep(newp); // Save pointers to/from both to simplify relinking. this->clonep(newp); // Save pointers to/from both to simplify relinking.
@@ -618,10 +627,10 @@ AstNode* AstNode::cloneTreeIter() {
} }
AstNode* AstNode::cloneTreeIterList() { AstNode* AstNode::cloneTreeIterList() {
// Clone list of nodes, set m_headtailp // private: Clone list of nodes, set m_headtailp
if (!this) return NULL;
AstNode* newheadp = NULL; AstNode* newheadp = NULL;
AstNode* newtailp = NULL; AstNode* newtailp = NULL;
// Audited to make sure this is never NULL
for (AstNode* oldp = this; oldp; oldp=oldp->m_nextp) { for (AstNode* oldp = this; oldp; oldp=oldp->m_nextp) {
AstNode* newp = oldp->cloneTreeIter(); AstNode* newp = oldp->cloneTreeIter();
newp->m_headtailp = NULL; newp->m_headtailp = NULL;
@@ -636,7 +645,7 @@ AstNode* AstNode::cloneTreeIterList() {
} }
AstNode* AstNode::cloneTree(bool cloneNextLink) { AstNode* AstNode::cloneTree(bool cloneNextLink) {
if (!this) return NULL; if (!this) return NULL; // verilog.y relies on this
this->debugTreeChange("-cloneThs: ", __LINE__, cloneNextLink); this->debugTreeChange("-cloneThs: ", __LINE__, cloneNextLink);
cloneClearTree(); cloneClearTree();
AstNode* newp; AstNode* newp;
@@ -657,7 +666,7 @@ AstNode* AstNode::cloneTree(bool cloneNextLink) {
// Delete // Delete
void AstNode::deleteNode() { void AstNode::deleteNode() {
if (!this) return; // private: Delete single node. Publicly call deleteTree() instead.
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n"); UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
editCountInc(); editCountInc();
// Change links of old node so we coredump if used // Change links of old node so we coredump if used
@@ -677,14 +686,15 @@ AstNode::~AstNode() {
} }
void AstNode::deleteTreeIter() { void AstNode::deleteTreeIter() {
if (!this) return; // private: Delete list of nodes. Publicly call deleteTree() instead.
// Audited to make sure this is never NULL
for (AstNode* nodep=this, *nnextp; nodep; nodep=nnextp) { for (AstNode* nodep=this, *nnextp; nodep; nodep=nnextp) {
nnextp = nodep->m_nextp; nnextp = nodep->m_nextp;
// MUST be depth first! // MUST be depth first!
nodep->m_op1p->deleteTreeIter(); if (nodep->m_op1p) nodep->m_op1p->deleteTreeIter();
nodep->m_op2p->deleteTreeIter(); if (nodep->m_op2p) nodep->m_op2p->deleteTreeIter();
nodep->m_op3p->deleteTreeIter(); if (nodep->m_op3p) nodep->m_op3p->deleteTreeIter();
nodep->m_op4p->deleteTreeIter(); if (nodep->m_op4p) nodep->m_op4p->deleteTreeIter();
nodep->m_nextp = NULL; nodep->m_nextp = NULL;
nodep->m_backp = NULL; nodep->m_backp = NULL;
nodep->deleteNode(); nodep->deleteNode();
@@ -694,7 +704,6 @@ void AstNode::deleteTreeIter() {
void AstNode::deleteTree() { void AstNode::deleteTree() {
// deleteTree always deletes the next link, because you must have called // deleteTree always deletes the next link, because you must have called
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this. // unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
if (!this) return;
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n"); UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
this->debugTreeChange("-delTree: ", __LINE__, true); this->debugTreeChange("-delTree: ", __LINE__, true);
this->editCountInc(); this->editCountInc();
@@ -723,53 +732,48 @@ void AstNode::operator delete(void* objp, size_t size) {
//====================================================================== //======================================================================
// Iterators // Iterators
void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) { void AstNode::iterateChildren(AstNVisitor& v) {
// This is a very hot function // This is a very hot function
if (!this) return;
ASTNODE_PREFETCH(m_op1p); ASTNODE_PREFETCH(m_op1p);
ASTNODE_PREFETCH(m_op2p); ASTNODE_PREFETCH(m_op2p);
ASTNODE_PREFETCH(m_op3p); ASTNODE_PREFETCH(m_op3p);
ASTNODE_PREFETCH(m_op4p); ASTNODE_PREFETCH(m_op4p);
// if () not needed since iterateAndNext accepts null this, but faster with it. if (m_op1p) m_op1p->iterateAndNext(v);
if (m_op1p) m_op1p->iterateAndNext(v, vup); if (m_op2p) m_op2p->iterateAndNext(v);
if (m_op2p) m_op2p->iterateAndNext(v, vup); if (m_op3p) m_op3p->iterateAndNext(v);
if (m_op3p) m_op3p->iterateAndNext(v, vup); if (m_op4p) m_op4p->iterateAndNext(v);
if (m_op4p) m_op4p->iterateAndNext(v, vup);
} }
void AstNode::iterateChildrenConst(AstNVisitor& v, AstNUser* vup) { void AstNode::iterateChildrenConst(AstNVisitor& v) {
// This is a very hot function // This is a very hot function
if (!this) return;
ASTNODE_PREFETCH(m_op1p); ASTNODE_PREFETCH(m_op1p);
ASTNODE_PREFETCH(m_op2p); ASTNODE_PREFETCH(m_op2p);
ASTNODE_PREFETCH(m_op3p); ASTNODE_PREFETCH(m_op3p);
ASTNODE_PREFETCH(m_op4p); ASTNODE_PREFETCH(m_op4p);
// if () not needed since iterateAndNext accepts null this, but faster with it. if (m_op1p) m_op1p->iterateAndNextConst(v);
if (m_op1p) m_op1p->iterateAndNextConst(v, vup); if (m_op2p) m_op2p->iterateAndNextConst(v);
if (m_op2p) m_op2p->iterateAndNextConst(v, vup); if (m_op3p) m_op3p->iterateAndNextConst(v);
if (m_op3p) m_op3p->iterateAndNextConst(v, vup); if (m_op4p) m_op4p->iterateAndNextConst(v);
if (m_op4p) m_op4p->iterateAndNextConst(v, vup);
} }
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) { void AstNode::iterateAndNext(AstNVisitor& v) {
// This is a very hot function // This is a very hot function
// IMPORTANT: If you replace a node that's the target of this iterator, // IMPORTANT: If you replace a node that's the target of this iterator,
// then the NEW node will be iterated on next, it isn't skipped! // then the NEW node will be iterated on next, it isn't skipped!
// if (!this) return; // Part of for()
// Future versions of this function may require the node to have a back to be iterated; // 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. // there's no lower level reason yet though the back must exist.
AstNode* nodep=this; AstNode* nodep=this;
#ifdef VL_DEBUG // Otherwise too hot of a function for debug #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"); if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
#endif #endif
while (nodep) { while (nodep) { // effectively: if (!this) return; // Callers rely on this
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
ASTNODE_PREFETCH(nodep->m_nextp); ASTNODE_PREFETCH(nodep->m_nextp);
// Desirable check, but many places where multiple iterations are OK // Desirable check, but many places where multiple iterations are OK
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits"); //if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
// cppcheck-suppress nullPointer // cppcheck-suppress nullPointer
niterp->m_iterpp = &niterp; niterp->m_iterpp = &niterp;
niterp->accept(v, vup); niterp->accept(v);
// accept may do a replaceNode and change niterp on us... // 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 != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
if (!niterp) return; // Perhaps node deleted inside accept if (!niterp) return; // Perhaps node deleted inside accept
@@ -782,38 +786,37 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
} }
} }
void AstNode::iterateListBackwards(AstNVisitor& v, AstNUser* vup) { void AstNode::iterateListBackwards(AstNVisitor& v) {
if (!this) return; UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
AstNode* nodep=this; AstNode* nodep=this;
while (nodep->m_nextp) nodep=nodep->m_nextp; while (nodep->m_nextp) nodep=nodep->m_nextp;
while (nodep) { while (nodep) {
// Edits not supported: nodep->m_iterpp = &nodep; // Edits not supported: nodep->m_iterpp = &nodep;
nodep->accept(v, vup); nodep->accept(v);
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp(); if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
else nodep = NULL; // else: backp points up the tree. else nodep = NULL; // else: backp points up the tree.
} }
} }
void AstNode::iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup) { void AstNode::iterateChildrenBackwards(AstNVisitor& v) {
if (!this) return; if (m_op1p) m_op1p->iterateListBackwards(v);
this->op1p()->iterateListBackwards(v,vup); if (m_op2p) m_op2p->iterateListBackwards(v);
this->op2p()->iterateListBackwards(v,vup); if (m_op3p) m_op3p->iterateListBackwards(v);
this->op3p()->iterateListBackwards(v,vup); if (m_op4p) m_op4p->iterateListBackwards(v);
this->op4p()->iterateListBackwards(v,vup);
} }
void AstNode::iterateAndNextConst(AstNVisitor& v, AstNUser* vup) { void AstNode::iterateAndNextConst(AstNVisitor& v) {
// Keep following the current list even if edits change it // Keep following the current list even if edits change it
if (!this) return; if (!this) return; // A few cases could be cleaned up, but want symmetry with iterateAndNext
for (AstNode* nodep=this; nodep; ) { for (AstNode* nodep=this; nodep; ) { // effectively: if (!this) return; // Callers rely on this
AstNode* nnextp = nodep->m_nextp; AstNode* nnextp = nodep->m_nextp;
ASTNODE_PREFETCH(nnextp); ASTNODE_PREFETCH(nnextp);
nodep->accept(v, vup); nodep->accept(v);
nodep = nnextp; nodep = nnextp;
} }
} }
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) { AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) {
// Some visitors perform tree edits (such as V3Const), and may even // Some visitors perform tree edits (such as V3Const), and may even
// replace/delete the exact nodep that the visitor is called with. If // replace/delete the exact nodep that the visitor is called with. If
// this happens, the parent will lose the handle to the node that was // this happens, the parent will lose the handle to the node that was
@@ -823,12 +826,12 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
AstNode* nodep = this; // Note "this" may point to bogus point later in this function AstNode* nodep = this; // Note "this" may point to bogus point later in this function
if (nodep->castNetlist()) { if (nodep->castNetlist()) {
// Calling on top level; we know the netlist won't get replaced // Calling on top level; we know the netlist won't get replaced
nodep->accept(v, vup); nodep->accept(v);
} else if (!nodep->backp()) { } else if (!nodep->backp()) {
// Calling on standalone tree; insert a shim node so we can keep track, then delete it on completion // Calling on standalone tree; insert a shim node so we can keep track, then delete it on completion
AstBegin* tempp = new AstBegin(nodep->fileline(),"[EditWrapper]",nodep); AstBegin* tempp = new AstBegin(nodep->fileline(),"[EditWrapper]",nodep);
{ {
tempp->stmtsp()->accept(v, vup); VL_DANGLING(nodep); // nodep to null as may be replaced tempp->stmtsp()->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced
} }
nodep = tempp->stmtsp()->unlinkFrBackWithNext(); nodep = tempp->stmtsp()->unlinkFrBackWithNext();
tempp->deleteTree(); VL_DANGLING(tempp); tempp->deleteTree(); VL_DANGLING(tempp);
@@ -842,7 +845,7 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp); else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp);
if (!nextnodepp) this->v3fatalSrc("Node's back doesn't point to forward to node itself"); if (!nextnodepp) this->v3fatalSrc("Node's back doesn't point to forward to node itself");
{ {
nodep->accept(v, vup); VL_DANGLING(nodep); // nodep to null as may be replaced nodep->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced
} }
nodep = *nextnodepp; // Grab new node from point where old was connected nodep = *nextnodepp; // Grab new node from point where old was connected
} }
@@ -852,16 +855,16 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
//====================================================================== //======================================================================
void AstNode::cloneRelinkTree() { void AstNode::cloneRelinkTree() {
if (!this) return; // private: Cleanup clone() operation on whole tree. Publicly call cloneTree() instead.
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) { for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
if (m_dtypep && m_dtypep->clonep()) { if (m_dtypep && m_dtypep->clonep()) {
m_dtypep = m_dtypep->clonep()->castNodeDType(); m_dtypep = m_dtypep->clonep();
} }
nodep->cloneRelink(); nodep->cloneRelink();
nodep->m_op1p->cloneRelinkTree(); if (nodep->m_op1p) nodep->m_op1p->cloneRelinkTree();
nodep->m_op2p->cloneRelinkTree(); if (nodep->m_op2p) nodep->m_op2p->cloneRelinkTree();
nodep->m_op3p->cloneRelinkTree(); if (nodep->m_op3p) nodep->m_op3p->cloneRelinkTree();
nodep->m_op4p->cloneRelinkTree(); if (nodep->m_op4p) nodep->m_op4p->cloneRelinkTree();
} }
} }
@@ -869,30 +872,30 @@ void AstNode::cloneRelinkTree() {
// Comparison // Comparison
bool AstNode::gateTreeIter() { bool AstNode::gateTreeIter() {
// Return true if the two trees are identical // private: Return true if the two trees are identical
if (this==NULL) return true;
if (!isGateOptimizable()) return false; if (!isGateOptimizable()) return false;
return (this->op1p()->gateTreeIter() if (m_op1p && !m_op1p->gateTreeIter()) return false;
&& this->op2p()->gateTreeIter() if (m_op2p && !m_op2p->gateTreeIter()) return false;
&& this->op3p()->gateTreeIter() if (m_op3p && !m_op3p->gateTreeIter()) return false;
&& this->op4p()->gateTreeIter()); if (m_op4p && !m_op4p->gateTreeIter()) return false;
return true;
} }
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) { bool AstNode::sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly) {
// Return true if the two trees are identical // private: Return true if the two trees are identical
if (this==NULL && node2p==NULL) return true; if (!node1p && !node2p) return true;
if (this==NULL || node2p==NULL) return false; if (!node1p || !node2p) return false;
if (this->type() != node2p->type() if (node1p->type() != node2p->type()
|| this->dtypep() != node2p->dtypep() || node1p->dtypep() != node2p->dtypep()
|| !this->same(node2p) || !node1p->same(node2p)
|| (gateOnly && !this->isGateOptimizable())) { || (gateOnly && !node1p->isGateOptimizable())) {
return false; return false;
} }
return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly) return (sameTreeIter(node1p->m_op1p, node2p->m_op1p,false,gateOnly)
&& this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly) && sameTreeIter(node1p->m_op2p, node2p->m_op2p,false,gateOnly)
&& this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly) && sameTreeIter(node1p->m_op3p, node2p->m_op3p,false,gateOnly)
&& this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly) && sameTreeIter(node1p->m_op4p, node2p->m_op4p,false,gateOnly)
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly)) && (ignNext || sameTreeIter(node1p->m_nextp, node2p->m_nextp,false,gateOnly))
); );
} }
@@ -916,6 +919,7 @@ V3Hash::V3Hash(const string& name) {
// Debugging // Debugging
void AstNode::checkTreeIter(AstNode* backp) { void AstNode::checkTreeIter(AstNode* backp) {
// private: Check a tree and children
if (backp != this->backp()) { if (backp != this->backp()) {
this->v3fatalSrc("Back node inconsistent"); this->v3fatalSrc("Back node inconsistent");
} }
@@ -924,15 +928,15 @@ void AstNode::checkTreeIter(AstNode* backp) {
if (op1p()||op2p()||op3p()||op4p()) if (op1p()||op2p()||op3p()||op4p())
this->v3fatalSrc("Terminal operation with non-terminals"); this->v3fatalSrc("Terminal operation with non-terminals");
} }
if (op1p()) op1p()->checkTreeIterList(this); if (m_op1p) m_op1p->checkTreeIterList(this);
if (op2p()) op2p()->checkTreeIterList(this); if (m_op2p) m_op2p->checkTreeIterList(this);
if (op3p()) op3p()->checkTreeIterList(this); if (m_op3p) m_op3p->checkTreeIterList(this);
if (op4p()) op4p()->checkTreeIterList(this); if (m_op4p) m_op4p->checkTreeIterList(this);
} }
void AstNode::checkTreeIterList(AstNode* backp) { void AstNode::checkTreeIterList(AstNode* backp) {
// Check a (possible) list of nodes, this is always the head of the list // private: Check a (possible) list of nodes, this is always the head of the list
if (!this) v3fatalSrc("Null nodep"); // Audited to make sure this is never NULL
AstNode* headp = this; AstNode* headp = this;
AstNode* tailp = this; AstNode* tailp = this;
for (AstNode* nodep=headp; nodep; nodep=nodep->nextp()) { for (AstNode* nodep=headp; nodep; nodep=nodep->nextp()) {
@@ -946,7 +950,6 @@ void AstNode::checkTreeIterList(AstNode* backp) {
} }
void AstNode::checkTree() { void AstNode::checkTree() {
if (!this) return;
if (!debug()) return; if (!debug()) return;
if (this->backp()) { if (this->backp()) {
// Linked tree- check only the passed node // Linked tree- check only the passed node
@@ -957,17 +960,17 @@ void AstNode::checkTree() {
} }
void AstNode::dumpGdb() { // For GDB only void AstNode::dumpGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; } if (!dynamic_cast<const AstNode*>(this)) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader(); dumpGdbHeader();
cout<<" "; dump(cout); cout<<endl; cout<<" "; dump(cout); cout<<endl;
} }
void AstNode::dumpGdbHeader() const { // For GDB only void AstNode::dumpGdbHeader() const { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; } if (!dynamic_cast<const AstNode*>(this)) { cout<<"This=NULL"<<endl; return; }
dumpPtrs(cout); dumpPtrs(cout);
cout<<" Fileline = "<<fileline()<<endl; cout<<" Fileline = "<<fileline()<<endl;
} }
void AstNode::dumpTreeGdb() { // For GDB only void AstNode::dumpTreeGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; } if (!dynamic_cast<const AstNode*>(this)) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader(); dumpGdbHeader();
dumpTree(cout); dumpTree(cout);
} }
@@ -1007,7 +1010,6 @@ void AstNode::dumpPtrs(ostream& os) const {
} }
void AstNode::dumpTree(ostream& os, const string& indent, int maxDepth) { void AstNode::dumpTree(ostream& os, const string& indent, int maxDepth) {
if (!this) return;
os<<indent<<" "<<this<<endl; os<<indent<<" "<<this<<endl;
if (debug()>8) { os<<indent<<" "; dumpPtrs(os); } if (debug()>8) { os<<indent<<" "; dumpPtrs(os); }
if (maxDepth==1) { if (maxDepth==1) {
@@ -1021,7 +1023,7 @@ void AstNode::dumpTree(ostream& os, const string& indent, int maxDepth) {
} }
void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) { void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
if (!this) return; // Audited to make sure this is never NULL
for (AstNode* nodep=this; nodep; nodep=nodep->nextp()) { for (AstNode* nodep=this; nodep; nodep=nodep->nextp()) {
nodep->dumpTree(os, indent, maxDepth); nodep->dumpTree(os, indent, maxDepth);
} }
@@ -1056,7 +1058,13 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
} }
void AstNode::v3errorEnd(ostringstream& str) const { void AstNode::v3errorEnd(ostringstream& str) const {
if (this && m_fileline) { if (!dynamic_cast<const AstNode*>(this)) {
// No known cases cause this, but better than a core dump
if (debug()) UINFO(0, "-node: NULL. Please report this along with a --gdbbt backtrace as a Verilator bug.\n");
V3Error::v3errorEnd(str);
} else if (!m_fileline) {
V3Error::v3errorEnd(str);
} else {
ostringstream nsstr; ostringstream nsstr;
nsstr<<str.str(); nsstr<<str.str();
if (debug()) { if (debug()) {
@@ -1064,14 +1072,11 @@ void AstNode::v3errorEnd(ostringstream& str) const {
nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl; nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl;
} }
m_fileline->v3errorEnd(nsstr); m_fileline->v3errorEnd(nsstr);
} else {
V3Error::v3errorEnd(str);
} }
} }
string AstNode::warnMore() const { string AstNode::warnMore() const {
if (this) return this->fileline()->warnMore(); return fileline()->warnMore();
else return V3Error::warnMore();
} }
//====================================================================== //======================================================================
+150 -122
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -427,6 +427,7 @@ public:
SUPPLY0, SUPPLY0,
SUPPLY1, SUPPLY1,
WIRE, WIRE,
WREAL,
IMPLICITWIRE, IMPLICITWIRE,
TRIWIRE, TRIWIRE,
TRI0, TRI0,
@@ -448,13 +449,13 @@ public:
static const char* names[] = { static const char* names[] = {
"?","GPARAM","LPARAM","GENVAR", "?","GPARAM","LPARAM","GENVAR",
"VAR","INPUT","OUTPUT","INOUT", "VAR","INPUT","OUTPUT","INOUT",
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE", "SUPPLY0","SUPPLY1","WIRE","WREAL","IMPLICITWIRE",
"TRIWIRE","TRI0","TRI1", "TRIWIRE","TRI0","TRI1",
"PORT", "PORT",
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP", "BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
"IFACEREF"}; "IFACEREF"};
return names[m_e]; } return names[m_e]; }
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE bool isSignal() const { return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|| m_e==TRIWIRE || m_e==TRIWIRE
|| m_e==TRI0 || m_e==TRI1 || m_e==TRI0 || m_e==TRI1
|| m_e==SUPPLY0 || m_e==SUPPLY1 || m_e==SUPPLY0 || m_e==SUPPLY1
@@ -514,6 +515,7 @@ public:
inline AstVarAttrClocker (en _e) : m_e(_e) {} inline AstVarAttrClocker (en _e) : m_e(_e) {}
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
bool unknown() const { return m_e==CLOCKER_UNKNOWN; }
AstVarAttrClocker invert() const { AstVarAttrClocker invert() const {
if (m_e==CLOCKER_YES) return CLOCKER_NO; if (m_e==CLOCKER_YES) return CLOCKER_NO;
else if (m_e==CLOCKER_NO) return CLOCKER_YES; else if (m_e==CLOCKER_NO) return CLOCKER_YES;
@@ -714,7 +716,7 @@ struct VBasicTypeKey {
}; };
//###################################################################### //######################################################################
// AstNUser - Generic pointer base class for AST User nodes. // AstNUser - Generic base class for AST User nodes.
// - Also used to allow parameter passing up/down iterate calls // - Also used to allow parameter passing up/down iterate calls
class WidthVP; class WidthVP;
@@ -723,26 +725,30 @@ class OrderBlockNU;
class OrderVarNU; class OrderVarNU;
class V3GraphVertex; class V3GraphVertex;
class VSymEnt; class VSymEnt;
struct AstNUser {
AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p()) class VNUser {
union {
void* up;
int ui;
} m_u;
public:
VNUser() {}
VNUser(int i) { m_u.up = 0; m_u.ui = i; }
VNUser(void* p) { m_u.up = p; }
~VNUser() {}
// Casters // Casters
WidthVP* c() { return ((WidthVP*)this); } WidthVP* c() { return ((WidthVP*)m_u.up); }
LinkVP* castLinkVP() { return ((LinkVP*)this); } LinkVP* toLinkVP() { return ((LinkVP*)m_u.up); }
VSymEnt* castSymEnt() { return ((VSymEnt*)this); } VSymEnt* toSymEnt() { return ((VSymEnt*)m_u.up); }
AstNode* castNode() { return ((AstNode*)this); } AstNode* toNodep() { return ((AstNode*)m_u.up); }
OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); } OrderBlockNU* toOrderBlock() { return ((OrderBlockNU*)m_u.up); }
OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); } OrderVarNU* toOrderVar() { return ((OrderVarNU*)m_u.up); }
V3GraphVertex* castGraphVertex() { return ((V3GraphVertex*)this); } V3GraphVertex* toGraphVertex() { return ((V3GraphVertex*)m_u.up); }
inline int castInt() { inline int toInt() {
union { AstNUser* up; int ui; } u; return m_u.ui;
u.up = this;
return u.ui;
}
static inline AstNUser* fromInt (int i) {
union { AstNUser* up; int ui; } u;
u.up=0; u.ui=i;
return u.up;
} }
static inline VNUser fromZero () { return VNUser(0); }
static inline VNUser fromInt (int i) { return VNUser(i); }
}; };
//###################################################################### //######################################################################
@@ -861,7 +867,8 @@ public:
} }
#include "V3Ast__gen_visitor.h" // From ./astgen #include "V3Ast__gen_visitor.h" // From ./astgen
// Things like: // Things like:
// virtual void visit(type*) = 0; // virtual void visit(AstBreak* nodep) { visit((AstNodeStmt*)(nodep)); }
// virtual void visit(AstNodeStmt* nodep) { visit((AstNode*)(nodep)); }
}; };
//###################################################################### //######################################################################
@@ -914,7 +921,7 @@ public:
class FullValue {}; // for creator type-overload selection class FullValue {}; // for creator type-overload selection
explicit V3Hash(Illegal) { m_both=0; } explicit V3Hash(Illegal) { m_both=0; }
// Saving and restoring inside a userp // Saving and restoring inside a userp
explicit V3Hash(AstNUser* up) { m_both=up->castInt(); } explicit V3Hash(VNUser u) { m_both=u.toInt(); }
V3Hash operator+= (const V3Hash& rh) { V3Hash operator+= (const V3Hash& rh) {
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval())); setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
return *this; }; return *this; };
@@ -973,15 +980,15 @@ class AstNode {
// // Space for more bools here // // Space for more bools here
// This member ordering both allows 64 bit alignment and puts associated data together // 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 VNUser m_user1u; // Contains any information the user iteration routine wants
uint32_t m_user1Cnt; // Mark of when userp was set uint32_t m_user1Cnt; // Mark of when userp was set
uint32_t m_user2Cnt; // Mark of when userp was set uint32_t m_user2Cnt; // Mark of when userp was set
AstNUser* m_user2p; // Pointer to any information the user iteration routine wants VNUser m_user2u; // Contains any information the user iteration routine wants
AstNUser* m_user3p; // Pointer to any information the user iteration routine wants VNUser m_user3u; // Contains any information the user iteration routine wants
uint32_t m_user3Cnt; // Mark of when userp was set uint32_t m_user3Cnt; // Mark of when userp was set
uint32_t m_user4Cnt; // Mark of when userp was set uint32_t m_user4Cnt; // Mark of when userp was set
AstNUser* m_user4p; // Pointer to any information the user iteration routine wants VNUser m_user4u; // Contains any information the user iteration routine wants
AstNUser* m_user5p; // Pointer to any information the user iteration routine wants VNUser m_user5u; // Contains any information the user iteration routine wants
uint32_t m_user5Cnt; // Mark of when userp was set uint32_t m_user5Cnt; // Mark of when userp was set
// METHODS // METHODS
@@ -991,17 +998,17 @@ class AstNode {
void op4p(AstNode* nodep) { m_op4p = nodep; if (nodep) nodep->m_backp = this; } void op4p(AstNode* nodep) { m_op4p = nodep; if (nodep) nodep->m_backp = this; }
void init(); // initialize value of AstNode void init(); // initialize value of AstNode
void iterateListBackwards(AstNVisitor& v, AstNUser* vup=NULL); void iterateListBackwards(AstNVisitor& v);
private: private:
AstNode* cloneTreeIter(); AstNode* cloneTreeIter();
AstNode* cloneTreeIterList(); AstNode* cloneTreeIterList();
void checkTreeIter(AstNode* backp); void checkTreeIter(AstNode* backp);
void checkTreeIterList(AstNode* backp); void checkTreeIterList(AstNode* backp);
bool gateTreeIter(); bool gateTreeIter();
bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly); bool sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly);
void deleteTreeIter(); void deleteTreeIter();
public:
void deleteNode(); void deleteNode();
public:
static void relinkOneLink(AstNode*& pointpr, AstNode* newp); static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
// cppcheck-suppress functionConst // cppcheck-suppress functionConst
void debugTreeChange(const char* prefix, int lineno, bool next); void debugTreeChange(const char* prefix, int lineno, bool next);
@@ -1109,57 +1116,75 @@ public:
bool isSigned() const; bool isSigned() const;
bool isString() const; bool isString() const;
AstNUser* user1p() const { VNUser user1u() const {
// Slows things down measurably, so disabled by default // Slows things down measurably, so disabled by default
//UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy"); //UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy");
return ((m_user1Cnt==AstUser1InUse::s_userCntGbl)?m_user1p:NULL); return ((m_user1Cnt==AstUser1InUse::s_userCntGbl) ? m_user1u : VNUser(0));
} }
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; } AstNode* user1p() const { return user1u().toNodep(); }
int user1() const { return user1p()->castInt(); } void user1u(const VNUser& user) { m_user1u=user; m_user1Cnt=AstUser1InUse::s_userCntGbl; }
void user1(int val) { user1p(AstNUser::fromInt(val)); } void user1p(void* userp) { user1u(VNUser(userp)); }
int user1Inc() { int v=user1(); user1(v+1); return v; } int user1() const { return user1u().toInt(); }
void user1(int val) { user1u(VNUser(val)); }
int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; }
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc() 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 static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user2p() const { VNUser user2u() const {
//UASSERT_STATIC(AstUser2InUse::s_userBusy, "user2p set w/o busy"); // Slows things down measurably, so disabled by default
return ((m_user2Cnt==AstUser2InUse::s_userCntGbl)?m_user2p:NULL); } //UASSERT_STATIC(AstUser2InUse::s_userBusy, "userp set w/o busy");
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; } return ((m_user2Cnt==AstUser2InUse::s_userCntGbl) ? m_user2u : VNUser(0));
int user2() const { return user2p()->castInt(); } }
void user2(int val) { user2p(AstNUser::fromInt(val)); } AstNode* user2p() const { return user2u().toNodep(); }
int user2Inc() { int v=user2(); user2(v+1); return v; } void user2u(const VNUser& user) { m_user2u=user; m_user2Cnt=AstUser2InUse::s_userCntGbl; }
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; } void user2p(void* userp) { user2u(VNUser(userp)); }
static void user2ClearTree() { AstUser2InUse::clear(); } int user2() const { return user2u().toInt(); }
void user2(int val) { user2u(VNUser(val)); }
int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; }
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; } // Better for cache than user2Inc()
static void user2ClearTree() { AstUser2InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user3p() const { VNUser user3u() const {
//UASSERT_STATIC(AstUser3InUse::s_userBusy, "user3p set w/o busy"); // Slows things down measurably, so disabled by default
return ((m_user3Cnt==AstUser3InUse::s_userCntGbl)?m_user3p:NULL); } //UASSERT_STATIC(AstUser3InUse::s_userBusy, "userp set w/o busy");
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; } return ((m_user3Cnt==AstUser3InUse::s_userCntGbl) ? m_user3u : VNUser(0));
int user3() const { return user3p()->castInt(); } }
void user3(int val) { user3p(AstNUser::fromInt(val)); } AstNode* user3p() const { return user3u().toNodep(); }
int user3Inc() { int v=user3(); user3(v+1); return v; } void user3u(const VNUser& user) { m_user3u=user; m_user3Cnt=AstUser3InUse::s_userCntGbl; }
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; } void user3p(void* userp) { user3u(VNUser(userp)); }
static void user3ClearTree() { AstUser3InUse::clear(); } int user3() const { return user3u().toInt(); }
void user3(int val) { user3u(VNUser(val)); }
int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; }
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; } // Better for cache than user3Inc()
static void user3ClearTree() { AstUser3InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user4p() const { VNUser user4u() const {
//UASSERT_STATIC(AstUser4InUse::s_userBusy, "user4p set w/o busy"); // Slows things down measurably, so disabled by default
return ((m_user4Cnt==AstUser4InUse::s_userCntGbl)?m_user4p:NULL); } //UASSERT_STATIC(AstUser4InUse::s_userBusy, "userp set w/o busy");
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; } return ((m_user4Cnt==AstUser4InUse::s_userCntGbl) ? m_user4u : VNUser(0));
int user4() const { return user4p()->castInt(); } }
void user4(int val) { user4p(AstNUser::fromInt(val)); } AstNode* user4p() const { return user4u().toNodep(); }
int user4Inc() { int v=user4(); user4(v+1); return v; } void user4u(const VNUser& user) { m_user4u=user; m_user4Cnt=AstUser4InUse::s_userCntGbl; }
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; } void user4p(void* userp) { user4u(VNUser(userp)); }
static void user4ClearTree() { AstUser4InUse::clear(); } int user4() const { return user4u().toInt(); }
void user4(int val) { user4u(VNUser(val)); }
int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; }
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; } // Better for cache than user4Inc()
static void user4ClearTree() { AstUser4InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user5p() const { VNUser user5u() const {
//UASSERT_STATIC(AstUser5InUse::s_userBusy, "user5p set w/o busy"); // Slows things down measurably, so disabled by default
return ((m_user5Cnt==AstUser5InUse::s_userCntGbl)?m_user5p:NULL); } //UASSERT_STATIC(AstUser5InUse::s_userBusy, "userp set w/o busy");
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; } return ((m_user5Cnt==AstUser5InUse::s_userCntGbl) ? m_user5u : VNUser(0));
int user5() const { return user5p()->castInt(); } }
void user5(int val) { user5p(AstNUser::fromInt(val)); } AstNode* user5p() const { return user5u().toNodep(); }
int user5Inc() { int v=user5(); user5(v+1); return v; } void user5u(const VNUser& user) { m_user5u=user; m_user5Cnt=AstUser5InUse::s_userCntGbl; }
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; } void user5p(void* userp) { user5u(VNUser(userp)); }
static void user5ClearTree() { AstUser5InUse::clear(); } int user5() const { return user5u().toInt(); }
void user5(int val) { user5u(VNUser(val)); }
int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; }
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; } // Better for cache than user5Inc()
static void user5ClearTree() { AstUser5InUse::clear(); } // Clear userp()'s across the entire tree
vluint64_t editCount() const { return m_editCount; } vluint64_t editCount() const { return m_editCount; }
void editCountInc() { m_editCount = ++s_editCntGbl; } // Preincrement, so can "watch AstNode::s_editCntGbl=##" void editCountInc() { m_editCount = ++s_editCntGbl; } // Preincrement, so can "watch AstNode::s_editCntGbl=##"
@@ -1211,8 +1236,10 @@ public:
void dumpGdbHeader() const; void dumpGdbHeader() const;
// METHODS - Tree modifications // METHODS - Tree modifications
AstNode* addNext(AstNode* newp); // Returns this, adds to end of list static AstNode* addNext(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp to end of nodep's list
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
void addNextHere(AstNode* newp); // Adds after speced node void addNextHere(AstNode* newp); // Adds after speced node
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); } void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
@@ -1261,18 +1288,16 @@ public:
virtual const char* broken() const { return NULL; } virtual const char* broken() const { return NULL; }
// INVOKERS // INVOKERS
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0; virtual void accept(AstNVisitor& v) = 0;
void iterate(AstNVisitor& v, AstNUser* vup=NULL) { this->accept(v,vup); } // Does this; excludes following this->next void iterate(AstNVisitor& v) { this->accept(v); } // Does this; excludes following this->next
void iterateAndNext(AstNVisitor& v, AstNUser* vup=NULL); void iterateAndNext(AstNVisitor& v);
void iterateAndNextConst(AstNVisitor& v, AstNUser* vup=NULL); void iterateAndNextConst(AstNVisitor& v);
void iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup=NULL) { iterateAndNextConst(v, vup); } void iterateChildren(AstNVisitor& v); // Excludes following this->next
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next void iterateChildrenBackwards(AstNVisitor& v); // Excludes following this->next
void iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next void iterateChildrenConst(AstNVisitor& v); // Excludes following this->next
void iterateChildrenConst(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next AstNode* iterateSubtreeReturnEdits(AstNVisitor& v); // Return edited nodep; see comments in V3Ast.cpp
AstNode* acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup=NULL); // Return edited nodep; see comments in V3Ast.cpp
// CONVERSION // CONVERSION
AstNode* castNode() { return this; }
#include "V3Ast__gen_interface.h" // From ./astgen #include "V3Ast__gen_interface.h" // From ./astgen
// Things like: // Things like:
// AstAlways* castAlways(); // AstAlways* castAlways();
@@ -1287,7 +1312,8 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
#define ASTNODE_BASE_FUNCS(name) \ #define ASTNODE_BASE_FUNCS(name) \
virtual ~Ast ##name() {} \ virtual ~Ast ##name() {} \
Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##name(); } Ast ##name * cloneTree(bool cloneNext) { return static_cast<Ast ##name *>(AstNode::cloneTree(cloneNext)); } \
Ast ##name * clonep() const { return static_cast<Ast ##name *>(AstNode::clonep()); }
class AstNodeMath : public AstNode { class AstNodeMath : public AstNode {
// Math -- anything that's part of an expression tree // Math -- anything that's part of an expression tree
@@ -1315,7 +1341,7 @@ public:
// Know no children, and hot function, so skip iterator for speed // Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children // See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst // cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v) { }
}; };
class AstNodeUniop : public AstNodeMath { class AstNodeUniop : public AstNodeMath {
@@ -1326,7 +1352,7 @@ public:
dtypeFrom(lhsp); dtypeFrom(lhsp);
setOp1p(lhsp); } setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop) ASTNODE_BASE_FUNCS(NodeUniop)
AstNode* lhsp() const { return op1p()->castNode(); } AstNode* lhsp() const { return op1p(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); } void lhsp(AstNode* nodep) { return setOp1p(nodep); }
// METHODS // METHODS
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
@@ -1347,8 +1373,10 @@ public:
: AstNodeMath(fl) { : AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); } setOp1p(lhs); setOp2p(rhs); }
ASTNODE_BASE_FUNCS(NodeBiop) ASTNODE_BASE_FUNCS(NodeBiop)
AstNode* lhsp() const { return op1p()->castNode(); } virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
AstNode* rhsp() const { return op2p()->castNode(); } // ACCESSORS
AstNode* lhsp() const { return op1p(); }
AstNode* rhsp() const { return op2p(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); } void lhsp(AstNode* nodep) { return setOp1p(nodep); }
void rhsp(AstNode* nodep) { return setOp2p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); }
// METHODS // METHODS
@@ -1372,9 +1400,9 @@ public:
: AstNodeMath(fl) { : AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); } setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
ASTNODE_BASE_FUNCS(NodeTriop) ASTNODE_BASE_FUNCS(NodeTriop)
AstNode* lhsp() const { return op1p()->castNode(); } AstNode* lhsp() const { return op1p(); }
AstNode* rhsp() const { return op2p()->castNode(); } AstNode* rhsp() const { return op2p(); }
AstNode* thsp() const { return op3p()->castNode(); } AstNode* thsp() const { return op3p(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); } void lhsp(AstNode* nodep) { return setOp1p(nodep); }
void rhsp(AstNode* nodep) { return setOp2p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); }
void thsp(AstNode* nodep) { return setOp3p(nodep); } void thsp(AstNode* nodep) { return setOp3p(nodep); }
@@ -1416,9 +1444,9 @@ public:
ASTNODE_BASE_FUNCS(NodeCond) ASTNODE_BASE_FUNCS(NodeCond)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) { virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); } if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
AstNode* condp() const { return op1p()->castNode(); } // op1 = Condition AstNode* condp() const { return op1p(); } // op1 = Condition
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true... AstNode* expr1p() const { return op2p(); } // op2 = If true...
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false... AstNode* expr2p() const { return op3p(); } // op3 = If false...
virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; } virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; }
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; } virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
@@ -1436,10 +1464,10 @@ public:
: AstNode(fl) { : AstNode(fl) {
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); } setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
ASTNODE_BASE_FUNCS(NodePreSel) ASTNODE_BASE_FUNCS(NodePreSel)
AstNode* lhsp() const { return op1p()->castNode(); } AstNode* lhsp() const { return op1p(); }
AstNode* fromp() const { return lhsp(); } AstNode* fromp() const { return lhsp(); }
AstNode* rhsp() const { return op2p()->castNode(); } AstNode* rhsp() const { return op2p(); }
AstNode* thsp() const { return op3p()->castNode(); } AstNode* thsp() const { return op3p(); }
AstAttrOf* attrp() const { return op4p()->castAttrOf(); } AstAttrOf* attrp() const { return op4p()->castAttrOf(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); } void lhsp(AstNode* nodep) { return setOp1p(nodep); }
void rhsp(AstNode* nodep) { return setOp2p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); }
@@ -1471,8 +1499,8 @@ public:
ASTNODE_BASE_FUNCS(NodeAssign) ASTNODE_BASE_FUNCS(NodeAssign)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back. virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
AstNode* rhsp() const { return op1p()->castNode(); } // op1 = Assign from AstNode* rhsp() const { return op1p(); } // op1 = Assign from
AstNode* lhsp() const { return op2p()->castNode(); } // op2 = Assign to AstNode* lhsp() const { return op2p(); } // op2 = Assign to
void rhsp(AstNode* np) { setOp1p(np); } void rhsp(AstNode* np) { setOp1p(np); }
void lhsp(AstNode* np) { setOp2p(np); } void lhsp(AstNode* np) { setOp2p(np); }
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
@@ -1491,10 +1519,10 @@ public:
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp); addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
} }
ASTNODE_BASE_FUNCS(NodeFor) ASTNODE_BASE_FUNCS(NodeFor)
AstNode* initsp() const { return op1p()->castNode(); } // op1= initial statements AstNode* initsp() const { return op1p(); } // op1= initial statements
AstNode* condp() const { return op2p()->castNode(); } // op2= condition to continue AstNode* condp() const { return op2p(); } // op2= condition to continue
AstNode* incsp() const { return op3p()->castNode(); } // op3= increment statements AstNode* incsp() const { return op3p(); } // op3= increment statements
AstNode* bodysp() const { return op4p()->castNode(); } // op4= body of loop AstNode* bodysp() const { return op4p(); } // op4= body of loop
virtual bool isGateOptimizable() const { return false; } virtual bool isGateOptimizable() const { return false; }
virtual int instrCount() const { return instrCountBranch(); } virtual int instrCount() const { return instrCountBranch(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
@@ -1533,9 +1561,9 @@ public:
} }
ASTNODE_BASE_FUNCS(NodeCase) ASTNODE_BASE_FUNCS(NodeCase)
virtual int instrCount() const { return instrCountBranch(); } virtual int instrCount() const { return instrCountBranch(); }
AstNode* exprp() const { return op1p()->castNode(); } // op1 = case condition <expression> AstNode* exprp() const { return op1p(); } // op1 = case condition <expression>
AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions
AstNode* notParallelp() const { return op3p()->castNode(); } // op3 = assertion code for non-full case's AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's
void addItemsp(AstNode* nodep) { addOp2p(nodep); } void addItemsp(AstNode* nodep) { addOp2p(nodep); }
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
}; };
@@ -1597,7 +1625,7 @@ public:
// Know no children, and hot function, so skip iterator for speed // Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children // See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst // cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v) { }
}; };
class AstNodeText : public AstNode { class AstNodeText : public AstNode {
@@ -1728,7 +1756,7 @@ public:
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep()))); return NULL; } || (!m_refDTypep && childDTypep()))); return NULL; }
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
m_refDTypep = m_refDTypep->clonep()->castNodeDType(); m_refDTypep = m_refDTypep->clonep();
}} }}
virtual bool same(AstNode* samep) const { virtual bool same(AstNode* samep) const {
AstNodeArrayDType* sp = samep->castNodeArrayDType(); AstNodeArrayDType* sp = samep->castNodeArrayDType();
@@ -1764,9 +1792,9 @@ public:
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp) AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeBiop(fl, fromp, bitp) {} :AstNodeBiop(fl, fromp, bitp) {}
ASTNODE_BASE_FUNCS(NodeSel) ASTNODE_BASE_FUNCS(NodeSel)
AstNode* fromp() const { return op1p()->castNode(); } // op1 = Extracting what (NULL=TBD during parsing) AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
void fromp(AstNode* nodep) { setOp1p(nodep); } void fromp(AstNode* nodep) { setOp1p(nodep); }
AstNode* bitp() const { return op2p()->castNode(); } // op2 = Msb selection expression AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression
void bitp(AstNode* nodep) { setOp2p(nodep); } void bitp(AstNode* nodep) { setOp2p(nodep); }
int bitConst() const; int bitConst() const;
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
@@ -1818,11 +1846,11 @@ public:
string cname() const { return m_cname; } string cname() const { return m_cname; }
void cname(const string& cname) { m_cname = cname; } void cname(const string& cname) { m_cname = cname; }
// op1 = Output variable (functions only, NULL for tasks) // op1 = Output variable (functions only, NULL for tasks)
AstNode* fvarp() const { return op1p()->castNode(); } AstNode* fvarp() const { return op1p(); }
void addFvarp(AstNode* nodep) { addNOp1p(nodep); } void addFvarp(AstNode* nodep) { addNOp1p(nodep); }
bool isFunction() const { return fvarp()!=NULL; } bool isFunction() const { return fvarp()!=NULL; }
// op3 = Statements/Ports/Vars // op3 = Statements/Ports/Vars
AstNode* stmtsp() const { return op3p()->castNode(); } // op3 = List of statements AstNode* stmtsp() const { return op3p(); } // op3 = List of statements
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
// op4 = scope name // op4 = scope name
AstScopeName* scopeNamep() const { return op4p()->castScopeName(); } AstScopeName* scopeNamep() const { return op4p()->castScopeName(); }
@@ -1867,7 +1895,7 @@ public:
ASTNODE_BASE_FUNCS(NodeFTaskRef) ASTNODE_BASE_FUNCS(NodeFTaskRef)
virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; } virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; }
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) { virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
m_taskp = m_taskp->clonep()->castNodeFTask(); m_taskp = m_taskp->clonep();
}} }}
virtual void dump(ostream& str=cout); virtual void dump(ostream& str=cout);
virtual string name() const { return m_name; } // * = Var name virtual string name() const { return m_name; } // * = Var name
@@ -1885,7 +1913,7 @@ public:
// op1 = namep // op1 = namep
AstNode* namep() const { return op1p(); } AstNode* namep() const { return op1p(); }
// op2 = Pin interconnection list // op2 = Pin interconnection list
AstNode* pinsp() const { return op2p()->castNode(); } AstNode* pinsp() const { return op2p(); }
void addPinsp(AstNode* nodep) { addOp2p(nodep); } void addPinsp(AstNode* nodep) { addOp2p(nodep); }
// op3 = scope tracking // op3 = scope tracking
AstScopeName* scopeNamep() const { return op3p()->castScopeName(); } AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
@@ -1917,7 +1945,7 @@ public:
virtual void dump(ostream& str); virtual void dump(ostream& str);
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
virtual string name() const { return m_name; } virtual string name() const { return m_name; }
AstNode* stmtsp() const { return op2p()->castNode(); } // op2 = List of statements AstNode* stmtsp() const { return op2p(); } // op2 = List of statements
AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks
// METHODS // METHODS
void addInlinesp(AstNode* nodep) { addOp1p(nodep); } void addInlinesp(AstNode* nodep) { addOp1p(nodep); }
@@ -1967,8 +1995,8 @@ inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); } inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); } inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); } inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(node2p, true, false); } inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, false); }
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(node2p, true, true); } inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, true); }
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); } inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
@@ -1979,8 +2007,8 @@ inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsC
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); } inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
inline void AstIfaceRefDType::cloneRelink() { inline void AstIfaceRefDType::cloneRelink() {
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep()->castCell(); if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep();
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep()->castIface(); if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep();
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep()->castModport(); } if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); }
#endif // Guard #endif // Guard
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+11 -5
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -53,7 +53,7 @@ const char* AstNodeVarRef::broken() const {
} }
void AstNodeVarRef::cloneRelink() { void AstNodeVarRef::cloneRelink() {
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep()->castVar(); } if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); }
} }
int AstNodeSel::bitConst() const { int AstNodeSel::bitConst() const {
@@ -195,6 +195,8 @@ string AstVar::verilogKwd() const {
return "tri"; return "tri";
} else if (varType()==AstVarType::WIRE) { } else if (varType()==AstVarType::WIRE) {
return "wire"; return "wire";
} else if (varType()==AstVarType::WREAL) {
return "wreal";
} else { } else {
return dtypep()->name(); return dtypep()->name();
} }
@@ -386,6 +388,7 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
// TODO this function should be removed in favor of recursing the dtype(), // TODO this function should be removed in favor of recursing the dtype(),
// as that allows for more complicated data types. // as that allows for more complicated data types.
int dim = 0; int dim = 0;
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
for (AstNodeDType* dtypep=this; dtypep; ) { for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
@@ -420,6 +423,7 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
uint32_t AstNodeDType::arrayUnpackedElements() { uint32_t AstNodeDType::arrayUnpackedElements() {
uint32_t entries=1; uint32_t entries=1;
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
for (AstNodeDType* dtypep=this; dtypep; ) { for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) { if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
@@ -438,6 +442,7 @@ pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
// How many array dimensions (packed,unpacked) does this Var have? // How many array dimensions (packed,unpacked) does this Var have?
uint32_t packed = 0; uint32_t packed = 0;
uint32_t unpacked = 0; uint32_t unpacked = 0;
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
for (AstNodeDType* dtypep=this; dtypep; ) { for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) { if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
@@ -492,9 +497,9 @@ const char* AstScope::broken() const {
} }
void AstScope::cloneRelink() { void AstScope::cloneRelink() {
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep()->castScope(); if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep();
if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep()->castCell(); if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep();
if (m_modp && ((AstNode*)m_modp)->clonep()) ((AstNode*)m_modp)->clonep()->castNodeModule(); if (m_modp && ((AstNode*)m_modp)->clonep()) ((AstNode*)m_modp)->clonep();
} }
string AstScope::nameDotless() const { string AstScope::nameDotless() const {
@@ -974,6 +979,7 @@ void AstVar::dump(ostream& str) {
if (attrFileDescr()) str<<" [aFD]"; if (attrFileDescr()) str<<" [aFD]";
if (isFuncReturn()) str<<" [FUNCRTN]"; if (isFuncReturn()) str<<" [FUNCRTN]";
else if (isFuncLocal()) str<<" [FUNC]"; else if (isFuncLocal()) str<<" [FUNC]";
if (!attrClocker().unknown()) str<<" ["<<attrClocker().ascii()<<"] ";
str<<" "<<varType(); str<<" "<<varType();
} }
void AstSenTree::dump(ostream& str) { void AstSenTree::dump(ostream& str) {
+547 -353
View File
File diff suppressed because it is too large Load Diff
+39 -14
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -56,7 +56,7 @@ public:
m_anyFuncInBegin = false; m_anyFuncInBegin = false;
} }
~BeginState() {} ~BeginState() {}
void userMarkChanged(AstNodeFTask* nodep) { void userMarkChanged(AstNode* nodep) {
nodep->user1(true); nodep->user1(true);
m_anyFuncInBegin = true; m_anyFuncInBegin = true;
} }
@@ -84,13 +84,13 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
m_repeatNum = 0; m_repeatNum = 0;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep) {
UINFO(8," "<<nodep<<endl); UINFO(8," "<<nodep<<endl);
// Rename it // Rename it
if (m_unnamedScope != "") { if (m_unnamedScope != "") {
@@ -113,7 +113,7 @@ private:
m_namedScope = oldScope; m_namedScope = oldScope;
m_unnamedScope = oldUnnamed; m_unnamedScope = oldUnnamed;
} }
virtual void visit(AstBegin* nodep, AstNUser*) { virtual void visit(AstBegin* nodep) {
// Begin blocks were only useful in variable creation, change names and delete // Begin blocks were only useful in variable creation, change names and delete
UINFO(8," "<<nodep<<endl); UINFO(8," "<<nodep<<endl);
string oldScope = m_namedScope; string oldScope = m_namedScope;
@@ -162,19 +162,21 @@ private:
} }
pushDeletep(nodep); VL_DANGLING(nodep); pushDeletep(nodep); VL_DANGLING(nodep);
} }
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep) {
if (m_unnamedScope != "") { if (m_unnamedScope != "") {
// Rename it // Rename it
nodep->name(m_unnamedScope+"__DOT__"+nodep->name()); nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
m_statep->userMarkChanged(nodep);
// Move to module // Move to module
nodep->unlinkFrBack(); nodep->unlinkFrBack();
if (m_ftaskp) m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func if (m_ftaskp) m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func
else m_modp->addStmtp(nodep); else m_modp->addStmtp(nodep);
} }
} }
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep) {
UINFO(8," CELL "<<nodep<<endl); UINFO(8," CELL "<<nodep<<endl);
if (m_namedScope != "") { if (m_namedScope != "") {
m_statep->userMarkChanged(nodep);
// Rename it // Rename it
nodep->name(m_namedScope+"__DOT__"+nodep->name()); nodep->name(m_namedScope+"__DOT__"+nodep->name());
UINFO(8," rename to "<<nodep->name()<<endl); UINFO(8," rename to "<<nodep->name()<<endl);
@@ -182,8 +184,16 @@ private:
nodep->unlinkFrBack(); nodep->unlinkFrBack();
m_modp->addStmtp(nodep); m_modp->addStmtp(nodep);
} }
nodep->iterateChildren(*this);
} }
virtual void visit(AstScopeName* nodep, AstNUser*) { virtual void visit(AstVarXRef* nodep) {
UINFO(9, " VARXREF "<<nodep<<endl);
if (m_namedScope != "" && nodep->inlinedDots() == "") {
nodep->inlinedDots(m_namedScope);
UINFO(9, " rescope to "<<nodep<<endl);
}
}
virtual void visit(AstScopeName* nodep) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline // Similar code in V3Inline
if (nodep->user1SetOnce()) return; // Don't double-add text's if (nodep->user1SetOnce()) return; // Don't double-add text's
@@ -196,13 +206,13 @@ private:
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstCoverDecl* nodep, AstNUser*) { virtual void visit(AstCoverDecl* nodep) {
// Don't need to fix path in coverage statements, they're not under // Don't need to fix path in coverage statements, they're not under
// any BEGINs, but V3Coverage adds them all under the module itself. // any BEGINs, but V3Coverage adds them all under the module itself.
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// VISITORS - LINT CHECK // VISITORS - LINT CHECK
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered virtual void visit(AstIf* nodep) { // Note not AstNodeIf; other types don't get covered
// Check IFDEPTH warning - could be in other transform files if desire // Check IFDEPTH warning - could be in other transform files if desire
int prevIfDepth = m_ifDepth; int prevIfDepth = m_ifDepth;
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
@@ -215,8 +225,8 @@ private:
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_ifDepth = prevIfDepth; m_ifDepth = prevIfDepth;
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -242,15 +252,30 @@ private:
// AstNodeFTask::user1p // Node replaced, rename it // AstNodeFTask::user1p // Node replaced, rename it
// VISITORS // VISITORS
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep) {
if (nodep->taskp()->user1()) { // It was converted if (nodep->taskp()->user1()) { // It was converted
UINFO(9, " relinkFTask "<<nodep<<endl); UINFO(9, " relinkFTask "<<nodep<<endl);
nodep->name(nodep->taskp()->name()); nodep->name(nodep->taskp()->name());
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstVarRef* nodep) {
if (nodep->varp()->user1()) { // It was converted
UINFO(9, " relinVarRef "<<nodep<<endl);
nodep->name(nodep->varp()->name());
}
nodep->iterateChildren(*this);
}
virtual void visit(AstIfaceRefDType* nodep) {
// May have changed cell names
// TypeTable is always after all modules, so names are stable
UINFO(8," IFACEREFDTYPE "<<nodep<<endl);
if (nodep->cellp()) nodep->cellName(nodep->cellp()->name());
UINFO(8," rename to "<<nodep<<endl);
nodep->iterateChildren(*this);
}
//-------------------- //--------------------
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+5 -5
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -75,7 +75,7 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeIf* nodep, AstNUser*) { virtual void visit(AstNodeIf* nodep) {
UINFO(4," IF: "<<nodep<<endl); UINFO(4," IF: "<<nodep<<endl);
int lastLikely = m_likely; int lastLikely = m_likely;
int lastUnlikely = m_unlikely; int lastUnlikely = m_unlikely;
@@ -101,17 +101,17 @@ private:
m_likely = lastLikely; m_likely = lastLikely;
m_unlikely = lastUnlikely; m_unlikely = lastUnlikely;
} }
virtual void visit(AstCCall* nodep, AstNUser*) { virtual void visit(AstCCall* nodep) {
checkUnlikely(nodep); checkUnlikely(nodep);
nodep->funcp()->user1Inc(); nodep->funcp()->user1Inc();
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
checkUnlikely(nodep); checkUnlikely(nodep);
m_cfuncsp.push_back(nodep); m_cfuncsp.push_back(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
checkUnlikely(nodep); checkUnlikely(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+3 -3
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -192,7 +192,7 @@ private:
nodep->iterateChildrenConst(*this); nodep->iterateChildrenConst(*this);
} }
// VISITORS // VISITORS
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
processAndIterate(nodep); processAndIterate(nodep);
} }
public: public:
@@ -236,7 +236,7 @@ private:
nodep->iterateChildrenConst(*this); nodep->iterateChildrenConst(*this);
BrokenTable::setUnder(nodep,false); BrokenTable::setUnder(nodep,false);
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
processAndIterate(nodep); processAndIterate(nodep);
} }
public: public:
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+117
View File
@@ -0,0 +1,117 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Generate C language constructors and AstCReset nodes.
//
// Code available from: http://www.veripool.org/verilator
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// V3CCtors's Transformations:
// Iterates over all modules and
// for all AstVar, create a creates a AstCReset node in an _ctor_var_reset AstCFunc.
// for all AstCoverDecl, move the declaration into a _configure_coverage AstCFunc.
// For each variable that needs reset, add a AstCReset node.
//
// This transformation honors outputSplitCFuncs.
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
#include "V3Global.h"
#include "V3EmitCBase.h"
#include "V3CCtors.h"
class V3CCtorsVisitor {
private:
string m_basename;
string m_argsp;
string m_callargsp;
AstNodeModule* m_modp; // Current module
AstCFunc* m_tlFuncp; // Top level function being built
AstCFunc* m_funcp; // Current function
int m_numStmts; // Number of statements output
int m_funcNum; // Function number being built
public:
void add(AstNode* nodep) {
if (v3Global.opt.outputSplitCFuncs()
&& v3Global.opt.outputSplitCFuncs() < m_numStmts) {
m_funcp = NULL;
}
if (!m_funcp) {
m_funcp = new AstCFunc(m_modp->fileline(), m_basename + "_" + cvtToStr(++m_funcNum), NULL, "void");
m_funcp->isStatic(false);
m_funcp->declPrivate(true);
m_funcp->slow(true);
m_funcp->argTypes(m_argsp);
m_modp->addStmtp(m_funcp);
// Add a top call to it
AstCCall* callp = new AstCCall(m_modp->fileline(), m_funcp);
callp->argTypes(m_callargsp);
m_tlFuncp->addStmtsp(callp);
m_numStmts = 0;
}
m_funcp->addStmtsp(nodep);
m_numStmts += 1;
}
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="") {
m_basename = basename;
m_argsp = argsp;
m_callargsp = callargsp;
m_modp = nodep;
m_numStmts = 0;
m_funcNum = 0;
m_tlFuncp = new AstCFunc(nodep->fileline(), basename, NULL, "void");
m_tlFuncp->declPrivate(true);
m_tlFuncp->isStatic(false);
m_tlFuncp->slow(true);
m_tlFuncp->argTypes(m_argsp);
m_funcp = m_tlFuncp;
m_modp->addStmtp(m_tlFuncp);
}
};
//######################################################################
void V3CCtors::cctorsAll() {
UINFO(2,__FUNCTION__<<": "<<endl);
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
// Process each module in turn
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
V3CCtorsVisitor configure_coverage (modp, "_configure_coverage",
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first");
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
AstVar* varp = np->castVar();
if (varp) var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
AstCoverDecl* coverp = np->castCoverDecl();
if (coverp) {
AstNode* backp = coverp->backp();
coverp->unlinkFrBack();
configure_coverage.add(coverp);
np = backp;
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit CFunc's for class construction and configuration
//
// Code available from: http://www.veripool.org/verilator
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3CCTORS_H_
#define _V3CCTORS_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3CCtors {
public:
static void cctorsAll();
};
#endif // Guard
+6 -6
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -65,7 +65,7 @@ private:
return level; return level;
} }
virtual void visit(AstNodeCase* nodep, AstNUser*) { virtual void visit(AstNodeCase* nodep) {
if (nodep->castCase() && nodep->castCase()->casex()) { if (nodep->castCase() && nodep->castCase()->casex()) {
nodep->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)"); nodep->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)");
} }
@@ -90,7 +90,7 @@ private:
m_caseExprp = NULL; m_caseExprp = NULL;
} }
} }
virtual void visit(AstConst* nodep, AstNUser*) { virtual void visit(AstConst* nodep) {
// See also neverItem // See also neverItem
if (m_caseExprp && nodep->num().isFourState()) { if (m_caseExprp && nodep->num().isFourState()) {
if (m_caseExprp->castGenCase()) { if (m_caseExprp->castGenCase()) {
@@ -107,7 +107,7 @@ private:
} }
} }
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -451,7 +451,7 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstCase* nodep, AstNUser*) { virtual void visit(AstCase* nodep) {
V3Case::caseLint(nodep); V3Case::caseLint(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (debug()>=9) nodep->dumpTree(cout," case_old: "); if (debug()>=9) nodep->dumpTree(cout," case_old: ");
@@ -467,7 +467,7 @@ private:
} }
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+10 -10
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can // Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -107,19 +107,19 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeUniop* nodep, AstNUser*) { virtual void visit(AstNodeUniop* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1()); nodep->user1(nodep->lhsp()->user1());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp()); if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
} }
virtual void visit(AstNodeBiop* nodep, AstNUser*) { virtual void visit(AstNodeBiop* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1() nodep->user1(nodep->lhsp()->user1()
| nodep->rhsp()->user1()); | nodep->rhsp()->user1());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp()); if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp()); if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
} }
virtual void visit(AstNodeTriop* nodep, AstNUser*) { virtual void visit(AstNodeTriop* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1() nodep->user1(nodep->lhsp()->user1()
| nodep->rhsp()->user1() | nodep->rhsp()->user1()
@@ -128,12 +128,12 @@ private:
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp()); if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp()); if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
} }
virtual void visit(AstCCast* nodep, AstNUser*) { virtual void visit(AstCCast* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureLower32Cast(nodep); insureLower32Cast(nodep);
nodep->user1(1); nodep->user1(1);
} }
virtual void visit(AstNegate* nodep, AstNUser*) { virtual void visit(AstNegate* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1()); nodep->user1(nodep->lhsp()->user1());
if (nodep->lhsp()->widthMin()==1) { if (nodep->lhsp()->widthMin()==1) {
@@ -145,7 +145,7 @@ private:
insureCast(nodep->lhsp()); insureCast(nodep->lhsp());
} }
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
if (!nodep->lvalue() if (!nodep->lvalue()
&& !nodep->backp()->castCCast() && !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath() && nodep->backp()->castNodeMath()
@@ -158,7 +158,7 @@ private:
} }
nodep->user1(1); nodep->user1(1);
} }
virtual void visit(AstConst* nodep, AstNUser*) { virtual void visit(AstConst* nodep) {
// Constants are of unknown size if smaller than 33 bits, becase // Constants are of unknown size if smaller than 33 bits, becase
// we're too lazy to wrap every constant in the universe in // we're too lazy to wrap every constant in the universe in
// ((IData)#). // ((IData)#).
@@ -166,11 +166,11 @@ private:
} }
// NOPs // NOPs
virtual void visit(AstVar* nodep, AstNUser*) {} virtual void visit(AstVar* nodep) {}
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can // Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+27 -27
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -138,7 +138,7 @@ private:
ofstream* m_ofp; // Output file ofstream* m_ofp; // Output file
string m_prefix; string m_prefix;
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
*m_ofp<<m_prefix; *m_ofp<<m_prefix;
if (nodep->user3()) *m_ofp<<" %%"; if (nodep->user3()) *m_ofp<<" %%";
else *m_ofp<<" "; else *m_ofp<<" ";
@@ -172,7 +172,7 @@ private:
int m_maxLineno; int m_maxLineno;
size_t m_maxFilenameLen; size_t m_maxFilenameLen;
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Keeping line+filename lengths separate is much faster than calling ascii().length() // Keeping line+filename lengths separate is much faster than calling ascii().length()
if (nodep->fileline()->lineno() >= m_maxLineno) { if (nodep->fileline()->lineno() >= m_maxLineno) {
@@ -604,19 +604,19 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep) {
UINFO(4," SCOPE "<<nodep<<endl); UINFO(4," SCOPE "<<nodep<<endl);
m_scopep = nodep; m_scopep = nodep;
m_logicVertexp = NULL; m_logicVertexp = NULL;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_scopep = NULL; m_scopep = NULL;
} }
virtual void visit(AstActive* nodep, AstNUser*) { virtual void visit(AstActive* nodep) {
// Create required blocks and add to module // Create required blocks and add to module
UINFO(4," BLOCK "<<nodep<<endl); UINFO(4," BLOCK "<<nodep<<endl);
AstNode::user2ClearTree(); AstNode::user2ClearTree();
@@ -627,7 +627,7 @@ private:
m_domainp = NULL; m_domainp = NULL;
AstNode::user2ClearTree(); AstNode::user2ClearTree();
} }
virtual void visit(AstNodeVarRef* nodep, AstNUser*) { virtual void visit(AstNodeVarRef* nodep) {
if (m_scopep) { if (m_scopep) {
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n"); if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
AstVarScope* varscp = nodep->varScopep(); AstVarScope* varscp = nodep->varScopep();
@@ -655,72 +655,72 @@ private:
} }
} }
} }
virtual void visit(AstAssignDly* nodep, AstNUser*) { virtual void visit(AstAssignDly* nodep) {
m_inDly = true; m_inDly = true;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_inDly = false; m_inDly = false;
} }
virtual void visit(AstSenItem* nodep, AstNUser*) { virtual void visit(AstSenItem* nodep) {
// Note we look at only AstSenItems, not AstSenGate's // Note we look at only AstSenItems, not AstSenGate's
// The gating term of a AstSenGate is normal logic // The gating term of a AstSenGate is normal logic
m_inSenItem = true; m_inSenItem = true;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_inSenItem = false; m_inSenItem = false;
} }
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep) {
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { virtual void visit(AstAlwaysPublic* nodep) {
// CDC doesn't care about public variables // CDC doesn't care about public variables
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
virtual void visit(AstSenGate* nodep, AstNUser*) { virtual void visit(AstSenGate* nodep) {
// First handle the clock part will be handled in a minute by visit AstSenItem // First handle the clock part will be handled in a minute by visit AstSenItem
// The logic gating term is delt with as logic // The logic gating term is delt with as logic
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
virtual void visit(AstAssignAlias* nodep, AstNUser*) { virtual void visit(AstAssignAlias* nodep) {
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
virtual void visit(AstAssignW* nodep, AstNUser*) { virtual void visit(AstAssignW* nodep) {
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
// Math that shouldn't cause us to clear hazard // Math that shouldn't cause us to clear hazard
virtual void visit(AstConst* nodep, AstNUser*) { } virtual void visit(AstConst* nodep) { }
virtual void visit(AstReplicate* nodep, AstNUser*) { virtual void visit(AstReplicate* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstConcat* nodep, AstNUser*) { virtual void visit(AstConcat* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstNot* nodep, AstNUser*) { virtual void visit(AstNot* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstSel* nodep, AstNUser*) { virtual void visit(AstSel* nodep) {
if (!nodep->lsbp()->castConst()) setNodeHazard(nodep); if (!nodep->lsbp()->castConst()) setNodeHazard(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstNodeSel* nodep, AstNUser*) { virtual void visit(AstNodeSel* nodep) {
if (!nodep->bitp()->castConst()) setNodeHazard(nodep); if (!nodep->bitp()->castConst()) setNodeHazard(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// Ignores // Ignores
virtual void visit(AstInitial* nodep, AstNUser*) { } virtual void visit(AstInitial* nodep) { }
virtual void visit(AstTraceInc* nodep, AstNUser*) { } virtual void visit(AstTraceInc* nodep) { }
virtual void visit(AstCoverToggle* nodep, AstNUser*) { } virtual void visit(AstCoverToggle* nodep) { }
virtual void visit(AstNodeDType* nodep, AstNUser*) { } virtual void visit(AstNodeDType* nodep) { }
//-------------------- //--------------------
// Default // Default
virtual void visit(AstNodeMath* nodep, AstNUser*) { virtual void visit(AstNodeMath* nodep) {
setNodeHazard(nodep); setNodeHazard(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+69 -19
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -51,12 +51,54 @@ public:
AstNodeModule* m_topModp; // Top module AstNodeModule* m_topModp; // Top module
AstScope* m_scopetopp; // Scope under TOPSCOPE AstScope* m_scopetopp; // Scope under TOPSCOPE
AstCFunc* m_chgFuncp; // Change function we're building AstCFunc* m_chgFuncp; // Change function we're building
AstCFunc* m_tlChgFuncp; // Top level change function we're building
int m_numStmts; // Number of statements added to m_chgFuncp
int m_funcNum; // Number of change functions emitted
ChangedState() { ChangedState() {
m_topModp = NULL; m_topModp = NULL;
m_chgFuncp = NULL; m_chgFuncp = NULL;
m_scopetopp = NULL; m_scopetopp = NULL;
m_tlChgFuncp = NULL;
m_numStmts = 0;
m_funcNum = 0;
} }
~ChangedState() {} ~ChangedState() {}
void maybeCreateChgFuncp() {
// Don't create an extra function call if splitting is disabled
if (!v3Global.opt.outputSplitCFuncs()) {
m_chgFuncp = m_tlChgFuncp;
return;
}
if (!m_chgFuncp || v3Global.opt.outputSplitCFuncs() < m_numStmts) {
m_chgFuncp = new AstCFunc(m_scopetopp->fileline(), "_change_request_" + cvtToStr(++m_funcNum), m_scopetopp, "QData");
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_chgFuncp->symProlog(true);
m_chgFuncp->declPrivate(true);
m_scopetopp->addActivep(m_chgFuncp);
// Add a top call to it
AstCCall* callp = new AstCCall(m_scopetopp->fileline(), m_chgFuncp);
callp->argTypes("vlSymsp");
if (!m_tlChgFuncp->stmtsp()) {
m_tlChgFuncp->addStmtsp(new AstCReturn(m_scopetopp->fileline(), callp));
} else {
AstCReturn* returnp = m_tlChgFuncp->stmtsp()->castCReturn();
if (!returnp) m_scopetopp->v3fatalSrc("Lost CReturn in top change function");
// This is currently using AstLogOr which will shortcut the evaluation if
// any function returns true. This is likely what we want and is similar to the logic already in use
// inside V3EmitC, however, it also means that verbose logging may miss to print change detect variables.
AstNode* newp = new AstCReturn(m_scopetopp->fileline(),
new AstLogOr(m_scopetopp->fileline(), callp,
returnp->lhsp()->unlinkFrBack()));
returnp->replaceWith(newp);
returnp->deleteTree(); VL_DANGLING(returnp);
}
m_numStmts = 0;
}
}
}; };
//###################################################################### //######################################################################
@@ -87,6 +129,8 @@ private:
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl); <<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl);
return; return;
} }
m_statep->maybeCreateChgFuncp();
AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(), AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(),
m_varEqnp->cloneTree(true), m_varEqnp->cloneTree(true),
m_newRvEqnp->cloneTree(true), false); m_newRvEqnp->cloneTree(true), false);
@@ -95,15 +139,17 @@ private:
m_newLvEqnp->cloneTree(true), m_newLvEqnp->cloneTree(true),
m_varEqnp->cloneTree(true)); m_varEqnp->cloneTree(true));
m_statep->m_chgFuncp->addFinalsp(initp); m_statep->m_chgFuncp->addFinalsp(initp);
EmitCBaseCounterVisitor visitor(initp);
m_statep->m_numStmts += visitor.count();
} }
virtual void visit(AstBasicDType* nodep, AstNUser*) { virtual void visit(AstBasicDType* nodep) {
newChangeDet(); newChangeDet();
} }
virtual void visit(AstPackArrayDType* nodep, AstNUser*) { virtual void visit(AstPackArrayDType* nodep) {
newChangeDet(); newChangeDet();
} }
virtual void visit(AstUnpackArrayDType* nodep, AstNUser*) { virtual void visit(AstUnpackArrayDType* nodep) {
for (int index=0; index < nodep->elementsConst(); ++index) { for (int index=0; index < nodep->elementsConst(); ++index) {
AstNode* origVEp = m_varEqnp; AstNode* origVEp = m_varEqnp;
AstNode* origNLEp = m_newLvEqnp; AstNode* origNLEp = m_newLvEqnp;
@@ -124,7 +170,7 @@ private:
m_newRvEqnp = origNREp; m_newRvEqnp = origNREp;
} }
} }
virtual void visit(AstNodeClassDType* nodep, AstNUser*) { virtual void visit(AstNodeClassDType* nodep) {
if (nodep->packedUnsup()) { if (nodep->packedUnsup()) {
newChangeDet(); newChangeDet();
} else { } else {
@@ -132,7 +178,7 @@ private:
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName()); m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
} }
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-"); if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-");
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName()); m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
@@ -193,14 +239,15 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
if (nodep->isTop()) { if (nodep->isTop()) {
m_statep->m_topModp = nodep; m_statep->m_topModp = nodep;
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstTopScope* nodep, AstNUser*) {
virtual void visit(AstTopScope* nodep) {
UINFO(4," TS "<<nodep<<endl); UINFO(4," TS "<<nodep<<endl);
// Clearing // Clearing
AstNode::user1ClearTree(); AstNode::user1ClearTree();
@@ -208,18 +255,21 @@ private:
AstScope* scopep = nodep->scopep(); AstScope* scopep = nodep->scopep();
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n"); if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
m_statep->m_scopetopp = scopep; m_statep->m_scopetopp = scopep;
// Create change detection function
m_statep->m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData"); // Create a wrapper change detection function that calls each change detection function
m_statep->m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar()); m_statep->m_tlChgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
m_statep->m_chgFuncp->symProlog(true); m_statep->m_tlChgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_statep->m_chgFuncp->declPrivate(true); m_statep->m_tlChgFuncp->symProlog(true);
m_statep->m_scopetopp->addActivep(m_statep->m_chgFuncp); m_statep->m_tlChgFuncp->declPrivate(true);
// We need at least one change detect so we know to emit the correct code m_statep->m_scopetopp->addActivep(m_statep->m_tlChgFuncp);
// Each change detection function needs at least one AstChangeDet
// to ensure that V3EmitC outputs the necessary code.
m_statep->maybeCreateChgFuncp();
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false)); m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
//
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep) {
if (nodep->isCircular()) { if (nodep->isCircular()) {
UINFO(8," CIRC "<<nodep<<endl); UINFO(8," CIRC "<<nodep<<endl);
if (!nodep->user1SetOnce()) { if (!nodep->user1SetOnce()) {
@@ -227,12 +277,12 @@ private:
} }
} }
} }
virtual void visit(AstNodeMath* nodep, AstNUser*) { virtual void visit(AstNodeMath* nodep) {
// Short-circuit // Short-circuit
} }
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+28 -23
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -78,7 +78,7 @@ private:
if (old_dtypep->width() != width) { if (old_dtypep->width() != width) {
// Since any given dtype's cppWidth() is the same, we can just // Since any given dtype's cppWidth() is the same, we can just
// remember one convertion for each, and reuse it // remember one convertion for each, and reuse it
if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNode()->castNodeDType()) { if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNodeDType()) {
nodep->dtypep(new_dtypep); nodep->dtypep(new_dtypep);
} else { } else {
nodep->dtypeChgWidth(width, nodep->widthMin()); nodep->dtypeChgWidth(width, nodep->widthMin());
@@ -173,12 +173,12 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstNodeUniop* nodep, AstNUser*) { virtual void visit(AstNodeUniop* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
computeCppWidth(nodep); computeCppWidth(nodep);
if (nodep->cleanLhs()) { if (nodep->cleanLhs()) {
@@ -186,45 +186,45 @@ private:
} }
setClean (nodep, nodep->cleanOut()); setClean (nodep, nodep->cleanOut());
} }
virtual void visit(AstNodeBiop* nodep, AstNUser*) { virtual void visit(AstNodeBiop* nodep) {
operandBiop(nodep); operandBiop(nodep);
setClean (nodep, nodep->cleanOut()); setClean (nodep, nodep->cleanOut());
} }
virtual void visit(AstAnd* nodep, AstNUser*) { virtual void visit(AstAnd* nodep) {
operandBiop(nodep); operandBiop(nodep);
setClean (nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp())); setClean (nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp()));
} }
virtual void visit(AstXor* nodep, AstNUser*) { virtual void visit(AstXor* nodep) {
operandBiop(nodep); operandBiop(nodep);
setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp())); setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
} }
virtual void visit(AstOr* nodep, AstNUser*) { virtual void visit(AstOr* nodep) {
operandBiop(nodep); operandBiop(nodep);
setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp())); setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
} }
virtual void visit(AstNodeMath* nodep, AstNUser*) { virtual void visit(AstNodeMath* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
computeCppWidth(nodep); computeCppWidth(nodep);
setClean (nodep, nodep->cleanOut()); setClean (nodep, nodep->cleanOut());
} }
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
computeCppWidth(nodep); computeCppWidth(nodep);
if (nodep->cleanRhs()) { if (nodep->cleanRhs()) {
insureClean(nodep->rhsp()); insureClean(nodep->rhsp());
} }
} }
virtual void visit(AstText* nodep, AstNUser*) { virtual void visit(AstText* nodep) {
setClean (nodep, true); setClean (nodep, true);
} }
virtual void visit(AstScopeName* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep) {
setClean (nodep, true); setClean (nodep, true);
} }
virtual void visit(AstSel* nodep, AstNUser*) { virtual void visit(AstSel* nodep) {
operandTriop(nodep); operandTriop(nodep);
setClean (nodep, nodep->cleanOut()); setClean (nodep, nodep->cleanOut());
} }
virtual void visit(AstUCFunc* nodep, AstNUser*) { virtual void visit(AstUCFunc* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
computeCppWidth(nodep); computeCppWidth(nodep);
setClean (nodep, false); setClean (nodep, false);
@@ -234,46 +234,51 @@ private:
} }
insureCleanAndNext (nodep->bodysp()); insureCleanAndNext (nodep->bodysp());
} }
virtual void visit(AstTraceInc* nodep, AstNUser*) { virtual void visit(AstTraceInc* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->valuep()); insureCleanAndNext (nodep->valuep());
} }
virtual void visit(AstTypedef* nodep, AstNUser*) { virtual void visit(AstTypedef* nodep) {
// No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this);
}
virtual void visit(AstParamTypeDType* nodep) {
// No cleaning, or would loose pointer to enum // No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// Control flow operators // Control flow operators
virtual void visit(AstNodeCond* nodep, AstNUser*) { virtual void visit(AstNodeCond* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureClean(nodep->condp()); insureClean(nodep->condp());
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p())); setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
} }
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureClean(nodep->condp()); insureClean(nodep->condp());
} }
virtual void visit(AstNodeIf* nodep, AstNUser*) { virtual void visit(AstNodeIf* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureClean(nodep->condp()); insureClean(nodep->condp());
} }
virtual void visit(AstSFormatF* nodep, AstNUser*) { virtual void visit(AstSFormatF* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->exprsp()); insureCleanAndNext (nodep->exprsp());
setClean(nodep, true); // generates a string, so not relevant setClean(nodep, true); // generates a string, so not relevant
} }
virtual void visit(AstUCStmt* nodep, AstNUser*) { virtual void visit(AstUCStmt* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->bodysp()); insureCleanAndNext (nodep->bodysp());
} }
virtual void visit(AstCCall* nodep, AstNUser*) { virtual void visit(AstCCall* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->argsp()); insureCleanAndNext (nodep->argsp());
setClean (nodep, true);
} }
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
computeCppWidth(nodep); computeCppWidth(nodep);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+21 -21
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2008-2015 by Wilson Snyder. This program is free software; you can // Copyright 2008-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -199,19 +199,19 @@ private:
if (m_isSimple) nodep->iterateChildren(*this); if (m_isSimple) nodep->iterateChildren(*this);
} }
// VISITORS // VISITORS
virtual void visit(AstOr* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstOr* nodep) { okIterate(nodep); }
virtual void visit(AstAnd* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstAnd* nodep) { okIterate(nodep); }
virtual void visit(AstNot* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstNot* nodep) { okIterate(nodep); }
virtual void visit(AstLogOr* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstLogOr* nodep) { okIterate(nodep); }
virtual void visit(AstLogAnd* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstLogAnd* nodep) { okIterate(nodep); }
virtual void visit(AstLogNot* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstLogNot* nodep) { okIterate(nodep); }
virtual void visit(AstVarRef* nodep, AstNUser*) { okIterate(nodep); } virtual void visit(AstVarRef* nodep) { okIterate(nodep); }
// Other possibilities are equals, etc // Other possibilities are equals, etc
// But, we don't want to get too complicated or it will take too much // But, we don't want to get too complicated or it will take too much
// effort to calculate the gater // effort to calculate the gater
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
m_isSimple = false; m_isSimple = false;
//nodep->iterateChildren(*this); //nodep->iterateChildren(*this);
} }
@@ -248,10 +248,10 @@ class GaterBodyVisitor : public GaterBaseVisitor {
uint32_t m_state; // Parsing state uint32_t m_state; // Parsing state
// VISITORS // VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
if (nodep->lvalue()) { if (nodep->lvalue()) {
AstVarScope* vscp = nodep->varScopep(); AstVarScope* vscp = nodep->varScopep();
if (vscp->user2p()->castNode() == m_exprp) { if (vscp->user2p() == m_exprp) {
// This variable's block needs to move to the new always // This variable's block needs to move to the new always
if (m_original) { if (m_original) {
UINFO(9," VARREF delete in old: "<<nodep<<endl); UINFO(9," VARREF delete in old: "<<nodep<<endl);
@@ -272,11 +272,11 @@ class GaterBodyVisitor : public GaterBaseVisitor {
} }
} }
//virtual void visit(AstNodeIf* nodep, AstNUser*) { ... } //virtual void visit(AstNodeIf* nodep) { ... }
// Not needed, it's the same handling as any other statement. Cool, huh? // Not needed, it's the same handling as any other statement. Cool, huh?
// (We may get empty IFs but the constant propagater will rip them up for us) // (We may get empty IFs but the constant propagater will rip them up for us)
virtual void visit(AstNodeStmt* nodep, AstNUser*) { virtual void visit(AstNodeStmt* nodep) {
uint32_t oldstate = m_state; uint32_t oldstate = m_state;
// Find if children want to delete this or not. // Find if children want to delete this or not.
// Note children may bicker, and want to both keep and delete (branches on a if) // Note children may bicker, and want to both keep and delete (branches on a if)
@@ -304,7 +304,7 @@ class GaterBodyVisitor : public GaterBaseVisitor {
m_state |= STATE_KEEP; m_state |= STATE_KEEP;
} }
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -701,7 +701,7 @@ class GaterVisitor : public GaterBaseVisitor {
} }
// VISITORS // VISITORS
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep) {
if (debug()>=9) cout<<endl<<endl<<endl; if (debug()>=9) cout<<endl<<endl<<endl;
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl); UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
if (nodep->user4SetOnce()) return; if (nodep->user4SetOnce()) return;
@@ -751,7 +751,7 @@ class GaterVisitor : public GaterBaseVisitor {
} }
UINFO(5, " Gater done"<<endl); UINFO(5, " Gater done"<<endl);
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
if (nodep->lvalue()) { if (nodep->lvalue()) {
AstVarScope* vscp = nodep->varScopep(); AstVarScope* vscp = nodep->varScopep();
if (nodep->varp()->isSigPublic()) { if (nodep->varp()->isSigPublic()) {
@@ -778,7 +778,7 @@ class GaterVisitor : public GaterBaseVisitor {
} }
} }
} }
virtual void visit(AstNodeIf* nodep, AstNUser*) { virtual void visit(AstNodeIf* nodep) {
m_ifDepth++; m_ifDepth++;
bool allowGater = m_directlyUnderAlw && m_ifDepth <= IF_DEPTH_MAX; bool allowGater = m_directlyUnderAlw && m_ifDepth <= IF_DEPTH_MAX;
if (allowGater) { if (allowGater) {
@@ -819,12 +819,12 @@ class GaterVisitor : public GaterBaseVisitor {
m_ifDepth--; m_ifDepth--;
} }
virtual void visit(AstAssignDly* nodep, AstNUser*) { virtual void visit(AstAssignDly* nodep) {
// iterateChildrenAlw will detect this is a statement for us // iterateChildrenAlw will detect this is a statement for us
iterateChildrenAlw(nodep, false); iterateChildrenAlw(nodep, false);
} }
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep) {
// Note NOT AssignDly; handled above, We'll just mark this block as // Note NOT AssignDly; handled above, We'll just mark this block as
// not optimizable. // not optimizable.
// //
@@ -836,7 +836,7 @@ class GaterVisitor : public GaterBaseVisitor {
// No reason to iterate. // No reason to iterate.
} }
virtual void visit(AstSenItem* nodep, AstNUser*) { virtual void visit(AstSenItem* nodep) {
if (!nodep->isClocked()) { if (!nodep->isClocked()) {
nonOptimizable(nodep, "Non-clocked sensitivity"); nonOptimizable(nodep, "Non-clocked sensitivity");
} }
@@ -844,7 +844,7 @@ class GaterVisitor : public GaterBaseVisitor {
} }
//-------------------- //--------------------
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
if (m_nonopt=="") { // Else accelerate if (m_nonopt=="") { // Else accelerate
iterateChildrenAlw(nodep, false); iterateChildrenAlw(nodep, false);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+18 -12
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -108,6 +108,12 @@ private:
// HIGHEDGE: var // HIGHEDGE: var
// LOWEDGE: ~var // LOWEDGE: ~var
AstNode* newp = NULL; AstNode* newp = NULL;
if (nodep->edgeType()==AstEdgeType::ET_ILLEGAL) {
if (!v3Global.opt.bboxUnsup()) {
nodep->v3error("Unsupported: Complicated event expression in sensitive activity list");
}
return NULL;
}
AstVarScope* clkvscp = nodep->varrefp()->varScopep(); AstVarScope* clkvscp = nodep->varrefp()->varScopep();
if (nodep->edgeType()==AstEdgeType::ET_POSEDGE) { if (nodep->edgeType()==AstEdgeType::ET_POSEDGE) {
AstVarScope* lastVscp = getCreateLastClk(clkvscp); AstVarScope* lastVscp = getCreateLastClk(clkvscp);
@@ -182,7 +188,7 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstTopScope* nodep, AstNUser*) { virtual void visit(AstTopScope* nodep) {
UINFO(4," TOPSCOPE "<<nodep<<endl); UINFO(4," TOPSCOPE "<<nodep<<endl);
m_topScopep=nodep; m_topScopep=nodep;
m_scopep = nodep->scopep(); m_scopep = nodep->scopep();
@@ -243,14 +249,14 @@ private:
m_topScopep=NULL; m_topScopep=NULL;
m_scopep = NULL; m_scopep = NULL;
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
//UINFO(4," MOD "<<nodep<<endl); //UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep; m_modp = nodep;
m_stableNum = 0; m_stableNum = 0;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp= NULL; m_modp= NULL;
} }
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep) {
//UINFO(4," SCOPE "<<nodep<<endl); //UINFO(4," SCOPE "<<nodep<<endl);
m_scopep = nodep; m_scopep = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -261,7 +267,7 @@ private:
} }
m_scopep = NULL; m_scopep = NULL;
} }
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep) {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName()); AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
nodep->replaceWith(cmtp); nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) { if (AstNode* stmtsp = nodep->bodysp()) {
@@ -270,7 +276,7 @@ private:
} }
nodep->deleteTree(); VL_DANGLING(nodep); nodep->deleteTree(); VL_DANGLING(nodep);
} }
virtual void visit(AstAlwaysPost* nodep, AstNUser*) { virtual void visit(AstAlwaysPost* nodep) {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName()); AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
nodep->replaceWith(cmtp); nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) { if (AstNode* stmtsp = nodep->bodysp()) {
@@ -279,7 +285,7 @@ private:
} }
nodep->deleteTree(); VL_DANGLING(nodep); nodep->deleteTree(); VL_DANGLING(nodep);
} }
virtual void visit(AstCoverToggle* nodep, AstNUser*) { virtual void visit(AstCoverToggle* nodep) {
//nodep->dumpTree(cout,"ct:"); //nodep->dumpTree(cout,"ct:");
//COVERTOGGLE(INC, ORIG, CHANGE) -> //COVERTOGGLE(INC, ORIG, CHANGE) ->
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; } // IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
@@ -299,7 +305,7 @@ private:
origp->cloneTree(false))); origp->cloneTree(false)));
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
} }
virtual void visit(AstInitial* nodep, AstNUser*) { virtual void visit(AstInitial* nodep) {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName()); AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
nodep->replaceWith(cmtp); nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) { if (AstNode* stmtsp = nodep->bodysp()) {
@@ -308,7 +314,7 @@ private:
} }
nodep->deleteTree(); VL_DANGLING(nodep); nodep->deleteTree(); VL_DANGLING(nodep);
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Link to global function // Link to global function
if (nodep->formCallTree()) { if (nodep->formCallTree()) {
@@ -318,7 +324,7 @@ private:
m_finalFuncp->addStmtsp(callp); m_finalFuncp->addStmtsp(callp);
} }
} }
virtual void visit(AstSenTree* nodep, AstNUser*) { virtual void visit(AstSenTree* nodep) {
// Delete it later; Actives still pointing to it // Delete it later; Actives still pointing to it
nodep->unlinkFrBack(); nodep->unlinkFrBack();
pushDeletep(nodep); pushDeletep(nodep);
@@ -335,7 +341,7 @@ private:
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
} }
virtual void visit(AstActive* nodep, AstNUser*) { virtual void visit(AstActive* nodep) {
// Careful if adding variables here, ACTIVES can be under other ACTIVES // Careful if adding variables here, ACTIVES can be under other ACTIVES
// Need to save and restore any member state in AstUntilStable block // Need to save and restore any member state in AstUntilStable block
if (!m_topScopep || !nodep->stmtsp()) { if (!m_topScopep || !nodep->stmtsp()) {
@@ -380,7 +386,7 @@ private:
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+14 -14
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -134,13 +134,13 @@ public:
} }
private: private:
// VISITORS // VISITORS
virtual void visit(AstCCall* nodep, AstNUser*) { virtual void visit(AstCCall* nodep) {
addCall(nodep); addCall(nodep);
} }
// Speed things up // Speed things up
virtual void visit(AstNodeAssign* nodep, AstNUser*) {} virtual void visit(AstNodeAssign* nodep) {}
virtual void visit(AstNodeMath* nodep, AstNUser*) {} virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -163,7 +163,7 @@ private:
// OUTPUT: // OUTPUT:
// AstNode::user3() -> bool. True to indicate duplicated // AstNode::user3() -> bool. True to indicate duplicated
// VISITORS // VISITORS
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->user3(true); nodep->user3(true);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -389,7 +389,7 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) { virtual void visit(AstNetlist* nodep) {
// Track all callers of each function // Track all callers of each function
m_call.main(nodep); m_call.main(nodep);
// //
@@ -398,7 +398,7 @@ private:
// Required so that a module instantiating another can benefit from collapsing. // Required so that a module instantiating another can benefit from collapsing.
nodep->iterateChildrenBackwards(*this); nodep->iterateChildrenBackwards(*this);
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep; m_modp = nodep;
m_modNFuncs = 0; m_modNFuncs = 0;
@@ -426,7 +426,7 @@ private:
} }
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
m_funcp = nodep; m_funcp = nodep;
if (!nodep->dontCombine()) { if (!nodep->dontCombine()) {
if (m_state == STATE_HASH) { if (m_state == STATE_HASH) {
@@ -437,7 +437,7 @@ private:
} }
m_funcp = NULL; m_funcp = NULL;
} }
virtual void visit(AstNodeStmt* nodep, AstNUser*) { virtual void visit(AstNodeStmt* nodep) {
if (m_state == STATE_HASH && m_funcp) { if (m_state == STATE_HASH && m_funcp) {
hashStatement(nodep); hashStatement(nodep);
} }
@@ -448,10 +448,10 @@ private:
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstVar*, AstNUser*) {} virtual void visit(AstVar*) {}
virtual void visit(AstTraceDecl*, AstNUser*) {} virtual void visit(AstTraceDecl*) {}
virtual void visit(AstTraceInc*, AstNUser*) {} virtual void visit(AstTraceInc*) {}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can // Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can // Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+86 -73
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -33,6 +33,7 @@
#include <algorithm> #include <algorithm>
#include "V3Global.h" #include "V3Global.h"
#include "V3String.h"
#include "V3Const.h" #include "V3Const.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3Width.h" #include "V3Width.h"
@@ -46,10 +47,10 @@ class ConstVarMarkVisitor : public AstNVisitor {
// AstVar::user4p -> bool, Var marked, 0=not set yet // AstVar::user4p -> bool, Var marked, 0=not set yet
private: private:
// VISITORS // VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
if (nodep->varp()) nodep->varp()->user4(1); if (nodep->varp()) nodep->varp()->user4(1);
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -68,17 +69,17 @@ class ConstVarFindVisitor : public AstNVisitor {
bool m_found; bool m_found;
private: private:
// VISITORS // VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
if (nodep->varp() && nodep->varp()->user4()) m_found = true; if (nodep->varp() && nodep->varp()->user4()) m_found = true;
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
explicit ConstVarFindVisitor(AstNode* nodep) { explicit ConstVarFindVisitor(AstNode* nodep) {
m_found = false; m_found = false;
nodep->iterateAndNext(*this, NULL); nodep->iterateAndNext(*this);
} }
virtual ~ConstVarFindVisitor() {} virtual ~ConstVarFindVisitor() {}
// METHODS // METHODS
@@ -450,7 +451,6 @@ private:
if (!ifvarp || !elsevarp) return false; if (!ifvarp || !elsevarp) return false;
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
if (!ifvarp->sameGateTree(elsevarp)) return false; if (!ifvarp->sameGateTree(elsevarp)) return false;
UINFO(1,"HERE "<<nodep<<endl);
if (!ifp->rhsp()->gateTree()) return false; if (!ifp->rhsp()->gateTree()) return false;
if (!elsep->rhsp()->gateTree()) return false; if (!elsep->rhsp()->gateTree()) return false;
return true; return true;
@@ -808,8 +808,8 @@ private:
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node // like a AstExtend{$rhsp}, but we need to set the width correctly from base node
arg0p->unlinkFrBack(); arg0p->unlinkFrBack();
AstNode* newp = (nodep->castExtendS() AstNode* newp = (nodep->castExtendS()
? (new AstExtendS(nodep->fileline(), arg0p))->castNode() ? static_cast<AstNode*>(new AstExtendS(nodep->fileline(), arg0p))
: (new AstExtend (nodep->fileline(), arg0p))->castNode()); : static_cast<AstNode*>(new AstExtend (nodep->fileline(), arg0p)));
newp->dtypeFrom(nodep); newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep); nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
} }
@@ -1037,10 +1037,8 @@ private:
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign(); AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
asn1ap->dtypeFrom(sel1p); asn1ap->dtypeFrom(sel1p);
asn2ap->dtypeFrom(sel2p); asn2ap->dtypeFrom(sel2p);
// cppcheck-suppress nullPointer // addNext deals with it newp = AstNode::addNext(newp, asn1ap);
newp = newp->addNext(asn1ap); newp = AstNode::addNext(newp, asn2ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2ap);
} else { } else {
if (!m_modp) nodep->v3fatalSrc("Not under module"); if (!m_modp) nodep->v3fatalSrc("Not under module");
// We could create just one temp variable, but we'll get better optimization // We could create just one temp variable, but we'll get better optimization
@@ -1070,14 +1068,10 @@ private:
asn2ap->dtypeFrom(temp2p); asn2ap->dtypeFrom(temp2p);
asn2bp->dtypeFrom(temp2p); asn2bp->dtypeFrom(temp2p);
// This order matters // This order matters
// cppcheck-suppress nullPointer // addNext deals with it newp = AstNode::addNext(newp, asn1ap);
newp = newp->addNext(asn1ap); newp = AstNode::addNext(newp, asn2ap);
// cppcheck-suppress nullPointer // addNext deals with it newp = AstNode::addNext(newp, asn1bp);
newp = newp->addNext(asn2ap); newp = AstNode::addNext(newp, asn2bp);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1bp);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2bp);
} }
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: "); if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
nodep->addNextHere(newp); nodep->addNextHere(newp);
@@ -1201,23 +1195,23 @@ private:
//---------------------------------------- //----------------------------------------
// VISITORS // VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) { virtual void visit(AstNetlist* nodep) {
// Iterate modules backwards, in bottom-up order. That's faster // Iterate modules backwards, in bottom-up order. That's faster
nodep->iterateChildrenBackwards(*this); nodep->iterateChildrenBackwards(*this);
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
// No ASSIGNW removals under funcs, we've long eliminated INITIALs // No ASSIGNW removals under funcs, we've long eliminated INITIALs
// (We should perhaps rename the assignw's to just assigns) // (We should perhaps rename the assignw's to just assigns)
m_wremove = false; m_wremove = false;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_wremove = true; m_wremove = true;
} }
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep) {
// No ASSIGNW removals under scope, we've long eliminated INITIALs // No ASSIGNW removals under scope, we've long eliminated INITIALs
m_scopep = nodep; m_scopep = nodep;
m_wremove = false; m_wremove = false;
@@ -1290,16 +1284,16 @@ private:
} }
// Special cases // Special cases
virtual void visit(AstConst* nodep, AstNUser*) {} // Already constant virtual void visit(AstConst* nodep) {} // Already constant
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep) {
if (m_params) { if (m_params) {
nodep->paramsp()->iterateAndNext(*this); nodep->paramsp()->iterateAndNext(*this);
} else { } else {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
} }
virtual void visit(AstPin* nodep, AstNUser*) { virtual void visit(AstPin* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -1420,14 +1414,14 @@ private:
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep); nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
} }
virtual void visit(AstAttrOf* nodep, AstNUser*) { virtual void visit(AstAttrOf* nodep) {
AstAttrOf* oldAttr = m_attrp; AstAttrOf* oldAttr = m_attrp;
m_attrp = nodep; m_attrp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_attrp = oldAttr; m_attrp = oldAttr;
} }
virtual void visit(AstArraySel* nodep, AstNUser*) { virtual void visit(AstArraySel* nodep) {
nodep->bitp()->iterateAndNext(*this); nodep->bitp()->iterateAndNext(*this);
if (nodep->bitp()->castConst() if (nodep->bitp()->castConst()
&& nodep->fromp()->castVarRef() && nodep->fromp()->castVarRef()
@@ -1441,12 +1435,17 @@ private:
if (!m_selp) { if (!m_selp) {
nodep->v3error("Illegal assignment of constant to unpacked array"); nodep->v3error("Illegal assignment of constant to unpacked array");
} else { } else {
nodep->replaceWith(nodep->fromp()->unlinkFrBack()); AstNode* fromp = nodep->fromp()->unlinkFrBack();
nodep->replaceWith(fromp);
if (fromp->dtypep()->skipRefp()->castNodeArrayDType()) {
// Strip off array to find what array references
fromp->dtypeFrom(fromp->dtypep()->skipRefp()->castNodeArrayDType()->subDTypep());
}
} }
} }
m_selp = NULL; m_selp = NULL;
} }
virtual void visit(AstNodeVarRef* nodep, AstNUser*) { virtual void visit(AstNodeVarRef* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->varp()) nodep->v3fatalSrc("Not linked"); if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
bool did=false; bool did=false;
@@ -1470,9 +1469,21 @@ private:
did=true; did=true;
} }
else if (m_selp && valuep->castInitArray()) { else if (m_selp && valuep->castInitArray()) {
int bit = m_selp->bitConst(); AstInitArray* initarp = valuep->castInitArray();
AstNode* itemp = valuep->castInitArray()->initsp(); uint32_t bit = m_selp->bitConst();
for (int n=0; n<bit && itemp; ++n, itemp=itemp->nextp()) {} int pos = 0;
AstNode* itemp = initarp->initsp();
for (; itemp; ++pos, itemp=itemp->nextp()) {
uint32_t index = initarp->posIndex(pos);
if (index == bit) break;
if (index > bit) {
if (initarp->defaultp()) {
itemp = initarp->defaultp();
} else {
initarp->v3fatalSrc("Not enough values in array initalizement");
}
}
}
if (itemp->castConst()) { if (itemp->castConst()) {
const V3Number& num = itemp->castConst()->num(); const V3Number& num = itemp->castConst()->num();
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl); //UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
@@ -1486,7 +1497,7 @@ private:
nodep->v3error("Expecting expression to be constant, but variable isn't const: "<<nodep->varp()->prettyName()); nodep->v3error("Expecting expression to be constant, but variable isn't const: "<<nodep->varp()->prettyName());
} }
} }
virtual void visit(AstEnumItemRef* nodep, AstNUser*) { virtual void visit(AstEnumItemRef* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->itemp()) nodep->v3fatalSrc("Not linked"); if (!nodep->itemp()) nodep->v3fatalSrc("Not linked");
bool did=false; bool did=false;
@@ -1504,7 +1515,7 @@ private:
} }
} }
// virtual void visit(AstCvtPackString* nodep, AstNUser*) { // virtual void visit(AstCvtPackString* nodep) {
// Not constant propagated (for today) because AstMath::isOpaque is set // Not constant propagated (for today) because AstMath::isOpaque is set
// Someday if lower is constant, convert to quoted "string". // Someday if lower is constant, convert to quoted "string".
@@ -1512,7 +1523,7 @@ private:
// Only one if it's not in a list // Only one if it's not in a list
return (!nodep->nextp() && nodep->backp()->nextp() != nodep); return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
} }
virtual void visit(AstSenItem* nodep, AstNUser*) { virtual void visit(AstSenItem* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doNConst if (m_doNConst
&& (nodep->sensp()->castConst() && (nodep->sensp()->castConst()
@@ -1548,11 +1559,12 @@ private:
} else if (!m_doNConst // Deal with later when doNConst missing } else if (!m_doNConst // Deal with later when doNConst missing
&& (nodep->sensp()->castEnumItemRef() && (nodep->sensp()->castEnumItemRef()
|| nodep->sensp()->castConst())) { || nodep->sensp()->castConst())) {
} else if (nodep->isIllegal()) { // Deal with later
} else { } else {
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable"); if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
} }
} }
virtual void visit(AstSenGate* nodep, AstNUser*) { virtual void visit(AstSenGate* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (AstConst* constp = nodep->rhsp()->castConst()) { if (AstConst* constp = nodep->rhsp()->castConst()) {
if (constp->isZero()) { if (constp->isZero()) {
@@ -1598,7 +1610,7 @@ private:
} }
}; };
virtual void visit(AstSenTree* nodep, AstNUser*) { virtual void visit(AstSenTree* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doExpensive) { if (m_doExpensive) {
//cout<<endl; nodep->dumpTree(cout,"ssin: "); //cout<<endl; nodep->dumpTree(cout,"ssin: ");
@@ -1702,17 +1714,17 @@ private:
//----- //-----
// Zero elimination // Zero elimination
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doNConst && replaceNodeAssign(nodep)) return; if (m_doNConst && replaceNodeAssign(nodep)) return;
} }
virtual void visit(AstAssignAlias* nodep, AstNUser*) { virtual void visit(AstAssignAlias* nodep) {
// Don't perform any optimizations, keep the alias around // Don't perform any optimizations, keep the alias around
} }
virtual void visit(AstAssignVarScope* nodep, AstNUser*) { virtual void visit(AstAssignVarScope* nodep) {
// Don't perform any optimizations, the node won't be linked yet // Don't perform any optimizations, the node won't be linked yet
} }
virtual void visit(AstAssignW* nodep, AstNUser*) { virtual void visit(AstAssignW* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doNConst && replaceNodeAssign(nodep)) return; if (m_doNConst && replaceNodeAssign(nodep)) return;
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
@@ -1739,7 +1751,7 @@ private:
} }
} }
virtual void visit(AstNodeIf* nodep, AstNUser*) { virtual void visit(AstNodeIf* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doNConst) { if (m_doNConst) {
if (AstConst* constp = nodep->condp()->castConst()) { if (AstConst* constp = nodep->condp()->castConst()) {
@@ -1817,7 +1829,7 @@ private:
} }
} }
virtual void visit(AstSFormatF* nodep, AstNUser*) { virtual void visit(AstSFormatF* nodep) {
// Substitute constants into displays. The main point of this is to // Substitute constants into displays. The main point of this is to
// simplify assertion methodologies which call functions with display's. // simplify assertion methodologies which call functions with display's.
// This eliminates a pile of wide temps, and makes the C a whole lot more readable. // This eliminates a pile of wide temps, and makes the C a whole lot more readable.
@@ -1828,7 +1840,7 @@ private:
} }
if (m_doNConst && anyconst) { if (m_doNConst && anyconst) {
//UINFO(9," Display in "<<nodep->text()<<endl); //UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = ""; string newFormat = "";
string fmt = ""; string fmt = "";
bool inPct = false; bool inPct = false;
AstNode* argp = nodep->exprsp(); AstNode* argp = nodep->exprsp();
@@ -1846,33 +1858,30 @@ private:
switch (tolower(ch)) { switch (tolower(ch)) {
case '%': break; // %% - just output a % case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name" case 'm': break; // %m - auto insert "name"
case 'l': break; // %m - auto insert "library" case 'l': break; // %l - auto insert "library"
default: // Most operators, just move to next argument default: // Most operators, just move to next argument
if (argp) { if (argp) {
AstNode* nextp=argp->nextp(); AstNode* nextp=argp->nextp();
if (argp && argp->castConst()) { // Convert it if (argp && argp->castConst()) { // Convert it
string out = argp->castConst()->num().displayed(fmt); string out = argp->castConst()->num().displayed(nodep->fileline(), fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl); UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
{ // fmt = out w/ replace % with %% as it must be literal. // fmt = out w/ replace % with %% as it must be literal.
fmt = ""; fmt = VString::quotePercent(out);
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
if (*pos == '%') fmt += '%';
fmt += *pos;
}
}
argp->unlinkFrBack()->deleteTree(); argp->unlinkFrBack()->deleteTree();
} }
argp=nextp; argp=nextp;
} }
break; break;
} // switch } // switch
dispout += fmt; newFormat += fmt;
} else { } else {
dispout += ch; newFormat += ch;
} }
} }
nodep->text(dispout); if (newFormat != nodep->text()) {
//UINFO(9," Display out "<<nodep->text()<<endl); nodep->text(newFormat);
UINFO(9," Display out "<<nodep<<endl);
}
} }
if (!nodep->exprsp() if (!nodep->exprsp()
&& nodep->name().find("%") == string::npos && nodep->name().find("%") == string::npos
@@ -1882,17 +1891,17 @@ private:
} }
} }
virtual void visit(AstFuncRef* nodep, AstNUser*) { virtual void visit(AstFuncRef* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_params) { // Only parameters force us to do constant function call propagation if (m_params) { // Only parameters force us to do constant function call propagation
replaceWithSimulation(nodep); replaceWithSimulation(nodep);
} }
} }
virtual void visit(AstArg* nodep, AstNUser*) { virtual void visit(AstArg* nodep) {
// replaceWithSimulation on the Arg's parent FuncRef replaces these // replaceWithSimulation on the Arg's parent FuncRef replaces these
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doNConst) { if (m_doNConst) {
if (nodep->condp()->isZero()) { if (nodep->condp()->isZero()) {
@@ -1906,17 +1915,17 @@ private:
} }
} }
} }
virtual void visit(AstInitArray* nodep, AstNUser*) { virtual void visit(AstInitArray* nodep) {
// Constant if all children are constant // Constant if all children are constant
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any // These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any
// If output of a presel didn't get consted, chances are V3Param didn't visit properly // If output of a presel didn't get consted, chances are V3Param didn't visit properly
virtual void visit(AstNodePreSel* nodep, AstNUser*) {} virtual void visit(AstNodePreSel* nodep) {}
// Ignored, can eliminate early // Ignored, can eliminate early
virtual void visit(AstSysIgnore* nodep, AstNUser*) { virtual void visit(AstSysIgnore* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doNConst) { if (m_doNConst) {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
@@ -1924,7 +1933,7 @@ private:
} }
// Simplify // Simplify
virtual void visit(AstBasicDType* nodep, AstNUser*) { virtual void visit(AstBasicDType* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->cvtRangeConst(); nodep->cvtRangeConst();
} }
@@ -1932,12 +1941,12 @@ private:
//----- //-----
// Jump elimination // Jump elimination
virtual void visit(AstJumpGo* nodep, AstNUser*) { virtual void visit(AstJumpGo* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_doExpensive) { nodep->labelp()->user4(true); } if (m_doExpensive) { nodep->labelp()->user4(true); }
} }
virtual void visit(AstJumpLabel* nodep, AstNUser*) { virtual void visit(AstJumpLabel* nodep) {
// Because JumpLabels disable many optimizations, // Because JumpLabels disable many optimizations,
// remove JumpLabels that are not pointed to by any AstJumpGos // remove JumpLabels that are not pointed to by any AstJumpGos
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this // Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
@@ -2266,11 +2275,15 @@ private:
// Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101 // Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101
//----- //-----
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
// Default: Just iterate // Default: Just iterate
if (m_required) { if (m_required) {
nodep->v3error("Expecting expression to be constant, but can't convert a " if (nodep->castNodeDType() || nodep->castRange()) {
<<nodep->prettyTypeName()<<" to constant."); // Ignore dtypes for parameter type pins
} else {
nodep->v3error("Expecting expression to be constant, but can't convert a "
<<nodep->prettyTypeName()<<" to constant.");
}
} else { } else {
// Calculate the width of this operation // Calculate the width of this operation
if (m_params && !nodep->width()) { if (m_params && !nodep->width()) {
@@ -2322,7 +2335,7 @@ public:
virtual ~ConstVisitor() {} virtual ~ConstVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) { AstNode* mainAcceptEdit(AstNode* nodep) {
// Operate starting at a random place // Operate starting at a random place
return nodep->acceptSubtreeReturnEdits(*this); return nodep->iterateSubtreeReturnEdits(*this);
} }
}; };
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+12 -12
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -83,10 +83,10 @@ private:
const char* varIgnoreToggle(AstVar* nodep) { const char* varIgnoreToggle(AstVar* nodep) {
// Return true if this shouldn't be traced // Return true if this shouldn't be traced
// See also similar rule in V3TraceDecl::varIgnoreTrace // See also similar rule in V3TraceDecl::varIgnoreTrace
string prettyName = nodep->prettyName();
if (!nodep->isToggleCoverable()) if (!nodep->isToggleCoverable())
return "Not relevant signal type"; return "Not relevant signal type";
if (!v3Global.opt.coverageUnderscore()) { if (!v3Global.opt.coverageUnderscore()) {
string prettyName = nodep->prettyName();
if (prettyName[0] == '_') if (prettyName[0] == '_')
return "Leading underscore"; return "Leading underscore";
if (prettyName.find("._") != string::npos) if (prettyName.find("._") != string::npos)
@@ -128,7 +128,7 @@ private:
} }
// VISITORS - BOTH // VISITORS - BOTH
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
m_fileps.clear(); m_fileps.clear();
@@ -138,7 +138,7 @@ private:
} }
// VISITORS - TOGGLE COVERAGE // VISITORS - TOGGLE COVERAGE
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep) {
bool oldtog = m_inToggleOff; bool oldtog = m_inToggleOff;
{ {
m_inToggleOff = true; m_inToggleOff = true;
@@ -146,7 +146,7 @@ private:
} }
m_inToggleOff = oldtog; m_inToggleOff = oldtog;
} }
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_modp && !m_inModOff && !m_inToggleOff if (m_modp && !m_inModOff && !m_inToggleOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) { && nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
@@ -279,7 +279,7 @@ private:
} }
// VISITORS - LINE COVERAGE // VISITORS - LINE COVERAGE
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered virtual void visit(AstIf* nodep) { // Note not AstNodeIf; other types don't get covered
UINFO(4," IF: "<<nodep<<endl); UINFO(4," IF: "<<nodep<<endl);
if (m_checkBlock) { if (m_checkBlock) {
// An else-if. When we iterate the if, use "elsif" marking // An else-if. When we iterate the if, use "elsif" marking
@@ -312,7 +312,7 @@ private:
m_checkBlock = true; // Reset as a child may have cleared it m_checkBlock = true; // Reset as a child may have cleared it
} }
} }
virtual void visit(AstCaseItem* nodep, AstNUser*) { virtual void visit(AstCaseItem* nodep) {
UINFO(4," CASEI: "<<nodep<<endl); UINFO(4," CASEI: "<<nodep<<endl);
if (m_checkBlock && !m_inModOff if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { && nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
@@ -324,7 +324,7 @@ private:
m_checkBlock = true; // Reset as a child may have cleared it m_checkBlock = true; // Reset as a child may have cleared it
} }
} }
virtual void visit(AstPslCover* nodep, AstNUser*) { virtual void visit(AstPslCover* nodep) {
UINFO(4," PSLCOVER: "<<nodep<<endl); UINFO(4," PSLCOVER: "<<nodep<<endl);
m_checkBlock = true; // Always do cover blocks, even if there's a $stop m_checkBlock = true; // Always do cover blocks, even if there's a $stop
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -334,11 +334,11 @@ private:
} }
m_checkBlock = true; // Reset as a child may have cleared it m_checkBlock = true; // Reset as a child may have cleared it
} }
virtual void visit(AstStop* nodep, AstNUser*) { virtual void visit(AstStop* nodep) {
UINFO(4," STOP: "<<nodep<<endl); UINFO(4," STOP: "<<nodep<<endl);
m_checkBlock = false; m_checkBlock = false;
} }
virtual void visit(AstPragma* nodep, AstNUser*) { virtual void visit(AstPragma* nodep) {
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) { if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
// Skip all NEXT nodes under this block, and skip this if/case branch // Skip all NEXT nodes under this block, and skip this if/case branch
UINFO(4," OFF: "<<nodep<<endl); UINFO(4," OFF: "<<nodep<<endl);
@@ -348,7 +348,7 @@ private:
if (m_checkBlock) nodep->iterateChildren(*this); if (m_checkBlock) nodep->iterateChildren(*this);
} }
} }
virtual void visit(AstBegin* nodep, AstNUser*) { virtual void visit(AstBegin* nodep) {
// Record the hierarchy of any named begins, so we can apply to user // Record the hierarchy of any named begins, so we can apply to user
// coverage points. This is because there may be cov points inside // coverage points. This is because there may be cov points inside
// generate blocks; each point should get separate consideration. // generate blocks; each point should get separate consideration.
@@ -368,7 +368,7 @@ private:
} }
// VISITORS - BOTH // VISITORS - BOTH
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
// Default: Just iterate // Default: Just iterate
if (m_checkBlock) { if (m_checkBlock) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+5 -5
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -103,19 +103,19 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) { virtual void visit(AstNetlist* nodep) {
// Find all Coverage's // Find all Coverage's
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Simplify // Simplify
detectDuplicates(); detectDuplicates();
} }
virtual void visit(AstCoverToggle* nodep, AstNUser*) { virtual void visit(AstCoverToggle* nodep) {
m_toggleps.push_back(nodep); m_toggleps.push_back(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
//-------------------- //--------------------
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate virtual void visit(AstNodeMath* nodep) {} // Accelerate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+192 -47
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -25,7 +25,18 @@
// dependencies easier to resolve. // dependencies easier to resolve.
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme // NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
// instead of needing as many visitors. // instead of needing as many visitors.
//************************************************************************* //
// The following nodes have package pointers and are cleaned up here:
// AstRefDType, AstEnumItemRef, AstNodeVarRef, AstNodeFTask
// These have packagep but will not exist at this stage
// AstPackageImport, AstDot, AstPackageRef
//
// Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links
// are no longer used, but their presence prevents us from removing empty
// packages. As the links as no longer used after V3Scope, we remove them
// here after scoping to allow more dead node
// removal.
// *************************************************************************
#include "config_build.h" #include "config_build.h"
#include "verilatedos.h" #include "verilatedos.h"
@@ -47,13 +58,13 @@ private:
// NODE STATE // NODE STATE
// ** Shared with DeadVisitor ** // ** Shared with DeadVisitor **
// VISITORS // VISITORS
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->modp()->user1(nodep->modp()->user1() - 1); nodep->modp()->user1Inc(-1);
} }
//----- //-----
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate virtual void visit(AstNodeMath* nodep) {} // Accelerate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
@@ -71,10 +82,10 @@ class DeadVisitor : public AstNVisitor {
private: private:
// NODE STATE // NODE STATE
// Entire Netlist: // Entire Netlist:
// AstNodeModule::user1() -> int. Count of number of cells referencing this module. // AstNodeModule::user1() -> int. Count of number of cells referencing this module.
// AstVar::user1() -> int. Count of number of references // AstVar::user1() -> int. Count of number of references
// AstVarScope::user1() -> int. Count of number of references // AstVarScope::user1() -> int. Count of number of references
// AstNodeDType::user1() -> int. Count of number of references // AstNodeDType::user1() -> int. Count of number of references
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
// TYPES // TYPES
@@ -82,11 +93,16 @@ private:
// STATE // STATE
AstNodeModule* m_modp; // Current module AstNodeModule* m_modp; // Current module
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
vector<AstNode*> m_dtypesp; // List of all encountered to avoid another loop through tree
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
vector<AstScope*> m_scopesp; // List of all encountered to avoid another loop through tree
vector<AstCell*> m_cellsp; // List of all encountered to avoid another loop through tree
AssignMap m_assignMap; // List of all simple assignments for each variable AssignMap m_assignMap; // List of all simple assignments for each variable
bool m_elimUserVars; // Allow removal of user's vars bool m_elimUserVars; // Allow removal of user's vars
bool m_elimDTypes; // Allow removal of DTypes bool m_elimDTypes; // Allow removal of DTypes
bool m_elimScopes; // Allow removal of Scopes
bool m_elimCells; // Allow removal of Cells
bool m_sideEffect; // Side effects discovered in assign RHS bool m_sideEffect; // Side effects discovered in assign RHS
// METHODS // METHODS
@@ -97,34 +113,56 @@ private:
} }
void checkAll(AstNode* nodep) { void checkAll(AstNode* nodep) {
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc(); if (AstNode* subnodep = nodep->dtypep()) {
subnodep->user1Inc();
}
}
if (AstNode* subnodep = nodep->getChildDTypep()) {
subnodep->user1Inc();
} }
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
} }
void checkDType(AstNodeDType* nodep) { void checkDType(AstNodeDType* nodep) {
if (!nodep->generic() // Don't remove generic types if (!nodep->generic() // Don't remove generic types
&& m_elimDTypes // dtypes stick around until post-widthing && m_elimDTypes // dtypes stick around until post-widthing
&& !nodep->castMemberDType() // Keep member names iff upper type exists && !nodep->castMemberDType() // Keep member names iff upper type exists
) { ) {
m_varEtcsp.push_back(nodep); m_dtypesp.push_back(nodep);
}
if (AstNode* subnodep = nodep->virtRefDTypep()) {
subnodep->user1Inc();
} }
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
m_modp = nodep; m_modp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->scopep()) nodep->scopep()->user1Inc();
}
virtual void visit(AstScope* nodep) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
if (!nodep->isTop() && !nodep->varsp() && !nodep->blocksp() && !nodep->finalClksp()) {
m_scopesp.push_back(nodep);
}
}
virtual void visit(AstCell* nodep) {
nodep->iterateChildren(*this);
checkAll(nodep);
m_cellsp.push_back(nodep);
nodep->modp()->user1Inc(); nodep->modp()->user1Inc();
} }
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
virtual void visit(AstNodeVarRef* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->varScopep()) { if (nodep->varScopep()) {
@@ -135,60 +173,79 @@ private:
nodep->varp()->user1Inc(); nodep->varp()->user1Inc();
} }
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1Inc(); if (m_elimCells) nodep->packagep(NULL);
else nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1Inc(); if (m_elimCells) nodep->packagep(NULL);
else nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstRefDType* nodep, AstNUser*) { virtual void visit(AstRefDType* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkDType(nodep); checkDType(nodep);
checkAll(nodep); checkAll(nodep);
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1Inc(); if (m_elimCells) nodep->packagep(NULL);
else nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstNodeDType* nodep, AstNUser*) { virtual void visit(AstNodeDType* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkDType(nodep); checkDType(nodep);
checkAll(nodep); checkAll(nodep);
} }
virtual void visit(AstEnumItemRef* nodep, AstNUser*) { virtual void visit(AstEnumItemRef* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1Inc(); if (m_elimCells) nodep->packagep(NULL);
else nodep->packagep()->user1Inc();
} }
checkAll(nodep);
} }
virtual void visit(AstTypedef* nodep, AstNUser*) { virtual void visit(AstModport* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_elimCells) {
if (!nodep->varsp()) {
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
return;
}
}
checkAll(nodep);
}
virtual void visit(AstTypedef* nodep) {
nodep->iterateChildren(*this);
if (m_elimCells && !nodep->attrPublic()) {
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
return;
}
checkAll(nodep); checkAll(nodep);
// Don't let packages with only public variables disappear // Don't let packages with only public variables disappear
// Normal modules may disappear, e.g. if they are parameterized then removed // Normal modules may disappear, e.g. if they are parameterized then removed
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc(); if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
} }
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (mightElim(nodep->varp())) { if (nodep->scopep()) nodep->scopep()->user1Inc();
if (mightElimVar(nodep->varp())) {
m_vscsp.push_back(nodep); m_vscsp.push_back(nodep);
} }
} }
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc(); if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
if (mightElim(nodep)) { if (mightElimVar(nodep)) {
m_varEtcsp.push_back(nodep); m_varsp.push_back(nodep);
} }
} }
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
// See if simple assignments to variables may be eliminated because that variable is never used. // See if simple assignments to variables may be eliminated because that variable is never used.
// Similar code in V3Life // Similar code in V3Life
m_sideEffect = false; m_sideEffect = false;
@@ -199,7 +256,7 @@ private:
if (varrefp && !m_sideEffect if (varrefp && !m_sideEffect
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping && varrefp->varScopep()) { // For simplicity, we only remove post-scoping
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep)); m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
checkAll(varrefp); // Must track reference to dtype() checkAll(varrefp); // Must track reference to dtype()
} else { // Track like any other statement } else { // Track like any other statement
nodep->lhsp()->iterateAndNext(*this); nodep->lhsp()->iterateAndNext(*this);
} }
@@ -207,7 +264,7 @@ private:
} }
//----- //-----
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
if (nodep->isOutputter()) m_sideEffect=true; if (nodep->isOutputter()) m_sideEffect=true;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
@@ -235,13 +292,45 @@ private:
} }
} }
} }
bool mightElim(AstVar* nodep) { bool mightElimVar(AstVar* nodep) {
return (!nodep->isSigPublic() // Can't elim publics! return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO() && !nodep->isIO()
&& (nodep->isTemp() && (nodep->isTemp()
|| (nodep->isParam() && !nodep->isTrace()) || (nodep->isParam() && !nodep->isTrace())
|| m_elimUserVars)); // Post-Trace can kill most anything || m_elimUserVars)); // Post-Trace can kill most anything
} }
void deadCheckScope() {
for (bool retry=true; retry; ) {
retry = false;
for (vector<AstScope*>::iterator it = m_scopesp.begin(); it != m_scopesp.end();++it) {
AstScope* scp = *it;
if (!scp)
continue;
if (scp->user1() == 0) {
UINFO(4, " Dead AstScope " << scp << endl);
scp->aboveScopep()->user1Inc(-1);
if (scp->dtypep()) {
scp->dtypep()->user1Inc(-1);
}
scp->unlinkFrBack()->deleteTree(); VL_DANGLING(scp);
*it = NULL;
retry = true;
}
}
}
}
void deadCheckCells() {
for (vector<AstCell*>::iterator it = m_cellsp.begin(); it!=m_cellsp.end(); ++it) {
AstCell* cellp = *it;
if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) {
cellp->modp()->user1Inc(-1);
cellp->unlinkFrBack()->deleteTree(); VL_DANGLING(cellp);
}
}
}
void deadCheckVar() { void deadCheckVar() {
// Delete any unused varscopes // Delete any unused varscopes
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) { for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
@@ -251,34 +340,76 @@ private:
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp); pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) { for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
AstNodeAssign* assp = it->second; AstNodeAssign* assp = it->second;
UINFO(4," Dead assign "<<assp<<endl); UINFO(4," Dead assign "<<assp<<endl);
assp->dtypep()->user1Inc(-1);
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp); assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
} }
if (vscp->scopep()) vscp->scopep()->user1Inc(-1);
vscp->dtypep()->user1Inc(-1);
vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp); vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp);
} }
} }
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) { for (bool retry=true; retry; ) {
retry = false;
for (vector<AstVar *>::iterator it = m_varsp.begin(); it != m_varsp.end();++it) {
AstVar* varp = *it;
if (!varp)
continue;
if (varp->user1() == 0) {
UINFO(4, " Dead " << varp << endl);
if (varp->dtypep()) {
varp->dtypep()->user1Inc(-1);
}
varp->unlinkFrBack()->deleteTree(); VL_DANGLING(varp);
*it = NULL;
retry = true;
}
}
}
for (vector<AstNode*>::iterator it = m_dtypesp.begin(); it != m_dtypesp.end();++it) {
if ((*it)->user1() == 0) { if ((*it)->user1() == 0) {
UINFO(4," Dead "<<(*it)<<endl); AstNodeClassDType *classp;
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL; // It's possible that there if a reference to each individual member, but
// not to the dtype itself. Check and don't remove the parent dtype if
// members are still alive.
if ((classp = (*it)->castNodeClassDType())) {
bool cont = true;
for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = memberp->nextp()->castMemberDType()) {
if (memberp->user1() != 0) {
cont = false;
break;
}
}
if (!cont)
continue;
}
(*it)->unlinkFrBack()->deleteTree(); VL_DANGLING(*it);
} }
} }
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) { DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes, bool elimCells) {
m_modp = NULL; m_modp = NULL;
m_elimCells = elimCells;
m_elimUserVars = elimUserVars; m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes; m_elimDTypes = elimDTypes;
m_elimScopes = elimScopes;
m_sideEffect = false; m_sideEffect = false;
// Prepare to remove some datatypes // Prepare to remove some datatypes
nodep->typeTablep()->clearCache(); nodep->typeTablep()->clearCache();
// Operate on whole netlist // Operate on whole netlist
nodep->accept(*this); nodep->accept(*this);
deadCheckVar(); deadCheckVar();
// We only elimate scopes when in a flattened structure
// Otherwise we have no easy way to know if a scope is used
if (elimScopes) deadCheckScope();
if (elimCells) deadCheckCells();
// Modules after vars, because might be vars we delete inside a mod we delete // Modules after vars, because might be vars we delete inside a mod we delete
deadCheckMod(); deadCheckMod();
// We may have removed some datatypes, cleanup // We may have removed some datatypes, cleanup
nodep->typeTablep()->repairCache(); nodep->typeTablep()->repairCache();
} }
@@ -290,16 +421,30 @@ public:
void V3Dead::deadifyModules(AstNetlist* nodep) { void V3Dead::deadifyModules(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, false); DeadVisitor visitor (nodep, false, false, false, false);
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
} }
void V3Dead::deadifyDTypes(AstNetlist* nodep) { void V3Dead::deadifyDTypes(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true); DeadVisitor visitor (nodep, false, true, false, false);
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("deadDtypes.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true, true, false);
V3Global::dumpCheckGlobalTree("deadDtypesScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyAll(AstNetlist* nodep) { void V3Dead::deadifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true); DeadVisitor visitor (nodep, true, true, false, true);
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true, true, true);
V3Global::dumpCheckGlobalTree("deadAllScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+3 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -33,8 +33,10 @@ public:
static void deadifyModules(AstNetlist* nodep); static void deadifyModules(AstNetlist* nodep);
// Modules, Data types // Modules, Data types
static void deadifyDTypes(AstNetlist* nodep); static void deadifyDTypes(AstNetlist* nodep);
static void deadifyDTypesScoped(AstNetlist* nodep);
// Everything that's possible // Everything that's possible
static void deadifyAll(AstNetlist* nodep); static void deadifyAll(AstNetlist* nodep);
static void deadifyAllScoped(AstNetlist* nodep);
}; };
#endif // Guard #endif // Guard
+17 -17
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -268,7 +268,7 @@ private:
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one. // then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
// This is good for code like: // This is good for code like:
// for (i=0; i<5; i++) vector[i] <= something; // for (i=0; i<5; i++) vector[i] <= something;
setvscp = nodep->user3p()->castNode()->castVarScope(); setvscp = nodep->user3p()->castVarScope();
++m_statSharedSet; ++m_statSharedSet;
} else { // Create new one } else { // Create new one
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
@@ -303,9 +303,9 @@ private:
// Build "IF (changeit) ... // Build "IF (changeit) ...
UINFO(9," For "<<setvscp<<endl); UINFO(9," For "<<setvscp<<endl);
UINFO(9," & "<<varrefp<<endl); UINFO(9," & "<<varrefp<<endl);
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost(); AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castAlwaysPost();
if (finalp) { if (finalp) {
AstActive* oldactivep = finalp->user2p()->castNode()->castActive(); AstActive* oldactivep = finalp->user2p()->castActive();
checkActivePost(varrefp, oldactivep); checkActivePost(varrefp, oldactivep);
if (setinitp) oldactivep->addStmtsp(setinitp); if (setinitp) oldactivep->addStmtsp(setinitp);
} else { // first time we've dealt with this memory } else { // first time we've dealt with this memory
@@ -318,10 +318,10 @@ private:
if (setinitp) newactp->addStmtsp(setinitp); if (setinitp) newactp->addStmtsp(setinitp);
} }
AstIf* postLogicp; AstIf* postLogicp;
if (finalp->user3p()->castNode() == setvscp) { if (finalp->user3p() == setvscp) {
// Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*, // Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*,
// we can share the IF statement too // we can share the IF statement too
postLogicp = finalp->user4p()->castNode()->castIf(); postLogicp = finalp->user4p()->castIf();
if (!postLogicp) nodep->v3fatalSrc("Delayed assignment misoptimized; prev var found w/o associated IF"); if (!postLogicp) nodep->v3fatalSrc("Delayed assignment misoptimized; prev var found w/o associated IF");
} else { } else {
postLogicp = new AstIf (nodep->fileline(), postLogicp = new AstIf (nodep->fileline(),
@@ -338,22 +338,22 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) { virtual void visit(AstNetlist* nodep) {
//VV***** We reset all userp() on the netlist //VV***** We reset all userp() on the netlist
m_modVarMap.clear(); m_modVarMap.clear();
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep) {
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
AstNode::user3ClearTree(); AstNode::user3ClearTree();
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
m_cfuncp = nodep; m_cfuncp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_cfuncp = NULL; m_cfuncp = NULL;
} }
virtual void visit(AstActive* nodep, AstNUser*) { virtual void visit(AstActive* nodep) {
m_activep = nodep; m_activep = nodep;
bool oldinit = m_inInitial; bool oldinit = m_inInitial;
m_inInitial = nodep->hasInitial(); m_inInitial = nodep->hasInitial();
@@ -361,7 +361,7 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_inInitial = oldinit; m_inInitial = oldinit;
} }
virtual void visit(AstAssignDly* nodep, AstNUser*) { virtual void visit(AstAssignDly* nodep) {
m_inDly = true; m_inDly = true;
m_nextDlyp = nodep->nextp()->castAssignDly(); // Next assignment in same block, maybe NULL. m_nextDlyp = nodep->nextp()->castAssignDly(); // Next assignment in same block, maybe NULL.
if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task"); if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task");
@@ -385,7 +385,7 @@ private:
m_nextDlyp = NULL; m_nextDlyp = NULL;
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep) {
if (!nodep->user2Inc()) { // Not done yet if (!nodep->user2Inc()) { // Not done yet
if (m_inDly && nodep->lvalue()) { if (m_inDly && nodep->lvalue()) {
UINFO(4,"AssignDlyVar: "<<nodep<<endl); UINFO(4,"AssignDlyVar: "<<nodep<<endl);
@@ -394,9 +394,9 @@ private:
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active"); if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
AstVarScope* oldvscp = nodep->varScopep(); AstVarScope* oldvscp = nodep->varScopep();
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n"); if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope(); AstVarScope* dlyvscp = oldvscp->user1p()->castVarScope();
if (dlyvscp) { // Multiple use of delayed variable if (dlyvscp) { // Multiple use of delayed variable
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive(); AstActive* oldactivep = dlyvscp->user2p()->castActive();
checkActivePost(nodep, oldactivep); checkActivePost(nodep, oldactivep);
} }
if (!dlyvscp) { // First use of this delayed variable if (!dlyvscp) { // First use of this delayed variable
@@ -432,10 +432,10 @@ private:
} }
} }
virtual void visit(AstNodeFor* nodep, AstNUser*) { virtual void visit(AstNodeFor* nodep) {
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n"); nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
} }
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep) {
bool oldloop = m_inLoop; bool oldloop = m_inLoop;
m_inLoop = true; m_inLoop = true;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -444,7 +444,7 @@ private:
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+10 -10
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -85,14 +85,14 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep; m_modp = nodep;
m_funcp = NULL; m_funcp = NULL;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
m_funcp = nodep; m_funcp = nodep;
m_depth = 0; m_depth = 0;
m_maxdepth = 0; m_maxdepth = 0;
@@ -106,13 +106,13 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_stmtp = NULL; m_stmtp = NULL;
} }
virtual void visit(AstNodeStmt* nodep, AstNUser*) { virtual void visit(AstNodeStmt* nodep) {
visitStmt(nodep); visitStmt(nodep);
} }
// Operators // Operators
virtual void visit(AstNodeTermop* nodep, AstNUser*) { virtual void visit(AstNodeTermop* nodep) {
} }
virtual void visit(AstNodeMath* nodep, AstNUser*) { virtual void visit(AstNodeMath* nodep) {
// We have some operator defines that use 2 parens, so += 2. // We have some operator defines that use 2 parens, so += 2.
m_depth += 2; m_depth += 2;
if (m_depth>m_maxdepth) m_maxdepth=m_depth; if (m_depth>m_maxdepth) m_maxdepth=m_depth;
@@ -139,19 +139,19 @@ private:
m_funcp->isStatic(false); m_funcp->isStatic(false);
} }
} }
virtual void visit(AstUCFunc* nodep, AstNUser*) { virtual void visit(AstUCFunc* nodep) {
needNonStaticFunc(nodep); needNonStaticFunc(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstUCStmt* nodep, AstNUser*) { virtual void visit(AstUCStmt* nodep) {
needNonStaticFunc(nodep); needNonStaticFunc(nodep);
visitStmt(nodep); visitStmt(nodep);
} }
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars virtual void visit(AstVar* nodep) {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+7 -7
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can // Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -76,14 +76,14 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep) {
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep; m_modp = nodep;
m_deepNum = 0; m_deepNum = 0;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep) {
// We recurse into this. // We recurse into this.
int lastDepth = m_depth; int lastDepth = m_depth;
AstCFunc* lastFuncp = m_funcp; AstCFunc* lastFuncp = m_funcp;
@@ -111,15 +111,15 @@ private:
} }
m_depth--; m_depth--;
} }
virtual void visit(AstNodeStmt* nodep, AstNUser*) { virtual void visit(AstNodeStmt* nodep) {
visitStmt(nodep); visitStmt(nodep);
} }
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate virtual void visit(AstNodeMath* nodep) {} // Accelerate
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars virtual void visit(AstVar* nodep) {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }

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