Compare commits

..
226 Commits
Author SHA1 Message Date
Wilson Snyder 2433848408 Version bump - changelog 2012-12-01 16:38:21 -05:00
Wilson Snyder e602f7febc Version bump 2012-12-01 16:15:40 -05:00
Wilson Snyder f607b32938 Fix crash on dotted references into dead modules, bug583. 2012-11-30 06:57:36 -05:00
Wilson Snyder c7a088faa5 Fix mis-optimized identical submodule subtract, bug581. Take 2. 2012-11-28 20:18:41 -05:00
Wilson Snyder 30f6c0e105 Fix mis-optimized identical submodule subtract, bug581. 2012-11-28 07:36:47 -05:00
Wilson Snyder 38b9fa7b93 driver: Print message when no Parallel::Forker. 2012-11-21 07:09:29 -05:00
Jeremy Bennett 39a31fc17f Fix --debug overriding preceding --dump-treei, bug580.
Signed-off-by: Wilson Snyder <[email protected]>
2012-11-21 06:55:28 -05:00
Wilson Snyder 899a7df14a Fix VerilatedSave compile issue on MSVCC, bug577. 2012-11-13 20:36:20 -05:00
Wilson Snyder 7a8c425103 Add +1364-1995ext and similar language options, bug532. 2012-11-13 20:12:23 -05:00
Wilson Snyder 0e8ce59022 Fix svdpi compile issue on MSVCC, bug571. 2012-11-05 10:22:19 -05:00
Wilson Snyder 77ac76a158 devel release 2012-11-03 20:19:31 -04:00
Wilson Snyder 8108b97050 Version bump 2012-11-03 20:16:01 -04:00
Wilson Snyder a1c3491dea Display speed ups, bug574. 2012-11-03 20:11:53 -04:00
Wilson Snyder 8bba96a84e Tests 2012-11-03 09:23:34 -04:00
Wilson Snyder 6cd9b25a53 Fix array of struct references giving false error, bug566. 2012-11-03 09:17:42 -04:00
Wilson Snyder 0431b1909c Fix name collision on task inputs, bug569. 2012-11-03 08:01:19 -04:00
Wilson Snyder 907665e2e8 Fix name collision on unnamed blocks, bug567. 2012-11-02 20:30:47 -04:00
Wilson Snyder 61e8836fbd Add -x-initial-edge, bug570. by Jeremy Bennett; from BENNETT/initial-edge branch. 2012-11-02 19:55:34 -04:00
Wilson Snyder 0e921b5dff Speed display, bug373. 2012-11-02 17:54:14 -04:00
Wilson Snyder 7ef37d6e17 Fix missing var access functions when no DPI, bug572. 2012-10-30 03:02:35 -04:00
Wilson Snyder dce227684a Fix mangling on GCC 4.7, msg927. 2012-10-28 17:35:48 -04:00
Wilson Snyder 158e112752 Internals: Resolve misc bison comments with Verilog-Perl. No functional change. 2012-10-08 21:20:13 -04:00
Wilson Snyder ec992c7f5e Internals: Resolve misc bison comments with Verilog-Perl 2012-10-08 20:45:39 -04:00
Wilson Snyder e7d63c7644 Fix large shift error on large shift constants. 2012-10-08 07:05:54 -04:00
Wilson Snyder 6464e8fee6 Misc code cleanups. Merge from assignment pattern branch. No functional change. 2012-09-25 19:27:00 -04:00
Wilson Snyder 047d66a657 Slice code cleanup. No functional change. 2012-09-25 19:17:57 -04:00
Wilson Snyder 55c23360d9 Commentary 2012-09-24 18:28:19 -04:00
Wilson Snyder c378d32c85 Fix parameter pins interspersed with cells broke in 3.840. 2012-09-07 19:51:41 -04:00
Wilson Snyder 3d9540c58c devel release 2012-09-03 20:32:32 -04:00
Wilson Snyder 39724eb916 Version bump 2012-09-03 20:03:25 -04:00
Jeremy Bennett 48dddd4ae7 Debug: Use dot label rather than a custom nTITLE node to label the graph. Generate all graph level attributes as attributes of the graph entity. bug555.
Signed-off-by: Wilson Snyder <[email protected]>
2012-08-27 19:02:27 -04:00
Wilson Snyder 9c00fd10de Add --savable to support model save/restore. 2012-08-26 21:19:43 -04:00
Jeremy Bennett 9309d0b00f Commentary on internals.pod, bug554.
Signed-off-by: Wilson Snyder <[email protected]>
2012-08-25 12:47:59 -04:00
Wilson Snyder 038b5d32a3 Commentary 2012-08-25 12:18:06 -04:00
Jeremy Bennett 706920ba19 Tests: t_vpi_var: Fix vector length, bug553.
Signed-off-by: Wilson Snyder <[email protected]>
2012-08-25 12:05:08 -04:00
Jeremy Bennett 39492a0726 Tidy up .gitignore and MANIFEST.SKIP, bug552.
Signed-off-by: Wilson Snyder <[email protected]>
2012-08-25 07:52:07 -04:00
Wilson Snyder df1170fea9 Test 2012-08-23 13:26:12 -04:00
Wilson Snyder f0e1d204fa Fix triangle symbol resolution error broke in 3.840, bug550.
This requires the parse symbol table persist across all parse runs. This is
probably more correct than before, but may result in some fallout if people
relied on data types not being persistant across separately parsed cells.
2012-08-15 21:28:30 -04:00
Wilson Snyder 8ece0a8a5f Create V3ParseSym. No functional change. 2012-08-15 21:14:20 -04:00
Wilson Snyder 1373b81e7c Include: Allow external progs to test command args 2012-08-14 20:37:15 -04:00
Wilson Snyder d3601dd561 Support '{} assignment pattern on structures, part of bug355. 2012-08-12 15:15:21 -04:00
Wilson Snyder f685cf1d0c Fix duplicate begin error broke in 3.840, bug548. 2012-08-10 19:39:18 -04:00
Wilson Snyder d5fcf0c153 Test for bug349 2012-08-08 22:15:07 -04:00
Wilson Snyder 5f9810070d Fix imports under multiple instantiated cells, bug542. 2012-08-08 21:59:17 -04:00
Wilson Snyder 923efa004b New tests 2012-08-07 20:59:34 -04:00
Wilson Snyder 869e8eab3c tests; check package to package refs 2012-08-07 20:37:28 -04:00
Wilson Snyder b51d197117 Fix defparam in generate broke in 3.840, bug543. 2012-08-07 18:24:51 -04:00
Wilson Snyder e4f0a8952c Fix double-deep parameter cell WIDTHs, bug541. 2012-08-02 07:02:57 -04:00
Wilson Snyder 072ee425f4 Fix previous mis-commit 2012-08-02 07:00:12 -04:00
Wilson Snyder a4c2819be2 Commentary 2012-07-31 19:23:19 -04:00
Wilson Snyder 2a274f9c19 Devel version 2012-07-31 18:53:51 -04:00
Wilson Snyder b4d5a20670 Version bump 2012-07-31 18:09:00 -04:00
Wilson Snyder 6339159b04 MAJOR: Support packed structures and unions, bug181. 2012-07-29 10:16:20 -04:00
Wilson Snyder aec019991c Tests: Misc fixes from struct branch. 2012-07-28 14:05:30 -04:00
Wilson Snyder 33e6a17747 Internals: Look at tree state instead of back for AstAttr. No functional change. 2012-07-28 10:52:29 -04:00
Wilson Snyder ecf508ec23 Fix replicate verilog dump being backwards 2012-07-28 08:25:27 -04:00
Wilson Snyder a5bcfc0509 Tests: Rename t_structure 2012-07-27 21:14:13 -04:00
Wilson Snyder 1899096ff4 Internals: Width debug and null print check 2012-07-27 21:12:06 -04:00
Wilson Snyder 6e219f5831 Internals: Rework V3WidthSel func for non-vars. No functional change intended. 2012-07-25 07:26:41 -04:00
Jeremy Bennett de1bb5aeb6 Tests: fix driver.pl not tracing time 0, bug536.
Signed-off-by: Wilson Snyder <[email protected]>
2012-07-24 18:48:51 -04:00
Wilson Snyder b52d94273c Internals: Move variable referencing into LinkDot in support of structs. 2012-07-24 06:26:35 -04:00
Wilson Snyder e655c85489 Internals: findBit etc can be const. No functional change. 2012-07-23 21:29:53 -04:00
Wilson Snyder dee7210231 Debug: add GDB dtf function to dump tree to file 2012-07-23 20:21:04 -04:00
Wilson Snyder cbd073ed08 Commentary: pthread 2012-07-23 10:12:43 -04:00
Wilson Snyder 09ebc0c163 Internals: Fix 0x tree debug suffix. Misc merges from struct. No functional change. 2012-07-22 22:48:39 -04:00
Wilson Snyder d2ede75c71 Fix compile error under git submodules, bug534. 2012-07-22 19:51:14 -04:00
Wilson Snyder 3e03fef3e3 Tests: Add t_var_notfound_bad 2012-07-22 09:09:53 -04:00
Wilson Snyder 0f583f4b33 Internals: Remove dead varref code, part of last change. 2012-07-21 21:23:57 -04:00
Wilson Snyder f175db74a5 Internals: Rework implicit handling to make room for ParseRef vs. VarRef 2012-07-21 21:18:07 -04:00
Wilson Snyder 8d5e37a413 Internals: Move trace check up. No functional change. 2012-07-21 20:33:24 -04:00
Wilson Snyder 8b9b7178a2 Internals: MAJOR CHANGE. Combine V3Link and V3LinkDot stages for structures.
Functionality should be similar, but may introduce instability in resolving variables/cells.
Final merge from dot.
2012-07-21 17:12:42 -04:00
Wilson Snyder a2f49063e2 Internals: Rename LinkDot methods. Merge from dot. No functional change 2012-07-21 09:27:57 -04:00
Wilson Snyder f3f34baa73 debug: Avoid identical skip in driver debug 2012-07-21 09:16:19 -04:00
Wilson Snyder abe9ecd225 Internals: Move AstBegin code below GenFor. No functional change. 2012-07-21 07:28:39 -04:00
Wilson Snyder 67409af38d Fix valgrind uninitialized bits. 2012-07-19 22:26:15 -04:00
Wilson Snyder b7d1c34aa6 Internals: Add more sym table debug, renames. Merge from dot. No functional change 2012-07-19 21:18:39 -04:00
Wilson Snyder 92809b95c9 driver: Sort results. Merge from dot. 2012-07-19 21:02:36 -04:00
Wilson Snyder b18690cbe2 Linking renames. Merge from dot. No functional change. 2012-07-17 21:29:10 -04:00
Wilson Snyder 96155365b2 Fix GCC 4.7.0 compile warnings, bug530. 2012-07-15 12:27:36 -04:00
Wilson Snyder 3e5067feb1 Fix svdpi.h for apple. 2012-07-15 11:33:27 -04:00
Wilson Snyder 3ec687a0cf Internals: Merge from struct branch, rework LinkDot symbol table. No functional change intended. 2012-06-20 06:13:28 -04:00
Wilson Snyder 365034d7dd Internals: Merge from struct branch, rename SymTable calls. No functional change intended. 2012-06-20 06:09:07 -04:00
Wilson Snyder 09aa9f87d8 Internals: Move initial resolution to V3LinkParse. No functional change intended. 2012-06-13 23:08:45 -04:00
Wilson Snyder 97963fb8c9 Internals: Move DECLFILENAME code to LinkCells. 2012-06-13 22:18:12 -04:00
Wilson Snyder ee1643ce39 Fix false UNUSED warning on file system calls. 2012-06-03 08:20:12 -04:00
Wilson Snyder a82cdcfe48 Add --converge-limit option. 2012-05-31 18:56:31 -04:00
Wilson Snyder 1b439703ff Fix leak issues, bug521 2012-05-30 23:17:55 -04:00
Wilson Snyder 4cc5943f90 Leak fix - Null sense item shouldn't disable event 2012-05-30 23:15:25 -04:00
Wilson Snyder 5fad666678 Fix +: and -: memory leak. 2012-05-29 23:16:13 -04:00
Wilson Snyder e12bf35996 Fix leak check compile and run, bug521. 2012-05-29 22:59:17 -04:00
Wilson Snyder d34fccec22 Internals: Remove typedefFwd earlier to simplify Link 2012-05-28 10:23:47 -04:00
Wilson Snyder 429437f1b9 Internals: Reorder code. No functional change. 2012-05-28 09:19:51 -04:00
Wilson Snyder c6e7d87960 Commentary - Remove author lines as amany contributors now 2012-05-24 19:19:48 -04:00
Wilson Snyder 716320f3ca Extra debug check 2012-05-24 19:15:28 -04:00
Wilson Snyder 1d12b47cb8 Fix internal readWholefile error check, bug518. 2012-05-22 10:20:35 -04:00
Wilson Snyder 1bc1ee9e08 Fix duplicate warnings/errors, bug516. 2012-05-21 21:31:52 -04:00
Wilson Snyder 53f50463bc Internals: Add warnMore() for all continued messages. 2012-05-21 21:24:17 -04:00
Jeremy Bennett 7ab91e660f Tests: Add t_sv_enum_type_methods, bug515.
Signed-off-by: Wilson Snyder <[email protected]>
2012-05-21 18:39:45 -04:00
Wilson Snyder 2f0e230522 Tests: New struct tests. Merge from branch. 2012-05-16 22:27:59 -04:00
Wilson Snyder 280f674ce9 Fix signed extending biops with WIDTH warning off, bug511. 2012-05-16 22:18:52 -04:00
Wilson Snyder a92c66d512 Internals: Pass expected dtype in width. No functional change intended. 2012-05-16 20:58:15 -04:00
Wilson Snyder c45eedcb02 Tests: New t_inst_signed test 2012-05-16 20:21:02 -04:00
Wilson Snyder a9a49345ba Fix loop error message to report line, bug513. 2012-05-16 19:31:24 -04:00
Wilson Snyder 8d960a2eb9 Tests: Add t_sv_cpu, bug473. By Jeremy Bennett. 2012-05-16 18:38:01 -04:00
Wilson Snyder 3e623b8959 Fix GCC 4.6.3 warning 2012-05-15 19:28:07 -04:00
Wilson Snyder 1b1991d53d Fix output with select hitting tristate, bug514. 2012-05-15 19:26:20 -04:00
Wilson Snyder 6d0f39d841 Fix sign-extension underneath boolean operators. (In theory shouldn't matter, since comparing to zero.) 2012-05-11 18:26:45 -04:00
Wilson Snyder 3087501b6c Tests: file_grep prints failing expected value when possible. 2012-05-11 18:24:49 -04:00
Wilson Snyder b429319bc0 Portability fixes for gcc 4.6.3 2012-05-10 22:04:53 -04:00
Wilson Snyder 247e855dbf Fix not showing internal error when no coredump. 2012-05-10 21:58:02 -04:00
Wilson Snyder 1aec645510 Internals: Fix dead parameter calls. No functional change. 2012-05-09 23:06:43 -04:00
Wilson Snyder 3ea2038d3d Internals: Fix dead parameter calls. No functional change. 2012-05-09 23:04:20 -04:00
Wilson Snyder 942cb5e87e Internals: Make findDtype functions use this. No functional change. 2012-05-09 22:12:57 -04:00
Wilson Snyder 37a3a7cdce Fix tristate bug512, broken with tristate commit. 2012-05-09 20:34:15 -04:00
Wilson Snyder 435a27b66a Tristate: Major rework to support Z tieoffs, bug499, bug510. 2012-05-08 21:53:22 -04:00
Wilson Snyder b31a7cdcbf Internals: Fix uninitialized m_alhs 2012-05-08 20:05:43 -04:00
Wilson Snyder ac61548e6a Optimize tristate structure OR(AND(x,y),AND(z,y)). 2012-05-08 19:20:23 -04:00
Wilson Snyder f5ace0f72a Tests: Add bug508, bug509 examples 2012-05-08 17:41:42 -04:00
Wilson Snyder e498b73933 Internals: Misc tristate merges. Pins renamed but... No functional change intended. 2012-05-07 23:43:19 -04:00
Wilson Snyder ff69bdbc6f Debug: Add @ to end of dtype to avoid miscutting 2012-05-07 19:01:45 -04:00
Wilson Snyder 0c1e184cb7 Fix newlines in radix values, bug507. 2012-05-07 08:58:29 -04:00
Wilson Snyder e97541dcbc Internals: Minor tristate changes from branch. No functional change. 2012-05-06 16:52:08 -04:00
Wilson Snyder 7b3eb22865 Fix compile warning 2012-05-06 14:05:56 -04:00
Wilson Snyder d55f065ce2 Internals: Tristate join AND/OR visitor pull setter. No functional change 2012-05-05 15:04:33 -04:00
Wilson Snyder 86af244636 Internals: Tristate common pull setter. No functional change 2012-05-05 15:03:00 -04:00
Wilson Snyder 2c9e2b2e3c Internals: Common insert function in tristate. No functional change. 2012-05-05 14:55:35 -04:00
Wilson Snyder 33c8bf886e Debug: Assume PDF output for dot. 2012-05-05 14:50:11 -04:00
Wilson Snyder ef71a089a6 Internals: Spacing. No functional change 2012-05-05 14:49:43 -04:00
Wilson Snyder 5fc98cce0d Fix parameters not supported in constant functions, bug474. 2012-05-03 21:59:47 -04:00
Wilson Snyder b9101c3d6a Better message for display-like format warnings, bug500. 2012-05-02 21:04:50 -04:00
Wilson Snyder 6aab0f627c Fix input and real loosing real data type, bug501. 2012-05-02 20:53:38 -04:00
Wilson Snyder 6b97673d0a Internals: Fix dtype() dead code drop on assign varrefs 2012-05-02 20:53:19 -04:00
Wilson Snyder 5d8c1ce84e Internals: Avoid broken recusion 2012-05-02 20:52:10 -04:00
Wilson Snyder 33c9591a4b Internals: Move widthPow2. No functional change. 2012-04-29 11:34:25 -04:00
Wilson Snyder 87e8736823 IMPORTANT: Major internal changes for supporting complex data types.
Adds dtype() to every node, keep global table of dtypes and remove duplicates.
Final merge from dtype branch.
2012-04-29 10:14:13 -04:00
Wilson Snyder c0da16bfcd Internals: Create dtypeFrom. Merge from dtype. No functional change. 2012-04-29 09:42:17 -04:00
Wilson Snyder a4ddc5b3ac Internals: Create user1SetOnce(). No functional change. 2012-04-29 08:55:33 -04:00
Wilson Snyder 91e4010039 Internals: Rename AstRefDType subDTypep. Merge from dtype. No functional change. 2012-04-29 08:38:53 -04:00
Wilson Snyder 486b6580d8 Internals: Rename VSignedState. Merge from dtype. No functional change. 2012-04-29 08:30:02 -04:00
Wilson Snyder 9c4ef27d49 Internals: Cleanup dead function names. Merge from dtype. No functional change. 2012-04-29 08:24:32 -04:00
Wilson Snyder 33577eaa68 Tests: Less sensitivity to XML change 2012-04-29 08:23:24 -04:00
Wilson Snyder d5e19661bd Debug: Tree compare between versions; merge from dtype branch. No functional change. 2012-04-28 13:00:44 -04:00
Wilson Snyder 799afac05b Internals: V3Hashed cleanups; merge from dtype branch. No functional change. 2012-04-28 12:33:51 -04:00
Wilson Snyder 3ba36dc30c Debugging: Show tree file writes, commentary 2012-04-28 12:22:38 -04:00
Wilson Snyder 641024c235 Fix generated inouts with duplicated modules, bug498. 2012-04-27 19:41:13 -04:00
Wilson Snyder d9598db117 Internals: In debug dumps, show user pointers 2012-04-27 19:01:08 -04:00
Wilson Snyder 2e4da07a15 Fix ITOD internal error on real conversions, bug491. 2012-04-26 22:30:22 -04:00
Wilson Snyder 40f4411b69 Fix tristate connection to unconnected input, bug494, bug495. 2012-04-26 21:11:48 -04:00
Wilson Snyder c75de0f37c Add INITIALDLY warning on initial assignments, bug478. 2012-04-26 20:40:13 -04:00
Wilson Snyder 74c4c1bf44 Internals: Pass unconnected pins through structures. No functional change intended. 2012-04-26 19:01:11 -04:00
Wilson Snyder 60a637921c Add PINMISSING and PINNOCONNECT lint checks. 2012-04-26 18:46:44 -04:00
Wilson Snyder 22312b3c9c Internals: Remove dead code. No functional change intended. 2012-04-26 18:42:02 -04:00
Wilson Snyder 2e26e44538 Commentary, bug497. Merge from Bennett. 2012-04-26 07:10:49 -04:00
Wilson Snyder 24e79ecc68 Fix coredump on constant connect 2012-04-25 22:51:31 -04:00
Wilson Snyder 5b532a1812 Fix generate if, broke in earlier committ, bug492. Merge from Bennett. 2012-04-25 18:17:10 -04:00
Wilson Snyder f3867d7f80 Fix imports causing symbol table error, bug490. 2012-04-24 21:21:26 -04:00
Wilson Snyder fb90e47e70 Tests: Add t_udp_noname, bug468 2012-04-24 20:43:15 -04:00
Wilson Snyder 68046244dd Fix 'output tri0' 2001 declaration; Var characteristics must be attributes 2012-04-24 07:45:02 -04:00
Wilson Snyder b1507060ad Fix output with tri1, but489 2012-04-24 07:12:51 -04:00
Wilson Snyder ffbd595d88 Support nmos and pmos, bug488. 2012-04-23 20:13:07 -04:00
Wilson Snyder ed5bc1e69c Internals: Rename arrayp to rangep(). No functional change intended. 2012-04-22 19:18:51 -04:00
Wilson Snyder 9734931f67 IMPORTANT: Rewrite tristate handling, tri0, tri1, etc. 2012-04-21 21:45:28 -04:00
Wilson Snyder 0048b04540 Merge from Tristate branch, part 1 of 2. No functional change intended 2012-04-21 19:30:08 -04:00
Wilson Snyder c361932fe2 Commentary: Test documentation, bug486. Merge from Bennett. 2012-04-21 12:58:46 -04:00
Wilson Snyder 2d8feabe54 Fix generate operators not short circuiting, bug413. Merge from Jeremy Bennett. 2012-04-19 22:53:52 -04:00
Wilson Snyder 1b511dd130 Internals: Add opLogIf(f). No functional change. Merge from Jeremy Bennet. 2012-04-19 21:02:08 -04:00
Wilson Snyder 52024f4d80 Makefile: Correct tag file selection. Merge from Jeremy Bennet. 2012-04-19 21:00:58 -04:00
Wilson Snyder 735fa6287f Fix linking suppressing duplicate var and block name errors 2012-04-19 20:51:21 -04:00
Wilson Snyder 7eb407fe2b driver.pl: Add --no-verilation option 2012-04-16 20:28:24 -04:00
Wilson Snyder 897d5c58b3 Devel version 2012-04-16 20:20:58 -04:00
Wilson Snyder dc9086512b Doxygen logo and commentary 2012-04-16 07:31:27 -04:00
Wilson Snyder 0029d068c7 Version bump 2012-04-15 16:21:31 -04:00
Wilson Snyder de388b3dc8 Part of last commit 2012-04-15 16:14:18 -04:00
Wilson Snyder fb904d53cd Add doxygen comments, bug482 2012-04-15 15:44:32 -04:00
Wilson Snyder 600cc02de3 Commentary 2012-04-15 15:08:13 -04:00
Wilson Snyder 946d0cd219 Add readme.pdf and internal.pdf 2012-04-15 14:51:04 -04:00
Wilson Snyder 4d0b964e36 Internals: Merge from dtype. Create subDTypep. No functional change intended. 2012-04-14 12:43:03 -04:00
Wilson Snyder 2b12ab4d5a Internals: Merge from dtype. Add hasDType; still unused. No functional change. 2012-04-14 11:03:38 -04:00
Wilson Snyder 8114957e6d Internals: Merge from dtype. Rename isSigned to dtypeChgSigned. No functional change. 2012-04-14 10:45:24 -04:00
Wilson Snyder 50edef4ab2 Add Emacs indentation line. No functional change 2012-04-12 21:08:20 -04:00
Wilson Snyder e5a991988f Tests added 2012-04-12 20:13:35 -04:00
Wilson Snyder e85eb6d0f4 Tests: Add t_enum_type_methods, bug473 2012-04-12 18:21:08 -04:00
Wilson Snyder 6949f35f22 Tests: Add t_array_query, t_sv_conditional, bug473 2012-04-12 18:15:39 -04:00
Wilson Snyder e0391b93c4 Commentary 2012-04-12 06:48:02 -04:00
Wilson Snyder 4a5e775a2b Fix change detections on arrays. 2012-04-09 20:17:51 -04:00
Wilson Snyder 323f019350 Tests: Add t_interface, bug481. Merge from JERAS/test_sv. 2012-04-08 18:13:56 -04:00
Wilson Snyder 98053c2d4c Tests: Add t_param_type, bug480. Merge from JERAS/test_sv. 2012-04-08 17:59:46 -04:00
Wilson Snyder aab338760c Increase VL_VALUE_STRING_MAX_WIDTH, bug479 2012-04-05 21:46:55 -04:00
Wilson Snyder ab9a2b1728 Internal: Prevent possible buffer overrun 2012-04-05 21:46:03 -04:00
Wilson Snyder 6a38d3bcf3 Add SELRANGE as warning instead of error, bug477. 2012-04-04 21:55:20 -04:00
Wilson Snyder 76f3cbdf4c Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2012-04-02 22:05:40 -04:00
Wilson Snyder d45d58b6bf Fix real constant parameter functions, bug475. 2012-04-02 21:58:40 -04:00
Wilson Snyder f32a422330 Tests: New test 2012-04-02 19:38:42 -04:00
Wilson Snyder 74d4be28dd Commentary 2012-04-02 07:17:37 -04:00
Wilson Snyder b4a31bd292 Internals: Merge AstCCast minwidth set. No functional change intended 2012-04-01 21:17:58 -04:00
Wilson Snyder cc1adf9b38 Internals: merge V3Hashed cleanups. No functional change intended 2012-04-01 21:04:28 -04:00
Wilson Snyder 1601b3b6b0 Internals: Merge VFlagChildDtype calls. No functional change intended. 2012-03-31 11:22:19 -04:00
Wilson Snyder 61cbdd1a19 Internals: Merge VFlag rename. No functional change. 2012-03-31 11:10:34 -04:00
Wilson Snyder a3ee6131a3 Internals: Merge using dtypeSetLogicSized. No functional change intended 2012-03-31 10:53:53 -04:00
Wilson Snyder 6dfddaa453 Internals: Rename dtypeChg to dtypeSet. No functional change 2012-03-31 10:19:27 -04:00
Wilson Snyder de696b7092 Debug: Print dtype big endian correctly 2012-03-30 21:50:37 -04:00
Wilson Snyder 9165233657 Fix OpenSolaris compile error. 2012-03-30 07:26:00 -04:00
Wilson Snyder aa3a417e97 Tests: Add t_dpi_accessors 2012-03-27 20:06:59 -04:00
Wilson Snyder 996f48fcf0 Fix processing unused parametrized modules, bug470. 2012-03-24 15:54:06 -04:00
Wilson Snyder 81d83f629f Tests: default_nettype is ok 2012-03-24 15:15:32 -04:00
Wilson Snyder 5e3b0bf348 tests: Add unsupported as target type; additional tests 2012-03-24 11:10:17 -04:00
Wilson Snyder 4a31463299 Fix genvar and begin under generate, bug461. 2012-03-23 08:49:47 -04:00
Wilson Snyder 8a5471e175 Tests: skip test for bug462 2012-03-22 22:35:24 -04:00
Wilson Snyder 605fd9f8e1 Tests: Skip test for bug461 2012-03-22 22:15:35 -04:00
Wilson Snyder 2bda43875d Support += and -= in standard for loops, bug463. 2012-03-22 21:02:38 -04:00
Wilson Snyder 11edc9e7a7 Debug: Add --dump-treei option 2012-03-20 22:45:35 -04:00
Wilson Snyder 3b9b823511 tests: Fix missing manifest from earlier test commit 2012-03-20 22:45:00 -04:00
Wilson Snyder da0ecf59c6 Tests: Rename t_mem_packed_assign_bad since fails 2012-03-20 20:55:16 -04:00
Wilson Snyder e5b1fdf668 Tests: Added additional SystemVerilog tests.
Squashed commit of the following:

commit c1eeda7d472fc14a0ffd5c1712ae7f7c614073a1
Author: Iztok Jeras <[email protected]>
Date:   Tue Mar 20 16:39:44 2012 +0100

- fixed assignment operator in t_array_packed_write_read.v from = to <=
- added tests for enumerations (existing tests do not use methods like
next(), num(), ...)
- added t_sv_bus_mux_demux test, with packed arrays, structures and unions
2012-03-20 19:28:35 -04:00
Wilson Snyder 204fb82975 Add very experimental --xml option 2012-03-20 16:13:10 -04:00
Wilson Snyder 37839e2709 Cleanup trailing whitespace. No functional change 2012-03-20 16:01:53 -04:00
Wilson Snyder dbaedb5995 Internals: Add XML output internals, unused. No functional change. 2012-03-20 15:57:29 -04:00
Wilson Snyder 0a832e90bd Internals: Rename left/right to match IEEE. No functional change. 2012-03-19 21:32:05 -04:00
Wilson Snyder b4e908d04d Fix warning on gcc 4.6.1 2012-03-16 18:06:32 -04:00
Wilson Snyder 4619d29b78 Commentary; bug457 2012-03-15 18:44:08 -04:00
Wilson Snyder c63b697636 Fix signed array warning, bug456. 2012-03-12 20:29:00 -04:00
Wilson Snyder 06d29d6fda Commentary 2012-03-10 10:56:48 -05:00
Wilson Snyder c0f7bc4b5e Tests: Parameter bug case 2012-03-09 19:35:37 -05:00
Wilson Snyder 7139c9ae59 Fix and document --gdb option, bug454. 2012-03-09 18:37:38 -05:00
Wilson Snyder 0ae00fc921 Commentary; bug452. 2012-03-08 18:36:51 -05:00
Wilson Snyder fe456cb83d Devel version 2012-03-07 23:02:24 -05:00
480 changed files with 22081 additions and 5199 deletions
+3 -1
View File
@@ -9,15 +9,17 @@
.*.swp
*.tmp
*.tex
*.pdf
/Makefile
README
TAGS
autom4te.cache
config.cache
config.status
configure
dddrun*
doxygen-doc
gdbrun*
internals.txt
verilator.pdf
verilator.txt
verilator_bin*
+119 -2
View File
@@ -3,6 +3,123 @@ 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.843 2012/12/01
*** Add +1364-1995ext and similar language options, bug532. [Jeremy Bennett]
**** Fix mis-optimized identical submodule subtract, bug581. [Charlie Brej]
**** Fix crash on dotted references into dead modules, bug583. [Jeremy Bennett]
**** Fix compile issues on MSVCC, bug571, bug577. [Amir Gonnen]
**** Fix --debug overriding preceding --dump-treei, bug580. [Jeremy Bennett]
* Verilator 3.842 2012/11/03
**** Add -x-initial-edge, bug570. [Jeremy Bennett]
**** Fix parameter pins interspersed with cells broke in 3.840. [Bernard Deadman]
**** Fix large shift error on large shift constants. [David Welch]
**** Fix $display mangling on GCC 4.7 and speed up, msg927, bug373, bug574. [R Diez]
**** Fix array of struct references giving false error, bug566. [Julius Baxter]
**** Fix missing var access functions when no DPI, bug572. [Amir Gonnen]
**** Fix name collision on unnamed blocks, bug567. [Chandan Egbert]
**** Fix name collision on task inputs, bug569. [Chandan Egbert]
* Verilator 3.841 2012/09/03
*** Add --savable to support model save/restore. [Jeremy Bennett]
*** Support '{} assignment pattern on structures, part of bug355.
**** Fix double-deep parameter cell WIDTHs, bug541. [Hiroki Honda]
**** Fix imports under multiple instantiated cells, bug542. [Alex Solomatnikov]
**** Fix defparam in generate broke in 3.840, bug543. [Alex Solomatnikov]
**** Fix duplicate begin error broke in 3.840, bug548. [Alex Solomatnikov]
**** Fix triangle symbol resolution error broke in 3.840, bug550. [Ted Campbell]
* Verilator 3.840 2012/07/31 Beta
** Rewrote tristate handling; supports tri0, tri1, tristate bit selects,
concatenates and pullup/pulldowns, bug395, bug56, bug54, bug51.
[Alex Solomatnikov, Lane Brooks, et al]
** Support packed structures and unions, bug181.
Note this was a major internal change that may lead to some instability.
*** Support tri0 and tri1, bug462. [Alex Solomatnikov]
*** Support nmos and pmos, bug488. [Alex Solomatnikov]
*** Add INITIALDLY warning on initial assignments, bug478. [Alex Solomatnikov]
*** Add PINMISSING and PINNOCONNECT lint checks.
*** Add --converge-limit option.
*** Fix generate operators not short circuiting, bug413. [by Jeremy Bennett]
*** Fix parameters not supported in constant functions, bug474. [Alex Solomatnikov]
**** Fix duplicate warnings/errors, bug516. [Alex Solomatnikov]
**** Fix signed extending biops with WIDTH warning off, bug511. [Junji Hashimoto]
**** Fix ITOD internal error on real conversions, bug491. [Alex Solomatnikov]
**** Fix input and real loosing real data type, bug501. [Alex Solomatnikov]
**** Fix imports causing symbol table error, bug490. [Alex Solomatnikov]
**** Fix newlines in radix values, bug507. [Walter Lavino]
**** Fix loop error message to report line, bug513. [Jeremy Bennett]
**** Fix false UNUSED warning on file system calls.
**** Fix GCC 4.7.0 compile warnings, bug530. [Jeremy Bennett]
**** Fix svdpi.h compile error on Apple OS.
**** Fix compile error under git submodules, bug534. [Aurelien Francillon]
* Verilator 3.833 2012/04/15
*** Support += and -= in standard for loops, bug463. [Alex Solomatnikov]
*** Fix processing unused parametrized modules, bug469, bug470. [Alex Solomatnikov]
**** Add SELRANGE as warning instead of error, bug477. [Alex Solomatnikov]
**** Add readme.pdf and internal.pdf and doxygen, bug483. [by Jeremy Bennett]
**** Fix change detections on arrays, bug364. [John Stevenson, Alex Solomatnikov]
**** Fix signed array warning, bug456. [Alex Solomatnikov]
**** Fix genvar and begin under generate, bug461. [Alex Solomatnikov]
**** Fix real constant parameter functions, bug475. [Alex Solomatnikov]
**** Fix and document --gdb option, bug454. [Jeremy Bennett]
**** Fix OpenSolaris compile error. [Sanjay Singh]
* Verilator 3.832 2012/03/07
@@ -56,7 +173,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Support $system. [Ruben Diez]
**** Support $sscanf with %g. [Holger Wächtler]
**** Support $sscanf with %g. [Holger Waechtler]
**** Indicate 'exiting due to errors' if errors, not warnings. [Ruben Diez]
@@ -64,7 +181,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix reporting not found modules if generate-off, bug403. [Jeremy Bennett]
**** Fix $display with %d following %g. [Holger Wächtler]
**** Fix $display with %d following %g. [Holger Waechtler]
* Verilator 3.824 2011/10/25
+3
View File
@@ -35,3 +35,6 @@ nodist/
/simv.daidir/
/vc_hdrs.h$
/csrc/
doxygen-doc/.*
TAGS
.*~
+39 -13
View File
@@ -54,11 +54,13 @@ srcdir = @srcdir@
VPATH = @srcdir@
HOST = @HOST@
DOXYGEN = doxygen
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
MAKEINFO = makeinfo
POD2TEXT = pod2text
POD2LATEXFIX = $(srcdir)/src/pod2latexfix
PERL = @PERL@
# Destination prefix for RPMs
@@ -100,7 +102,8 @@ SHELL = /bin/sh
SUBDIRS = src test_verilated test_c test_sc test_sp test_regress test_vcs
INFOS = README internals.txt verilator.txt verilator.html verilator.1 verilator.pdf
INFOS = README README.html README.pdf internals.txt internals.html \
internals.pdf verilator.txt verilator.html verilator.1 verilator.pdf
# Files that can be generated, but should be up to date for a distribution.
DISTDEP = info Makefile
@@ -110,6 +113,7 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
Changes TODO \
MANIFEST.SKIP \
bin/* \
doxygen-mainpage doxygen.config veripool-logo.png \
install-sh configure mkinstalldirs *.pod \
include/*.[chv]* \
include/*.in \
@@ -121,7 +125,8 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
test_verilated/vgen*.pl \
test_regress/t/tsub/*.v* \
test_regress/t/t*/*.sv* \
test_regress/t/t*/*.v* \
test_regress/t/*.cpp \
test_regress/t/*.h \
test_regress/t/*.dat \
@@ -215,15 +220,7 @@ verilator.html: ${srcdir}/bin/verilator
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
verilator.pdf: ${srcdir}/bin/verilator Makefile
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
cat < verilator.tex \
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\usepackage{fancyhdr} \\pagestyle{fancy}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\title{$(DISTTITLE)} \\date{${DISTDATE}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.org}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\lhead[$(DISTTITLE)]{$(DISTTITLE)}\n\\begin{document}/' \
| sed 's/\\tableofcontents/\\begin{titlepage} \\maketitle \\end{titlepage}\n\\tableofcontents/' \
> verilator2.tex
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE)" "${DISTDATE}" < verilator.tex > verilator2.tex
mv verilator2.tex verilator.tex
pdflatex verilator.tex
pdflatex verilator.tex
@@ -233,10 +230,34 @@ README: readme.pod
-rm -f $@
$(POD2TEXT) --loose $< > $@
README.html: readme.pod
pod2html $< >$@
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
README.pdf: readme.pod Makefile
pod2latex --full --out README.tex readme.pod
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE) README File" "${DISTDATE}" < README.tex > README2.tex
mv README2.tex README.tex
pdflatex README.tex
pdflatex README.tex
-rm -f README.toc README.aux README.idx README.out
internals.txt: internals.pod
-rm -f $@
$(POD2TEXT) --loose $< > $@
internals.html: internals.pod
pod2html $< >$@
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
internals.pdf: internals.pod Makefile
pod2latex --full --out internals.tex internals.pod
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE) Internals Manual" "${DISTDATE}" < internals.tex > internals2.tex
mv internals2.tex internals.tex
pdflatex internals.tex
pdflatex internals.tex
-rm -f internals.toc internals.aux internals.idx internals.out
# 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
@@ -436,12 +457,17 @@ distclean maintainer-clean::
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
rm -f include/verilated.mk
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/[a-z]*.in \
${srcdir}/[a-z]*.in ${srcdir}/*.pod
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
${srcdir}/*.in ${srcdir}/*.pod
TAGS: $(TAGFILES)
etags $(TAGFILES)
.PHONY: doxygen
doxygen:
$(DOXYGEN) doxygen.config
######################################################################
# Test targets
+414 -116
View File
@@ -69,7 +69,7 @@ if (! GetOptions (
"debug:s" => \&debug,
# "version!" => \&version, # Also passthru'ed
# Switches
"gdb=s" => \$opt_gdb, # Undocumented debugging
"gdb!" => \$opt_gdb,
"gdbbt!" => \$opt_gdbbt,
# Additional parameters
"<>" => sub {}, # Ignored
@@ -82,17 +82,24 @@ 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) {
if ($opt_gdb) {
# Generic GDB interactive
run (("gdb"||$ENV{VERILATOR_GDB})
." ".verilator_bin()
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
." -ex 'set width 0'"
." -ex 'bt'");
} elsif ($opt_gdbbt && $Debug) {
# Run under GDB to get gdbbt
run ("gdb ".verilator_bin()
run ("gdb"
." ".verilator_bin()
." --batch --quiet --return-child-result"
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
." -ex 'set width 0'"
." -ex 'bt'");
} else {
# Normal, non gdb
run (($opt_gdb?"$opt_gdb ":"")
.verilator_bin()
run (verilator_bin()
." ".join(' ',@Opt_Verilator_Sw));
}
@@ -167,10 +174,10 @@ sub run {
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n";
}
if ($status & 255) {
if (($status & 255) == 8 || ($status & 255) == 11) { # SIGFPA or SIGSEGV
if ($status & 127) {
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 255) == 6) { # SIGABRT
} elsif (($status & 127) == 6) { # SIGABRT
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
} else {
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
@@ -234,6 +241,11 @@ descriptions in the next sections for more information.
{file.c/cc/cpp} Optional C++ files to compile in
{file.a/o/so} Optional C++ files to link in
+1364-1995ext+<ext> Use Verilog 1995 with file extension <ext>
+1364-2001ext+<ext> Use Verilog 2001 with file extension <ext>
+1364-2005ext+<ext> Use Verilog 2005 with file extension <ext>
+1800-2005ext+<ext> Use SystemVerilog 2005 with file extension <ext>
+1800-2009ext+<ext> Use SystemVerilog 2009 with file extension <ext>
--assert Enable all assertions
--autoflush Flush streams after all $displays
--bbox-sys Blackbox unknown $system calls
@@ -243,23 +255,27 @@ descriptions in the next sections for more information.
--cc Create C++ output
--cdc Clock domain crossing analysis
--compiler <compiler-name> Tune for specified C++ compiler
--converge-limit <loops> Tune convergence settle time
--coverage Enable all coverage
--coverage-line Enable line coverage
--coverage-toggle Enable toggle coverage
--coverage-user Enable PSL/SVL user coverage
--coverage-underscore Enable covarge of _signals
--coverage-underscore Enable coverage of _signals
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
+define+<var>+<value> Set preprocessor define
--dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level
-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
--gdb Run Verilator under GDB interactively
--gdbbt Run Verilator under GDB for backtrace
--help Display this help
-I<dir> Directory to search for includes
@@ -269,7 +285,7 @@ descriptions in the next sections for more information.
--inline-mult <value> Tune module inlining
-LDFLAGS <flags> Linker pre-object flags for makefile
-LDLIBS <flags> Linker library flags for makefile
--language <lang> Language standard to parse
--language <lang> Default language standard to parse
+libext+<ext>+[ext]... Extensions for finding modules
--lint-only Lint, but do not make output
--MMD Create .d dependency files
@@ -293,10 +309,12 @@ descriptions in the next sections for more information.
--private Debugging; see docs
--psl Enable PSL parsing
--public Debugging; see docs
--savable Enable model save-restore
--sc Create SystemC output
--sp Create SystemPerl output
--stats Create statistics file
-sv Enable SystemVerilog parsing
+systemverilogext+<ext> Synonym for +1800-2009ext+<ext>
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
@@ -309,13 +327,16 @@ descriptions in the next sections for more information.
--unused-regexp <regexp> Tune UNUSED lint signals
-V Verbose version and config
-v <filename> Verilog library
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
-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
--x-assign <mode> Initially assign Xs to this value
--x-initial-edge Enable initial X->0 and X->1 edge triggers
-y <dir> Directory to search for modules
@@ -343,18 +364,56 @@ this way, Verilator will include a make rule that uses these files when
linking the I<module> executable. This generally is only useful when used
with the --exe option.
=item +1364-1995ext+I<ext>
=item +1364-2001ext+I<ext>
=item +1364-2005ext+I<ext>
=item +1800-2005ext+I<ext>
=item +1800-2009ext+I<ext>
Specifies the language standard to be used with a specific filename
extension, I<ext>.
For compatibility with other simulators, see also the synonyms
C<+verilog1995ext+>I<ext>, C<+verilog2001ext+>I<ext>, and
C<+systemverilogext+>I<ext>.
For any source file, the language specified by these options takes
precedence over any language specified by the C<--default-language> or
C<--language> options.
These options take effect in the order they are encountered. Thus the
following would use Verilog 1995 for C<a.v> and Verilog 2001 for C<b.v>.
verilator ... +1364-1995ext+v a.v +1364-2001ext+v b.v
These flags are only recommended for legacy mixed language designs, as the
preferable option is to edit the code to repair new keywords, or add
appropriate C<`begin_keywords>.
B<Note> C<`begin_keywords> is a SystemVerilog construct, which specifies
I<only> which the set of keywords is to be recognized. Whatever set is
chosen, the semantics will be those of SystemVerilog. By contrast
C<+1364-1995ext+> etc. specify both the syntax I<and> semantics to be used.
=item --assert
Enable all assertions, includes enabling the --psl flag. (If psl is not
desired, but other assertions are, use --assert --nopsl.)
See also --x-assign; setting "--x-assign unique" may be desirable.
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
and/or "--x-initial-edge" may be desirable.
=item --autoflush
After every $display or $fdisplay, flush the output stream. This insures
that messages will appear immediately but may reduce performance. Defaults
off, which will buffer output as provided by the normal C stdio calls.
that messages will appear immediately but may reduce performance; for best
performance call "fflush(stdout)" occasionally in the main C loop.
Defaults off, which will buffer output as provided by the normal C stdio
calls.
=item --bbox-sys
@@ -418,6 +477,11 @@ functions to avoid error C1061.
=back
=item --converge-limit <loops>
Rarely needed. Specifies the maximum number of runtime iterations before
creating a model failed to converge error. Defaults to 100.
=item --coverage
Enables all forms of coverage, alias for "--coverage-line --coverage-toggle
@@ -509,10 +573,32 @@ Rarely needed. Enable internal debugging assertion checks, without
changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi <level>
=item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally
or on the specified source file to the specified level.
to the specified debug level (1-10) or set the specified source file to the
specified level. Higher levels produce more detailed messages (plain
C<--debug> is equivalent to C<--debugi 4>).
=item --default-language I<value>
Select the language to be used by default when first processing each
Verilog file. The language value must be "1364-1995", "1364-2001",
"1364-2005", "1800-2005" or "1800-2009".
Any language associated with a particular file extension (see the various
+I<lang>ext+ options) will be used in preference to the language specified
by --default-language.
The --default-language flag is only recommended for legacy code using the
same language in all source files, as the preferable option is to edit the
code to repair new keywords, or add appropriate C<`begin_keywords>. For
legacy mixed language designs, the various +I<lang>ext+ options should be
used.
If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2009) is used.
=item +define+I<var>+I<value>
@@ -521,10 +607,18 @@ standard across Verilog tools while -D is an alias for GCC compatibility.
=item --dump-tree
Rarely needed. Enable writing .tree debug files. This is enabled with
Rarely needed. Enable writing .tree debug files with dumping level 3,
which dumps the standard critical stages. For details on the format see
the Verilator Internals manual. --dump-tree is enabled automatically with
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
large and not desired.
=item --dump-treei <level>
Rarely needed. Enable writing .tree debug files with a specific dumping
level, 0 disbles dumps and is equivelent to "--no-dump-tree". Level 9
enables dumping of every stage.
=item -E
Preprocess the source code, but do not compile, as with 'gcc -E'. Output
@@ -558,11 +652,17 @@ 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 --gdb
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
variable value) session. See also --gdbbt.
=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.
If --debug is specified, run Verilator underneath a GDB process and print a
backtrace on exit, then exit GDB immediately. Without --debug or if GDB
doesn't seem to work, this flag is ignored. Intended for easy creation of
backtraces by users; otherwise see the --gdb flag.
=item --help
@@ -609,15 +709,8 @@ in the Make variable LDLIBS, not LDFLAGS.)
=item --language I<value>
Select the language to be used when first processing each Verilog file.
The language value must be "1364-1995", "1364-2001", "1364-2001",
"1364-2005", "1800-2005", "VAMS-2.3". Verilator also allows the
non-standard "1800+VAMS" to allow both the full SystemVerilog and
Verilog-AMS keywords.
The --language flag is only recommended for legacy code, as the preferable
option is to edit the code to repair new keywords, or add appropriate
`begin_keywords.
A synonym for C<--default-langauge>, for compatibility with other tools and
earlier versions of Verilator.
=item +libext+I<ext>+I<ext>...
@@ -785,6 +878,27 @@ inlining. This will also turn off inlining as if all modules had a
/*verilator public_module*/, unless the module specifically enabled it with
/*verilator inline_module*/.
=item --savable
Enable including save and restore functions in the generated model.
The user code must create a VerilatedSerialize or VerilatedDeserialze
object then calling the << or >> operators on the generated model and any
other data the process needs saved/restored. For example:
void save_model(const char* filenamep) {
VerilatedSave os;
os.open(filenamep);
os << main_time; // user code must save the timestamp, etc
os << *topp;
}
void restore_model(const char* filenamep) {
VerilatedRestore os;
os.open(filenamep);
os >> main_time;
os >> *topp;
}
=item --sc
Specifies SystemC output mode; see also --cc and -sp.
@@ -803,6 +917,10 @@ Specifies SystemVerilog language features should be enabled; equivalent to
"--language 1800-2005". This option is selected by default, it exists for
compatibility with other simulators.
=item +systemverilogext+I<ext>
A synonym for C<+1800-2009ext+>I<ext>.
=item --top-module I<topname>
When the input Verilog contains more than one top level module, specifies
@@ -878,6 +996,12 @@ 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 +verilog1995ext+I<ext>
=item +verilog2001ext+I<ext>
Synonyms for C<+1364-1995ext+>I<ext> and C<+1364-2001ext+>I<ext> respectively
=item -Wall
Enable all warnings, including code style warnings that are normally
@@ -906,8 +1030,8 @@ Disable the specified warning message.
Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
-Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN
-Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus
the list shown for Wno-style.
-Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
-Wno-WIDTH" plus the list shown for Wno-style.
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
@@ -917,8 +1041,8 @@ received from third parties.
Disable all code style related warning messages (note by default they are
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
-Wno-VARHIDDEN".
-Wno-INCABSPATH -Wno-PINNOCONNECT -Wno-SYNCASYNCNET -Wno-UNDRIVEN
-Wno-UNUSED -Wno-VARHIDDEN".
=item -Wno-fatal
@@ -938,37 +1062,72 @@ Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
-Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
-Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style
Enable all code style related warning messages. This is equivalent to
"-Wwarn ASSIGNDLY -Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH
-Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
-Wwarn-PINNOCONNECT -Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED
-Wwarn-VARHIDDEN".
=item -x-assign 0
=item --x-assign 0
=item -x-assign 1
=item --x-assign 1
=item -x-assign fast (default)
=item --x-assign fast (default)
=item -x-assign unique
=item --x-assign unique
Controls the two-state value that is replaced when an assignment to X is
encountered. -x-assign=fast, the default, converts all Xs to whatever is
best for performance. -x-assign=0 converts all Xs to 0s, and is also fast.
-x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
likely to find reset bugs as active high logic will fire. -x-assign=unique
encountered. --x-assign=fast, the default, converts all Xs to whatever is
best for performance. --x-assign=0 converts all Xs to 0s, and is also fast.
--x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
likely to find reset bugs as active high logic will fire. --x-assign=unique
will call a function to determine the value, this allows randomization of
all Xs to find reset bugs and is the slowest, but safest for finding reset
bugs in code.
If using -x-assign unique, you may want to seed your random number
If using --x-assign unique, you may want to seed your random number
generator such that each regression run gets a different randomization
sequence. Use the system's srand48() or for Windows srand() function to do
this. You'll probably also want to print any seeds selected, and code to
enable rerunning with that same seed so you can reproduce bugs.
B<Note.> This option applies only to variables which are explicitly assigned
to X in the Verilog source code. Initial values of clocks are set to 0 unless
--x-initial-edge is specified. Initial values of all other state holding
variables are set as though --x-assign unique had been specified.
=item --x-initial-edge
Enables emulation of event driven simulators which generally trigger an
edge on a transition from X to 1 (C<posedge>) or X to 0 (C<negedge>). Thus
the following code, where C<rst_n> is uninitialized would set C<res_n> to
C<1'b1> when C<rst_n> is first set to zero:
reg res_n = 1'b0;
always @(negedge rst_n) begin
if (rst_n == 1'b0) begin
res_n <= 1'b1;
end
end
In Verilator, by default, uninitialized clocks are given a value of zero,
so the above C<always> block would not trigger.
While it is not good practice, there are some designs that rely on X
E<rarr> 0 triggering a C<negedge>, particularly in reset sequences. Using
--x-initial-edge with Verilator will replicate this behaviour. It will also
ensure that X E<rarr> 1 triggers a C<posedge>.
B<Note.> Some users have reported that using this option can affect
convergence, and that it may be necessary to use --converge-limit to
increase the number of convergence iterations. This may be another
indication of problems with the modelled design that should be addressed.
=item -y I<dir>
Add the directory to the list of directories that should be searched for
@@ -1004,6 +1163,7 @@ We'll compile this example into C++.
Verilated::commandArgs(argc, argv);
Vour* top = new Vour;
while (!Verilated::gotFinish()) { top->eval(); }
delete top;
exit(0);
}
EOF
@@ -1071,6 +1231,7 @@ This is an example similar to the above, but using SystemPerl.
top = new Vour("top"); // SP_CELL (top, Vour);
top->clk(clk); // SP_PIN (top, clk, clk);
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
delete top;
exit(0);
}
EOF
@@ -1104,6 +1265,9 @@ And link with SystemC. Note your path to the libraries may vary,
depending on the operating system.
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
# Might be needed if SystemC 2.3.0
export SYSTEMC_CXX_FLAGS=-pthread
g++ -L$SYSTEMC_LIBDIR ../sc_main.o Vour__ALL*.o verilated.o \
-o Vour -lsystemc
@@ -1124,9 +1288,9 @@ the test_sp directory in the distribution for an example.
=head1 BENCHMARKING & OPTIMIZATION
For best performance, run Verilator with the "-O3 -x-assign=fast
For best performance, run Verilator with the "-O3 --x-assign=fast
--noassert" flags. The -O3 flag will require longer compile times, and
-x-assign=fast may increase the risk of reset bugs in trade for
--x-assign=fast may increase the risk of reset bugs in trade for
performance; see the above documentation for these flags.
Minor Verilog code changes can also give big wins. You should not have any
@@ -1141,8 +1305,10 @@ C++ compiler and size of your CPU's caches.
By default, the lib/verilated.mk file has optimization turned off. This is
for the benefit of new users, as it improves compile times at the cost of
runtimes. To add optimization as the default, set one of three variables,
OPT, OPT_FAST, or OPT_SLOW in lib/verilated.mk. Or, just for one run, pass
them on the command line to make:
OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
-LDFLAGS option on the verilator command line to pass the flags directly to
the compiler or linker. Or, just for one run, pass them on the command
line to make:
make OPT_FAST="-O2" -f Vour.mk Vour__ALL.a
@@ -1153,7 +1319,9 @@ rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
with "-static". Nearly the same results can be had with much better
compile times with OPT_FAST="-O1 -fstrict-aliasing".
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
such as "-O3" may help, but gcc compile times may be excessive under O3 on
even medium sized designs.
Unfortunately, using the optimizer with SystemC files can result in
compiles taking several minutes. (The SystemC libraries have many little
@@ -1167,6 +1335,11 @@ If you will be running many simulations on a single compile, investigate
feedback driven compilation. With GCC, using -fprofile-arcs, then
-fbranch-probabilities will yield another 15% or so.
Modern compilers also support link-time optimization (LTO), which can help
especially if you link in DPI code. To enable LTO on GCC, pass "-flto" in
both compilation and link. Note LTO may cause excessive compile times on
large designs.
You may uncover further tuning possibilities by profiling the Verilog code.
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
either oprofile or gprof to see where in the C++ code the time is spent.
@@ -1257,7 +1430,7 @@ was compiled).
=item SYSTEMC_CXX_FLAGS
Specifies additional flags that are required to be passed to GCC when
building the SystemC model.
building the SystemC model. System 2.3.0 may need this set to "-pthread".
=item SYSTEMC_INCLUDE
@@ -1270,7 +1443,7 @@ SYSTEMC/include.
If set, specifies the directory containing the libsystemc.a library. If not
specified, it will come from a default optionally specified at configure
time (before Verilator was compiled), or compted from
time (before Verilator was compiled), or computed from
SYSTEMC/lib-SYSTEMC_ARCH.
=item SYSTEMPERL
@@ -1299,6 +1472,11 @@ baseline regression tests.
If set, specifies an alternative name of the Verilator binary. May be used
for debugging and selecting between multiple operating system builds.
=item VERILATOR_GDB
If set, the command to run when using the --gdb option, such as "ddd". If
not specified, it will use "gdb".
=item VERILATOR_ROOT
Specifies the directory containing the distribution kit. This is used to
@@ -1361,6 +1539,7 @@ example:
top->final(); // Done simulating
// // (Though this example doesn't get here)
delete top;
}
Note signals are read and written as member variables of the lower module.
@@ -1451,6 +1630,26 @@ DPI compatible but is easier to read and better supports multiple designs.
Vour::publicSetBool(value);
// or top->publicSetBool(value);
Note that if the DPI task or function accesses any register or net within the
RTL, it will require a scope to be set. This can be done using the standard
functions within svdpi.h, after the module is instantiated, but before the
task(s) and/or function(s) are called.
For example, if the top level module is instantiated with the name "dut" and
the name references within tasks are all hierarchical (dotted) names with
respect to that top level module, then the scope could be set with
#include "svdpi.h"
...
svSetScope (svGetScopeFromName ("dut"));
(Remember that Verilator adds a "V" to the top of the module hierarchy.)
Scope can also be set from within a DPI imported C function that has been
called from Verilog by querying the scope of that function. See the
sections on DPI Context Functions and DPI Header Isolation below and the
comments within the svdpi.h header for more information.
=head2 DPI Display Functions
Verilator allows writing $display like functions using this syntax:
@@ -1687,8 +1886,8 @@ Verilator supports ==? and !=? operators, ++ and -- in some contexts,
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
const, do-while, enum, export, final, import, int, logic, longint, package,
program, shortint, time, typedef, var, void, priority case/if, and unique
case/if.
program, shortint, struct, time, typedef, union, var, void, priority
case/if, and unique case/if.
It also supports .name and .* interconnection.
@@ -1895,9 +2094,17 @@ The Verilog code returns to the last language mode specified with
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. It's also a good idea to enable the
related to it. (Typically by adding a latch, and running static timing
analysis.) For example:
reg enable_r /*verilator clock_enable*/;
wire gated_clk = clk & enable_r;
always_ff @ (posedge clk)
enable_r <= enable_early;
The clock_enable attribute will cause the clock gate to be ignored in the
scheduling algorithm, sometimes required for correct clock behavior, and
always 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*/
@@ -2150,49 +2357,71 @@ Verilator is optimized for edge sensitive (flop based) designs. It will
attempt to do the correct thing for latches, but most performance
optimizations will be disabled around the latch.
=head2 Structures and Unions
Verilator only presently supports packed structs and packed unions. Rand
and randc tags on members are simply ignored. All structures and unions
are represented as a single vector, which means that generating one member
of a structure from blocking, and another from non-blocking assignments is
unsupported.
=head2 Time
All delays (#) are ignored, as they are in synthesis.
=head2 Two State
=head2 Unknown states
Verilator is a two state simulator, not a four state simulator. However, it
has two features which uncover most initialization bugs (including many that
a four state simulator will miss.)
First, assigning a variable to a X will actually assign the variable to a
random value (see the -x-assign switch.) Thus if the value is actually
used, the random value should cause downstream errors. Integers also
randomize, even though the Verilog 2001 specification says they initialize
to zero.
Verilator is mostly a two state simulator, not a four state simulator.
However, it has two features which uncover most initialization bugs
(including many that a four state simulator will miss.)
Identity comparisons (=== or !==) are converted to standard ==/!== when
neither side is a constant. This may make the expression result differ
from a four state simulator.
from a four state simulator. An === comparison to X will always be false,
so that Verilog code which checks for uninitialized logic will not fire.
Assigning a variable to a X will actually assign the variable to a random
value (see the --x-assign switch.) Thus if the value is actually used, the
random value should cause downstream errors. Integers also randomize, even
though the Verilog 2001 specification says they initialize to zero.
All variables are randomly initialized using a function. By running
several random simulation runs you can determine that reset is working
correctly. On the first run, the function initializes variables to zero.
On the second, have it initialize variables to one. On the third and
following runs have it initialize them randomly. If the results match,
reset works. (Note this is what the hardware will really do.) In
practice, just setting all variables to one at startup finds most problems.
B<Note.> --x-assign applies to variables explicitly initialized or assigned to
X. Unititialized clocks are initialized to zero, while all other state holding
variables are initialized to a random value.
Event driven simulators will generally trigger an edge on a transition from X
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
are initialized to zero, Verilator will not trigger an initial negedge. Some
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
runs with and without this switch will find such problems.
All variables are initialized using a function. By running several
random simulation runs you can determine that reset is working correctly.
On the first run, the function initializes variables to zero. On the
second, have it initialize variables to one. On the third and following
runs have it initialize them randomly. If the results match, reset works.
(Note this is what the hardware will really do.) In practice, just setting
all variables to one at startup finds most problems.
=head2 Tri/Inout
Verilator converts some simple tristate structures into two state. An assignment
of the form:
Verilator converts some simple tristate structures into two state. Pullup,
pulldown, bufif0, bufif1, notif0, notif1, pmos, nmos, tri0 and tri1 are
also supported. Simple comparisons with === 1'bz are also supported.
An assignment of the form:
inout driver;
wire driver = (enable) ? output_value : 1'bz;
Will be converted to
input driver__in; // Value being driven in from "external" drivers
output driver__en; // True if driven from this module
output driver__enout; // Value being driven from this module
input driver; // Value being driven in from "external" drivers
output driver__en; // True if driven from this module
output driver__out; // Value being driven from this module
Pullup, pulldown, bufif0, bufif1, notif0, notif1 are also supported.
External logic will be needed to combine these signals with any external
drivers.
@@ -2214,10 +2443,12 @@ different.)
=head2 Generated Clocks
Verilator attempts to deal with generated clocks correctly, however new
cases may turn up bugs in the scheduling algorithm. The safest option is
to have all clocks as primary inputs to the model, or wires directly
attached to primary inputs.
Verilator attempts to deal with generated and enabled clocks correctly,
however some cases cause problems in the scheduling algorithm which is
optimized for performance. The safest option is to have all clocks as
primary inputs to the model, or wires directly attached to primary inputs.
For proper behavior clock enables may also need the /*verilator
clock_enable*/ attribute.
=head2 Ranges must be big-bit-endian
@@ -2294,6 +2525,12 @@ Increment/decrement can only be used as standalone statements or in for
loops. They cannot be used as side effect operators inside more complicate
expressions ("a = b++;").
=item '{} operator
Assignment patterns with order based, default, constant integer (array) or
member identifier (struct/union) keys are supported. Data type keys and
keys which are computed from a constant expression are not supported.
=item cast operator
Casting is supported only between simple scalar types, signed and unsigned,
@@ -2655,6 +2892,15 @@ command line to specify the top include source directory.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item INITIALDLY
Warns that you have a delayed assignment inside of an initial or final
block. If this message is suppressed, Verilator will convert this to a
non-delayed assignment. See also the COMBDLY warning.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item LITENDIAN
Warns that a vector is declared with little endian bit numbering
@@ -2692,6 +2938,23 @@ not really needed. The best solution is to insure that each module is in a
unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y.
=item PINMISSING
Warns that a module has a pin which is not mentioned in a cell
instantiation. If a pin is not missing it should still be specified on the
cell declaration with a empty connection,using "(.pin_name())".
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item PINNOCONNECT
Warns that a cell instantiation has a pin which is not connected to another
signal.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item REALCVT
Warns that a real number is being implicitly rounded to an integer, with
@@ -2714,6 +2977,23 @@ is not possible, add a undef to indicate the code is overriding the value:
`undef MACRO
`define MACRO otherdef
=item SELRANGE
Warns that a selection index will go out of bounds:
wire vec[6:0];
initial out = vec[7]; // There is no 7
Verilator will assume zero for this value, instead of X. Note that in some
cases this warning may be false, when a condition upstream or downstream of
the access means the access out of bounds will never execute or be used.
wire vec[6:0];
initial begin
seven = 7;
...
if (seven != 7) out = vec[seven]; // Never will use vec[7]
=item STMTDLY
Warns that you have a statement with a delayed time in front of it, for
@@ -3321,12 +3601,27 @@ follows:
cp -p t/t_EXAMPLE.pl t/t_BUG.pl
cp -p t/t_EXAMPLE.v t/t_BUG.v
There are many hits on how to write a good test in the driver.pl
documentation which can be seen by running:
cd $VERILATOR_ROOT # Need the original distribution kit
test_regress/driver.pl --help
Edit t/t_BUG.pl to suit your example; you can do anything you want in the
Verilog code there; just make sure it retains the single clk input and no
outputs. Now, the following should fail:
cd $VERILATOR_ROOT # Need the original distribution kit
cd test_regress
t/t_BUG.pl
t/t_BUG.pl # Run on Verilator
t/t_BUG.pl --debug # Run on Verilator, passing --debug to Verilator
t/t_BUG.pl --vcs # Run on a commercial simulator
t/t_BUG.pl --nc|--iv|--ghdl # Likewise on other simulators
The test driver accepts a number of options, many of which mirror the main
Verilator option. For example the previous test could have been run with
debugging enabled. The full set of test options can be seen by running
driver.pl --help as shown above.
Finally, report the bug using the bug tracker at
L<http://www.veripool.org/verilator>. The bug will become publicly
@@ -3370,43 +3665,44 @@ faster than many popular commercial simulators.
Many people have provided ideas and other assistance with Verilator.
The major corporate sponsors of Verilator, by providing significant
contributions of time or funds include include Compaq Corporation, Digital
Equipment Corporation, Intel Corporation, Mindspeed Technologies Inc.,
MicroTune Inc., picoChip Designs Ltd., Sun Microsystems, Nauticus Networks,
and SiCortex Inc.
contributions of time or funds include include Cavium Networks, Compaq
Corporation, Digital Equipment Corporation, Embecosm Ltd., Hicamp Systems,
Intel Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip
Designs Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
The people who have contributed major functionality are Byron Bradley, Lane
Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder. Major testers include
Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
The people who have contributed major functionality are Byron Bradley,
Jeremy Bennett, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder.
Major testers include Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels,
Alex Solomatnikov, Sebastien Van Cauwenberghe and Gene Weber.
Some of the people who have provided ideas and feedback for Verilator
include: David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
Baxter, Jeremy Bennett, David Black, Gregg Bouchard, Christopher Boumenot,
Nick Bowler, Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee,
Lawrence Butcher, Chris Candler, Lauren Carlson, Donal Casey, Terry Chen,
Robert A. Clark, Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard
Deadman, John Deroo, John Dickol, Danny Ding, Ivan Djordjevic, Alex Duller,
Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell,
Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone,
Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins, David Hewson,
Jae Hossell, Ben Jackson, Iztok Jeras, Mike Kagen, Guy-Armand Kamendje,
Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan
Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Stephane
Laurent, Christian Leber, Charlie Lind, Paul Liu, Dan Lussier, Fred Ma,
include: David Addison, Vasu Arasanipalai, Jens Arm, J Baxter, Jeremy
Bennett, David Black, Gregg Bouchard, Christopher Boumenot, Nick Bowler,
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher,
Chris Candler, Lauren Carlson, Donal Casey, Terry Chen, Robert A. Clark,
Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, Mike
Denio, John Deroo, John Dickol, Ruben Diez, Danny Ding, Ivan Djordjevic,
Alex Duller, Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy,
Robert Farrell, Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri,
Sam Gladstone, Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins,
David Hewson, Jae Hossell, Ben Jackson, Iztok Jeras, Christophe Joly, Mike
Kagen, Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan
Katz, Sol Katzman, Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki,
David Kravitz, Steve Lang, Stephane Laurent, Walter Lavino, Christian
Leber, John Li, Charlie Lind, Andrew Ling, Paul Liu, Dan Lussier, Fred Ma,
Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Oleg Rodionov, John
Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey
Short, Rodney Sinclair, Brian Small, Alex Solomatnikov, Art Stamness, John
Stroebel, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Stefan
Thiede, Gary Thomas, Steve Tong, Holger Waechtler, Stefan Wallentowitz,
Shawn Wang, Greg Waters, Eugene Weber, David Welch, Leon Wildman, Gerald
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Johan Wouters, and
Ding Xiaoliang.
Thanks all.
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Alberto Del Rio, Oleg
Rodionov, John Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael
Shirakawa, Jeffrey Short, Rodney Sinclair, Brian Small, Alex Solomatnikov,
Art Stamness, John Stroebel, Emerson Suguimoto, Gene Sullivan, Renga
Sundararajan, Stefan Thiede, Gary Thomas, Steve Tong, Hans Van Antwerpen,
Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters, Thomas
Watts, Eugene Weber, David Welch, Leon Wildman, Gerald Williams, Trevor
Williams, Jeff Winston, Joshua Wise, Johan Wouters, and Ding Xiaoliang.
Thanks to them, and all those we've missed including above.
=head1 DISTRIBUTION
@@ -3427,9 +3723,11 @@ Major concepts by Paul Wasson and Duane Galbi.
=head1 SEE ALSO
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>,
And internals.txt in the distribution.
L<verilator --help> which is the source for this document,
and internals.txt in the distribution.
=cut
+62 -4
View File
@@ -14,6 +14,19 @@ use vars qw ($Debug);
#======================================================================
# Old version 1 dump nodes with no dtypep's
our %Ver1_Non_Dtyped = map {$_ => 1} qw(
ACTIVE ALWAYS ALWAYSPOST ALWAYSPUBLIC ATTROF BEGIN BREAK CASE CASEITEM
CCALL CELL CELLINLINE CFILE CFUNC CHANGEDET CLOCKING COMMENT CONTINUE
COVERDECL COVERINC COVERTOGGLE CRETURN CSTMT DEFPARAM DISABLE DISPLAY DOT
DPIEXPORT FCLOSE FFLUSH FINAL FINISH FOPEN GENCASE GENERATE GENFOR GENIF
IF IMPLICIT INITARRAY INITIAL JUMPGO JUMPLABEL MODULE NETLIST
NOTFOUNDMODULE PACKAGE PACKAGEIMPORT PARSEREF PIN PORT PRAGMA PRIMITIVE
PSLASSERT PSLCOVER PSLDEFCLOCK PULL RANGE READMEM REPEAT RETURN SCCTOR
SCDTOR SCHDR SCIMP SCIMPHDR SCINT SCOPE SELBIT SELEXTRACT SELMINUS
SELPLUS SENGATE SENITEM SENTREE SFORMAT SFORMATF STOP SYSIGNORE SYSTEMT
TASK TASKREF TEXT TOPSCOPE TYPEDEFFWD TYPETABLE UCSTMT UDPTABLE
UDPTABLELINE UNTILSTABLE VASSERT WHILE );
#======================================================================
# main
@@ -79,27 +92,72 @@ sub diff_file {
my $a = shift;
my $b = shift;
# Compare the two tree files
my $tmp_a = "/tmp/$$.a";
my $tmp_b = "/tmp/$$.b";
(my $short_a = $a) =~ s/[^a-zA-Z0-9.]+/_/g;
(my $short_b = $b) =~ s/[^a-zA-Z0-9.]+/_/g;
my $tmp_a = "/tmp/${$}_${short_a}.a";
my $tmp_b = "/tmp/${$}_${short_b}.b";
filter ($a, $tmp_a);
filter ($b, $tmp_b);
my $vera = version_from($a);
my $verb = version_from($b);
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|| ($vera >= 0x3900 && $verb < 0x3900));
filter ($a, $tmp_a, $verCvt);
filter ($b, $tmp_b, $verCvt);
system("diff -u $tmp_a $tmp_b");
unlink $tmp_a;
unlink $tmp_b;
}
sub version_from {
my $fn = shift;
# Return dump format
my $f1 = IO::File->new ($fn) or die "%Error: $! $fn,";
while (defined (my $line=$f1->getline())) {
last if $. > 10;
return hex $1 if $line =~ /\(format (0x[0-9.]+)\)/;
}
return 1.0;
}
sub filter {
my $fn1 = shift;
my $fn2 = shift;
my $verCvt = shift;
# Remove hex numbers before diffing
my $f1 = IO::File->new ($fn1) or die "%Error: $! $fn1,";
my $f2 = IO::File->new ($fn2,"w") or die "%Error: $! $fn2,";
while (defined (my $line=$f1->getline())) {
same_line:
next if $line =~ / This=/;
$line =~ s/0x[a-f0-9]+/0x/g;
$line =~ s/<e[0-9]+\#?>/<e>/g;
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
if ($verCvt) {
next if $line =~ /^ NETLIST/;
$line =~ s!\@dt=0x\(G?/?([^)]+)\)!$1!g; # NEW: @dt -> OLD: non @dt format
# # Below Ver1_Non_Dtyped may replace above further
if ($line =~ /: ([A-Z]+) /) {
my $type = $1;
next if $type =~ 'DTYPE';
if ($type eq 'TYPETABLE' || $type eq 'RANGE') {
$line =~ /^(\s+\S+:) /; my $prefix = $1;
while (defined ($line=$f1->getline())) {
next if $line =~ /^\s+[a-z]/; # Table body
next if $line =~ /^${prefix}[0-9]:/;
goto same_line;
}
next;
}
if ($Ver1_Non_Dtyped{$type}) {
$line =~ s! w[0-9]+!!g;
}
}
$line =~ s!\@dt=0$!NoW!g; # NEW: dt=null -> common format
$line =~ s!\@dt=0 !NoW !g; # NEW: dt=null -> common format
$line =~ s! s?w0$! NoW!g; # OLD: no width -> common format
$line =~ s! s?w0 ! NoW !g; # OLD: no width -> common format
}
print $f2 $line;
}
$f1->close;
+4 -1
View File
@@ -4,7 +4,9 @@
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
AC_INIT([Verilator],[3.832 2012-03-07])
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.843 2012-12-01])
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
@@ -128,6 +130,7 @@ _MY_CXX_CHECK_OPT(-Wno-sign-compare)
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Checks for library functions.
+6
View File
@@ -0,0 +1,6 @@
/*! \mainpage Verilator Doxygen Documentation
*
* \section intro_sec Introduction
*
* This is a full doxygen analysis of the Verilator source tree.
*/
+1772
View File
File diff suppressed because it is too large Load Diff
+31 -16
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -27,20 +27,16 @@
#include "verilated_imp.h"
#include <cctype>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
//===========================================================================
// Global variables
// Slow path variables
int Verilated::s_randReset = 0;
VerilatedVoidCb Verilated::s_flushCb = NULL;
// Keep below together in one cache line
int Verilated::s_debug = 0;
bool Verilated::s_calcUnusedSigs = false;
bool Verilated::s_gotFinish = false;
bool Verilated::s_assertOn = true;
Verilated::Serialized Verilated::s_s;
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
VL_THREAD const char* Verilated::t_dpiFilename = "";
VL_THREAD int Verilated::t_dpiLineno = 0;
@@ -81,6 +77,17 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
}
#endif
//===========================================================================
// Overall class init
Verilated::Serialized::Serialized() {
s_randReset = 0;
s_debug = 0;
s_calcUnusedSigs = false;
s_gotFinish = false;
s_assertOn = true;
}
//===========================================================================
// Random reset -- Only called at init time, so don't inline.
@@ -301,7 +308,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
const char *ep = pos;
while (ep[0] && ep[0]!='%') ep++;
if (ep != pos) {
output += string(pos, ep-pos);
output.append(pos, ep-pos);
pos += ep-pos-1;
}
} else { // Format character
@@ -346,9 +353,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
// Deal with all read-and-print somethings
const int lbits = va_arg(ap, int);
QData ld = 0;
WData qlwp[2];
WDataInP lwp;
if (lbits <= VL_QUADSIZE) {
WData qlwp[2];
ld = _VL_VA_ARG_Q(ap, lbits);
VL_SET_WQ(qlwp,ld);
lwp = qlwp;
@@ -750,9 +757,10 @@ void VL_FCLOSE_I(IData fdi) {
}
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
string output;
_vl_vsformat(output, formatp, ap);
va_end(ap);
@@ -760,9 +768,10 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
}
string VL_SFORMATF_NX(const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
string output;
_vl_vsformat(output, formatp, ap);
va_end(ap);
@@ -770,9 +779,10 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
}
void VL_WRITEF(const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
string output;
_vl_vsformat(output, formatp, ap);
va_end(ap);
@@ -781,12 +791,13 @@ void VL_WRITEF(const char* formatp, ...) {
}
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return;
va_list ap;
va_start(ap,formatp);
string output;
_vl_vsformat(output, formatp, ap);
va_end(ap);
@@ -949,13 +960,13 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
}
IData VL_TESTPLUSARGS_I(const char* formatp) {
string match = VerilatedImp::argPlusMatch(formatp);
const string& match = VerilatedImp::argPlusMatch(formatp);
if (match == "") return 0;
else return 1;
}
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
string match = VerilatedImp::argPlusMatch(prefixp);
const string& match = VerilatedImp::argPlusMatch(prefixp);
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
if (match == "") return 0;
VL_ZERO_RESET_W(rbits, rwp);
@@ -991,7 +1002,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
}
const char* vl_mc_scan_plusargs(const char* prefixp) {
string match = VerilatedImp::argPlusMatch(prefixp);
const string& match = VerilatedImp::argPlusMatch(prefixp);
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match == "") return NULL;
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
@@ -1056,6 +1067,10 @@ void Verilated::commandArgs(int argc, const char** argv) {
VerilatedImp::commandArgs(argc,argv);
}
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
return VerilatedImp::argPlusMatch(prefixp).c_str();
}
void Verilated::scopesDump() {
VerilatedImp::scopesDump();
}
+24 -17
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -219,14 +219,18 @@ struct Verilated {
// MEMBERS
private:
// Slow path variables
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
static VerilatedVoidCb s_flushCb; ///< Flush callback function
// Fast path
static int s_debug; ///< See accessors... only when VL_DEBUG set
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
static bool s_gotFinish; ///< A $finish statement executed
static bool s_assertOn; ///< Assertions are enabled
static struct Serialized { // All these members serialized/deserialized
// Slow path
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
// Fast path
int s_debug; ///< See accessors... only when VL_DEBUG set
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
bool s_gotFinish; ///< A $finish statement executed
bool s_assertOn; ///< Assertions are enabled
Serialized();
} s_s;
static VL_THREAD const VerilatedScope* t_dpiScopep; ///< DPI context scope
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
@@ -241,29 +245,29 @@ public:
/// 0 = Set to zeros
/// 1 = Set all bits to one
/// 2 = Randomize all bits
static void randReset(int val) { s_randReset=val; }
static int randReset() { return s_randReset; } ///< Return randReset value
static void randReset(int val) { s_s.s_randReset=val; }
static int randReset() { return s_s.s_randReset; } ///< Return randReset value
/// Enable debug of internal verilated code
static inline void debug(int level) { s_debug = level; }
static inline void debug(int level) { s_s.s_debug = level; }
#ifdef VL_DEBUG
static inline int debug() { return s_debug; } ///< Return debug value
static inline int debug() { return s_s.s_debug; } ///< Return debug value
#else
static inline int debug() { return 0; } ///< Constant 0 debug, so C++'s optimizer rips up
#endif
/// Enable calculation of unused signals
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
static void calcUnusedSigs(bool flag) { s_s.s_calcUnusedSigs=flag; }
static bool calcUnusedSigs() { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
/// Did the simulation $finish?
static void gotFinish(bool flag) { s_gotFinish=flag; }
static bool gotFinish() { return s_gotFinish; } ///< Return if got a $finish
static void gotFinish(bool flag) { s_s.s_gotFinish=flag; }
static bool gotFinish() { return s_s.s_gotFinish; } ///< Return if got a $finish
/// Allow traces to at some point be enabled (disables some optimizations)
static void traceEverOn(bool flag) {
if (flag) { calcUnusedSigs(flag); }
}
/// Enable/disable assertions
static void assertOn(bool flag) { s_assertOn=flag; }
static bool assertOn() { return s_assertOn; }
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
static bool assertOn() { return s_s.s_assertOn; }
/// Flush callback for VCD waves
static void flushCb(VerilatedVoidCb cb);
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
@@ -271,6 +275,7 @@ public:
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
static void commandArgs(int argc, const char** argv);
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
static const char* commandArgsPlusMatch(const char* prefixp);
/// For debugging, print text list of all scope names with
/// dpiImport/Export context. This function may change in future
@@ -292,6 +297,8 @@ public:
static const char* dpiFilenamep() { return t_dpiFilename; }
static int dpiLineno() { return t_dpiLineno; }
static int exportFuncNum(const char* namep);
static size_t serializedSize() { return sizeof(s_s); }
static void* serializedPtr() { return &s_s; }
};
//=========================================================================
+1 -2
View File
@@ -1,4 +1,3 @@
// -*- C++ -*-
//*************************************************************************
//
// Code available from: http://www.veripool.org/verilator
@@ -23,7 +22,7 @@
`define _VERILATED_V_ 1
// Hide verilator pragmas from other tools
`ifdef verilator `else
`ifdef VERILATOR `else
`define coverage_block_off
`endif
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2010-2012 by Wilson Snyder. This program is free software; you can
+4 -2
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
@@ -55,7 +55,9 @@ class VerilatedImp {
// MEMBERS
static VerilatedImp s_s; ///< Static Singleton; One and only static this
ArgVec m_argVec; ///< Argument list
// Nothing here is save-restored; users expected to re-register appropriately
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
bool m_argVecLoaded; ///< Ever loaded argument list
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
+231
View File
@@ -0,0 +1,231 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2012 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
// This is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
//=============================================================================
///
/// \file
/// \brief C++ Tracing in VCD Format
///
/// AUTHOR: Wilson Snyder
///
//=============================================================================
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_save.h"
#include <fcntl.h>
#include <cerrno>
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# include <io.h>
#else
# include <unistd.h>
#endif
#ifndef O_LARGEFILE // For example on WIN32
# define O_LARGEFILE 0
#endif
#ifndef O_NONBLOCK
# define O_NONBLOCK 0
#endif
// CONSTANTS
static const char* VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
static const char* VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
//=============================================================================
//=============================================================================
//=============================================================================
// Searalization
bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t size) {
bufferCheck();
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
vluint8_t miss = 0;
while (size--) {
miss |= (*dp++ ^ *m_cp++);
}
return (miss!=0);
}
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
if (VL_UNLIKELY(readDiffers(datap,size))) {
string msg = (string)"Can't deserialize save-restore file as was made from different model";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
close();
}
return *this; // For function chaining
}
void VerilatedSerialize::header() {
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
assert((strlen(VLTSAVE_HEADER_STR) & 7) == 0); // Keep aligned
os.write(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR));
// Verilated doesn't do it itself, as if we're not using save/restore
// it doesn't need to compile this stuff in
os.write(Verilated::serializedPtr(), Verilated::serializedSize());
}
void VerilatedDeserialize::header() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
string msg = (string)"Can't deserialize; file has wrong header signature";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
close();
}
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
}
void VerilatedSerialize::trailer() {
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
assert((strlen(VLTSAVE_TRAILER_STR) & 7) == 0); // Keep aligned
os.write(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR));
}
void VerilatedDeserialize::trailer() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
close();
}
}
//=============================================================================
//=============================================================================
//=============================================================================
// Opening/Closing
void VerilatedSave::open (const char* filenamep) {
if (isOpen()) return;
VL_DEBUG_IF(VL_PRINTF("-vltSave: opening save file %s\n",filenamep););
if (filenamep[0]=='|') {
assert(0); // Not supported yet.
} else {
m_fd = ::open (filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
, 0666);
if (m_fd<0) {
// User code can check isOpen()
m_isOpen = false;
return;
}
}
m_isOpen = true;
m_filename = filenamep;
m_cp = m_bufp;
header();
}
void VerilatedRestore::open (const char* filenamep) {
if (isOpen()) return;
VL_DEBUG_IF(VL_PRINTF("-vltRestore: opening restore file %s\n",filenamep););
if (filenamep[0]=='|') {
assert(0); // Not supported yet.
} else {
m_fd = ::open (filenamep, O_CREAT|O_RDONLY|O_LARGEFILE
, 0666);
if (m_fd<0) {
// User code can check isOpen()
m_isOpen = false;
return;
}
}
m_isOpen = true;
m_filename = filenamep;
m_cp = m_bufp;
m_endp = m_bufp;
header();
}
void VerilatedSave::close () {
if (!isOpen()) return;
trailer();
flush();
m_isOpen = false;
::close(m_fd); // May get error, just ignore it
}
void VerilatedRestore::close () {
if (!isOpen()) return;
trailer();
flush();
m_isOpen = false;
::close(m_fd); // May get error, just ignore it
}
//=============================================================================
// Buffer management
void VerilatedSave::flush() {
if (VL_UNLIKELY(!isOpen())) return;
vluint8_t* wp = m_bufp;
while (1) {
ssize_t remaining = (m_cp - wp);
if (remaining==0) break;
errno = 0;
ssize_t got = ::write (m_fd, wp, remaining);
if (got>0) {
wp += got;
} else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space)
string msg = string(__FUNCTION__)+": "+strerror(errno);
vl_fatal("",0,"",msg.c_str());
close();
break;
}
}
}
m_cp = m_bufp; // Reset buffer
}
void VerilatedRestore::fill() {
if (VL_UNLIKELY(!isOpen())) return;
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
vluint8_t* rp = m_bufp;
for (vluint8_t* sp=m_cp; rp < m_endp;) *rp++ = *sp++; // Overlaps
m_endp = m_bufp + (m_endp - m_cp);
m_cp = m_bufp; // Reset buffer
// Read into buffer starting at m_endp
while (1) {
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
if (remaining==0) break;
errno = 0;
ssize_t got = ::read (m_fd, m_endp, remaining);
if (got>0) {
m_endp += got;
} else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space)
string msg = string(__FUNCTION__)+": "+strerror(errno);
vl_fatal("",0,"",msg.c_str());
close();
break;
}
} else { // got==0, EOF
// Fill buffer from here to end with NULLs so reader's don't need to check eof each character.
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
break;
}
}
}
//=============================================================================
// Serialization of types
+234
View File
@@ -0,0 +1,234 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2012-2012 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
// This is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
//=============================================================================
///
/// \file
/// \brief Save-restore serialization of verilated modules
///
/// AUTHOR: Wilson Snyder
///
//=============================================================================
#ifndef _VERILATED_SAVE_C_H_
#define _VERILATED_SAVE_C_H_ 1
#include "verilatedos.h"
#include <string>
using namespace std;
//=============================================================================
// VerilatedSerialBase - internal base class for common code between VerilatedSerialize and VerilatedDeserialize
class VerilatedSerialBase {
protected:
// MEMBERS
// For speed, keep m_cp as the first member of this structure
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
vluint8_t* m_bufp; ///< Output buffer
bool m_isOpen; ///< True indicates open file/stream
string m_filename;
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
inline static size_t bufferInsertSize() { return 16*1024; }
// CREATORS
VerilatedSerialBase() {
m_isOpen = false;
m_bufp = new vluint8_t [bufferSize()];
m_cp = m_bufp;
}
public:
// CREATORS
virtual ~VerilatedSerialBase() {
close();
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
}
// METHODS
bool isOpen() const { return m_isOpen; }
string filename() const { return m_filename; }
virtual void close() { flush(); }
virtual void flush() {}
};
//=============================================================================
// VerilatedSerialize - convert structures to a stream representation
class VerilatedSerialize : public VerilatedSerialBase {
protected:
virtual void close() { flush(); }
virtual void flush() {}
void header();
void trailer();
public:
// CREATORS
VerilatedSerialize() {}
virtual ~VerilatedSerialize() { close(); }
// METHODS
VerilatedSerialize& bufferCheck() {
// Flush the write buffer if there's not enough space left for new information
// We only call this once per vector, so we need enough slop for a very wide "b###" line
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
flush();
}
return *this; // For function chaining
}
inline VerilatedSerialize& write (const void* __restrict datap, size_t size) {
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
while (size) {
bufferCheck();
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk;
while (dp < maxp) *m_cp++ = *dp++;
size -= blk;
}
return *this; // For function chaining
}
};
//=============================================================================
// VerilatedDeserial - load structures from a stream representation
class VerilatedDeserialize : public VerilatedSerialBase {
protected:
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
virtual void fill() = 0;
void header();
void trailer();
public:
// CREATORS
VerilatedDeserialize() {}
virtual ~VerilatedDeserialize() { close(); }
// METHODS
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
while (size) {
bufferCheck();
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
const vluint8_t* __restrict maxp = dp + blk;
while (dp < maxp) *dp++ = *m_cp++;
size -= blk;
}
return *this; // For function chaining
}
// Read a datum and compare with expected value
bool readDiffers (const void* __restrict datap, size_t size);
VerilatedDeserialize& readAssert (const void* __restrict datap, size_t size);
VerilatedDeserialize& readAssert (vluint64_t data) { return readAssert(&data, sizeof(data)); }
VerilatedDeserialize& bufferCheck() {
// Flush the write buffer if there's not enough space left for new information
// We only call this once per vector, so we need enough slop for a very wide "b###" line
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
fill();
}
return *this; // For function chaining
}
};
//=============================================================================
// VerilatedSave - serialize to a file
class VerilatedSave : public VerilatedSerialize {
private:
int m_fd; ///< File descriptor we're writing to
public:
// CREATORS
VerilatedSave() {}
virtual ~VerilatedSave() { close(); }
// METHODS
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
void open(const string& filename) { open(filename.c_str()); }
virtual void close();
virtual void flush();
};
//=============================================================================
// VerilatedRestore - deserialize from a file
class VerilatedRestore : public VerilatedDeserialize {
private:
int m_fd; ///< File descriptor we're writing to
public:
// CREATORS
VerilatedRestore() {}
virtual ~VerilatedRestore() { close(); }
// METHODS
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
void open(const string& filename) { open(filename.c_str()); }
virtual void close();
virtual void flush() {}
virtual void fill();
};
//=============================================================================
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint64_t& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs){
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint32_t& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint16_t& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint8_t& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, bool& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, bool& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, double& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, double& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
return os.write(&rhs, sizeof(rhs));
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
vluint32_t len=rhs.length();
os<<len;
return os.write(rhs.data(), len);
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
vluint32_t len;
os>>len;
rhs.resize(len);
return os.read((void*)rhs.data(), len);
}
#endif // guard
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- SystemC -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- SystemC -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- SystemC -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- SystemC -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
+1 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
+3 -3
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
@@ -182,7 +182,7 @@ public:
vluint32_t entSize() const { return m_entSize; }
virtual const char* name() { return m_varp->name(); }
virtual const char* fullname() {
static VL_THREAD string out;
VL_STATIC_OR_THREAD string out;
out = string(m_scopep->name())+"."+name();
return out.c_str();
}
@@ -207,7 +207,7 @@ public:
virtual ~VerilatedVpioVarIndex() {}
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
virtual const char* fullname() {
static VL_THREAD string out;
VL_STATIC_OR_THREAD string out;
char num[20]; sprintf(num,"%d",m_index);
out = string(scopep()->name())+"."+name()+"["+num+"]";
return out.c_str();
+5 -1
View File
@@ -1,4 +1,4 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -78,8 +78,12 @@
# else
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
# endif
# define VL_STATIC_OR_THREAD ///< Static if unthreaded, as some strings can be faster
// ///< if non-dynamic and can't do "static VL_THREAD string"
#else
# define VL_THREAD ///< Storage class for thread-local storage
# define VL_STATIC_OR_THREAD static ///< Static if unthreaded, as some strings can be faster
// ///< if non-dynamic and can't do "static VL_THREAD string"
#endif
#ifdef _MSC_VER
+6
View File
@@ -27,6 +27,8 @@ typedef signed __int32 int32_t;
typedef signed __int8 int8_t;
#elif defined(__MINGW32__)
#include <stdint.h>
#elif defined(__APPLE__)
#include <stdint.h>
#elif defined(__linux)
#include <inttypes.h>
#else
@@ -34,18 +36,22 @@ typedef signed __int8 int8_t;
#endif
/* Use to export a symbol from application */
#ifndef DPI_DLLISPEC
#if defined (_MSC_VER)
#define DPI_DLLISPEC __declspec(dllimport)
#else
#define DPI_DLLISPEC
#endif
#endif
/* Use to import a symbol into application */
#ifndef DPI_DLLESPEC
#if defined (_MSC_VER)
#define DPI_DLLESPEC __declspec(dllexport)
#else
#define DPI_DLLESPEC
#endif
#endif
/* Use to mark a function as external */
#ifndef DPI_EXTERN
+515 -74
View File
@@ -14,32 +14,6 @@ the first for reference for developers and debugging problems.
See also the Verilator internals presentation at http://www.veripool.org.
=head1 ADDING A NEW FEATURE
Generally what would you do to add a new feature?
=over 4
File a bug (if there isn't already) so others know what you're working on.
Make a testcase in the test_regress/t/t_EXAMPLE format, see TESTING Below.
If grammar changes are needed, look at the git version of VerilogPerl's
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
language and has a lot of back-and-forth with Verilator's grammar. Copy
the appropriate rules to src/verilog.y and modify the productions.
If a new Ast type is needed, add it to V3AstNodes.h.
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
file which you can examine to see if the parsing worked. See also the
sections below on debugging.
Modify the later visitor functions to process the new feature as needed.
=back
=head1 CODE FLOWS
=head2 Verilator Flow
@@ -52,7 +26,11 @@ 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.
Verilator then makes a series of passes over the AST, progressively refining
and optimizing it.
Cells in the AST first linked, which will read and parse additional files as
above.
Functions, variable and other references are linked to their definitions.
@@ -87,6 +65,96 @@ hints, and performs additional constant propagation.
Verilator finally writes the C++ modules.
=head2 Key Classes Used in the Verilator Flow
=over 4
=item C<AstNode>
The AST is represented at the top level by the class C<AstNode>. This abstract
class has derived classes for the individual components (e.g. C<AstGenerate>
for a generate block) or groups of components (e.g. C<AstNodeFTask> for
functions and tasks, which in turn has C<AstFunc> and C<AstTask> as derived
classes).
Each C<AstNode> has pointers to up to four children, accessed by the
C<op1p> through C<op4p> methods. These methods are then abstracted in a
specific Ast* node class to a more specific name. For example with the
C<AstIf> node (for C<if> statements), C<ifsp> calls C<op1p> to give the
pointer to the AST for the "then" block, while C<elsesp> calls C<op2p> to
give the pointer to the AST for the "else" block, or NULL if there is not
one.
C<AstNode> has the concept of a next and previous AST - for example the
next and previous statements in a block. Pointers to the AST for these
statements (if they exist) can be obtained using the C<back> and C<next>
methods.
It is useful to remember that the derived class C<AstNetlist> is at the top
of the tree, so checking for this class is the standard way to see if you
are at the top of the tree.
By convention, each function/method uses the variable C<nodep> as a pointer
to the C<AstNode> currently being processed.
=item C<AstNVistor>
The passes are implemented by AST visitor classes (see L</Visitor
Functions>). These are implemented by subclasses of the abstract class,
C<AstNVisitor>. Each pass creates an instance of the visitor class, which
in turn implements a method to perform the pass.
=item C<V3Graph>
A number of passes use graph algorithms, and the class C<V3Graph> is provided
to represent those graphs. Graphs are directed, and algorithms are provided to
manipulate the graphs and to output them in I<GraphViz> dot format (see
L<http://www.graphviz.org/>). C<V3Graph.h> provides documentation of this
class.
=item C<V3GraphVertex>
This is the base class for vertices in a graph. Vertices have an associated
C<fanout>, C<color> and C<rank>, which may be used in algorithms for ordering
the graph. A generic C<user>/C<userp> member variable is also provided.
Virtual methods are provided to specify the name, color, shape and style to be
used in dot output. Typically users provided derived classes from
C<V3GraphVertex> which will reimplement these methods.
Iterators are provided to access in and out edges. Typically these are used in
the form:
for (V3GraphEdge *edgep = vertexp->inBeginp();
edgep;
edgep = edgep->inNextp()) {
=item C<V3GraphEdge>
This is the base class for directed edges between pairs of vertices. Edges
have an associated C<weight> and may also be made C<cutable>. A generic
C<user>/C<userp> member variable is also provided.
Accessors, C<fromp> and C<top> return the "from" and "to" vertices
respectively.
Virtual methods are provided to specify the label, color and style to be
used in dot output. Typically users provided derived classes from
C<V3GraphEdge> which will reimplement these methods.
=item C<V3GraphAlg>
This is the base class for graph algorithms. It implements a C<bool> method,
C<followEdge> which algorithms can use to decide whether an edge is
followed. This method returns true if the graph edge has weight greater than
one and a user function, C<edgeFuncp> (supplied in the constructor) returns
C<true>.
A number of predefined derived algorithm classes and access methods are
provided and documented in C<V3GraphAlg.cpp>.
=back
=head2 Verilated Flow
The evaluation loop outputted by Verilator is designed to allow a single
@@ -120,64 +188,256 @@ changed; if clear, checking those signals for changes may be skipped.
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
All files should contain the magic header to insure standard indentation:
(add-hook 'c-mode-common-hook '(lambda ()
(c-set-style "cc-mode"))))
// -*- mode: C++; c-file-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 The C<astgen> script
Some of the code implementing passes is extremely repetitive, and must be
implemented for each sub-class of C<AstNode>. However, while repetitive,
there is more variability than can be handled in C++ macros.
In Verilator this is implemented by using a Perl script, C<astgen> to
pre-process the C++ code. For example in C<V3Const.cpp> this is used to
implement the C<visit()> functions for each binary operation using the
TREEOP macro.
The original C++ source code is transformed into C++ code in the C<obj_opt>
and C<obj_dbg> sub-directories (the former for the optimized version of
Verilator, the latter for the debug version). So for example C<V3Const.cpp>
into C<V3Const__gen.cpp>.
=head2 Visitor Functions
There's three ways data is passed between visitor functions.
Verilator uses the I<Visitor> design pattern to implement its refinement
and optimization passes. This allows separation of the pass algorithm from
the AST on which it operates. Wikipedia provides an introduction to the
concept at L<http://en.wikipedia.org/wiki/Visitor_pattern>.
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.
As noted above, all visitors are derived classes of C<AstNvisitor>. All
derived classes of C<AstNode> implement the C<accept> method, which takes
as argument a reference to an instance or a C<AstNVisitor> derived class
and applies the visit method of the C<AstNVisitor> to the invoking AstNode
instance (i.e. C<this>).
One possible difficulty is that a call to C<accept> may perform an edit
which destroys the node it receives as argument. The
C<acceptSubtreeReturnEdits> method of C<AstNode> is provided to apply
C<accept> and return the resulting node, even if the original node is
destroyed (if it is not destroyed it will just return the original node).
The behavior of the visitor classes is achieved by overloading the C<visit>
function for the different C<AstNode> derived classes. If a specific
implementation is not found, the system will look in turn for overloaded
implementations up the inheritance hierarchy. For example calling C<accept>
on C<AstIf> will look in turn for:
void visit (AstIf* nodep, AstNUser* vup)
void visit (AstNodeIf* nodep, AstNUser* vup)
void visit (AstNodeStmt* nodep, AstNUser* vup)
void visit (AstNode* nodep, AstNUser* vup)
There are three ways data is passed between visitor functions.
=over 4
=item 1.
A visitor-class member variable. This is generally for passing "parent"
information down to children. C<m_modp> is a common example. It's set to
NULL in the constructor, where that node (C<AstModule> visitor) sets it,
then the children are iterated, then it's cleared. Children under an
C<AstModule> will see it set, while nodes elsewhere will see it clear. If
there can be nested items (for example an C<AstFor> under an C<AstFor>) the
variable needs to be save-set-restored in the C<AstFor> visitor, otherwise
exiting the lower for will lose the upper for's setting.
=item 2.
User attributes. Each C<AstNode> (B<Note.> The AST node, not the visitor)
has five user attributes, which may be accessed as an integer using the
C<user1()> through C<user5()> methods, or as a pointer (of type
C<AstNuser>) using the C<user1p()> through C<user5p()> methods (a common
technique lifted from graph traversal packages).
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:
C<AstNode::user#ClearTree()>, then it can mark any node's user() with whatever
data it wants. Readers just call C<< nodep->user() >>, but may need to cast
appropriately, so you'll often see C<< nodep->userp()->castSOMETYPE() >>. At
the top of each visitor are comments describing how the C<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.
This says that at the C<AstNetlist> C<user1ClearTree()> is called. Each
C<AstModule>'s C<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.
These comments are important to make sure a C<user#()> on a given C<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
Note that calling C<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.)
=item 3.
Parameters can be passed between the visitors in close to the "normal"
function caller to callee way. This is the second C<vup> parameter of type
C<AstNuser> 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.)
=back
=head2 Iterators
C<AstNode> provides a set of iterators to facilitate walking over the
tree. Each takes two arguments, a visitor, C<v>, of type C<AstNVisitor> and
an optional pointer user data, C<vup>, of type C<AstNuser*>. The second is
one of the ways to pass parameters to visitors described in L</Visitor
Functions>, but its use is no deprecated and should be used for new visitor
classes.
=over 4
=item C<iterate()>
This just applies the C<accept> method of the C<AstNode> to the visitor
function.
=item C<iterateAndNextIgnoreEdit>
Applies the C<accept> method of each C<AstNode> in a list (i.e. connected
by C<nextp> and C<backp> pointers).
=item C<iterateAndNext>
Applies the C<accept> method of each C<AstNode> in a list. If a node is
edited by the call to C<accept>, apply C<accept> again, until the node does
not change.
=item C<iterateListBackwards>
Applies the C<accept> method of each C<AstNode> in a list, starting with
the last one.
=item C<iterateChildren>
Apply the C<iterateAndNext> method on each child C<op1p> through C<op4p> in
turn.
=item C<iterateChildrenBackwards>
Apply the C<iterateListBackwards> method on each child C<op1p> through
C<op4p> in turn.
=back
=head2 Identifying derived classes
A common requirement is to identify the specific C<AstNode> class we are
dealing with. For example a visitor might not implement separate C<visit>
methods for C<AstIf> and C<AstGenIf>, but just a single method for the base
class:
void visit (AstNodeIf* nodep, AstNUser* vup)
However that method might want to specify additional code if it is called
for C<AstGenIf>. Verilator does this by providing a C<castSOMETYPE()>
method for each possible node type, using C++ C<dynamic_cast>. This either
returns a pointer to the object cast to that type (if it is of class
C<SOMETYPE>, or a derived class of C<SOMETYPE>) or else NULL. So our
C<visit> method could use:
if (nodep->castAstGenIf()) {
<code specific to AstGenIf>
}
A common test is for C<AstNetlist>, which is the node at the root of the
AST.
=head1 TESTING
To write a test see notes in the forum and in the verilator.txt manual.
To write a test see the BUGS section of the Verilator primary manual, and
the documentation in:
Note you can run the regression tests in parallel; see the
test_regress/driver.pl script -j flag.
test_regress/t/driver.pl --help
It is important to add tests for failures as well as success (for example to
check that an error message is correctly triggered).
Tests that fail should by convenition have the suffix C<_bad> in their name,
and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
appropriate.
Developers will also want to configure with two extra flags:
=over 4
=item --enable-ccwarn
Causes the build to stop on warnings as well as errors. A good way to
ensure no sloppy code gets added, however it can be painful when it comes
to testing, since third party code used in the tests (e.g. SystemC) may not
be warning free.
=item --enable-longtests
In addition to the standard C, SystemC and SystemPerl tests also run the
tests in the C<test_vcs>, C<test_verilated> and C<test_regress> directories
when using I<make test>. This is disabled by default as SystemC/SystemPerl
installation problems would otherwise falsely indicate a Verilator problem.
=back
When enabling the long tests, some additional PERL modules are needed, which
you can install using cpan.
cpan install Unix::Processors
There are some traps to avoid when running regression tests
=over 4
=item *
The regression tests will assume that you have a version of SystemPerl to
match. Typically if working on Verilator from git, also use SystemPerl from
git.
=item *
When checking the MANIFEST, the test will barf on unexpected code in the
Verilator tree. So make sure to keep any such code outside the tree.
=item *
Not all Linux systems install Perldoc by default. This is needed for the
I<--help> option to Verilator, and also for regression testing. This can be
installed using cpan:
cpan install Pod::Perldoc
Many Linux systems also offer a standard package for this. Red
Hat/Fedora/Centos offer I<perl-Pod-Perldoc>, while Debian/Ubuntu/Linux Mint
offer I<perl-doc>.
=item *
Running regression may exhaust resources on some Linux systems, particularly
file handles and user processes. Increase these to respectively 16,384 and
4,096. The method of doing this is system dependent, but on Fedora Linux it
would require editing the C</etc/security/limits.conf> file as root.
=back
=head1 DEBUGGING
@@ -207,27 +467,32 @@ viewers let us know; ZGRViewer isn't great for large graphs.
Tree files are dumps of the AST Tree and are produced between every major
algorithmic stage. An example:
NETLIST 0x90fb00 <e1> {a0} w0
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
NETLIST 0x90fb00 <e1> {a0}
1: MODULE 0x912b20 <e8822> {a8} top L2 [P]
*1:2: VAR 0x91a780 <e74#> {a22} @dt=0xa2e640(w32) out_wide [O] WIRE
1:2:1: BASICDTYPE 0xa2e640 <e2149> {e24} @dt=this(sw32) integer kwd=integer range=[31:0]
=over 4
"1:2:" indicates the hierarchy the VAR is op2p under the MODULE.
The following summarizes the above example dump, with more detail on each
field in the section below.
"1:2:" indicates the hierarchy of the C<VAR> is the C<op2p> pointer under
the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
"VAR" is the AstNodeType.
"0x91a780" is the address of this node.
"<e74>" means the 74th edit to the netlist was the last modification to
this node. A trailing # indicates this node changed since the last tree
dump was made. You can gdb break on this edit; see below.
this node.
"{a22}" indicates this node is related to line 22 in the source filename
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
"a", where "a" is the first file read, "z" the 26th, and "aa" the 27th.
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
"@dt=0x..." indicates the address of the data type this node contains.
"w32" indicates the width is 32 bits.
"out_wide" is the name of the node, in this case the name of the variable.
@@ -236,11 +501,129 @@ variable is an output.
=back
In more detail the following fields are dumped common to all nodes. They
are produced by the C<AstNode::dump()> method:
=over 4
=item Tree Hierarchy
The dump lines begin with numbers and colons to indicate the child node
hierarchy. As noted above in L</Key Classes Used in the Verilator Flow>,
C<AstNode> has lists of items at the same level in the AST, connected by
the C<nextp()> and C<prevp()> pointers. These appear as nodes at the same
level. For example after inlining:
NETLIST 0x929c1c8 <e1> {a0} w0
1: MODULE 0x92bac80 <e3144> {e14} w0 TOP_t L1 [P]
1:1: CELLINLINE 0x92bab18 <e3686#> {e14} w0 v -> t
1:1: CELLINLINE 0x92bc1d8 <e3688#> {e24} w0 v__DOT__i_test_gen -> test_gen
...
1: MODULE 0x92b9bb0 <e503> {e47} w0 test_gen L3
...
=item AstNode type
The textual name of this node AST type (always in capitals). Many of these
correspond directly to Verilog entities (for example C<MODULE> and
C<TASK>), but others are internal to Verialtor (for example C<NETLIST> and
C<BASICDTYPE>).
=item Address of the node
A hexadecimal address of the node in memory. Useful for examining with the
debugger.
=item Last edit number
Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
of the last edit to modify this node. The trailing C<#> indicates the node
has been edited since the last tree dump (which typically means in the last
refinement or optimization pass). GDB can watch for this, see L</Debugging
with GDB>.
=item Source file and line
Of the form C<< {xxnnnn} >>, where C{xx} is the filename letter (or
letters) and C<nnnn> is the line number within that file. The first file is
C<a>, the 26th is C<z>, the 27th is C<aa> and so on.
=item User pointers
Shows the value of the node's user1p...user5p, if non-NULL.
=item Data type
Many nodes have an explicit data type. "@dt=0x..." indicates the address
of the data type (AstNodeDType) this node uses.
If a data type is present and is numberic, it then prints the width of the
item. This field is a squence of flag characters and width data as follows:
C<s> if the node is signed.
C<d> if the node is a double (i.e a floating point entity).
C<w> always present, indicating this is the width field.
C<u> if the node is unsized.
C</nnnn> if the node is unsized, where C<nnnn> is the minimum width.
=item Name of the entity represented by the node if it exists
For example for a C<VAR> it is the name of the variable.
=back
Many nodes follow these fields with additional node specific
information. Thus the C<VARREF> node will print either C<[LV]> or C<[RV]>
to indicate a left value or right value, followed by the node of the
variable being referred to. For example:
1:2:1:1: VARREF 0x92c2598 <e509> {e24} w0 clk [RV] <- VAR 0x92a2e90 <e79> {e18} w0 clk [I] INPUT
In general, examine the C<dump()> method in C<V3AstNodes.cpp> of the node
type in question to determine additional fields that may be printed.
The C<MODULE> has a list of C<CELLINLINE> nodes referred to by its
C<op1p()> pointer, connected by C<nextp()> and C<prevp()> pointers.
Similarly the C<NETLIST> has a list of modules referred to by its C<op1p()>
pointer.
=head2 Debugging with GDB
The test_regress/driver.pl script accepts --debug --gdb to start Verilator
under gdb. You can also use --debug --gdbbt to just backtrace and then
exit gdb.
under gdb and break when an error is hit or the program is about to exit.
You can also use --debug --gdbbt to just backtrace and then exit gdb. To
debug the Verilated executable, use --gdbsim.
If you wish to start Verilator under GDB (or another debugger), then you
can use --debug and look at the underlying invocation of verilator_dgb. For
example
t/t_alw_dly.pl --debug
shows it invokes the command:
../verilator_bin_dbg --prefix Vt_alw_dly --x-assign unique --debug
-cc -Mdir obj_dir/t_alw_dly --debug-check -f input.vc t/t_alw_dly.v
Start GDB, then C<start> with the remaining arguments.
gdb ../verilator_bin_dbg
...
(gdb) start --prefix Vt_alw_dly --x-assign unique --debug -cc -Mdir
obj_dir/t_alw_dly --debug-check -f input.vc t/t_alw_dly.v
> obj_dir/t_alw_dly/vlt_compile.log
...
Temporary breakpoint 1, main (argc=13, argv=0xbfffefa4, env=0xbfffefdc)
at ../Verilator.cpp:615
615 ios::sync_with_stdio();
(gdb)
You can then continue execution with breakpoints as required.
To break at a specific edit number which changed a node (presumably to find
what made a <e####> line in the tree dumps):
@@ -249,8 +632,66 @@ what made a <e####> line in the tree dumps):
To print a node:
call nodep->dumpGdb() # aliased to "pn" in .gdbinit
call nodep->dumpTreeGdb() # aliased to "pnt" in .gdbinit
pn nodep
# or: call nodep->dumpGdb() # aliased to "pn" in src/.gdbinit
pnt nodep
# or: call nodep->dumpTreeGdb() # aliased to "pnt" in src/.gdbinit
When GDB halts, it is useful to understand that the backtrace will commonly
show the iterator functions between each invocation of C<visit> in the
backtrace. You will typically see a frame sequence something like
...
visit()
iterateChildren()
iterateAndNext()
accept()
visit()
...
=head1 ADDING A NEW FEATURE
Generally what would you do to add a new feature?
=over 4
=item 1.
File a bug (if there isn't already) so others know what you're working on.
=item 2.
Make a testcase in the test_regress/t/t_EXAMPLE format, see L<TESTING>.
=item 3.
If grammar changes are needed, look at the git version of VerilogPerl's
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
language and has a lot of back-and-forth with Verilator's grammar. Copy
the appropriate rules to src/verilog.y and modify the productions.
=item 4.
If a new Ast type is needed, add it to V3AstNodes.h.
=back
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
file which you can examine to see if the parsing worked. See also the
sections above on debugging.
Modify the later visitor functions to process the new feature as needed.
=head2 Adding a new pass
For more substantial changes you may need to add a new pass. The simplest way
to do this is to copy the C<.cpp> and C<.h> files from an existing
pass. You'll need to add a call into your pass from the C<process()> function
in C<src/verilator.cpp>.
To get your pass to build you'll need to add its binary filename to the list
in C<src/Makefile_obj.in> and reconfigure.
=head1 DISTRIBUTION
+14
View File
@@ -18,3 +18,17 @@ end
document pnt
Verilator: Print AstNode NODEP's tree
end
define dtf
call AstNode::dumpTreeFileGdb(0)
end
document dtf
Verilator: Dump AstNode tree to file
end
define watchedit
watch AstNode::s_editCntGbl==$arg0
end
document watchedit
Verilator: Create watch on where a edit number is made
end
+4 -2
View File
@@ -65,12 +65,14 @@ dbg: ../verilator_bin_dbg
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
prefiles::
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
prefiles:: config_rev.h
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
else
config_rev.h: ${srcdir}/config_rev.pl
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
endif
maintainer-copy::
+2 -1
View File
@@ -182,6 +182,7 @@ RAW_OBJS = \
V3EmitCSyms.o \
V3EmitMk.o \
V3EmitV.o \
V3EmitXml.o \
V3Error.o \
V3Expand.o \
V3File.o \
@@ -197,7 +198,6 @@ RAW_OBJS = \
V3Inst.o \
V3Life.o \
V3LifePost.o \
V3Link.o \
V3LinkCells.o \
V3LinkDot.o \
V3LinkJump.o \
@@ -219,6 +219,7 @@ RAW_OBJS = \
V3SplitAs.o \
V3Stats.o \
V3StatsReport.o \
V3String.o \
V3Subst.o \
V3Table.o \
V3Task.o \
+18 -11
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into sensitivity active domains
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -163,16 +162,22 @@ public:
// Active AssignDly replacement functions
class ActiveDlyVisitor : public ActiveBaseVisitor {
public:
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL };
private:
bool m_combo; // Combo logic
CheckType m_check; // Combo logic or other
AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign
// VISITORS
virtual void visit(AstAssignDly* nodep, AstNUser*) {
if (m_combo) {
if (m_check != CT_SEQ) {
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
} else {
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
}
AstNode* newp = new AstAssign (nodep->fileline(),
nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack());
@@ -181,7 +186,7 @@ private:
}
}
virtual void visit(AstAssign* nodep, AstNUser*) {
if (!m_combo) {
if (m_check == CT_SEQ) {
AstNode* las = m_assignp;
m_assignp = nodep;
nodep->lhsp()->iterateAndNext(*this);
@@ -190,7 +195,7 @@ private:
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
AstVar* varp=nodep->varp();
if (!m_combo
if (m_check == CT_SEQ
&& m_assignp
&& !varp->isUsedLoopIdx() // Ignore loop indicies
&& !varp->isTemp()
@@ -212,9 +217,9 @@ private:
}
public:
// CONSTUCTORS
ActiveDlyVisitor(AstNode* nodep, bool combo) {
ActiveDlyVisitor(AstNode* nodep, CheckType check) {
m_alwaysp = nodep;
m_combo = combo;
m_check = check;
m_assignp = NULL;
nodep->accept(*this);
}
@@ -251,6 +256,7 @@ private:
virtual void visit(AstInitial* nodep, AstNUser*) {
// Relink to IACTIVE, unless already under it
UINFO(4," INITIAL "<<nodep<<endl);
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
AstActive* wantactivep = m_namer.getIActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
@@ -283,6 +289,7 @@ private:
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
if (!m_scopeFinalp) {
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep());
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
@@ -353,10 +360,10 @@ private:
// Warn and/or convert any delayed assignments
if (combo && !sequent) {
ActiveDlyVisitor dlyvisitor (nodep, true);
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
}
else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor (nodep, false);
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
}
}
virtual void visit(AstAlways* nodep, AstNUser*) {
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into sensitivity block domains
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into sensitivity active domains
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into sensitivity block domains
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+2 -3
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Collect and print statistics
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
@@ -177,7 +176,7 @@ private:
// VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (!nodep->user1Inc()) {
if (!nodep->user1SetOnce()) {
bool has_default=false;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
if (itemp->isDefault()) has_default=true;
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Assertion expansion
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Collect and print statistics
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Assertion pre-expansion
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
+80 -23
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Ast node structures
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -52,6 +51,9 @@ bool AstUser3InUse::s_userBusy=false;
bool AstUser4InUse::s_userBusy=false;
bool AstUser5InUse::s_userBusy=false;
int AstNodeDType::s_uniqueNum = 0;
//######################################################################
// V3AstType
@@ -71,14 +73,12 @@ void AstNode::init() {
m_op3p = NULL;
m_op4p = NULL;
m_iterpp = NULL;
m_dtypep = NULL;
m_clonep = NULL;
m_cloneCnt = 0;
// Attributes
m_numeric = (int)AstNumeric::UNSIGNED;
m_didWidth = false;
m_doingWidth = false;
m_width = 0;
m_widthMin = 0;
m_user1p = NULL;
m_user1Cnt = 0;
m_user2p = NULL;
@@ -228,15 +228,6 @@ string AstNode::quoteName(const string& namein) {
return out;
}
int AstNode::widthPow2() const {
// I.e. width 30 returns 32, width 32 returns 32.
uint32_t width = this->width();
for (int p2=30; p2>=0; p2--) {
if (width > (1UL<<p2)) return (1UL<<(p2+1));
}
return 1;
}
//######################################################################
// Insertion
@@ -767,13 +758,16 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
// Future versions of this function may require the node to have a back to be iterated;
// there's no lower level reason yet though the back must exist.
AstNode* nodep=this;
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
#endif
while (nodep) {
AstNode* niterp = nodep;
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
ASTNODE_PREFETCH(nodep->m_nextp);
niterp->m_iterpp = &niterp;
niterp->accept(v, vup);
// accept may do a replaceNode and change niterp on us...
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
if (!niterp) return;
niterp->m_iterpp = NULL;
if (VL_UNLIKELY(niterp!=nodep)) { // Edited it
@@ -855,6 +849,9 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
void AstNode::cloneRelinkTree() {
if (!this) return;
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
if (m_dtypep && m_dtypep->clonep()) {
m_dtypep = m_dtypep->clonep()->castNodeDType();
}
nodep->cloneRelink();
nodep->m_op1p->cloneRelinkTree();
nodep->m_op2p->cloneRelinkTree();
@@ -875,8 +872,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
if (this==NULL && node2p==NULL) return true;
if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type()
|| this->width() != node2p->width()
|| this->numeric() != node2p->numeric()
|| this->dtypep() != node2p->dtypep()
|| !this->same(node2p)) {
return false;
}
@@ -953,15 +949,19 @@ void AstNode::dumpGdb() { // For GDB only
dumpGdbHeader();
cout<<" "; dump(cout); cout<<endl;
}
void AstNode::dumpGdbHeader() const { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpPtrs(cout);
cout<<" Fileline = "<<fileline()<<endl;
}
void AstNode::dumpTreeGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader();
dumpTree(cout);
}
void AstNode::dumpGdbHeader() const { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpPtrs(cout);
cout<<" Fileline = "<<fileline()<<endl;
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree",98);
v3Global.rootp()->dumpTreeFile(filename);
}
void AstNode::dumpPtrs(ostream& os) const {
@@ -1010,11 +1010,13 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
void AstNode::dumpTreeFile(const string& filename, bool append) {
if (v3Global.opt.dumpTree()) {
{ // Write log & close
UINFO(2,"Dumping "<<filename<<endl);
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
if (editCountGbl()==editCountLast()) {
if (editCountGbl()==editCountLast()
&& !(v3Global.opt.dumpTree()>=9)) {
*logsp<<endl;
*logsp<<"No changes since last dump!\n";
} else {
@@ -1047,6 +1049,61 @@ void AstNode::v3errorEnd(ostringstream& str) const {
}
}
string AstNode::warnMore() const {
if (this) return this->fileline()->warnMore();
else return V3Error::warnMore();
}
//======================================================================
// Data type conversion
void AstNode::dtypeChgSigned(bool flag) {
if (!dtypep()) this->v3fatalSrc("No dtype when changing to (un)signed");
dtypeChgWidthSigned(dtypep()->width(), dtypep()->widthMin(),
flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
}
void AstNode::dtypeChgWidth(int width, int widthMin) {
if (!dtypep()) this->v3fatalSrc("No dtype when changing width"); // Use ChgWidthSigned(...UNSIGNED) otherwise
dtypeChgWidthSigned(width, widthMin, dtypep()->numeric());
}
void AstNode::dtypeChgWidthSigned(int width, int widthMin, bool issigned) {
AstNumeric numeric = issigned ? AstNumeric::SIGNED : AstNumeric::UNSIGNED;
if (!dtypep()) {
// We allow dtypep() to be null, as before/during widthing dtypes are not resolved
dtypeSetLogicSized(width, widthMin, numeric);
} else {
if (width==dtypep()->width()
&& widthMin==dtypep()->widthMin()
&& numeric==dtypep()->numeric()) return; // Correct already
// FUTURE: We may be pointing at a two state data type, and this may
// convert it to logic. Since the AstVar remains correct, we
// work OK but this assumption may break in the future.
// Note we can't just clone and do a widthForce, as if it's a BasicDType
// the msb() indications etc will be incorrect.
dtypeSetLogicSized(width, widthMin, numeric);
}
}
AstNodeDType* AstNode::findBasicDType(AstBasicDTypeKwd kwd) const {
// For 'simple' types we use the global directory. These are all unsized.
// More advanced types land under the module/task/etc
return v3Global.rootp()->typeTablep()
->findBasicDType(fileline(), kwd);
}
AstNodeDType* AstNode::findBitDType(int width, int widthMin, AstNumeric numeric) const {
return v3Global.rootp()->typeTablep()
->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, width, widthMin, numeric);
}
AstNodeDType* AstNode::findLogicDType(int width, int widthMin, AstNumeric numeric) const {
return v3Global.rootp()->typeTablep()
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric);
}
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
return v3Global.rootp()->typeTablep()
->findInsertSameDType(nodep);
}
//######################################################################
// AstNVisitor
+294 -74
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Ast node structure
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -36,8 +34,9 @@
// class V3AstNode;
// Hint class so we can choose constructors
class AstLogicPacked {};
class AstBitPacked {};
class VFlagLogicPacked {};
class VFlagBitPacked {};
class VFlagChildDType {}; // Used by parser.y to select constructor that sets childDType
//######################################################################
@@ -60,28 +59,40 @@ public:
//######################################################################
enum VSignedState {
// This can't be in the fancy class as the lexer union will get upset
signedst_UNSIGNED=0, signedst_SIGNED=1, signedst_NOSIGN=2
};
//######################################################################
class AstNumeric {
public:
enum en {
UNSIGNED,
SIGNED,
DOUBLE
// Limited to 2 bits, unless change V3Ast's packing function
NOSIGN,
_ENUM_MAX // Leave last
};
enum en m_e;
const char* ascii() const {
static const char* names[] = {
"UNSIGNED","SIGNED","DOUBLE"
"UNSIGNED","SIGNED","NOSIGN"
};
return names[m_e];
};
inline AstNumeric () : m_e(UNSIGNED) {}
inline AstNumeric (en _e) : m_e(_e) {}
inline AstNumeric (VSignedState signst) {
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
else if (signst==signedst_SIGNED) m_e=SIGNED;
else m_e=NOSIGN;
}
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
inline bool isDouble() const { return m_e==DOUBLE; }
inline bool isSigned() const { return m_e==SIGNED; }
inline bool isUnsigned() const { return m_e==UNSIGNED; }
inline bool isNosign() const { return m_e==NOSIGN; }
// No isUnsigned() as it's ambiguous if NOSIGN should be included or not.
};
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
@@ -210,6 +221,8 @@ public:
ILLEGAL,
EXPR_BITS, // V3Const converts to constant
//
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
//
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
@@ -224,8 +237,8 @@ public:
enum en m_e;
const char* ascii() const {
static const char* names[] = {
"%E-AT", "EXPR_BITS", "VAR_BASE",
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"%E-AT", "EXPR_BITS", "MEMBER_BASE",
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
};
@@ -252,8 +265,12 @@ public:
STRING,
// Internal types for mid-steps
SCOPEPTR, CHARPTR,
// Unsigned and two state; fundamental types
UINT32, UINT64,
// Internal types, eliminated after parsing
LOGIC_IMPLICIT
LOGIC_IMPLICIT,
// Leave last
_ENUM_MAX
};
enum en m_e;
const char* ascii() const {
@@ -263,7 +280,9 @@ public:
"real", "shortint", "shortreal", "time",
"string",
"VerilatedScope*", "char*",
"LOGIC_IMPLICIT"
"IData", "QData",
"LOGIC_IMPLICIT",
" MAX"
};
return names[m_e];
};
@@ -274,22 +293,28 @@ public:
"double", "short int", "float", "long long",
"const char*",
"dpiScope", "const char*",
""
"IData", "QData",
"svLogic", // Though shouldn't be needed
" MAX"
};
return names[m_e];
};
static void test() {
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"),"Enum array mismatch");
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
}
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
int width() const {
switch (m_e) {
case BIT: return 1;
case BIT: return 1; // scalar, can't bit extract unless ranged
case BYTE: return 8;
case CHANDLE: return 64;
case INT: return 32;
case INTEGER: return 32;
case LOGIC: return 1;
case LOGIC: return 1; // scalar, can't bit extract unless ranged
case LONGINT: return 64;
case DOUBLE: return 64; // opaque
case FLOAT: return 32; // opaque
@@ -298,11 +323,18 @@ public:
case STRING: return 64; // opaque // Just the pointer, for today
case SCOPEPTR: return 0; // opaque
case CHARPTR: return 0; // opaque
case UINT32: return 32;
case UINT64: return 64;
default: return 0;
}
}
bool isSigned() const {
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER;
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER
|| m_e==DOUBLE || m_e==FLOAT;
}
bool isUnsigned() const {
return m_e==CHANDLE || m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR
|| m_e==UINT32 || m_e==UINT64;
}
bool isFourstate() const {
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
@@ -311,6 +343,10 @@ public:
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
}
bool isIntNumeric() const { // Enum increment supported
return (m_e==BIT || m_e==BYTE || m_e==INT || m_e==INTEGER || m_e==LOGIC
|| m_e==LONGINT || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64);
}
bool isSloppy() const { // Don't be as anal about width warnings
return !(m_e==LOGIC || m_e==BIT);
}
@@ -333,13 +369,6 @@ public:
//######################################################################
enum AstSignedState {
// This can't be in the fancy class as the lexer union will get upset
signedst_NOSIGNED=0, signedst_UNSIGNED=1, signedst_SIGNED=2
};
//######################################################################
class AstVarType {
public:
enum en {
@@ -356,6 +385,8 @@ public:
WIRE,
IMPLICITWIRE,
TRIWIRE,
TRI0,
TRI1,
PORT, // Temp type used in parser only
BLOCKTEMP,
MODULETEMP,
@@ -371,9 +402,16 @@ public:
static const char* names[] = {
"?","GPARAM","LPARAM","GENVAR",
"VAR","INPUT","OUTPUT","INOUT",
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE","TRIWIRE","PORT",
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE",
"TRIWIRE","TRI0","TRI1",
"PORT",
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
return names[m_e]; }
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE
|| m_e==TRIWIRE
|| m_e==TRI0 || m_e==TRI1
|| m_e==SUPPLY0 || m_e==SUPPLY1
|| m_e==VAR); }
};
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
@@ -464,10 +502,11 @@ class AstParseRefExp {
public:
enum en {
PX_NONE, // Used in V3LinkParse only
PX_VAR_MEM,
PX_VAR_ANY,
PX_TASK,
PX_FUNC
PX_TEXT, // Unknown ID component
PX_PREDOT, // Module name or misc component above var/task/func/member
PX_VAR_MEM, // Variable that must be a memory
PX_VAR_ANY, // Variable/structure member
PX_FTASK // Task/Function (AstParse::ftaskrefp() will be set)
};
enum en m_e;
inline AstParseRefExp() : m_e(PX_NONE) {}
@@ -476,7 +515,7 @@ public:
operator en () const { return m_e; }
const char* ascii() const {
static const char* names[] = {
"","VAR_MEM","VAR_ANY","TASK","FUNC"};
"","TEXT","PREDOT","VAR_MEM","VAR_ANY","FTASK"};
return names[m_e]; }
};
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
@@ -484,6 +523,83 @@ public:
inline bool operator== (AstParseRefExp::en lhs, AstParseRefExp rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstParseRefExp rhs) { return os<<rhs.ascii(); }
//######################################################################
// VNumRange - Structure containing numberic range information
// See also AstRange, which is a symbolic version of this
struct VNumRange {
int m_msb; // MSB, MSB always >= LSB
int m_lsb; // LSB
union {
int mu_flags;
struct {
bool m_ranged:1; // Has a range
bool m_littleEndian:1; // Bit vector is little endian
};
};
inline bool operator== (const VNumRange& rhs) const {
return m_msb == rhs.m_msb
&& m_lsb == rhs.m_lsb
&& mu_flags == rhs.mu_flags; }
inline bool operator< (const VNumRange& rhs) const {
if ( (m_msb < rhs.m_msb)) return true;
if (!(m_msb == rhs.m_msb)) return false; // lhs > rhs
if ( (m_lsb < rhs.m_lsb)) return true;
if (!(m_lsb == rhs.m_lsb)) return false; // lhs > rhs
if ( (mu_flags < rhs.mu_flags)) return true;
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs
return false;
}
//
VNumRange() : m_msb(0), m_lsb(0), mu_flags(0) {}
~VNumRange() {}
// MEMBERS
void init(int msb, int lsb, bool littleEndian) {
m_msb=msb; m_lsb=lsb; mu_flags=0; m_ranged=true; m_littleEndian=littleEndian;
}
int msb() const { return m_msb; }
int lsb() const { return m_lsb; }
int left() const { return littleEndian()?lsb():msb(); } // How to show a declaration
int right() const { return littleEndian()?msb():lsb(); }
bool ranged() const { return m_ranged; }
bool littleEndian() const { return m_littleEndian; }
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
{ return (!m_ranged || (m_lsb==0 && m_msb>=1 && !m_littleEndian)); }
};
//######################################################################
struct VBasicTypeKey {
int m_width; // From AstNodeDType: Bit width of operation
int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation
AstNumeric m_numeric; // From AstNodeDType: Node is signed
AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
inline bool operator== (const VBasicTypeKey& rhs) const {
return m_width == rhs.m_width
&& m_widthMin == rhs.m_widthMin
&& m_numeric == rhs.m_numeric
&& m_keyword == rhs.m_keyword
&& m_nrange == rhs.m_nrange; }
inline bool operator< (const VBasicTypeKey& rhs) const {
if ( (m_width < rhs.m_width)) return true;
if (!(m_width == rhs.m_width)) return false; // lhs > rhs
if ( (m_widthMin < rhs.m_widthMin)) return true;
if (!(m_widthMin == rhs.m_widthMin)) return false; // lhs > rhs
if ( (m_numeric < rhs.m_numeric)) return true;
if (!(m_numeric == rhs.m_numeric)) return false; // lhs > rhs
if ( (m_keyword < rhs.m_keyword)) return true;
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
if ( (m_nrange < rhs.m_nrange)) return true;
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
return false; }
VBasicTypeKey(int width, int widthMin, AstNumeric numeric, AstBasicDTypeKwd kwd,
VNumRange nrange)
: m_width(width), m_widthMin(widthMin), m_numeric(numeric),
m_keyword(kwd), m_nrange(nrange) {}
~VBasicTypeKey() {}
};
//######################################################################
// AstNUser - Generic pointer base class for AST User nodes.
// - Also used to allow parameter passing up/down iterate calls
@@ -493,13 +609,13 @@ class LinkVP;
class OrderBlockNU;
class OrderVarNU;
class V3GraphVertex;
class V3SymTable;
class VSymEnt;
struct AstNUser {
AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p())
// Casters
WidthVP* c() { return ((WidthVP*)this); }
LinkVP* castLinkVP() { return ((LinkVP*)this); }
V3SymTable* castSymTable() { return ((V3SymTable*)this); }
VSymEnt* castSymEnt() { return ((VSymEnt*)this); }
AstNode* castNode() { return ((AstNode*)this); }
OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); }
OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); }
@@ -692,11 +808,14 @@ public:
// Creating from raw data (sameHash functions)
V3Hash() { setBoth(1,0); }
V3Hash(uint32_t val) { setBoth(1,val); }
V3Hash(void* vp) { setBoth(1,cvtToHash(vp)); }
V3Hash(const void* vp) { setBoth(1,cvtToHash(vp)); }
V3Hash(const string& name);
V3Hash(V3Hash lh, V3Hash rh) {
setBoth(1,lh.hshval()*31+rh.hshval());
}
V3Hash(V3Hash h1, V3Hash h2) {
setBoth(1,h1.hshval()*31+h2.hshval()); }
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3) {
setBoth(1,(h1.hshval()*31+h2.hshval())*31+h3.hshval()); }
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3, V3Hash h4) {
setBoth(1,((h1.hshval()*31+h2.hshval())*31+h3.hshval())*31+h4.hshval()); }
};
ostream& operator<<(ostream& os, V3Hash rhs);
@@ -726,18 +845,17 @@ class AstNode {
static vluint64_t s_editCntGbl; // Global edit counter
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
AstNodeDType* m_dtypep; // Data type of output or assignment (etc)
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
int m_cloneCnt; // Mark of when userp was set
static int s_cloneCntGbl; // Count of which userp is set
// Attributes
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
bool m_didWidth:1; // Did V3Width computation
bool m_doingWidth:1; // Inside V3Width
// // Space for more bools here
int m_width; // Bit width of operation
int m_widthMin; // If unsized, bitwidth of minimum implementation
// This member ordering both allows 64 bit alignment and puts associated data together
AstNUser* m_user1p; // Pointer to any information the user iteration routine wants
uint32_t m_user1Cnt; // Mark of when userp was set
@@ -811,6 +929,7 @@ public:
AstNode* op2p() const { return m_op2p; }
AstNode* op3p() const { return m_op3p; }
AstNode* op4p() const { return m_op4p; }
AstNodeDType* dtypep() const { return m_dtypep; }
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
bool brokeExists() const;
@@ -851,26 +970,18 @@ public:
string prettyTypeName() const; // "VARREF name" for error messages
FileLine* fileline() const { return m_fileline; }
void fileline(FileLine* fl) { m_fileline=fl; }
int width() const { return m_width; }
bool width1() const { return width()==1; }
int widthWords() const { return VL_WORDS_I(width()); }
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
int widthPow2() const;
int widthInstrs() const { return isWide()?widthWords():1; }
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
AstNumeric numeric() const { return AstNumeric(m_numeric); }
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
bool isUnsigned() const { return numeric().isUnsigned(); }
bool width1() const;
int widthInstrs() const;
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false;}
void doingWidth(bool flag) { m_doingWidth=flag; }
bool doingWidth() const { return m_doingWidth; }
//TODO stomp these width functions out, and call via dtypep() instead
int width() const;
int widthMin() const;
int widthWords() const { return VL_WORDS_I(width()); }
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); }
bool isDouble() const;
@@ -885,6 +996,7 @@ public:
int user1() const { return user1p()->castInt(); }
void user1(int val) { user1p(AstNUser::fromInt(val)); }
int user1Inc() { int v=user1(); user1(v+1); return v; }
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user2p() const {
@@ -894,6 +1006,7 @@ public:
int user2() const { return user2p()->castInt(); }
void user2(int val) { user2p(AstNUser::fromInt(val)); }
int user2Inc() { int v=user2(); user2(v+1); return v; }
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
static void user2ClearTree() { AstUser2InUse::clear(); }
AstNUser* user3p() const {
@@ -903,6 +1016,7 @@ public:
int user3() const { return user3p()->castInt(); }
void user3(int val) { user3p(AstNUser::fromInt(val)); }
int user3Inc() { int v=user3(); user3(v+1); return v; }
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
static void user3ClearTree() { AstUser3InUse::clear(); }
AstNUser* user4p() const {
@@ -912,6 +1026,7 @@ public:
int user4() const { return user4p()->castInt(); }
void user4(int val) { user4p(AstNUser::fromInt(val)); }
int user4Inc() { int v=user4(); user4(v+1); return v; }
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
static void user4ClearTree() { AstUser4InUse::clear(); }
AstNUser* user5p() const {
@@ -921,6 +1036,7 @@ public:
int user5() const { return user5p()->castInt(); }
void user5(int val) { user5p(AstNUser::fromInt(val)); }
int user5Inc() { int v=user5(); user5(v+1); return v; }
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
static void user5ClearTree() { AstUser5InUse::clear(); }
vluint64_t editCount() const { return m_editCount; }
@@ -938,14 +1054,33 @@ public:
bool isAllOnesV(); // Verilog width rules apply
// METHODS - data type changes especially for initial creation
void dtypeChgLogicBool() { numeric(AstNumeric::UNSIGNED); width(1,1); }
void dtypeChgDouble() { numeric(AstNumeric::DOUBLE); }
void dtypeChgSigned32() { numeric(AstNumeric::SIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
void dtypeChgUInt32() { numeric(AstNumeric::UNSIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
void dtypeChgUInt64() { numeric(AstNumeric::UNSIGNED); width(VL_QUADSIZE,VL_QUADSIZE); }
void dtypep(AstNodeDType* nodep) { if (m_dtypep != nodep) { m_dtypep = nodep; editCountInc(); } }
void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }}
void dtypeChgSigned(bool flag=true);
void dtypeChgWidth(int width, int widthMin);
void dtypeChgWidthSigned(int width, int widthMin, bool issigned);
void dtypeSetBitSized(int width, int widthMin, AstNumeric numeric) { dtypep(findBitDType(width,widthMin,numeric)); }
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
void dtypeSetDouble() { dtypep(findDoubleDType()); }
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
// Data type locators
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
// METHODS - dump and error
void v3errorEnd(ostringstream& str) const;
string warnMore() const;
virtual void dump(ostream& str=cout);
void dumpGdb(); // For GDB only
void dumpGdbHeader() const;
@@ -973,9 +1108,11 @@ public:
void checkTree(); // User Interface version
void dumpPtrs(ostream& str=cout) const;
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
void dumpTreeGdb(); // For GDB only
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
void dumpTreeFile(const string& filename, bool append=false);
static void dumpTreeFileGdb(const char* filenamep=NULL);
// METHODS - queries
virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
@@ -988,6 +1125,8 @@ public:
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
virtual bool same(AstNode* otherp) const { return true; }
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
virtual bool broken() const { return false; }
@@ -1007,7 +1146,7 @@ public:
// AstAlways* castAlways();
};
inline ostream& operator<<(ostream& os, AstNode* rhs) { rhs->dump(os); return os;}
inline ostream& operator<<(ostream& os, AstNode* rhs) { if (!rhs) os<<"NULL"; else rhs->dump(os); return os; }
inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
//######################################################################
@@ -1024,6 +1163,7 @@ struct AstNodeMath : public AstNode {
: AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeMath)
// METHODS
virtual bool hasDType() const { return true; }
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
virtual string emitC() = 0;
virtual string emitSimpleOperator() { return ""; }
@@ -1048,7 +1188,7 @@ struct AstNodeUniop : public AstNodeMath {
// Unary math
AstNodeUniop(FileLine* fl, AstNode* lhsp)
: AstNodeMath(fl) {
if (lhsp) widthSignedFrom(lhsp);
dtypeFrom(lhsp);
setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop)
AstNode* lhsp() const { return op1p()->castNode(); }
@@ -1128,8 +1268,8 @@ struct AstNodeBiComAsv : public AstNodeBiCom {
struct AstNodeCond : public AstNodeTriop {
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop(fl, condp, expr1p, expr2p) {
if (expr1p) widthSignedFrom(expr1p);
else if (expr2p) widthSignedFrom(expr2p);
if (expr1p) dtypeFrom(expr1p);
else if (expr2p) dtypeFrom(expr2p);
}
ASTNODE_BASE_FUNCS(NodeCond)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
@@ -1173,15 +1313,15 @@ struct AstNodeStmt : public AstNode {
: AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeStmt)
// METHODS
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
};
struct AstNodeAssign : public AstNodeStmt {
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt(fl) {
setOp1p(rhsp); setOp2p(lhsp);
if (lhsp) widthSignedFrom(lhsp);
dtypeFrom(lhsp);
}
ASTNODE_BASE_FUNCS(NodeAssign)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
@@ -1190,6 +1330,7 @@ struct AstNodeAssign : public AstNodeStmt {
AstNode* lhsp() const { return op2p()->castNode(); } // op2 = Assign to
void rhsp(AstNode* np) { setOp1p(np); }
void lhsp(AstNode* np) { setOp2p(np); }
virtual bool hasDType() const { return true; }
virtual bool cleanRhs() { return true; }
virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); }
@@ -1286,6 +1427,7 @@ public:
init();
}
ASTNODE_BASE_FUNCS(NodeVarRef)
virtual bool hasDType() const { return true; }
virtual bool broken() const;
virtual int instrCount() const { return widthInstrs(); }
virtual void cloneRelink();
@@ -1327,19 +1469,89 @@ public:
};
struct AstNodeDType : public AstNode {
// Data type
AstNodeDType(FileLine* fl) : AstNode(fl) {}
private:
// Ideally width() would migrate to BasicDType as that's where it makes sense,
// but it's currently so prevalent in the code we leave it here.
// Note the below members are included in AstTypeTable::Key lookups
int m_width; // (also in AstTypeTable::Key) Bit width of operation
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
// Other members
bool m_generic; // Simple globally referenced type, don't garbage collect
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
public:
// CONSTRUCTORS
AstNodeDType(FileLine* fl) : AstNode(fl) {
m_width=0; m_widthMin=0; m_generic=false;
}
ASTNODE_BASE_FUNCS(NodeDType)
// Accessors
// ACCESSORS
virtual void dump(ostream& str);
virtual void dumpSmall(ostream& str);
virtual bool hasDType() const { return true; }
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs to next non-typeref type
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool maybePointedTo() const { return true; }
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
//
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
// For backward compatibility AstArrayDType and others inherit width and signing from the subDType/base type
void widthFromSub(AstNodeDType* nodep) { m_width=nodep->m_width; m_widthMin=nodep->m_widthMin; m_numeric=nodep->m_numeric; }
//
int width() const { return m_width; }
void numeric(AstNumeric flag) { m_numeric = flag; }
bool isSigned() const { return m_numeric.isSigned(); }
bool isNosign() const { return m_numeric.isNosign(); }
AstNumeric numeric() const { return m_numeric; }
int widthWords() const { return VL_WORDS_I(width()); }
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
int widthPow2() const;
void widthMinFromWidth() { m_widthMin = m_width; }
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
bool generic() const { return m_generic; }
void generic(bool flag) { m_generic = flag; }
AstNodeDType* dtypeDimensionp(int depth);
pair<uint32_t,uint32_t> dimensions();
uint32_t arrayElements(); // 1, or total multiplication of all dimensions
static int uniqueNumInc() { return ++s_uniqueNum; }
};
struct AstNodeClassDType : public AstNodeDType {
private:
// TYPES
typedef map<string,AstMemberDType*> MemberNameMap;
// MEMBERS
bool m_packed;
MemberNameMap m_members;
public:
AstNodeClassDType(FileLine* fl, AstNumeric numericUnpack)
: AstNodeDType(fl) {
// AstNumeric::NOSIGN overloaded to indicate not packed
m_packed = (numericUnpack != AstNumeric::NOSIGN);
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
}
ASTNODE_BASE_FUNCS(NodeClassDType)
virtual bool broken() const;
virtual void dump(ostream& str);
// For basicp() we reuse the size to indicate a "fake" basic type of same size
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// op1 = members
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
bool packed() const { return m_packed; }
void clearCache() { m_members.clear(); }
void repairMemberCache();
AstMemberDType* findMember(const string& name) const {
MemberNameMap::const_iterator it = m_members.find(name);
return (it==m_members.end()) ? NULL : it->second;
}
};
struct AstNodeSel : public AstNodeBiop {
@@ -1352,6 +1564,7 @@ struct AstNodeSel : public AstNodeBiop {
AstNode* bitp() const { return op2p()->castNode(); } // op2 = Msb selection expression
void bitp(AstNode* nodep) { setOp2p(nodep); }
int bitConst() const;
virtual bool hasDType() const { return true; }
};
//######################################################################
@@ -1471,13 +1684,14 @@ private:
bool m_modPublic:1; // Module has public references
bool m_modTrace:1; // Tracing this module
bool m_inLibrary:1; // From a library, no error if not used, never top level
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
int m_level; // 1=top module, 2=cell off top module, ...
int m_varNum; // Incrementing variable number
public:
AstNodeModule(FileLine* fl, const string& name)
: AstNode (fl)
,m_name(name), m_origName(name)
,m_modPublic(false), m_modTrace(false), m_inLibrary(false)
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false)
,m_level(0), m_varNum(0) { }
ASTNODE_BASE_FUNCS(NodeModule)
virtual void dump(ostream& str);
@@ -1502,6 +1716,8 @@ public:
bool modPublic() const { return m_modPublic; }
void modTrace(bool flag) { m_modTrace = flag; }
bool modTrace() const { return m_modTrace; }
void dead(bool flag) { m_dead = flag; }
bool dead() const { return m_dead; }
};
//######################################################################
@@ -1515,8 +1731,12 @@ public:
//######################################################################
// Inline ACCESSORS
inline bool AstNode::isDouble() const { return numeric().isDouble(); }
inline bool AstNode::isSigned() const { return numeric().isSigned(); }
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
@@ -1524,6 +1744,6 @@ inline bool AstNode::isOne() { return (this->castConst() && this->castConst
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline void AstNodeVarRef::init() { if (m_varp) widthSignedFrom((AstNode*)m_varp); }
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
#endif // Guard
+260 -36
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Ast node structures
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -47,6 +46,28 @@ int AstNodeSel::bitConst() const {
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
}
void AstNodeClassDType::repairMemberCache() {
clearCache();
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
else m_members.insert(make_pair(itemp->name(), itemp));
}
}
bool AstNodeClassDType::broken() const {
set<AstMemberDType*> exists;
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
exists.insert(itemp);
}
for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) {
if (exists.find(it->second) == exists.end()) {
this->v3error("Internal: Structure member broken: "<<it->first);
return true;
}
}
return false;
}
int AstBasicDType::widthAlignBytes() const {
if (width()<=8) return 1;
else if (width()<=16) return 2;
@@ -61,6 +82,22 @@ int AstBasicDType::widthTotalBytes() const {
else return widthWords()*(VL_WORDSIZE/8);
}
int AstNodeClassDType::widthTotalBytes() const {
if (width()<=8) return 1;
else if (width()<=16) return 2;
else if (isQuad()) return 8;
else return widthWords()*(VL_WORDSIZE/8);
}
int AstNodeClassDType::widthAlignBytes() const {
// Could do max across members but that would be slow,
// instead intuit based on total structure size
if (width()<=8) return 1;
else if (width()<=16) return 2;
else if (width()<=32) return 4;
else return 8;
}
bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
}
@@ -74,16 +111,26 @@ bool AstVar::isScBv() const {
}
void AstVar::combineType(AstVarType type) {
// These flags get combined with the existing settings of the flags.
// We don't test varType for certain types, instead set flags since
// when we combine wires cross-hierarchy we need a union of all characteristics.
if (type == AstVarType::SUPPLY0) type = AstVarType::WIRE;
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
m_varType=type; // For debugging prints only
// These flags get combined with the existing settings of the flags.
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
m_input = true;
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT)
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
m_output = true;
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE)
m_declOutput = true;
}
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE
|| type==AstVarType::TRI0 || type==AstVarType::TRI1)
m_tristate = true;
if (type==AstVarType::TRI0)
m_isPulldown = true;
if (type==AstVarType::TRI1)
m_isPullup = true;
}
string AstVar::verilogKwd() const {
@@ -264,7 +311,7 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
if ((dim++)==dimension) {
return dtypep;
}
dtypep = adtypep->dtypep();
dtypep = adtypep->subDTypep();
continue;
}
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
@@ -276,6 +323,14 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
}
return NULL;
}
else if (AstNodeClassDType* adtypep = dtypep->castNodeClassDType()) {
if (adtypep->packed()) {
if ((dim++) == dimension) {
return adtypep;
}
}
return NULL;
}
// Node no ->next in loop; use continue where necessary
break;
}
@@ -288,7 +343,7 @@ uint32_t AstNodeDType::arrayElements() {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
entries *= adtypep->elementsConst();
dtypep = adtypep->dtypep();
dtypep = adtypep->subDTypep();
}
else {
// AstBasicDType - nothing below, 1
@@ -307,7 +362,7 @@ pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
if (adtypep->isPacked()) packed += 1;
else unpacked += 1;
dtypep = adtypep->dtypep();
dtypep = adtypep->subDTypep();
}
else {
// AstBasicDType - nothing below, 1
@@ -317,6 +372,15 @@ pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
return make_pair(packed, unpacked);
}
int AstNodeDType::widthPow2() const {
// I.e. width 30 returns 32, width 32 returns 32.
uint32_t width = this->width();
for (int p2=30; p2>=0; p2--) {
if (width > (1UL<<p2)) return (1UL<<(p2+1));
}
return 1;
}
// Special operators
int AstArraySel::dimension(AstNode* nodep) {
// How many dimensions is this reference from the base variable?
@@ -336,7 +400,7 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable
while (nodep) {
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
// AstNodeSelPre stashes the associated variable under a ATTROF so it isn't constified
// AstNodeSelPre stashes the associated variable under a ATTROF of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
else if (nodep->castNodePreSel()) {
if (nodep->castNodePreSel()->attrp()) {
@@ -431,6 +495,87 @@ bool AstSenTree::hasCombo() {
return false;
}
void AstTypeTable::clearCache() {
// When we mass-change widthMin in V3WidthCommit, we need to correct the table.
// Just clear out the maps; the search functions will be used to rebuild the map
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
m_basicps[i] = NULL;
}
for (int isbit=0; isbit<_IDX0_MAX; ++isbit) {
for (int numer=0; numer<AstNumeric::_ENUM_MAX; ++numer) {
LogicMap& mapr = m_logicMap[isbit][numer];
mapr.clear();
}
}
m_detailedMap.clear();
// Clear generic()'s so dead detection will work
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
bdtypep->generic(false);
}
}
}
void AstTypeTable::repairCache() {
// After we mass-change widthMin in V3WidthCommit, we need to correct the table.
clearCache();
for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
(void)findInsertSameDType(bdtypep);
}
}
}
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd) {
if (m_basicps[kwd]) return m_basicps[kwd];
//
AstBasicDType* new1p = new AstBasicDType(fl, kwd);
// Because the detailed map doesn't update this map,
// check the detailed map for this same node
// Also adds this new node to the detailed map
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
else addTypesp(newp);
//
m_basicps[kwd] = newp;
return newp;
}
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
int width, int widthMin, AstNumeric numeric) {
int idx = IDX0_LOGIC;
if (kwd == AstBasicDTypeKwd::LOGIC) idx = IDX0_LOGIC;
else if (kwd == AstBasicDTypeKwd::BIT) idx = IDX0_BIT;
else fl->v3fatalSrc("Bad kwd for findLogicBitDType");
pair<int,int> widths = make_pair(width,widthMin);
LogicMap& mapr = m_logicMap[idx][(int)numeric];
LogicMap::const_iterator it = mapr.find(widths);
if (it != mapr.end()) return it->second;
//
AstBasicDType* new1p = new AstBasicDType(fl, AstBasicDTypeKwd::BIT, numeric, width, widthMin);
// Because the detailed map doesn't update this map,
// check the detailed map for this same node, and if found update this map
// Also adds this new node to the detailed map
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
else addTypesp(newp);
//
mapr.insert(make_pair(widths,newp));
return newp;
}
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
nodep->keyword(), nodep->nrange());
DetailedMap& mapr = m_detailedMap;
DetailedMap::const_iterator it = mapr.find(key);
if (it != mapr.end()) return it->second;
mapr.insert(make_pair(key,nodep));
nodep->generic(true);
// No addTypesp; the upper function that called new() is responsible for adding
return nodep;
}
//======================================================================
// Special walking tree inserters
@@ -501,11 +646,21 @@ void AstNode::dump(ostream& str) {
//<<" "<<(void*)this->m_backp
<<" <e"<<dec<<editCount()
<<((editCount()>=editCountLast())?"#>":">")
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) str<<"/"<<widthMin();
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}";
if (user1p()) str<<" u1="<<(void*)user1p();
if (user2p()) str<<" u2="<<(void*)user2p();
if (user3p()) str<<" u3="<<(void*)user3p();
if (user4p()) str<<" u4="<<(void*)user4p();
if (user5p()) str<<" u5="<<(void*)user5p();
if (hasDType()) {
if (dtypep()==this) str<<" @dt="<<"this@";
else str<<" @dt="<<(void*)dtypep()<<"@"; // Final @ so less likely to by accident think it's nodep
if (AstNodeDType* dtp = dtypep()) {
dtp->dumpSmall(str);
}
} else { // V3Broken will throw an error
if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep();
}
if (name()!="") str<<" "<<AstNode::quoteName(name());
}
@@ -524,8 +679,7 @@ void AstAttrOf::dump(ostream& str) {
void AstBasicDType::dump(ostream& str) {
this->AstNodeDType::dump(str);
str<<" kwd="<<keyword().ascii();
if (isRanged() && !rangep()) str<<" range=["<<msb()<<":"<<lsb()<<"]";
if (implicit()) str<<" [IMPLICIT]";
if (isRanged() && !rangep()) str<<" range=["<<left()<<":"<<right()<<"]";
}
void AstCCast::dump(ostream& str) {
this->AstNode::dump(str);
@@ -571,8 +725,87 @@ void AstRefDType::dump(ostream& str) {
if (defp()) { str<<" -> "; defp()->dump(str); }
else { str<<" -> UNLINKED"; }
}
void AstNodeClassDType::dump(ostream& str) {
this->AstNode::dump(str);
if (packed()) str<<" [PACKED]";
}
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
if (generic()) str<<" [GENERIC]";
if (AstNodeDType* dtp = virtRefDTypep()) {
str<<" refdt="<<(void*)(dtp);
dtp->dumpSmall(str);
}
}
void AstNodeDType::dumpSmall(ostream& str) {
str<<"("
<<(generic()?"G/":"")
<<((isSigned()&&!isDouble())?"s":"")
<<(isNosign()?"n":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) str<<"/"<<widthMin();
str<<")";
}
void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str);
str<<" L"<<level();
if (modPublic()) str<<" [P]";
if (inLibrary()) str<<" [LIB]";
if (dead()) str<<" [DEAD]";
}
void AstPackageImport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
}
void AstTypeTable::dump(ostream& str) {
this->AstNode::dump(str);
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
if (AstBasicDType* subnodep=m_basicps[i]) {
str<<endl; // Newline from caller, so newline first
str<<"\t\t"<<setw(8)<<AstBasicDTypeKwd(i).ascii();
str<<" -> ";
subnodep->dump(str);
}
}
for (int isbit=0; isbit<2; ++isbit) {
for (int issigned=0; issigned<AstNumeric::_ENUM_MAX; ++issigned) {
LogicMap& mapr = m_logicMap[isbit][issigned];
for (LogicMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
AstBasicDType* dtypep = it->second;
str<<endl; // Newline from caller, so newline first
stringstream nsstr;
nsstr<<(isbit?"bw":"lw")
<<it->first.first<<"/"<<it->first.second;
str<<"\t\t"<<setw(8)<<nsstr.str();
if (issigned) str<<" s"; else str<<" u";
str<<" -> ";
dtypep->dump(str);
}
}
}
{
DetailedMap& mapr = m_detailedMap;
for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
AstBasicDType* dtypep = it->second;
str<<endl; // Newline from caller, so newline first
stringstream nsstr;
str<<"\t\tdetailed -> ";
dtypep->dump(str);
}
}
// Note get newline from caller too.
}
void AstVarScope::dump(ostream& str) {
this->AstNode::dump(str);
if (isCircular()) str<<" [CIRC]";
if (varp()) { str<<" -> "; varp()->dump(str); }
else { str<<" ->UNLINKED"; }
}
void AstVarXRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
str<<dotted()<<". - ";
@@ -581,27 +814,9 @@ void AstVarXRef::dump(ostream& str) {
else if (varp()) { varp()->dump(str); }
else { str<<"UNLINKED"; }
}
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
}
void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str);
str<<" L"<<level();
if (modPublic()) str<<" [P]";
if (inLibrary()) str<<" [LIB]";
}
void AstPackageImport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
}
void AstVarScope::dump(ostream& str) {
this->AstNode::dump(str);
if (isCircular()) str<<" [CIRC]";
if (varp()) { str<<" -> "; varp()->dump(str); }
else { str<<" ->UNLINKED"; }
}
void AstVarRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
if (varScopep()) { varScopep()->dump(str); }
@@ -618,9 +833,11 @@ void AstVar::dump(ostream& str) {
else if (isOutput()) str<<" [O]";
}
if (isConst()) str<<" [CONST]";
if (isPullup()) str<<" [PULLUP]";
if (isPulldown()) str<<" [PULLDOWN]";
if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]";
if (isUsedLoopIdx()) str<<" [LOOP]";
if (attrClockEn()) str<<" [aCLKEN]";
if (attrIsolateAssign()) str<<" [aISO]";
if (attrFileDescr()) str<<" [aFD]";
@@ -639,6 +856,11 @@ void AstSenItem::dump(ostream& str) {
void AstParseRef::dump(ostream& str) {
this->AstNode::dump(str);
str<<" ["<<expect().ascii()<<"]";
if (start()) str<<" [START]";
}
void AstDot::dump(ostream& str) {
this->AstNode::dump(str);
if (start()) str<<" [START]";
}
void AstActive::dump(ostream& str) {
this->AstNode::dump(str);
@@ -648,6 +870,7 @@ void AstActive::dump(ostream& str) {
}
void AstNodeFTaskRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
str<<" -> ";
if (dotted()!="") { str<<dotted()<<". - "; }
if (taskp()) { taskp()->dump(str); }
@@ -664,7 +887,8 @@ void AstNodeFTask::dump(ostream& str) {
void AstBegin::dump(ostream& str) {
this->AstNode::dump(str);
if (unnamed()) str<<" [UNNAMED]";
if (hidden()) str<<" [HIDDEN]";
if (generate()) str<<" [GEN]";
if (genforp()) str<<" [GENFOR]";
}
void AstCoverDecl::dump(ostream& str) {
this->AstNode::dump(str);
+638 -302
View File
File diff suppressed because it is too large Load Diff
+8 -13
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Removal of named begin blocks
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -135,32 +134,27 @@ private:
if (m_unnamedScope=="") m_unnamedScope = ident;
else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
// Create CellInline for dotted var resolution
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
m_unnamedScope, "__BEGIN__");
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
if (!m_ftaskp) {
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
m_unnamedScope, "__BEGIN__");
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
}
}
}
// Remap var names and replace lower Begins
nodep->stmtsp()->iterateAndNext(*this);
if (nodep->genforp()) nodep->v3fatalSrc("GENFORs should have been expanded earlier");
}
m_namedScope = oldScope;
m_unnamedScope = oldUnnamed;
// Don't change var names of generate FOR() variables, but do recurse into a child FOR
nodep->flatsp()->iterateAndNext(*this);
// Cleanup
AstNode* addsp = NULL;
if (AstNode* stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = addsp->addNextNull(stmtsp);
}
if (AstNode* stmtsp = nodep->flatsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = addsp->addNextNull(stmtsp);
}
if (addsp) {
nodep->replaceWith(addsp);
} else {
@@ -192,6 +186,7 @@ private:
virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline
if (nodep->user1SetOnce()) return; // Don't double-add text's
if (m_namedScope != "") {
// To keep correct visual order, must add before other Text's
AstNode* afterp = nodep->scopeAttrp();
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Removal of named begin blocks
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Branch prediction
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Branch prediction
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+31 -11
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Find broken links in tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -57,7 +56,7 @@ public:
// METHODS
static void deleted(const AstNode* nodep) {
// Called by operator delete on any node - only if VL_LEAK_CHECKS
if (debug()) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
if (debug()>=9) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
@@ -66,7 +65,7 @@ public:
}
static void addNewed(const AstNode* nodep) {
// Called by operator new on any node - only if VL_LEAK_CHECKS
if (debug()) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
@@ -147,7 +146,7 @@ public:
&& (it->first->backp() ? backs==1 : backs==0)) {
// Use only AstNode::dump instead of the virtual one, as there
// may be varp() and other cross links that are bad.
if (debug()) {
if (v3Global.opt.debugCheck()) {
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
((AstNode*)(it->first))->AstNode::dump(cerr);
cerr<<endl;
@@ -206,9 +205,22 @@ private:
if (nodep->broken()) {
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)");
}
if (nodep->dtypep()) {
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
else if (!nodep->dtypep()->castNodeDType()) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
}
if (v3Global.assertDTypesResolved()) {
if (!nodep->width() && nodep->castNodeMath()) {
nodep->v3fatalSrc("Math node has no assigned width");
if (nodep->hasDType()) {
if (!nodep->dtypep()) nodep->v3fatalSrc("No dtype on node with hasDType(): "<<nodep->prettyTypeName());
} else {
if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName());
}
if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed");
if (AstNodeDType* dnodep = nodep->castNodeDType()) {
if (dnodep->width() != dnodep->widthMin()
&& v3Global.assertWidthsMatch()) {
dnodep->v3fatalSrc("Width != WidthMin");
}
}
}
if (v3Global.assertWidthsMatch()) {
@@ -232,10 +244,18 @@ public:
void V3Broken::brokenAll(AstNetlist* nodep) {
//UINFO(9,__FUNCTION__<<": "<<endl);
BrokenTable::prepForTree();
BrokenMarkVisitor mvisitor (nodep);
BrokenCheckVisitor cvisitor (nodep);
BrokenTable::doneWithTree();
static bool inBroken = false;
if (inBroken) {
// A error called by broken can recurse back into broken; avoid this
UINFO(1,"Broken called under broken, skipping recursion.\n");
} else {
inBroken = true;
BrokenTable::prepForTree();
BrokenMarkVisitor mvisitor (nodep);
BrokenCheckVisitor cvisitor (nodep);
BrokenTable::doneWithTree();
inBroken = false;
}
}
void V3Broken::addNewed(AstNode* nodep) {
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Find broken links in tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+2 -3
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -197,7 +196,7 @@ private:
}
}
}
// Defaults were moved to last in the caseitem list by V3Link
// Defaults were moved to last in the caseitem list by V3LinkDot
if (itemp->isDefault()) { // Case statement's default... Fill the table
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if (!m_valueItem[i]) m_valueItem[i] = itemp;
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+2 -4
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
@@ -77,8 +76,7 @@ private:
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
//
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
castp->width(needsize, nodep->widthMin());
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize, nodep->widthMin());
relinkHandle.relink(castp);
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
//
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
+4 -5
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Clock Domain Crossing Lint
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -361,7 +360,7 @@ private:
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
if (vertexp->user()>=m_userGeneration) return NULL; // Processed - prevent loop
vertexp->user(m_userGeneration);
CdcEitherVertex* mark_outp = NULL;
@@ -384,7 +383,7 @@ private:
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
eFromVertexp->asyncPath(true);
}
return false;
return NULL;
}
// Also ok if from flop, but partially trace the flop so more obvious to users
if (vvertexp->fromFlop()) {
@@ -392,7 +391,7 @@ private:
CdcEitherVertex* eFromVertexp = (CdcEitherVertex*)edgep->fromp();
eFromVertexp->asyncPath(true);
}
return false;
return NULL;
}
}
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into sensitivity block domains
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+47 -16
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -59,6 +58,12 @@ private:
AstScope* m_scopetopp; // Scope under TOPSCOPE
AstCFunc* m_chgFuncp; // Change function we're building
// CONSTANTS
enum MiscConsts {
DETECTARRAY_MAX_INDEXES = 256 // How many indexes before error
// Ok to increase this, but may result in much slower model
};
// METHODS
static int debug() {
static int level = -1;
@@ -66,14 +71,34 @@ private:
return level;
}
AstNode* aselIfNeeded(bool isArray, int index, AstNode* childp) {
if (isArray) {
return new AstArraySel(childp->fileline(), childp,
new AstConst(childp->fileline(), index));
} else {
return childp;
}
}
void genChangeDet(AstVarScope* vscp) {
#ifdef NEW_ORDERING
vscp->v3fatalSrc("Not applicable\n");
#endif
AstVar* varp = vscp->varp();
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
if (!varp->dtypeSkipRefp()->castBasicDType()) {
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
AstArrayDType* arrayp = varp->dtypeSkipRefp()->castArrayDType();
bool isArray = arrayp;
int msb = isArray ? arrayp->msb() : 0;
int lsb = isArray ? arrayp->lsb() : 0;
if (isArray && ((msb - lsb + 1) > DETECTARRAY_MAX_INDEXES)) {
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<<cvtToStr(DETECTARRAY_MAX_INDEXES)
<<" array indexes (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName()<<endl
<<vscp->warnMore()
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased to at least "<<cvtToStr(msb-lsb+1));
} else if (!isArray
&& !varp->dtypeSkipRefp()->castBasicDType()) {
if (debug()) varp->dumpTree(cout,"-DETECTARRAY-");
vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
} else {
string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName();
// Create: VARREF(_last)
@@ -84,17 +109,23 @@ private:
m_topModp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp);
m_scopetopp->addVarp(newvscp);
AstChangeDet* changep
= new AstChangeDet (vscp->fileline(),
new AstVarRef(vscp->fileline(), vscp, false),
new AstVarRef(vscp->fileline(), newvscp, false),
false);
m_chgFuncp->addStmtsp(changep);
AstAssign* initp
= new AstAssign (vscp->fileline(),
new AstVarRef(vscp->fileline(), newvscp, true),
new AstVarRef(vscp->fileline(), vscp, false));
m_chgFuncp->addFinalsp(initp);
for (int index=lsb; index<=msb; ++index) {
AstChangeDet* changep
= new AstChangeDet (vscp->fileline(),
aselIfNeeded(isArray, index,
new AstVarRef(vscp->fileline(), vscp, false)),
aselIfNeeded(isArray, index,
new AstVarRef(vscp->fileline(), newvscp, false)),
false);
m_chgFuncp->addStmtsp(changep);
AstAssign* initp
= new AstAssign (vscp->fileline(),
aselIfNeeded(isArray, index,
new AstVarRef(vscp->fileline(), newvscp, true)),
aselIfNeeded(isArray, index,
new AstVarRef(vscp->fileline(), vscp, false)));
m_chgFuncp->addFinalsp(initp);
}
}
}
@@ -128,7 +159,7 @@ private:
virtual void visit(AstVarScope* nodep, AstNUser*) {
if (nodep->isCircular()) {
UINFO(8," CIRC "<<nodep<<endl);
if (!nodep->user1Inc()) {
if (!nodep->user1SetOnce()) {
genChangeDet(nodep);
}
}
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Pre C-Emit stage changes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+21 -8
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -48,8 +47,10 @@ private:
// Entire netlist:
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN
// AstNode::user2() -> bool. True indicates widthMin has been propagated
// AstNodeDType::user3() -> AstNodeDType*. Alternative node with C size
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
// TYPES
enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
@@ -70,16 +71,28 @@ private:
else if (nodep->width()<=VL_QUADSIZE) return VL_QUADSIZE;
else return nodep->widthWords()*VL_WORDSIZE;
}
void setCppWidth (AstNode* nodep, int width, int widthMin) {
void setCppWidth (AstNode* nodep) {
nodep->user2(true); // Don't resize it again
nodep->width(width, widthMin);
AstNodeDType* old_dtypep = nodep->dtypep();
int width=cppWidth(nodep); // widthMin is unchanged
if (old_dtypep->width() != width) {
// Since any given dtype's cppWidth() is the same, we can just
// remember one convertion for each, and reuse it
if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNode()->castNodeDType()) {
nodep->dtypep(new_dtypep);
} else {
nodep->dtypeChgWidth(width, nodep->widthMin());
AstNodeDType* new_dtypep2 = nodep->dtypep();
if (new_dtypep2 == old_dtypep) nodep->v3fatalSrc("Dtype didn't change when width changed");
old_dtypep->user3p(new_dtypep2); // Remember for next time
}
}
}
void computeCppWidth (AstNode* nodep) {
if (!nodep->user2()) {
if (!nodep->user2() && nodep->hasDType()) {
if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths!
setCppWidth(nodep, nodep->width(), nodep->width()); // set widthMin anyways so can see it later
} else {
setCppWidth(nodep, cppWidth(nodep), nodep->widthMin());
setCppWidth(nodep);
}
}
}
@@ -116,7 +129,7 @@ private:
AstNode* cleanp = new AstAnd (nodep->fileline(),
new AstConst (nodep->fileline(), mask),
nodep);
setCppWidth (cleanp, cppWidth(nodep), nodep->widthMin());
cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS
relinkHandle.relink(cleanp);
}
void insureClean(AstNode* nodep) {
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Pre C-Emit stage changes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+2 -4
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into sensitivity active domains
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2008-2012 by Wilson Snyder. This program is free software; you can
@@ -705,7 +703,7 @@ class GaterVisitor : public GaterBaseVisitor {
virtual void visit(AstAlways* nodep, AstNUser*) {
if (debug()>=9) cout<<endl<<endl<<endl;
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
if (nodep->user4Inc()) return;
if (nodep->user4SetOnce()) return;
clear();
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Break always into clock gated blocks
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+4 -5
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -84,8 +83,8 @@ private:
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
AstVar* varp = vscp->varp();
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1);
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->name());
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
m_modp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
vscp->user1p(newvscp);
@@ -103,7 +102,7 @@ private:
AstVarScope* getCreateLocalVar(FileLine* fl, const string& name, AstVar* examplep, int width) {
AstVar* newvarp;
if (width) {
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, AstLogicPacked(), width);
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, VFlagLogicPacked(), width);
} else {
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, examplep); // No range; 1 bit.
}
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Combine common code into functions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Combine common code into functions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+4 -4
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Configuration Files
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2010-2012 by Wilson Snyder. This program is free software; you can
@@ -26,6 +25,7 @@
#include <set>
#include "V3Global.h"
#include "V3String.h"
#include "V3Config.h"
//######################################################################
@@ -62,7 +62,7 @@ class V3ConfigIgnores {
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)
V3ConfigIgnores() { m_lastLineno = -1; }
@@ -90,7 +90,7 @@ class V3ConfigIgnores {
it = m_ignFiles.find(filename);
// Make new list for this file of all matches
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
if (VString::wildmatch(filename.c_str(), fnit->first.c_str())) {
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
it->second.insert(*lit);
}
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Configuration Files
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2010-2012 by Wilson Snyder. This program is free software; you can
+143 -61
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Constant folding
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -106,8 +105,10 @@ private:
bool m_doNConst; // Enable non-constant-child simplifications
bool m_doShort; // Remove expressions that short circuit
bool m_doV; // Verilog, not C++ conversion
bool m_doGenerate; // Postpone width checking inside generate
AstNodeModule* m_modp; // Current module
AstNode* m_scopep; // Current scope
AstAttrOf* m_attrp; // Current attribute
// METHODS
static int debug() {
@@ -150,7 +151,7 @@ private:
// BIASV(CONSTa,BIASV(b...,BIASV(CONSTc,d...))) // hits operandAsvUp
// BIASV(CONSTa,BIASV(CONSTc,BIASV(c...,d...))) // hits operandAsvConst
// BIASV(BIASV(CONSTa,CONSTc),BIASV(c...,d...))) // hits normal constant propagation
// BIASV(CONST_a_c,BIASV(c...,d...)))
// BIASV(CONST_a_c,BIASV(c...,d...)))
//
// Idea for the future: All BiComAsvs could be lists, sorted by if they're constant
AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv();
@@ -172,13 +173,16 @@ private:
return rnodep->lhsp()->castConst();
}
static bool operandAndOrSame(AstNode* nodep) {
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
AstNodeBiop* np = nodep->castNodeBiop();
AstNodeBiop* lp = np->lhsp()->castNodeBiop();
AstNodeBiop* rp = np->rhsp()->castNodeBiop();
return (lp && rp
&& lp->width()==rp->width()
&& lp->type()==rp->type()
&& operandsSame(lp->lhsp(),rp->lhsp()));
&& (operandsSame(lp->lhsp(),rp->lhsp())
|| operandsSame(lp->rhsp(),rp->rhsp())));
}
static bool matchOrAndNot(AstNodeBiop* nodep) {
// AstOr{$a, AstAnd{AstNot{$b}, $c}} if $a.width1, $a==$b => AstOr{$a,$c}
@@ -367,6 +371,11 @@ private:
// Extraction checks
bool warnSelect(AstSel* nodep) {
AstNode* basefromp = AstArraySel::baseFromp(nodep);
if (m_doGenerate) {
// Never checked yet
V3Width::widthParamsEdit(nodep);
nodep->iterateChildren(*this); // May need "constifying"
}
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
AstVar* varp = varrefp->varp();
if (!varp->dtypep()) varp->v3fatalSrc("Data type lost");
@@ -385,7 +394,7 @@ private:
else if ((nodep->msbConst() > bdtypep->msbMaxSelect())
|| (nodep->lsbConst() > bdtypep->msbMaxSelect())) {
// See also warning in V3Width
nodep->v3error("Selection index out of range: "
nodep->v3warn(SELRANGE, "Selection index out of range: "
<<nodep->msbConst()<<":"<<nodep->lsbConst()
<<" outside "<<bdtypep->msbMaxSelect()<<":0"
<<(bdtypep->lsb()>=0 ? ""
@@ -403,7 +412,10 @@ private:
return node1p->sameTree(node2p);
}
else if (node1p->castVarRef() && node2p->castVarRef()) {
return node1p->sameTree(node2p);
// Avoid comparing widthMin's, which results in lost optimization attempts
// If cleanup sameTree to be smarter, this can be restored.
//return node1p->sameTree(node2p);
return node1p->same(node2p);
} else {
return false;
}
@@ -418,7 +430,7 @@ private:
AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
if (!ifvarp || !elsevarp) return false;
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
if (ifvarp->varp() != elsevarp->varp()) return false;
if (!ifvarp->sameTree(elsevarp)) return false;
return true;
}
bool operandIfIf(AstNodeIf* nodep) {
@@ -441,7 +453,7 @@ private:
oldp->v3fatalSrc("Already constant??\n");
}
AstNode* newp = new AstConst(oldp->fileline(), num);
newp->widthSignedFrom(oldp);
newp->dtypeFrom(oldp);
if (debug()>5) oldp->dumpTree(cout," const_old: ");
if (debug()>5) newp->dumpTree(cout," _new: ");
oldp->replaceWith(newp);
@@ -476,7 +488,7 @@ private:
AstNode* newp = new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(), 0),
checkp->unlinkFrBack());
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
@@ -523,10 +535,24 @@ private:
void replaceWChild(AstNode* nodep, AstNode* childp) {
// NODE(..., CHILD(...)) -> CHILD(...)
childp->unlinkFrBackWithNext();
childp->widthSignedFrom(nodep);
childp->dtypeFrom(nodep);
nodep->replaceWith(childp);
nodep->deleteTree(); nodep=NULL;
}
//! Replace a ternary node with its RHS after iterating
//! Used with short-circuting, where the RHS has not yet been iterated.
void replaceWIteratedRhs(AstNodeTriop* nodep) {
if (AstNode *rhsp = nodep->rhsp()) rhsp->iterateAndNext(*this);
replaceWChild(nodep, nodep->rhsp()); // May have changed
}
//! Replace a ternary node with its THS after iterating
//! Used with short-circuting, where the THS has not yet been iterated.
void replaceWIteratedThs(AstNodeTriop* nodep) {
if (AstNode *thsp = nodep->thsp()) thsp->iterateAndNext(*this);
replaceWChild(nodep, nodep->thsp()); // May have changed
}
void replaceWLhs(AstNodeUniop* nodep) {
// Keep LHS, remove RHS
replaceWChild(nodep, nodep->lhsp());
@@ -583,7 +609,9 @@ private:
//nodep->dumpTree(cout, " repAsvRUp_new: ");
}
void replaceAndOr (AstNodeBiop* nodep) {
// Or(And(CONSTll,lr),And(CONSTrl==ll,rr)) -> And(CONSTll,Or(lr,rr))
// OR (AND (CONSTll,lr), AND(CONSTrl==ll,rr)) -> AND (CONSTll, OR(lr,rr))
// OR (AND (CONSTll,lr), AND(CONSTrl, rr=lr)) -> AND (OR(ll,rl), rr)
// nodep ^lp ^llp ^lrp ^rp ^rlp ^rrp
// (Or/And may also be reversed)
AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop();
AstNode* llp = lp->lhsp()->unlinkFrBack();
@@ -592,12 +620,23 @@ private:
AstNode* rlp = rp->lhsp()->unlinkFrBack();
AstNode* rrp = rp->rhsp()->unlinkFrBack();
nodep->replaceWith(lp);
lp->lhsp(llp);
lp->rhsp(nodep);
nodep->lhsp(lrp);
nodep->rhsp(rrp);
rp->deleteTree();
rlp->deleteTree();
if (operandsSame(llp,rlp)) {
lp->lhsp(llp);
lp->rhsp(nodep);
nodep->lhsp(lrp);
nodep->rhsp(rrp);
rp->deleteTree();
rlp->deleteTree();
} else if (operandsSame(lrp, rrp)) {
lp->lhsp(nodep);
lp->rhsp(rrp);
nodep->lhsp(llp);
nodep->rhsp(rlp);
rp->deleteTree();
lrp->deleteTree();
} else {
nodep->v3fatalSrc("replaceAndOr on something operandAndOrSame shouldn't have matched");
}
//nodep->dumpTree(cout, " repAndOr_new: ");
}
void replaceShiftSame (AstNodeBiop* nodep) {
@@ -625,7 +664,7 @@ private:
AstNode* newp = (nodep->castExtendS()
? (new AstExtendS(nodep->fileline(), arg0p))->castNode()
: (new AstExtend (nodep->fileline(), arg0p))->castNode());
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replacePowShift (AstNodeBiop* nodep) { // Pow or PowS
@@ -634,8 +673,8 @@ private:
AstShiftL* newp = new AstShiftL(nodep->fileline(),
new AstConst(nodep->fileline(), 1),
rhsp);
newp->widthSignedFrom(nodep);
newp->lhsp()->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
newp->lhsp()->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift
@@ -644,7 +683,7 @@ private:
AstNode* opp = nodep->rhsp()->unlinkFrBack();
AstShiftL* newp = new AstShiftL(nodep->fileline(),
opp, new AstConst(nodep->fileline(), amount));
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift
@@ -653,7 +692,7 @@ private:
AstNode* opp = nodep->lhsp()->unlinkFrBack();
AstShiftR* newp = new AstShiftR(nodep->fileline(),
opp, new AstConst(nodep->fileline(), amount));
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceShiftOp (AstNodeBiop* nodep) {
@@ -713,11 +752,11 @@ private:
newp = new AstShiftL(nodep->fileline(), ap,
new AstConst(nodep->fileline(), newshift));
}
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
newp = new AstAnd (nodep->fileline(),
newp,
new AstConst (nodep->fileline(), mask));
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
//newp->dumpTree(cout, " repShiftShift_new: ");
newp->accept(*this); // Further reduce, either node may have more reductions.
@@ -736,7 +775,7 @@ private:
AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false;
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false;
AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false;
if (varref1p->varp() != varref2p->varp()) return false;
if (!varref1p->sameTree(varref2p)) return false;
AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false;
AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
// We need to make sure there's no self-references involved in either
@@ -787,7 +826,7 @@ private:
bool replaceNodeAssign(AstNodeAssign* nodep) {
if (nodep->lhsp()->castVarRef()
&& nodep->rhsp()->castVarRef()
&& nodep->lhsp()->sameTree(nodep->rhsp())
&& nodep->lhsp()->castVarRef()->sameNoLvalue(nodep->rhsp()->castVarRef())
&& !nodep->castAssignDly()) {
// X = X. Quite pointless, though X <= X may override another earlier assignment
if (nodep->castAssignW()) {
@@ -837,16 +876,14 @@ private:
// Form ranges
AstSel* sel1p = new AstSel(conp->fileline(), rhsp, lsb1, msb1-lsb1+1);
AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2-lsb2+1);
sel1p->width(msb1-lsb1+1,msb1-lsb1+1);
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
// Make new assigns of same flavor as old one
//*** Not cloneTree; just one node.
AstNode* newp = NULL;
if (!need_temp) {
AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
asn1ap->dtypeFrom(sel1p);
asn2ap->dtypeFrom(sel2p);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1ap);
// cppcheck-suppress nullPointer // addNext deals with it
@@ -858,9 +895,9 @@ private:
string name1 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc()));
string name2 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc()));
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
AstLogicPacked(), msb1-lsb1+1);
VFlagLogicPacked(), msb1-lsb1+1);
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
AstLogicPacked(), msb2-lsb2+1);
VFlagLogicPacked(), msb2-lsb2+1);
m_modp->addStmtp(temp1p);
m_modp->addStmtp(temp2p);
AstNodeAssign* asn1ap=nodep->cloneType
@@ -875,10 +912,10 @@ private:
AstNodeAssign* asn2bp=nodep->cloneType
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
->castNodeAssign();
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
asn1ap->dtypeFrom(temp1p);
asn1bp->dtypeFrom(temp1p);
asn2ap->dtypeFrom(temp2p);
asn2bp->dtypeFrom(temp2p);
// This order matters
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1ap);
@@ -924,7 +961,7 @@ private:
AstAnd* newp = new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(), val),
fromp);
newp->width(nodep->width(), nodep->width()); // widthMin no longer applicable
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
if (debug()>=9) newp->dumpTree(cout," _new: ");
@@ -938,7 +975,7 @@ private:
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
<<nodep->prettyTypeName()<<endl
<<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
<<errorp->warnMore()<<"... Location of non-constant "
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
replaceZero(nodep); nodep=NULL;
} else {
@@ -1075,8 +1112,8 @@ private:
// expression, not the potentially smaller lsb1p's width
newlsbp = new AstAdd(lsb1p->fileline(),
lsb2p, new AstExtend(lsb1p->fileline(), lsb1p));
newlsbp->widthFrom(lsb2p); // Unsigned
newlsbp->castAdd()->rhsp()->widthFrom(lsb2p); // Unsigned
newlsbp->dtypeFrom(lsb2p); // Unsigned
newlsbp->castAdd()->rhsp()->dtypeFrom(lsb2p);
}
AstSel* newp = new AstSel(nodep->fileline(),
fromp,
@@ -1136,7 +1173,7 @@ private:
fromp,
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
widthp);
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
@@ -1154,7 +1191,7 @@ private:
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->rhsp(new AstSel(nodep->fileline(),
birhsp, lsbp, widthp));
fromp->widthSignedFrom(nodep);
fromp->dtypeFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
void replaceSelIntoUniop(AstSel* nodep) {
@@ -1167,16 +1204,22 @@ private:
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->widthSignedFrom(nodep);
bilhsp, lsbp, widthp));
fromp->dtypeFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstAttrOf* nodep, AstNUser*) {
AstAttrOf* oldAttr = m_attrp;
m_attrp = nodep;
nodep->iterateChildren(*this);
m_attrp = oldAttr;
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
bool did=false;
if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
if (m_doV && nodep->varp()->hasSimpleInit() && !m_attrp) {
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
nodep->varp()->valuep()->iterateAndNext(*this);
if (operandConst(nodep->varp()->valuep())
@@ -1219,16 +1262,6 @@ private:
// Not constant propagated (for today) because AstMath::isOpaque is set
// Someday if lower is constant, convert to quoted "string".
virtual void visit(AstAttrOf* nodep, AstNUser*) {
// Don't iterate children, don't want to lose VarRef.
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
replaceNum(nodep, num); nodep=NULL;
} else {
nodep->v3fatalSrc("Missing ATTR type case");
}
}
bool onlySenItemInSenTree(AstNodeSenItem* nodep) {
// Only one if it's not in a list
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
@@ -1382,7 +1415,7 @@ private:
break;
}
}
// Pass2, remove dup edges
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
senp; senp=nextp) {
@@ -1680,6 +1713,8 @@ private:
// v--- *1* These ops are always first, as we warn before replacing
// v--- *V* This op is a verilog op, only in m_doV mode
// v--- *C* This op works on all constant children, allowed in m_doConst mode
// v--- *S* This op specifies a type should use short-circuting of its lhs op
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
// Generic constants on both side. Do this first to avoid other replacements
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
@@ -1687,7 +1722,11 @@ private:
// Zero on one side or the other
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstAnd {$lhsp.isZero, $rhsp, isTPure($rhsp)}", "replaceZero(nodep)"); // Can't use replaceZeroChkPure as we make this pattern in ChkPure
// This visit function here must allow for short-circuiting.
TREEOPS("AstLogAnd {$lhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
// This visit function here must allow for short-circuiting.
TREEOPS("AstLogOr {$lhsp.isOne}", "replaceNum(nodep, 1)");
TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
@@ -1741,6 +1780,9 @@ private:
TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
// This visit function here must allow for short-circuiting.
TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)");
TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)");
TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b
@@ -1914,6 +1956,8 @@ private:
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
// Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
// This visit function here must allow for short-circuiting.
TREEOPS("AstLogIf {$lhsp.isZero}", "replaceNum(nodep, 1)");
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
// Strings
@@ -1947,13 +1991,14 @@ public:
// Processing Mode Enum
enum ProcMode {
PROC_PARAMS,
PROC_GENERATE,
PROC_LIVE,
PROC_V_WARN,
PROC_V_NOWARN,
PROC_V_EXPENSIVE,
PROC_CPP
};
// CONSTUCTORS
ConstVisitor(ProcMode pmode) {
m_params = false;
@@ -1962,13 +2007,16 @@ public:
m_doNConst = false;
m_doShort = true; // Presently always done
m_doV = false;
m_doGenerate = false; // Inside generate conditionals
m_warn = false;
m_wremove = true; // Overridden in visitors
m_modp = NULL;
m_scopep = NULL;
m_attrp = NULL;
//
switch (pmode) {
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
case PROC_GENERATE: m_doV = true; m_doNConst = true; m_params = true; m_required = true; m_doGenerate = true; break;
case PROC_LIVE: break;
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
@@ -1987,12 +2035,46 @@ public:
//######################################################################
// Const class functions
//! Force this cell node's parameter list to become a constant
//! @return Pointer to the edited node.
AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
// Resize even if the node already has a width, because burried in the treee we may
// have a node we just created with signing, etc, that isn't sized yet.
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
// Resize even if the node already has a width, because buried in the tree
// we may have a node we just created with signing, etc, that isn't sized yet.
// Make sure we've sized everything first
nodep = V3Width::widthParamsEdit(nodep);
ConstVisitor visitor(ConstVisitor::PROC_PARAMS);
if (AstVar* varp=nodep->castVar()) {
// If a var wants to be constified, it's really a param, and
// we want the value to be constant. We aren't passed just the
// init value because we need widthing above to handle the var's type.
if (varp->valuep()) visitor.mainAcceptEdit(varp->valuep());
} else {
nodep = visitor.mainAcceptEdit(nodep);
}
// Because we do edits, nodep links may get trashed and core dump this.
//if (debug()>0) nodep->dumpTree(cout," forceConDONE: ");
return nodep;
}
//! Force this cell node's parameter list to become a constant inside generate.
//! If we are inside a generated "if", "case" or "for", we don't want to
//! trigger warnings when we deal with the width. It is possible that these
//! are spurious, existing within sub-expressions that will not actually be
//! generated. Since such occurrences, must be constant, in order to be
//! someting a generate block can depend on, we can wait until later to do the
//! width check.
//! @return Pointer to the edited node.
AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
// Resize even if the node already has a width, because buried in the tree
// we may have a node we just created with signing, etc, that isn't sized
// yet.
// Make sure we've sized everything first
nodep = V3Width::widthGenerateParamsEdit(nodep);
ConstVisitor visitor(ConstVisitor::PROC_GENERATE);
if (AstVar* varp=nodep->castVar()) {
// If a var wants to be constified, it's really a param, and
// we want the value to be constant. We aren't passed just the
+2 -5
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Propagate constants across AST
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -31,9 +29,8 @@
class V3Const {
public:
// Force this cell node's parameter list to become a constant
// Return new node that may have replaced nodep
static AstNode* constifyParamsEdit(AstNode* nodep);
static AstNode* constifyGenerateParamsEdit(AstNode* nodep);
// Only do constant pushing, without removing dead logic
static void constifyAllLive(AstNetlist* nodep);
// Everything that's possible
+2 -3
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Netlist (top level) functions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -216,7 +215,7 @@ private:
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code),
new AstArraySel(varp->fileline(), above.m_chgRefp->cloneTree(true), index_code));
toggleVarRecurse(adtypep->dtypeSkipRefp(), depth+1,
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
newent,
varp, chgVarp);
newent.cleanup();
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Coverage modules/signals together
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Netlist (top level) functions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Coverage modules/signals together
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+41 -5
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Dead code elimination
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -22,6 +21,8 @@
// Remove any unreferenced modules
// Remove any unreferenced variables
//
// TODO: A graph would make the process of circular and interlinked
// dependencies easier to resolve.
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
// instead of needing as many visitors.
//*************************************************************************
@@ -73,6 +74,7 @@ private:
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
// AstVar::user1() -> int. Count of number of references
// AstVarScope::user1() -> int. Count of number of references
// AstNodeDType::user1() -> int. Count of number of references
AstUser1InUse m_inuser1;
// TYPES
@@ -83,6 +85,7 @@ private:
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
AssignMap m_assignMap; // List of all simple assignments for each variable
bool m_elimUserVars; // Allow removal of user's vars
bool m_elimDTypes; // Allow removal of DTypes
bool m_sideEffect; // Side effects discovered in assign RHS
// METHODS
@@ -91,7 +94,19 @@ private:
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void checkAll(AstNode* nodep) {
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc();
}
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
}
void checkDType(AstNodeDType* nodep) {
if (!nodep->generic() // Don't remove generic types
&& m_elimDTypes) { // dtypes stick around until post-widthing
m_varEtcsp.push_back(nodep);
}
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
}
// VISITORS
@@ -123,11 +138,17 @@ private:
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkDType(nodep);
checkAll(nodep);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstNodeDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkDType(nodep);
checkAll(nodep);
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
@@ -155,11 +176,13 @@ private:
// Similar code in V3Life
m_sideEffect = false;
nodep->rhsp()->iterateAndNext(*this);
checkAll(nodep);
// Has to be direct assignment without any EXTRACTing.
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
if (varrefp && !m_sideEffect
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
checkAll(varrefp); // Must track reference to dtype()
} else { // Track like any other statement
nodep->lhsp()->iterateAndNext(*this);
}
@@ -225,14 +248,19 @@ private:
public:
// CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes;
m_sideEffect = false;
// Prepare to remove some datatypes
nodep->typeTablep()->clearCache();
// Operate on whole netlist
nodep->accept(*this);
deadCheckVar();
// Modules after vars, because might be vars we delete inside a mod we delete
deadCheckMod();
// We may have removed some datatypes, cleanup
nodep->typeTablep()->repairCache();
}
virtual ~DeadVisitor() {}
};
@@ -240,7 +268,15 @@ public:
//######################################################################
// Dead class functions
void V3Dead::deadifyAll(AstNetlist* nodep, bool elimUserVars) {
void V3Dead::deadifyModules(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, elimUserVars);
DeadVisitor visitor (nodep, false, false);
}
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true);
}
void V3Dead::deadifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true);
}
+6 -4
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Dead branch elimination
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -31,8 +29,12 @@
class V3Dead {
public:
// Modules, no vars/dtypes
static void deadifyModules(AstNetlist* nodep);
// Modules, Data types
static void deadifyDTypes(AstNetlist* nodep);
// Everything that's possible
static void deadifyAll(AstNetlist* nodep, bool elimUserVars);
static void deadifyAll(AstNetlist* nodep);
};
#endif // Guard
+6 -7
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -132,9 +131,9 @@ private:
} else {
if (width==0) {
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
varp->widthSignedFrom(oldvarscp);
varp->dtypeFrom(oldvarscp);
} else { // Used for vset and dimensions, so can zero init
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstBitPacked(), width);
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, VFlagBitPacked(), width);
}
addmodp->addStmtp(varp);
m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp));
@@ -157,9 +156,9 @@ private:
if (oldactivep->sensesp() != m_activep->sensesp()) {
if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
&& !varrefp->varp()->user2()) {
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName());
varrefp->v3warn(MULTIDRIVEN,"... Location of first driving block");
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName()<<endl
<<varrefp->warnMore()<<"... Location of first driving block"<<endl
<<oldactivep->warnMore()<<"... Location of other driving block");
varrefp->varp()->user2(true);
}
UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Pre C-Emit stage changes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+2 -3
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Prevent very deep expressions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -69,7 +68,7 @@ private:
// though it's one bit wide, needs the mask in the upper bits.
// (Someday we'll have a valid bitmask instead of widths....)
// See t_func_crc for an example test that requires this
AstLogicPacked(), nodep->width());
VFlagLogicPacked(), nodep->width());
if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function");
m_funcp->addInitsp(varp);
// Replace node tree with reference to var
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Prevent very deep expressions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Prevent very deep expressions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Prevent very deep expressions
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Rename scope references to module-local references
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Rename scope references to module-local references
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+133 -30
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit C++ for tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -30,10 +29,11 @@
#include <algorithm>
#include "V3Global.h"
#include "V3String.h"
#include "V3EmitC.h"
#include "V3EmitCBase.h"
#define VL_VALUE_STRING_MAX_WIDTH 1024 // We use a static char array in VL_VALUE_STRING
#define VL_VALUE_STRING_MAX_WIDTH 8192 // We use a static char array in VL_VALUE_STRING
//######################################################################
// Emit statements and math operators
@@ -486,7 +486,7 @@ public:
visit(nodep->castNodeUniop(), vup);
} else {
putbs("VL_REDXOR_");
puts(cvtToStr(nodep->lhsp()->widthPow2()));
puts(cvtToStr(nodep->lhsp()->dtypep()->widthPow2()));
puts("(");
nodep->lhsp()->iterateAndNext(*this);
puts(")");
@@ -623,6 +623,7 @@ public:
virtual void visit(AstTraceDecl*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTraceInc*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstCFile*, AstNUser*) {} // Handled outside the Visit class
virtual void visit(AstTypedef*, AstNUser*) {} // Nothing needed presently
// Default
virtual void visit(AstNode* nodep, AstNUser*) {
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
@@ -661,10 +662,10 @@ class EmitCImp : EmitCStmts {
changep->lhsp()->iterateAndNext(*this);
}
else {
AstVarRef* lhsp = changep->lhsp()->castVarRef();
AstVarRef* rhsp = changep->rhsp()->castVarRef();
if (!lhsp) changep->v3fatalSrc("Not ref?");
if (!rhsp) changep->v3fatalSrc("Not ref?");
AstNode* lhsp = changep->lhsp();
AstNode* rhsp = changep->rhsp();
if (!lhsp->castVarRef() && !lhsp->castArraySel()) changep->v3fatalSrc("Not ref?");
if (!rhsp->castVarRef() && !rhsp->castArraySel()) changep->v3fatalSrc("Not ref?");
for (int word=0; word<changep->lhsp()->widthWords(); word++) {
if (!gotOne) {
gotOne = true;
@@ -842,6 +843,7 @@ class EmitCImp : EmitCStmts {
void emitCoverageDecl(AstNodeModule* modp);
void emitCoverageImp(AstNodeModule* modp);
void emitDestructorImp(AstNodeModule* modp);
void emitSavableImp(AstNodeModule* modp);
void emitTextSection(AstType type);
void emitIntFuncDecls(AstNodeModule* modp);
// High level
@@ -888,7 +890,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(nodep->name());
if (isArray) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
}
@@ -909,7 +911,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->isWide()) puts("W");
puts("("+nodep->name());
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
@@ -931,7 +933,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(nodep->vlArgType(true,false));
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
puts(";\n");
@@ -957,7 +959,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(nodep->name());
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
@@ -1062,7 +1064,7 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format,
++pos;
switch (pos[0]) {
case 'q': emitIQW(detailp); break;
case 'w':
case 'w':
COMMA;
puts(cvtToStr(detailp->widthMin()));
needComma = true;
@@ -1191,11 +1193,11 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
AstNode* argp = *elistp;
if (!argp) {
// expectDisplay() checks this first, so internal error if found here
dispp->v3error("Internal: Missing arguments for $display format");
dispp->v3error("Internal: Missing arguments for $display-like format");
return;
}
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
dispp->v3error("Exceeded limit of 1024 bits for any display arguments");
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any $display-like arguments");
}
if (argp && argp->isWide()
&& (fmtLetter=='d'||fmtLetter=='u')) {
@@ -1286,17 +1288,17 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
case 'z':
case 'l':
case 'v':
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
nodep->v3error("Unsupported: $display-like format code: %"<<pos[0]);
break;
default:
nodep->v3error("Unknown $display format code: %"<<pos[0]);
nodep->v3error("Unknown $display-like format code: %"<<pos[0]);
break;
}
}
}
if (elistp != NULL) {
// expectFormat also checks this, and should have found it first, so internal
elistp->v3error("Internal: Extra arguments for $display format");
elistp->v3error("Internal: Extra arguments for $display-like format");
}
displayEmit(nodep, isScan);
}
@@ -1340,7 +1342,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
int vecnum = vects++;
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
@@ -1366,7 +1368,16 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
puts(varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
if (zeroit) {
puts(" = 0;\n");
// We want to force an initial edge on uninitialized clocks (from 'X' to
// whatever the first value is). Since the class is instantiated before
// initial blocks are evaluated, this should not clash with any initial
// block settings. Clocks are always BIT datatypes, so zeroit is true.
if (v3Global.opt.xInitialEdge()
&& (0 == varp->name().find("__Vclklast__"))) {
puts(" = 1;\n");
} else {
puts(" = 0;\n");
}
} else {
puts(" = VL_RAND_RESET_");
emitIQW(varp);
@@ -1436,7 +1447,7 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
// compatible, and have a common wrapper.
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
puts( "const char* hierp, const char* pagep, const char* commentp) {\n");
puts( "static uint32_t fake_zero_count = 0;\n");
puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant
puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin
puts( "*countp = 0;\n");
puts( "SP_COVER_INSERT(countp,");
@@ -1459,6 +1470,79 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) {
puts("}\n");
}
void EmitCImp::emitSavableImp(AstNodeModule* modp) {
if (v3Global.opt.savable() ) {
puts("\n// Savable\n");
for (int de=0; de<2; ++de) {
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
string funcname = de ? "__Vdeserialize" : "__Vserialize";
string writeread = de ? "read" : "write";
string op = de ? ">>" : "<<";
puts("void "+modClassName(modp)+"::"+funcname+"("+classname+"& os) {\n");
// Place a computed checksum to insure proper structure save/restore formatting
// OK if this hash includes some things we won't dump, since just looking for loading the wrong model
VHashFnv hash;
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstVar* varp = nodep->castVar()) {
hash.hash(varp->name());
hash.hash(varp->dtypep()->width());
}
}
ofp()->printf( "vluint64_t __Vcheckval = VL_ULL(0x%" VL_PRI64 "x);\n",
hash.value());
if (de) {
puts("os.readAssert(__Vcheckval);\n");
} else {
puts("os<<__Vcheckval;\n");
}
// Save all members
if (v3Global.opt.inhibitSim()) puts("os"+op+"__Vm_inhibitSim;\n");
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstVar* varp = nodep->castVar()) {
if (varp->isIO() && modp->isTop() && optSystemC()) {
// System C top I/O doesn't need loading, as the lower level subinst code does it.
}
else if (varp->isParam()) {}
else if (varp->isStatic() && varp->isConst()) {}
else {
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
int vecnum = vects++;
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
puts("; ++"+ivar+") {\n");
}
if (varp->basicp() && (varp->basicp()->keyword() == AstBasicDTypeKwd::STRING
|| !varp->basicp()->isWide())) {
puts("os"+op+varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts(";\n");
} else {
puts("os."+writeread+"(&"+varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts(",sizeof("+varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts("));\n");
}
for (int v=0; v<vects; ++v) puts( "}}\n");
}
}
}
if (modp->isTop()) { // Save the children
puts( "__VlSymsp->"+funcname+"(os);\n");
}
puts("}\n");
}
}
}
void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
// Need implementation here. Be careful of alignment code; needs to be uniquified
// with module name to avoid multiple symbols.
@@ -1516,7 +1600,7 @@ void EmitCImp::emitSensitives() {
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
int vecnum = vects++;
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
@@ -1557,7 +1641,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts( "_eval(vlSymsp);\n");
#ifndef NEW_ORDERING
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts("}\n");
#endif
puts("}\n");
@@ -1576,7 +1661,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts( "_eval(vlSymsp);\n");
#ifndef NEW_ORDERING
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "}\n");
#endif
puts("}\n");
@@ -1673,8 +1759,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
} else {
puts("#include \"verilated.h\"\n");
}
if (v3Global.opt.savable()) {
puts("#include \"verilated_save.h\"\n");
}
if (v3Global.opt.coverage()) {
puts("#include \"SpCoverage.h\"\n");
if (v3Global.opt.savable()) v3error("--coverage and --savable not supported together");
}
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
puts("#include \""+topClassName()+"__Inlines.h\"\n");
@@ -1840,10 +1930,22 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
puts("static void traceFull ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
puts("static void traceChg ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
}
if (v3Global.opt.savable()) {
puts("void __Vserialize(VerilatedSerialize& os);\n");
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
puts("\n");
}
puts("} VL_ATTR_ALIGNED(64);\n");
puts("} VL_ATTR_ALIGNED(128);\n");
puts("\n");
// Save/restore
if (v3Global.opt.savable() && modp->isTop()) {
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vserialize(os); return os;}\n");
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vdeserialize(os); return os;}\n");
puts("\n");
}
// finish up h-file
if (!optSystemPerl()) {
puts("#endif /*guard*/\n");
@@ -1891,6 +1993,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
emitCtorImp(modp);
emitConfigureImp(modp);
emitDestructorImp(modp);
emitSavableImp(modp);
emitCoverageImp(modp);
}
@@ -2076,7 +2179,7 @@ class EmitCTrace : EmitCStmts {
puts("vcdp->declArray");
} else if (nodep->isQuad()) {
puts("vcdp->declQuad ");
} else if (nodep->msbEndianed() || nodep->lsbEndianed()) {
} else if (nodep->left() || nodep->right()) {
puts("vcdp->declBus ");
} else {
puts("vcdp->declBit ");
@@ -2091,8 +2194,8 @@ class EmitCTrace : EmitCStmts {
puts(",-1");
}
if (!nodep->isDouble() // When float/double no longer have widths this can go
&& (nodep->msbEndianed() || nodep->lsbEndianed())) {
puts(","+cvtToStr(nodep->msbEndianed())+","+cvtToStr(nodep->lsbEndianed()));
&& (nodep->left() || nodep->right())) {
puts(","+cvtToStr(nodep->left())+","+cvtToStr(nodep->right()));
}
puts(");");
}
@@ -2108,7 +2211,7 @@ class EmitCTrace : EmitCStmts {
puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad ");
} else if (nodep->declp()->msbEndianed() || nodep->declp()->lsbEndianed()) {
} else if (nodep->declp()->left() || nodep->declp()->right()) {
puts("vcdp->"+full+"Bus ");
} else {
puts("vcdp->"+full+"Bit ");
@@ -2118,7 +2221,7 @@ class EmitCTrace : EmitCStmts {
puts(",");
emitTraceValue(nodep, arrayindex);
if (!nodep->isDouble() // When float/double no longer have widths this can go
&& (nodep->declp()->msbEndianed() || nodep->declp()->lsbEndianed() || emitTraceIsScBv(nodep))) {
&& (nodep->declp()->left() || nodep->declp()->right() || emitTraceIsScBv(nodep))) {
puts(","+cvtToStr(nodep->declp()->widthMin()));
}
puts(");\n");
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit C++ code for module tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+1 -71
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit C++ for tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -34,74 +32,6 @@
#include "V3File.h"
#include "V3Ast.h"
//######################################################################
// V3OutCFile: A class for abstracting out SystemC/C++ details
class V3OutCFile : public V3OutFile {
int m_private;
public:
V3OutCFile(const string& filename) : V3OutFile(filename) {
resetPrivate();
}
virtual ~V3OutCFile() {}
virtual void putsCellDecl(const string& classname, const string& cellname) {
this->printf("%-19s\t%s;\n",
(classname + "*").c_str(),cellname.c_str());
}
virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); }
virtual void putsIntTopInclude() { }
// Print out public/privates
void resetPrivate() { m_private = 0; }
void putsPrivate(bool setPrivate) {
if (setPrivate && m_private!=1) {
puts("private:\n");
m_private = 1;
} else if (!setPrivate && m_private!=2) {
puts("public:\n");
m_private = 2;
}
}
};
class V3OutScFile : public V3OutCFile {
public:
V3OutScFile(const string& filename) : V3OutCFile(filename) {}
virtual ~V3OutScFile() {}
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
virtual void putsIntTopInclude() {
puts("#include \"systemc.h\"\n");
puts("#include \"verilated_sc.h\"\n");
}
};
class V3OutSpFile : public V3OutCFile {
public:
V3OutSpFile(const string& filename) : V3OutCFile(filename) {}
virtual ~V3OutSpFile() {}
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
virtual void putsIntTopInclude() {
puts("#include \"systemperl.h\"\n");
puts("#include \"verilated_sc.h\"\n");
}
};
class V3OutVFile : public V3OutFile {
public:
V3OutVFile(const string& filename) : V3OutFile(filename) {}
virtual ~V3OutVFile() {}
virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); }
};
class V3OutMkFile : public V3OutFile {
public:
V3OutMkFile(const string& filename) : V3OutFile(filename) {}
virtual ~V3OutMkFile() {}
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
// No automatic indentation yet.
void puts(const char* strg) { putsNoTracking(strg); }
void puts(const string& strg) { putsNoTracking(strg); }
};
//######################################################################
// Base Visitor class -- holds output file pointer
+1 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit C++ for tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+36 -10
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit C++ for tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -116,8 +115,8 @@ class EmitCSyms : EmitCBaseVisitor {
AstScope* scopep = it->first; AstNodeModule* smodp = it->second;
for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
AstNodeModule* modp = it->first;
AstVar* varp = it->second;
if (modp == smodp) {
AstVar* varp = it->second;
// Need to split the module + var name into the original-ish full scope and variable name under that scope.
// The module instance name is included later, when we know the scopes this module is under
string whole = scopep->name()+"__DOT__"+varp->name();
@@ -205,7 +204,8 @@ class EmitCSyms : EmitCBaseVisitor {
}
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->isSigUserRdPublic()) {
if (nodep->isSigUserRdPublic()
&& !nodep->isParam()) { // The VPI functions require a pointer to allow modification, but parameters are constants
m_modVars.push_back(make_pair(m_modp, nodep));
}
}
@@ -340,8 +340,13 @@ void EmitCSyms::emitSymHdr() {
puts("\n// METHODS\n");
puts("inline const char* name() { return __Vm_namep; }\n");
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
if (v3Global.opt.savable() ) {
puts("void __Vserialize(VerilatedSerialize& os);\n");
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
}
puts("\n");
puts("} VL_ATTR_ALIGNED(64);\n");
puts("\n");
puts("#endif /*guard*/\n");
}
@@ -461,10 +466,10 @@ void EmitCSyms::emitSymImp() {
for (AstNodeDType* dtypep=varp->dtypep(); dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
bounds += " ,"; bounds += cvtToStr(adtypep->arrayp()->msbConst());
bounds += ","; bounds += cvtToStr(adtypep->arrayp()->lsbConst());
bounds += " ,"; bounds += cvtToStr(adtypep->msb());
bounds += ","; bounds += cvtToStr(adtypep->lsb());
dim++;
dtypep = adtypep->dtypep();
dtypep = adtypep->subDTypep();
}
else break; // AstBasicDType - nothing below, 1
}
@@ -499,7 +504,28 @@ void EmitCSyms::emitSymImp() {
}
puts("}\n");
puts("\n");
if (v3Global.opt.savable() ) {
puts("\n");
for (int de=0; de<2; ++de) {
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
string funcname = de ? "__Vdeserialize" : "__Vserialize";
string op = de ? ">>" : "<<";
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
puts( "// LOCAL STATE\n");
// __Vm_namep presumably already correct
puts( "os"+op+"__Vm_activity;\n");
puts( "os"+op+"__Vm_didInit;\n");
puts( "// SUBCELL STATE\n");
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
if (!modp->isTop()) {
puts( scopep->nameDotless()+"."+funcname+"(os);\n");
}
}
puts("}\n");
}
}
}
//######################################################################
@@ -525,7 +551,7 @@ void EmitCSyms::emitDpiHdr() {
puts("extern \"C\" {\n");
puts("#endif\n");
puts("\n");
int firstExp = 0;
int firstImp = 0;
for (vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
@@ -571,7 +597,7 @@ void EmitCSyms::emitDpiImp() {
puts("// or 2. Compile all __Dpi.cpp files in the same compiler run,\n");
puts("// and #ifdefs already inserted here will sort everything out.\n");
puts("\n");
puts("#include \""+topClassName()+"__Dpi.h\"\n");
puts("#include \""+topClassName()+".h\"\n");
puts("\n");
+4 -2
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit Makefile
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
@@ -81,6 +80,9 @@ public:
if (v3Global.dpi()) {
putMakeClassEntry(of, "verilated_dpi.cpp");
}
if (v3Global.opt.savable()) {
putMakeClassEntry(of, "verilated_save.cpp");
}
if (v3Global.opt.systemPerl()) {
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
}
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit Makefile
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+33 -10
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit Verilog from tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
@@ -61,7 +60,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
putsNoTracking(AstNode::quoteName(str));
putsNoTracking("\"");
}
// VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) {
nodep->iterateChildren(*this);
@@ -383,6 +382,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
// %l lhsp - if appropriate
// %r rhsp - if appropriate
// %t thsp - if appropriate
// %d dtypep - if appropriate
// %k Potential line break
bool inPct = false;
putbs("");
@@ -412,6 +412,11 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
else thsp->iterateAndNext(*this);
break;
}
case 'd': {
if (!nodep->dtypep()) { nodep->v3fatalSrc("emitVerilog() references undef node"); }
else nodep->dtypep()->iterateAndNext(*this);
break;
}
default:
nodep->v3fatalSrc("Unknown emitVerilog format code: %"<<pos[0]);
break;
@@ -447,11 +452,11 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
puts("[");
if (nodep->msbp()->castConst() && nodep->lsbp()->castConst()) {
// Looks nicer if we print [1:0] rather than [32'sh1:32sh0]
puts(cvtToStr(nodep->msbEndianedp()->castConst()->toSInt())); puts(":");
puts(cvtToStr(nodep->lsbEndianedp()->castConst()->toSInt())); puts("]");
puts(cvtToStr(nodep->leftp()->castConst()->toSInt())); puts(":");
puts(cvtToStr(nodep->rightp()->castConst()->toSInt())); puts("]");
} else {
nodep->msbEndianedp()->iterateAndNext(*this); puts(":");
nodep->lsbEndianedp()->iterateAndNext(*this); puts("]");
nodep->leftp()->iterateAndNext(*this); puts(":");
nodep->rightp()->iterateAndNext(*this); puts("]");
}
}
virtual void visit(AstSel* nodep, AstNUser*) {
@@ -490,7 +495,24 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
virtual void visit(AstConstDType* nodep, AstNUser*) {
putfs(nodep,"const ");
nodep->dtypep()->iterateAndNext(*this);
nodep->subDTypep()->iterateAndNext(*this);
}
virtual void visit(AstArrayDType* nodep, AstNUser*) {
nodep->subDTypep()->iterateAndNext(*this);
nodep->rangep()->iterateAndNext(*this);
}
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
puts(nodep->verilogKwd()+" ");
if (nodep->packed()) puts("packed ");
puts("\n");
nodep->membersp()->iterateAndNext(*this);
puts("}");
}
virtual void visit(AstMemberDType* nodep, AstNUser*) {
nodep->subDTypep()->iterateAndNext(*this);
puts(" ");
puts(nodep->name());
puts("}");
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
@@ -596,7 +618,7 @@ class EmitVStreamVisitor : public EmitVBaseVisitor {
virtual void putbs(const string& str) { puts(str); }
virtual void putfs(AstNode*, const string& str) { putbs(str); }
virtual void putqs(AstNode*, const string& str) { putbs(str); }
public:
public:
EmitVStreamVisitor(AstNode* nodep, ostream& os)
: m_os(os) {
nodep->accept(*this);
@@ -635,7 +657,8 @@ public:
FileLine* prefixFl() const { return m_prefixFl; }
int column() const { return m_column; }
EmitVPrefixedFormatter(ostream& os, const string& prefix, int flWidth)
: V3OutFormatter("__STREAM", true), m_os(os), m_prefix(prefix), m_flWidth(flWidth) {
: V3OutFormatter("__STREAM", V3OutFormatter::LA_VERILOG)
, m_os(os), m_prefix(prefix), m_flWidth(flWidth) {
m_column = 0;
m_prefixFl = v3Global.rootp()->fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks
}
+1 -3
View File
@@ -1,11 +1,9 @@
//-*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit Verilog code for module tree
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+196
View File
@@ -0,0 +1,196 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Emit Verilog from tree
//
// Code available from: http://www.veripool.org/verilator
//
//*************************************************************************
//
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// 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.
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
#include "V3Global.h"
#include "V3String.h"
#include "V3EmitXml.h"
#include "V3EmitCBase.h"
//######################################################################
// Emit statements and math operators
class EmitXmlFileVisitor : public EmitCBaseVisitor {
// MEMBERS
V3OutFile* m_ofp;
// METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// Outfile methods
V3OutFile* ofp() const { return m_ofp; }
virtual void puts(const string& str) { ofp()->puts(str); }
virtual void putbs(const string& str) { ofp()->putbs(str); }
virtual void putfs(AstNode*, const string& str) { putbs(str); }
virtual void putqs(AstNode*, const string& str) { putbs(str); }
virtual void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); }
virtual void putsQuoted(const string& str) {
// Quote \ and " for use inside C programs
// Don't use to quote a filename for #include - #include doesn't \ escape.
// Duplicate in V3File - here so we can print to string
putsNoTracking("\"");
putsNoTracking(AstNode::quoteName(str));
putsNoTracking("\"");
}
// XML methods
void outputTag(AstNode* nodep, string tag) {
if (tag=="") tag = VString::downcase(nodep->typeName());
puts("<"+tag+" "+nodep->fileline()->xml());
if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); }
}
void outputChildrenEnd(AstNode* nodep, string tag) {
if (tag=="") tag = VString::downcase(nodep->typeName());
if (nodep->op1p() || nodep->op2p() || nodep->op3p() || nodep->op4p()) {
puts(">\n");
nodep->iterateChildren(*this);
puts("</"+tag+">\n");
} else {
puts("/>\n");
}
}
// VISITORS
virtual void visit(AstNetlist* nodep, AstNUser*) {
puts("<netlist>\n");
nodep->iterateChildren(*this);
puts("</netlist>\n");
}
virtual void visit(AstNodeModule* nodep, AstNUser*) {
outputTag(nodep, "");
if (nodep->level()==1 || nodep->level()==2) // ==2 because we don't add wrapper when in XML mode
puts(" topModule=\"1\""); // IEEE vpiTopModule
outputChildrenEnd(nodep, "");
}
virtual void visit(AstCell* nodep, AstNUser*) {
outputTag(nodep, "instance"); // IEEE: vpiInstance
puts(" defName="); putsQuoted(nodep->modName()); // IEEE vpiDefName
outputChildrenEnd(nodep, "instance");
}
virtual void visit(AstPin* nodep, AstNUser*) {
// What we call a pin in verilator is a port in the IEEE spec.
outputTag(nodep, "port"); // IEEE: vpiPort
if (nodep->modVarp()->isInOnly())
puts(" direction=\"in\"");
else if (nodep->modVarp()->isOutOnly())
puts(" direction=\"out\"");
else puts(" direction=\"inout\"");
puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
outputChildrenEnd(nodep, "port");
}
virtual void visit(AstAssignW* nodep, AstNUser*) {
outputTag(nodep, "contAssign"); // IEEE: vpiContAssign
outputChildrenEnd(nodep, "contAssign");
}
// Data types
virtual void visit(AstBasicDType* nodep, AstNUser*) {
outputTag(nodep, "basicDType ");
if (nodep->isRanged()) {
puts(" left=\""+cvtToStr(nodep->left())+"\"");
puts(" right=\""+cvtToStr(nodep->right())+"\"");
}
puts("/>\n");
}
// Default
virtual void visit(AstNode* nodep, AstNUser*) {
outputTag(nodep, "");
outputChildrenEnd(nodep, "");
}
public:
EmitXmlFileVisitor(AstNode* nodep, V3OutFile* ofp) {
m_ofp = ofp;
nodep->accept(*this);
}
virtual ~EmitXmlFileVisitor() {}
};
//######################################################################
// Emit to a stream (perhaps stringstream)
class EmitXmlPrefixedFormatter : public V3OutFormatter {
ostream& m_os;
string m_prefix; // What to print at beginning of each line
int m_flWidth; // Padding of fileline
int m_column; // Rough location; need just zero or non-zero
FileLine* m_prefixFl;
// METHODS
virtual void putcOutput(char chr) {
if (chr == '\n') {
m_column = 0;
m_os<<chr;
} else {
if (m_column == 0) {
m_column = 10;
m_os<<m_prefixFl->ascii()+":";
m_os<<V3OutFile::indentSpaces(m_flWidth-(m_prefixFl->ascii().length()+1));
m_os<<" ";
m_os<<m_prefix;
}
m_column++;
m_os<<chr;
}
}
public:
void prefixFl(FileLine* fl) { m_prefixFl = fl; }
FileLine* prefixFl() const { return m_prefixFl; }
int column() const { return m_column; }
EmitXmlPrefixedFormatter(ostream& os, const string& prefix, int flWidth)
: V3OutFormatter("__STREAM", V3OutFormatter::LA_VERILOG)
, m_os(os), m_prefix(prefix), m_flWidth(flWidth) {
m_column = 0;
m_prefixFl = v3Global.rootp()->fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks
}
virtual ~EmitXmlPrefixedFormatter() {}
};
//######################################################################
// EmitXml class functions
void V3EmitXml::emitxml() {
UINFO(2,__FUNCTION__<<": "<<endl);
// All-in-one file
V3OutXmlFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+".xml");
of.putsHeader();
of.puts("<!-- DESCR" "IPTION: Verilator output: XML representation of netlist -->\n");
of.puts("<verilator_xml>\n");
{
stringstream sstr;
FileLine::fileNameNumMapDumpXml(sstr);
of.puts(sstr.str());
}
EmitXmlFileVisitor visitor (v3Global.rootp(), &of);
of.puts("</verilator_xml>\n");
}
+6 -8
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Link modules/signals together
// DESCRIPTION: Verilator: Emit XML code
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -20,8 +18,8 @@
//
//*************************************************************************
#ifndef _V3LINK_H_
#define _V3LINK_H_ 1
#ifndef _V3EMITXML_H_
#define _V3EMITXML_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
@@ -29,9 +27,9 @@
//============================================================================
class V3Link {
class V3EmitXml {
public:
static void link(AstNetlist* nodep);
static void emitxml();
};
#endif // Guard
+107 -79
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Error handling
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -44,6 +43,7 @@ bool V3Error::s_errorSuppressed = false;
bool V3Error::s_describedEachWarn[V3ErrorCode::_ENUM_MAX];
bool V3Error::s_describedWarnings = false;
bool V3Error::s_pretendError[V3ErrorCode::_ENUM_MAX];
V3Error::MessagesSet V3Error::s_messages;
struct v3errorIniter {
v3errorIniter() { V3Error::init(); }
@@ -67,18 +67,50 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
//######################################################################
// FileLineSingleton class functions
const string FileLineSingleton::filenameLetters(int no) {
const int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
char out[size];
char* op = out+size-1;
*--op = '\0'; // We build backwards
int num = no;
do {
*--op = 'a'+num%26;
num /= 26;
} while (num);
return op;
}
//! Convert filenames to a filenameno
//! This lets us assign a nice small identifier for debug messages, but more
//! importantly lets us use a 4 byte int instead of 8 byte pointer in every
//! FileLine.
//! We associate a language with each source file, so we also set the default
//! for this.
int FileLineSingleton::nameToNumber(const string& filename) {
// Convert filenames to a filenameno
// This lets us assign a nice small identifier for debug messages, but more
// importantly lets us use a 4 byte int instead of 8 byte pointer in every FileLine.
map<string,int>::const_iterator iter = m_namemap.find(filename);
FileNameNumMap::const_iterator iter = m_namemap.find(filename);
if (VL_LIKELY(iter != m_namemap.end())) return iter->second;
int num = m_names.size();
m_names.push_back(filename);
m_languages.push_back(V3LangCode::mostRecent());
m_namemap.insert(make_pair(filename,num));
return num;
}
//! Support XML output
//! Experimental. Updated to also put out the language.
void FileLineSingleton::fileNameNumMapDumpXml(ostream& os) {
os<<"<files>\n";
for (FileNameNumMap::const_iterator it = m_namemap.begin(); it != m_namemap.end(); ++it) {
os<<"<file id=\""<<filenameLetters(it->second)
<<"\" filename=\""<<it->first
<<"\" language=\""<<numberToLang(it->second).ascii()<<"\"/>\n";
}
os<<"</files>\n";
}
//######################################################################
// FileLine class functions
@@ -94,19 +126,6 @@ FileLine::FileLine(FileLine::EmptySecret) {
}
}
const string FileLine::filenameLetters() const {
const int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
char out[size];
char* op = out+size-1;
*--op = '\0'; // We build backwards
int num = m_filenameno;
do {
*--op = 'a'+num%26;
num /= 26;
} while (num);
return op;
}
string FileLine::lineDirectiveStrg(int enterExit) const {
char numbuf[20]; sprintf(numbuf, "%d", lineno());
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
@@ -162,6 +181,10 @@ FileLine* FileLine::copyOrSameFileLine() {
return newp;
}
void FileLine::updateLanguage () {
language(v3Global.opt.fileLanguage(filename()));
}
const string FileLine::filebasename() const {
string name = filename();
string::size_type pos;
@@ -256,6 +279,14 @@ void FileLine::v3errorEnd(ostringstream& str) {
}
}
string FileLine::warnMore() const {
if (this && m_lineno) {
return V3Error::warnMore()+ascii()+": ";
} else {
return V3Error::warnMore();
}
}
#ifdef VL_LEAK_CHECKS
typedef set<FileLine*> FileLineCheckSet;
FileLineCheckSet fileLineLeakChecks;
@@ -292,7 +323,7 @@ void FileLine::deleteAllRemaining() {
// Eventually the list will be empty and terminate the loop.
}
fileLineLeakChecks.clear();
FileLineSingleton::clear();
singleton().clear();
#endif
}
@@ -361,7 +392,9 @@ bool V3Error::isError(V3ErrorCode code, bool supp) {
else return false;
}
string V3Error::msgPrefix(V3ErrorCode code, bool supp) {
string V3Error::msgPrefix() {
V3ErrorCode code=s_errorCode;
bool supp=s_errorSuppressed;
if (supp) return "-arning-suppressed: ";
else if (code==V3ErrorCode::EC_INFO) return "-Info: ";
else if (code==V3ErrorCode::EC_FATAL) return "%Error: ";
@@ -386,18 +419,6 @@ void V3Error::vlAbort () {
//======================================================================
// Global Functions
string V3Error::v3sform (const char* format, ...) {
static char msg[1000] = "";
va_list ap;
va_start(ap,format);
vsprintf(msg,format,ap);
va_end(ap);
string out = msg;
return out;
}
void V3Error::suppressThisWarning() {
if (s_errorCode>=V3ErrorCode::EC_MIN) {
V3Stats::addStatSum(string("Warnings, Suppressed ")+s_errorCode.ascii(), 1);
@@ -405,63 +426,70 @@ void V3Error::suppressThisWarning() {
}
}
string V3Error::warnMore() {
return msgPrefix();
}
void V3Error::v3errorEnd (ostringstream& sstr) {
#if defined(__COVERITY__) || defined(__cppcheck__)
if (s_errorCode==V3ErrorCode::EC_FATAL) __coverity_panic__(x);
#endif
if (!s_errorSuppressed
// Skip suppressed messages
if (s_errorSuppressed
// On debug, show only non default-off warning to prevent pages of warnings
|| (debug() && !s_errorCode.defaultsOff())) {
cerr<<msgPrefix()<<sstr.str();
if (sstr.str()[sstr.str().length()-1] != '\n') {
cerr<<endl;
}
if (!s_errorSuppressed && s_errorCode!=V3ErrorCode::EC_INFO) {
if (!s_describedEachWarn[s_errorCode]
&& !s_pretendError[s_errorCode]) {
s_describedEachWarn[s_errorCode] = true;
if (s_errorCode>=V3ErrorCode::EC_FIRST_WARN && !s_describedWarnings) {
cerr<<msgPrefix()<<"Use \"/* verilator lint_off "<<s_errorCode.ascii()
<<" */\" and lint_on around source to disable this message."<<endl;
s_describedWarnings = true;
}
if (s_errorCode.dangerous()) {
cerr<<msgPrefix()<<"*** See the manual before disabling this,"<<endl;
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
}
&& (!debug() || s_errorCode.defaultsOff())) return;
string msg = msgPrefix()+sstr.str();
if (msg[msg.length()-1] != '\n') msg += '\n';
// Suppress duplicates
if (s_messages.find(msg) != s_messages.end()) return;
s_messages.insert(msg);
// Output
cerr<<msg;
if (!s_errorSuppressed && s_errorCode!=V3ErrorCode::EC_INFO) {
if (!s_describedEachWarn[s_errorCode]
&& !s_pretendError[s_errorCode]) {
s_describedEachWarn[s_errorCode] = true;
if (s_errorCode>=V3ErrorCode::EC_FIRST_WARN && !s_describedWarnings) {
cerr<<msgPrefix()<<"Use \"/* verilator lint_off "<<s_errorCode.ascii()
<<" */\" and lint_on around source to disable this message."<<endl;
s_describedWarnings = true;
}
// If first warning is not the user's fault (internal/unsupported) then give the website
// Not later warnings, as a internal may be caused by an earlier problem
if (s_tellManual == 0) {
if (s_errorCode.mentionManual()
|| sstr.str().find("Unsupported") != string::npos) {
s_tellManual = 1;
} else {
if (s_errorCode.dangerous()) {
cerr<<msgPrefix()<<"*** See the manual before disabling this,"<<endl;
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
}
}
// If first warning is not the user's fault (internal/unsupported) then give the website
// Not later warnings, as a internal may be caused by an earlier problem
if (s_tellManual == 0) {
if (s_errorCode.mentionManual()
|| sstr.str().find("Unsupported") != string::npos) {
s_tellManual = 1;
} else {
s_tellManual = 2;
}
}
if (isError(s_errorCode, s_errorSuppressed)) incErrors();
else incWarnings();
if (s_errorCode==V3ErrorCode::EC_FATAL
|| s_errorCode==V3ErrorCode::EC_FATALSRC) {
static bool inFatal = false;
if (!inFatal) {
inFatal = true;
if (s_tellManual==1) {
cerr<<msgPrefix()<<"See the manual and http://www.veripool.org/verilator for more assistance."<<endl;
s_tellManual = 2;
}
}
if (isError(s_errorCode, s_errorSuppressed)) incErrors();
else incWarnings();
if (s_errorCode==V3ErrorCode::EC_FATAL
|| s_errorCode==V3ErrorCode::EC_FATALSRC) {
static bool inFatal = false;
if (!inFatal) {
inFatal = true;
if (s_tellManual==1) {
cerr<<msgPrefix()<<"See the manual and http://www.veripool.org/verilator for more assistance."<<endl;
s_tellManual = 2;
}
#ifndef _V3ERROR_NO_GLOBAL_
if (debug()) {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
V3Stats::statsFinalAll(v3Global.rootp());
V3Stats::statsReport();
}
#endif
if (debug()) {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
V3Stats::statsFinalAll(v3Global.rootp());
V3Stats::statsReport();
}
vlAbort();
#endif
}
vlAbort();
}
}
}
+59 -19
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Error handling
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -29,8 +27,11 @@
#include <sstream>
#include <bitset>
#include <map>
#include <set>
#include <deque>
#include "V3LangCode.h"
//######################################################################
class V3ErrorCode {
@@ -76,11 +77,15 @@ public:
IMPLICIT, // Implicit wire
IMPURE, // Impure function not being inlined
INCABSPATH, // Include has absolute path
INITIALDLY, // Initial delayed statement
LITENDIAN, // Little bit endian vector
MODDUP, // Duplicate module
MULTIDRIVEN, // Driven from multiple blocks
PINMISSING, // Cell pin not specified
PINNOCONNECT, // Cell pin not connected
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro
SELRANGE, // Selection index out of range
STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word
SYNCASYNCNET, // Mixed sync + async reset
@@ -116,11 +121,13 @@ public:
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
"COMBDLY", "DEFPARAM", "DECLFILENAME",
"ENDLABEL", "GENCLK",
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
"INCABSPATH", "INITIALDLY",
"LITENDIAN", "MODDUP",
"MULTIDRIVEN",
"PINMISSING", "PINNOCONNECT",
"REALCVT", "REDEFMACRO",
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
" MAX"
@@ -145,6 +152,7 @@ public:
|| m_e==ENDLABEL
|| m_e==IMPLICIT
|| m_e==LITENDIAN
|| m_e==PINMISSING
|| m_e==REALCVT
|| m_e==UNSIGNED
|| m_e==WIDTH); }
@@ -154,6 +162,7 @@ public:
|| m_e==DEFPARAM
|| m_e==DECLFILENAME
|| m_e==INCABSPATH
|| m_e==PINNOCONNECT
|| m_e==SYNCASYNCNET
|| m_e==UNDRIVEN
|| m_e==UNUSED
@@ -168,6 +177,9 @@ public:
class V3Error {
// Base class for any object that wants debugging and error reporting
typedef set<string> MessagesSet;
private:
static bool s_describedWarnings; // Told user how to disable warns
static bool s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning
@@ -179,6 +191,7 @@ class V3Error {
static ostringstream s_errorStr; // Error string being formed
static V3ErrorCode s_errorCode; // Error string being formed will abort
static bool s_errorSuppressed; // Error being formed should be suppressed
static MessagesSet s_messages; // What errors we've outputted
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
V3Error() { cerr<<("Static class"); abort(); }
@@ -188,7 +201,7 @@ class V3Error {
// ACCESSORS
static void debugDefault(int level) { s_debugDefault = level; }
static int debugDefault() { return s_debugDefault; }
static string msgPrefix(V3ErrorCode code=s_errorCode, bool supp=s_errorSuppressed); // returns %Error/%Warn
static string msgPrefix(); // returns %Error/%Warn
static int errorCount() { return s_errCount; }
static int warnCount() { return s_warnCount; }
static int errorOrWarnCount() { return errorCount()+warnCount(); }
@@ -201,15 +214,17 @@ class V3Error {
static void suppressThisWarning(); // Suppress next %Warn if user has it off
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
static bool isError(V3ErrorCode code, bool supp);
static string v3sform (const char* format, ...);
static string lineStr (const char* filename, int lineno);
static V3ErrorCode errorCode() { return s_errorCode; }
// When printing an error/warning, print prefix for multiline message
static string warnMore();
// Internals for v3error()/v3fatal() macros only
// Error end takes the string stream to output, be careful to seek() as needed
static ostringstream& v3errorPrep (V3ErrorCode code) {
s_errorStr.str(""); s_errorCode=code; s_errorSuppressed=false; return s_errorStr; }
static ostringstream& v3errorStr () { return s_errorStr; }
static void v3errorPrep(V3ErrorCode code) {
s_errorStr.str(""); s_errorCode=code; s_errorSuppressed=false; }
static ostringstream& v3errorStr() { return s_errorStr; }
static void vlAbort();
static void v3errorEnd(ostringstream& sstr); // static, but often overridden in classes.
};
@@ -220,7 +235,9 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
// These allow errors using << operators: v3error("foo"<<"bar");
// Careful, you can't put () around msg, as you would in most macro definitions
#define v3warnCode(code,msg) v3errorEnd(((V3Error::v3errorPrep(code)<<msg),V3Error::v3errorStr()));
// Note the commas are the comma operator, not separating arguments. These are needed to insure
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
#define v3warnCode(code,msg) v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
#define v3warn(code,msg) v3warnCode(V3ErrorCode::code,msg)
#define v3info(msg) v3warn(EC_INFO,msg)
#define v3fatal(msg) v3warn(EC_FATAL,msg)
@@ -244,10 +261,10 @@ template< class T> std::string cvtToStr (const T& t) {
ostringstream os; os<<t; return os.str();
}
inline uint32_t cvtToHash(void* vp) {
inline uint32_t cvtToHash(const void* vp) {
// We can shove a 64 bit pointer into a 32 bit bucket
// On 32 bit systems, lower is always 0, but who cares?
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
union { const void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
u.l.upper=0; u.l.lower=0; u.up=vp;
return u.l.upper^u.l.lower;
}
@@ -256,9 +273,18 @@ inline uint32_t cvtToHash(void* vp) {
class FileLine;
//! Singleton class with tables of per-file data.
//! This singleton class contains tables of data that are unchanging in each
//! source file (each with its own unique filename number).
class FileLineSingleton {
map<string,int> m_namemap; // filenameno for each filename
// TYPES
typedef map<string,int> FileNameNumMap;
typedef map<string,V3LangCode> FileLangNumMap;
// MEMBERS
FileNameNumMap m_namemap; // filenameno for each filename
deque<string> m_names; // filename text for each filenameno
deque<V3LangCode> m_languages; // language for each filenameno
// COSNTRUCTORS
FileLineSingleton() { }
~FileLineSingleton() { }
@@ -267,15 +293,22 @@ protected:
// METHODS
int nameToNumber(const string& filename);
const string numberToName(int filenameno) const { return m_names[filenameno]; }
void clear() { m_namemap.clear(); m_names.clear(); }
const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
void numberToLang(int filenameno, const V3LangCode l) { m_languages[filenameno] = l; }
void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); }
void fileNameNumMapDumpXml(ostream& os);
static const string filenameLetters(int fileno);
};
//! File and line number of an object, mostly for error reporting
//! This class is instantiated for every source code line (potentially
//! millions). To save space, per-file information (e.g. filename, source
//! language is held in tables in the FileLineSingleton class.
class FileLine {
// File and line number of an object, mostly for error reporting
int m_lineno;
int m_filenameno;
bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
// Consider moving opt.language() into here, so can know language per-node
private:
struct EmptySecret {};
@@ -295,6 +328,7 @@ protected:
friend class V3PreLex;
friend class V3PreProcImp;
void lineno(int num) { m_lineno = num; }
void language (V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
void lineDirective(const char* textp, int& enterExitRef);
void linenoInc() { m_lineno++; }
@@ -317,12 +351,15 @@ public:
#endif
int lineno () const { return m_lineno; }
V3LangCode language () const { return singleton().numberToLang(m_filenameno); }
void updateLanguage ();
string ascii() const;
const string filename () const { return singleton().numberToName(m_filenameno); }
const string filenameLetters() const;
const string filenameLetters() const { return singleton().filenameLetters(m_filenameno); }
const string filebasename () const;
const string filebasenameNoExt () const;
const string profileFuncname() const;
const string xml() const { return "fl=\""+filenameLetters()+cvtToStr(lineno())+"\""; }
string lineDirectiveStrg(int enter_exit_level) const;
void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code,flag); } // Turn on/off warning messages on this line.
void warnOff(V3ErrorCode code, bool flag) { warnOn(code,!flag); }
@@ -348,17 +385,20 @@ public:
defaultFileLine().warnOff(code, flag); }
static bool globalWarnOff(const string& code, bool flag) {
return defaultFileLine().warnOff(code, flag); }
static void fileNameNumMapDumpXml(ostream& os) {
singleton().fileNameNumMapDumpXml(os); }
// METHODS - Called from netlist
// Merge warning disables from another fileline
void modifyStateInherit(const FileLine* fromp);
// Change the current fileline due to actions discovered after parsing
// and may have side effects on other nodes sharing this FileLine.
// Use only when this is intended
// Use only when this is intended
void modifyWarnOff(V3ErrorCode code, bool flag) { warnOff(code,flag); }
// OPERATORS
void v3errorEnd(ostringstream& str);
string warnMore() const;
inline bool operator==(FileLine rhs) const {
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
}
+23 -24
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Add temporaries, such as for expand nodes
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
@@ -126,13 +125,13 @@ private:
new AstConst(nodep->fileline(), word));
} else if (nodep->isQuad() && word==0) {
AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
quadfromp->dtypeSetBitSized(VL_QUADSIZE,quadfromp->widthMin(),AstNumeric::UNSIGNED);
return new AstCCast (nodep->fileline(),
quadfromp,
VL_WORDSIZE);
} else if (nodep->isQuad() && word==1) {
AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
quadfromp->dtypeSetBitSized(VL_QUADSIZE,quadfromp->widthMin(),AstNumeric::UNSIGNED);
return new AstCCast (nodep->fileline(),
new AstShiftR (nodep->fileline(),
quadfromp,
@@ -310,7 +309,7 @@ private:
// VISITORS
virtual void visit(AstExtend* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->isWide()) {
// See under ASSIGN(EXTEND)
@@ -319,7 +318,7 @@ private:
AstNode* newp = lhsp;
if (nodep->isQuad()) {
if (lhsp->isQuad()) {
lhsp->widthSignedFrom(nodep); // Just mark it, else nop
lhsp->dtypeFrom(nodep); // Just mark it, else nop
} else if (lhsp->isWide()) {
nodep->v3fatalSrc("extending larger thing into smaller?");
} else {
@@ -330,7 +329,7 @@ private:
if (lhsp->isQuad() || lhsp->isWide()) {
nodep->v3fatalSrc("extending larger thing into smaller?");
} else {
lhsp->widthSignedFrom(nodep); // Just mark it, else nop
lhsp->dtypeFrom(nodep); // Just mark it, else nop
}
}
replaceWithDelete(nodep,newp); nodep=NULL;
@@ -349,7 +348,7 @@ private:
}
virtual void visit(AstSel* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
// Remember, Sel's may have non-integer rhs, so need to optimize for that!
if (nodep->widthMin()!=(int)nodep->widthConst()) nodep->v3fatalSrc("Width mismatch");
@@ -438,7 +437,7 @@ private:
AstNode* newp = lowp;
if (midp) newp = new AstOr (nodep->fileline(), midp, newp);
if (hip) newp = new AstOr (nodep->fileline(), hip, newp);
newp->widthFrom(nodep);
newp->dtypeFrom(nodep);
replaceWithDelete(nodep,newp); nodep=NULL;
}
else { // Long/Quad from Long/Quad
@@ -450,11 +449,11 @@ private:
fromp,
dropCondBound(lsbp),
nodep->width());
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
if (!nodep->isQuad() && fromp->isQuad()) {
newp = new AstCCast (newp->fileline(), newp, nodep);
}
newp->widthSignedFrom(nodep);
newp->dtypeFrom(nodep);
replaceWithDelete(nodep,newp); nodep=NULL;
}
}
@@ -646,7 +645,7 @@ private:
}
virtual void visit(AstConcat* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->isWide()) {
// See under ASSIGN(WIDE)
@@ -663,7 +662,7 @@ private:
new AstConst (nodep->fileline(), rhsshift),
nodep->width()),
rhsp);
newp->widthFrom(nodep); // Unsigned
newp->dtypeFrom(nodep); // Unsigned
replaceWithDelete(nodep,newp); nodep=NULL;
}
}
@@ -686,7 +685,7 @@ private:
}
virtual void visit(AstReplicate* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->isWide()) {
// See under ASSIGN(WIDE)
@@ -712,11 +711,11 @@ private:
new AstConst (nodep->fileline(), rhsshift),
nodep->width()),
newp);
newp->widthFrom(nodep); // Unsigned
newp->dtypeFrom(nodep); // Unsigned
}
lhsp->deleteTree(); // Never used
}
newp->widthFrom(nodep); // Unsigned
newp->dtypeFrom(nodep); // Unsigned
replaceWithDelete(nodep,newp); nodep=NULL;
}
}
@@ -731,7 +730,7 @@ private:
AstNode* newp;
if (lhswidth==1) {
newp = new AstNegate (nodep->fileline(), lhsp->cloneTree(true));
newp->width(VL_WORDSIZE,VL_WORDSIZE);
newp->dtypeSetLogicSized(VL_WORDSIZE,VL_WORDSIZE,AstNumeric::UNSIGNED); // Replicate always unsigned
} else {
newp = newAstWordSelClone (lhsp, w);
for (unsigned repnum=1; repnum<times; repnum++) {
@@ -747,7 +746,7 @@ private:
}
virtual void visit(AstChangeXor* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
UINFO(8," Wordize ChangeXor "<<nodep<<endl);
// -> (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}}
@@ -762,7 +761,7 @@ private:
}
void visitEqNeq(AstNodeBiop* nodep) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->lhsp()->isWide()) {
UINFO(8," Wordize EQ/NEQ "<<nodep<<endl);
@@ -788,7 +787,7 @@ private:
virtual void visit(AstNeq* nodep, AstNUser*) { visitEqNeq (nodep); }
virtual void visit(AstRedOr* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->lhsp()->isWide()) {
UINFO(8," Wordize REDOR "<<nodep<<endl);
@@ -812,7 +811,7 @@ private:
}
}
virtual void visit(AstRedAnd* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->lhsp()->isWide()) {
UINFO(8," Wordize REDAND "<<nodep<<endl);
@@ -841,7 +840,7 @@ private:
}
}
virtual void visit(AstRedXor* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
nodep->iterateChildren(*this);
if (nodep->lhsp()->isWide()) {
UINFO(8," Wordize REDXOR "<<nodep<<endl);
@@ -860,13 +859,13 @@ private:
}
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
m_stmtp = nodep;
nodep->iterateChildren(*this);
m_stmtp = NULL;
}
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
if (nodep->user1Inc()) return; // Process once
if (nodep->user1SetOnce()) return; // Process once
m_stmtp = nodep;
nodep->iterateChildren(*this);
bool did = false;
+1 -3
View File
@@ -1,11 +1,9 @@
// -*- C++ -*-
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Expansion of wide operator macros to C operators
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
+37 -19
View File
@@ -1,10 +1,9 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
@@ -301,7 +300,7 @@ private:
}
bool readContentsFile(const string& filename, StrList& outl) {
int fd = open (filename.c_str(), O_RDONLY);
if (!fd) return false;
if (fd<0) return false;
m_readEof = false;
readBlocks(fd, -1, outl);
close(fd);
@@ -436,7 +435,7 @@ private:
dup2(fd_stdout[P_WR], 1);
// And stderr comes from parent
execl("/bin/sh", "sh", "-c", command.c_str(), NULL);
execl("/bin/sh", "sh", "-c", command.c_str(), (char*)NULL);
// Don't use v3fatal, we don't share the common structures any more
fprintf(stderr,"--pipe-filter: exec failed: %s\n",strerror(errno));
_exit(10);
@@ -546,8 +545,8 @@ bool V3InFilter::readWholefile(const string& filename, V3InFilter::StrList& outl
//######################################################################
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
V3OutFormatter::V3OutFormatter(const string& filename, bool verilog)
: m_filename(filename), m_verilog(verilog)
V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang)
: m_filename(filename), m_lang(lang)
, m_lineno(1), m_column(0)
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
@@ -560,7 +559,7 @@ const char* V3OutFormatter::indentStr(int num) {
static char str[MAXSPACE+20];
char* cp = str;
if (num>MAXSPACE) num=MAXSPACE;
if (!m_verilog) { // verilogPrefixedTree doesn't want tabs
if (!m_lang==LA_VERILOG) { // verilogPrefixedTree doesn't want tabs
while (num>=8) {
*cp++ = '\t';
num -= 8;
@@ -625,8 +624,13 @@ int V3OutFormatter::endLevels (const char *strg) {
case ')':
levels-=INDBLK;
break;
case '<':
if (m_lang==LA_XML) {
if (cp[1] == '/') levels-=INDBLK;
}
break;
case 'e':
if (m_verilog && tokenEnd(cp)) {
if (m_lang==LA_VERILOG && tokenEnd(cp)) {
levels-=INDBLK;
}
break;
@@ -668,39 +672,53 @@ void V3OutFormatter::puts (const char *strg) {
case '{':
indentInc();
break;
case '}':
indentDec();
break;
case '(':
indentInc();
m_parenVec.push(m_column);
break;
case '}':
indentDec();
break;
case ')':
if (!m_parenVec.empty()) m_parenVec.pop();
indentDec();
break;
case '<':
if (m_lang==LA_XML) {
if (cp[1] == '/') {} // Zero as the > will result in net decrease by one
else if (cp[1] == '!' || cp[1] == '?') { indentInc(); } // net same indent
else { indentInc(); indentInc(); } // net increase by one
}
break;
case '>':
if (m_lang==LA_XML) {
indentDec();
if (cp>strg && cp[-1]=='/') indentDec(); // < ..... /> stays same level
}
break;
case 'b':
if (wordstart && m_verilog && tokenStart(cp,"begin")) {
if (wordstart && m_lang==LA_VERILOG && tokenStart(cp,"begin")) {
indentInc();
}
wordstart = false;
break;
case 'c':
if (wordstart && m_verilog && (tokenStart(cp,"case")
|| tokenStart(cp,"casex")
|| tokenStart(cp,"casez"))) {
if (wordstart && m_lang==LA_VERILOG
&& (tokenStart(cp,"case")
|| tokenStart(cp,"casex")
|| tokenStart(cp,"casez"))) {
indentInc();
}
wordstart = false;
break;
case 'e':
if (wordstart && m_verilog && tokenEnd(cp)) {
if (wordstart && m_lang==LA_VERILOG && tokenEnd(cp)) {
indentDec();
}
wordstart = false;
break;
case 'm':
if (wordstart && m_verilog && tokenStart(cp,"module")) {
if (wordstart && m_lang==LA_VERILOG && tokenStart(cp,"module")) {
indentInc();
}
wordstart = false;
@@ -801,8 +819,8 @@ void V3OutFormatter::printf (const char *fmt...) {
//######################################################################
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
V3OutFile::V3OutFile(const string& filename)
: V3OutFormatter(filename, false) {
V3OutFile::V3OutFile(const string& filename, V3OutFormatter::Language lang)
: V3OutFormatter(filename, lang) {
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
v3fatal("Cannot write "<<filename);
}

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