Compare commits

...
163 Commits
Author SHA1 Message Date
Wilson Snyder a20b4f2864 Version bump 2011-04-06 07:33:44 -04:00
Wilson Snyder 44a19d2a0a Fix missing test files 2011-04-06 07:33:32 -04:00
Wilson Snyder 02f3beb8db Add V3Number rotate functions; unused as yet 2011-03-30 21:31:29 -04:00
Wilson Snyder 3269cc3d90 Add +libext+.sv default 2011-03-30 21:30:36 -04:00
Wilson Snyder fb70a1f4ab Add --Wno-fatal to turn off abort on warnings. 2011-03-22 18:09:39 -04:00
Wilson Snyder df0aa483ce Support ${...} and $(...) env variables in .vc files 2011-03-21 12:25:31 -04:00
Wilson Snyder c83f12a55c Support simple cast operators, bug335. 2011-03-17 22:25:49 -04:00
Wilson Snyder 9704f59566 Internals: Rename AstCast to AstCCast 2011-03-17 21:09:52 -04:00
Wilson Snyder 2923893d34 Support loop unrolling on width mismatches, bug 333 2011-03-12 07:45:04 -05:00
Wilson Snyder 890dab0742 Write logfile on each failure 2011-03-12 07:44:29 -05:00
Wilson Snyder 607e26b041 Commentary 2011-03-08 06:49:45 -05:00
Wilson Snyder ea75290f65 Add error on circular parameter definitions, bug329 2011-03-07 20:44:19 -05:00
Wilson Snyder a176054118 Add --trace-max-width and --trace-max-array, bug 319. 2011-02-23 21:58:27 -05:00
Wilson Snyder 9a697dc5f5 Accelerate bit-selected inversions. 2011-02-23 21:36:38 -05:00
Wilson Snyder cfdb852843 Fix concatenates and vectored bufif1, bug326. 2011-02-23 21:21:59 -05:00
Wilson Snyder 2e67a91982 Support $bits(data_type), bug327. 2011-02-23 19:04:15 -05:00
Wilson Snyder 074ca9330d Make width violation on function outputs a fatal error 2011-02-18 20:52:26 -05:00
Wilson Snyder f0d7cdcb20 Commentary 2011-02-18 07:11:03 -05:00
Wilson Snyder 40d961e059 Version bump 2011-02-14 19:05:55 -05:00
Wilson Snyder e5de759236 Report error on function call output tied to constant.
Fix internal error on functions called as SV tasks.
2011-02-14 19:25:30 -05:00
Wilson Snyder e26a75c59d Fix internal error on non-inlined inout pins. 2011-02-07 19:15:58 -05:00
Wilson Snyder 8701145b40 Fix error on constants connected to outputs, bug323. 2011-01-31 07:05:04 -05:00
Wilson Snyder a2558886c8 Report errors on empty pins, bug321 2011-01-29 18:00:48 -05:00
Wilson Snyder f818ee86ae Report errors on duplicated pins, bug321. 2011-01-29 17:01:06 -05:00
Wilson Snyder ad0dbdaa9c CDC: Print nice net names instead of ___5f 2011-01-19 11:44:23 -05:00
Wilson Snyder a9f14b294f Internals: Cdc notes; marking submodules won't work 2011-01-18 21:37:53 -05:00
Wilson Snyder a435ae98f9 Throw UNUSED/UNDRIVEN only once per net in a parametrized module. 2011-01-18 21:28:51 -05:00
Wilson Snyder 481b261458 Internals: add a few userIncs, No functional change 2011-01-18 21:19:12 -05:00
Wilson Snyder 48df52d743 Reduce use of CRELINE so line numbers more closely match first parsed location 2011-01-18 21:12:31 -05:00
Wilson Snyder 0af0d3b171 Cleanup CDC reports, remove TOP-> signal prefixes 2011-01-17 14:58:58 -05:00
Wilson Snyder 8287cf35e7 Fix warnings to point to lowest net usage, not upper level ports. 2011-01-17 14:10:01 -05:00
Wilson Snyder fab7924cc2 Fix block comment not separating identifiers, bug311. 2011-01-11 18:46:21 -05:00
Wilson Snyder 0ab739e8b1 Fix false BLKSEQ on non-unrolled for loop indexes. 2011-01-06 06:46:19 -05:00
Wilson Snyder 2dcd4d171b Version bump 2011-01-03 13:32:16 -05:00
Wilson Snyder e7f4d18c3d First test is verilator -V 2011-01-03 13:30:33 -05:00
Wilson Snyder 1611362c22 Add --unused-regexp 2011-01-01 19:43:22 -05:00
Wilson Snyder 2327698160 driver: Allow --site specific tests 2011-01-01 19:18:32 -05:00
Wilson Snyder 71c1f00ec2 Copyright year update 2011-01-01 18:21:19 -05:00
Wilson Snyder 6574a126ef spdiff: Ignore copyright differences 2011-01-01 18:20:30 -05:00
Wilson Snyder 1e68086355 Fix defparam test failing after make clean 2011-01-01 18:12:29 -05:00
Wilson Snyder 326cc8fd67 Fix DLYSYNC with for loop variables 2010-12-31 20:18:21 -05:00
Wilson Snyder 4afcb421bd With --Wall, add BLKSEQ warning on blocking assignments in seq blocks. 2010-12-31 18:36:29 -05:00
Wilson Snyder 8d21917035 Add SYNCASYNCNET 2010-12-31 07:51:14 -05:00
Wilson Snyder 4ca7f8834c Fix test ignores 2010-12-30 21:20:58 -05:00
Wilson Snyder b43299c8da Fix suppression of messages under debug 2010-12-30 08:41:23 -05:00
Wilson Snyder b763809f5e Fix last commit; allow multiple exprs 2010-12-30 08:26:36 -05:00
Wilson Snyder 2cb97f7475 For UNUSED, ignore black boxed sys calls 2010-12-30 07:55:31 -05:00
Wilson Snyder 6283df7491 Vlt lint off now has optional msgname 2010-12-30 06:58:02 -05:00
Wilson Snyder acc4490370 For UNUSED, skip primitive tables 2010-12-29 20:24:31 -05:00
Wilson Snyder f85c1a995a For UNUSED, better by-bit warnings 2010-12-29 19:59:07 -05:00
Wilson Snyder 809e5fda8a Ignore DECLFILENAME on library files 2010-12-29 19:34:33 -05:00
Wilson Snyder dce245da5a Allow wildcards in vlt config files 2010-12-29 19:14:49 -05:00
Wilson Snyder d261c4cd27 For UNUSED warning, ignore genvars 2010-12-29 18:10:02 -05:00
Wilson Snyder c33299d542 Add UNUSED and UNDRIVEN warnings 2010-12-29 08:06:05 -05:00
Wilson Snyder ebdf8a5f3c Internals: Constify tristates with ConstLive, unused so no functional change 2010-12-29 07:56:22 -05:00
Wilson Snyder c8852d183f Internals: Add V3Const preserving liveness, no functional change 2010-12-28 21:23:16 -05:00
Wilson Snyder 9f161b20ef Internals: Avoid passing vars from V3Const visitor; no functional change 2010-12-28 20:46:13 -05:00
Wilson Snyder 40f9d64973 Commentary 2010-12-27 17:25:28 -05:00
Wilson Snyder 4a2e68a0fd Avoid -wall 2010-12-26 15:26:04 -05:00
Wilson Snyder bcd90d3401 Constify LSB subtractions immediately, no functional change intended 2010-12-26 15:20:57 -05:00
Wilson Snyder 114af7d33f Make UNUSED/UNDRIVEN -Wall only 2010-12-26 10:17:35 -05:00
Wilson Snyder 7b83d2de49 Commentary 2010-12-26 09:40:17 -05:00
Wilson Snyder 850de5913d With --Wall, add IFDEPTH warning on deep if statements. 2010-12-26 09:31:09 -05:00
Wilson Snyder bb9ee46f40 Use 'suggest' in INCABSPATH warning 2010-12-26 08:19:45 -05:00
Wilson Snyder e94fc1305b Support unique0; track internally with new attributes 2010-12-26 08:09:25 -05:00
Wilson Snyder 3e4e8feb29 With --Wall, add DECLFILENAME warning on modules not matching filename. 2010-12-25 16:31:22 -05:00
Wilson Snyder fedf347b1a With --Wall, add INCABSPATH warning on `include with absolute paths. 2010-12-25 15:50:07 -05:00
Wilson Snyder 285277a50b Add -Wall; move VARHIDDEN to style warnings 2010-12-25 15:28:13 -05:00
Wilson Snyder 323c96f42f Add -Wwarn-style, -Wno-style, and DEFPARAM warnings 2010-12-25 15:13:56 -05:00
Wilson Snyder 7dee344ea9 Add limited support for VPI access to public signals, see docs. 2010-12-25 14:39:41 -05:00
Wilson Snyder 65bce588e4 Add fatalSrc debug dump check 2010-12-24 13:15:46 -05:00
Wilson Snyder 233ff1b744 --gdbbt now documented, and uses return-child-results
Use this in first test_c to backtrace if any problems.
2010-12-17 20:14:25 -05:00
Wilson Snyder 0837e39787 With -V, print VERILATOR_BIN env var 2010-12-17 19:40:08 -05:00
Wilson Snyder 86db565a21 Fix extra / in binary name 2010-12-14 18:08:41 -05:00
Wilson Snyder d6ac5e5001 Support ++,--,+= etc as standalone statements. 2010-12-07 20:18:47 -05:00
Wilson Snyder e6443f1981 Fix manifest tsub error, broke earlier 2010-12-07 11:45:31 -05:00
Wilson Snyder d13e6c73db When running with VERILATOR_ROOT, optionally find binaries under bin. 2010-12-07 11:43:43 -05:00
Wilson Snyder 79ca7f3cb5 Commentary 2010-12-07 09:30:52 -05:00
Wilson Snyder cfd07ccd34 Suppress WIDTH warnings when adding/subtracting 1'b1. 2010-12-02 14:00:43 -05:00
Wilson Snyder 48047d523a Remove dead code ifdef, bug299 2010-11-03 12:38:26 -04:00
Wilson Snyder eeb8fc2626 Add -F option to read relative option files, bug297. 2010-11-03 07:21:34 -04:00
Wilson Snyder 3d1baf3f2f Version bump 2010-11-02 21:11:02 -04:00
Wilson Snyder 4e382d6765 tests: add --golden flag 2010-11-02 21:10:52 -04:00
Wilson Snyder 582963375d tests: fix pipe bad golden 2010-11-02 21:10:44 -04:00
Wilson Snyder 56c7c1bcc8 Add warning when directory contains spaces, msg378 2010-10-28 09:51:36 -04:00
Wilson Snyder f88e57ddb8 Fix DPI export name not found, msg369. 2010-10-22 13:10:31 -04:00
Wilson Snyder 9d98e012e4 Fix segfault on SystemVerilog "output wire foo=0", bug291. 2010-10-04 07:48:09 -04:00
Wilson Snyder d305a774f0 Fix wrong filename on include file errors, bug289 2010-09-28 09:33:59 -04:00
Wilson Snyder 16b0c8d353 Commentary 2010-09-25 07:59:18 -04:00
Wilson Snyder 55da4fdbf6 Typo fixes. 2010-09-25 07:46:09 -04:00
Wilson Snyder ed2fbd8f25 Version bump 2010-09-20 15:46:17 -04:00
Wilson Snyder 42199bc8e5 Fix preprocessor `` of existing base define, bug283. 2010-09-20 15:20:16 -04:00
Wilson Snyder 7c5318768c Reduce debug verbosity (match Verilog-Perl) 2010-09-20 13:13:31 -04:00
Wilson Snyder aba25aab19 On core dump, print debug suggestions. 2010-09-20 09:21:29 -04:00
Wilson Snyder f99bd33f91 Support tracing/coverage of underscore signals, bug280. 2010-08-29 19:28:46 -04:00
Wilson Snyder a6a6ce83f0 Internals: Use branch prediction in asserts 2010-08-10 11:19:45 -04:00
Wilson Snyder f4908a9758 Increase define recursions before error 2010-08-10 11:18:53 -04:00
Wilson Snyder 5e4ca4b76a Version bump 2010-07-10 18:41:23 -04:00
Wilson Snyder 1e938d0e90 Update preprocessor to match next Verilog-Perl version.
Fix preprocessor preservation of newlines across macro substitutions.
Fix preprocessor stringification of nested macros.
Fix preprocessor whitespace on define arguments
2010-07-10 18:30:16 -04:00
Wilson Snyder f3704f4c05 Tests: Rename includes to .vh extensions 2010-07-08 20:51:54 -04:00
Wilson Snyder 8800efe953 Internals: Rename incLineno to match Verilog-Perl, no functional change. 2010-07-08 20:31:41 -04:00
Wilson Snyder a320c4584e Fix do {...} while() not requiring final semicolon. 2010-07-07 19:15:51 -04:00
Wilson Snyder 3841850168 Preproc: fix pass-through of `line enter-exit codes.
Internals: Merge Verilog-Perl preproc changes through d450722.
2010-07-06 20:29:12 -04:00
Wilson Snyder beb3885840 Add t_clk_2in test 2010-06-21 20:40:34 -04:00
Wilson Snyder 06967c0c46 Fix some constant parameter functions causing crash, bug253. 2010-05-25 19:37:45 -04:00
Wilson Snyder 9a382c572c Commentary, bug251 2010-05-02 06:29:02 -04:00
Wilson Snyder 44b6c371db Version bump 2010-05-01 14:18:56 -04:00
Wilson Snyder 00970be996 Fix bit reductions on multi-packed dimensions, bug227/patch0004. 2010-04-22 09:40:53 -04:00
Wilson Snyder aca4ab015f Fix removing if assigned to unused var, bug248. 2010-04-19 19:38:22 -04:00
Wilson Snyder 68b63d5783 Increase unrollStmts, bug247, due to unreleased change. 2010-04-19 13:59:15 -04:00
Wilson Snyder 4b499f2bb1 Commentary, bug246 2010-04-19 09:44:48 -04:00
Wilson Snyder ed17581f92 Fix loop unroller out of memory; change --unroll-stmts. 2010-04-17 08:01:22 -04:00
Wilson Snyder a46c4ec912 Accelerate and reduce memory usage of V3Expand 2010-04-15 21:05:21 -04:00
Wilson Snyder 930cbeec17 Internals: Create user#Inc routines 2010-04-15 20:56:54 -04:00
Wilson Snyder 10689ffaba Fix carrage return purging, broke in pre-release only 2010-04-10 09:11:52 -04:00
Wilson Snyder 29b0ea0af9 Debug: Allow --debugi-V3PreShell to turn on flex debug 2010-04-10 08:20:28 -04:00
Wilson Snyder 57d00946be Fix MSVC compile issues 2010-04-10 06:46:24 -04:00
Wilson Snyder ef51de72c9 Fix word size to match uint64_t on -m64 systems, bug238. 2010-04-09 21:51:15 -04:00
Wilson Snyder c807bf1e0e Internals: Fix useless rule and flex warning 2010-04-09 21:06:16 -04:00
Byron Bradley 2525b3fb05 Fix bit reductions on multi-packed dimensions, bug227
Signed-off-by: Wilson Snyder <[email protected]>
2010-04-09 21:05:46 -04:00
Byron Bradley 9163ce0f6e Internals: modify AstVar::dimensions() to return a pair, bug227
Signed-off-by: Wilson Snyder <[email protected]>
2010-04-09 20:43:25 -04:00
Byron Bradley d776638f53 Internals: Mark packed dimensions in arrays, bug227
Signed-off-by: Wilson Snyder <[email protected]>
2010-04-09 20:40:41 -04:00
Wilson Snyder 83fff41312 Fix installing data files as non-executable, bug168. 2010-04-09 20:21:00 -04:00
Wilson Snyder dd7d9bc95b Fix some spelling mistakes in verilator executable & manpage, bug240 2010-04-09 19:45:46 -04:00
Wilson Snyder f8eabbc100 From Verilog-Perl: Fix parsing single files > 2GB. 2010-04-06 20:20:44 -04:00
Wilson Snyder 7ed18ac62d Internals: Track Verilog-Perl 3.240 parser changes 2010-04-06 18:55:54 -04:00
Wilson Snyder 3ac707c645 Tests: Fix vpi_user addition failure 2010-04-06 18:43:24 -04:00
Wilson Snyder 8e9a1e0bf3 Add standard vpi_user.h file 2010-04-05 20:08:13 -04:00
Wilson Snyder bc31b5d27a Commentary 2010-04-05 20:08:07 -04:00
Wilson Snyder 936738b750 Add /*verilator public_flat_rw*/ for timing-specific public access. 2010-04-05 20:01:17 -04:00
Wilson Snyder 7c3048ab9c Report errors when extra underscores used in meta-comments. 2010-03-24 22:08:59 -04:00
Wilson Snyder 64719f3ace Makefile: Add local install-cadtools rule 2010-03-24 16:09:29 -04:00
Wilson Snyder a11a5f04d5 Default Verilated::debug() to off 2010-03-23 20:31:22 -04:00
Wilson Snyder eb5c035dde Internals: Fix some missing branch prediction 2010-03-22 19:07:03 -04:00
Wilson Snyder c3887efbf3 Internals: Remove dead code 2010-03-22 19:06:30 -04:00
Wilson Snyder 495585830d Fix trace files with empty modules crashing some viewers. 2010-03-22 18:38:24 -04:00
Wilson Snyder 6715cb9880 Improve error handling on slices of arrays, bug226. 2010-03-20 21:29:16 -04:00
Wilson Snyder 41b167d23c Fix DPI display bogus error 2010-03-20 07:13:52 -04:00
Wilson Snyder 7ea8b54210 Tests: Support atsim and cleanup verilator-only tests 2010-03-18 12:03:08 -04:00
Wilson Snyder bcea39a858 Fix "make install" with configure outside srcdir. 2010-03-17 20:20:40 -04:00
Wilson Snyder fb560abac4 Commentary 2010-03-17 19:57:38 -04:00
Wilson Snyder ba93a08b40 Support runtime access to public signal names 2010-03-17 08:22:49 -04:00
Wilson Snyder 2be6b3481c Pre-version 2010-03-17 08:05:07 -04:00
Wilson Snyder 6ef44a6fbb Version bump 2010-03-17 07:59:12 -04:00
Wilson Snyder 2afe40a0b5 verilated: Add debug pointers to scopeDump() 2010-03-16 19:28:29 -04:00
Wilson Snyder e57d004718 Fix clock-gates with non-AND complex logic, bug220. 2010-03-16 18:50:26 -04:00
Wilson Snyder d780d0aabb Fix flushing VCD buffers on . 2010-03-12 20:00:08 -05:00
Wilson Snyder 0f9e3f0767 Cleanup flex compiles again - remove yyleng from preproc.cpp 2010-03-05 12:02:56 -05:00
Wilson Snyder 381972c923 Fix Mac OS-X compile issues, bug217. 2010-02-26 19:50:44 -05:00
Wilson Snyder 845d7ad718 Commentary 2010-02-26 18:57:34 -05:00
Wilson Snyder f1b6c0c559 Support "`default_nettype none|wire". 2010-02-23 09:27:16 -05:00
Wilson Snyder e39eddf3fe Fix parametrized defines with empty arguments. 2010-02-21 07:20:39 -05:00
Wilson Snyder 72218fb475 Defines with // comments still need continuation - spec ambiguity 2010-02-18 20:57:46 -05:00
Wilson Snyder 9a3e497c22 Fix specparam defaults 2010-02-18 08:43:16 -05:00
Wilson Snyder 85d510cd48 Fix vl_mc_scan_plusarg returning stack based pointer 2010-02-16 11:54:39 -05:00
Wilson Snyder 786c65ea5f Makefile: reconfigure when src/*.in changes 2010-02-15 07:34:55 -05:00
Wilson Snyder 10e6f61125 Commentary 2010-02-14 19:23:29 -05:00
Wilson Snyder cdd06e7236 Support "break", "continue", "return". 2010-02-14 10:01:21 -05:00
Wilson Snyder 48603c0ee2 Commentary 2010-02-10 08:50:41 -05:00
Wilson Snyder 63f30492be Skip SystemC tests if not installed. 2010-02-08 20:51:43 -05:00
Wilson Snyder 0e8772290d Fix make uninstall, bug216 2010-02-08 09:28:40 -05:00
Wilson Snyder 6cfc5798b0 Tests: Move sc_main.cpp as there's more sc than sp users 2010-02-08 08:10:07 -05:00
Wilson Snyder 6be275f5d4 Post release version bump 2010-02-08 06:27:07 -05:00
410 changed files with 11910 additions and 2046 deletions
+148 -1
View File
@@ -3,6 +3,153 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.812 2011/04/06
*** Add --trace-max-width and --trace-max-array, bug 319. [Alex Solomatnikov]
*** Add --Wno-fatal to turn off abort on warnings. [by Stefan Wallentowitz]
**** Support ${...} and $(...) env vars in .vc files. [by Stefan Wallentowitz]
**** Support $bits(data_type), bug327. [Alex Solomatnikov]
**** Support loop unrolling on width mismatches, bug 333. [Joe Eiler]
**** Support simple cast operators, bug335. [Alex Solomatnikov]
**** Accelerate bit-selected inversions.
**** Add error on circular parameter definitions, bug329. [Alex Solomatnikov]
**** Fix concatenates and vectored bufif1, bug326. [Iztok Jeras]
* Verilator 3.811 2011/02/14
**** Report errors on duplicated or empty pins, bug321. [Christian Leber]
**** Report error on function call output tied to constant. [Bernard Deadman]
**** Throw UNUSED/UNDRIVEN only once per net in a parametrized module.
**** Fix internal error on functions called as SV tasks. [Bernard Deadman]
**** Fix internal error on non-inlined inout pins. [Jeff Winston]
**** Fix false BLKSEQ on non-unrolled for loop indexes. [Jeff Winston]
**** Fix block comment not separating identifiers, bug311. [Gene Sullivan]
**** Fix warnings to point to lowest net usage, not upper level ports.
**** Fix error on constants connected to outputs, bug323. [Christian Leber]
* Verilator 3.810 2011/01/03
** Add limited support for VPI access to public signals, see docs.
*** Add -F option to read relative option files, bug297. [Neil Hamilton]
*** Support ++,--,+= etc as standalone statements. [Alex Solomatnikov]
**** When running with VERILATOR_ROOT, optionally find binaries under bin.
**** Suppress WIDTH warnings when adding/subtracting 1'b1.
** Add -Wall, -Wwarn-style, -Wno-style to enable code style warnings
that have been added to this release, and disabled by default:
*** With --Wall, add BLKSEQ warning on blocking assignments in seq blocks.
*** With --Wall, add DECLFILENAME warning on modules not matching filename.
*** With --Wall, add DEFPARAM warning on deprecated defparam statements.
*** With --Wall, add IFDEPTH warning on deep if statements.
*** With --Wall, add INCABSPATH warning on `include with absolute paths.
*** With --Wall, add SYNCASYNCNET warning on mixed sync/async reset nets.
*** With --Wall, add UNDRIVEN warning on undriven nets.
*** With --Wall, add UNUSED warning on unused nets.
*** The VARHIDDEN warning is now disabled by default, use -Wall to enable.
* Verilator 3.805 2010/11/02
**** Add warning when directory contains spaces, msg378. [Salman Sheikh]
**** Fix wrong filename on include file errors, bug289. [Brad Parker]
**** Fix segfault on SystemVerilog "output wire foo=0", bug291. [Joshua Wise]
**** Fix DPI export name not found, msg369. [Terry Chen]
* Verilator 3.804 2010/09/20
*** Support tracing/coverage of underscore signals, bug280. [by Jason McMullan]
**** Fix preprocessor `` of existing base define, bug283. [Usha Priyadharshini]
**** Increase define recursions before error. [Paul Liu]
**** On core dump, print debug suggestions.
* Verilator 3.803 2010/07/10
*** Fix preprocessor preservation of newlines across macro substitutions.
**** Fix preprocessor stringification of nested macros.
**** Fix some constant parameter functions causing crash, bug253. [Nick Bowler]
**** Fix do {...} while() not requiring final semicolon.
* Verilator 3.802 2010/05/01
*** Support runtime access to public signal names.
*** Add /*verilator public_flat_rw*/ for timing-specific public access.
*** Fix word size to match uint64_t on -m64 systems, bug238. [Joe Eiler]
**** Improve error handling on slices of arrays, bug226. [by Byron Bradley]
**** Report errors when extra underscores used in meta-comments.
**** Fix bit reductions on multi-packed dimensions, bug227. [by Byron Bradley]
**** Fix removing $fscanf if assigned to unused var, bug248. [Ashutosh Das]
**** Fix "make install" with configure outside srcdir. [Stefan Wallentowitz]
**** Fix loop unroller out of memory; change --unroll-stmts. [Ashutosh Das]
**** Fix trace files with empty modules crashing some viewers.
**** Fix parsing single files > 2GB. [Jeffrey Short]
**** Fix installing data files as non-executable, bug168. [by Ahmed El-Mahmoudy]
* Verilator 3.801 2010/03/17
*** Support "break", "continue", "return".
*** Support "`default_nettype none|wire". [Dominic Plunkett]
**** Skip SystemC tests if not installed. [Iztok Jeras]
**** Fix clock-gates with non-AND complex logic, bug220. [Ashutosh Das]
**** Fix flushing VCD buffers on $stop. [Ashutosh Das]
**** Fix Mac OS-X compile issues, bug217. [Joshua Wise, Trevor Williams]
**** Fix make uninstall, bug216. [Iztok Jeras]
**** Fix parametrized defines with empty arguments.
* Verilator 3.800 2010/02/07
Application visible changes:
@@ -1585,7 +1732,7 @@ of input ports exists for tracing.
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
Copyright 2001-2010 by Wilson Snyder. This program is free software; you
Copyright 2001-2011 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.
+98 -41
View File
@@ -9,7 +9,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2011 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.
@@ -118,8 +118,9 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
src/*.pl src/*.pod \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
test_verilated/vgen*.pl \
test_regress/t/tsub/*.v* \
test_regress/t/*.cpp \
test_regress/t/*.h \
test_regress/t/*.dat \
@@ -134,10 +135,9 @@ INST_PROJ_FILES = \
bin/verilator \
bin/verilator_includer \
bin/verilator_profcfunc \
include/verilated.[chv]* \
include/verilated.mk \
include/verilatedos.[chv]* \
include/verilated_*.[chv]* \
include/*.[chv]* \
include/vltstd/*.[chv]* \
INST_PROJ_BIN_FILES = \
verilator_bin \
@@ -145,8 +145,6 @@ INST_PROJ_BIN_FILES = \
DISTFILES := $(DISTFILES_INC)
VL_INST_MAN_FILES = verilator.1
ifeq ($(OBJCACHE_JOBS),)
ifneq ($(OBJCACHE_HOSTS),)
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
@@ -238,11 +236,29 @@ internals.txt: internals.pod
-rm -f $@
$(POD2TEXT) --loose $< > $@
# See uninstall also
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
verilator_includer verilator_profcfunc
# Some scripts go into both the search path and pkgdatadir,
# so they can be found by the user, and under $VERILATOR_ROOT.
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
VL_INST_MAN_FILES = verilator.1
VL_INST_INC_BLDDIR_FILES = \
include/verilated.mk \
# Files under srcdir, instead of build time
VL_INST_INC_SRCDIR_FILES = \
include/*.[chv]* \
include/vltstd/*.[chv]* \
VL_INST_DATA_SRCDIR_FILES = \
test_v/*.[chv]* \
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
test_sp/*.[chv]* test_sp/Makefile test_sp/Makefile_obj \
installbin:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
@@ -255,26 +271,52 @@ installbin:
installman: $(VL_INST_MAN_FILES)
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(mandir)/man1/$$p; \
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
done
installdata:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd $(DESTDIR)$(pkgdatadir)/examples
cp -r include/*.* $(DESTDIR)$(pkgdatadir)/include
cp -r ${srcdir}/include/*.* $(DESTDIR)$(pkgdatadir)/include
cp -r ${srcdir}/include/vltstd/*.* $(DESTDIR)$(pkgdatadir)/include/vltstd
cp -r ${srcdir}/test_c $(DESTDIR)$(pkgdatadir)/examples
cp -r ${srcdir}/test_sc $(DESTDIR)$(pkgdatadir)/examples
cp -r ${srcdir}/test_sp $(DESTDIR)$(pkgdatadir)/examples
cp -r ${srcdir}/test_v $(DESTDIR)$(pkgdatadir)/examples
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd
for p in $(VL_INST_INC_BLDDIR_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
done
cd $(srcdir) \
; for p in $(VL_INST_INC_SRCDIR_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
done
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sp
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v
cd $(srcdir) \
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
done
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
uninstall:
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_BIN_FILES)
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
-rmdir $(DESTDIR)$(pkgdatadir)/bin
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
-rmdir $(DESTDIR)$(pkgdatadir)/include
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_c
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sc
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sp
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
-rmdir $(DESTDIR)$(pkgdatadir)/examples
-rmdir $(DESTDIR)$(pkgdatadir)
VL_INST_DATA_FILES = verilator.1
install: all_nomsg installbin installman installdata install-msg
install-here: installman ftp
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
DIRPROJECT := $(shell project_dir --project)
VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH)
INST_PROJ_CVS = cp_if_cvs_diff
install-project: dist
@@ -282,7 +324,7 @@ install-project: dist
strip verilator_bin*
$(MAKE) install-project-quick
for p in verilator.1 ; do \
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
done
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
rm $(DISTNAME).tgz
@@ -299,6 +341,34 @@ endif
for p in $(INST_PROJ_BIN_FILES) ; do \
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p-$(DIRPROJECT_ARCH); \
done
install-cadtools: dist
@echo "Install-project to $(CAD_DIR)"
strip verilator_bin*
$(MAKE) install-cadtools-quick
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
for p in verilator.1 ; do \
$(INSTALL_DATA) $$p $(VERILATOR_CAD_DIR)/man/man1/$$p; \
done
$(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz
rm $(DISTNAME).tgz
install-cadtools-quick:
ifeq ($(CFG_WITH_DEFENV),yes)
@echo "%Error: Reconfigure with './configure --disable-defenv' to avoid hardcoded paths."
false
endif
@echo "Install-cadtools-quick (no strip) to $(VERILATOR_CAD_DIR)"
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/include/vltstd
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/bin
for p in $(INST_PROJ_FILES) ; do \
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
done
for p in $(INST_PROJ_BIN_FILES) ; do \
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
done
# VERILATOR_AUTHOR_SITE
endif
ftp: info
@@ -306,33 +376,19 @@ ftp: info
install-msg:
@echo "Installed!"
@echo
@echo "Add to your startup file (for bash or csh, as appropriate):"
@echo " export VERILATOR_ROOT="`pwd`
@echo " setenv VERILATOR_ROOT "`pwd` " ; export VERILATOR_ROOT "
@echo
@echo "See 'verilator.txt' for documentation."
@echo "Fod documentation see 'man verilator' or 'verilator --help'"
@echo "For forums and to report bugs see http://www.veripool.org/verilator"
@echo
uninstall:
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
-rm -f $(DESTDIR)$(pkgdatadir)
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in
# autoheader might not change config_build.h.in, so touch a stamp file.
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
*.in */*.in */*.in
${srcdir}/config_build.h.in: stamp-h.in
${srcdir}/stamp-h.in: configure.ac $(wildcard $(IN_WILD))
# autoheader might not change config_build.h.in, so touch it
${srcdir}/config_build.h: ${srcdir}/config_build.h.in configure
cd ${srcdir} && autoheader
echo timestamp > ${srcdir}/stamp-h.in
config_build.h: stamp-h
stamp-h: config_build.h.in config.status
./config.status
Makefile: Makefile.in config.status
./config.status
src/Makefile: src/Makefile.in config.status
touch $@
Makefile: Makefile.in config.status $(IN_WILD)
./config.status
src/Makefile: src/Makefile.in Makefile
config.status: configure
./config.status --recheck
configure: configure.ac
@@ -382,6 +438,7 @@ DISTCONFIG = ${srcdir}/src/config_build.h.in
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
DISTNAMEREV := $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q src/config_rev.h)
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
DISTDATE := $(subst /,-,$(DISTDATEPRE))
+99 -90
View File
@@ -1,134 +1,143 @@
// DESCRIPTION: Verilator: List of To Do issues.
//
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2011 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.
Features:
Latch optimizations {Need here}
Task I/Os connecting to non-simple variables.
Fix ordering of each bit separately in a signal (mips)
Language support:
* Fix ordering of each bit separately in a signal (mips)
assign b[3:0] = b[7:4]; assign b[7:4] = in;
Support gate primitives/ cell libraries from xilinx, etc
Assign dont_care value to an 1'bzzz assignment
Function to eval combo logic after /*verilator public*/ functions [gwaters]
Support generated clocks (correctness)
?gcov coverage
Selectable SystemC types based on widths (see notes below)
Coverage
Points should be per-scope like everything else rather then per-module
Expression coverage (see notes)
Constant functions for widths, etc, IE "input [log2(PARAM):0] xx;"
More Verilog 2001 Support
(* *) Attributes (just ignore -- preprocessor?)
Real numbers (NEVER)
Recursive functions (NEVER)
Verilog configuration files (NEVER)
DPI to define C/C++ calls from Verilog
* Support UDP gate primitives/ cell libraries
(have code for combos - problem is sequential udps)
* Function to eval combo logic after /*verilator public*/ functions [gwaters]
* Support generated clocks (correctness)
* Real numbers
* Recursive functions
* Verilog configuration files
* Structs/unions (have starting point)
* DPI to define C/C++ calls from Verilog
* Expression coverage (see notes)
* Better tristate support
Long-term Features
Assertions
VHDL parser [Philips]
Tristate support
SystemPerl integration
Multithreaded execution
* Assertions
* Tristate support
* Multithreaded execution
Configure/Make/Install
* Full MSVC++ compilation (does scons support this?) (4.000?)
* Distribute with flex/bison already expanded?
Flex library not needed. Probably too difficult to be worth it.
* Integrate SystemPerl coverage
(Note in /usr/include there are no upper cased include files.)
Coverage.pm -- Need all functionality, but in C?
Coverage/Item.pm -- Need all functionality, but in C?
Coverage/ItemKey.pm -- Need all functionality, but in C?
sp_preproc -- Some steps in here need to be moved to generated C
src/Sp.cpp -- n/a
src/SpCommon.h -- mostly overlaps verilatedos.h
src/SpCoverage.cpp/h -- All needed
src/SpFunctor.cpp/h -- No longer used
src/SpTraceVcd.cpp/h -- MOVED
src/SpTraceVcdC.cpp/h -- MOVED
src/sp_log.cpp/h -- Not needed
src/systemperl.h -- some stuff may be cut
vcoverage -- Need all functionality, but in C?
Testing:
Capture all inputs into global "rerun it" file
Code to make wrapper that sets signals, so can do comparison checks
New random program generator
Better graph viewer with search and zoom
Port and test against opencores.org code
* Move test_c/sp/v/verilated into test_regress format (4.000?)
* Capture all inputs into global "rerun it" file
* Code to make wrapper that sets signals, so can do comparison checks
* New random program generator
* Better graph viewer with search and zoom
* Port and test against opencores.org code
Usability:
Better reporting of unopt problems, including what lines of code
Report more errors (all of them?) before exiting [Eugene Weber]
* Detect and pre-remove most UNOPTFLATs (4.000)
* Better reporting of unopt problems, including what lines of code
* Report more errors (all of them?) before exiting [Eugene Weber]
* Auto-create scons config files
* Print version/etc message at runtime. (4.000?)
Include number of lines of code, percent comments, code complexity measurement
<-80chars------------------------------------------------------------------->
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2011.
Verilated #### modules, #### instances, ##### sigs,
#### non-comment lines, ##### ops, ### KB model size
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
Lint:
* CDCRSTLOGIC should allow filtering with paths
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
Internal Code:
Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
and removing it will speed up and simplify all the other code.
V3Graph should be templated container type, taking in Vertex + Edge types
* Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
and removing it will speed up and simplify all the other code.
* V3Graph should be templated container type, taking in Vertex + Edge types
* Rename V3PreLex etc to match VerilogPerl filenames
* Instead of string, have an VEncodedString/VIdString which contains __DOT__ish
things, to reduce bugs. Also add _20 trailing space to \ encoded names. (4.000)
Runtime:
* New evalulation loop ~/src/verilator/notes/event_loop.txt (4.000?)
* Remove all private internal functions from top level wrapper header, move
to new level (4.000?)
* Completely standalone simulation (4.000)
main() records arguments for $test$plusvars
instantiates top,
does tracing (support $dump?)
calls top->simulateForever()
exits
Performance:
Constant propagation
* Latch optimizations
* Constant propagation
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
Extra shift (perhaps due to clean): if (1 & CAST (VARREF >> #))
Gated clock and latch conversion to flops. [JeanPaul Vanitegem]
* Gated clock and latch conversion to flops. [JeanPaul Vanitegem]
Could propagate the AND into pos/negedges and let domaining optimize.
Negedge reset
* Negedge reset
Switch to remove negedges that don't matter
Can't remove async resets from control flops (like in syncronizers)
If all references to array have a constant index, blow up into separate signals-per-index
Multithreaded execution
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
Move _last sets and all other combo logic inside master
* If all references to array have a constant index, blow up into separate signals-per-index
* Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
* Move _last sets and all other combo logic inside master
if() that triggers on all possible sense items
Rewrite and combine V3Life, V3Subst
* Rewrite and combine V3Life, V3Subst
If block temp only ever set in one place to constant, propagate it
Used in t_mem for array delayed assignments
Replace variables if set later in same cfunc branch
See for example duplicate sets of _narrow in cycle 90/91 of t_select_plusloop
Same assignment on both if branches
* Same assignment on both if branches
"if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..."
Careful though, as b could appear in the statement or multiple times in statement
(Could just require exatly two 'b's in statement)
Simplify XOR/XNOR/AND/OR bit selection trees
* Simplify XOR/XNOR/AND/OR bit selection trees
Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 )
Combine variables into wider elements
* Combine variables into wider elements
Parallel statements on different bits should become single signal
Variables that are always consumed in "parallel" can be joined
Duplicate assignments in gate optimization
* Duplicate assignments in gate optimization
Common to have many separate posedge blocks, each with identical
reset_r <= rst_in
*If signal is used only once (not counting trace), always gate substitute
* If signal is used only once (not counting trace), always gate substitute
Don't merge if any combining would form circ logic (out goes back to in)
Multiple assignments each bit can become single assign with concat
* Multiple assignments each bit can become single assign with concat
Make sure a SEL of a CONCAT can get the single bit back.
Usually blocks/values
* Usually blocks/values
Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out
Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
Allow Split of case statements without a $display/$stop
I-cache packing improvements (what/how?)
Data cache organization (order of vars in class)
* Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
* Allow Split of case statements without a $display/$stop
* I-cache packing improvements (what/how?)
* Data cache organization (order of vars in class)
First have clocks,
then bools instead of uint32_t's
then based on what sense list they come from, all outputs, then all inputs
finally have any signals part of a "usually" block, or constant.
Rather then tracking widths, have a MSB...LSB of this expression
* Rather then tracking widths, have a MSB...LSB of this expression
(or better, a bitmask of bits relevant in this expression)
Track recirculation and convert into clock-enables
Clock enables should become new clocking domains for speed
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
All of the temp vars that get set, exp pre_ vars and never feedback
(not flops) don't need to be stored in the structs, but instead can
be per-invocation, and even better register-colored-like to reuse
the space. This will greatly reduce the data footprint.
//**********************************************************************
//* Eventual tristate bus Stuff allowed (old verilator)
1) Tristate assignments must be continuous assignments
The RHS of a tristate assignment can be the following
a) a node (tristate or non-tristate)
b) a constant (must be all or no z's)
x'b0, x'bz, x{x'bz}, x{x'b0} -> are allowed
c) a conditional whose possible values are (a) or (b)
2) One can lose that fact that a node is a tristate node. This happens
if a tristate node is assigned to a 'standard' node, or is used on
RHS of a conditional. The following infer tristate signals:
a) inout <SIGNAL>
b) tri <SIGNAL>
c) assigning to 'Z' (maybe through a conditional)
Note: tristate-ness of an output port determined only by
statements in the module (not the instances it calls)
4) Tristate variables can't be multidimensional arrays
5) Only check tristate contention between modules (not within!)
6) Only simple compares with 'Z' are allowed (===)
* Track recirculation and convert into clock-enables
* Clock enables should become new clocking domains for speed
* If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
* Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
+423 -72
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
######################################################################
#
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you
# Copyright 2003-2011 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.
@@ -78,15 +78,17 @@ if (! GetOptions (
}
# Determine runtime flags and run
if ($opt_gdbbt && !gdb_works()) {
warn "-Info: --gdbbt ignored: gdb doesn't seem to be working\n" if $Debug;
$opt_gdbbt = 0;
}
if ($opt_gdbbt && !$opt_gdb && $Debug) {
# Run under GDB to get gdbbt
run ("gdb ".verilator_bin()
." --batch --quiet"
." --batch --quiet --return-child-result"
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
." -ex 'set width 0'"
." -ex 'bt'"
." -ex 'c'");
die "%Error: --gdbbt looses the exit status; so must assume run went badly...";
." -ex 'bt'");
} else {
# Normal, non gdb
run (($opt_gdb?"$opt_gdb ":"")
@@ -113,9 +115,18 @@ sub debug {
sub verilator_bin {
my $bin = "";
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
$bin .= $ENV{VERILATOR_ROOT}."/" if defined($ENV{VERILATOR_ROOT});
$bin .= ($ENV{VERILATOR_BIN}
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
my $basename = ($ENV{VERILATOR_BIN}
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
if (defined($ENV{VERILATOR_ROOT})) {
my $dir = $ENV{VERILATOR_ROOT};
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
$bin = "$dir/bin/$basename";
} else {
$bin = "$dir/$basename"; # From pointing to kit directory
}
} else {
$bin = $basename;
}
return $bin;
}
@@ -123,9 +134,21 @@ sub verilator_bin {
#######################################################################
# Utilities
sub gdb_works {
$! = undef; # Cleanup -x
system("gdb /bin/echo"
." --batch-silent --quiet --return-child-result"
." -ex 'run -n'" # `echo -n`
." -ex 'set width 0'"
." -ex 'bt'");
my $status = $?;
return $status==0;
}
sub run {
# Run command, check errors
my $command = shift;
$! = undef; # Cleanup -x
print "\t$command\n" if $Debug>=3;
system($command);
my $status = $?;
@@ -137,6 +160,15 @@ sub run {
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n";
}
if ($status & 255) {
if (($status & 255) == 8 || ($status & 255) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 255) == 6) { # SIGABRT
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
} else {
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
}
}
die "%Error: Command Failed $command\n";
}
}
@@ -199,7 +231,7 @@ descriptions in the next sections for more information.
--bbox-sys Blackbox unknown $system calls
--bbox-unsup Blackbox unsupported language features
--bin <filename> Override Verilator binary
-CFLAGS <flags> C++ Compiler flags for makefile
-CFLAGS <flags> C++ Compiler flags for makefile
--cc Create C++ output
--cdc Clock domain crossing analysis
--compiler <compiler-name> Tune for specified C++ compiler
@@ -207,6 +239,7 @@ descriptions in the next sections for more information.
--coverage-line Enable line coverage
--coverage-toggle Enable toggle coverage
--coverage-user Enable PSL/SVL user coverage
--coverage-underscore Enable covarge of _signals
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
@@ -214,17 +247,20 @@ descriptions in the next sections for more information.
--debugi-<srcfile> <level> Enable debugging a source file at a level
+define+<var>+<value> Set preprocessor define
--dump-tree Enable dumping .tree files
-E Preprocess, but do not compile
-E Preprocess, but do not compile
--error-limit <value> Abort after this number of errors
--exe Link to create executable
-F <file> Parse options from a file, relatively
-f <file> Parse options from a file
--help Display this help.
--gdbbt Run Verilator under GDB for backtrace
--help Display this help
-I<dir> Directory to search for includes
--if-depth <value> Tune IFDEPTH warning
+incdir+<dir> Directory to search for includes
--inhibit-sim Create function to turn off sim
--inline-mult <value> Tune module inlining
-LDFLAGS <flags> Linker pre-object flags for makefile
-LDLIBS <flags> Linker library flags for makefile
-LDFLAGS <flags> Linker pre-object flags for makefile
-LDLIBS <flags> Linker library flags for makefile
--language <lang> Language standard to parse
+libext+<ext>+[ext]... Extensions for finding modules
--lint-only Lint, but do not make output
@@ -238,12 +274,12 @@ descriptions in the next sections for more information.
-O0 Disable optimizations
-O3 High performance optimizations
-O<optimization-letter> Selectable optimizations
-o <executable> Name of final executable
-o <executable> Name of final executable
--output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .ccp functions
--pins-bv <bits> Specify types for top level ports
--pins-uint8 Specify types for top level ports
--pipe-filter <command> Filter all input through a script
--pipe-filter <command> Filter all input through a script
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--private Debugging; see docs
@@ -256,15 +292,21 @@ descriptions in the next sections for more information.
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
--trace-max-array <bits> Maximum bit width for tracing
--trace-max-width <depth> Maximum array depth for tracing
--trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations
--unroll-stmts <stmts> Tune maximum loop body size
--unused-regexp <regexp> Tune UNUSED lint signals
-V Verbose version and config
-v <filename> Verilog library
-Werror-<message> Convert warning to error
-Wfuture-<message> Disable unknown message warnings
-Wno-<message> Disable warning
-Wno-lint Disable all lint warnings
-Wno-style Disable all style warnings
-Wno-fatal Disable fatal exit on warnings
-x-assign <mode> Initially assign Xs to this value
-y <dir> Directory to search for modules
@@ -426,6 +468,11 @@ counting such behavior.
A /*verilator coverage_off/on */ comment pair can be used around signals
that do not need toggle analysis, such as RAMs and register files.
=item --coverage-underscore
Enable coverage of signals that start with an underscore. Normally, these
signals are not covered. See also --trace-underscore.
=item --coverage-user
Enables user inserted functional coverage. Currently, all functional
@@ -486,10 +533,28 @@ After this number of errors or warnings are encountered, exit. Defaults to
Generate a executable. You will also need to pass additional .cpp files on
the command line that implement the main loop for your simulation.
=item -F I<file>
Read the specified file, and act as if all text inside it was specified as
command line parameters. Any relative paths are relative to the directory
containing the specified file. See also -f. Note -F is fairly standard
across Verilog tools.
=item -f I<file>
Read the specified file, and act as if all text inside it was specified as
command line parameters. Note -f is fairly standard across Verilog tools.
command line parameters. Any relative paths are relative to the current
directory. See also -F. Note -f is fairly standard across Verilog tools.
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
variable.
=item --gdbbt
If --debug is specified, run Verilator underneath a GDB process and print
a backtrace on exit. Without --debug or if GDB doesn't seem to work, this
flag is ignored.
=item --help
@@ -502,6 +567,11 @@ include directories or libraries. Same as +incdir and -y; +incdir and -y
are fairly standard across Verilog tools while -I is an alias for GCC
compatibility.
=item --if-depth I<value>
Rarely needed. Set the depth at which the IFDEPTH warning will fire,
defaults to 0 which disables this warning.
=item +incdir+I<dir>
Add the directory to the list of directories that should be searched for
@@ -547,12 +617,15 @@ appropriate `begin_keywords.
Specify the extensions that should be used for finding modules. If for
example module I<x> is referenced, look in I<x>.I<ext>. Note +libext+ is
fairly standard across Verilog tools.
fairly standard across Verilog tools. Defaults to .v and .sv.
=item --lint-only
Check the files for lint violations only, do not create any other output.
You may also want the -Wall option to enable messages that are considered
stylistic and not enabled by default.
If the design is not to be completely Verilated see also the --bbox-sys and
--bbox-unsup options.
@@ -750,6 +823,23 @@ Specify the number of levels deep to enable tracing, for example
entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size.
=item --trace-max-array I<bits>
Rarely needed. Specify the maximum array depth of a signal that may be
traced. Defaults to 32, as tracing large arrays may greatly slow traced
simulations.
=item --trace-max-width I<depth>
Rarely needed. Specify the maximum bit width of a signal that may be
traced. Defaults to 256, as tracing large vectors may greatly slow traced
simulations.
=item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these
signals are not output during tracing. See also --coverage-underscore.
=item -UI<var>
Undefines the given preprocessor symbol.
@@ -764,6 +854,12 @@ unrolled. See also BLKLOOPINIT warning.
Rarely needed. Specifies the maximum number of statements in a loop for
that loop to be unrolled. See also BLKLOOPINIT warning.
=item --unused-regexp I<regexp>
Rarely needed. Specifies a simple regexp with * and ? that if a signal
name matches will suppress the UNUSED warning. Defaults to "*unused*".
Setting it to "" disables matching.
=item -V
Shows the verbose version, including configuration information compiled
@@ -775,6 +871,11 @@ Read the filename as a Verilog library. Any modules in the file may be
used to resolve cell instantiations in the top level module, else ignored.
Note -v is fairly standard across Verilog tools.
=item -Wall
Enable all warnings, including code style warnings that are normally
disabled by default.
=item -Werror-I<message>
Convert the specified warning message into a error message. This is
@@ -783,11 +884,11 @@ example C<-Werror-NOUNOPTFLAT>.
=item -Wfuture-I<message>
Suppress unknown Verilator comments or warning messages with the given
message code. This is used to allow code written with pragmas for a later
version of Verilator to run under a older version; add -Wfuture- arguments
for each message code or comment that the new version supports which the
older version does not support.
Rarely needed. Suppress unknown Verilator comments or warning messages
with the given message code. This is used to allow code written with
pragmas for a later version of Verilator to run under a older version; add
-Wfuture- arguments for each message code or comment that the new version
supports which the older version does not support.
=item -Wno-I<message>
@@ -795,19 +896,49 @@ Disable the specified warning message.
=item -Wno-lint
Disable all lint related warning messages. This is equivalent to
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEWITHX
-Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-UNDRIVEN -Wno-UNSIGNED
-Wno-UNUSED -Wno-VARHIDDEN -Wno-WIDTH".
Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
-Wno-CASEWITHX -Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-SYNCASYNCNET
-Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for
Wno-style.
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
received from third parties.
=item -Wno-style
Disable all code style related warning messages (note by default they are
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
-Wno-VARHIDDEN".
=item -Wno-fatal
When warnings are detected, print them, but do not exit the simulator.
Having warning messages in builds is sloppy. It is strongly recommended
you cleanup your code, use inline lint_off, or use -Wno-... flags rather
than using this option.
=item -Wwarn-I<message>
Enables the specified warning message.
=item -Wwarn-lint
Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED
-Wwarn-WIDTH".
=item -Wwarn-style
Enable all code style related warning messages. This is equivalent to
"-Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH -Wwarn-SYNCASYNCNET
-Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
=item -x-assign 0
=item -x-assign 1
@@ -850,7 +981,7 @@ We'll compile this example into C++.
cat <<EOF >our.v
module our;
initial begin \$display("Hello World"); \$finish; end
initial begin $display("Hello World"); $finish; end
endmodule
EOF
@@ -865,10 +996,15 @@ We'll compile this example into C++.
}
EOF
Now we run Verilator on our little example.
If you installed Verilator from sources, or a tarball, but not as part of
your operating system (as an RPM), first you need to point to the kit:
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
$VERILATOR_ROOT/bin/verilator --cc our.v --exe sim_main.cpp
export PATH=$VERILATOR_ROOT/bin:$PATH
Now we run Verilator on our little example.
verilator -Wall --cc our.v --exe sim_main.cpp
We can see the source code under the "obj_dir" directory. See the FILES
section below for descriptions of some of the files that were created.
@@ -878,7 +1014,7 @@ section below for descriptions of some of the files that were created.
We then can compile it
cd obj_dir
make -f Vour.mk Vour
make -j -f Vour.mk Vour
(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
@@ -910,7 +1046,7 @@ This is an example similar to the above, but using SystemPerl.
module our (clk);
input clk; // Clock is required to get initial activation
always @ (posedge clk)
begin \$display("Hello World"); \$finish; end
begin $display("Hello World"); $finish; end
endmodule
EOF
@@ -927,10 +1063,15 @@ This is an example similar to the above, but using SystemPerl.
}
EOF
Now we run Verilator on our little example.
If you installed Verilator from sources, or a tarball, but not as part of
your operating system (as an RPM), first you need to point to the kit:
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
$VERILATOR_ROOT/bin/verilator --sp our.v
export PATH=$VERILATOR_ROOT/bin:$PATH
Now we run Verilator on our little example.
verilator -Wall --sp our.v
Then we convert the SystemPerl output to SystemC.
@@ -944,9 +1085,8 @@ Verilator by replacing the verilator --sp flag in the previous step with
We then can compile it
make -f Vour.mk Vour__ALL.a
make -f Vour.mk ../sc_main.o
make -f Vour.mk verilated.o
make -j -f Vour.mk Vour__ALL.a
make -j -f Vour.mk ../sc_main.o verilated.o
And link with SystemC. Note your path to the libraries may vary,
depending on the operating system.
@@ -1142,7 +1282,8 @@ for debugging and selecting between multiple operating system builds.
Specifies the directory containing the distribution kit. This is used to
find the executable, Perl library, and include files. If not specified, it
will come from a default optionally specified at configure time (before
Verilator was compiled).
Verilator was compiled). It should not be specified if using a pre-compiled
Verilator RPM as the hardcoded value should be correct.
=back
@@ -1296,6 +1437,38 @@ The /*verilator sformat*/ indicates that this function accepts a $display
like format specifier followed by any number of arguments to satisfy the
format.
=head2 DPI Context Functions
Verilator supports IEEE DPI Context Functions. Context imports pass the
simulator context, including calling scope name, and filename and line
number to the C code. For example, in Verilog:
import "DPI-C" context function int dpic_line();
initial $display("This is line %d, again, line %d\n", `line, dpic_line());
This will call C++ code which may then use the svGet* functions to read
information, in this case the line number of the Verilog statement that
invoked the dpic_line function:
int dpic_line() {
// Get a scope: svScope scope = svGetScope();
const char* scopenamep = svGetNameFromScope(scope);
assert(scopenamep);
const char* filenamep = "";
int lineno = 0;
if (svGetCallerInfo(&filenamep, &lineno)) {
printf("dpic_line called from scope %s on line %d\n",
scopenamep, lineno);
return lineno;
} else {
return 0;
}
}
See the IEEE Standard for more information.
=head2 DPI Header Isolation
Verilator places the IEEE standard header files such as svdpi.h into a
@@ -1307,12 +1480,64 @@ svdpi.h and similar standard files with different contents, the vltstd
directory should not be included to prevent picking up incompatible
definitions.
=head2 Public Functions
=head2 Public Functions
Instead of DPI exporting, there's also Verilator public functions, which
are slightly faster, but less compatible.
=head1 VERIFICATION PROCEDURAL INTERFACE (VPI)
Verilator supports a very limited subset of the VPI. This subset allows
inspection, examination, value change callbacks, and depositing of values
to public signals only.
To access signals via the VPI, Verilator must be told exactly which signals
are to be accessed. This is done using the Verilator public pragmas
documented below.
Verilator has an important difference from an event based simulator; signal
values that are changed by the VPI will not immediately propagate their
values, instead the top level header file's eval() method must be called.
Normally this would be part of the normal evaluation (IE the next clock
edge), not as part of the value change. This makes the performance of VPI
routines extremely fast compared to event based simulators, but can confuse
some test-benches that expect immediate propagation.
Note the VPI by it's specified implementation will always be much slower
than accessing the Verilator values by direct reference
(structure->module->signame), as the VPI accessors perform lookup in
functions at runtime requiring at best hundreds of instructions, while the
direct references are evaluated by the compiler and result in only a couple
of instructions.
=head2 VPI Example
In the below example, we have readme marked read-only, and writeme which if
written from outside the model will have the same semantics as if it
changed on the specified clock edge.
module t;
reg readme /*verilator public_flat_rd*/;
reg writeme /*verilator public_flat_rw @(posedge clk) */;
endmodule
There are many online tutorials and books on the VPI, but an example that
accesses the above would be:
void read_and_check() {
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
if (!vh1) { error... }
const char* name = vpi_get_str(vpiName, vh1);
printf("Module name: %s\n"); // Prints "readme"
s_vpi_value v;
v.format = vpiIntVal;
vpi_get_value(vh1, &v);
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
}
=head1 CROSS COMPILATION
Verilator supports cross-compiling Verilated code. This is generally used
@@ -1390,20 +1615,25 @@ Verilator configuration commands.
=item coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
Disable coverage for the specified filename (or all files if ommitted) and
range of line numbers (or all lines if ommitted). Often used to ignore an
entire module for coverage analysis purposes.
Disable coverage for the specified filename (or wildcard with '*' or '?',
or all files if omitted) and range of line numbers (or all lines if
omitted). Often used to ignore an entire module for coverage analysis
purposes.
=item lint_off -msg <message> [-file "<filename>" [-lines <line> [ - <line>]]]
=item lint_off [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
Disables the specified lint warning in the specified filename (or all files
if ommitted) and range of line numbers (or all lines if ommitted).
Disables the specified lint warning, in the specified filename (or wildcard
with '*' or '?', or all files if omitted) and range of line numbers (or all
lines if omitted).
If the -msg is omitted, all lint warnings are disabled. This will override
all later lint warning enables for the specified region.
=item tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
Disable waveform tracing for all future signals declared in the specified
filename (or all files if ommitted) and range of line numbers (or all lines
if ommitted).
filename (or wildcard with '*' or '?', or all files if omitted) and range
of line numbers (or all lines if omitted).
=back
@@ -1630,7 +1860,8 @@ Used after a signal declaration to indicate the signal is used to gate a
clock, and the user takes responsibility for insuring there are no races
related to it. (Typically by adding a latch, and running static timing
analysis.) This will cause the clock gate to be ignored in the scheduling
algorithm, improving performance.
algorithm, improving performance. It's also a good idea to enable the
IMPERFECTSCH warning, to insure all clock enables are properly recognized.
=item /*verilator coverage_block_off*/
@@ -1644,7 +1875,7 @@ Often used to ignore an entire module for coverage analysis purposes.
=item /*verilator coverage_on*/
Specifies that following lines of code should have coverage reenabled (if
Specifies that following lines of code should have coverage re-enabled (if
appropriate --coverage flags are passed) after being disabled earlier with
/*verilator coverage_off*/.
@@ -1770,6 +2001,18 @@ signal. This will not declare this module public, which means the name of
the signal or path to it may change based upon the module inlining which
takes place.
=item /*verilator public_flat_rd*/ (variable)
Used after a input, output, register, or wire declaration to indicate the
signal should be declared public_flat (see above), but read-only.
=item /*verilator public_flat_rw @(<edge_list>) */ (variable)
Used after a input, output, register, or wire declaration to indicate the
signal should be declared public_flat_rd (see above), and also writable,
where writes should be considered to have the timing specified by the given
sensitivity edge list.
=item /*verilator public_module*/
Used after a module statement to indicate the module should not be inlined
@@ -1819,14 +2062,17 @@ program will find for you.
Verilator supports only the Synthesis subset with a few minor additions
such as $stop, $finish and $display. That is, you cannot use hierarchical
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;
will recompute y when there is a change in x or a change in z, which is
what Design Compiler will synthesize. A compliant simulator would only
calculate y if x changes. (Use verilog-mode's /*AS*/ or Verilog 2001's
always @* to prevent these issues.)
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
what Design Compiler will synthesize.) A compliant simulator would only
calculate y if x changes. Use verilog-mode's /*AS*/ or Verilog 2001's
always @* to reduce missing activity items. Avoid putting $displays in
combo blocks, as they may print multiple times when not desired, even on
compliant simulators as event ordering is not specified.
=head2 Dotted cross-hierarchy references
@@ -1893,7 +2139,7 @@ of the form:
inout driver;
wire driver = (enable) ? output_value : 1'bz;
Will be converted to
input driver__in; // Value being driven in from "external" drivers
@@ -1996,6 +2242,17 @@ supply1, task, time, tri, typedef, var, vectored, while, wire, xnor, xor
Generally supported.
=item ++, -- operators
Increment/decrement can only be used as standalone statements or in for
loops. They cannot be used as side effect operators inside more complicate
expressions ("a = b++;").
=item cast operator
Casting is supported only between simple scalar types, signed and unsigned,
not arrays nor structs.
=item chandle
Treated as a "longint"; does not yet warn about operations that are
@@ -2143,6 +2400,20 @@ inside a public task.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item BLKSEQ
This indicates that a blocking assignment (=) is used in a sequential
block. Generally non-blocking/delayed assignments (<=) are used in
sequential blocks, to avoid the possibility of simulator races. It can be
reasonable to do this if the generated signal is used ONLY later in the
same block, however this style is generally discouraged as it is error
prone.
always @ (posedge clk) foo = ...
Disabled by default as this is a code style warning; it will simulate
correctly.
=item BLKLOOPINIT
This indicates that the initialization of an array needs to use non-delayed
@@ -2227,6 +2498,26 @@ L<http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf>
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item DECLFILENAME
Warns that a module or other declaration's name doesn't match the filename
with path and extension stripped that it is declared in. The filename a
modules/interfaces/programs is declared in should match the name of the
module etc. so that -y directory searching will work. This warning is
printed for only the first mismatching module in any given file, and -v
library files are ignored.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item DEFPARAM
Warns that the "defparam" statement was deprecated in Verilog 2001 and all
designs should now be using the #(...) format to specify parameters.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item GENCLK
Warns that the specified signal is generated, but is also being used as a
@@ -2240,6 +2531,16 @@ additional ones.)
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item IFDEPTH
Warns that if/if else statements have exceeded the depth specified with
--if-depth, as they are likely to result in slow priority encoders. Unique
and priority if statements are ignored. Solutions include changing the
code to a case statement, or a SystemVerilog 'unique if' or 'priority if'.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item IMPERFECTSCH
Warns that the scheduling of the model is not absolutely perfect, and some
@@ -2268,6 +2569,17 @@ Verilator cannot schedule these variables correctly.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item INCABSPATH
Warns that an `include filename specifies an absolute path. This means the
code will not work on any other system with a different file system layout.
Instead of using absolute paths, relative paths (preferably without any
directory specified whatever) should be used, and +include used on the
command line to specify the top include source directory.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item LITENDIAN
Warns that a vector is declared with little endian bit numbering
@@ -2339,6 +2651,18 @@ name would result in odd C compiler errors. You may disable this error
message as you would disable warnings, but the symbol will be renamed by
Verilator to avoid the conflict.
=item SYNCASYNCNET
Warns that the specified net is used in at least two different always
statements with posedge/negedges (i.e. a flop). One usage has the signal
in the sensitivity list and body, probably as a async reset, and the other
usage has the signal only in the body, probably as a sync reset. Mixing
sync and async resets is usually a mistake. The warning may be disabled
with a lint_off pragma around the net, or either flopped block.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item TASKNSVAR
Error when a call to a task or function has a output from that task tied to
@@ -2364,9 +2688,11 @@ cases would result in simulator mismatches.
=item UNDRIVEN
Warns that the specified signal is never sourced.
Warns that the specified signal is never sourced. Verilator is fairly
liberal in the usage calculations; making a signal public, or loading only
a single array element marks the entire signal as driven.
Ignoring this warning will only suppress the lint check, it will simulate
Disabled by default as this is a code style warning; it will simulate
correctly.
=item UNOPT
@@ -2449,12 +2775,31 @@ correctly.
=item UNUSED
Warns that the specified signal is never sinked. This is a future message,
currently Verilator will not produce this warning.
Warns that the specified signal is never sinked. Verilator is fairly
liberal in the usage calculations; making a signal public, a signal
matching --unused-regexp ("*unused*") or accessing only a single array
element marks the entire signal as used.
Ignoring this warning will only suppress the lint check, it will simulate
Disabled by default as this is a code style warning; it will simulate
correctly.
A recommended style for unused nets is to put at the bottom of a file code
similar to the following:
wire _unused_ok = &{1'b0,
sig_not_used_a,
sig_not_used_yet_b, // To be fixed
1'b0};
The reduction AND and constant zeros mean the net will always be zero, so
won't use simulation time. The redundant leading and trailing zeros avoid
syntax errors if there are no signals between them. The magic name
"unused" (-unused-regexp) is recognized by Verilator and suppresses
warnings; if using other lint tools, either teach to tool to ignore signals
with "unused" in the name, or put the appropriate lint_off around the wire.
Having unused signals in one place makes it easy to find what is unused,
and reduces the number of lint_off pragmas, reducing bugs.
=item VARHIDDEN
Warns that a task, function, or begin/end block is declaring a variable by
@@ -2462,7 +2807,7 @@ the same name as a variable in the upper level module or begin/end block
(thus hiding the upper variable from being able to be used.) Rename the
variable to avoid confusion when reading the code.
Ignoring this warning will only suppress the lint check, it will simulate
Disabled by default as this is a code style warning; it will simulate
correctly.
=item WIDTH
@@ -2597,8 +2942,8 @@ allows you to modify Verilator for internal use without distributing the
modified version. But please contribute back to the community!
One limit is that you cannot under either license release a commercial
simulation product incorporating Verilator without making the source code
available.
Verilog simulation product incorporating Verilator without making the
source code available.
=item Why is Verilation so slow?
@@ -2620,8 +2965,10 @@ in your main loop call "trace_object->dump(time)" every time step, and
finally call "trace_object->close()". For an example, see below and the
test_c/sim_main.cpp file of the distribution.
You also need to compile verilated_vcd_c.cpp and add it to your link. This
is done for you if using the Verilator --exe flag.
You also need to compile verilated_vcd_c.cpp and add it to your link,
preferably by adding the dependencies in $(VK_GLOBAL_OBJS) to your
Makefile's link rule. This is done for you if using the Verilator --exe
flag.
Note you can also call ->trace on multiple Verilated objects with the same
trace file if you want all data to land in the same output file.
@@ -2658,8 +3005,10 @@ Alternatively you may use the C++ trace mechanism described in the previous
question, however the timescale and timeprecision will not inherited from
your SystemC settings.
You also need to compile verilated_vcd_sc.cpp and add it to your link.
This is done for you if using the Verilator --exe flag.
You also need to compile verilated_vcd_sc.cpp and verilated_vcd_c.cpp and
add them to your link, preferably by adding the dependencies in
$(VK_GLOBAL_OBJS) to your Makefile's link rule. This is done for you if
using the Verilator --exe flag.
Note you can also call ->trace on multiple Verilated objects with the same
trace file if you want all data to land in the same output file.
@@ -2765,15 +3114,17 @@ simulator knows the current time. See the "CONNECTING TO C++" examples.
=item Why do I get "undefined reference to `VL_RAND_RESET_I' or `Verilated::...'"?
You need to link your compiled Verilated code against the verilated.cpp
file found in the include directory of the Verilator kit.
file found in the include directory of the Verilator kit. This is one
target in the $(VK_GLOBAL_OBJS) make variable, which should be part of your
Makefile's link rule.
=item Is the PLI supported?
No, but the DPI is.
Only somewhat. More specifically, the common PLI-ish calls $display,
$finish, $stop, $time, $write are converted to C++ equivalents. You can
also use the "import DPI" SystemVerilog feature to call C code (see the
chapter above). There is also limited VPI access to public signals.
More specifically, the common PLI-ish calls $display, $finish, $stop,
$time, $write are converted to C++ equivalents. You can also use the
"import DPI" SystemVerilog feature to call C code (see the chapter above).
If you want something more complex, since Verilator emits standard C++
code, you can simply write your own C++ routines that can access and modify
signal values without needing any PLI interface code, and call it with
@@ -2972,7 +3323,7 @@ Thanks all.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
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
License Version 2.0.
+1 -1
View File
@@ -177,7 +177,7 @@ Do not show differences in line numbering.
The latest version is available from L<http://www.veripool.org/verilator>.
Copyright 2005-2010 by Wilson Snyder. This package is free software; you can
Copyright 2005-2011 by Wilson Snyder. This package 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.
+1 -1
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
# DESCRIPTION: Print include statements for each ARGV
#
# Copyright 2003-2010 by Wilson Snyder. This package is free software; you can
# Copyright 2003-2011 by Wilson Snyder. This package 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.
######################################################################
+1 -1
View File
@@ -208,7 +208,7 @@ Displays this message and program version and exits.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2007-2010 by Wilson Snyder. Verilator is free software; you can
Copyright 2007-2011 by Wilson Snyder. Verilator 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.
+1 -1
View File
@@ -1,6 +1,6 @@
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
dnl
dnl Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
dnl Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
dnl redistribute it and/or modify it under the terms of either the GNU Lesser
dnl General Public License Version 3 or the Perl Artistic License Version 2.0.
+102 -11
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -33,8 +33,12 @@
//===========================================================================
// Global variables
// Slow path variables
int Verilated::s_randReset = 0;
int Verilated::s_debug = 1;
VerilatedVoidCb Verilated::s_flushCb = NULL;
// Keep below together in one cache line
int Verilated::s_debug = 0;
bool Verilated::s_calcUnusedSigs = false;
bool Verilated::s_gotFinish = false;
bool Verilated::s_assertOn = true;
@@ -53,6 +57,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) {
VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum);
if (Verilated::gotFinish()) {
VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum);
Verilated::flushCall();
exit(0);
}
Verilated::gotFinish(true);
@@ -62,6 +67,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) {
#ifndef VL_USER_STOP // Define this to override this function
void vl_stop (const char* filename, int linenum, const char* hier) {
Verilated::gotFinish(true);
Verilated::flushCall();
vl_fatal (filename,linenum,hier,"Verilog $stop");
}
#endif
@@ -71,6 +77,7 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
if (0 && hier) {}
Verilated::gotFinish(true);
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
Verilated::flushCall();
abort();
}
#endif
@@ -826,7 +833,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
} else {
needinc = true;
//printf(" Value width=%d @%x = %c\n", width, addr, c);
if (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");
} else {
int entry = addr - array_lsb;
@@ -854,7 +861,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
datap[0] |= value;
}
if (value>=(1<<shift)) {
if (VL_UNLIKELY(value>=(1<<shift))) {
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
}
}
@@ -871,7 +878,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
// Final checks
fclose(fp);
if (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");
}
}
@@ -920,8 +927,12 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
const char* vl_mc_scan_plusargs(const char* prefixp) {
string match = VerilatedImp::argPlusMatch(prefixp);
if (match == "") return 0;
else return match.c_str()+strlen(prefixp)+1; // +1 to skip the "+"
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match == "") return NULL;
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
VL_VALUE_STRING_MAX_WIDTH);
outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
return outstr;
}
//===========================================================================
@@ -967,6 +978,15 @@ const char* Verilated::catName(const char* n1, const char* n2) {
return strp;
}
void Verilated::flushCb(VerilatedVoidCb cb) {
if (s_flushCb == cb) {} // Ok - don't duplicate
else if (!s_flushCb) { s_flushCb=cb; }
else {
// Someday we may allow multiple callbacks ala atexit(), but until then
vl_fatal("unknown",0,"", "Verilated::flushCb called twice with different callbacks");
}
}
void Verilated::commandArgs(int argc, const char** argv) {
VerilatedImp::commandArgs(argc,argv);
}
@@ -975,6 +995,10 @@ void Verilated::scopesDump() {
VerilatedImp::scopesDump();
}
const VerilatedScope* Verilated::scopeFind(const char* namep) {
return VerilatedImp::scopeFind(namep);
}
int Verilated::exportFuncNum(const char* namep) {
return VerilatedImp::exportFind(namep);
}
@@ -990,6 +1014,23 @@ VerilatedModule::~VerilatedModule() {
if (m_namep) free((void*)m_namep); m_namep=NULL;
}
//======================================================================
// VerilatedVar:: Methods
vluint32_t VerilatedVar::entSize() const {
vluint32_t size = 1;
switch (vltype()) {
case VLVT_PTR: size=sizeof(void*); break;
case VLVT_UINT8: size=sizeof(CData); break;
case VLVT_UINT16: size=sizeof(SData); break;
case VLVT_UINT32: size=sizeof(IData); break;
case VLVT_UINT64: size=sizeof(QData); break;
case VLVT_WDATA: size=VL_WORDS_I(range().bits())*sizeof(IData); break;
default: size=0; break;
}
return size;
}
//======================================================================
// VerilatedScope:: Methods
@@ -997,12 +1038,14 @@ VerilatedScope::VerilatedScope() {
m_callbacksp = NULL;
m_namep = NULL;
m_funcnumMax = 0;
m_varsp = NULL;
}
VerilatedScope::~VerilatedScope() {
VerilatedImp::scopeErase(this);
if (m_namep) { delete [] m_namep; m_namep = NULL; }
if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; }
if (m_varsp) { delete m_varsp; m_varsp = NULL; }
m_funcnumMax = 0; // Force callback table to empty
}
@@ -1027,10 +1070,10 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
// Alternative is to dynamically stretch the array, which is more code, and slower.
if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
} else {
if (funcnum >= m_funcnumMax) {
if (VL_UNLIKELY(funcnum >= m_funcnumMax)) {
vl_fatal(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum");
}
if (!m_callbacksp) { // First allocation
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
m_callbacksp = new void* [m_funcnumMax];
memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
}
@@ -1038,6 +1081,47 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
}
}
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
VerilatedVarType vltype, int vlflags, int dims, ...) {
// Grab dimensions
// In the future we may just create a large table at emit time and statically construct from that.
if (!finalize) return;
if (!m_varsp) m_varsp = new VerilatedVarNameMap();
VerilatedVar var (namep, datap, vltype, (VerilatedVarFlags)vlflags, dims);
va_list ap;
va_start(ap,dims);
for (int i=0; i<dims; ++i) {
int msb = va_arg(ap,int);
int lsb = va_arg(ap,int);
if (i==0) {
var.m_range.m_lhs = msb;
var.m_range.m_rhs = lsb;
} else if (i==1) {
var.m_array.m_lhs = msb;
var.m_array.m_rhs = lsb;
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
vl_fatal(__FILE__,__LINE__,"",(string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
}
}
va_end(ap);
m_varsp->insert(make_pair(namep,var));
}
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
if (VL_LIKELY(m_varsp)) {
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
if (VL_LIKELY(it != m_varsp->end())) {
return &(it->second);
}
}
return NULL;
}
void* VerilatedScope::exportFindNullError(int funcnum) const {
// Slowpath - Called only when find has failed
string msg = (string("Testbench C called '")
@@ -1058,10 +1142,17 @@ void* VerilatedScope::exportFindError(int funcnum) const {
}
void VerilatedScope::scopeDump() const {
VL_PRINTF(" SCOPE: %s\n", name());
VL_PRINTF(" SCOPE %p: %s\n", this, name());
for (int i=0; i<m_funcnumMax; i++) {
if (m_callbacksp && m_callbacksp[i]) {
VL_PRINTF(" DPI-EXPORT: %s\n", VerilatedImp::exportName(i));
VL_PRINTF(" DPI-EXPORT %p: %s\n",
m_callbacksp[i], VerilatedImp::exportName(i));
}
}
if (varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp()->begin();
it != varsp()->end(); ++it) {
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
}
}
}
+55 -11
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -62,11 +62,37 @@ typedef vluint32_t WData; ///< Verilated pack data, >64 bits, as an array
typedef const WData* WDataInP; ///< Array input to a function
typedef WData* WDataOutP; ///< Array output from a function
typedef void (*VerilatedVoidCb)(void);
class SpTraceVcd;
class SpTraceVcdCFile;
class VerilatedVar;
class VerilatedVarNameMap;
class VerilatedVcd;
class VerilatedVcdC;
enum VerilatedVarType {
VLVT_UNKNOWN=0,
VLVT_PTR, // Pointer to something
VLVT_UINT8, // AKA CData
VLVT_UINT16, // AKA SData
VLVT_UINT32, // AKA IData
VLVT_UINT64, // AKA QData
VLVT_WDATA, // AKA WData
VLVT_STRING // C++ string
};
enum VerilatedVarFlags {
VLVD_IN=1, // == vpiInput
VLVD_OUT=2, // == vpiOutput
VLVD_INOUT=3, // == vpiInOut
VLVD_NODIR=5, // == vpiNoDirection
VLVF_MASK_DIR=7, // Bit mask for above directions
// Flags
VLVF_PUB_RD=(1<<8), // Public readable
VLVF_PUB_RW=(1<<9) // Public writable
};
//=========================================================================
/// Base class for all Verilated module classes
@@ -136,6 +162,9 @@ public:
#ifndef VL_PRINTF
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired
#endif
#ifndef VL_VPRINTF
# define VL_VPRINTF vprintf ///< Print ala vprintf; may redefine if desired
#endif
//===========================================================================
/// Verilator symbol table base class
@@ -149,19 +178,25 @@ class VerilatedSyms {
class VerilatedScope {
// Fastpath:
VerilatedSyms* m_symsp; ///< Symbol table
void** m_callbacksp; ///< Callback table pointer (Fastpath)
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
VerilatedSyms* m_symsp; ///< Symbol table
void** m_callbacksp; ///< Callback table pointer (Fastpath)
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
// 4 bytes padding (on -m64), for rent.
const char* m_namep; ///< Scope name (Slowpath)
VerilatedVarNameMap* m_varsp; ///< Variable map
const char* m_namep; ///< Scope name (Slowpath)
public: // But internals only - called from VerilatedModule's
VerilatedScope();
~VerilatedScope();
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp);
void exportInsert(int finalize, const char* namep, void* cb);
void varInsert(int finalize, const char* namep, void* datap,
VerilatedVarType vltype, int vlflags, int dims, ...);
// ACCESSORS
const char* name() const { return m_namep; }
inline VerilatedSyms* symsp() const { return m_symsp; }
VerilatedVar* varFind(const char* namep) const;
VerilatedVarNameMap* varsp() const { return m_varsp; }
void* exportFindError(int funcnum) const;
void* exportFindNullError(int funcnum) const;
void scopeDump() const;
@@ -182,7 +217,11 @@ public: // But internals only - called from VerilatedModule's
struct Verilated {
// MEMBERS
private:
// Slow path variables
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
static VerilatedVoidCb s_flushCb; ///< Flush callback function
// Fast path
static int s_debug; ///< See accessors... only when VL_DEBUG set
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
static bool s_gotFinish; ///< A $finish statement executed
@@ -224,6 +263,9 @@ public:
/// Enable/disable assertions
static void assertOn(bool flag) { s_assertOn=flag; }
static bool assertOn() { return s_assertOn; }
/// Flush callback for VCD waves
static void flushCb(VerilatedVoidCb cb);
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
static void commandArgs(int argc, const char** argv);
@@ -237,6 +279,8 @@ public:
// METHODS - INTERNAL USE ONLY
// Internal: Create a new module name by concatenating two strings
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
// Internal: Find scope
static const VerilatedScope* scopeFind(const char* namep);
// Internal: Get and set DPI context
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
@@ -347,6 +391,9 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
//=========================================================================
// Pli macros
#ifndef VL_TIME_PRECISION
# define VL_TIME_PRECISION -12 ///< Timescale units only for for VPI return - picoseconds
#endif
#ifndef VL_TIME_MULTIPLIER
# define VL_TIME_MULTIPLIER 1
#endif
@@ -898,14 +945,11 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
return(owp);
}
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround
#if 1 //defined(__GNUC__) && __GNUC__ < 3
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
// we can't just
//# define VL_UNARYMIN_I(data) (-(data))
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
#else
# define VL_UNARYMIN_I(IData data) (-(data))
# define VL_UNARYMIN_Q(QData data) (-(data))
#endif
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
QData carry = 0;
+8 -1
View File
@@ -2,7 +2,7 @@
######################################################################
# DESCRIPTION: Makefile commands for all verilated target files
#
# Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
# Copyright 2003-2011 by Wilson Snyder. Verilator 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.
######################################################################
@@ -19,6 +19,13 @@ RANLIB = ranlib
SP_PREPROC = sp_preproc
SP_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
######################################################################
# Make checks
ifneq ($(words $(CURDIR)),1)
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
endif
######################################################################
# C Preprocessor flags
+1 -1
View File
@@ -5,7 +5,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2011 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.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2011 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.
+3 -9
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2011 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.
@@ -31,6 +31,7 @@
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_heavy.h"
#include "verilated_syms.h"
#include <map>
#include <vector>
@@ -41,13 +42,6 @@ class VerilatedScope;
//======================================================================
// Types
struct VerilatedCStrCmp {
// For ordering maps keyed by const char*'s
bool operator() (const char *a, const char *b) const {
return std::strcmp(a, b) < 0;
}
};
class VerilatedImp {
// Whole class is internal use only - Global information shared between verilated*.cpp files.
@@ -55,7 +49,7 @@ class VerilatedImp {
typedef vector<string> ArgVec;
typedef map<pair<const void*,void*>,void*> UserMap;
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
typedef map<const char*, int> ExportNameMap;
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
// MEMBERS
static VerilatedImp s_s; ///< Static Singleton; One and only static this
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2011 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.
+100
View File
@@ -0,0 +1,100 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2011 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.
//
//*************************************************************************
///
/// \file
/// \brief Verilator: Include to allow symbol inspection
///
/// This file is for inclusion by files that need to inspect
/// the symbol table. It is not included in verilated.h
/// as it requires some heavyweight C++ classes.
///
/// Code available from: http://www.veripool.org/verilator
///
//*************************************************************************
#ifndef _VERILATED_SYMS_H_
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
#include "verilated_heavy.h"
#include <map>
//======================================================================
// Types
struct VerilatedCStrCmp {
/// Ordering maps keyed by const char*'s
bool operator() (const char *a, const char *b) const {
return std::strcmp(a, b) < 0;
}
};
//===========================================================================
/// Verilator range
class VerilatedRange {
int m_lhs;
int m_rhs;
protected:
friend class VerilatedVar;
friend class VerilatedScope;
VerilatedRange() : m_lhs(0), m_rhs(0) {}
void sets(int lhs, int rhs) { m_lhs=lhs; m_rhs=rhs; }
public:
~VerilatedRange() {}
int lhs() const { return m_lhs; }
int rhs() const { return m_rhs; }
int bits() const { return (VL_LIKELY(m_lhs>=m_rhs)?(m_lhs-m_rhs+1):(m_rhs-m_lhs+1)); }
};
//===========================================================================
/// Verilator variable
class VerilatedVar {
void* m_datap; // Location of data
VerilatedVarType m_vltype; // Data type
VerilatedVarFlags m_vlflags; // Direction
VerilatedRange m_range; // First range
VerilatedRange m_array; // Array
int m_dims; // Dimensions
const char* m_namep; // Name - slowpath
protected:
friend class VerilatedScope;
VerilatedVar(const char* namep, void* datap,
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
: m_datap(datap), m_vltype(vltype), m_vlflags(vlflags), m_dims(dims), m_namep(namep) {}
public:
~VerilatedVar() {}
void* datap() const { return m_datap; }
VerilatedVarType vltype() const { return m_vltype; }
VerilatedVarFlags vldir() const { return (VerilatedVarFlags)((int)m_vlflags & VLVF_MASK_DIR); }
vluint32_t entSize() const;
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
const VerilatedRange& range() const { return m_range; }
const VerilatedRange& array() const { return m_array; }
const char* name() const { return m_namep; }
int dims() const { return m_dims; }
};
//======================================================================
/// Types
struct VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
VerilatedVarNameMap() {}
~VerilatedVarNameMap() {}
};
#endif // Guard
+45 -13
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
// Copyright 2001-2011 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.
//
@@ -88,6 +88,11 @@ void VerilatedVcd::open (const char* filename) {
m_filename = filename;
s_vcdVecp.push_back(this);
// SPDIFF_OFF
// Set callback so an early exit will flush us
Verilated::flushCb(&flush_all);
// SPDIFF_ON
openNext (m_rolloverMB!=0);
if (!isOpen()) return;
@@ -149,6 +154,39 @@ void VerilatedVcd::openNext (bool incFilename) {
m_wroteBytes = 0;
}
void VerilatedVcd::makeNameMap() {
// Take signal information from each module and build m_namemapp
m_namemapp = new NameMap;
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
VerilatedVcdCallInfo *cip = m_callbacks[ent];
cip->m_code = nextCode();
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
}
// Though not speced, it's illegal to generate a vcd with signals
// not under any module - it crashes at least two viewers.
// If no scope was specified, prefix everything with a "top"
// This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str();
if (hiername[0] == '\t') nullScope=true;
}
if (nullScope) {
NameMap* newmapp = new NameMap;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const string& hiername = it->first;
const string& decl = it->second;
string newname = string("top");
if (hiername[0] != '\t') newname += ' ';
newname += hiername;
newmapp->insert(make_pair(newname,decl));
}
delete m_namemapp; m_namemapp=NULL;
m_namemapp = newmapp;
}
}
VerilatedVcd::~VerilatedVcd() {
close();
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
@@ -196,7 +234,7 @@ void VerilatedVcd::printStr (const char* str) {
void VerilatedVcd::printQuad (vluint64_t n) {
char buf [100];
sprintf(buf,"%" VL_PRI64 "u",(long long unsigned)n);
sprintf(buf,"%" VL_PRI64 "u", n);
printStr(buf);
}
@@ -222,10 +260,10 @@ void VerilatedVcd::bufferFlush () {
if (VL_UNLIKELY(!isOpen())) return;
char* wp = m_wrBufp;
while (1) {
size_t remaining = (m_writep - wp);
ssize_t remaining = (m_writep - wp);
if (remaining==0) break;
errno = 0;
int got = write (m_fd, wp, remaining);
ssize_t got = write (m_fd, wp, remaining);
if (got>0) {
wp += got;
m_wroteBytes += got;
@@ -309,13 +347,7 @@ void VerilatedVcd::dumpHeader () {
printStr(doubleToTimescale(m_timeRes).c_str());
printStr(" $end\n");
// Take signal information from each module and build m_namemapp
m_namemapp = new NameMap;
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
VerilatedVcdCallInfo *cip = m_callbacks[ent];
cip->m_code = nextCode();
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
}
makeNameMap();
// Signal header
assert (m_modDepth==0);
@@ -341,7 +373,7 @@ void VerilatedVcd::dumpHeader () {
// Skip common prefix, it must break at a space or tab
for (; *np && (*np == *lp); np++, lp++) {}
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; }
//cout <<"hier "<<hiername<<endl<<" lp "<<lp<<endl<<" np "<<np<<endl;
//printf("hier %s\n lp=%s\n np=%s\n",hiername,lp,np);
// Any extra spaces in last name are scope ups we need to do
bool first = true;
@@ -389,7 +421,7 @@ void VerilatedVcd::module (string name) {
}
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
int arraynum, bool tri, bool bussed, int msb, int lsb) {
int arraynum, bool tri, bool bussed, int msb, int lsb) {
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
+2 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
// Copyright 2001-2011 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.
//
@@ -99,6 +99,7 @@ private:
void closePrev();
void closeErr();
void openNext();
void makeNameMap();
void printIndent (int levelchange);
void printStr (const char* str);
void printQuad (vluint64_t n);
+1 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
// Copyright 2001-2011 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.
//
+1 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
// Copyright 2001-2011 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.
//
+33
View File
@@ -0,0 +1,33 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2011 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.
//
//=========================================================================
///
/// \file
/// \brief Verilator: VPI implementation code
///
/// This file must be compiled and linked against all objects
/// created from Verilator or called by Verilator that use the VPI.
///
/// Code available from: http://www.veripool.org/verilator
///
//=========================================================================
#include "verilated_vpi.h"
//======================================================================
VerilatedVpi VerilatedVpi::s_s; // Singleton
vluint8_t* VerilatedVpio::s_freeHead = NULL;
//======================================================================
+835
View File
@@ -0,0 +1,835 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2011 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.
//
//=========================================================================
///
/// \file
/// \brief Verilator: VPI implementation code
///
/// This file must be compiled and linked against all objects
/// created from Verilator or called by Verilator that use the VPI.
///
/// "//-" indicates features that are as yet unimplemented.
///
/// Code available from: http://www.veripool.org/verilator
///
//=========================================================================
#ifndef CHPI_VERILATED_VPI_H
#define CHPI_VERILATED_VPI_H 1
#include "verilated.h"
#include "verilated_syms.h"
//======================================================================
// From IEEE 1800-2009 annex K
#include "vltstd/vpi_user.h"
//======================================================================
// Internal macros
// Not supported yet
#define _VL_VPI_UNIMP() \
vl_fatal(__FILE__,__LINE__,"",Verilated::catName("Unsupported VPI function: ",VL_FUNC))
//======================================================================
// Implementation
#include <set>
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
// Base VPI handled object
class VerilatedVpio {
// MEM MANGLEMENT
static vluint8_t* s_freeHead;
public:
// CONSTRUCTORS
VerilatedVpio() {}
virtual ~VerilatedVpio() {}
inline static void* operator new(size_t size) {
// We new and delete tons of vpi structures, so keep them around
// To simplify our free list, we use a size large enough for all derived types
// We reserve word zero for the next pointer, as that's safer in case a
// dangling reference to the original remains around.
static size_t chunk = 96;
if (VL_UNLIKELY(size>chunk)) vl_fatal(__FILE__,__LINE__,"", "increase chunk");
if (VL_LIKELY(s_freeHead)) {
vluint8_t* newp = s_freeHead;
s_freeHead = *((vluint8_t**)newp);
return newp+8;
} else {
// +8: 8 bytes for next
vluint8_t* newp = (vluint8_t*)(::operator new(chunk+8));
return newp+8;
}
}
inline static void operator delete(void* obj, size_t size) {
vluint8_t* oldp = ((vluint8_t*)obj)-8;
*((void**)oldp) = s_freeHead;
s_freeHead = oldp;
}
// MEMBERS
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
inline vpiHandle castVpiHandle() { return (vpiHandle)(this); }
// ACCESSORS
virtual const char* name() { return "<null>"; }
virtual const char* fullname() { return "<null>"; }
virtual const char* defname() { return "<null>"; }
virtual vpiHandle dovpi_scan() { return 0; }
};
typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
class VerilatedVpioCb : public VerilatedVpio {
t_cb_data m_cbData;
QData m_time;
public:
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
vluint32_t reason() const { return m_cbData.reason; }
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
t_cb_data* cb_datap() { return &(m_cbData); }
QData time() const { return m_time; }
};
class VerilatedVpioConst : public VerilatedVpio {
vlsint32_t m_num;
public:
VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
virtual ~VerilatedVpioConst() {}
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
vlsint32_t num() const { return m_num; }
};
class VerilatedVpioRange : public VerilatedVpio {
vlsint32_t m_lhs; // Ranges can be signed
vlsint32_t m_rhs;
bool m_iteration;
public:
VerilatedVpioRange(vlsint32_t lhs, vlsint32_t rhs) : m_lhs(lhs), m_rhs(rhs), m_iteration(0) {}
virtual ~VerilatedVpioRange() {}
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
vlsint32_t lhs() const { return m_lhs; }
vlsint32_t rhs() const { return m_rhs; }
int iteration() const { return m_iteration; }
void iterationInc() { ++m_iteration; }
virtual vpiHandle dovpi_scan() {
if (!iteration()) {
VerilatedVpioRange* nextp = new VerilatedVpioRange(*this);
nextp->iterationInc();
return ((nextp)->castVpiHandle());
} else {
return 0; // End of list - only one deep
}
}
};
class VerilatedVpioScope : public VerilatedVpio {
const VerilatedScope* m_scopep;
public:
VerilatedVpioScope(const VerilatedScope* scopep)
: m_scopep(scopep) {}
virtual ~VerilatedVpioScope() {}
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
const VerilatedScope* scopep() const { return m_scopep; }
virtual const char* name() { return m_scopep->name(); }
virtual const char* fullname() { return m_scopep->name(); }
};
class VerilatedVpioVar : public VerilatedVpio {
const VerilatedVar* m_varp;
const VerilatedScope* m_scopep;
vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange
vluint32_t m_mask; // memoized variable mask
vluint32_t m_entSize; // memoized variable size
protected:
void* m_varDatap; // varp()->datap() adjusted for array entries
vlsint32_t m_index;
public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp(varp), m_scopep(scopep), m_index(0) {
m_prevDatap = NULL;
m_mask = VL_MASK_I(varp->range().bits());
m_entSize = varp->entSize();
m_varDatap = varp->datap();
}
virtual ~VerilatedVpioVar() {
if (m_prevDatap) { delete [] m_prevDatap; m_prevDatap = NULL; }
}
static inline VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVar*>((VerilatedVpio*)h); }
const VerilatedVar* varp() const { return m_varp; }
const VerilatedScope* scopep() const { return m_scopep; }
vluint32_t mask() const { return m_mask; }
vluint32_t entSize() const { return m_entSize; }
virtual const char* name() { return m_varp->name(); }
virtual const char* fullname() {
static VL_THREAD string out;
out = string(m_scopep->name())+"."+name();
return out.c_str();
}
void* prevDatap() const { return m_prevDatap; }
void* varDatap() const { return m_varDatap; }
void createPrevDatap() {
if (VL_UNLIKELY(!m_prevDatap)) {
m_prevDatap = new vluint8_t [entSize()];
memcpy(prevDatap(), varp()->datap(), entSize());
}
}
};
class VerilatedVpioVarIndex : public VerilatedVpioVar {
public:
VerilatedVpioVarIndex(const VerilatedVar* varp, const VerilatedScope* scopep,
vlsint32_t index, int offset)
: VerilatedVpioVar(varp, scopep) {
m_index = index;
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
}
virtual ~VerilatedVpioVarIndex() {}
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
virtual const char* fullname() {
static VL_THREAD string out;
char num[20]; sprintf(num,"%d",m_index);
out = string(scopep()->name())+"."+name()+"["+num+"]";
return out.c_str();
}
};
class VerilatedVpioVarIter : public VerilatedVpio {
const VerilatedScope* m_scopep;
VerilatedVarNameMap::iterator m_it;
bool m_started;
public:
VerilatedVpioVarIter(const VerilatedScope* scopep)
: m_scopep(scopep), m_started(false) { }
virtual ~VerilatedVpioVarIter() {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) {
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
else ++m_it;
if (m_it == m_scopep->varsp()->end()) return 0;
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
->castVpiHandle());
} else {
return 0; // End of list - only one deep
}
}
};
//======================================================================
struct VerilatedVpiTimedCbsCmp {
/// Ordering sets keyed by time, then callback descriptor
bool operator() (const pair<QData,VerilatedVpioCb*>& a,
const pair<QData,VerilatedVpioCb*>& b) const {
if (a.first < b.first) return 1;
if (a.first > b.first) return 0;
return a.second < b.second;
}
};
class VerilatedVpi {
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
typedef set<VerilatedVpioCb*> VpioCbSet;
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
VpioTimedCbs m_timedCbs; // Time based callbacks
static VerilatedVpi s_s; // Singleton
public:
VerilatedVpi() {}
~VerilatedVpi() {}
static void cbReasonAdd(VerilatedVpioCb* vop) {
if (vop->reason() == cbValueChange) {
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
varop->createPrevDatap();
}
}
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
s_s.m_cbObjSets[vop->reason()].insert(vop);
}
static void cbTimedAdd(VerilatedVpioCb* vop) {
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
}
static void cbReasonRemove(VerilatedVpioCb* cbp) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
VpioCbSet::iterator it=cbObjSet.find(cbp);
if (VL_LIKELY(it != cbObjSet.end())) {
cbObjSet.erase(it);
}
}
static void cbTimedRemove(VerilatedVpioCb* cbp) {
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
s_s.m_timedCbs.erase(it);
}
}
static void callTimedCbs() {
QData time = VL_TIME_Q();
for (VpioTimedCbs::iterator it=s_s.m_timedCbs.begin(); it!=s_s.m_timedCbs.end(); ) {
if (VL_UNLIKELY(it->first <= time)) {
VerilatedVpioCb* vop = it->second;
++it; // iterator may be deleted by callback
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: timed_callback %p\n",vop););
(vop->cb_rtnp()) (vop->cb_datap());
}
else { ++it; }
}
}
static QData cbNextDeadline() {
VpioTimedCbs::iterator it=s_s.m_timedCbs.begin();
if (VL_LIKELY(it!=s_s.m_timedCbs.end())) {
return it->first;
} else {
return ~VL_ULL(0); // maxquad
}
}
static void callCbs(vluint32_t reason) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
VerilatedVpioCb* vop = *it;
++it; // iterator may be deleted by callback
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
(vop->cb_rtnp()) (vop->cb_datap());
}
}
static void callValueCbs() {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
VerilatedVpioCb* vop = *it;
++it; // iterator may be deleted by callback
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
void* newDatap = varop->varDatap();
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_test %s v[0]=%d/%d %p %p\n",
varop->fullname(), *((CData*)newDatap), *((CData*)prevDatap),
newDatap, prevDatap););
if (memcmp(prevDatap, newDatap, varop->entSize())) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize());
(vop->cb_rtnp()) (vop->cb_datap());
}
}
}
}
};
// callback related
vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
if (VL_UNLIKELY(!cb_data_p)) return NULL;
switch (cb_data_p->reason) {
case cbAfterDelay: {
QData time = 0;
if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time);
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p delay=%" VL_PRI64 "d\n",cb_data_p->reason,vop,time););
VerilatedVpi::cbTimedAdd(vop);
return vop->castVpiHandle();
}
case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp
case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp
case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp
case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp
case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object
case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object
case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0);
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop););
VerilatedVpi::cbReasonAdd(vop);
return vop->castVpiHandle();
}
default:
_VL_VPI_UNIMP(); return NULL;
};
}
PLI_INT32 vpi_remove_cb(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_remove_cb %p\n",object););
VerilatedVpioCb* vop = VerilatedVpioCb::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->cb_datap()->reason == cbAfterDelay) {
VerilatedVpi::cbTimedRemove(vop);
} else {
VerilatedVpi::cbReasonRemove(vop);
}
return 1;
}
//-void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// for obtaining handles
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
if (VL_UNLIKELY(!namep)) return NULL;
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_name %s %p\n",namep,scope););
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
const VerilatedVar* varp;
const VerilatedScope* scopep;
string scopeAndName = namep;
if (voScopep) {
scopeAndName = string(voScopep->fullname()) + "." + namep;
namep = (PLI_BYTE8*)scopeAndName.c_str();
}
{
// This doesn't yet follow the hierarchy in the proper way
scopep = Verilated::scopeFind(namep);
if (scopep) { // Whole thing found as a scope
return (new VerilatedVpioScope(scopep))->castVpiHandle();
}
const char* baseNamep = scopeAndName.c_str();
string scopename;
const char* dotp = strrchr(namep, '.');
if (VL_LIKELY(dotp)) {
baseNamep = dotp+1;
scopename = string(namep,dotp-namep);
}
scopep = Verilated::scopeFind(scopename.c_str());
if (!scopep) return NULL;
varp = scopep->varFind(baseNamep);
}
if (!varp) return NULL;
return (new VerilatedVpioVar(varp, scopep))->castVpiHandle();
}
vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
// Used to get array entries
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_index %p %d\n",object, indx););
VerilatedVpioVar* varop = VerilatedVpioVar::castp(object);
if (VL_LIKELY(varop)) {
if (varop->varp()->dims()<2) return 0;
if (VL_LIKELY(varop->varp()->array().lhs() >= varop->varp()->array().rhs())) {
if (VL_UNLIKELY(indx > varop->varp()->array().lhs() || indx < varop->varp()->array().rhs())) return 0;
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().rhs()))
->castVpiHandle();
} else {
if (VL_UNLIKELY(indx < varop->varp()->array().lhs() || indx > varop->varp()->array().rhs())) return 0;
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().lhs()))
->castVpiHandle();
}
} else {
_VL_VPI_UNIMP(); return 0;
}
}
// for traversing relationships
vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object););
switch (type) {
case vpiLeftRange: // FALLTHRU
case vpiRightRange: {
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
vluint32_t num = ((type==vpiLeftRange)
? vop->varp()->range().lhs()
: vop->varp()->range().rhs());
return (new VerilatedVpioConst(num))->castVpiHandle();
} else if (VerilatedVpioRange* vop = VerilatedVpioRange::castp(object)) {
vluint32_t num = ((type==vpiLeftRange)
? vop->lhs()
: vop->rhs());
return (new VerilatedVpioConst(num))->castVpiHandle();
} else {
return 0;
}
}
default:
_VL_VPI_UNIMP();
return 0;
}
}
//-vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHandle2, ... ) {
//- _VL_VPI_UNIMP(); return 0;
//-}
vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_iterate %d %p\n",type,object););
switch (type) {
case vpiMemoryWord: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims() < 2) return 0;
// Unsupported is multidim list
return ((new VerilatedVpioRange(vop->varp()->array().lhs(),
vop->varp()->array().rhs()))
->castVpiHandle());
}
case vpiReg: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return ((new VerilatedVpioVarIter(vop->scopep()))
->castVpiHandle());
}
case vpiIODecl: // Skipping - we'll put under reg
case vpiNet: // Skipping - we'll put under reg
return 0;
default:
_VL_VPI_UNIMP(); return 0;
}
}
vpiHandle vpi_scan(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_scan %p\n",object););
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return NULL;
return vop->dovpi_scan();
}
// for processing properties
PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
// Leave this in the header file - in many cases the compiler can constant propagate "object"
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get %d %p\n",property,object););
switch (property) {
case vpiTimePrecision: {
return VL_TIME_PRECISION;
}
case vpiType: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return ((vop->varp()->dims()>1) ? vpiMemory : vpiReg);
}
case vpiDirection: {
// By forthought, the directions already are vpi enumerated
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return vop->varp()->vldir();
}
case vpiVector: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims()==0) return 0;
else return 1;
}
default:
_VL_VPI_UNIMP();
return 0;
}
}
//-PLI_INT64 vpi_get64(PLI_INT32 property, vpiHandle object) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_str %d %p\n",property,object););
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return NULL;
switch (property) {
case vpiName: {
return (PLI_BYTE8*)vop->name();
}
case vpiFullName: {
return (PLI_BYTE8*)vop->fullname();
}
case vpiDefName: {
return (PLI_BYTE8*)vop->defname();
}
default:
_VL_VPI_UNIMP();
return 0;
}
}
// delay processing
//-void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// value processing
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
if (VL_UNLIKELY(!value_p)) return;
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
if (value_p->format == vpiVectorVal) {
// Vector pointer must come from our memory pool
// It only needs to persist until the next vpi_get_value
static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2];
value_p->value.vector = out;
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
out[0].aval = *((CData*)(vop->varDatap()));
out[0].bval = 0;
return;
case VLVT_UINT16:
out[0].aval = *((SData*)(vop->varDatap()));
out[0].bval = 0;
return;
case VLVT_UINT32:
out[0].aval = *((IData*)(vop->varDatap()));
out[0].bval = 0;
return;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().bits());
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
}
WDataInP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
out[i].aval = datap[i];
out[i].bval = 0;
}
return;
}
case VLVT_UINT64: {
QData data = *((QData*)(vop->varDatap()));
out[1].aval = (IData)(data>>VL_ULL(32));
out[1].bval = 0;
out[0].aval = (IData)(data);
out[0].bval = 0;
return;
}
default: {
_VL_VPI_UNIMP();
return;
}
}
} else {
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
value_p->value.integer = *((CData*)(vop->varDatap()));
return;
case VLVT_UINT16:
value_p->value.integer = *((SData*)(vop->varDatap()));
return;
case VLVT_UINT32:
value_p->value.integer = *((IData*)(vop->varDatap()));
return;
case VLVT_WDATA:
case VLVT_UINT64:
// Not legal
value_p->value.integer = 0;
default:
_VL_VPI_UNIMP();
return;
}
}
}
else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
value_p->value.integer = vop->num();
return;
}
_VL_VPI_UNIMP();
}
vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
p_vpi_time time_p, PLI_INT32 flags) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value %p %p\n",object, value_p););
if (VL_UNLIKELY(!value_p)) return 0;
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value name=%s fmt=%d vali=%d\n",
vop->fullname(), value_p->format, value_p->value.integer);
VL_PRINTF("-vltVpi: varp=%p putatp=%p\n",
vop->varp()->datap(), vop->varDatap()););
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
VL_PRINTF("%%Warning: Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: %s\n",
vop->fullname());
return 0;
}
if (value_p->format == vpiVectorVal) {
if (VL_UNLIKELY(!value_p->value.vector)) return NULL;
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
*((CData*)(vop->varDatap())) = value_p->value.vector[0].aval;
return object;
case VLVT_UINT16:
*((SData*)(vop->varDatap())) = value_p->value.vector[0].aval;
return object;
case VLVT_UINT32:
*((IData*)(vop->varDatap())) = value_p->value.vector[0].aval;
return object;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().bits());
WDataOutP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
datap[i] = value_p->value.vector[i].aval;
}
return object;
}
case VLVT_UINT64: {
*((QData*)(vop->varDatap())) = _VL_SET_QII(
value_p->value.vector[1].aval,
value_p->value.vector[0].aval);
return object;
}
default: {
_VL_VPI_UNIMP();
return NULL;
}
}
} else {
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
*((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_UINT16:
*((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_UINT32:
*((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_WDATA: // FALLTHRU
case VLVT_UINT64: // FALLTHRU
default:
_VL_VPI_UNIMP();
return 0;
}
}
}
_VL_VPI_UNIMP(); return NULL;
}
//-void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
//- PLI_INT32 *index_p, PLI_UINT32 num) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
//- PLI_INT32 *index_p, PLI_UINT32 num) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// time processing
//-void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
//- _VL_VPI_UNIMP();
//-}
// I/O routines
//-PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
va_list ap;
va_start(ap,formatp);
int chars = vpi_vprintf(formatp, ap);
va_end(ap);
return chars;
}
PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
return VL_VPRINTF(formatp, ap);
}
//-PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_flush(void) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// utility routines
//-PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_free_object(vpiHandle object) {
return vpi_release_handle(object); // Deprecated
}
PLI_INT32 vpi_release_handle (vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_release_handle %p\n",object););
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
vpi_remove_cb(object); // May not be a callback, but that's ok
delete vop;
return 1;
}
//-PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// routines added with 1364-2001
//-PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void *vpi_get_userdata(vpiHandle obj) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_control %d\n",operation););
switch (operation) {
case vpiFinish: {
vl_finish(__FILE__,__LINE__,"*VPI*");
return 1;
}
case vpiStop: {
vl_stop(__FILE__,__LINE__,"*VPI*");
return 1;
}
}
_VL_VPI_UNIMP(); return 0;
}
//-vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index, PLI_INT32 *index_array) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//======================================================================
#endif // Guard
+25 -3
View File
@@ -1,7 +1,7 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -126,8 +126,13 @@ typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibili
typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
# endif
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#elif defined(_WIN32) && defined(_MSC_VER)
@@ -141,6 +146,14 @@ typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
# ifndef _SSIZE_T_DEFINED
# ifdef _WIN64
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
# else
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
# endif
# endif
#else // Linux or compliant Unix flavors, -m64
# include <stdint.h> // Linux and most flavors
@@ -149,8 +162,13 @@ typedef uint8_t vluint8_t; ///< 32-bit unsigned type
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit signed type
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#endif
//=========================================================================
@@ -160,7 +178,11 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#ifdef _WIN32
# define VL_PRI64 "I64"
#else // Linux or compliant Unix flavors
# define VL_PRI64 "ll"
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
# define VL_PRI64 "l"
# else
# define VL_PRI64 "ll"
# endif
#endif
//=========================================================================
File diff suppressed because it is too large Load Diff
+144 -55
View File
@@ -40,7 +40,148 @@ Modify the later visitor functions to process the new feature as needed.
=back
=head1 DEBUG OUTPUT/ TREE FILES
=head1 CODE FLOWS
=head2 Verilator Flow
The main flow of Verilator can be followed by reading the Verilator.cpp
process() function:
First, the files specified on the command line are read. Reading involves
preprocessing, then lexical analysis with Flex and parsing with Bison.
This produces an abstract syntax tree (AST) representation of the design,
which is what is visible in the .tree files described below.
Cells are then linked, which will read and parse additional files as above.
Functions, variable and other references are linked to their definitions.
Parameters are resolved and the design is elaborated.
Verilator then performs many additional edits and optimizations on the
hierarchical design. This includes coverage, assertions, X elimination,
inlining, constant propagation, and dead code elimination.
References in the design are then psudo-flattened. Each module's variables
and functions get "Scope" references. A scope reference is an occurrence of
that un-flattened variable in the flattened hierarchy. A module that occurs
only once in the hierarchy will have a single scope and single VarScope for
each variable. A module that occurs twice will have a scope for each
occurrence, and two VarScopes for each variable. This allows optimizations
to proceed across the flattened design, while still preserving the
hierarchy.
Additional edits and optimizations proceed on the psudo-flat design. These
include module references, function inlining, loop unrolling, variable
lifetime analysis, lookup table creation, always splitting, and logic gate
simplifications (pushing inverters, etc).
Verilator orders the code. Best case, this results in a single "eval"
function which has all always statements flowing from top to bottom with no
loops.
Verilator mostly removes the flattening, so that code may be shared between
multiple invocations of the same module. It localizes variables, combines
identical functions, expands macros to C primitives, adds branch prediction
hints, and performs additional constant propagation.
Verilator finally writes the C++ modules.
=head2 Verilated Flow
The evaluation loop outputted by Verilator is designed to allow a single
function to perform evaluation under most situations.
On the first evaluation, the Verilated code calls initial blocks, and then
"settles" the modules, by evaluating functions (from always statements)
until all signals are stable.
On other evaluations, the Verilated code detects what input signals have
changes. If any are clocks, it calls the appropriate sequential functions
(from always @ posedge statements). Interspersed with sequential functions
it calls combo functions (from always @*). After this is complete, it
detects any changes due to combo loops or internally generated clocks, and
if one is found must reevaluate the model again.
For SystemC code, the eval() function is wrapped in a SystemC SC_METHOD,
sensitive to all inputs. (Ideally it would only be sensitive to clocks and
combo inputs, but tracing requires all signals to cause evaluation, and the
performance difference is small.)
If tracing is enabled, a callback examines all variables in the design for
changes, and writes the trace for each change. To accelerate this process
the evaluation process records a bitmask of variables that might have
changed; if clear, checking those signals for changes may be skipped.
=head1 CODING CONVENTIONS
=head2 Indentation style
To match the indentation of Verilator C++ sources, use 4 spaces per level,
and leave tabs at 8 columns, so every other indent level is a tab stop.
In Emacs, use in your ~/.emacs
(add-hook 'c-mode-common-hook '(lambda ()
(c-set-style "cc-mode"))))
This sets indentation to the cc-mode defaults. (Verilator predates a
CC-mode change of several years ago which overrides the defaults with GNU
style indentation; the c-set-style undoes that.)
=head2 Visitor Functions
There's three ways data is passed between visitor functions.
1. A visitor-class member variable. This is generally for passing "parent"
information down to children. m_modp is a common example. It's set to
NULL in the constructor, where that node (AstModule visitor) sets it, then
the children are iterated, then it's cleared. Children under an AstModule
will see it set, while nodes elsewhere will see it clear. If there can be
nested items (for example an AstFor under an AstFor) the variable needs to
be save-set-restored in the AstFor visitor, otherwise exiting the lower for
will loose the upper for's setting.
2. User() attributes. Each node has 5 ->user() number or ->userp() pointer
utility values (a common technique lifted from graph traversal packages).
A visitor first clears the one it wants to use by calling
AstNode::user#ClearTree(), then it can mark any node's user() with whatever
data it wants. Readers just call nodep->user(), but may need to cast
appropriately, so you'll often see nodep->userp()->castSOMETYPE(). At the
top of each visitor are comments describing how the user() stuff applies to
that visitor class. For example:
// NODE STATE
// Cleared entire netlist
// AstModule::user1p() // bool. True to inline this module
This says that at the AstNetlist user1ClearTree() is called. Each
AstModule's is user1() is used to indicate if we're going to inline it.
These comments are important to make sure a user#() on a given AstNode type
is never being used for two different purposes.
Note that calling user#ClearTree is fast, it doesn't walk the tree, so it's
ok to call fairly often. For example, it's commonly called on every
module.
3. Parameters can be passed between the visitors in close to the "normal"
function caller to callee way. This is the second "vup" parameter that is
ignored on most of the visitor functions. V3Width does this, but it proved
more messy than the above and is deprecated. (V3Width was nearly the first
module written. Someday this scheme may be removed, as it slows the
program down to have to pass vup everywhere.)
=head1 TESTING
To write a test see notes in the forum and in the verilator.txt manual.
Note you can run the regression tests in parallel; see the
test_regress/driver.pl script -j flag.
=head1 DEBUGGING
=head2 --debug
When you run with --debug there are two primary output file types placed into
the obj_dir, .tree and .dot files.
@@ -94,59 +235,7 @@ variable is an output.
=back
=head1 TESTING
To write a test see notes in the forum and in the verilator.txt manual.
Note you can run the regression tests in parallel; see the
test_regress/driver.pl script -j flag.
=head1 VISITOR FUNCTIONS
=head2 Passing Variables
There's three ways data is passed between visitor functions.
1. A visitor-class member variable. This is generally for passing "parent"
information down to children. m_modp is a common example. It's set to
NULL in the constructor, where that node (AstModule visitor) sets it, then
the children are iterated, then it's cleared. Children under an AstModule
will see it set, while nodes elsewhere will see it clear. If there can be
nested items (for example an AstFor under an AstFor) the variable needs to
be save-set-restored in the AstFor visitor, otherwise exiting the lower for
will loose the upper for's setting.
2. User() attributes. Each node has 5 ->user() number or ->userp() pointer
utility values (a common technique lifted from graph traversal packages).
A visitor first clears the one it wants to use by calling
AstNode::user#ClearTree(), then it can mark any node's user() with whatever
data it wants. Readers just call nodep->user(), but may need to cast
appropriately, so you'll often see nodep->userp()->castSOMETYPE(). At the
top of each visitor are comments describing how the user() stuff applies to
that visitor class. For example:
// NODE STATE
// Cleared entire netlist
// AstModule::user1p() // bool. True to inline this module
This says that at the AstNetlist user1ClearTree() is called. Each
AstModule's is user1() is used to indicate if we're going to inline it.
These comments are important to make sure a user#() on a given AstNode type
is never being used for two different purposes.
Note that calling user#ClearTree is fast, it doesn't walk the tree, so it's
ok to call fairly often. For example, it's commonly called on every
module.
3. Parameters can be passed between the visitors in close to the "normal"
function caller to callee way. This is the second "vup" parameter that is
ignored on most of the visitor functions. V3Width does this, but it proved
more messy than the above and is deprecated. (V3Width was nearly the first
module written. Someday this scheme may be removed, as it slows the
program down to have to pass vup everywhere.)
=head1 DEBUGGING WITH GDB
=head2 Debugging with GDB
The test_regress/driver.pl script accepts --debug --gdb to start Verilator
under gdb. You can also use --debug --gdbbt to just backtrace and then
@@ -161,7 +250,7 @@ what made a <e####> line in the tree dumps):
The latest version is available from L<http://www.veripool.org/>.
Copyright 2008-2010 by Wilson Snyder. Verilator is free software; you can
Copyright 2008-2011 by Wilson Snyder. Verilator 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.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
# Copyright 2007-2011 by Wilson Snyder. This package 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.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
# Copyright 2007-2011 by Wilson Snyder. This package 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.
+1 -1
View File
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2011 by Wilson Snyder. Verilator 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.
+1 -1
View File
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2011 by Wilson Snyder. Verilator 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.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
# Copyright 2007-2011 by Wilson Snyder. This package 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.
+3 -3
View File
@@ -59,9 +59,9 @@ sub test {
my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin";
IO::File->new(">$testdir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); end endmodule'."\n");
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc --exe foo.v");
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v");
run("cd $testdir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
#Need .c file for this to work
#Need .c file, and --exe for this to work
#run("cd $testdir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
}
}
@@ -117,7 +117,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2009-2010 by Wilson Snyder. This package is free software; you
Copyright 2009-2011 by Wilson Snyder. This package 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.
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/perl -w
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','axiom-athdl');
exec('atsim',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
=pod
=head1 NAME
invoke_atsim - Invoke tool under "modules" command
=head1 SYNOPSIS
invoke_atsim {ncv arguments}
=head1 DESCRIPTION
=head1 DISTRIBUTION
Copyright 2005-2011 by Wilson Snyder. This package 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.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./invoke_atsim -help"
### End:
+1 -1
View File
@@ -40,7 +40,7 @@ invoke_iccr - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2007-2010 by Wilson Snyder. This package is free software; you
Copyright 2007-2011 by Wilson Snyder. This package 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.
+1 -1
View File
@@ -40,7 +40,7 @@ invoke_ncverilog - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
Copyright 2005-2011 by Wilson Snyder. This package 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.
+1 -1
View File
@@ -40,7 +40,7 @@ invoke_vcs - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
Copyright 2005-2011 by Wilson Snyder. This package 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.
+3 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2010-2010 by Wilson Snyder. This package is free software; you
# Copyright 2010-2011 by Wilson Snyder. This package 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.
@@ -81,6 +81,7 @@ sub prep {
$line =~ s/SP_NOTICE.*// if $sp;
$line =~ s/vl_fatal.*// if !$sp;
$line =~ s/VL_PRINT.*// if !$sp;
$line =~ s/Copyright \d+-\d+/Copyright #-#/g;
push @wf, $line;
@@ -126,6 +127,7 @@ sub prep {
#
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
$wholefile =~ s/%ll/%" VL_PRI64 "/g;
$wholefile =~ s/\(long long unsigned\)n/ n/g; # printQuad
#
$wholefile =~ s/\bSP_SC_BV/VL_SC_BV/g;
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
+1 -1
View File
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2011 by Wilson Snyder. Verilator 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.
+44 -21
View File
@@ -9,7 +9,7 @@ This is the Verilator Package README file.
=head1 DISTRIBUTION
This package is Copyright 2003-2010 by Wilson Snyder. (Report bugs to
This package is Copyright 2003-2011 by Wilson Snyder. (Report bugs to
L<http://www.veripool.org/>.)
Verilator is free software; you can redistribute it and/or modify it under
@@ -72,15 +72,14 @@ Download the latest package from that site, and decompress.
If you will be using SystemC (vs straight C++ output), download SystemC
2.0.1 from L<http://www.systemc.org>. Follow their installation
instructions. As described in the System-Perl README, you will need to set
SYSTEMC and/or SYSTEMC_KIT to point to this download. Also, set
SYSTEMC_ARCH to the architecture name you used with SystemC, generally
'linux' or 'cygwin'.
instructions. You will need to set the SYSTEMC environment variable to
point to this download. Also, setenv SYSTEMC_ARCH to the architecture name
you used with SystemC, generally 'linux' or 'cygwin'.
=item
If you will be using SystemPerl or coverage, download and install
Verilog-Perl, L<http://www.veripool.org/verilog-perl>.
Verilator assumes you did a make in the SystemC kit directory and SYSTEMC
points to that directory. There must be appropriate files in
C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux> for SystemC compilation to
work.
=item
@@ -98,20 +97,49 @@ C<cd> to the Verilator directory containing this README.
You now have to decide how you're going to eventually install the kit.
Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC,
SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
executable, so try to have them correct before configuring.
=over 4
=item 1.
Our personal favorite is to always run Verilator from the kit directory.
This allows the easiest experimentation and upgrading. It's also how most
EDA tools operate; you just point to the tarball.
EDA tools operate; to run any of them you point to the tarball.
export VERILATOR_ROOT=`pwd` # if your shell is bash
setenv VERILATOR_ROOT `pwd` # if your shell is csh
./configure
=item 2.
To install globally onto a "cad" disk with multiple versions of every tool,
and add it to path using Modules/modulecmd:
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
# For the tarball, use the version number instead of git describe
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
After installing you'll want a module file like the following:
set install_root /CAD_DISK/verilator/{version-number-used-above}
setenv VERILATOR_ROOT $install_root
prepend-path PATH $install_root/bin
prepend-path MANPATH $install_root/man
=item 3.
The next option is to install it globally, using the normal system paths:
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
./configure
=item 4.
Alternatively you can configure a prefix that install will populate, as
most GNU tools support:
@@ -119,11 +147,7 @@ most GNU tools support:
unsetenv VERILATOR_ROOT # if your shell is csh
./configure --prefix /opt/verilator-VERSION
Finally, if you are configuring Verilator to be part of a RPM or other
distribution package system, you may want to tune the various install
directories and use the --enable-defenv configure flag. This will take the
current value of VERILATOR_ROOT, SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and
SYSTEMPERL_INCLUDE and build them as defaults into the executable.
=back
=item
@@ -141,16 +165,15 @@ unsigned long uint32_t;}.
=item
If you used the VERILATOR_ROOT sheme you're done. Programs should set the
If you used the VERILATOR_ROOT scheme you're done. Programs should set the
environment variable VERILATOR_ROOT to point to this distribution, then
execute $VERILATOR_ROOT/bin/verilator, which will find the path to all
needed files.
If you used the prefix scheme, now do a C<make install>.
Verilator assumes you did a make in the SystemC kit directory. If not, you
will need to populate C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux>
appropriately.
If you used the prefix scheme, now do a C<make install>. To run verilator,
have the verilator binary directory in your PATH (this should already be
true if using the default configure), and make sure VERILATOR_ROOT is not
set.
=back
+1 -1
View File
@@ -26,7 +26,7 @@ This is the Verilator Package.
@node Copyright, Description, Top, Top
@section Copyright
This package is Copyright 2003-2010 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
This package is Copyright 2003-2011 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
Verilator is free software; you can redistribute it and/or modify it
under the terms of either the GNU Lesser General Public License
+5 -1
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2011 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.
@@ -46,6 +46,10 @@ export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
endif
endif
ifneq ($(words $(CURDIR)),1)
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
endif
UNDER_GIT = $(wildcard ../.git/logs/HEAD)
#*********************************************************************
+9 -6
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2011 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.
@@ -121,6 +121,7 @@ HEADERS = $(wildcard V*.h v*.h)
ASTGEN = $(srcdir)/astgen
BISONPRE = $(srcdir)/bisonpre
FLEXFIX = $(srcdir)/flexfix
######################################################################
#### Top level
@@ -194,8 +195,9 @@ RAW_OBJS = \
V3Link.o \
V3LinkCells.o \
V3LinkDot.o \
V3LinkLevel.o \
V3LinkJump.o \
V3LinkLValue.o \
V3LinkLevel.o \
V3LinkParse.o \
V3LinkResolve.o \
V3Localize.o \
@@ -219,6 +221,7 @@ RAW_OBJS = \
V3Trace.o \
V3TraceDecl.o \
V3Tristate.o \
V3Undriven.o \
V3Unknown.o \
V3Unroll.o \
V3Width.o \
@@ -295,15 +298,15 @@ V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS)
${LEX} --version
${LEX} ${LFLAGS} -o$@ $<
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp
$(PERL) $(srcdir)/flexfix <$< >$@
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp $(FLEXFIX)
$(PERL) $(FLEXFIX) V3Lexer <$< >$@
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
${LEX} --version
${LEX} ${LFLAGS} -o$@ $<
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp
$(PERL) $(srcdir)/flexfix <$< >$@
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
$(PERL) $(FLEXFIX) V3PreLex <$< >$@
######################################################################
######################################################################
+77 -36
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -160,26 +160,58 @@ public:
class ActiveDlyVisitor : public ActiveBaseVisitor {
private:
bool m_combo; // Combo logic
AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign
// VISITORS
virtual void visit(AstAssignDly* nodep, AstNUser*) {
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) blocks should be non-delayed assignments (=).");
AstNode* newp = new AstAssign (nodep->fileline(),
nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack());
nodep->replaceWith(newp);
nodep->deleteTree(); nodep = NULL;
if (m_combo) {
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
AstNode* newp = new AstAssign (nodep->fileline(),
nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack());
nodep->replaceWith(newp);
nodep->deleteTree(); nodep = NULL;
}
}
virtual void visit(AstAssign* nodep, AstNUser*) {
if (!m_combo) {
AstNode* las = m_assignp;
m_assignp = nodep;
nodep->lhsp()->iterateAndNext(*this);
m_assignp = las;
}
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
AstVar* varp=nodep->varp();
if (!m_combo
&& m_assignp
&& !varp->isUsedLoopIdx() // Ignore loop indicies
&& !varp->isTemp()
) {
// Allow turning off warnings on the always, or the variable also
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
) {
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
nodep->v3warn(BLKSEQ,"Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).");
}
}
}
// Empty visitors, speed things up
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
//--------------------
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
ActiveDlyVisitor(AstNode* nodep) {
ActiveDlyVisitor(AstNode* nodep, bool combo) {
m_alwaysp = nodep;
m_combo = combo;
m_assignp = NULL;
nodep->accept(*this);
}
virtual ~ActiveDlyVisitor() {}
@@ -197,7 +229,6 @@ private:
// STATE
ActiveNamer m_namer; // Tracking of active names
AstCFunc* m_scopeFinalp; // Final function for this scope
AstAlways* m_alwaysp; // Under always
bool m_itemCombo; // Found a SenItem combo
bool m_itemSequent; // Found a SenItem sequential
@@ -264,32 +295,22 @@ private:
}
// METHODS
virtual void visit(AstAlways* nodep, AstNUser*) {
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp) {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
if (!nodep->bodysp()) {
// Empty always. Kill it.
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
if (nodep->sensesp()
&& nodep->sensesp()->sensesp()
&& nodep->sensesp()->sensesp()->castSenItem()
&& nodep->sensesp()->sensesp()->castSenItem()->isNever()) {
if (oldsensesp
&& oldsensesp->sensesp()
&& oldsensesp->sensesp()->castSenItem()
&& oldsensesp->sensesp()->castSenItem()->isNever()) {
// Never executing. Kill it.
if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
// Read sensitivitues
m_alwaysp = nodep;
m_itemCombo = false;
m_itemSequent = false;
nodep->sensesp()->iterateAndNext(*this);
m_alwaysp = NULL;
oldsensesp->iterateAndNext(*this);
bool combo = m_itemCombo;
bool sequent = m_itemSequent;
@@ -311,15 +332,15 @@ private:
// always (posedge RESET) { if (RESET).... } we know RESET is true.
// Summarize a long list of combo inputs as just "combo"
#ifndef __COVERITY__ // Else dead code on next line.
if (combo) nodep->sensesp()->addSensesp
if (combo) oldsensesp->addSensesp
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
#endif
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp());
wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
}
// Delete sensitivity list
if (AstNode* oldsense = nodep->sensesp()) {
oldsense->unlinkFrBackWithNext()->deleteTree(); oldsense=NULL;
if (oldsensesp) {
oldsensesp->unlinkFrBackWithNext()->deleteTree(); oldsensesp=NULL;
}
// Move node to new active
@@ -328,8 +349,29 @@ private:
// Warn and/or convert any delayed assignments
if (combo && !sequent) {
ActiveDlyVisitor dlyvisitor (nodep);
ActiveDlyVisitor dlyvisitor (nodep, true);
}
else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor (nodep, false);
}
}
virtual void visit(AstAlways* nodep, AstNUser*) {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
if (!nodep->bodysp()) {
// Empty always. Kill it.
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
visitAlways(nodep, nodep->sensesp());
}
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
visitAlways(nodep, nodep->sensesp());
}
virtual void visit(AstSenGate* nodep, AstNUser*) {
AstSenItem* subitemp = nodep->sensesp();
@@ -366,7 +408,6 @@ public:
// CONSTUCTORS
ActiveVisitor(AstNetlist* nodep) {
m_scopeFinalp = NULL;
m_alwaysp = NULL;
m_itemCombo = false;
m_itemSequent = false;
nodep->accept(*this);
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+4 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -133,6 +133,9 @@ private:
virtual void visit(AstAlways* nodep, AstNUser*) {
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstFinal* nodep, AstNUser*) {
nodep->v3fatalSrc("Node should have been deleted");
}
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+6 -6
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2011 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.
@@ -177,13 +177,12 @@ private:
// VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (!nodep->user1()) {
nodep->user1(true);
if (!nodep->user1Inc()) {
bool has_default=false;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
if (itemp->isDefault()) has_default=true;
}
if (nodep->fullPragma()) {
if (nodep->fullPragma() || nodep->priorityPragma()) {
// Simply need to add a default if there isn't one already
m_statAsFull++;
if (!has_default) {
@@ -191,7 +190,7 @@ private:
newFireAssert(nodep, "synthesis full_case, but non-match found")));
}
}
if (nodep->parallelPragma()) {
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
// Need to check that one, and only one of the case items match at any moment
// If there's a default, we allow none to match, else exactly one must match
m_statAsFull++;
@@ -208,7 +207,8 @@ private:
else propp = onep;
}
}
AstNode* ohot = (has_default
bool allow_none = has_default || nodep->unique0Pragma();
AstNode* ohot = (allow_none
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
: (new AstOneHot (nodep->fileline(), propp))->castNode());
AstIf* ifp = new AstIf (nodep->fileline(),
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2011 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.
+3 -2
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -192,6 +192,7 @@ string AstNode::prettyName(const string& namein) {
}
}
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
return pretty;
}
@@ -813,7 +814,7 @@ void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
// Some visitors perform tree edits (such as V3Const), and may even
// replace/delete the exact nodep that the visitor is called with. If
// this happens, the parent will loose the handle to the node that was
// this happens, the parent will lose the handle to the node that was
// processed.
// To solve this, this function returns the pointer to the replacement node,
// which in many cases is just the same node that was passed in.
+13 -2
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -179,6 +179,8 @@ public:
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
};
@@ -186,7 +188,8 @@ public:
const char* ascii() const {
static const char* names[] = {
"EXPR_BITS", "VAR_BASE",
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_PUBLIC_FLAT",
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT"
};
return names[m_e];
@@ -761,6 +764,7 @@ public:
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
bool brokeExists() const;
bool brokeExistsAbove() const;
// CONSTRUCTORS
virtual ~AstNode();
@@ -818,6 +822,7 @@ public:
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
int user1() const { return user1p()->castInt(); }
void user1(int val) { user1p(AstNUser::fromInt(val)); }
int user1Inc() { int v=user1(); user1(v+1); return v; }
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user2p() const {
@@ -826,6 +831,7 @@ public:
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
int user2() const { return user2p()->castInt(); }
void user2(int val) { user2p(AstNUser::fromInt(val)); }
int user2Inc() { int v=user2(); user2(v+1); return v; }
static void user2ClearTree() { AstUser2InUse::clear(); }
AstNUser* user3p() const {
@@ -834,6 +840,7 @@ public:
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
int user3() const { return user3p()->castInt(); }
void user3(int val) { user3p(AstNUser::fromInt(val)); }
int user3Inc() { int v=user3(); user3(v+1); return v; }
static void user3ClearTree() { AstUser3InUse::clear(); }
AstNUser* user4p() const {
@@ -842,6 +849,7 @@ public:
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
int user4() const { return user4p()->castInt(); }
void user4(int val) { user4p(AstNUser::fromInt(val)); }
int user4Inc() { int v=user4(); user4(v+1); return v; }
static void user4ClearTree() { AstUser4InUse::clear(); }
AstNUser* user5p() const {
@@ -850,6 +858,7 @@ public:
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
int user5() const { return user5p()->castInt(); }
void user5(int val) { user5p(AstNUser::fromInt(val)); }
int user5Inc() { int v=user5(); user5(v+1); return v; }
static void user5ClearTree() { AstUser5InUse::clear(); }
vluint64_t editCount() const { return m_editCount; }
@@ -870,6 +879,7 @@ public:
AstNode* addNext(AstNode* newp); // Returns this, adds to end of list
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK
void addNextHere(AstNode* newp); // Adds after speced node
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
void replaceWith(AstNode* newp); // Replace current node in tree with new node
void v3errorEnd(ostringstream& str) const;
@@ -966,6 +976,7 @@ struct AstNodeUniop : public AstNodeMath {
setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop)
AstNode* lhsp() const { return op1p()->castNode(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
// METHODS
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0;
+59 -7
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -137,6 +137,43 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
return arg;
}
string AstVar::vlEnumType() const {
string arg;
AstBasicDType* bdtypep = basicp();
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
return "VLVT_PTR";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
return "VLVT_PTR";
} else if (strtype) {
arg += "VLVT_STRING";
} else if (widthMin() <= 8) {
arg += "VLVT_UINT8";
} else if (widthMin() <= 16) {
arg += "VLVT_UINT16";
} else if (widthMin() <= VL_WORDSIZE) {
arg += "VLVT_UINT32";
} else if (isQuad()) {
arg += "VLVT_UINT64";
} else if (isWide()) {
arg += "VLVT_WDATA";
}
// else return "VLVT_UNKNOWN"
return arg;
}
string AstVar::vlEnumDir() const {
if (isInout()) {
return "VLVD_INOUT";
} else if (isInOnly()) {
return "VLVD_IN";
} else if (isOutOnly()) {
return "VLVD_OUT";
} else {
return "VLVD_NODIR";
}
}
string AstVar::cPubArgType(bool named, bool forReturn) const {
if (forReturn) named=false;
string arg;
@@ -258,13 +295,15 @@ uint32_t AstVar::arrayElements() const {
return entries;
}
uint32_t AstVar::dimensions() const {
// How many array dimensions does this Var have?
uint32_t dim = 0;
pair<uint32_t,uint32_t> AstVar::dimensions() const {
// How many array dimensions (packed,unpacked) does this Var have?
uint32_t packed = 0;
uint32_t unpacked = 0;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
dim += 1;
if (adtypep->isPacked()) packed += 1;
else unpacked += 1;
dtypep = adtypep->dtypep();
}
else {
@@ -272,7 +311,7 @@ uint32_t AstVar::dimensions() const {
break;
}
}
return dim;
return make_pair(packed, unpacked);
}
// Special operators
@@ -348,6 +387,8 @@ string AstScopeName::scopeSymName() const {
out += textp->text();
}
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
if (out.substr(0,1) == ".") out.replace(0,1,"");
string::size_type pos;
while ((pos=out.find(".")) != string::npos) {
out.replace(pos, 1, "__");
@@ -464,6 +505,10 @@ void AstNode::dump(ostream& os) {
if (name()!="") os<<" "<<AstNode::quoteName(name());
}
void AstArrayDType::dump(ostream& str) {
this->AstNode::dump(str);
if (isPacked()) str<<" [PACKED]";
}
void AstArraySel::dump(ostream& str) {
this->AstNode::dump(str);
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
@@ -477,7 +522,7 @@ void AstBasicDType::dump(ostream& str) {
str<<" ["<<keyword().ascii()<<"]";
if (implicit()) str<<" [IMPLICIT]";
}
void AstCast::dump(ostream& str) {
void AstCCast::dump(ostream& str) {
this->AstNode::dump(str);
str<<" sz"<<size();
}
@@ -494,6 +539,12 @@ void AstDisplay::dump(ostream& str) {
this->AstNode::dump(str);
//str<<" "<<displayType().ascii();
}
void AstJumpGo::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> ";
if (labelp()) { labelp()->dump(str); }
else { str<<"%Error:UNLINKED"; }
}
void AstEnumItemRef::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> ";
@@ -560,6 +611,7 @@ void AstVar::dump(ostream& str) {
}
if (isUsedClock()) str<<" [C]";
if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]";
if (attrClockEn()) str<<" [aCLKEN]";
if (attrIsolateAssign()) str<<" [aISO]";
if (attrFileDescr()) str<<" [aFD]";
+207 -25
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -204,13 +204,17 @@ public:
struct AstArrayDType : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
AstArrayDType(FileLine* fl, AstNodeDType* dtypep, AstRange* rangep)
: AstNodeDType(fl) {
private:
bool m_packed;
public:
AstArrayDType(FileLine* fl, AstNodeDType* dtypep, AstRange* rangep, bool isPacked=false)
: AstNodeDType(fl), m_packed(isPacked) {
setOp1p(dtypep);
setOp2p(rangep);
widthSignedFrom(dtypep);
}
ASTNODE_NODE_FUNCS(ArrayDType, ARRAYDTYPE)
virtual void dump(ostream& str);
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable
void dtypep(AstNodeDType* nodep) { setOp1p(nodep); }
@@ -225,6 +229,7 @@ struct AstArrayDType : public AstNodeDType {
int lsb() const { return arrayp()->lsbConst(); }
int elementsConst() const { return arrayp()->elementsConst(); }
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
bool isPacked() const { return m_packed; }
};
struct AstBasicDType : public AstNodeDType {
@@ -542,15 +547,20 @@ private:
bool m_sc:1; // SystemC variable
bool m_scClocked:1; // SystemC sc_clk<> needed
bool m_scSensitive:1;// SystemC sensitive() needed
bool m_sigPublic:1; // User C code accesses this signal
bool m_sigPublic:1; // User C code accesses this signal or is top signal
bool m_sigModPublic:1;// User C code accesses this signal and module
bool m_sigUserRdPublic:1; // User C code accesses this signal, read only
bool m_sigUserRWPublic:1; // User C code accesses this signal, read-write
bool m_usedClock:1; // Signal used as a clock
bool m_usedParam:1; // Parameter is referenced (on link; later signals not setup)
bool m_usedLoopIdx:1; // Variable subject of for unrolling
bool m_funcLocal:1; // Local variable for a function
bool m_funcReturn:1; // Return variable for a function
bool m_attrClockEn:1;// User clock enable attribute
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_attrSFormat:1;// User sformat attribute
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_didWidth:1; // V3Width completed; can skip iteration
bool m_fileDescr:1; // File descriptor
bool m_isConst:1; // Table contains constant data
bool m_isStatic:1; // Static variable
@@ -560,10 +570,11 @@ private:
m_input=false; m_output=false; m_tristate=false;
m_primaryIO=false;
m_sc=false; m_scClocked=false; m_scSensitive=false;
m_usedClock=false; m_usedParam=false;
m_sigPublic=false; m_sigModPublic=false;
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false;
m_didSigning=false; m_didWidth=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false;
m_trace=false;
}
@@ -607,12 +618,14 @@ public:
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
string vlArgType(bool named, bool forReturn) const; // Return Verilator internal type for argument: CData, SData, IData, WData
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
void combineType(AstVarType type);
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
AstNodeDType* dtypeDimensionp(int depth) const;
uint32_t dimensions() const;
pair<uint32_t,uint32_t> dimensions() const;
AstNode* valuep() const { return op3p()->castNode(); } // op3 = Initial value that never changes (static const)
void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than a AstConst
void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
@@ -624,10 +637,17 @@ public:
void attrScClocked(bool flag) { m_scClocked = flag; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
void attrSFormat(bool flag) { m_attrSFormat = flag; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void usedClock(bool flag) { m_usedClock = flag; }
void usedParam(bool flag) { m_usedParam = flag; }
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
void sigPublic(bool flag) { m_sigPublic = flag; }
void sigModPublic(bool flag) { m_sigModPublic = flag; }
void sigUserRdPublic(bool flag) { m_sigUserRdPublic = flag; if (flag) sigPublic(true); }
void sigUserRWPublic(bool flag) { m_sigUserRWPublic = flag; if (flag) sigUserRdPublic(true); }
void sc(bool flag) { m_sc = flag; }
void scSensitive(bool flag) { m_scSensitive = flag; }
void primaryIO(bool flag) { m_primaryIO = flag; }
@@ -664,12 +684,15 @@ public:
bool isBitLogic() const { AstBasicDType* bdtypep = basicp(); return bdtypep && bdtypep->isBitLogic(); }
bool isUsedClock() const { return m_usedClock; }
bool isUsedParam() const { return m_usedParam; }
bool isUsedLoopIdx() const { return m_usedLoopIdx; }
bool isSc() const { return m_sc; }
bool isScQuad() const;
bool isScBv() const;
bool isScSensitive() const { return m_scSensitive; }
bool isSigPublic() const;
bool isSigModPublic() const { return m_sigModPublic; }
bool isSigUserRdPublic() const { return m_sigUserRdPublic; }
bool isSigUserRWPublic() const { return m_sigUserRWPublic; }
bool isTrace() const { return m_trace; }
bool isConst() const { return m_isConst; }
bool isStatic() const { return m_isStatic; }
@@ -699,6 +722,8 @@ public:
combineType(typevarp->varType());
if (typevarp->isSigPublic()) sigPublic(true);
if (typevarp->isSigModPublic()) sigModPublic(true);
if (typevarp->isSigUserRdPublic()) sigUserRdPublic(true);
if (typevarp->isSigUserRWPublic()) sigUserRWPublic(true);
if (typevarp->attrScClocked()) attrScClocked(true);
}
void inlineAttrReset(const string& name) {
@@ -894,7 +919,9 @@ public:
,m_name(name), m_svImplicit(false) {
m_pinNum = pinNum;
m_modVarp = NULL;
setNOp1p(exprp); }
setNOp1p(exprp);
if (exprp) widthSignedFrom(exprp);
}
ASTNODE_NODE_FUNCS(Pin, PIN)
virtual void dump(ostream& str);
virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); }
@@ -903,7 +930,7 @@ public:
bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked
int pinNum() const { return m_pinNum; }
void exprp(AstNode* nodep) { addOp1p(nodep); }
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
void modVarp(AstVar* varp) { m_modVarp=varp; }
bool svImplicit() const { return m_svImplicit; }
@@ -1265,6 +1292,24 @@ struct AstAlways : public AstNode {
bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); }
};
struct AstAlwaysPublic : public AstNodeStmt {
// "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/
// Body statements are just AstVarRefs to the public signals
AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
: AstNodeStmt(fl) {
addNOp1p(sensesp); addNOp2p(bodysp);
}
ASTNODE_NODE_FUNCS(AlwaysPublic, ALWAYSPUBLIC)
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
//
AstSenTree* sensesp() const { return op1p()->castSenTree(); } // op1 = Sensitivity list
AstNode* bodysp() const { return op2p()->castNode(); } // op2 = Statements to evaluate
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
// Special accessors
bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); }
};
struct AstAlwaysPost : public AstNode {
// Like always but post assignments for memory assignment IFs
AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
@@ -1505,11 +1550,15 @@ private:
AstCaseType m_casex; // 0=case, 1=casex, 2=casez
bool m_fullPragma; // Synthesis full_case
bool m_parallelPragma; // Synthesis parallel_case
bool m_uniquePragma; // unique case
bool m_unique0Pragma; // unique0 case
bool m_priorityPragma; // priority case
public:
AstCase(FileLine* fileline, AstCaseType casex, AstNode* exprp, AstNode* casesp)
: AstNodeCase(fileline, exprp, casesp) {
m_casex=casex;
m_fullPragma=false; m_parallelPragma=false;
m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false;
}
ASTNODE_NODE_FUNCS(Case, CASE)
virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; }
@@ -1521,6 +1570,12 @@ public:
void fullPragma(bool flag) { m_fullPragma=flag; }
bool parallelPragma() const { return m_parallelPragma; }
void parallelPragma(bool flag) { m_parallelPragma=flag; }
bool uniquePragma() const { return m_uniquePragma; }
void uniquePragma(bool flag) { m_uniquePragma=flag; }
bool unique0Pragma() const { return m_unique0Pragma; }
void unique0Pragma(bool flag) { m_unique0Pragma=flag; }
bool priorityPragma() const { return m_priorityPragma; }
void priorityPragma(bool flag) { m_priorityPragma=flag; }
};
struct AstCaseItem : public AstNode {
@@ -1636,6 +1691,22 @@ struct AstSFormat : public AstNode {
void lhsp(AstNode* nodep) { setOp3p(nodep); }
};
struct AstSysIgnore : public AstNode {
// Parents: stmtlist
// Children: varrefs or exprs
AstSysIgnore(FileLine* fileline, AstNode* exprsp)
: AstNode (fileline) { addNOp1p(exprsp); }
ASTNODE_NODE_FUNCS(SysIgnore, SYSIGNORE)
virtual string verilogKwd() const { return "$ignored"; }
virtual bool isGateOptimizable() const { return false; } // Though deleted before opt
virtual bool isPredictOptimizable() const { return false; } // Though deleted before opt
virtual bool isSplittable() const { return false; } // Though deleted before opt
virtual bool isOutputter() const { return true; } // Though deleted before opt
virtual int instrCount() const { return instrCountPli(); }
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
};
struct AstFClose : public AstNodeStmt {
// Parents: stmtlist
// Children: file which must be a varref
@@ -1846,14 +1917,6 @@ struct AstGenFor : public AstNodeFor {
ASTNODE_NODE_FUNCS(GenFor, GENFOR)
};
struct AstFor : public AstNodeFor {
AstFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* incsp, AstNode* bodysp)
: AstNodeFor(fileline, initsp, condp, incsp, bodysp) {
}
ASTNODE_NODE_FUNCS(For, FOR)
};
struct AstRepeat : public AstNodeStmt {
AstRepeat(FileLine* fileline, AstNode* countp, AstNode* bodysp)
: AstNodeStmt(fileline) {
@@ -1869,16 +1932,18 @@ struct AstRepeat : public AstNodeStmt {
};
struct AstWhile : public AstNodeStmt {
AstWhile(FileLine* fileline, AstNode* condp, AstNode* bodysp)
AstWhile(FileLine* fileline, AstNode* condp, AstNode* bodysp, AstNode* incsp=NULL)
: AstNodeStmt(fileline) {
setOp2p(condp); addNOp3p(bodysp);
setOp2p(condp); addNOp3p(bodysp); addNOp4p(incsp);
}
ASTNODE_NODE_FUNCS(While, WHILE)
AstNode* precondsp() const { return op1p()->castNode(); } // op1= prepare statements for condition (exec every loop)
AstNode* condp() const { return op2p()->castNode(); } // op2= condition to continue
AstNode* bodysp() const { return op3p()->castNode(); } // op3= body of loop
AstNode* incsp() const { return op4p()->castNode(); } // op4= increment (if from a FOR loop)
void addPrecondsp(AstNode* newp) { addOp1p(newp); }
void addBodysp(AstNode* newp) { addOp3p(newp); }
void addIncsp(AstNode* newp) { addOp4p(newp); }
virtual bool isGateOptimizable() const { return false; }
virtual int instrCount() const { return instrCountBranch(); }
virtual V3Hash sameHash() const { return V3Hash(); }
@@ -1887,6 +1952,36 @@ struct AstWhile : public AstNodeStmt {
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
};
struct AstBreak : public AstNodeStmt {
AstBreak(FileLine* fileline)
: AstNodeStmt (fileline) {}
ASTNODE_NODE_FUNCS(Break, BREAK)
virtual string verilogKwd() const { return "break"; };
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
};
struct AstContinue : public AstNodeStmt {
AstContinue(FileLine* fileline)
: AstNodeStmt (fileline) {}
ASTNODE_NODE_FUNCS(Continue, CONTINUE)
virtual string verilogKwd() const { return "continue"; };
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
};
struct AstReturn : public AstNodeStmt {
AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
: AstNodeStmt (fileline) {
setNOp1p(lhsp);
}
ASTNODE_NODE_FUNCS(Return, RETURN)
virtual string verilogKwd() const { return "return"; };
virtual V3Hash sameHash() const { return V3Hash(); }
AstNode* lhsp() const { return op1p(); }
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
};
struct AstGenIf : public AstNodeIf {
AstGenIf(FileLine* fileline, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
: AstNodeIf(fileline, condp, ifsp, elsesp) {
@@ -1895,10 +1990,69 @@ struct AstGenIf : public AstNodeIf {
};
struct AstIf : public AstNodeIf {
private:
bool m_uniquePragma; // unique case
bool m_unique0Pragma; // unique0 case
bool m_priorityPragma; // priority case
public:
AstIf(FileLine* fileline, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
: AstNodeIf(fileline, condp, ifsp, elsesp) {
m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false;
}
ASTNODE_NODE_FUNCS(If, IF)
bool uniquePragma() const { return m_uniquePragma; }
void uniquePragma(bool flag) { m_uniquePragma=flag; }
bool unique0Pragma() const { return m_unique0Pragma; }
void unique0Pragma(bool flag) { m_unique0Pragma=flag; }
bool priorityPragma() const { return m_priorityPragma; }
void priorityPragma(bool flag) { m_priorityPragma=flag; }
};
struct AstJumpLabel : public AstNodeStmt {
// Jump point declaration
// Separate from AstJumpGo; as a declaration can't be deleted
// Parents: {statement list}
// Children: {statement list, with JumpGo below}
private:
int m_labelNum; // Set by V3EmitCSyms to tell final V3Emit what to increment
public:
AstJumpLabel(FileLine* fl, AstNode* stmtsp)
: AstNodeStmt(fl) ,m_labelNum(0) {
addNOp1p(stmtsp);
}
virtual int instrCount() const { return 0; }
ASTNODE_NODE_FUNCS(JumpLabel, JUMPLABEL)
virtual bool maybePointedTo() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
// op1 = Statements
AstNode* stmtsp() const { return op1p()->castNode(); } // op1 = List of statements
void addStmtsp(AstNode* nodep) { addNOp1p(nodep); }
int labelNum() const { return m_labelNum; }
void labelNum(int flag) { m_labelNum=flag; }
};
struct AstJumpGo : public AstNodeStmt {
// Jump point; branch up to the JumpLabel
// Parents: {statement list}
private:
AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration
public:
AstJumpGo(FileLine* fl, AstJumpLabel* labelp)
: AstNodeStmt(fl) {
m_labelp = labelp;
}
ASTNODE_NODE_FUNCS(JumpGo, JUMPGO)
virtual bool broken() const { return !labelp()->brokeExistsAbove(); }
virtual void cloneRelink() { if (m_labelp->clonep()) m_labelp = m_labelp->clonep()->castJumpLabel(); }
virtual void dump(ostream& str);
virtual int instrCount() const { return instrCountBranch(); }
virtual V3Hash sameHash() const { return V3Hash(labelp()); }
virtual bool same(AstNode* samep) const { // Also same if identical tree structure all the way down, but hard to detect
return labelp()==samep->castJumpGo()->labelp(); }
virtual bool isGateOptimizable() const { return false; }
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
AstJumpLabel* labelp() const { return m_labelp; }
};
struct AstUntilStable : public AstNodeStmt {
@@ -2468,27 +2622,42 @@ struct AstOneHot0 : public AstNodeUniop {
virtual int instrCount() const { return widthInstrs()*3; }
};
struct AstCast : public AstNodeUniop {
// Cast to appropriate data type
struct AstCast : public AstNode {
// Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc
AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtypep) : AstNode(fl) {
setOp1p(lhsp); setOp2p(dtypep);
if (dtypep) { widthSignedFrom(dtypep); }
}
ASTNODE_NODE_FUNCS(Cast, CAST)
virtual string emitVerilog() { return "((%r)'(%l))"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
AstNode* lhsp() const { return op1p(); }
AstNodeDType* dtypep() const { return op2p()->castNodeDType(); }
};
struct AstCCast : public AstNodeUniop {
// Cast to C-based data type
private:
int m_size;
public:
AstCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
AstCCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
m_size=setwidth;
if (setwidth) { width(setwidth,setwidth); }
}
AstCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
if (widthFromp) { widthSignedFrom(widthFromp); }
m_size=width();
}
ASTNODE_NODE_FUNCS(Cast, CAST)
ASTNODE_NODE_FUNCS(CCast, CCAST)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
virtual string emitVerilog() { return "%f$_CAST(%l)"; }
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
virtual V3Hash sameHash() const { return V3Hash(size()); }
virtual bool same(AstNode* samep) const { return size()==samep->castCast()->size(); }
virtual bool same(AstNode* samep) const { return size()==samep->castCCast()->size(); }
virtual void dump(ostream& str=cout);
//
int size() const { return m_size; }
@@ -3005,6 +3174,19 @@ struct AstReplicate : public AstNodeBiop {
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*2; }
};
struct AstBufIf1 : public AstNodeBiop {
// lhs is enable, rhs is data to drive
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
virtual string emitVerilog() { return "bufif(%r,%l)"; }
virtual string emitC() { V3ERROR_NA; return false;} // Lclean || Rclean
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean || Rclean
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstFGetS : public AstNodeBiop {
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FGetS, FGETS)
+18 -48
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -53,6 +53,7 @@ private:
string m_namedScope; // Name of begin blocks above us
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
int m_repeatNum; // Repeat counter
int m_ifDepth; // Current if depth
// METHODS
static int debug() {
@@ -135,53 +136,6 @@ private:
m_modp->addStmtp(nodep);
}
}
virtual void visit(AstFor* nodep, AstNUser*) {
// So later optimizations don't need to deal with them,
// FOR(init,cond,assign,body) -> init,WHILE(cond) { body, assign }
AstNode* initsp = nodep->initsp(); if (initsp) initsp->unlinkFrBackWithNext();
AstNode* condp = nodep->condp(); if (condp) condp->unlinkFrBackWithNext();
AstNode* incsp = nodep->incsp(); if (incsp) incsp->unlinkFrBackWithNext();
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
bodysp = bodysp->addNext(incsp);
AstNode* newp = new AstWhile(nodep->fileline(),
condp,
bodysp);
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstRepeat* nodep, AstNUser*) {
// So later optimizations don't need to deal with them,
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
// Note var can be signed or unsigned based on original number.
AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), countp->width());
m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
countp);
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1)));
AstNode* condp;
if (countp->isSigned()) {
condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 0));
} else {
condp = new AstGt (nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 0));
}
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
bodysp = bodysp->addNext(decp);
AstNode* newp = new AstWhile(nodep->fileline(),
condp,
bodysp);
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline
@@ -199,6 +153,21 @@ private:
// any BEGINs, but V3Coverage adds them all under the module itself.
nodep->iterateChildren(*this);
}
// VISITORS - LINT CHECK
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
// Check IFDEPTH warning - could be in other transform files if desire
int prevIfDepth = m_ifDepth;
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
} else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) {
m_ifDepth = -1;
} else if (++m_ifDepth > v3Global.opt.ifDepth()) {
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
m_ifDepth = -1;
}
nodep->iterateChildren(*this);
m_ifDepth = prevIfDepth;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
@@ -208,6 +177,7 @@ public:
m_modp = NULL;
m_ftaskp = NULL;
m_repeatNum = 0;
m_ifDepth = 0;
nodep->accept(*this);
}
virtual ~BeginVisitor() {}
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+25 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -52,6 +52,7 @@ private:
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
static const int FLAG_LEAKED = 0x08; // Known to have been leaked
static const int FLAG_UNDER_NOW = 0x10; // Is in tree as parent of current node
public:
// METHODS
static void deleted(const AstNode* nodep) {
@@ -74,6 +75,15 @@ public:
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
}
}
static void setUnder(const AstNode* nodep, bool flag) {
// Called by BrokenCheckVisitor when each node entered/exited
if (!okIfLinkedTo(nodep)) return;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter!=s_nodes.end()) {
iter->second &= ~FLAG_UNDER_NOW;
if (flag) iter->second |= FLAG_UNDER_NOW;
}
}
static void addInTree(AstNode* nodep, bool linkable) {
#ifndef VL_LEAK_CHECKS
if (!linkable) return; // save some time, else the map will get huge!
@@ -111,6 +121,14 @@ public:
if (!(iter->second & FLAG_LINKABLE)) return false;
return true;
}
static bool okIfBelow(const AstNode* nodep) {
// Must be linked to and below current node
if (!okIfLinkedTo(nodep)) return false;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) return false;
if (!(iter->second & FLAG_UNDER_NOW)) return false;
return true;
}
static void prepForTree() {
#ifndef VL_LEAK_CHECKS
s_nodes.clear();
@@ -152,6 +170,10 @@ bool AstNode::brokeExists() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::okIfLinkedTo(this);
}
bool AstNode::brokeExistsAbove() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::okIfBelow(this);
}
//######################################################################
@@ -180,6 +202,7 @@ public:
class BrokenCheckVisitor : public AstNVisitor {
private:
virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::setUnder(nodep,true);
if (nodep->broken()) {
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)\n");
}
@@ -192,6 +215,7 @@ private:
}
}
nodep->iterateChildren(*this);
BrokenTable::setUnder(nodep,false);
}
public:
// CONSTUCTORS
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+6 -6
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2011 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.
@@ -77,7 +77,7 @@ private:
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
//
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize);
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
castp->width(needsize, nodep->widthMin());
relinkHandle.relink(castp);
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
@@ -97,13 +97,13 @@ private:
insertCast(nodep, castSize(nodep->backp()));
}
}
void insureLower32Cast(AstCast* nodep) {
void insureLower32Cast(AstCCast* nodep) {
// If we have uint64 = CAST(uint64(x)) then the upcasting
// really needs to be CAST(uint64(CAST(uint32(x))).
// Otherwise a (uint64)(a>b) would return wrong value, as
// less than has undeterministic signedness.
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
&& !nodep->lhsp()->castCast()) {
&& !nodep->lhsp()->castCCast()) {
insertCast(nodep->lhsp(), VL_WORDSIZE);
}
}
@@ -130,7 +130,7 @@ private:
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
}
virtual void visit(AstCast* nodep, AstNUser*) {
virtual void visit(AstCCast* nodep, AstNUser*) {
nodep->iterateChildren(*this);
insureLower32Cast(nodep);
nodep->user1(1);
@@ -149,7 +149,7 @@ private:
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->lvalue()
&& !nodep->backp()->castCast()
&& !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath()
&& nodep->backp()->width()
&& castSize(nodep) != castSize(nodep->varp())) {
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2011 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.
+19 -11
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -65,9 +65,9 @@ class CdcEitherVertex : public V3GraphVertex {
AstNode* m_nodep;
AstSenTree* m_srcDomainp;
AstSenTree* m_dstDomainp;
bool m_srcDomainSet;
bool m_dstDomainSet;
bool m_asyncPath;
bool m_srcDomainSet:1;
bool m_dstDomainSet:1;
bool m_asyncPath:1;
public:
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
@@ -109,11 +109,12 @@ public:
};
class CdcLogicVertex : public CdcEitherVertex {
bool m_hazard;
bool m_isFlop;
bool m_hazard:1;
bool m_isFlop:1;
public:
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
: CdcEitherVertex(graphp,scopep,nodep), m_hazard(false), m_isFlop(false)
: CdcEitherVertex(graphp,scopep,nodep)
, m_hazard(false), m_isFlop(false)
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
virtual ~CdcLogicVertex() {}
// Accessors
@@ -132,7 +133,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
private:
// NODE STATE
//Entire netlist:
// {statement}Node::user3p -> bool, indicating not hazard
// {statement}Node::user3 -> bool, indicating not hazard
ofstream* m_ofp; // Output file
string m_prefix;
@@ -290,9 +291,12 @@ private:
void setNodeHazard(AstNode* nodep) {
// Need to not clear if warnings are off (rather than when report it)
// as bypassing this warning may turn up another path that isn't warning off'ed.
// We can't modifyWarnOff here, as one instantiation might not be an issue until we find a hitting flop
// Furthermore, a module like a "Or" module would only get flagged once,
// even though the signals feeding it are radically different.
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
UINFO(9,"Set hazard "<<nodep<<endl);
UINFO(8,"Set hazard "<<nodep<<endl);
m_logicVertexp->setHazard(nodep);
}
}
@@ -335,7 +339,7 @@ private:
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
if (vvertexp->cntAsyncRst()) {
m_userGeneration++; // Effectively a userClearVertices()
UINFO(9, " Trace One async: "<<vvertexp<<endl);
UINFO(8, " Trace One async: "<<vvertexp<<endl);
// Twice, as we need to detect, then propagate
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
if (markp) { // Mark is non-NULL if something bad on this path
@@ -351,7 +355,8 @@ private:
}
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
// Return vertex of any hazardous stuff attached, or NULL if OK
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
vertexp->user(m_userGeneration);
@@ -642,6 +647,9 @@ private:
virtual void visit(AstAlways* nodep, AstNUser*) {
iterateNewStmt(nodep);
}
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// CDC doesn't care about public variables
}
virtual void visit(AstCFunc* nodep, AstNUser*) {
iterateNewStmt(nodep);
}
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+2 -3
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -128,8 +128,7 @@ private:
virtual void visit(AstVarScope* nodep, AstNUser*) {
if (nodep->isCircular()) {
UINFO(8," CIRC "<<nodep<<endl);
if (!nodep->user1()) {
nodep->user1(true);
if (!nodep->user1Inc()) {
genChangeDet(nodep);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+2 -3
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2008-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2008-2011 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.
@@ -704,8 +704,7 @@ class GaterVisitor : public GaterBaseVisitor {
virtual void visit(AstAlways* nodep, AstNUser*) {
if (debug()>=9) cout<<endl<<endl<<endl;
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
if (nodep->user4()) return;
nodep->user4(1);
if (nodep->user4Inc()) return;
clear();
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+30 -17
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2011 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.
@@ -60,7 +60,8 @@ class V3ConfigIgnores {
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
IgnLines::const_iterator m_lastEnd; // Point with end()
IgnFiles m_ignFiles; // Ignores for each filename
IgnFiles m_ignWilds; // Ignores for each wildcarded filename
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
@@ -68,13 +69,13 @@ class V3ConfigIgnores {
~V3ConfigIgnores() {}
// METHODS
inline IgnLines* findLines(const string& filename) {
IgnFiles::iterator it = m_ignFiles.find(filename);
if (it != m_ignFiles.end()) {
inline IgnLines* findWilds(const string& wildname) {
IgnFiles::iterator it = m_ignWilds.find(wildname);
if (it != m_ignWilds.end()) {
return &(it->second);
} else {
m_ignFiles.insert(make_pair(filename, IgnLines()));
it = m_ignFiles.find(filename);
m_ignWilds.insert(make_pair(wildname, IgnLines()));
it = m_ignWilds.find(wildname);
return &(it->second);
}
}
@@ -82,23 +83,35 @@ class V3ConfigIgnores {
// Given a filename, find all wildcard matches against it and build
// hash with the specific filename. This avoids having to wildmatch
// more than once against any filename.
IgnLines* linesp = findLines(filename);
m_lastIt = linesp->begin();
m_lastEnd = linesp->end();
IgnFiles::iterator it = m_ignFiles.find(filename);
if (it == m_ignFiles.end()) {
// Haven't seen this filename before
m_ignFiles.insert(make_pair(filename, IgnLines()));
it = m_ignFiles.find(filename);
// Make new list for this file of all matches
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
it->second.insert(*lit);
}
}
}
}
m_lastIt = it->second.begin();
m_lastEnd = it->second.end();
}
public:
inline static V3ConfigIgnores& singleton() { return s_singleton; }
void addIgnore(V3ErrorCode code, string filename, int lineno, bool on) {
void addIgnore(V3ErrorCode code, string wildname, int lineno, bool on) {
// Insert
IgnLines* linesp = findLines(filename);
UINFO(9,"config addIgnore "<<filename<<":"<<lineno<<", "<<code<<", "<<on<<endl);
IgnLines* linesp = findWilds(wildname);
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
linesp->insert(V3ConfigLine(code, lineno, on));
if (m_lastFilename == filename) {
// Flush the match cache, due to a change in the rules.
m_lastFilename = " ";
}
// Flush the match cache, due to a change in the rules.
m_ignFiles.clear();
m_lastFilename = " ";
}
inline void applyIgnores(FileLine* filelinep) {
// HOT routine, called each parsed token line
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2011 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.
+390 -213
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -93,17 +93,19 @@ public:
class ConstVisitor : public AstNVisitor {
private:
// NODE STATE
// ** only when m_warn/m_expensive is set. If state is needed other times,
// ** only when m_warn/m_doExpensive is set. If state is needed other times,
// ** must track down everywhere V3Const is called and make sure no overlaps.
// AstVar::user4p -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
// AstJumpLabel::user4 -> bool. Set when AstJumpGo uses this label
// STATE
bool m_params; // If true, propogate parameterized and true numbers only
bool m_required; // If true, must become a constant
bool m_wremove; // Inside scope, no assignw removal
bool m_warn; // Output warnings
bool m_cpp; // C++ conversions only
bool m_expensive; // Enable computationally expensive optimizations
bool m_doExpensive; // Enable computationally expensive optimizations
bool m_doNConst; // Enable non-constant-child simplifications
bool m_doV; // Verilog, not C++ conversion
AstNodeModule* m_modp; // Current module
AstNode* m_scopep; // Current scope
@@ -288,13 +290,61 @@ private:
// SEL(EXTEND(any,width,...),(width-1),0) -> ...
// Since select's return unsigned, this is always an extend
AstExtend* extendp = nodep->fromp()->castExtend();
return (!m_cpp
&& extendp
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
&& (int)nodep->widthConst()==extendp->lhsp()->width()
);
if (!(m_doV
&& extendp
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
&& (int)nodep->widthConst()==extendp->lhsp()->width()
)) return false;
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
return true;
}
bool operandSelBiLower(AstSel* nodep) {
// SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b))
// Add or any operation which doesn't care if we discard top bits
AstNodeBiop* bip = nodep->fromp()->castNodeBiop();
if (!(m_doV
&& bip
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
)) return false;
if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:");
AstNode* bilhsp = bip->lhsp()->unlinkFrBack();
AstNode* birhsp = bip->rhsp()->unlinkFrBack();
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
replaceWChild(nodep, bip); nodep=NULL;
return true;
}
bool operandBiExtendConst(AstNodeBiop* nodep) {
// Loop unrolling likes standalone compares
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
// Beware that the constant must have zero bits (+ 1 if signed) or compare
// would be incorrect
AstExtend* extendp = nodep->lhsp()->castExtend();
if (!extendp) return false;
AstNode* smallerp = extendp->lhsp();
int subsize = smallerp->width();
AstConst* constp = nodep->rhsp()->castConst();
if (!constp) return false;
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
//
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
smallerp->unlinkFrBack();
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
nodep->lhsp(smallerp);
constp->unlinkFrBack();
V3Number num (constp->fileline(), subsize);
num.opAssign(constp->num());
nodep->rhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); constp=NULL;
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
return true;
}
AstNode* afterComment(AstNode* nodep) {
@@ -723,7 +773,7 @@ private:
return true;
}
}
else if (!m_cpp && nodep->lhsp()->castConcat()) {
else if (m_doV && nodep->lhsp()->castConcat()) {
bool need_temp = false;
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
// Note only do this (need user4) when m_warn, which is
@@ -854,10 +904,10 @@ private:
// Run it - may be unoptimizable due to large for loop, etc
simvis.mainParamEmulate(nodep);
if (!simvis.optimizable()) {
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
<<nodep->prettyTypeName()<<endl
<<V3Error::msgPrefix()<<errorp->fileline()<<"... Location of non-constant "
<<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
replaceZero(nodep); nodep=NULL;
} else {
@@ -1059,16 +1109,50 @@ private:
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceSelIntoBiop(AstSel* nodep) {
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
if (!fromp) nodep->v3fatalSrc("Called on non biop");
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->rhsp(new AstSel(nodep->fileline(),
birhsp, lsbp, widthp));
fromp->widthSignedFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
void replaceSelIntoUniop(AstSel* nodep) {
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop();
if (!fromp) nodep->v3fatalSrc("Called on non biop");
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->widthSignedFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
bool did=false;
if (!m_cpp && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
nodep->varp()->valuep()->iterateAndNext(*this);
if (operandConst(nodep->varp()->valuep())
&& !nodep->lvalue()
&& ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations
&& ((!m_params // Can reduce constant wires into equations
&& m_doNConst
&& v3Global.opt.oConst()
&& !nodep->varp()->isSigPublic())
|| nodep->varp()->isParam())) {
AstConst* constp = nodep->varp()->valuep()->castConst();
@@ -1105,7 +1189,7 @@ private:
// Someday if lower is constant, convert to quoted "string".
virtual void visit(AstAttrOf* nodep, AstNUser*) {
// Don't iterate children, don't want to loose VarRef.
// Don't iterate children, don't want to lose VarRef.
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
@@ -1120,8 +1204,9 @@ private:
}
virtual void visit(AstSenItem* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->sensp()->castConst()
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
if (m_doNConst
&& (nodep->sensp()->castConst()
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
// Constants in sensitivity lists may be removed (we'll simplify later)
if (nodep->isClocked()) { // A constant can never get a pos/negexge
if (onlySenItemInSenTree(nodep)) {
@@ -1134,7 +1219,7 @@ private:
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
nodep->deleteTree(); nodep=NULL;
}
} else if (nodep->sensp()->castNot()) {
} else if (m_doNConst && nodep->sensp()->castNot()) {
// V3Gate may propagate NOTs into clocks... Just deal with it
AstNode* sensp = nodep->sensp();
AstNode* lastSensp = sensp;
@@ -1201,7 +1286,7 @@ private:
virtual void visit(AstSenTree* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_expensive) {
if (m_doExpensive) {
//cout<<endl; nodep->dumpTree(cout,"ssin: ");
// Optimize ideas for the future:
// SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b))
@@ -1304,22 +1389,21 @@ private:
// Zero elimination
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
nodep->iterateChildren(*this);
replaceNodeAssign(nodep);
if (m_doNConst && replaceNodeAssign(nodep)) return;
}
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
// Don't perform any optimizations, keep the alias around
}
virtual void visit(AstAssignW* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (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
if (m_wremove
if (m_wremove && !m_params && m_doNConst
&& m_modp && operandConst(nodep->rhsp())
&& !nodep->rhsp()->castConst()->num().isFourState()
&& varrefp // Don't do messes with BITREFs/ARRAYREFs
&& !varrefp->varp()->valuep() // Not already constified
&& !varrefp->varScopep() // Not scoped (or each scope may have different initial value)
&& !m_params) {
&& !varrefp->varScopep()) { // Not scoped (or each scope may have different initial value)
// ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) )
UINFO(4,"constAssignW "<<nodep<<endl);
// Make a initial assignment
@@ -1339,77 +1423,79 @@ private:
virtual void visit(AstNodeIf* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (AstConst* constp = nodep->condp()->castConst()) {
AstNode* keepp = NULL;
if (constp->isZero()) {
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
keepp = nodep->elsesp();
} else {
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
keepp = nodep->ifsp();
if (m_doNConst) {
if (AstConst* constp = nodep->condp()->castConst()) {
AstNode* keepp = NULL;
if (constp->isZero()) {
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
keepp = nodep->elsesp();
} else {
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
keepp = nodep->ifsp();
}
if (keepp) {
keepp->unlinkFrBackWithNext();
nodep->replaceWith(keepp);
} else {
nodep->unlinkFrBack();
}
nodep->deleteTree(); nodep=NULL;
}
if (keepp) {
keepp->unlinkFrBackWithNext();
nodep->replaceWith(keepp);
} else {
nodep->unlinkFrBack();
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
// Empty block, remove it
// Note if we support more C++ then there might be side effects in the condition itself
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
else if (!afterComment(nodep->ifsp())) {
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
AstNode* condp = nodep->condp();
AstNode* elsesp = nodep->elsesp();
condp->unlinkFrBackWithNext();
elsesp->unlinkFrBackWithNext();
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
nodep->addIfsp(elsesp);
}
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|| (nodep->condp()->castLogNot()))
&& nodep->ifsp() && nodep->elsesp()) {
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (ifSameAssign(nodep)) {
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
ifp->unlinkFrBack();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* truep = ifp->rhsp()->unlinkFrBack();
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
ifp->rhsp(new AstCond(truep->fileline(),
condp, truep, falsep));
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
&& operandIfIf(nodep)) {
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
condp, lowerCondp));
lowerIfp->replaceWith(lowerIfsp);
lowerIfp->deleteTree(); lowerIfp=NULL;
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
}
nodep->deleteTree(); nodep=NULL;
}
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
// Empty block, remove it
// Note if we support more C++ then there might be side effects in the condition itself
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
else if (!afterComment(nodep->ifsp())) {
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
AstNode* condp = nodep->condp();
AstNode* elsesp = nodep->elsesp();
condp->unlinkFrBackWithNext();
elsesp->unlinkFrBackWithNext();
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
nodep->addIfsp(elsesp);
}
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|| (nodep->condp()->castLogNot()))
&& nodep->ifsp() && nodep->elsesp()) {
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (ifSameAssign(nodep)) {
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
ifp->unlinkFrBack();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* truep = ifp->rhsp()->unlinkFrBack();
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
ifp->rhsp(new AstCond(truep->fileline(),
condp, truep, falsep));
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
&& operandIfIf(nodep)) {
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
condp, lowerCondp));
lowerIfp->replaceWith(lowerIfsp);
lowerIfp->deleteTree(); lowerIfp=NULL;
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
}
}
@@ -1422,7 +1508,7 @@ private:
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
if (argp->castConst()) { anyconst=true; break; }
}
if (anyconst) {
if (m_doNConst && anyconst) {
//UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
string fmt = "";
@@ -1485,13 +1571,16 @@ private:
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->condp()->isZero()) {
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
if (m_doNConst) {
if (nodep->condp()->isZero()) {
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
}
}
}
@@ -1499,6 +1588,38 @@ private:
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
virtual void visit(AstNodePreSel* nodep, AstNUser*) {}
// Ignored, can eliminate early
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_doNConst) {
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
}
//-----
// Jump elimination
virtual void visit(AstJumpGo* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_doExpensive) { nodep->labelp()->user4(true); }
}
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
// Because JumpLabels disable many optimizations,
// remove JumpLabels that are not pointed to by any AstJumpGos
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
nodep->iterateChildren(*this);
// AstJumpGo's below here that point to this node will set user4
if (m_doExpensive && !nodep->user4()) {
UINFO(4,"JUMPLABEL => unused "<<nodep<<endl);
AstNode* underp = NULL;
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
if (underp) nodep->replaceWith(underp);
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
}
}
//-----
// Below lines are magic expressions processed by astgen
// "AstNODETYPE { # bracket not paren
@@ -1520,78 +1641,81 @@ private:
// Lint Checks
// v--- *1* These ops are always first, as we warn before replacing
// v--- *V* This op is a verilog op, ignore when in m_cpp mode
// v--- *V* This op is a verilog op, only in m_doV mode
// v--- *C* This op works on all constant children, allowed in m_doConst mode
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
// Generic constants on both side. Do this first to avoid other replacements
TREEOP("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
TREEOP("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
// Zero on one side or the other
TREEOP("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
// Non-zero on one side or the other
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
TREEOP("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
TREEOP("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
TREEOP("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
TREEOP("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
TREEOP ("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
TREEOP ("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
TREEOP ("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP ("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP ("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
// Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
TREEOP("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
TREEOP("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
TREEOP("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a|b
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
TREEOP("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a|b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
// v--- *1* as These ops are always first, as we warn before replacing
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
@@ -1640,33 +1764,40 @@ private:
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
// Compress out EXTENDs to appease loop unroller
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
// Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon
TREEOP("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP ("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP ("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP ("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP ("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
///=== Verilog operators
// Comparison against 1'b0/1'b1; must be careful about widths.
// These use Not, so must be Verilog only
@@ -1717,18 +1848,33 @@ private:
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
// Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy.
TREEOPV("AstSel{operandSelExtend(nodep)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())");
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
TREEOPV("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
TREEOPV("AstSel{$fromp.castAdd, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
// V3Tristate requires selects below BufIf1.
// Also do additional operators that are bit-independent, but only definite
// win if bit select is a constant (otherwise we may need to compute bit index several times)
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
// Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
// Strings
TREEOP ("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
// Possible futures:
@@ -1755,15 +1901,37 @@ private:
}
public:
// Processing Mode Enum
enum ProcMode {
PROC_PARAMS,
PROC_LIVE,
PROC_V_WARN,
PROC_V_NOWARN,
PROC_V_EXPENSIVE,
PROC_CPP
};
// CONSTUCTORS
ConstVisitor(bool params, bool expensive, bool warn, bool cpp) {
m_params = params; m_required = params;
m_expensive = expensive;
m_warn = warn;
m_cpp = cpp;
m_wremove = true;
ConstVisitor(ProcMode pmode) {
m_params = false;
m_required = false;
m_doExpensive = false;
m_doNConst = false;
m_doV = false;
m_warn = false;
m_wremove = true; // Overridden in visitors
m_modp = NULL;
m_scopep = NULL;
//
switch (pmode) {
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
case PROC_LIVE: break;
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
case PROC_V_EXPENSIVE: m_doV = true; m_doNConst = true; m_doExpensive = true; break;
case PROC_CPP: m_doV = false; m_doNConst = true; break;
default: v3fatalSrc("Bad case"); break;
}
}
virtual ~ConstVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
@@ -1780,7 +1948,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
// Resize even if the node already has a width, because burried in the treee we may
// have a node we just created with signing, etc, that isn't sized yet.
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
ConstVisitor visitor (true,false,false,false);
ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
if (AstVar* varp=nodep->castVar()) {
// If a var wants to be constified, it's really a param, and
// we want the value to be constant. We aren't passed just the
@@ -1794,34 +1962,43 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
return nodep;
}
void V3Const::constifyAll(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,true,false,false);
(void)visitor.mainAcceptEdit(nodep);
}
void V3Const::constifyAllLint(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,false,true,false);
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep);
}
void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,false,false,true);
ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep);
}
AstNode* V3Const::constifyEdit(AstNode* nodep) {
ConstVisitor visitor (false,false,false,false);
ConstVisitor visitor (ConstVisitor::PROC_V_NOWARN);
nodep = visitor.mainAcceptEdit(nodep);
return nodep;
}
void V3Const::constifyAllLive(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
// This only pushes constants up, doesn't make any other edits
// IE doesn't prune dead statements, as we need to do some usability checks after this
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep);
}
void V3Const::constifyAll(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep);
}
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
ConstVisitor visitor (false,true,false,false);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
nodep = visitor.mainAcceptEdit(nodep);
return nodep;
}
+3 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -34,6 +34,8 @@ public:
// Force this cell node's parameter list to become a constant
// Return new node that may have replaced nodep
static AstNode* constifyParamsEdit(AstNode* nodep);
// Only do constant pushing, without removing dead logic
static void constifyAllLive(AstNetlist* nodep);
// Everything that's possible
static void constifyAll(AstNetlist* nodep);
// Also, warn
+7 -5
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -81,10 +81,12 @@ private:
string prettyName = nodep->prettyName();
if (!nodep->isToggleCoverable())
return "Not relevant signal type";
if (prettyName.c_str()[0] == '_')
return "Leading underscore";
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
if (!v3Global.opt.coverageUnderscore()) {
if (prettyName.c_str()[0] == '_')
return "Leading underscore";
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";
}
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
// We allow this, though tracing doesn't
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+9 -12
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -95,31 +95,31 @@ private:
// VISITORS
virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->modp()->user1(nodep->modp()->user1() + 1);
nodep->modp()->user1Inc();
}
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->varScopep()) {
nodep->varScopep()->user1(nodep->varScopep()->user1() + 1);
nodep->varScopep()->varp()->user1(nodep->varScopep()->varp()->user1() + 1);
nodep->varScopep()->user1Inc();
nodep->varScopep()->varp()->user1Inc();
}
if (nodep->varp()) {
nodep->varp()->user1(nodep->varp()->user1() + 1);
nodep->varp()->user1Inc();
}
if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstVarScope* nodep, AstNUser*) {
@@ -145,13 +145,10 @@ private:
nodep->lhsp()->iterateAndNext(*this);
}
}
virtual void visit(AstUCFunc* nodep, AstNUser*) {
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
nodep->iterateChildren(*this);
}
//-----
virtual void visit(AstNode* nodep, AstNUser*) {
if (nodep->isOutputter()) m_sideEffect=true;
nodep->iterateChildren(*this);
}
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+2 -4
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -345,9 +345,7 @@ private:
m_nextDlyp = NULL;
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->user2()) { // Not done yet
nodep->user2(true);
if (!nodep->user2Inc()) { // Not done yet
if (m_inDly && nodep->lvalue()) {
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
markVarUsage(nodep->varScopep(), VU_DLY);
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+20 -7
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -149,6 +149,8 @@ public:
if (decind) ofp()->blockDec();
if (!m_suppressSemi) puts(";\n");
}
virtual void visit(AstAlwaysPublic*, AstNUser*) {
}
virtual void visit(AstCCall* nodep, AstNUser*) {
puts(nodep->hiername());
puts(nodep->funcp()->name());
@@ -360,12 +362,22 @@ public:
puts(")); }\n");
}
}
virtual void visit(AstJumpGo* nodep, AstNUser*) {
puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n");
}
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
puts("{\n");
nodep->stmtsp()->iterateAndNext(*this);
puts("}\n");
puts("__Vlabel"+cvtToStr(nodep->labelNum())+": ;\n");
}
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->precondsp()->iterateAndNext(*this);
puts("while (");
nodep->condp()->iterateAndNext(*this);
puts(") {\n");
nodep->bodysp()->iterateAndNext(*this);
nodep->incsp()->iterateAndNext(*this);
nodep->precondsp()->iterateAndNext(*this); // Need to recompute before next loop
puts("}\n");
}
@@ -463,7 +475,7 @@ public:
}
visit(nodep->castNodeBiop(), vup);
}
virtual void visit(AstCast* nodep, AstNUser*) {
virtual void visit(AstCCast* nodep, AstNUser*) {
// Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) {
puts("(QData)(");
@@ -531,17 +543,18 @@ public:
}
for (int word=VL_WORDS_I(nodep->num().minWidth())-1; word>0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", (long long)(nodep->num().dataWord(word)));
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
}
ofp()->printf(",0x%08" VL_PRI64 "x)", (long long)(nodep->num().dataWord(0)));
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
} else if (nodep->isQuad()) {
vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", (long long)num);
else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", (long long)num);
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", num);
} else {
uint32_t num = nodep->toUInt();
// Only 32 bits - llx + long long here just to appease CPP format warning
if (num<10) puts(cvtToStr(num));
else ofp()->printf("0x%" VL_PRI64 "x", (long long)num);
else ofp()->printf("0x%" VL_PRI64 "x", (vluint64_t)num);
//Unneeded-Causes %lx format warnings:
// if (!nodep->num().isSigned() && (num & (1UL<<31))) puts("U");
}
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -8,7 +8,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
+142 -7
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2011 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.
@@ -45,13 +45,24 @@ class EmitCSyms : EmitCBaseVisitor {
AstUser1InUse m_inuser1;
// TYPES
struct ScopeNameData { string m_symName; string m_prettyName;
ScopeNameData(const string& symName, const string& prettyName)
: m_symName(symName), m_prettyName(prettyName) {}
};
struct ScopeFuncData { AstScopeName* m_scopep; AstCFunc* m_funcp; AstNodeModule* m_modp;
ScopeFuncData(AstScopeName* scopep, AstCFunc* funcp, AstNodeModule* modp)
: m_scopep(scopep), m_funcp(funcp), m_modp(modp) {}
};
struct ScopeVarData { string m_scopeName; string m_varBasePretty; AstVar* m_varp;
AstNodeModule* m_modp; AstScope* m_scopep;
ScopeVarData(const string& scopeName, const string& varBasePretty, AstVar* varp, AstNodeModule* modp, AstScope* scopep)
: m_scopeName(scopeName), m_varBasePretty(varBasePretty), m_varp(varp), m_modp(modp), m_scopep(scopep) {}
};
typedef map<string,ScopeFuncData> ScopeFuncs;
typedef map<string,AstScopeName*> ScopeNames;
typedef map<string,ScopeVarData> ScopeVars;
typedef map<string,ScopeNameData> ScopeNames;
typedef pair<AstScope*,AstNodeModule*> ScopeModPair;
typedef pair<AstNodeModule*,AstVar*> ModVarPair;
struct CmpName {
inline bool operator () (const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
return lhsp.first->name() < rhsp.first->name();
@@ -71,10 +82,13 @@ class EmitCSyms : EmitCBaseVisitor {
AstNodeModule* m_modp; // Current module
vector<ScopeModPair> m_scopes; // Every scope by module
vector<AstCFunc*> m_dpis; // DPI functions
vector<ModVarPair> m_modVars; // Each public {mod,var}
ScopeNames m_scopeNames; // Each unique AstScopeName
ScopeFuncs m_scopeFuncs; // Each {scope,dpiexportfunc}
ScopeFuncs m_scopeFuncs; // Each {scope,dpi-export-func}
ScopeVars m_scopeVars; // Each {scope,public-var}
V3LanguageWords m_words; // Reserved word detector
int m_coverBins; // Coverage bin number
int m_labelNum; // Next label number
// METHODS
void emitSymHdr();
@@ -94,10 +108,65 @@ class EmitCSyms : EmitCBaseVisitor {
}
}
void varsExpand() {
// We didn'e have all m_scopes loaded when we encountered variables, so expand them now
// It would be less code if each module inserted its own variables.
// Someday. For now public isn't common.
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* smodp = it->second;
for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
AstNodeModule* modp = it->first;
if (modp == smodp) {
AstVar* varp = it->second;
// Need to split the module + var name into the original-ish full scope and variable name under that scope.
// The module instance name is included later, when we know the scopes this module is under
string whole = scopep->name()+"__DOT__"+varp->name();
string scpName;
string varBase;
if (whole.substr(0,10) == "__DOT__TOP") whole.replace(0,10,"");
string::size_type pos = whole.rfind("__DOT__");
if (pos != string::npos) {
scpName = whole.substr(0,pos);
varBase = whole.substr(pos+strlen("__DOT__"));
} else {
varBase = whole;
}
//UINFO(9,"For "<<scopep->name()<<" - "<<varp->name()<<" Scp "<<scpName<<" Var "<<varBase<<endl);
string varBasePretty = AstNode::prettyName(varBase);
string scpPretty = AstNode::prettyName(scpName);
string scpSym;
{
string out = scpName;
string::size_type pos;
while ((pos=out.find("__PVT__")) != string::npos) {
out.replace(pos, 7, "");
}
if (out.substr(0,10) == "TOP__DOT__") out.replace(0,10,"");
if (out.substr(0,4) == "TOP.") out.replace(0,4,"");
while ((pos=out.find(".")) != string::npos) {
out.replace(pos, 1, "__");
}
while ((pos=out.find("__DOT__")) != string::npos) {
out.replace(pos, 7, "__");
}
scpSym = out;
}
//UINFO(9," scnameins sp "<<scpName<<" sp "<<scpPretty<<" ss "<<scpSym<<endl);
if (m_scopeNames.find(scpSym) == m_scopeNames.end()) {
m_scopeNames.insert(make_pair(scpSym, ScopeNameData(scpSym, scpPretty)));
}
m_scopeVars.insert(make_pair(scpSym + " " + varp->name(),
ScopeVarData(scpSym, varBasePretty, varp, modp, scopep)));
}
}
}
}
// VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) {
// Collect list of scopes
nodep->iterateChildren(*this);
varsExpand();
// Sort by names, so line/process order matters less
sort(m_scopes.begin(), m_scopes.end(), CmpName());
@@ -114,6 +183,7 @@ class EmitCSyms : EmitCBaseVisitor {
virtual void visit(AstNodeModule* nodep, AstNUser*) {
nameCheck(nodep);
m_modp = nodep;
m_labelNum = 0;
nodep->iterateChildren(*this);
m_modp = NULL;
}
@@ -123,8 +193,9 @@ class EmitCSyms : EmitCBaseVisitor {
}
virtual void visit(AstScopeName* nodep, AstNUser*) {
string name = nodep->scopeSymName();
//UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettyName()<<" ss "<<name<<endl);
if (m_scopeNames.find(name) == m_scopeNames.end()) {
m_scopeNames.insert(make_pair(name, nodep));
m_scopeNames.insert(make_pair(name, ScopeNameData(name, nodep->scopePrettyName())));
}
if (nodep->dpiExport()) {
if (!m_funcp) nodep->v3fatalSrc("ScopeName not under DPI function");
@@ -132,12 +203,22 @@ class EmitCSyms : EmitCBaseVisitor {
ScopeFuncData(nodep, m_funcp, m_modp)));
}
}
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->isSigUserRdPublic()) {
m_modVars.push_back(make_pair(m_modp, nodep));
}
}
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
// Assign numbers to all bins, so we know how big of an array to use
if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for
nodep->binNum(m_coverBins++);
}
}
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
nodep->labelNum(++m_labelNum);
nodep->iterateChildren(*this);
}
virtual void visit(AstCFunc* nodep, AstNUser*) {
if (nodep->dpiImport() || nodep->dpiExportWrapper()) {
m_dpis.push_back(nodep);
@@ -160,6 +241,7 @@ public:
m_funcp = NULL;
m_modp = NULL;
m_coverBins = 0;
m_labelNum = 0;
nodep->accept(*this);
}
};
@@ -248,7 +330,7 @@ void EmitCSyms::emitSymHdr() {
puts("\n// SCOPE NAMES\n");
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
puts("VerilatedScope __Vscope_"+it->second->scopeSymName()+";\n");
puts("VerilatedScope __Vscope_"+it->second.m_symName+";\n");
}
puts("\n// CREATORS\n");
@@ -338,8 +420,8 @@ void EmitCSyms::emitSymImp() {
puts("// Setup scope names\n");
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
puts("__Vscope_"+it->second->scopeSymName()+".configure(this,name(),");
putsQuoted(it->second->scopePrettyName());
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
putsQuoted(it->second.m_prettyName);
puts(");\n");
}
@@ -360,6 +442,59 @@ void EmitCSyms::emitSymImp() {
puts("));\n");
}
}
// It would be less code if each module inserted its own variables.
// Someday. For now public isn't common.
for (ScopeVars::iterator it = m_scopeVars.begin(); it != m_scopeVars.end(); ++it) {
AstNodeModule* modp = it->second.m_modp;
AstScope* scopep = it->second.m_scopep;
AstVar* varp = it->second.m_varp;
//
int dim=0;
string bounds;
if (AstBasicDType* basicp = varp->basicp()) {
// Range is always first, it's not in "C" order
if (basicp->rangep()) {
bounds += " ,"; bounds += cvtToStr(basicp->rangep()->msbConst());
bounds += ","; bounds += cvtToStr(basicp->rangep()->lsbConst());
dim++;
}
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
bounds += " ,"; bounds += cvtToStr(adtypep->arrayp()->msbConst());
bounds += ","; bounds += cvtToStr(adtypep->arrayp()->lsbConst());
dim++;
dtypep = adtypep->dtypep();
}
else break; // AstBasicDType - nothing below, 1
}
}
//
if (dim>2) {
puts("//UNSUP "); // VerilatedImp can't deal with >2d arrays
}
puts("__Vscope_"+it->second.m_scopeName+".varInsert(__Vfinal,");
putsQuoted(it->second.m_varBasePretty);
puts(", &(");
if (modp->isTop()) {
puts(scopep->nameDotless());
puts("p->");
} else {
puts(scopep->nameDotless());
puts(".");
}
puts(varp->name());
puts("), ");
puts(varp->vlEnumType()); // VLVT_UINT32 etc
puts(",");
puts(varp->vlEnumDir()); // VLVD_IN etc
if (varp->isSigUserRWPublic()) puts("|VLVF_PUB_RW");
else if (varp->isSigUserRdPublic()) puts("|VLVF_PUB_RD");
puts(",");
puts(cvtToStr(dim));
puts(bounds);
puts(");\n");
}
puts("}\n");
}
+1 -1
View File
@@ -7,7 +7,7 @@
//
//*************************************************************************
//
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2011 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.

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