Compare commits

...
300 Commits
Author SHA1 Message Date
Wilson Snyder 793c974480 Version bump 2015-04-05 10:56:20 -04:00
Wilson Snyder 78a321925f Add Parser useProtected argument to aid runtime, Verilog-Perl bug899. 2015-04-05 10:54:56 -04:00
Wilson Snyder 643572595e Fix compile warning, msg1613. 2015-03-16 10:08:59 -04:00
Wilson Snyder fb4d462325 Rename readme for github. Commentary. 2015-03-14 13:45:00 -04:00
Wilson Snyder c0df07c86f Commentary: Update contributor list 2015-03-13 07:38:17 -04:00
Wilson Snyder e918d945f2 Fix order of C style arrays. 2015-03-13 07:06:06 -04:00
Wilson Snyder 0ee5743853 Add --dump-treei-<srcfile>, bug894. 2015-03-12 19:48:04 -04:00
Wilson Snyder 486d69da5f Add --clk and related optimizations, msg1533. 2015-03-12 19:20:46 -04:00
Wilson Snyder 005b4b7609 Updated - add VerilatedVcdFile to allow real-time waveforms, bug890. 2015-03-05 20:21:48 -05:00
Wilson Snyder a0fd065dcf Add VerilatedVcdFile to allow real-time waveforms, bug890. 2015-03-05 08:54:57 -05:00
Wilson Snyder 751384cb5c Fix compile error on MinGW, bug887. 2015-02-26 20:40:45 -05:00
Wilson Snyder 6ac672b4a3 Fix SystemC arrayed bit vectors, bug886. 2015-02-25 21:09:55 -05:00
Wilson Snyder a89502be9f Fix comma-separated instantiations with parameters, bug884. 2015-02-22 11:41:10 -05:00
Wilson Snyder 04e7b3bd4d devel release 2015-02-12 20:39:20 -05:00
Wilson Snyder 9ebb37b6a5 Version bump 2015-02-12 20:37:44 -05:00
Wilson Snyder 052a7e3deb Fix sign extension of pattern members, bug882. 2015-02-12 07:47:45 -05:00
Wilson Snyder 108c0f6bb8 Fix configure selecting switches that give warnings. 2015-02-11 21:24:01 -05:00
Wilson Snyder 6ed89b6ca5 New test for bug882. 2015-02-11 19:46:19 -05:00
Wilson Snyder 27ccaffb37 Fix mis-optimizing gate assignments in unopt blocks, bug881. 2015-02-11 19:36:34 -05:00
Wilson Snyder a001babad2 Fix executable bit on driver.pl from recent change. 2015-02-11 18:14:08 -05:00
Wilson Snyder 32a76c5255 Fix clang warnings. 2015-02-10 22:38:05 -05:00
Wilson Snyder 099f797975 Fix slice connections of arrays to ports, bug880. 2015-02-10 20:24:21 -05:00
Wilson Snyder b7df3e24b4 Tests: Support -ms for modelsim testing, bug878 2015-02-10 20:16:03 -05:00
Wilson Snyder 8323092a0c Fix cppcheck warnings. No functional change. 2015-02-09 21:05:27 -05:00
Wilson Snyder e5af46d3fb Add warning on slice selection out of bounds, bug875. 2015-01-25 16:32:46 -05:00
Wilson Snyder a6743588b6 Fix UNOPTFLAT change detect on multidim arrays, bug872. 2015-01-21 20:43:21 -05:00
Wilson Snyder 90cbcd2dfd Fix non-ANSI modport instantiations, bug868. 2015-01-17 15:35:45 -05:00
Wilson Snyder a36b7afba5 Fix VM_PARALLEL_BUILDS broke in 3.868, bug870. 2015-01-17 13:31:27 -05:00
Wilson Snyder 4c91ade61d Copyright year update 2015-01-07 18:25:53 -05:00
Wilson Snyder f2a17b9b70 Fix $sccanf from string, bug866. 2014-12-24 21:50:38 -05:00
Wilson Snyder b71b9ccb57 Fix member select error broke in 3.868, bug867. 2014-12-24 19:27:46 -05:00
Wilson Snyder 8b0af19351 Support cast operator with expression size, bug865. 2014-12-23 22:11:31 -05:00
Wilson Snyder 9f7c473376 Suppress COMBDLY when inside always_latch, bug854. 2014-12-23 21:42:33 -05:00
Wilson Snyder 0206767478 devel release 2014-12-20 16:49:42 -05:00
Wilson Snyder 1a3378e0f5 Add --stats-vars, bug851. 2014-12-20 08:28:31 -05:00
Wilson Snyder 5c3eee34a1 Fix underscores in real literals, bug863. 2014-12-19 18:14:32 -05:00
Wilson Snyder 2b5017e610 Fix tracing SystemC signals with structures, bug858. Remove SC tracing of wrapper. 2014-12-10 22:33:28 -05:00
Wilson Snyder e755c7fdcc Internals: Rename to avoid off-by-one 2014-11-29 08:56:07 -05:00
Wilson Snyder 8d463b33cd Fix enum name off-by-one, bug854. 2014-11-29 08:47:03 -05:00
Wilson Snyder 7d9b21a874 Commentary 2014-11-28 21:37:47 -05:00
Wilson Snyder a118921b21 Fix bare generates in interfaces, bug789. 2014-11-28 21:32:57 -05:00
Wilson Snyder a1aefd2330 Tests: Check for bug509. 2014-11-28 20:54:55 -05:00
Wilson Snyder 8b511379ac Tests: Disabled test for static vars 2014-11-28 20:44:07 -05:00
Wilson Snyder c1593f856d Support enum.first/name and similar methods, bug848. 2014-11-28 20:34:23 -05:00
Wilson Snyder 93f1d7643d Fix duplicate Vdimtables and rename 2014-11-28 20:25:58 -05:00
Wilson Snyder ce4dfb4296 Fix misc string handling issues. 2014-11-28 20:24:42 -05:00
Wilson Snyder 2e5f5010f7 Internals: Make V3Width dimensionValue more generic. No functional change. 2014-11-28 15:51:35 -05:00
Wilson Snyder 7c588c2e30 Tests: Rename test. 2014-11-28 15:11:03 -05:00
Wilson Snyder 43be4cf2b5 Add 'string' printing and comparisons, bug746, bug747, etc. 2014-11-28 15:01:50 -05:00
Wilson Snyder 8b457b9b66 Internal: Rename string functions. No functional change. 2014-11-28 13:50:37 -05:00
Wilson Snyder 25efee2e62 Fix loss of data types in V3Premit. From strings branch. 2014-11-28 10:43:05 -05:00
Wilson Snyder 546c91a940 Fix runtime error with autoflush. 2014-11-28 07:56:21 -05:00
Wilson Snyder 85ebc5f7bd Fix called with narrow output strings 2014-11-27 12:32:41 -05:00
Wilson Snyder e002b0e25f Fix new inlining to be less aggressive 2014-11-27 12:04:16 -05:00
Wilson Snyder 4944383769 Fix to install verilator_coverage manpage. 2014-11-27 11:44:06 -05:00
Wilson Snyder 68c6f0ff07 Inline C functions that are used only once, msg1525. 2014-11-27 10:52:38 -05:00
Wilson Snyder 5078152292 Tests: Fix sigstop on parallel tests 2014-11-27 10:48:27 -05:00
Wilson Snyder 9837b40330 Remove SystemPerl tests 2014-11-27 08:30:54 -05:00
Jeremy Bennett cb645c9a74 Add missing header.
Signed-off-by: Wilson Snyder <[email protected]>
2014-11-26 16:46:16 -05:00
Wilson Snyder 87573a9fef Part of earlier commit - no SystemPerl now for coverage. 2014-11-24 18:37:55 -05:00
Wilson Snyder 7c486e27ba Tests: Remove unneeded SystemPerl dependencies. 2014-11-24 07:53:33 -05:00
Wilson Snyder 4a3bdc340d Tests: Remove unneeded SystemPerl dependencies. 2014-11-23 22:18:07 -05:00
Wilson Snyder 903ee0622d Remove test_vcs directory. 2014-11-23 22:04:09 -05:00
Wilson Snyder d33ad7600b Commentary. Cleanup stale SystemPerl references. 2014-11-23 22:00:00 -05:00
Wilson Snyder 9ec35a2348 New verilator_coverage and infrastructure to replace SystemPerl's vcoverage. 2014-11-23 21:06:10 -05:00
Wilson Snyder 6da13c6486 Internals: Split V3Error into V3FileLine. No functional change. 2014-11-22 11:48:39 -05:00
Wilson Snyder 87a47a5ca0 Remove PSL support 2014-11-22 10:14:14 -05:00
Wilson Snyder c682f1c16a Commentary and internal cleanups. 2014-11-22 09:04:14 -05:00
Wilson Snyder 591075a8ed Fix sc_main test to make trace data. 2014-11-18 19:43:44 -05:00
Wilson Snyder 41701673a0 devel release 2014-11-15 08:43:27 -05:00
Wilson Snyder 55f0d4ddd8 Version bump 2014-11-15 08:38:44 -05:00
Wilson Snyder 6d66fcaa57 Fix +define+A+B to define A and B to match other simulators, bug847. 2014-11-13 19:05:07 -05:00
Wilson Snyder 26e79ca889 Fix quoted comment slashes in defines, bug845. 2014-11-12 16:37:51 -05:00
Wilson Snyder 62eb247c1e Optimize SUB/ADD together. 2014-11-09 18:33:54 -05:00
Wilson Snyder c5fd583b2c Fix select when partially out-of-bound, bug823. 2014-11-09 18:29:52 -05:00
Wilson Snyder 117db3e11c Trace_off now operates on cells, bug826. 2014-11-08 14:15:10 -05:00
Wilson Snyder 3f82fd2f37 Add public enums, bug833. 2014-11-07 07:50:11 -05:00
Wilson Snyder e9c46afcf7 Fix public parameters in unused packages, bug804. 2014-11-06 17:53:01 -05:00
Wilson Snyder 3234fa15ef Fix trace overflow on huge arrays, bug834. 2014-11-05 22:22:27 -05:00
Jie Xu 7ef84df852 Add optimization of wires from arrayed cells, msg1447.
Signed-off-by: Wilson Snyder <[email protected]>
2014-11-05 21:09:35 -05:00
Jie Xu 4e2884b509 Optimize e.g. {(b<<4)[7:4], (b<<4)[3:0]}. From assignmerge tree.
Signed-off-by: Wilson Snyder <[email protected]>
2014-11-05 20:58:36 -05:00
Wilson Snyder 03100020ab Fix not tracing modules following primitives, bug837. 2014-11-04 07:49:03 -05:00
Wilson Snyder 8bfb5cc5e9 Internals: Add sameGateTree. 2014-11-02 19:52:49 -05:00
Wilson Snyder cf6d07aafa Add optimization of operators between concats, msg1447. 2014-10-22 21:44:41 -04:00
Wilson Snyder 85c3179dbd Commentary 2014-10-21 19:11:46 -04:00
Wilson Snyder bfbca34eb0 Fix cast-to-size context-determined sizing, bug828. 2014-10-17 19:01:04 -04:00
Wilson Snyder b73edc0564 Fix generate unrolling with function call, bug830. 2014-10-15 21:29:37 -04:00
Wilson Snyder 6ba90e3a50 devel release 2014-09-21 09:06:40 -04:00
Wilson Snyder e8edbad18c Version bump 2014-09-21 09:04:36 -04:00
Wilson Snyder c86fec5307 Fix string formats under deep expressions, bug820. 2014-09-21 08:52:09 -04:00
Wilson Snyder 6e476255ca Support power operator with real, bug809. 2014-09-21 08:24:44 -04:00
Wilson Snyder 27af9b6b06 Fix clang warnings, bug818. 2014-09-11 21:28:53 -04:00
Wilson Snyder f8208fa961 Print Aborting before aborting, bug819 2014-09-05 21:40:04 -04:00
Wilson Snyder 87b9cb49ad Fix / multi-argument ordering, bug816. 2014-09-04 22:25:19 -04:00
Wilson Snyder b2da0772e6 Commentary 2014-09-04 22:15:11 -04:00
Wilson Snyder 4f73e0850e Improve verilator_profcfunc time attributions. 2014-08-28 22:10:39 -04:00
Wilson Snyder b6a39db627 Fix optional parameter keyword in module #(), bug810. 2014-08-27 07:57:20 -04:00
Wilson Snyder 3a83b06572 Fix over-shift structure optimization error, bug803. 2014-07-28 07:31:01 -04:00
Wilson Snyder fe5bf01b25 Fix dpiGetContext in dotted scopes, bug740. 2014-07-21 20:55:52 -04:00
Wilson Snyder 5559ec903b Fix error when tracing public parameters, bug722. 2014-07-21 20:44:33 -04:00
Wilson Snyder 18750028b2 Fix mis-optimization of bit-swap in wide signal, bug800. 2014-07-04 09:13:59 -04:00
Wilson Snyder 6b88648c67 Commentary, bug799 2014-07-02 21:04:51 -04:00
Wilson Snyder 58ee803cb4 Fix test GCC warning, bug794. 2014-06-26 21:45:14 -04:00
Wilson Snyder 894ff73c7d Internals: Fix clang warning, bug791. 2014-06-19 18:02:42 -04:00
Wilson Snyder 8031f0ed7f Fix duplicate anonymous structures in , bug788. 2014-06-15 11:18:47 -04:00
Wilson Snyder 3a56b5da47 devel release 2014-06-10 20:43:10 -04:00
Wilson Snyder fedcb6d26a Version bump 2014-06-10 20:39:51 -04:00
Wilson Snyder eed3c5e543 Tests: Add t_tri_array and enable t_sv_cpu. 2014-06-10 20:02:18 -04:00
Wilson Snyder e26ab67e25 Report tristate errors closer to code which created them. 2014-06-10 19:58:51 -04:00
Wilson Snyder e77b7427b4 Fix shift corner-case, bug 774. 2014-06-10 19:13:55 -04:00
Wilson Snyder 475e4207cc Fix late constant division by zero giving X error, bug775. 2014-06-09 22:27:04 -04:00
Wilson Snyder 71b2eed32c Fix false name conflict on cells in generate blocks, bug749. 2014-06-09 22:00:45 -04:00
Wilson Snyder 6cf50e6579 Fix string corruption, bug780. 2014-06-08 21:36:18 -04:00
Wilson Snyder 69468708e2 Fix DETECTARRAY error on packed arrays, bug770. 2014-06-07 09:53:40 -04:00
Wilson Snyder 5da5678e64 Fix pattern assignment to conditionals, bug769. 2014-06-06 21:52:16 -04:00
Wilson Snyder a428e7f618 Fix pattern assignment to arrayed basic type, bug769. 2014-06-06 21:14:44 -04:00
Wilson Snyder 0eb5a0a539 Add -P to suppress `line and blanks with preprocessing, bug781. 2014-06-06 20:22:20 -04:00
Wilson Snyder a1c1ff9981 Fix seg-fault with variable of parameterized interface, bug692. 2014-05-28 07:33:40 -04:00
Wilson Snyder 2029ade18c Change SYMRSVDWORD to print as warning rather than error. 2014-05-28 07:24:02 -04:00
Wilson Snyder 5f8f474c0c Fix shift with XOR mis-optimization, bug776. 2014-05-26 18:16:52 -04:00
Wilson Snyder f705f9b275 Fix C compiler interpreting signing, bug773. 2014-05-24 08:00:01 -04:00
Wilson Snyder 91e706ec1f Fix X shift issue, bug772. 2014-05-24 07:05:23 -04:00
Wilson Snyder dcf351f847 Copyright 2014-05-20 06:12:08 -04:00
Wilson Snyder 06744b664a Fix huge shifts to zero with -Wno-WIDTH, bug768. 2014-05-16 07:09:43 -04:00
Wilson Snyder d3049d9c89 Fix huge shifts to zero with -Wno-WIDTH, bug766. 2014-05-15 21:49:43 -04:00
Wilson Snyder 1f2abb9c0f Fix gate primitives with arrays and non-arrayed pins. 2014-05-15 20:57:09 -04:00
Wilson Snyder 9f0d7e50a5 Using command line -Wno-{WARNING} now overrides file-local lint_on. 2014-05-15 20:54:45 -04:00
Wilson Snyder 5f262a8f11 Fix ENDLABEL warnings on escaped identifiers. 2014-05-15 20:52:22 -04:00
Wilson Snyder f62bc6a2e5 Support SV 2012 package import before port list. 2014-05-15 20:50:42 -04:00
Wilson Snyder d7e4bc1379 Fix huge shifts to zero with -Wno-WIDTH, bug765. 2014-05-13 08:10:59 -04:00
Wilson Snyder cd2d6575c6 devel release 2014-05-11 16:58:01 -04:00
Wilson Snyder b46f656d17 Version bump. 2014-05-11 16:51:56 -04:00
Wilson Snyder 58fd602bbd Fix flex warning 2014-05-11 09:36:39 -04:00
Wilson Snyder 9cc95704cd Tests: Add t_inst_dff parameter width change test. 2014-05-11 09:18:04 -04:00
Wilson Snyder 5f5a3dbb0a Tests: More width testing. 2014-05-10 21:51:21 -04:00
Wilson Snyder f8f53df4ec Fix X/Z extension with WIDTH param mismatch, bug764. 2014-05-10 21:38:36 -04:00
Wilson Snyder 56b85cc63c Suppress WIDTH warnings on 'x = 1<<a' 2014-05-10 17:19:57 -04:00
Wilson Snyder 90aca97e66 Internals: Flip sense of warnOn. No functional change intended. 2014-05-10 17:12:04 -04:00
Wilson Snyder 6ce2a52c5f Fix shift-right optmiization, bug763. 2014-05-10 16:38:20 -04:00
Wilson Snyder 1f56312132 Fix -Wno-UNOPTFLAT change detection with 64-bits, bug762. 2014-05-10 12:40:35 -04:00
Wilson Snyder 3aa290cddb Add error on power > 64-bits, bug761. 2014-05-10 08:24:51 -04:00
Wilson Snyder 1d1eb4fedb Testcase for bug756. 2014-05-10 08:20:10 -04:00
Wilson Snyder 266ff41386 For --cdc, don't show data types in dump file. 2014-05-10 07:50:04 -04:00
Wilson Snyder 02331e5536 Fix begin_keywords 1800+VAMS, msg1211. 2014-05-08 07:15:44 -04:00
Wilson Snyder 621c51589a Fix shift by x, bug760. 2014-05-04 08:50:44 -04:00
Wilson Snyder 4a58e859a4 Fix concats with no argments mis-sign extending, bug759. 2014-05-03 20:20:15 -04:00
Wilson Snyder 48d393d8f5 Tests: test_verilated must match signs on == sides. 2014-05-03 20:11:38 -04:00
Wilson Snyder 321552d998 Fix wide modulus uninit var 2014-05-03 20:09:45 -04:00
Wilson Snyder a985a1f9f5 Fix >>> sign extension based on expression, bug754. 2014-05-03 09:25:12 -04:00
Wilson Snyder d532a36739 Fix change detection error on unions, bug758. 2014-05-02 08:14:23 -04:00
Wilson Snyder b631b5927b Fix shift width extension, broke recent commit, bug754. 2014-04-30 22:47:01 -04:00
Wilson Snyder adb39ceb98 Internals: cppcheck clean and add cppcheck_filtered 2014-04-29 22:59:38 -04:00
Wilson Snyder 84b91b19ca Commentary 2014-04-29 22:02:48 -04:00
Wilson Snyder aaea68d3d6 Rewrite V3Width for better spec adherence when -Wno-WIDTH. 2014-04-29 22:01:50 -04:00
Wilson Snyder 2accba2e71 Update WIDTH warning message formats to match future commit. 2014-04-29 21:11:57 -04:00
Wilson Snyder 8f4f4eb5ae Fix coredump on undriven vector[-1]. 2014-04-29 21:09:44 -04:00
Wilson Snyder c5aabb3c6e Tests: Move most old test_v tests into test_regress. 2014-04-29 19:47:26 -04:00
Wilson Snyder 60c2d136e1 Internals: V3Width renames. Fix CASEEQ signing. 2014-04-26 16:52:09 -04:00
Wilson Snyder cae6ec16ba Commentary 2014-04-26 13:59:50 -04:00
Wilson Snyder 30601c77d4 tests: Add driver --unsupported 2014-04-22 20:50:22 -04:00
Wilson Snyder b0f4cf3c9c Support {} in always sensitivity lists, bug745. 2014-04-21 19:39:28 -04:00
Wilson Snyder c41dfcf6ad Fix assertions broken from bug725, bug743. 2014-04-16 22:33:25 -04:00
Wilson Snyder 2e10555f03 Fix tracing of packed arrays without --trace-structs, bug742. 2014-04-15 20:20:45 -04:00
Wilson Snyder 6b2ee0fcf3 Fix reporting struct members as reserved words, bug741. 2014-04-15 19:35:44 -04:00
Wilson Snyder 0dbdbffba7 Fix double I/O port warnings. 2014-04-15 18:50:04 -04:00
Wilson Snyder 9c5dd8d767 Fix RHEL5.6 compile warnings. 2014-04-15 18:18:36 -04:00
Glen Gibb fff0ebb5f3 Internals: Add AstReplicate dtype init.
Signed-off-by: Wilson Snyder <[email protected]>
2014-04-10 17:54:52 -04:00
Glen Gibb d34275150c Support streaming operators, bug649.
Signed-off-by: Wilson Snyder <[email protected]>
2014-04-09 20:29:35 -04:00
Wilson Snyder d04eb977c2 Fix mis-extending red xor/xand operators. 2014-04-09 07:58:46 -04:00
Wilson Snyder fb4928b2f5 Fix power calculation; setAllOnes should not set hidden state bits in V3Number. 2014-04-08 20:28:16 -04:00
Wilson Snyder 5c39420d91 Re-fix bug729 due to bug733; other internal sign extension cleanups too. 2014-04-07 21:34:00 -04:00
Wilson Snyder 14fcfd8a40 Fix signed extension problem with -Wno-WIDTH, bug729. 2014-04-05 15:52:05 -04:00
Wilson Snyder ff19dd94f9 Fix power operator calculation, bug730. 2014-04-05 15:44:49 -04:00
Wilson Snyder b6913ff9b3 With high c-splits, even split blank functions. 2014-04-05 12:41:00 -04:00
Wilson Snyder 4573fd3069 Tests: Fix unsupported items. 2014-04-03 22:03:03 -04:00
Wilson Snyder 6cf6d9f7e1 Fix modport function import not-found error. 2014-04-03 21:53:39 -04:00
Wilson Snyder 28e35a64ea Support parameter arrays, bug683. 2014-04-01 23:16:16 -04:00
Wilson Snyder 091818483a Order initial statements based on variables used. Merge from bug683 branch. 2014-04-01 22:01:25 -04:00
Wilson Snyder 3b43556c41 Internals: Remove dead NEW_ORDERING code. 2014-03-31 20:29:35 -04:00
Wilson Snyder ed39c66715 Internals: Make const iterator to fix missed-edits on dump. Merge from bug683 branch. 2014-03-31 20:24:05 -04:00
Wilson Snyder 446b0e4e5e Support '{} assignment pattern on arrays, bug355. 2014-03-30 20:41:20 -04:00
Wilson Snyder 6e3e8318d0 Internals: Add dtype to InitArray; misc Slice cleanups. From bug355 branch. 2014-03-30 20:28:51 -04:00
Wilson Snyder 17b8b660f0 Internals: Fix assignment pattern replication. From bug355 branch. 2014-03-30 10:20:12 -04:00
Wilson Snyder 40bceea68a Fix missing coverage line on else-if, bug727. 2014-03-29 11:04:13 -04:00
Holger Waechtler b655c17c09 Fix Mac OS-X test issues.
Signed-off-by: Wilson Snyder <[email protected]>
2014-03-29 08:30:08 -04:00
Wilson Snyder a3813f94fc Add PINCONNECTEMPTY warning. 2014-03-27 21:36:52 -04:00
Wilson Snyder c70540a825 Fix Mac OS-X include compile issue. 2014-03-27 21:07:59 -04:00
Holger Waechtler 9caffe330b Fix Mac OS-X test issues.
Signed-off-by: Wilson Snyder <[email protected]>
2014-03-24 20:19:43 -04:00
Wilson Snyder 8d8c5da812 Add assertions on 'unique if', bug725. 2014-03-16 21:38:29 -04:00
Wilson Snyder 55bb766c15 Fix escaped newline in assertion failures. 2014-03-16 20:57:15 -04:00
Wilson Snyder c18df68ead Fix C++-2011 warnings. 2014-03-15 14:50:03 -04:00
Wilson Snyder 3996e94c39 Fix Bison 4.0 warnings. From Verilog-Perl. 2014-03-15 14:23:19 -04:00
Wilson Snyder 1bdf017f9e PSL is no longer supported, please use System Verilog assertions. 2014-03-14 21:14:24 -04:00
Wilson Snyder 93790c1dc6 Fix tracing of package variables and real arrays. 2014-03-14 20:36:47 -04:00
Wilson Snyder ba8c11b25d Fix scope creating extra vars for package variables. See next trace commit for test. 2014-03-14 20:24:21 -04:00
Wilson Snyder ca57edfa0b Fix assignment temporaries not using real types. 2014-03-14 20:22:06 -04:00
Wilson Snyder ccb6545c32 tests: Fix bogus set of output. 2014-03-14 20:19:56 -04:00
Wilson Snyder d146dbc9d7 Commentary. 2014-03-14 20:13:41 -04:00
Glen Gibb b4eaaccc88 Documentation fixes, bug723.
Signed-off-by: Wilson Snyder <[email protected]>
2014-03-14 07:17:03 -04:00
Wilson Snyder c9ed9e74f2 Add --no-trace-params. 2014-03-13 20:08:43 -04:00
Wilson Snyder 587c7c70f5 devel release 2014-03-11 19:52:28 -04:00
Wilson Snyder 749ff021b6 Version bump 2014-03-11 19:48:57 -04:00
Wilson Snyder 85c5765c00 Fix parsing "#0 'b0", bug256. 2014-03-11 19:07:58 -04:00
Wilson Snyder 9e76078939 Fix signed shift right optimization, bug715. 2014-03-09 21:28:28 -04:00
Wilson Snyder 334e0e1ca6 Internals: Debug message. 2014-03-09 21:22:01 -04:00
Wilson Snyder dce4519995 Optimizer: Put constants on left side of compares to match other AstBiOps and extend optimizations. No runtime result change intended. 2014-03-09 17:13:37 -04:00
Wilson Snyder 45bbae80e7 Add parameters into trace files, bug706. 2014-03-08 15:36:04 -05:00
Wilson Snyder d37709a922 test driver: Update VCDs when given HARNESS_UPDATE_GOLDEN 2014-03-08 15:34:42 -05:00
Wilson Snyder 2560ae9bc1 Fix slice extraction from packed array, bug717. 2014-03-08 14:55:05 -05:00
Wilson Snyder 2bdd3ca353 Internals: Refactoring V3WidthSel. No functional change. 2014-03-08 14:41:11 -05:00
Wilson Snyder 8a8aab1aae Internals: Shrink AstSelPlus code. No functional change. 2014-03-08 14:17:39 -05:00
Wilson Snyder 85d790ff79 Fix inside statement EQWILD error, bug718. 2014-03-08 13:33:44 -05:00
Wilson Snyder 68afc96a9f Fix internal error on "input x =" syntax error, bug716. 2014-03-08 12:26:34 -05:00
Wilson Snyder 94efaa7675 Commentary 2014-02-14 08:11:49 -05:00
Wilson Snyder 180af74a50 Fix missing VL_SHIFTRS_IQI with WIDTH warning, bug514. 2014-02-13 18:13:30 -05:00
Wilson Snyder 88af0d3509 Fix --skip-identical mis-detecting on OS-X, bug707. 2014-02-09 16:32:49 -05:00
Wilson Snyder 97633f7bed Fix array bound checks on real variables. 2014-02-09 09:19:05 -05:00
Wilson Snyder 053e016388 Add unsupported test, bug711. 2014-01-25 09:49:56 -05:00
Wilson Snyder 2d61e0270e Support case inside, bug708. 2014-01-20 21:59:53 -05:00
Wilson Snyder 3a23afb0bc devel release 2014-01-20 21:55:27 -05:00
Wilson Snyder 470f12ff46 Version bump 2014-01-18 13:16:08 -05:00
Wilson Snyder 4422de0c6c Copyright year update. 2014-01-06 19:28:57 -05:00
Wilson Snyder 8a708f52f7 Tests: Merge from pattern branch. 2013-12-21 08:29:04 -05:00
Wilson Snyder bcefc17631 Support modport import, bug696. 2013-12-21 06:51:15 -05:00
Wilson Snyder daf19e241e Fix struct trace coredump from recent commit. 2013-12-21 06:46:48 -05:00
Wilson Snyder b5f5b1fdf9 Fix wire declarations with size and not range, bug466. 2013-12-14 19:50:55 -05:00
Wilson Snyder 801b718953 Add --trace-structs to show struct names, bug673. 2013-12-14 19:13:31 -05:00
Wilson Snyder f571658aa4 Commentary 2013-12-14 18:07:55 -05:00
Wilson Snyder 5d233b8c09 Fix parameter pin vs. normal pin error, bug704. 2013-12-14 18:04:10 -05:00
Wilson Snyder 00724597f4 Fix tracing of packed structs, bug705. 2013-12-14 16:51:08 -05:00
Wilson Snyder c659940ea8 Internals: Use VNumRange for AstTraceDecl 2013-12-14 12:17:31 -05:00
Wilson Snyder 23539eb55c Fix some delayed assignments of typedefed unpacked arrays. See following trace test. 2013-12-14 10:33:08 -05:00
Wilson Snyder e69bf418de Fix --lint-only with MinGW, msg1283. 2013-11-29 08:28:48 -05:00
Wilson Snyder 0e1fcd38bb Version bump 2013-11-26 19:52:19 -05:00
Wilson Snyder e74186565d Add --compiler clang to work around compiler bug, bug694. 2013-11-26 18:46:55 -05:00
Wilson Snyder 7e54281e26 Fix array assignment from const var, bug693. 2013-10-31 22:39:26 -04:00
Wilson Snyder 15f512bdee Debug: With --debug, run check tree at all steps even if no --dump-more 2013-10-30 23:25:54 -04:00
Wilson Snyder ecfe0283e2 Fix crash with coverage of structures, bug691. 2013-10-29 20:15:01 -04:00
Wilson Snyder 3b874f759c Fix of last commit, bug689. 2013-10-28 21:57:52 -04:00
Wilson Snyder 9c9b4ed4e0 Fix vpi_remove_cb inside callback, bug689. 2013-10-28 21:00:40 -04:00
Wilson Snyder 4f6d80c602 Add UNPACKED warning to convert unpacked structs. 2013-10-28 20:41:05 -04:00
Wilson Snyder b50542531d Fix enum value extension of '1. 2013-10-28 20:24:31 -04:00
Wilson Snyder 8ab28d1d12 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2013-10-28 11:15:33 -04:00
Wilson Snyder 9567da22f8 Compiler warning fix. 2013-10-28 11:14:13 -04:00
Wilson Snyder 36814b7681 Support vpi_get_time, bug688. 2013-10-22 22:02:53 -04:00
Wilson Snyder 82235e6c6f Fix vpi_get of vpiSuppressVal, bug687. 2013-10-22 22:01:19 -04:00
Wilson Snyder a8310f35f2 Fix evaluation of chained parameter functions, bug684. 2013-10-18 07:06:32 -04:00
Rich Porter 85989af031 Fix vpi_get of vpiSize, bug680.
Signed-off-by: Wilson Snyder <[email protected]>
2013-10-13 20:05:57 -04:00
Rich Porter cf9ffd16dd tests: For icarus, exit on stop. Merge from RPORTER/vpi-vpiSize-680.
Signed-off-by: Wilson Snyder <[email protected]>
2013-10-11 21:34:48 -04:00
Wilson Snyder 0602537cce Fix t/t_select_index2 test. 2013-10-11 21:29:54 -04:00
Wilson Snyder 24e32420b7 Fix multiple VPI variable callbacks, bug679. 2013-10-03 07:24:50 -04:00
Wilson Snyder 39c494260b devel release 2013-09-30 16:56:52 -04:00
Wilson Snyder 761b9c9290 Version bump 2013-09-30 16:53:45 -04:00
Wilson Snyder 27686d8c2f Add --no-order-clock-delay to work around bug613. 2013-09-30 16:52:43 -04:00
Wilson Snyder d2b007005d devel release 2013-09-29 20:56:19 -04:00
Wilson Snyder f1ef30a5bb Version bump 2013-09-29 20:52:29 -04:00
Wilson Snyder f1d9437c55 Report SELRANGE warning for non-generate if, bug675. 2013-09-10 07:16:13 -04:00
Wilson Snyder bcba5075e8 Fix ordering of , msg1229. 2013-09-07 16:43:43 -04:00
Wilson Snyder d6e8b0263c Fix crash on 32-bit Ubuntu, bug670. 2013-09-03 21:40:43 -04:00
Wilson Snyder 9aba617bad Fix --output-split-cfunc to count internal functions. 2013-09-03 19:35:32 -04:00
Wilson Snyder c24f7b1391 Support named function and task arguments. 2013-08-17 20:34:49 -04:00
Wilson Snyder d4e27b635f devel release 2013-08-15 08:43:37 -04:00
Wilson Snyder c996d2870c Version bump 2013-08-15 08:39:46 -04:00
Wilson Snyder bbd59f8a22 Support passing strings to DPI imports. 2013-08-14 21:37:13 -04:00
Wilson Snyder d3d359e757 Fix clang warnings, bug668. 2013-08-08 19:39:39 -04:00
Wilson Snyder ae763ea93d Internals: Debugs for bug666. 2013-08-08 07:05:21 -04:00
Wilson Snyder 236b9e9761 Fix parameter real conversion from integer. 2013-07-29 22:03:47 -04:00
Wilson Snyder e42c9dfd84 Grammar 2013-07-29 21:53:43 -04:00
Wilson Snyder bebf5b291b Fix final duplicate declarations when non-inlined, bug661. 2013-07-29 21:47:23 -04:00
Wilson Snyder 1e3dcd203d Fix clang warning, bug668. 2013-07-29 10:37:58 -04:00
Wilson Snyder cc7da63dec Tests: Add t_mod_recurse. 2013-06-23 22:39:08 -04:00
Wilson Snyder 1baa2a2558 Fix interface ports with comma lists, msg1058. 2013-06-13 19:38:18 -04:00
Wilson Snyder e63ff77b15 VPI internals: Rename VerilatedRange left/right to match IEEE + VNumRange. No functional change. 2013-06-13 08:05:38 -04:00
Wilson Snyder 6cf9468477 Fix vpi_iterate on memory words, bug655. 2013-06-13 07:58:52 -04:00
Jeremy Bennett b277bc8750 Fix ordering of clock enables with delayed assigns, bug613.
Signed-off-by: Wilson Snyder <[email protected]>
2013-06-05 23:35:47 -04:00
Wilson Snyder ba9da64207 Fix t_trace_cat test, bug654. 2013-06-03 19:08:15 -04:00
Wilson Snyder 9cb9f9c80b devel release 2013-06-02 14:52:19 -04:00
Wilson Snyder 7a65df7636 Version bump 2013-06-02 14:47:36 -04:00
Wilson Snyder eab46d547d Version bump. 2013-06-02 14:38:53 -04:00
Wilson Snyder 3dd552c4a2 Duplicate clock gate optimization on by default, use -Od to disable 2013-05-27 22:39:59 -04:00
Wilson Snyder 23bb045a72 Support interfaces and modports, bug102. 2013-05-27 21:39:19 -04:00
Wilson Snyder 7c834ad118 Internals: Misc cleanups from interface branch. No functional change. 2013-05-27 20:56:20 -04:00
Wilson Snyder 8e2617ab8d Internals: V3Inline support for future hard-no-inline. No functional change. 2013-05-26 11:17:42 -04:00
Wilson Snyder 24fcae4f49 Internals: When broken link fatal, say which rule violated 2013-05-25 17:05:22 -04:00
Wilson Snyder ce18674d88 Internals: (see last) also dump on first non-fatal 2013-05-25 13:31:17 -04:00
Wilson Snyder 6b8d9b5c36 Internals: If registered, dump symtable on any error 2013-05-25 12:15:38 -04:00
Wilson Snyder 81bf95763c Internals: Refactor V3Inline to simplify if(m_cellp) out. No functional change. 2013-05-25 10:42:44 -04:00
Wilson Snyder 2d64077fd0 Internals: Prep to allow future move of wrapping. No functional change. 2013-05-25 10:15:10 -04:00
Wilson Snyder 38faebcf20 Fix packed array select internal error, bug652. 2013-05-24 21:32:54 -04:00
Wilson Snyder 48d177a9d0 Fix packed array select internal error, bug652. 2013-05-24 21:14:42 -04:00
Wilson Snyder 3b3a7f7354 Commentary 2013-05-24 19:09:41 -04:00
Wilson Snyder 99cd2818a1 Tests: Allow driver to find 't' signals when not first in file. 2013-05-23 22:00:55 -04:00
Wilson Snyder 5765e099a6 Debug: More digits for debug file sorting. 2013-05-23 20:50:48 -04:00
Wilson Snyder 175d59ecba Fix GCC version runtime changes, bug651. 2013-05-23 20:19:51 -04:00
Wilson Snyder 3bd3d01968 Tests: Move driver.pl tee into perl to avoid process issue, bug650. 2013-05-23 20:08:39 -04:00
Wilson Snyder 85e2a6bb45 Tests 2013-05-21 22:38:35 -04:00
Wilson Snyder 84efd239a5 Fix arrayed input compile error, bug645. Try 2. 2013-05-18 20:17:17 -04:00
Wilson Snyder 6a69813326 Internals: Renames for interfaces. No functional change. 2013-05-18 19:45:52 -04:00
Wilson Snyder 2c9dcc3913 Fix arrayed input compile error, bug645. 2013-05-15 22:00:28 -04:00
Wilson Snyder 20ea1ca018 devel release 2013-05-11 16:16:22 -04:00
647 changed files with 23584 additions and 6782 deletions
+1
View File
@@ -23,3 +23,4 @@ gdbrun*
internals.txt
verilator.txt
verilator_bin*
verilator_coverage_bin*
+323 -8
View File
@@ -3,20 +3,335 @@ 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.872 2015-04-05
*** Add VerilatedVcdFile to allow real-time waveforms, bug890. [HyungKi Jeong]
*** Add --clk and related optimizations, msg1533. [Jie Xu]
*** Fix order of C style arrays. [Duraid Madina]
**** Add --dump-treei-<srcfile>, bug894. [Jie Xu]
**** Fix comma-instantiations with parameters, bug884. [Franck Jullien]
**** Fix SystemC arrayed bit vectors, bug886. [David Poole]
**** Fix compile error on MinGW, bug887. [HyungKi Jeong]
* Verilator 3.870 2015-02-12
**** Suppress COMBDLY when inside always_latch, bug864. [Iztok Jeras]
**** Support cast operator with expression size, bug865. [Iztok Jeras]
**** Add warning on slice selection out of bounds, bug875. [Cong Van Nguyen].
**** Fix member select error broke in 3.868, bug867. [Iztok Jeras]
**** Fix $sccanf from string, bug866. [David Pierce]
**** Fix VM_PARALLEL_BUILDS broke in 3.868, bug870. [Hiroki Honda]
**** Fix non-ANSI modport instantiations, bug868. [Kevin Thompson]
**** Fix UNOPTFLAT change detect on multidim arrays, bug872. [Andrew Bardsley]
**** Fix slice connections of arrays to ports, bug880. [Varun Koyyalagunta]
**** Fix mis-optimizing gate assignments in unopt blocks, bug881. [Mike Thyer]
**** Fix sign extension of pattern members, bug882. [Iztok Jeras]
**** Fix clang compile warnings.
* Verilator 3.868 2014-12-20
** New verilator_coverage program added to replace SystemPerl's vcoverage.
** PSL support was removed, please use System Verilog assertions.
** SystemPerl mode is deprecated and now untested.
*** Support enum.first/name and similar methods, bug460, bug848.
*** Add 'string' printing and comparisons, bug746, bug747, etc.
*** Inline C functions that are used only once, msg1525. [Jie Xu]
*** Fix tracing SystemC signals with structures, bug858. [Eivind Liland]
Note that SystemC traces will no longer show the signals
in the wrapper, they can be seen one level further down.
**** Add --stats-vars, bug851. [Jeremy Bennett]
**** Fix bare generates in interfaces, bug789. [Bob Newgard]
**** Fix underscores in real literals, bug863. [Jonathon Donaldson]
* Verilator 3.866 2014-11-15
*** Fix +define+A+B to define A and B to match other simulators, bug847. [Adam Krolnik]
*** Add optimization of wires from arrayed cells, msg1447. [Jie Xu]
*** Add optimization of operators between concats, msg1447. [Jie Xu]
*** Add public enums, bug833. [Jonathon Donaldson]
*** Trace_off now operates on cells, bug826. [Lane Brooks]
**** Fix public parameters in unused packages, bug804. [Jonathon Donaldson]
**** Fix select when partially out-of-bound, bug823. [Cliffort Wolf]
**** Fix generate unrolling with function call, bug830. [Steven Slatter]
**** Fix cast-to-size context-determined sizing, bug828. [Geoff Barrett]
**** Fix not tracing modules following primitives, bug837. [Jie Xu]
**** Fix trace overflow on huge arrays, bug834. [Geoff Barrett]
**** Fix quoted comment slashes in defines, bug845. [Adam Krolnik]
* Verilator 3.864 2014-09-21
*** Support power operator with real, bug809. [Jonathon Donaldson]
**** Improve verilator_profcfunc time attributions. [Jonathon Donaldson]
**** Fix duplicate anonymous structures in $root, bug788. [Bob Newgard]
**** Fix mis-optimization of bit-swap in wide signal, bug800. [Jie Xu]
**** Fix error when tracing public parameters, bug722. [Jonathon Donaldson]
**** Fix dpiGetContext in dotted scopes, bug740. [Geoff Barrett]
**** Fix over-shift structure optimization error, bug803. [Jeff Bush]
**** Fix optional parameter keyword in module #(), bug810. [Iztok Jeras]
**** Fix $warning/$error multi-argument ordering, bug816. [Jonathon Donaldson]
**** Fix clang warnings, bug818. [Iztok Jeras]
**** Fix string formats under deep expressions, bug820. [Iztok Jeras]
* Verilator 3.862 2014-06-10
*** Using command line -Wno-{WARNING} now overrides file-local lint_on.
*** Add -P to suppress `line and blanks with preprocessing, bug781. [Derek Lockhart]
*** Support SV 2012 package import before port list.
**** Change SYMRSVDWORD to print as warning rather than error.
**** Fix seg-fault with variable of parameterized interface, bug692. [Jie Xu]
**** Fix false name conflict on cells in generate blocks, bug749. [Igor Lesik]
**** Fix pattern assignment to basic types, bug767. [Jie Xu]
**** Fix pattern assignment to conditionals, bug769. [Jie Xu]
**** Fix shift corner-cases, bug765, bug766, bug768, bug772, bug774, bug776. [Clifford Wolf]
**** Fix C compiler interpreting signing, bug773. [Clifford Wolf]
**** Fix late constant division by zero giving X error, bug775. [Clifford Wolf]
**** Fix gate primitives with arrays and non-arrayed pins.
**** Fix DETECTARRAY error on packed arrays, bug770. [Jie Xu]
**** Fix ENDLABEL warnings on escaped identifiers.
**** Fix string corruption, bug780. [Derek Lockhart]
* Verilator 3.860 2014-05-11
** PSL is no longer supported, please use System Verilog assertions.
** Support '{} assignment pattern on arrays, bug355.
** Support streaming operators, bug649. [Glen Gibb]
** Fix expression problems with -Wno-WIDTH, bug729, bug736, bug737, bug759.
Where WIDTH warnings were ignored this might result in different
warning messages and results, though it should better match the spec.
[Clifford Wolf]
*** Add --no-trace-params.
*** Add assertions on 'unique if', bug725. [Jeff Bush]
*** Add PINCONNECTEMPTY warning. [Holger Waechtler]
*** Support parameter arrays, bug683. [Jeremy Bennett]
*** Fix begin_keywords "1800+VAMS", msg1211.
**** Documentation fixes, bug723. [Glen Gibb]
**** Support {} in always sensitivity lists, bug745. [Igor Lesik]
**** Fix tracing of package variables and real arrays.
**** Fix tracing of packed arrays without --trace-structs, bug742. [Jie Xu]
**** Fix missing coverage line on else-if, bug727. [Sharad Bagri]
**** Fix modport function import not-found error.
**** Fix power operator calculation, bug730, bug735. [Clifford Wolf]
**** Fix reporting struct members as reserved words, bug741. [Chris Randall]
**** Fix change detection error on unions, bug758. [Jie Xu]
**** Fix -Wno-UNOPTFLAT change detection with 64-bits, bug762. [Clifford Wolf]
**** Fix shift-right optimization, bug763. [Clifford Wolf]
**** Fix Mac OS-X test issues. [Holger Waechtler]
**** Fix C++-2011 warnings.
* Verilator 3.856 2014-03-11
*** Support case inside, bug708. [Jan Egil Ruud]
*** Add parameters into trace files, bug706. [Alex Solomatnikov]
**** Fix parsing "#0 'b0", bug256.
**** Fix array bound checks on real variables.
**** Fix --skip-identical mis-detecting on OS-X, bug707.
**** Fix missing VL_SHIFTRS_IQI with WIDTH warning, bug714. [Fabrizio Ferrandi]
**** Fix signed shift right optimization, bug715. [Fabrizio Ferrandi]
**** Fix internal error on "input x =" syntax error, bug716. [Lane Brooks]
**** Fix slice extraction from packed array, bug717. [Jan Egil Ruud]
**** Fix inside statement EQWILD error, bug718. [Jan Egil Ruud]
* Verilator 3.855 2014-01-18
*** Support modport import, bug696. [Jeremy Bennett]
*** Add --trace-structs to show struct names, bug673. [Chris Randall]
**** Fix tracing of packed structs, bug705. [Jie Xu]
**** Fix --lint-only with MinGW, msg1283. [HyungKi Jeong]
**** Fix some delayed assignments of typedefed unpacked arrays.
**** Fix wire declarations with size and not range, bug466. [Alex Solomatnikov]
**** Fix parameter pin vs. normal pin error, bug704. [Alex Solomatnikov]
* Verilator 3.854 2013-11-26
*** Add UNPACKED warning to convert unpacked structs. [Jeremy Bennett]
*** Add --compiler clang to work around compiler bug, bug694. [Stefan Ludwig]
**** Support vpi_get of vpiSuppressVal, bug687. [Varun Koyyalagunta]
**** Support vpi_get_time, bug688. [Varun Koyyalagunta]
**** Fix evaluation of chained parameter functions, bug684. [Ted Campbell]
**** Fix enum value extension of '1.
**** Fix multiple VPI variable callbacks, bug679. [Rich Porter]
**** Fix vpi_get of vpiSize, bug680. [Rich Porter]
**** Fix vpi_remove_cb inside callback, bug689. [Varun Koyyalagunta]
**** Fix crash with coverage of structures, bug691. [Eivind Liland]
**** Fix array assignment from const var, bug693. [Jie Xu]
* Verilator 3.853 2013-09-30
**** Add --no-order-clock-delay to work around bug613. [Charlie Brej]
* Verilator 3.852 2013-09-29
*** Support named function and task arguments. [Chris Randall]
*** Report SELRANGE warning for non-generate if, bug675. [Roland Kruse]
**** Fix ordering of $fgetc, msg1229. [Frederic Requin]
**** Fix --output-split-cfunc to count internal functions. [Chris Randall]
**** Fix crash on 32-bit Ubuntu, bug670. [Mark Jackson Pulver]
* Verilator 3.851 2013-08-15
*** Fix ordering of clock enables with delayed assigns, bug613. [Jeremy Bennett]
*** Fix vpi_iterate on memory words, bug655. [Rich Porter]
**** Fix final duplicate declarations when non-inlined, bug661. [Charlie Brej]
**** Fix interface ports with comma lists, msg1058. [Ed Lander]
**** Fix parameter real conversion from integer.
**** Fix clang warnings, bug668. [Yutetsu Takatsukasa]
* Verilator 3.850 2013-06-02
** Support interfaces and modports, bug102. [Byron Bradley, Jeremy Bennett]
*** Duplicate clock gate optimization on by default, bug621.
**** Fix arrayed input compile error, bug645. [Krzysztof Jankowski]
**** Fix GCC version runtime changes, bug651. [Jeremy Bennett]
**** Fix packed array select internal error, bug652. [Krzysztof Jankowski]
* Verilator 3.847 2013-05-11
*** Add ALWCOMBORDER warning. [KC Buckenmaier]
*** Add --pins-sc-uint and --pins-sc-biguint, bug638. [Alex Hornung]
**** Support "signal[vec]++".
**** Fix simulation error when inputs and MULTIDRIVEN, bug634. [Ted Campbell]
**** Fix module resolution with __, bug631. [Jason McMullan]
**** Fix packed array non-zero right index select crash, bug642. [Krzysztof Jankowski]
**** Fix nested union crash, bug643. [Krzysztof Jankowski]
@@ -332,7 +647,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support $fopen and I/O with integer instead of `verilator_file_descriptor.
*** Support coverage in -cc and -sc output modes. [John Li]
Note this requires SystemPerl 1.338 or newer.
Note this requires SystemPerl 1.338 or newer.
**** Fix vpi_register_cb using bad s_cb_data, bug370. [by Thomas Watts]
@@ -2232,7 +2547,7 @@ of input ports exists for tracing.
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
Copyright 2001-2013 by Wilson Snyder. This program is free software; you
Copyright 2001-2015 by Wilson Snyder. This program is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1
View File
@@ -28,6 +28,7 @@ config.status$
verilator.log
verilator.tex
verilator_bin.*
verilator_coverage_bin.*
.vcsmx_rebuild$
autom4te\.cache/
nodist/
+32 -27
View File
@@ -3,13 +3,11 @@
#
# This file is part of Verilator.
#
# Author: Wilson Snyder <[email protected]>
#
# Code available from: http://www.veripool.org/verilator
#
#*****************************************************************************
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -100,10 +98,11 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
SHELL = /bin/sh
SUBDIRS = src test_verilated test_c test_sc test_sp test_regress test_vcs
SUBDIRS = src test_verilated test_c test_sc test_regress
INFOS = README README.html README.pdf internals.txt internals.html \
internals.pdf verilator.txt verilator.html verilator.1 verilator.pdf
internals.pdf verilator.txt verilator.html verilator.1 verilator.pdf \
verilator_coverage.1
# Files that can be generated, but should be up to date for a distribution.
DISTDEP = info Makefile
@@ -120,7 +119,9 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
include/.*ignore \
include/vltstd/*.[chv]* \
.*attributes */.*attributes */*/.*attributes \
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
src/.*ignore src/*.in src/*.cpp src/*.[chly] \
src/astgen src/bisonpre src/*fix src/cppcheck_filtered \
src/vlcovgen \
src/.gdbinit \
src/*.pl src/*.pod \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
@@ -139,6 +140,7 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
INST_PROJ_FILES = \
bin/verilator \
bin/verilator_coverage \
bin/verilator_includer \
bin/verilator_profcfunc \
include/verilated.mk \
@@ -148,6 +150,7 @@ INST_PROJ_FILES = \
INST_PROJ_BIN_FILES = \
verilator_bin \
verilator_bin_dbg \
verilator_coverage_bin_dbg \
DISTFILES := $(DISTFILES_INC)
@@ -164,7 +167,8 @@ all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
.PHONY:verilator_exe
.PHONY:verilator_bin
.PHONY:verilator_bin_dbg
verilator_exe verilator_bin verilator_bin_dbg:
.PHONY:verilator_coverage_bin_dbg
verilator_exe verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg:
@echo ------------------------------------------------------------
@echo "making verilator in src" ; \
(cd src && $(MAKE) $(OBJCACHE_JOBS) )
@@ -178,17 +182,15 @@ msg_test: all_nomsg
.PHONY:test
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
test: test_vcs test_c test_sc test_sp test_verilated test_regress
test: test_c test_sc test_verilated test_regress
else
test: test_c test_sc test_sp
test: test_c test_sc
endif
@echo "Tests passed!"
@echo
@echo "Type 'make install' to install documentation."
@echo
test_vcs: all_nomsg
@(cd test_vcs && $(MAKE))
test_c: all_nomsg
@(cd test_c && $(MAKE))
test_c_debug: all_nomsg
@@ -197,10 +199,6 @@ test_sc: all_nomsg
@(cd test_sc && $(MAKE))
test_sc_debug: all_nomsg
@(cd test_sc && $(MAKE) test_debug)
test_sp: all_nomsg
@(cd test_sp && $(MAKE))
test_sp_debug: all_nomsg
@(cd test_sp && $(MAKE) test_debug)
test_verilated: all_nomsg
@(cd test_verilated && $(MAKE))
test_regress: all_nomsg
@@ -212,6 +210,9 @@ info: $(INFOS)
verilator.1: ${srcdir}/bin/verilator
pod2man $< $@
verilator_coverage.1: ${srcdir}/bin/verilator_coverage
pod2man $< $@
verilator.txt: ${srcdir}/bin/verilator
$(POD2TEXT) $< $@
@@ -227,16 +228,16 @@ verilator.pdf: ${srcdir}/bin/verilator Makefile
pdflatex verilator.tex
-rm -f verilator.toc verilator.aux verilator.idx verilator.out
README: readme.pod
README: README.pod
-rm -f $@
$(POD2TEXT) --loose $< > $@
README.html: readme.pod
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
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
@@ -260,13 +261,13 @@ internals.pdf: internals.pod Makefile
-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
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg \
verilator_coverage verilator_includer verilator_profcfunc
# Some scripts go into both the search path and pkgdatadir,
# so they can be found by the user, and under $VERILATOR_ROOT.
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
VL_INST_MAN_FILES = verilator.1
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1
VL_INST_INC_BLDDIR_FILES = \
include/verilated.mk \
@@ -280,14 +281,15 @@ VL_INST_DATA_SRCDIR_FILES = \
test_v/*.[chv]* \
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
test_sp/Makefile test_sp/Makefile_obj \
installbin:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_coverage $(DESTDIR)$(bindir)/verilator_coverage )
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
( $(INSTALL_PROGRAM) verilator_coverage_bin_dbg $(DESTDIR)$(bindir)/verilator_coverage_bin_dbg )
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
@@ -310,7 +312,6 @@ installdata:
done
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sp
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v
cd $(srcdir) \
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
@@ -350,6 +351,7 @@ INST_PROJ_CVS = cp_if_cvs_diff
install-project: dist
@echo "Install-project to $(DIRPROJECT)"
strip verilator_bin*
strip verilator_coverage_bin*
$(MAKE) install-project-quick
for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
@@ -373,6 +375,7 @@ endif
install-cadtools: dist
@echo "Install-project to $(CAD_DIR)"
strip verilator_bin*
strip verilator_coverage_bin*
$(MAKE) install-cadtools-quick
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
for p in $(VL_INST_MAN_FILES) ; do \
@@ -400,8 +403,9 @@ endif
endif
# Use --xml flag to see the cppcheck code to use for suppression
CPPCHECK = cppcheck
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject --suppress=cstyleCast
CPPCHECK = src/cppcheck_filtered
CPPCHECK_FLAGS = --enable=all --inline-suppr \
--suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList
CPPCHECK_FLAGS += --xml
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
@@ -458,7 +462,8 @@ clean mostlyclean distclean maintainer-clean::
rm -f *.tex
distclean maintainer-clean::
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
rm -f Makefile config.status config.cache config.log TAGS
rm -f verilator_bin* verilator_coverage_bin*
rm -f include/verilated.mk include/verilated_config.h
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
+25 -37
View File
@@ -5,11 +5,13 @@
=head1 NAME
This is the Verilator Package README file.
This is the Verilator package README file.
=head1 DISTRIBUTION
This package is Copyright 2003-2013 by Wilson Snyder. (Report bugs to
http://www.veripool.org/verilator
This package is Copyright 2003-2015 by Wilson Snyder. (Report bugs to
L<http://www.veripool.org/>.)
Verilator is free software; you can redistribute it and/or modify it under
@@ -24,14 +26,14 @@ more details.
=head1 DESCRIPTION
Verilator converts synthesizable (not behavioral) Verilog code into C++ or
SystemC code. It is not a complete simulator, just a translator.
Verilator converts synthesizable (generally not behavioral) Verilog code
into C++ or SystemC code. It is not a complete simulator, just a
translator.
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
reads the specified Verilog code, lints it, and optionally adds coverage
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
it outputs .sp files for the SystemPerl preprocessor available at
http://www.veripool.org.
it outputs .cpp and .h files using the standard SystemC headers.
The resulting files are then compiled with C++. The user writes a little
C++ wrapper file, which instantiates the top level module. This is
@@ -41,14 +43,11 @@ The resulting executable will perform the actual simulation.
=head1 SUPPORTED SYSTEMS
Verilator is developed and has primary testing on:
SuSE 11.1 AMD64 i686-linux-2.6.27, GCC 4.3.2
Versions have also built on Redhat Linux, Macs OS-X, HPUX and Solaris. It
should run with minor porting on any Linix-ish platform. Verilator also
works on Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin).
Verilated output (not Verilator itself) compiles under MSVC++ 2008.
Verilator is developed and has primary testing on Ubuntu. Versions have
also built on Redhat Linux, Macs OS-X, HPUX and Solaris. It should run
with minor porting on any Linix-ish platform. Verilator also works on
Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin). Verilated
output (not Verilator itself) compiles under MSVC++ 2008 and newer.
=head1 INSTALLATION
@@ -71,19 +70,11 @@ Download the latest package from that site, and decompress.
=item
If you will be using SystemC (vs straight C++ output), download SystemC
2.0.1 from L<http://www.systemc.org>. Follow their installation
instructions. You will need to set SYSTEMC_INCLUDE to point to the
include directory with systemc.h in it, and SYSTEMC_LIBDIR to points
to the directory with libsystemc.a in it. (Older installations may
set SYSTEMC and SYSTEMC_ARCH instead.)
=item
If you will be using SystemPerl or coverage, download and install
System-Perl, L<http://www.veripool.org/systemperl>. Note you'll need to
set a C<SYSTEMPERL> environment variable to point to the downloaded kit.
Optionally also set C<SYSTEMPERL_INCLUDE> to point to the installed
headers.
from L<http://www.systemc.org>. Follow their installation instructions.
You will need to set SYSTEMC_INCLUDE to point to the include directory with
systemc.h in it, and SYSTEMC_LIBDIR to points to the directory with
libsystemc.a in it. (Older installations may set SYSTEMC and SYSTEMC_ARCH
instead.)
=item
@@ -98,8 +89,8 @@ C<cd> to the Verilator directory containing this README.
You now have to decide how you're going to eventually install the kit.
Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC_INCLUDE,
SYSTEMC_LIBDIR, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
executable, so try to have them correct before configuring.
and SYSTEMC_LIBDIR as defaults into the executable, so try to have them
correct before configuring.
=over 4
@@ -107,7 +98,7 @@ executable, so try to have them correct before configuring.
Our personal favorite is to always run Verilator from the kit directory.
This allows the easiest experimentation and upgrading. It's also how most
EDA tools operate; to run any of them you point to the tarball.
EDA tools operate; to run you point to the tarball, no install is needed.
export VERILATOR_ROOT=`pwd` # if your shell is bash
setenv VERILATOR_ROOT `pwd` # if your shell is csh
@@ -156,11 +147,10 @@ PATH.
Type C<make> to compile Verilator.
Type C<make test_c> to check the compilation.
Type C<make test> to check the compilation.
Type C<make test> for a more complete test. You may get a error about the
Bit::Vector Perl package. You will need to install it and SystemPerl if
you want all tests to pass.
Configure with C<--enable-longtests> for more complete developer tests.
Additional packages may be required for these tests.
You may get a error about a typedef conflict for uint32_t. Edit
verilated.h to change the typedef to work, probably to @samp{typedef
@@ -195,15 +185,13 @@ The directories in the kit after de-taring are as follows:
bin/verilator => Compiler Wrapper invoked to Verilate code
include/ => Files that should be in your -I compiler path
include/verilated*.cpp => Global routines to link into your simulator
include/verilated.h => Global headers
include/verilated*.h => Global headers
include/verilated.v => Stub defines for linting
include/verilated.mk => Common makefile
src/ => Translator source code
test_v => Example Verilog code for other test dirs
test_c => Example Verilog->C++ conversion
test_sc => Example Verilog->SystemC conversion
test_sp => Example Verilog->SystemPerl conversion
test_vcs => Example Verilog->VCS conversion (test the test)
test_verilated => Internal tests
test_regress => Internal tests
Regular → Executable
+2 -16
View File
@@ -1,6 +1,6 @@
// DESCRIPTION: Verilator: List of To Do issues.
//
// Copyright 2004-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -30,21 +30,6 @@ Configure/Make/Install
* Full MSVC++ compilation (does scons support this?) (4.000?)
* Distribute with flex/bison already expanded?
Flex library not needed. Probably too difficult to be worth it.
* Integrate SystemPerl coverage
(Note in /usr/include there are no upper cased include files.)
Coverage.pm -- Need all functionality, but in C?
Coverage/Item.pm -- Need all functionality, but in C?
Coverage/ItemKey.pm -- Need all functionality, but in C?
sp_preproc -- Some steps in here need to be moved to generated C
src/Sp.cpp -- n/a
src/SpCommon.h -- mostly overlaps verilatedos.h
src/SpCoverage.cpp/h -- All needed
src/SpFunctor.cpp/h -- No longer used
src/SpTraceVcd.cpp/h -- MOVED
src/SpTraceVcdC.cpp/h -- MOVED
src/sp_log.cpp/h -- Not needed
src/systemperl.h -- some stuff may be cut
vcoverage -- Need all functionality, but in C?
Testing:
* Move test_c/sp/v/verilated into test_regress format (4.000?)
@@ -53,6 +38,7 @@ Testing:
* New random program generator
* Better graph viewer with search and zoom
* Port and test against opencores.org code
* // verilator debug in code so can see only tree affecting those nodes
Usability:
* Detect and pre-remove most UNOPTFLATs (4.000)
+285 -219
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
######################################################################
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you
# Copyright 2003-2015 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.
@@ -24,14 +24,10 @@ BEGIN {
}
}
use File::Path;
use File::Basename;
use Getopt::Long;
use FindBin qw($RealBin $RealScript);
use IO::File;
use Pod::Usage;
use Config;
use Cwd qw(abs_path getcwd);
use strict;
use vars qw ($Debug @Opt_Verilator_Sw);
@@ -209,17 +205,13 @@ Verilator - Convert Verilog code to C++/SystemC
=head1 DESCRIPTION
Verilator converts synthesizable (not behavioral) Verilog code, plus some
Synthesis, SystemVerilog and a small subset of Verilog AMS and Sugar/PSL
assertions, into C++, SystemC or SystemPerl code. It is not a complete
simulator, just a compiler.
Synthesis, SystemVerilog and a small subset of Verilog AMS assertions, into
C++ or SystemC code. It is not a complete simulator, but a compiler.
Verilator is invoked with parameters similar to GCC, Cadence
Verilog-XL/NC-Verilog, or Synopsys's VCS. It reads the specified Verilog
code, lints it, and optionally adds coverage and waveform tracing code.
For C++ and SystemC formats, it outputs .cpp and .h files. For SystemPerl
format, it outputs .sp files for the SystemPerl preprocessor, which greatly
simplifies writing SystemC code and is available at
L<http://www.veripool.org>.
For C++ and SystemC formats, it outputs .cpp and .h files.
The files created by Verilator are then compiled with C++. The user writes
a little C++ wrapper file, which instantiates the top level module, and
@@ -254,12 +246,13 @@ descriptions in the next sections for more information.
-CFLAGS <flags> C++ Compiler flags for makefile
--cc Create C++ output
--cdc Clock domain crossing analysis
--clk <signal-name> Mark specified signal as clock
--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-user Enable SVL user coverage
--coverage-underscore Enable coverage of _signals
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
@@ -267,9 +260,10 @@ descriptions in the next sections for more information.
--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
+define+<var>=<value> Set preprocessor define
--dump-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level
--dump-treei-<srcfile> <level> Enable dumping .tree file at a source file at a level
-E Preprocess, but do not compile
--error-limit <value> Abort after this number of errors
--exe Link to create executable
@@ -292,6 +286,7 @@ descriptions in the next sections for more information.
--MP Create phony dependency targets
--Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes
--no-clk <signal-name> Prevent marking specified signal as clock
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
--no-skip-identical Disable skipping identical output
+notimingchecks Ignored
@@ -299,8 +294,11 @@ descriptions in the next sections for more information.
-O3 High performance optimizations
-O<optimization-letter> Selectable optimizations
-o <executable> Name of final executable
--no-order-clock-delay Disable ordering clock enable assignments
--output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .ccp functions
--output-split-cfuncs <statements> Split .cpp functions
--output-split-ctrace <statements> Split tracing functions
-P Disable line numbers and blanks with -E
--pins-bv <bits> Specify types for top level ports
--pins-sc-uint Specify types for top level ports
--pins-sc-biguint Specify types for top level ports
@@ -309,13 +307,12 @@ descriptions in the next sections for more information.
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--private Debugging; see docs
--psl Enable PSL parsing
--public Debugging; see docs
--report-unoptflat Extra diagnostics for UNOPTFLAT
--savable Enable model save-restore
--sc Create SystemC output
--sp Create SystemPerl output
--stats Create statistics file
--stats-vars Provide statistics on variables
-sv Enable SystemVerilog parsing
+systemverilogext+<ext> Synonym for +1800-2012ext+<ext>
--top-module <topname> Name of top level input module
@@ -323,6 +320,8 @@ descriptions in the next sections for more information.
--trace-depth <levels> Depth of tracing
--trace-max-array <depth> Maximum bit width for tracing
--trace-max-width <width> Maximum array depth for tracing
--trace-params Enable tracing parameters
--trace-structs Enable tracing structure names
--trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations
@@ -406,8 +405,7 @@ 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.)
Enable all assertions.
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
and/or "--x-initial-edge" may be desirable.
@@ -449,7 +447,7 @@ run on the generated makefile these will be passed to the C++ compiler
=item --cc
Specifies C++ without SystemC output mode; see also --sc and --sp.
Specifies C++ without SystemC output mode; see also --sc.
=item --cdc
@@ -461,12 +459,35 @@ information is also written to the file {prefix}__cdc.txt.
Currently only checks some items that other CDC tools missed; if you have
interest in adding more traditional CDC checks, please contact the authors.
=item --clk I<signal-name>
Sometimes it is quite difficult for Verilator to distinguish clock signals from
other data signals. Occasionally the clock signals can end up in the checking
list of signals which determines if further evaluation is needed. This will
heavily degrade the performance of verilated model.
With --clk <signal-name>, user can specified root clock into the model, then
Verilator will mark the signal as clocker and propagate the clocker attribute
automatically to other signals derived from that. In this way, Verilator will
try to avoid taking the clocker signal into checking list.
Note signal-name is specified by the RTL hiearchy path. For example, v.foo.bar.
If the signal is the input to top-module, the directly the signal name. If you
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
RTL file to mark the signal directly.
=item --compiler I<compiler-name>
Enables tunings and work-arounds for the specified C++ compiler.
=over 4
=item clang
Tune for clang. This may reduce execution speed as it enables several
workarounds to avoid silly hardcoded limits in clang. This includes
breaking deep structures as for msvc as described below.
=item gcc
Tune for Gnu C++, although generated code should work on almost any
@@ -553,24 +574,26 @@ signals are not covered. See also --trace-underscore.
=item --coverage-user
Enables user inserted functional coverage. Currently, all functional
coverage points are specified using PSL which must be separately enabled
with --psl.
coverage points are specified using SVA which must be separately enabled
with --assert.
For example, the following PSL statement will add a coverage point, with
For example, the following statement will add a coverage point, with
the comment "DefaultClock":
// psl default clock = posedge clk;
// psl cover {cyc==9} report "DefaultClock,expect=1";
DefaultClock: cover property (@(posedge clk) cyc==3);
=item -DI<var>=I<value>
Defines the given preprocessor symbol. Same as +define; +define is fairly
standard across Verilog tools while -D is an alias for GCC compatibility.
Defines the given preprocessor symbol, without allowing. Similar to
+define; +define is fairly standard across Verilog tools while -D is an
alias for GCC compatibility.
=item --debug
Select the debug built image of Verilator (if available), and enable more
internal assertions, debugging messages, and intermediate form dump files.
internal assertions (equivelent to C<--debug-check>), debugging messages
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
to C<--dump-treei 3>).
=item --debug-check
@@ -582,9 +605,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally
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>).
to the specified debug level (1-10) or set the specified Verilator source
file to the specified level (e.g. C<--debugi-V3Width 9>). Higher levels
produce more detailed messages.
=item --default-language I<value>
@@ -605,10 +628,13 @@ used.
If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used.
=item +define+I<var>+I<value>
=item +define+I<var>=I<value>
Defines the given preprocessor symbol. Same as -D; +define is fairly
standard across Verilog tools while -D is an alias for GCC compatibility.
=item +define+I<var>=I<value>+I<var2>=I<value2>...
Defines the given preprocessor symbol, or multiple symbols if separated by
plusses. Similar to -D; +define is fairly standard across Verilog tools
while -D is an alias for GCC compatibility.
=item --dump-tree
@@ -620,8 +646,12 @@ 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
=item --dump-treei-<srcfile> <level>
Rarely needed - for developer use. Set internal tree dumping level
globally to a specific dumping level or set the specified Verilator source
file to the specified tree dumping level (e.g. C<--dump-treei-V3Order 9>).
Level 0 disbles dumps and is equivalent to "--no-dump-tree". Level 9
enables dumping of every stage.
=item -E
@@ -746,13 +776,19 @@ to gcc -MP option.
=item --Mdir I<directory>
Specifies the name of the Make object directory. All generated files will
be placed in this directory. If not specified, "obj_dir" is used.
be placed in this directory. If not specified, "obj_dir" is used. The
directory is created if it does not exist and the parent directories exist;
otherwise manually create the Mdir before calling Verilator.
=item --mod-prefix I<topname>
Specifies the name to prepend to all lower level classes. Defaults to
the same as --prefix.
=item --no-clk <signal-name>
Prevent the specified signal from being marked as clock. See C<--clk>.
=item --no-pins64
Backward compatible alias for "--pins-bv 33".
@@ -772,8 +808,10 @@ Disables optimization of the model.
=item -O3
Enables slow optimizations. This may reduce simulation runtimes at the
cost of compile time. This currently sets --inline-mult -1.
Enables slow optimizations for the code Verilator itself generates (as
opposed to "-CFLAGS -O3" which effects the C compiler's optimization. -O3
may reduce simulation runtimes at the cost of compile time. This currently
sets --inline-mult -1.
=item -OI<optimization-letter>
@@ -788,6 +826,12 @@ mappings of optimizations to -O letters.
Specify the name for the final executable built if using --exe. Defaults
to the --prefix if not specified.
=item --no-order-clock-delay
Rarely needed. Disables a bug fix for ordering of clock enables with
delayed assignments. This flag should only be used when suggested by the
developers.
=item --output-split I<bytes>
Enables splitting the output .cpp/.sp files into multiple outputs. When a
@@ -810,6 +854,16 @@ worse with decreasing split values. Note that this option is stronger than
--output-split in the sense that --output-split will not split inside a
function.
=item --output-split-ctrace I<statements>
Enables splitting trace functions in the output .cpp/.sp files into
multiple functions. Defaults to same setting as --output-split-cfuncs.
=item -P
With -E, disable generation of `line markers and blank lines, similar to
GCC -P flag.
=item --pins64
Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
@@ -880,12 +934,6 @@ statements.
Opposite of --public. Is the default; this option exists for backwards
compatibility.
=item --psl
Enable PSL parsing. Without this switch, PSL meta-comments are ignored.
See the --assert flag to enable all assertions, and --coverage-user to
enable functional coverage.
=item --public
This is only for historical debug use. Using it may result in
@@ -907,7 +955,7 @@ break the loop.
In addition produces a GraphViz DOT file of the entire strongly connected
components within the source associated with each loop. This is produced
irrespective of whether --dump-tree is set. Such graphs may help in
analysing the problem, but can be very large indeed.
analyzing the problem, but can be very large indeed.
Various commands exist for viewing and manipulating DOT files. For example
the I<dot> command can be used to convert a DOT file to a PDF for
@@ -941,16 +989,18 @@ other data the process needs saved/restored. For example:
=item --sc
Specifies SystemC output mode; see also --cc and -sp.
=item --sp
Specifies SystemPerl output mode; see also --cc and -sc.
Specifies SystemC output mode; see also --cc.
=item --stats
Creates a dump file with statistics on the design in {prefix}__stats.txt.
=item --stats-vars
Creates more detailed statistics including a list of all the variables by
size (plain --stats just gives a count). See --stats, which is implied by
this.
=item -sv
Specifies SystemVerilog language features should be enabled; equivalent to
@@ -1000,6 +1050,17 @@ Rarely needed. Specify the maximum bit width of a signal that may be
traced. Defaults to 256, as tracing large vectors may greatly slow traced
simulations.
=item --no-trace-params
Disable tracing of parameters.
=item --trace-structs
Enable tracing to show the name of packed structure, union, and packed
array fields, rather than a simgle combined packed bus. Due to VCD file
format constraints this may result in significantly slower trace times and
larger trace files.
=item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these
@@ -1063,15 +1124,17 @@ supports which the older version does not support.
=item -Wno-I<message>
Disable the specified warning message.
Disable the specified warning message. This will override any lint_on
directives in the source, i.e. the warning will still not be printed.
=item -Wno-lint
Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-ALWCOMBORDER -Wno-CASEINCOMPLETE -Wno-CASEOVERLAP
-Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT
-Wno-LITENDIAN -Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN
-Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for Wno-style.
-Wno-LITENDIAN -Wno-PINCONNECTEMPTY -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
@@ -1081,8 +1144,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-PINNOCONNECT -Wno-SYNCASYNCNET -Wno-UNDRIVEN
-Wno-UNUSED -Wno-VARHIDDEN".
-Wno-INCABSPATH -Wno-PINCONNECTEMPTY -Wno-PINNOCONNECT -Wno-SYNCASYNCNET
-Wno-UNDRIVEN -Wno-UNUSED -Wno-VARHIDDEN".
=item -Wno-fatal
@@ -1161,7 +1224,7 @@ 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
--x-initial-edge with Verilator will replicate this behavior. 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
@@ -1250,7 +1313,7 @@ the test_c directory in the distribution for an example.
=head1 EXAMPLE SYSTEMC EXECUTION
This is an example similar to the above, but using SystemPerl.
This is an example similar to the above, but using SystemC.
mkdir test_our_sc
cd test_our_sc
@@ -1285,17 +1348,7 @@ your operating system (as an RPM), first you need to point to the kit:
Now we run Verilator on our little example.
verilator -Wall --sp our.v
Then we convert the SystemPerl output to SystemC.
cd obj_dir
export SYSTEMPERL=/path/to/where/systemperl/kit/came/from
$SYSTEMPERL/sp_preproc --preproc *.sp
(You can also skip the above sp_preproc by getting pure SystemC from
Verilator by replacing the verilator --sp flag in the previous step with
-sc.)
verilator -Wall --sc our.v
We then can compile it
@@ -1324,7 +1377,7 @@ And we get the same output as the C++ example:
Really, you're better off using a Makefile to do all this for you. Then,
when your source changes it will automatically run all of these steps. See
the test_sp directory in the distribution for an example.
the test_sc directory in the distribution for an example.
=head1 BENCHMARKING & OPTIMIZATION
@@ -1382,6 +1435,10 @@ 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.
If you are using your own makefiles, you may want to compile the Verilated
code with -DVL_INLINE_OPT=inline. This will inline functions, however this
requires that all cpp files be compiled in a single compiler run.
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.
@@ -1409,11 +1466,6 @@ For -cc and -sc mode, it also creates:
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files
{prefix}{each_verilog_module}.h // Lower level internal header files
For -sp mode, instead of .cpp and .h it creates:
{prefix}.sp // Top level SystemC file
{prefix}{each_verilog_module}.sp // Lower level internal SC files
In certain optimization modes, it also creates:
{prefix}__Dpi.h // DPI import and export declarations
@@ -1488,21 +1540,6 @@ specified, it will come from a default optionally specified at configure
time (before Verilator was compiled), or computed from
SYSTEMC/lib-SYSTEMC_ARCH.
=item SYSTEMPERL
Specifies the directory containing the SystemPerl distribution kit. This
is used to find the SystemPerl library and include files. If not
specified, it will come from a default optionally specified at configure
time (before Verilator was compiled). See also SYSTEMPERL_INCLUDE.
=item SYSTEMPERL_INCLUDE
Specifies the directory containing the Verilog-Perl include .cpp files,
from the src/ directory of the SystemPerl kit. If not specified, it will
be computed from the SYSTEMPERL environment variable if it is set, and if
SYSTEMPERL is not set SYSTEMPERL_INCLUDE will come from a default
optionally specified at configure time (before Verilator was compiled).
=item VCS_HOME
If set, specifies the directory containing the Synopsys VCS distribution.
@@ -1892,6 +1929,9 @@ Disables the specified lint warning, in the specified filename (or wildcard
with '*' or '?', or all files if omitted) and range of line numbers (or all
lines if omitted).
Using '*' will override any lint_on directives in the source, i.e. the
warning will still not be printed.
If the -msg is omitted, all lint warnings are disabled. This will override
all later lint warning enables for the specified region.
@@ -1920,16 +1960,12 @@ uwire keyword.
=head2 SystemVerilog 2005 (IEEE 1800-2005) Support
Verilator currently has some support for SystemVerilog synthesis
constructs. As SystemVerilog features enter common usage they are added;
please file a bug if a feature you need is missing.
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, struct, time, typedef, union, var, void, priority
case/if, and unique case/if.
const, do-while, enum, export, final, import, int, interface, logic,
longint, modport, package, program, shortint, struct, time, typedef, union,
var, void, priority case/if, and unique case/if.
It also supports .name and .* interconnection.
@@ -1950,7 +1986,7 @@ please file a bug if a feature you need is missing.
Verilator implements a very small subset of Verilog AMS (Verilog Analog and
Mixed-Signal Extensions) with the subset corresponding to those VMS
keywords with near equivelents in the Verilog 2005 or SystemVerilog 2009
keywords with near equivalents in the Verilog 2005 or SystemVerilog 2009
languages.
AMS parsing is enabled with "--language VAMS" or "--language 1800+VAMS".
@@ -1958,34 +1994,6 @@ AMS parsing is enabled with "--language VAMS" or "--language 1800+VAMS".
At present Verilator implements ceil, exp, floor, ln, log, pow, sqrt,
string, and wreal.
=head2 Sugar/PSL Support
Most future work is being directed towards improving SystemVerilog
assertions instead of PSL. If you are using these PSL features, please
contact the author as they may be depreciated in future versions.
With the --assert switch, Verilator enables support of the Property
Specification Language (PSL), specifically the simple PSL subset without
time-branching primitives. Verilator currently only converts PSL
assertions to simple "if (...) error" statements, and coverage statements
to increment the line counters described in the coverage section.
Verilator implements these keywords: assert, assume (same as assert),
default (for clocking), countones, cover, isunknown, onehot, onehot0,
report, and true.
Verilator implements these operators: -> (logical if).
Verilator does not support SEREs yet. All assertion and coverage
statements must be simple expressions that complete in one cycle. PSL
vmode/vprop/vunits are not supported. PSL statements must be in the module
they reference, at the module level where you would put an
initial... statement.
Verilator only supports (posedge CLK) or (negedge CLK), where CLK is the
name of a one bit signal. You may not use arbitrary expressions as
assertion clocks.
=head2 Synthesis Directive Assertion Support
With the --assert switch, Verilator reads any "//synopsys full_case" or
@@ -1998,8 +2006,8 @@ appropriate code to detect failing cases at runtime and print an "Assertion
failed" error message.
Verilator likewise also asserts any "unique" or "priority" SystemVerilog
keywords on case statements. However, "unique if" and "priority if" are
currently simply ignored.
keywords on case statement, as well as "unique" on if statements.
However, "priority if" is currently simply ignored.
=head1 LANGUAGE EXTENSIONS
@@ -2026,13 +2034,6 @@ supported by Verilator since 2006!)
This will report an error when encountered, like C++'s #error.
=item _(I<expr>)
A underline followed by an expression in parenthesis returns a Verilog
expression. This is different from normal parenthesis in special contexts,
such as PSL expressions, and can be used to embed bit concatenation ({})
inside of PSL statements.
=item $c(I<string>, ...);
The string will be embedded directly in the output C++ code at the point
@@ -2154,6 +2155,15 @@ 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 clocker*/
=item /*verilator no_clocker*/
Used after a signal declaration to indicate the signal is used as clock or
not. This information is used by Verilator to mark the signal as clocker
and propagate the clocker attribute automatically to derived signals. See
C<--clk> for more information.
=item /*verilator coverage_block_off*/
Specifies the entire begin/end block should be ignored for coverage
@@ -2176,8 +2186,8 @@ Specifies the module the comment appears in may be inlined into any modules
that use this module. This is useful to speed up simulation time with some
small loss of trace visibility and modularity. Note signals under inlined
submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not
allow "." in signal names. SystemPerl when tracing such signals will
replace the __DOT__ with the period.
allow "." in signal names. When tracing such signals the tracing routines
will replace the __DOT__ with the period.
=item /*verilator isolate_assignments*/
@@ -2251,6 +2261,14 @@ reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself.
=item /*verilator public*/ (typedef enum)
Used after an enum typedef declaration to indicate the emitted C code
should have the enum values visible. Due to C++ language restrictions, this
may only be used on 64-bit or narrower integral enumerations.
typedef enum logic [2:0] { ZERO = 3'b0 } pub_t /*verilator public*/;
=item /*verilator public*/ (variable)
Used after an input, output, register, or wire declaration to indicate the
@@ -2338,12 +2356,14 @@ behavior. See the test_regress/t/t_dpi_display.v file for an example.
=item /*verilator tracing_off*/
Disable waveform tracing for all future signals that are declared in this
module. Often this is placed just after a primitive's module statement, so
that the entire module is not traced.
module, or cells below this module. Often this is placed just after a
primitive's module statement, so that the entire module and cells below it
are not traced.
=item /*verilator tracing_on*/
Re-enable waveform tracing for all future signals that are declared.
Re-enable waveform tracing for all future signals or cells that are
declared.
=back
@@ -2446,7 +2466,7 @@ 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
X. Uninitialized 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
@@ -2605,6 +2625,12 @@ and continue keywords.
Inside expressions may not include unpacked array traversal or $ as an
upper bound. Case inside and case matches are also unsupported.
=item interface
Interfaces and modports, including with generated data types are supported.
Generate blocks around modports are not supported, nor are virtual
interfaces nor unnamed interfaces.
=item priority if, unique if
Priority and unique if's are treated as normal ifs and not asserted to be
@@ -2616,8 +2642,9 @@ All specify blocks and timing checks are ignored.
=item string
String is supported only to the point that they can be passed to DPI
imports.
String is supported only to the point that they can be assigned,
concatenated, compared, and passed to DPI imports. Standard method calls
on strings are not supported.
=item timeunit, timeprecision
@@ -2853,6 +2880,16 @@ With --cdc only, warns that asynchronous flop reset terms come from other
than primary inputs or flopped outputs, creating the potential for reset
glitches.
=item CLKDATA
Warns that clock signal is mixed used with/as data signal. The checking for
this warning is enabled only if user has explicitly marked some signal as
clocker using command line option or in-source meta comment (see C<--clk>).
The warning can be disabled without affecting the simulation result. But it
is recommanded to check the warning as this may degrade the performance of
the Verilated model.
=item CMPCONST
Warns that you are comparing a value in a way that will always be constant.
@@ -2966,8 +3003,8 @@ simulators.
Warns that an `include filename specifies an absolute path. This means the
code will not work on any other system with a different file system layout.
Instead of using absolute paths, relative paths (preferably without any
directory specified whatever) should be used, and +include used on the
command line to specify the top include source directory.
directory specified whatever) should be used, and +incdir used on the
command line to specify the top include source directories.
Disabled by default as this is a code style warning; it will simulate
correctly.
@@ -3018,11 +3055,21 @@ 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 PINCONNECTEMPTY
Warns that a cell instantiation has a pin which is connected to
.pin_name(), e.g. not another signal, but with an explicit mention of the
pin. It may be desirable to disable PINCONNECTEMPTY, as this indicates
intention to have a no-connect.
Disabled by default as this is a code style warning; it will simulate
correctly.
=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())".
cell declaration with a empty connection, using "(.pin_name())".
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
@@ -3086,10 +3133,9 @@ simulators.
=item SYMRSVDWORD
Error that a symbol matches a C++ reserved word and using this as a symbol
name would result in odd C compiler errors. You may disable this error
message as you would disable warnings, but the symbol will be renamed by
Verilator to avoid the conflict.
Warning that a symbol matches a C++ reserved word and using this as a symbol
name would result in odd C compiler errors. You may disable this warning,
but the symbol will be renamed by Verilator to avoid the conflict.
=item SYNCASYNCNET
@@ -3210,6 +3256,13 @@ section for more details.
Ignoring this warning will only slow simulations, it will simulate
correctly.
=item UNPACKED
Warns that unpacked structs and unions are not supported.
Ignoring this warning will make Verilator treat the structure as packed,
which may make Verilator simulations differ from other simulators.
=item UNSIGNED
Warns that you are comparing a unsigned value in a way that implies it is
@@ -3371,7 +3424,7 @@ so your simulator shouldn't have to be -- and Verilator is closer to the
synthesis interpretation, so this is a good thing for getting working
silicon.
=item Will Verilator output remain under my own copyright?
=item Will Verilator output remain under my own license?
Yes, it's just like using GCC on your programs; this is why Verilator uses
the "GNU *Lesser* Public License Version 3" instead of the more typical
@@ -3423,10 +3476,6 @@ flag.
Note you can also call ->trace on multiple Verilated objects with the same
trace file if you want all data to land in the same output file.
Note also older versions of Verilator used the SystemPerl package and
SpTraceVcdC class. This still works, but is depreciated as it requires
strong coupling between the Verilator and SystemPerl versions.
#include "verilated_vcd_c.h"
...
int main(int argc, char **argv, char **env) {
@@ -3449,7 +3498,7 @@ Add the --trace switch to Verilator, and in your top level C sc_main code,
include verilated_vcd_sc.h. Then call Verilated::traceEverOn(true). Then
create a VerilatedVcdSc object as you would create a normal SystemC trace
file. For an example, see the call to VerilatedVcdSc in the
test_sp/sc_main.cpp file of the distribution, and below.
test_sc/sc_main.cpp file of the distribution, and below.
Alternatively you may use the C++ trace mechanism described in the previous
question, however the timescale and timeprecision will not inherited from
@@ -3501,22 +3550,21 @@ network disk. Network disks are generally far slower.
=item How do I do coverage analysis?
Verilator supports both block (line) coverage and user inserted functional
coverage. Both require the SystemPerl package to be installed but do not
require use of the SystemPerl output mode.
coverage.
First, run verilator with the --coverage option. If you're using your own
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
using Verilator's, it will do this for you.)
makefile, compile the model with the GCC flag -DVM_COVERAGE (if using
Verilator's, it will do this for you.)
Run your tests in different directories. Each test will create a
logs/coverage.pl file.
After running all of your tests, the vcoverage utility (from the SystemPerl
package) is executed. Vcoverage reads the logs/coverage.pl file(s), and
creates an annotated source code listing showing code coverage details.
After running all of your tests, verilator_coverage is executed.
Verilator_coverage reads the logs/coverage.pl file(s), and creates an
annotated source code listing showing code coverage details.
For an example, after running 'make test' in the Verilator distribution,
see the test_sp/logs/coverage_source directory. Grep for lines starting
see the test_sc/logs directory. Grep for lines starting
with '%' to see what lines Verilator believes need more coverage.
=item Where is the translate_off command? (How do I ignore a construct?)
@@ -3745,70 +3793,88 @@ as the need arises. Verilator is now about 3x faster than in 2002, and is
faster than many popular commercial simulators.
=head1 CONTRIBUTORS
Many people have provided ideas and other assistance with Verilator.
The major corporate sponsors of Verilator, by providing significant
contributions of time or funds include include Cavium Networks, Compaq
Corporation, Digital Equipment Corporation, Embecosm Ltd., Hicamp Systems,
Intel Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip
Designs Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
The people who have contributed major functionality are Byron Bradley,
Jeremy Bennett, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder.
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, 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, 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
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2013 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0.
=head1 AUTHORS
When possible, please instead report bugs to L<http://www.veripool.org/>.
Wilson Snyder <[email protected]>
Major concepts by Paul Wasson and Duane Galbi.
Major concepts by Paul Wasson, Duane Galbi and Jie Xu.
=head1 CONTRIBUTORS
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 Atmel Corporation, Cavium
Inc., Compaq Corporation, Digital Equipment Corporation, Embecosm Ltd.,
Hicamp Systems, Intel Corporation, Mindspeed Technologies Inc., MicroTune
Inc., picoChip Designs Ltd., Sun Microsystems Inc., Nauticus Networks Inc.,
and SiCortex Inc.
The people who have contributed major functionality are Byron Bradley,
Jeremy Bennett, Jie Xu, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson
Snyder. Major testers include Jeff Dutton, Jonathon Donaldson, Ralf Karge,
David Hewson, Iztok Jeras, Wim Michiels, Alex Solomatnikov, Sebastien Van
Cauwenberghe, Gene Weber, and Clifford Wolf.
Some of the people who have provided ideas and feedback for Verilator
include: Yves Mathieu, David Addison, Nikana Anastasiadis, Hans Van
Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad Bagri, Andrew Bardsley,
Geoff Barrett, J Baxter, Julius Baxter, Jeremy Bennett, Michael Berman,
David Binderman, David Black, Daniel Bone, Gregg Bouchard, Christopher
Boumenot, Nick Bowler, Byron Bradley, Bryan Brady, Charlie Brej, Lane
Brooks, John Brownlee, Jeff Bush, Lawrence Butcher, Ted Campbell, Chris
Candler, Lauren Carlson, Donal Casey, Terry Chen, Robert A. Clark, Allan
Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, Mike Denio,
John Deroo, Philip Derrick, John Dickol, R. Diez, Ruben Diez, Danny Ding,
Ivan Djordjevic, Jonathon Donaldson, Alex Duller, Jeff Dutton, Chandan
Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell, Eugen Fekete,
Fabrizio Ferrandi, Andrea Foletto, Bob Fredieu, Christian Gelinek, Glen
Gibb, Shankar Giri, Sam Gladstone, Amir Gonnen, Chitlesh Goorah, Neil
Hamilton, Junji Hashimoto, Thomas Hawkins, David Hewson, Hiroki Honda, Alex
Hornung, Jae Hossell, Ben Jackson, Krzysztof Jankowski, HyungKi Jeong,
Iztok Jeras, James Johnson, Christophe Joly, Franck Jullien, Mike Kagen,
Kaalia Kahn, Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf
Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Sobhan Klnv, Gernot Koch,
Soon Koh, Steve Kolecki, Brett Koonce, Wojciech Koszek, Varun Koyyalagunta,
David Kravitz, Roland Kruse, Ed Lander, Steve Lang, Stephane Laurent,
Walter Lavino, Christian Leber, Igor Lesik, John Li, Eivind Liland, Charlie
Lind, Andrew Ling, Paul Liu, Derek Lockhart, Arthur Low, Stefan Ludwig, Dan
Lussier, Fred Ma, Duraid Madina, Mark Marshall, Jason McMullan, Wim
Michiels, Wai Sum Mong, Sean Moore, Dennis Muhlestein, John Murphy, Richard
Myers, Dimitris Nalbantis, Bob Newgard, Cong Van Nguyen, Paul Nitza, Pete
Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, David
Pierce, Dominic Plunkett, David Poole, Rich Porter, Niranjan Prabhu, Usha
Priyadharshini, Mark Jackson Pulver, Prateek Puri, Chris Randall, Frederic
Requin, Alberto Del Rio, Oleg Rodionov, Jan Egil Ruud, John Sanguinetti,
Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey Short, Rodney
Sinclair, Steven Slatter, Brian Small, Wilson Snyder, Alex Solomatnikov,
Art Stamness, John Stevenson, Todd Strader, John Stroebel, Emerson
Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu Takatsukasa, Peter
Tengstrand, Stefan Thiede, Gary Thomas, Kevin Thompson, Mike Thyer, Steve
Tong, Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters,
Thomas Watts, Eugene Weber, David Welch, Leon Wildman, Gerald Williams,
Trevor Williams, Jeff Winston, Joshua Wise, Clifford Wolf, Johan Wouters,
Ding Xiaoliang, Jie Xu, and Amir Yazdanbakhsh.
Thanks to them, and all those we've missed including above.
=head1 DISTRIBUTION
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0.
=head1 SEE ALSO
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>,
L<verilator_coverage>, L<verilator_profcfunc>, L<make>,
L<verilator --help> which is the source for this document,
+291
View File
@@ -0,0 +1,291 @@
: # -*-Mode: perl;-*- use perl, wherever it is
eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
######################################################################
#
# Copyright 2003-2015 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 program 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.
#
######################################################################
require 5.006_001;
use warnings;
BEGIN {
if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) {
# Magic to allow author testing of perl packages in local directory
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
}
}
use Getopt::Long;
use FindBin qw($RealBin $RealScript);
use IO::File;
use Pod::Usage;
use Cwd qw(abs_path getcwd);
use strict;
use vars qw ($Debug @Opt_Verilator_Sw);
#######################################################################
#######################################################################
# main
autoflush STDOUT 1;
autoflush STDERR 1;
$Debug = 0;
# No arguments can't do anything useful. Give help
if ($#ARGV < 0) {
pod2usage(-exitstatus=>2, -verbose=>0);
}
# We sneak a look at the flags so we can do some pre-environment checks
# All flags will hit verilator...
foreach my $sw (@ARGV) {
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
push @Opt_Verilator_Sw, $sw;
}
Getopt::Long::config ("no_auto_abbrev","pass_through");
if (! GetOptions (
# Major operating modes
"help" => \&usage,
"debug:s" => \&debug,
# "version!" => \&version, # Also passthru'ed
# Additional parameters
"<>" => sub {}, # Ignored
)) {
pod2usage(-exitstatus=>2, -verbose=>0);
}
# Normal, non gdb
run (verilator_coverage_bin()
." ".join(' ',@Opt_Verilator_Sw));
#----------------------------------------------------------------------
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
}
sub debug {
shift;
my $level = shift;
$Debug = $level||3;
}
#######################################################################
#######################################################################
# Builds
sub verilator_coverage_bin {
my $bin = "";
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
my $basename = ($ENV{VERILATOR_COVERAGE_BIN}
|| "verilator_coverage_bin_dbg");
if (defined($ENV{VERILATOR_ROOT})) {
my $dir = $ENV{VERILATOR_ROOT};
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
$bin = "$dir/bin/$basename";
} else {
$bin = "$dir/$basename"; # From pointing to kit directory
}
} else {
if (-x "$RealBin/$basename") {
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
} else {
$bin = $basename; # Find in PATH
}
# Note we don't look under bin/$basename which would be right if running
# in the kit dir. Running that would likely break, since
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
}
return $bin;
}
#######################################################################
#######################################################################
# Utilities
sub run {
# Run command, check errors
my $command = shift;
$! = undef; # Cleanup -x
print "\t$command\n" if $Debug>=3;
system($command);
my $status = $?;
if ($status) {
if ($! =~ /no such file or directory/i) {
warn "%Error: verilator_coverage: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
}
if ($Debug) { # For easy rerunning
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
warn "%Error: $command\n";
}
if ($status & 127) {
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
warn "%Error: Verilator_coverage internal fault, sorry.\n" if !$Debug;
} elsif (($status & 127) == 6) { # SIGABRT
warn "%Error: Verilator_coverage aborted.\n" if !$Debug;
} else {
warn "%Error: Verilator_coverage threw signal $status.\n" if !$Debug;
}
}
die "%Error: Command Failed $command\n";
}
}
#######################################################################
#######################################################################
package main;
__END__
=pod
=head1 NAME
verilator_coverage - Verilator coverage analyzer
=head1 SYNOPSIS
verilator_coverage --help
verilator_coverage --version
verilator_coverage --annotate <obj>
verilator_coverage -write merged.dat -read <datafiles>...
Verilator_coverage processes Verilator coverage reports.
With --anotate, it reads the specified data file and generates annotated
source code with coverage metrics annotated. If multiple coverage points
exist on the same line, additional lines will be inserted to report the
additional points.
Additional Verilog-standard arguments specify the search paths necessary to
find the source code that the coverage analysis was performed on.
To get correct coverage percentages, you may wish to read logs/coverage.pl
into Emacs and do a M-x keep-lines to include only those statistics of
interest.
For Verilog conditions that should never occur, you should add a $stop
statement. This will remove the coverage during the next build.
=head1 ARGUMENTS
=over 4
=item I<filename>
Specify input data file, may be repeated to read multiple inputs. If no
data file is specified, by default coverage.dat is read.
=item --annotate I<output_directory>
Sprcifies the directory name that source files with annotated coverage data
should be written to.
=item --annotate-all
Specifies all files should be shown. By default, only those source files
which have low coverage are written to the output directory.
=item --annotate-min I<count>
Specifies the minimum occurrence count that should be flagged if the
coverage point does not include a specified threshold. Defaults to 10.
=item --help
Displays this message and program version and exits.
=item --rank
Print an experimental report listing the relative importance of each test
in covering all of the coverage points. The report shows "Covered" which
indicates the number of points that test covers; a test is considered to
cover a point if it has a bucket count of at least 1. The "rank" column has
a higher number t indicate the test is more important, and rank 0 means the
test does not need to be run to cover the points. "RankPts" indicates the
number of coverage points this test will contribute to overall coverage if
all tests are run in the order of highest to lowest rank.
=item --unlink
When using --write to combine coverage data, unlink all input files after
the output has been created.
=item --version
Displays program version and exits.
=item --write I<filename>
Specifies the aggregate coverage results, summed across all the files,
should be written to the given filename. This is useful in scripts to
combine many sequential runs into one master coverage file.
=back
=head1 VERILOG ARGUMENTS
The following arguments are compatible with GCC, VCS and most Verilog
programs.
=over 4
=item +libext+I<ext>+I<ext>...
Defines the extensions for Verilog files.
=item +define+I<var>+I<value>
=item -DI<var>=I<value>
Defines the given variable.
=item +incdir+I<dir>
=item -II<dir>
Specifies a directory for finding include files.
=item -f I<file>
Specifies a file containing additional command line arguments.
=item -y I<dir>
Specifies a module search directory.
=back
=head1 DISTRIBUTION
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
C<verilator>
L<verilator_coverage --help> which is the source for this document.
=cut
######################################################################
+1 -1
View File
@@ -235,7 +235,7 @@ Do not show differences in line numbering.
The latest version is available from L<http://www.veripool.org/verilator>.
Copyright 2005-2013 by Wilson Snyder. This package is free software; you can
Copyright 2005-2015 by Wilson Snyder. This package is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+6 -2
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
# DESCRIPTION: Print include statements for each ARGV
#
# Copyright 2003-2013 by Wilson Snyder. This package is free software; you can
# Copyright 2003-2015 by Wilson Snyder. This package is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
######################################################################
@@ -12,5 +12,9 @@ require 5.005;
use warnings;
print "// DESCR"."IPTION: Generated by verilator_includer via makefile\n";
foreach my $param (@ARGV) {
print "#include \"$param\"\n"
if ($param =~ /^-D([^=]+)=(.*)/) {
print "#define $1 $2\n"
} else {
print "#include \"$param\"\n"
}
}
+16 -2
View File
@@ -118,6 +118,18 @@ sub profcfunc {
$groups{type}{"Common code under $design"} += $pct;
$groups{design}{$design} += $pct;
$groups{module}{$design." common code"} += $pct;
} elsif ($func =~ /^VL_[A-Z0-9_]+/
|| $func =~ /^_?vl_[a-zA-Z0-9_]+/
|| $func =~ /^verilated/i) {
$vfunc = sprintf("VLib %s", $func);
$groups{type}{'VLib'} += $pct;
$groups{design}{'VLib'} += $pct;
$groups{module}{'VLib'} += $pct;
} elsif ($func =~ /^_mcount_private/) {
$vfunc = sprintf("Prof %s", $func);
$groups{type}{'Prof'} += $pct;
$groups{design}{'Prof'} += $pct;
$groups{module}{'Prof'} += $pct;
} else {
$vfunc = sprintf("C++ %s", $func);
$groups{type}{'C++'} += $pct;
@@ -129,7 +141,7 @@ sub profcfunc {
}
foreach my $type qw(type design module) {
foreach my $type (qw(type design module)) {
my $missing = 100;
foreach (sort (keys %{$groups{$type}})) {
$missing -= $groups{$type}{$_};
@@ -150,8 +162,10 @@ sub profcfunc {
print("Verilog code profile:\n");
print(" These are split into three categories:\n");
print(" C++: Time in non-Verilated C++ code\n");
print(" Prof: Time in profile overhead\n");
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
print(" VLib: Time in Verilated common libraries, called by the Verilated code\n");
print("\n");
print(" % cumulative self \n");
@@ -208,7 +222,7 @@ Displays this message and program version and exits.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2007-2013 by Wilson Snyder. Verilator is free software; you can
Copyright 2007-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+33 -12
View File
@@ -1,12 +1,12 @@
# DESCRIPTION: Process this file with autoconf to produce a configure script.
#
# Copyright 2003-2013 by Wilson Snyder. Verilator is free software; you can
# Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.847 2013-05-11])
AC_INIT([Verilator],[3.872 2015-04-05])
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
@@ -107,30 +107,51 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
CXXFLAGS="$CXXFLAGS $1 -Werror"
AC_MSG_CHECKING([whether $CXX accepts $1])
CXXFLAGS="$CXXFLAGS $2 -Werror"
AC_MSG_CHECKING([whether $CXX accepts $2])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],[])],
[_my_result=yes],
[_my_result=yes
if test -s conftest.err; then
if grep -e "$2" conftest.err >/dev/null; then
_my_result=no
fi
fi],
[_my_result=no])
AC_MSG_RESULT($_my_result)
if test "$_my_result" = "yes" ; then
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1"
$1="$$1 $2"
fi
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
])# _MY_CXX_CHECK_OPT
# Flags for compiling Verilator internals including parser
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
AC_SUBST(CFG_CXXFLAGS_SRC)
# Flags for compiling Verilator parser
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-unused)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-parentheses-equality)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-null-conversion)
AC_SUBST(CFG_CXXFLAGS_PARSER)
# Flags for Verilated makefile
# For example, -Wno-div-by-zero isn't in 4.1.2
_MY_CXX_CHECK_OPT(-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-parentheses-equality)
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
# without this flag, even though there's a conditional to prevent the divide.
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
_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)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-sign-compare)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-but-set-variable)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-variable)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-fbracket-depth=4096)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Qunused-arguments)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Checks for library functions.
-2
View File
@@ -635,9 +635,7 @@ INPUT = doxygen-mainpage \
test_c \
test_regress \
test_sc \
test_sp \
test_v \
test_vcs \
test_verilated
# This tag can be used to specify the character encoding of the source files
+115 -41
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -74,6 +74,9 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
Verilated::gotFinish(true);
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
Verilated::flushCall();
VL_PRINTF("Aborting...\n");
Verilated::flushCall(); // Second flush in case VL_PRINTF does something needing a flush
abort();
}
#endif
@@ -207,7 +210,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
vluint32_t vn[VL_MULS_MAX_WORDS+1]; // v normalized
// Zero for ease of debugging and to save having to zero for shifts
for (int i=0; i<words; i++) { un[i]=vn[i]=0; }
// Note +1 as loop will use extra word
for (int i=0; i<words+1; i++) { un[i]=vn[i]=0; }
// Algorithm requires divisor MSB to be set
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set
@@ -339,6 +343,12 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += cstrp;
break;
}
case '@': { // Verilog/C++ string
va_arg(ap, int); // # bits is ignored
const string* cstrp = va_arg(ap, const string*);
output += *cstrp;
break;
}
case 'e':
case 'f':
case 'g': {
@@ -466,7 +476,7 @@ static inline void _vl_vsss_advance(FILE* fp, int& floc) {
if (fp) fgetc(fp);
else floc -= 8;
}
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const string& fstr) {
// Get a character without advancing
if (fp) {
int data = fgetc(fp);
@@ -476,23 +486,26 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
} else {
if (floc < 0) return EOF;
floc = floc & ~7; // Align to closest character
int data = (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
return data;
if (fromp == NULL) {
return fstr[fstr.length()-1 - (floc>>3)];
} else {
return (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
}
}
}
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp) {
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, const string& fstr) {
while (1) {
int c = _vl_vsss_peek(fp, floc, fromp);
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c==EOF || !isspace(c)) return;
_vl_vsss_advance(fp, floc);
}
}
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp,
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const string& fstr,
char* tmpp, const char* acceptp) {
// Read into tmp, consisting of characters from acceptp list
char* cp = tmpp;
while (1) {
int c = _vl_vsss_peek(fp, floc, fromp);
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c==EOF || isspace(c)) break;
if (acceptp!=NULL // String - allow anything
&& NULL==strchr(acceptp, c)) break;
@@ -537,6 +550,7 @@ static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const
IData _vl_vsscanf(FILE* fp, // If a fscanf
int fbits, WDataInP fromp, // Else if a sscanf
const string& fstr, // if a sscanf to string
const char* formatp, va_list ap) {
// Read a Verilog $sscanf/$fscanf style format into the output list
// The format must be pre-processed (and lower cased) by Verilator
@@ -547,15 +561,15 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
bool inPct = false;
const char* pos = formatp;
for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) {
//VL_PRINTF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc, _vl_vsss_peek(fp,floc,fromp));
//VL_PRINTF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc, _vl_vsss_peek(fp,floc,fromp,fstr));
if (!inPct && pos[0]=='%') {
inPct = true;
} else if (!inPct && isspace(pos[0])) { // Format spaces
while (isspace(pos[1])) pos++;
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_skipspace(fp,floc,fromp,fstr);
} else if (!inPct) { // Expected Format
_vl_vsss_skipspace(fp,floc,fromp);
int c = _vl_vsss_peek(fp,floc,fromp);
_vl_vsss_skipspace(fp,floc,fromp,fstr);
int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c != pos[0]) goto done;
else _vl_vsss_advance(fp,floc);
} else { // Format character
@@ -564,7 +578,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
char fmt = pos[0];
switch (fmt) {
case '%': {
int c = _vl_vsss_peek(fp,floc,fromp);
int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c != '%') goto done;
else _vl_vsss_advance(fp,floc);
break;
@@ -581,15 +595,15 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = 0;
switch (fmt) {
case 'c': {
int c = _vl_vsss_peek(fp,floc,fromp);
int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c==EOF) goto done;
else _vl_vsss_advance(fp,floc);
owp[0] = c;
break;
}
case 's': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, NULL);
if (!tmp[0]) goto done;
int pos = ((int)strlen(tmp))-1;
int lsb = 0;
@@ -599,8 +613,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break;
}
case 'd': { // Signed decimal
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
vlsint64_t ld;
sscanf(tmp,"%30" VL_PRI64 "d",&ld);
@@ -610,8 +624,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
case 'f':
case 'e':
case 'g': { // Real number
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE");
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done;
union { double r; vlsint64_t ld; } u;
u.r = strtod(tmp, NULL);
@@ -620,8 +634,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
}
case 't': // FALLTHRU // Time
case 'u': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_");
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
QData ld;
sscanf(tmp,"%30" VL_PRI64 "u",&ld);
@@ -629,22 +643,22 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break;
}
case 'b': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "01xXzZ?_");
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "01xXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_based(owp,obits, 1, tmp, 0, (int)strlen(tmp));
break;
}
case 'o': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xXzZ?_");
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "01234567xXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_based(owp,obits, 3, tmp, 0, (int)strlen(tmp));
break;
}
case 'x': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefABCDEFxXzZ?_");
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789abcdefABCDEFxXzZ?_");
if (!tmp[0]) goto done;
_vl_vsss_based(owp,obits, 4, tmp, 0, (int)strlen(tmp));
break;
@@ -758,6 +772,50 @@ void VL_FCLOSE_I(IData fdi) {
VerilatedImp::fdDelete(fdi);
}
void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
_vl_vsformat(output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
}
void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
_vl_vsformat(output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
}
void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
_vl_vsformat(output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
}
void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
_vl_vsformat(output, formatp, ap);
va_end(ap);
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
}
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
@@ -769,6 +827,15 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
_VL_STRING_TO_VINT(obits, destp, (int)output.length(), output.c_str());
}
void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
if (obits_ignored) {}
output = "";
va_list ap;
va_start(ap,formatp);
_vl_vsformat(output, formatp, ap);
va_end(ap);
}
string VL_SFORMATF_NX(const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
output = "";
@@ -812,7 +879,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(fp, 0, NULL, formatp, ap);
IData got = _vl_vsscanf(fp, 0, NULL, "", formatp, ap);
va_end(ap);
return got;
}
@@ -822,7 +889,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
IData got = _vl_vsscanf(NULL, lbits, fnw, "", formatp, ap);
va_end(ap);
return got;
}
@@ -831,14 +898,21 @@ IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
IData got = _vl_vsscanf(NULL, lbits, fnw, "", formatp, ap);
va_end(ap);
return got;
}
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, lbits, lwp, formatp, ap);
IData got = _vl_vsscanf(NULL, lbits, lwp, "", formatp, ap);
va_end(ap);
return got;
}
IData VL_SSCANF_INX(int, const string& ld, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, ld.length()*8, NULL, ld, formatp, ap);
va_end(ap);
return got;
}
@@ -1114,7 +1188,7 @@ vluint32_t VerilatedVar::entSize() const {
case VLVT_UINT16: size=sizeof(SData); break;
case VLVT_UINT32: size=sizeof(IData); break;
case VLVT_UINT64: size=sizeof(QData); break;
case VLVT_WDATA: size=VL_WORDS_I(range().bits())*sizeof(IData); break;
case VLVT_WDATA: size=VL_WORDS_I(range().elements())*sizeof(IData); break;
default: size=0; break;
}
return size;
@@ -1186,11 +1260,11 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
int msb = va_arg(ap,int);
int lsb = va_arg(ap,int);
if (i==0) {
var.m_range.m_lhs = msb;
var.m_range.m_rhs = lsb;
var.m_range.m_left = msb;
var.m_range.m_right = lsb;
} else if (i==1) {
var.m_array.m_lhs = msb;
var.m_array.m_rhs = lsb;
var.m_array.m_left = msb;
var.m_array.m_right = lsb;
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
@@ -1240,9 +1314,9 @@ void VerilatedScope::scopeDump() const {
m_callbacksp[i], VerilatedImp::exportName(i));
}
}
if (varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp()->begin();
it != varsp()->end(); ++it) {
if (VerilatedVarNameMap* varsp = this->varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp->begin();
it != varsp->end(); ++it) {
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
}
}
+181 -20
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -145,7 +145,7 @@ public:
# define VL_CELL(instname,type) ///< Declare a cell, ala SP_CELL
/// Declare a module, ala SC_MODULE
# define VL_MODULE(modname) struct modname : public VerilatedModule
# define VL_MODULE(modname) class modname : public VerilatedModule
/// Constructor, ala SC_CTOR
# define VL_CTOR(modname) modname(const char* __VCname="")
@@ -216,9 +216,8 @@ public: // But internals only - called from VerilatedModule's
//===========================================================================
/// Verilator global static information class
struct Verilated {
class Verilated {
// MEMBERS
private:
// Slow path variables
static VerilatedVoidCb s_flushCb; ///< Flush callback function
@@ -376,6 +375,10 @@ extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...);
extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs);
@@ -871,7 +874,7 @@ static inline WDataOutP VL_OR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP r
}
// EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits;
static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp,WDataInP rwp){
IData od;
IData od = 0;
for (int i=0; (i < words); i++) od |= (lwp[i] ^ rwp[i]);
return(od);
}
@@ -1129,7 +1132,9 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
int words = VL_WORDS_I(lbits);
IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[words-1]);
// cppcheck-suppress variableScope
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
@@ -1148,7 +1153,9 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
int words = VL_WORDS_I(lbits);
IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[words-1]);
// cppcheck-suppress variableScope
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
@@ -1164,7 +1171,10 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
}
}
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (VL_UNLIKELY(lhs==0)) return 0;
IData power = lhs;
IData out = 1;
@@ -1174,10 +1184,8 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
}
return out;
}
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (VL_UNLIKELY(lhs==0)) return 0;
QData power = lhs;
QData out = VL_ULL(1);
@@ -1188,6 +1196,36 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
return out;
}
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_III(obits, obits, rbits, lhs, rhs);
}
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_QQQ(obits, obits, rbits, lhs, rhs);
}
//===================================================================
// Concat/replication
@@ -1328,6 +1366,120 @@ static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP ow
return(owp);
}
// Left stream operator. Output will always be clean. LHS and RHS must be clean.
// Special "fast" versions for slice sizes that are a power of 2. These use
// shifts and masks to execute faster than the slower for-loop approach where a
// subset of bits is copied in during each iteration.
static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_log2) {
// Pre-shift bits in most-significant slice:
//
// If lbits is not a multiple of the slice size (i.e., lbits % rd != 0),
// then we end up with a "gap" in our reversed result. For example, if we
// have a 5-bit Verlilog signal (lbits=5) in an 8-bit C data type:
//
// ld = ---43210
//
// (where numbers are the Verilog signal bit numbers and '-' is an unused bit).
// Executing the switch statement below with a slice size of two (rd=2,
// rd_log2=1) produces:
//
// ret = 1032-400
//
// Pre-shifting the bits in the most-significant slice allows us to avoid
// this gap in the shuffled data:
//
// ld_adjusted = --4-3210
// ret = 10324---
IData ret = ld;
if (rd_log2) {
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2); // max multiple of rd <= lbits
vluint32_t lbitsRem = lbits - lbitsFloor; // number of bits in most-sig slice (MSS)
IData msbMask = VL_MASK_I(lbitsRem) << lbitsFloor; // mask to sel only bits in MSS
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_UL(1) << rd_log2) - lbitsRem));
}
switch (rd_log2) {
case 0:
ret = ((ret >> 1) & VL_UL(0x55555555)) | ((ret & VL_UL(0x55555555)) << 1); // FALLTHRU
case 1:
ret = ((ret >> 2) & VL_UL(0x33333333)) | ((ret & VL_UL(0x33333333)) << 2); // FALLTHRU
case 2:
ret = ((ret >> 4) & VL_UL(0x0f0f0f0f)) | ((ret & VL_UL(0x0f0f0f0f)) << 4); // FALLTHRU
case 3:
ret = ((ret >> 8) & VL_UL(0x00ff00ff)) | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
case 4:
ret = ((ret >> 16) | (ret << 16));
}
return ret >> (VL_WORDSIZE - lbits);
}
static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_log2) {
// Pre-shift bits in most-significant slice (see comment in VL_STREAML_FAST_III)
QData ret = ld;
if (rd_log2) {
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2);
vluint32_t lbitsRem = lbits - lbitsFloor;
QData msbMask = VL_MASK_Q(lbitsRem) << lbitsFloor;
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_ULL(1) << rd_log2) - lbitsRem));
}
switch (rd_log2) {
case 0:
ret = ((ret >> 1) & VL_ULL(0x5555555555555555)) | ((ret & VL_ULL(0x5555555555555555)) << 1); // FALLTHRU
case 1:
ret = ((ret >> 2) & VL_ULL(0x3333333333333333)) | ((ret & VL_ULL(0x3333333333333333)) << 2); // FALLTHRU
case 2:
ret = ((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4); // FALLTHRU
case 3:
ret = ((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8); // FALLTHRU
case 4:
ret = ((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16); // FALLTHRU
case 5:
ret = ((ret >> 32) | (ret << 32));
}
return ret >> (VL_QUADSIZE - lbits);
}
// Regular "slow" streaming operators
static inline IData VL_STREAML_III(int, int lbits, int, IData ld, IData rd) {
IData ret = 0;
// Slice size should never exceed the lhs width
IData mask = VL_MASK_I(rd);
for (int istart=0; istart<lbits; istart+=rd) {
int ostart=lbits-rd-istart;
ostart = ostart > 0 ? ostart : 0;
ret |= ((ld >> istart) & mask) << ostart;
}
return ret;
}
static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) {
QData ret = 0;
// Slice size should never exceed the lhs width
QData mask = VL_MASK_Q(rd);
for (int istart=0; istart<lbits; istart+=rd) {
int ostart=lbits-rd-istart;
ostart = ostart > 0 ? ostart : 0;
ret |= ((ld >> istart) & mask) << ostart;
}
return ret;
}
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp, IData rd) {
VL_ZERO_RESET_W(lbits, owp);
// Slice size should never exceed the lhs width
int ssize = (rd < (IData)lbits) ? rd : ((IData)lbits);
for (int istart=0; istart<lbits; istart+=rd) {
int ostart=lbits-rd-istart;
ostart = ostart > 0 ? ostart : 0;
for (int sbit=0; sbit<ssize && sbit<lbits-istart; sbit++) {
// Extract a single bit from lwp and shift it to the correct
// location for owp.
WData bit= ((lwp[VL_BITWORD_I(istart+sbit)] >> VL_BITBIT_I(istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
owp[VL_BITWORD_I(ostart+sbit)] |= bit;
}
}
return owp;
}
// Because concats are common and wide, it's valuable to always have a clean output.
// Thus we specify inputs must be clean, so we don't need to clean the output.
// Note the bit shifts are always constants, so the adds in these constify out.
@@ -1414,7 +1566,7 @@ static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or
static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
int word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_I(rd);
if ((int)rd >= obits) {
if (rd >= (IData)obits) { // rd may be huge with MSB set
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
} else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
for (int i=0; i < word_shift; i++) owp[i] = 0;
@@ -1432,7 +1584,7 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
int word_shift = VL_BITWORD_I(rd); // Maybe 0
int bit_shift = VL_BITBIT_I(rd);
if ((int)rd >= obits) {
if (rd >= (IData)obits) { // rd may be huge with MSB set
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift);
@@ -1456,29 +1608,37 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
}
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
static inline IData VL_SHIFTRS_III(int obits, int, int, IData lhs, IData rhs) {
static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData rhs) {
// Note the C standard does not specify the >> operator as a arithmetic shift!
IData sign = -(lhs >> (obits-1)); // ffff_ffff if negative
IData signext = ~(VL_MASK_I(obits) >> rhs); // One with bits where we've shifted "past"
// IEEE says signed if output signed, but bit position from lbits;
// must use lbits for sign; lbits might != obits,
// an EXTEND(SHIFTRS(...)) can became a SHIFTRS(...) within same 32/64 bit word length
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past"
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
}
static inline QData VL_SHIFTRS_QQI(int obits, int, int, QData lhs, IData rhs) {
QData sign = -(lhs >> (obits-1));
QData signext = ~(VL_MASK_Q(obits) >> rhs);
static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) {
QData sign = -(lhs >> (lbits-1));
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
}
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) {
return (IData)(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
}
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) {
int word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_I(rd);
int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(obits,lwp[lmsw]);
if ((int)rd >= obits) {
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
if (rd >= (IData)obits) { // Shifting past end, sign in all of lbits
for (int i=0; i <= lmsw; i++) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift);
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} else {
int loffset = rd & VL_SIZEBITS_I;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
@@ -1493,6 +1653,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP
}
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
}
return(owp);
}
@@ -1508,7 +1669,7 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) {
int word = VL_BITWORD_I(rd);
if (VL_UNLIKELY((int)rd>lbits)) {
if (VL_UNLIKELY(rd>(IData)lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
// We return all 1's as that's more likely to find bugs (?) than 0's.
} else {
+9 -6
View File
@@ -2,7 +2,7 @@
######################################################################
# DESCRIPTION: Makefile commands for all verilated target files
#
# Copyright 2003-2013 by Wilson Snyder. Verilator is free software; you can
# Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
######################################################################
@@ -23,7 +23,9 @@ CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
# Programs
SP_PREPROC = sp_preproc
SP_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
SP_INCLUDER = $(VERILATOR_INCLUDER)
VERILATOR_COVERAGE = $(PERL) $(VERILATOR_ROOT)/bin/verilator_coverage
VERILATOR_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
######################################################################
# Make checks
@@ -43,14 +45,14 @@ VK_CPPFLAGS_ALWAYS += \
-DVL_PRINTF=printf \
-DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \
$(CFG_CXXFLAGS_NO_UNUSED) \
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
VK_CPPFLAGS_WALL += -Wall \
$(CFG_CXXFLAGS_NO_UNUSED) \
-Werror
endif
CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL)
CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
VPATH += ..
VPATH += $(VERILATOR_ROOT)/include
@@ -157,9 +159,9 @@ ifneq ($(VM_PARALLEL_BUILDS),1)
VK_OBJS += $(VM_PREFIX)__ALLcls.o $(VM_PREFIX)__ALLsup.o
all_cpp: $(VM_PREFIX)__ALLcls.cpp $(VM_PREFIX)__ALLsup.cpp
$(VM_PREFIX)__ALLcls.cpp: $(VK_CLASSES_CPP)
$(SP_INCLUDER) $^ > $@
$(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
$(VM_PREFIX)__ALLsup.cpp: $(VK_SUPPORT_CPP)
$(SP_INCLUDER) $^ > $@
$(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
else
#Slow way of building... Each .cpp file by itself
VK_OBJS += $(addsuffix .o, $(VM_CLASSES) $(VM_SUPPORT))
@@ -195,6 +197,7 @@ debug-make::
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
@echo CPPFLAGS: $(CPPFLAGS)
@echo
######################################################################
+1 -1
View File
@@ -4,7 +4,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+452
View File
@@ -0,0 +1,452 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2015 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 Verilator coverage analysis
///
//=============================================================================
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_cov.h"
#include "verilated_cov_key.h"
#include <map>
#include <deque>
#include <fstream>
//=============================================================================
// VerilatedCovImpBase
/// Implementation base class for constants
struct VerilatedCovImpBase {
// TYPES
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
};
//=============================================================================
// VerilatedCovImpItem
/// Implementation class for a VerilatedCov item
class VerilatedCovImpItem : VerilatedCovImpBase {
public: // But only local to this file
// MEMBERS
int m_keys[MAX_KEYS]; ///< Key
int m_vals[MAX_KEYS]; ///< Value for specified key
// CONSTRUCTORS
// Derived classes should call zero() in their constructor
VerilatedCovImpItem() {
for (int i=0; i<MAX_KEYS; i++) {
m_keys[i]=KEY_UNDEF;
m_vals[i]=0;
}
}
virtual ~VerilatedCovImpItem() {}
virtual vluint64_t count() const = 0;
virtual void zero() const = 0;
};
//=============================================================================
/// VerilatedCoverItem templated for a specific class
/// Creates a new coverage item for the specified type.
/// This isn't in the header file for auto-magic conversion because it
/// inlines to too much code and makes compilation too slow.
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
private:
// MEMBERS
T* m_countp; ///< Count value
public:
// METHODS
virtual vluint64_t count() const { return *m_countp; }
virtual void zero() const { *m_countp = 0; }
// CONSTRUCTORS
VerilatedCoverItemSpec(T* countp) : m_countp(countp) { zero(); }
virtual ~VerilatedCoverItemSpec() {}
};
//=============================================================================
// VerilatedCovImp
/// Implementation class for VerilatedCov. See that class for public method information.
/// All value and keys are indexed into a unique number. Thus we can greatly reduce
/// the storage requirements for otherwise identical keys.
class VerilatedCovImp : VerilatedCovImpBase {
private:
// TYPES
typedef map<string,int> ValueIndexMap;
typedef map<int,string> IndexValueMap;
typedef deque<VerilatedCovImpItem*> ItemList;
private:
// MEMBERS
ValueIndexMap m_valueIndexes; ///< For each key/value a unique arbitrary index value
IndexValueMap m_indexValues; ///< For each key/value a unique arbitrary index value
ItemList m_items; ///< List of all items
VerilatedCovImpItem* m_insertp; ///< Item about to insert
const char* m_insertFilenamep; ///< Filename about to insert
int m_insertLineno; ///< Line number about to insert
// CONSTRUCTORS
VerilatedCovImp() {
m_insertp = NULL;
m_insertFilenamep = NULL;
m_insertLineno = 0;
}
public:
~VerilatedCovImp() { clear(); }
static VerilatedCovImp& imp() {
static VerilatedCovImp s_singleton;
return s_singleton;
}
private:
// PRIVATE METHODS
int valueIndex(const string& value) {
static int nextIndex = KEY_UNDEF+1;
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
if (iter != m_valueIndexes.end()) return iter->second;
nextIndex++; assert(nextIndex>0);
m_valueIndexes.insert(make_pair(value, nextIndex));
m_indexValues.insert(make_pair(nextIndex, value));
return nextIndex;
}
string dequote(const string& text) {
// Quote any special characters
string rtn;
for (const char* pos = text.c_str(); *pos; pos++) {
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
char hex[10]; sprintf(hex,"%%%02X",pos[0]);
rtn += hex;
} else {
rtn += *pos;
}
}
return rtn;
}
bool legalKey(const string& key) {
// Because we compress long keys to a single letter, and
// don't want applications to either get confused if they use
// a letter differently, nor want them to rely on our compression...
// (Considered using numeric keys, but will remain back compatible.)
if (key.length()<2) return false;
if (key.length()==2 && isdigit(key[1])) return false;
return true;
}
string keyValueFormatter (const string& key, const string& value) {
string name;
if (key.length()==1 && isalpha(key[0])) {
name += string("\001")+key;
} else {
name += string("\001")+dequote(key);
}
name += string("\002")+dequote(value);
return name;
}
string combineHier (const string& old, const string& add) {
// (foo.a.x, foo.b.x) => foo.*.x
// (foo.a.x, foo.b.y) => foo.*
// (foo.a.x, foo.b) => foo.*
if (old == add) return add;
if (old == "") return add;
if (add == "") return old;
const char* a = old.c_str();
const char* b = add.c_str();
// Scan forward to first mismatch
const char* apre = a;
const char* bpre = b;
while (*apre == *bpre) { apre++; bpre++; }
// We used to backup and split on only .'s but it seems better to be verbose
// and not assume . is the separator
string prefix = string(a,apre-a);
// Scan backward to last mismatch
const char* apost = a+strlen(a)-1;
const char* bpost = b+strlen(b)-1;
while (*apost == *bpost
&& apost>apre && bpost>bpre) { apost--; bpost--; }
// Forward to . so we have a whole word
string suffix = *bpost ? string(bpost+1) : "";
string out = prefix+"*"+suffix;
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
return out;
}
bool itemMatchesString(VerilatedCovImpItem* itemp, const string& match) {
for (int i=0; i<MAX_KEYS; i++) {
if (itemp->m_keys[i] != KEY_UNDEF) {
// We don't compare keys, only values
string val = m_indexValues[itemp->m_vals[i]];
if (string::npos != val.find(match)) { // Found
return true;
}
}
}
return false;
}
void selftest() {
// Little selftest
if (combineHier ("a.b.c","a.b.c") !="a.b.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("a.b.c","a.b") !="a.b*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("a.x.c","a.y.c") !="a.*.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("a.z.z.z.c","a.b.c") !="a.*.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("z","a") !="*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("q.a","q.b") !="q.*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("q.za","q.zb") !="q.z*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
if (combineHier ("1.2.3.a","9.8.7.a") !="*.a") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
}
public:
// PUBLIC METHODS
void clear() {
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
delete itemp;
}
m_items.clear();
m_indexValues.clear();
m_valueIndexes.clear();
}
void clearNonMatch (const char* matchp) {
if (matchp && matchp[0]) {
ItemList newlist;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
if (!itemMatchesString(itemp, matchp)) {
delete itemp;
} else {
newlist.push_back(itemp);
}
}
m_items = newlist;
}
}
void zero() {
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
(*it)->zero();
}
}
// We assume there's always call to i/f/p in that order
void inserti (VerilatedCovImpItem* itemp) {
assert(!m_insertp);
m_insertp = itemp;
}
void insertf (const char* filenamep, int lineno) {
m_insertFilenamep = filenamep;
m_insertLineno = lineno;
}
void insertp (const char* ckeyps[MAX_KEYS],
const char* valps[MAX_KEYS]) {
assert(m_insertp);
// First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
VlCovCvtToCStr linestrp (m_insertLineno);
ckeyps[1]="lineno"; valps[1]=linestrp;
// Default page if not specified
const char* fnstartp = m_insertFilenamep;
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1;
const char* fnendp = fnstartp;
while (*fnendp && *fnendp!='.') fnendp++;
string page_default = "sp_user/"+string(fnstartp,fnendp-fnstartp);
ckeyps[2]="page"; valps[2]=page_default.c_str();
// Keys -> strings
string keys[MAX_KEYS];
for (int i=0; i<MAX_KEYS; i++) {
if (ckeyps[i] && ckeyps[i][0]) {
keys[i] = ckeyps[i];
}
}
// Ignore empty keys
for (int i=0; i<MAX_KEYS; i++) {
if (keys[i]!="") {
for (int j=i+1; j<MAX_KEYS; j++) {
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
keys[i] = "";
break;
}
}
}
}
// Insert the values
int addKeynum=0;
for (int i=0; i<MAX_KEYS; i++) {
const string key = keys[i];
if (keys[i]!="") {
const string val = valps[i];
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
m_insertp->m_keys[addKeynum] = valueIndex(key);
m_insertp->m_vals[addKeynum] = valueIndex(val);
addKeynum++;
if (!legalKey(key)) {
string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
vl_fatal("",0,"",msg.c_str());
}
}
}
m_items.push_back(m_insertp);
// Prepare for next
m_insertp = NULL;
}
void write (const char* filename) {
#ifndef VM_COVERAGE
vl_fatal("",0,"","%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
#endif
selftest();
ofstream os (filename);
if (os.fail()) {
string msg = (string)"%Error: Can't write '"+filename+"'";
vl_fatal("",0,"",msg.c_str());
return;
}
os << "# SystemC::Coverage-3\n";
// Build list of events; totalize if collapsing hierarchy
typedef map<string,pair<string,vluint64_t> > EventMap;
EventMap eventCounts;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
string name;
string hier;
bool per_instance = false;
for (int i=0; i<MAX_KEYS; i++) {
if (itemp->m_keys[i] != KEY_UNDEF) {
string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
string val = m_indexValues[itemp->m_vals[i]];
if (key == VL_CIK_PER_INSTANCE) {
if (val != "0") per_instance = true;
}
if (key == VL_CIK_HIER) {
hier = val;
} else {
// Print it
name += keyValueFormatter(key,val);
}
}
}
if (per_instance) { // Not collapsing hierarchies
name += keyValueFormatter(VL_CIK_HIER,hier);
hier = "";
}
// Group versus point labels don't matter here, downstream
// deals with it. Seems bad for sizing though and doesn't
// allow easy addition of new group codes (would be
// inefficient)
// Find or insert the named event
EventMap::iterator cit = eventCounts.find(name);
if (cit != eventCounts.end()) {
const string& oldhier = cit->second.first;
cit->second.second += itemp->count();
cit->second.first = combineHier(oldhier, hier);
} else {
eventCounts.insert(make_pair(name, make_pair(hier,itemp->count())));
}
}
// Output body
for (EventMap::iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
os<<"C '"<<dec;
os<<it->first;
if (it->second.first != "") os<<keyValueFormatter(VL_CIK_HIER,it->second.first);
os<<"' "<<it->second.second;
os<<endl;
}
}
};
//=============================================================================
// VerilatedCov
void VerilatedCov::clear() {
VerilatedCovImp::imp().clear();
}
void VerilatedCov::clearNonMatch (const char* matchp) {
VerilatedCovImp::imp().clearNonMatch(matchp);
}
void VerilatedCov::zero() {
VerilatedCovImp::imp().zero();
}
void VerilatedCov::write (const char* filenamep) {
VerilatedCovImp::imp().write(filenamep);
}
void VerilatedCov::_inserti (vluint32_t* itemp) {
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint32_t>(itemp));
}
void VerilatedCov::_inserti (vluint64_t* itemp) {
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp));
}
void VerilatedCov::_insertf (const char* filename, int lineno) {
VerilatedCovImp::imp().insertf(filename,lineno);
}
#define K(n) const char* key ## n
#define A(n) const char* key ## n, const char* val ## n // Argument list
#define C(n) key ## n, val ## n // Calling argument list
#define N(n) "","" // Null argument list
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19),
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) {
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
= {NULL,NULL,NULL, // filename,lineno,page
key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,
key10,key11,key12,key13,key14,key15,key16,key17,key18,key19,
key20,key21,key22,key23,key24,key25,key26,key27,key28,key29};
const char* valps[VerilatedCovImpBase::MAX_KEYS]
= {NULL,NULL,NULL, // filename,lineno,page
val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,
val10,val11,val12,val13,val14,val15,val16,val17,val18,val19,
val20,val21,val22,val23,val24,val25,val26,val27,val28,val29};
VerilatedCovImp::imp().insertp(keyps, valps);
}
// And versions with fewer arguments (oh for a language with named parameters!)
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) {
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
}
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)) {
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
}
// Backward compatibility for Verilator
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
K(4),const string& val4, A(5),A(6)) {
_insertp(C(0),C(1),
key2,VlCovCvtToCStr(val2), key3,VlCovCvtToCStr(val3), key4, val4.c_str(),
C(5),C(6),N(7),N(8),N(9),
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
}
#undef A
#undef C
#undef N
#undef K
+144
View File
@@ -0,0 +1,144 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2015 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 Coverage analysis support
///
//=============================================================================
#ifndef _VERILATED_COV_H_
#define _VERILATED_COV_H_ 1
#include "verilatedos.h"
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
//=============================================================================
/// Conditionally compile coverage code
#ifdef VM_COVERAGE
# define VL_IF_COVER(stmts) do { stmts ; } while(0)
#else
# define VL_IF_COVER(stmts) do { if(0) { stmts ; } } while(0)
#endif
//=============================================================================
/// Insert a item for coverage analysis.
/// The first argument is a pointer to the count to be dumped.
/// The remaining arguments occur in pairs: A string key, and a value.
/// The value may be a string, or another type which will be auto-converted to a string.
///
/// Some typical keys:
/// filename File the recording occurs in. Defaults to __FILE__
/// lineno Line number the recording occurs in. Defaults to __LINE__
/// column Column number (or occurrence# for dup file/lines). Defaults to undef.
/// hier Hierarchical name. Defaults to name()
/// type Type of coverage. Defaults to "user"
/// Other types are 'block', 'fsm', 'toggle'.
/// comment Description of the coverage event. Should be set by the user.
/// Comments for type==block: 'if', 'else', 'elsif', 'case'
/// thresh Threshold to consider fully covered.
/// If unspecified, downstream tools will determine it.
///
/// Examples:
///
/// vluint32_t m_cases[10];
/// constructor {
/// for (int i=0; i<10; i++) { m_cases[i]=0; }
/// }
/// for (int i=0; i<10; i++) {
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
/// }
#define VL_COVER_INSERT(countp,args...) \
VL_IF_COVER(VerilatedCov::_inserti(countp); \
VerilatedCov::_insertf(__FILE__,__LINE__); \
VerilatedCov::_insertp("hier", name(), args))
//=============================================================================
/// Convert VL_COVER_INSERT value arguments to strings
template< class T> std::string vlCovCvtToStr (const T& t) {
ostringstream os; os<<t; return os.str();
}
/// Usage: something(VlCovCvtToCStr(i))
/// Note the pointer will only be valid for as long as the object remains
/// in scope!
struct VlCovCvtToCStr {
string m_str;
// Casters
template< class T> VlCovCvtToCStr (const T& t) {
ostringstream os; os<<t; m_str=os.str();
}
~VlCovCvtToCStr() {}
operator const char* () const { return m_str.c_str(); };
};
//=============================================================================
// VerilatedCov
/// Verilator coverage global class
////
/// Global class with methods affecting all coverage data.
class VerilatedCov {
public:
// GLOBAL METHODS
/// Return default filename
static const char* defaultFilename() { return "coverage.dat"; }
/// Write all coverage data to a file
static void write (const char* filenamep = defaultFilename());
/// Insert a coverage item
/// We accept from 1-30 key/value pairs, all as strings.
/// Call _insert1, followed by _insert2 and _insert3
/// Do not call directly; use VL_COVER_INSERT or higher level macros instead
// _insert1: Remember item pointer with count. (Not const, as may add zeroing function)
static void _inserti (vluint32_t* itemp);
static void _inserti (vluint64_t* itemp);
// _insert2: Set default filename and line number
static void _insertf (const char* filename, int lineno);
// _insert3: Set parameters
// We could have just the maximum argument version, but this compiles
// much slower (nearly 2x) than having smaller versions also. However
// there's not much more gain in having a version for each number of args.
#define K(n) const char* key ## n
#define A(n) const char* key ## n, const char* valp ## n // Argument list
#define D(n) const char* key ## n = NULL, const char* valp ## n = NULL // Argument list
static void _insertp (D(0),D(1),D(2),D(3),D(4),D(5),D(6),D(7),D(8),D(9));
static void _insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
,A(10),D(11),D(12),D(13),D(14),D(15),D(16),D(17),D(18),D(19));
static void _insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
,A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)
,A(20),D(21),D(22),D(23),D(24),D(25),D(26),D(27),D(28),D(29));
// Backward compatibility for Verilator
static void _insertp (A(0), A(1), K(2),int val2, K(3),int val3,
K(4),const string& val4, A(5),A(6));
#undef K
#undef A
#undef D
/// Clear coverage points (and call delete on all items)
static void clear();
/// Clear items not matching the provided string
static void clearNonMatch (const char* matchp);
/// Zero coverage points
static void zero();
};
#endif // guard
+145
View File
@@ -0,0 +1,145 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//=============================================================================
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2015 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 Coverage item keys
///
//=============================================================================
#ifndef _VERILATED_COV_KEY_H_
#define _VERILATED_COV_KEY_H_ 1
#include "verilatedos.h"
#include <string>
using namespace std;
//=============================================================================
// Data used to edit below file, using vlcovgen
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
VLCOVGEN_ITEM("name=>'col0_name', short=>'C0', group=>1, default=>undef, descr=>'The column title for the header line of this column'")
VLCOVGEN_ITEM("name=>'col1_name', short=>'C1', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'col2_name', short=>'C2', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'col3_name', short=>'C3', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'column', short=>'n', group=>1, default=>0, descr=>'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
VLCOVGEN_ITEM("name=>'filename', short=>'f', group=>1, default=>undef, descr=>'Filename of the item'")
VLCOVGEN_ITEM("name=>'groupdesc', short=>'d', group=>1, default=>'', descr=>'Description of the covergroup this item belongs to'")
VLCOVGEN_ITEM("name=>'groupname', short=>'g', group=>1, default=>'', descr=>'Group name of the covergroup this item belongs to'")
VLCOVGEN_ITEM("name=>'groupcmt', short=>'O', group=>1, default=>'', ")
VLCOVGEN_ITEM("name=>'per_instance',short=>'P', group=>1, default=>0, descr=>'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
VLCOVGEN_ITEM("name=>'row0_name', short=>'R0', group=>1, default=>undef, descr=>'The row title for the header line of this row'")
VLCOVGEN_ITEM("name=>'row1_name', short=>'R1', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'row2_name', short=>'R2', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'row3_name', short=>'R3', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'table', short=>'T', group=>1, default=>undef, descr=>'The name of the table for automatically generated tables'")
VLCOVGEN_ITEM("name=>'thresh', short=>'s', group=>1, default=>undef, ")
VLCOVGEN_ITEM("name=>'type', short=>'t', group=>1, default=>'', descr=>'Type of coverage (block, line, fsm, etc)'")
// Bin attributes
VLCOVGEN_ITEM("name=>'col0', short=>'c0', group=>0, default=>undef, descr=>'The (enumeration) value name for this column in a table cross' ")
VLCOVGEN_ITEM("name=>'col1', short=>'c1', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'col2', short=>'c2', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'col3', short=>'c3', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'comment', short=>'o', group=>0, default=>'', descr=>'Textual description for the item'")
VLCOVGEN_ITEM("name=>'hier', short=>'h', group=>0, default=>'', descr=>'Hierarchy path name for the item'")
VLCOVGEN_ITEM("name=>'limit', short=>'L', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'lineno', short=>'l', group=>0, default=>0, descr=>'Line number for the item'")
VLCOVGEN_ITEM("name=>'row0', short=>'r0', group=>0, default=>undef, descr=>'The (enumeration) value name for this row in a table cross'")
VLCOVGEN_ITEM("name=>'row1', short=>'r1', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ")
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
//=============================================================================
// VerilatedCovKey
/// Verilator coverage global class
////
/// Global class with methods affecting all coverage data.
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
#define VL_CIK_COL0 "c0"
#define VL_CIK_COL0_NAME "C0"
#define VL_CIK_COL1 "c1"
#define VL_CIK_COL1_NAME "C1"
#define VL_CIK_COL2 "c2"
#define VL_CIK_COL2_NAME "C2"
#define VL_CIK_COL3 "c3"
#define VL_CIK_COL3_NAME "C3"
#define VL_CIK_COLUMN "n"
#define VL_CIK_COMMENT "o"
#define VL_CIK_FILENAME "f"
#define VL_CIK_GROUPCMT "O"
#define VL_CIK_GROUPDESC "d"
#define VL_CIK_GROUPNAME "g"
#define VL_CIK_HIER "h"
#define VL_CIK_LIMIT "L"
#define VL_CIK_LINENO "l"
#define VL_CIK_PER_INSTANCE "P"
#define VL_CIK_ROW0 "r0"
#define VL_CIK_ROW0_NAME "R0"
#define VL_CIK_ROW1 "r1"
#define VL_CIK_ROW1_NAME "R1"
#define VL_CIK_ROW2 "r2"
#define VL_CIK_ROW2_NAME "R2"
#define VL_CIK_ROW3 "r3"
#define VL_CIK_ROW3_NAME "R3"
#define VL_CIK_TABLE "T"
#define VL_CIK_THRESH "s"
#define VL_CIK_TYPE "t"
#define VL_CIK_WEIGHT "w"
// VLCOVGEN_CIK_AUTO_EDIT_END
class VerilatedCovKey {
public:
static string shortKey(const string& key) {
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
if (key == "col0") return VL_CIK_COL0;
if (key == "col0_name") return VL_CIK_COL0_NAME;
if (key == "col1") return VL_CIK_COL1;
if (key == "col1_name") return VL_CIK_COL1_NAME;
if (key == "col2") return VL_CIK_COL2;
if (key == "col2_name") return VL_CIK_COL2_NAME;
if (key == "col3") return VL_CIK_COL3;
if (key == "col3_name") return VL_CIK_COL3_NAME;
if (key == "column") return VL_CIK_COLUMN;
if (key == "comment") return VL_CIK_COMMENT;
if (key == "filename") return VL_CIK_FILENAME;
if (key == "groupcmt") return VL_CIK_GROUPCMT;
if (key == "groupdesc") return VL_CIK_GROUPDESC;
if (key == "groupname") return VL_CIK_GROUPNAME;
if (key == "hier") return VL_CIK_HIER;
if (key == "limit") return VL_CIK_LIMIT;
if (key == "lineno") return VL_CIK_LINENO;
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
if (key == "row0") return VL_CIK_ROW0;
if (key == "row0_name") return VL_CIK_ROW0_NAME;
if (key == "row1") return VL_CIK_ROW1;
if (key == "row1_name") return VL_CIK_ROW1_NAME;
if (key == "row2") return VL_CIK_ROW2;
if (key == "row2_name") return VL_CIK_ROW2_NAME;
if (key == "row3") return VL_CIK_ROW3;
if (key == "row3_name") return VL_CIK_ROW3_NAME;
if (key == "table") return VL_CIK_TABLE;
if (key == "thresh") return VL_CIK_THRESH;
if (key == "type") return VL_CIK_TYPE;
if (key == "weight") return VL_CIK_WEIGHT;
// VLCOVGEN_SHORT_AUTO_EDIT_END
return key;
}
};
#endif // guard
+2 -2
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2015 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.
@@ -82,7 +82,7 @@ void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w) {
void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w) {
_VL_SVDPI_UNIMP();
}
void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal s, int i, int w) {
void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w) {
_VL_SVDPI_UNIMP();
}
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+17 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2010-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2015 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.
@@ -41,11 +41,27 @@ inline string VL_CVT_PACK_STR_NQ(QData lhs) {
IData lw[2]; VL_SET_WQ(lw, lhs);
return VL_CVT_PACK_STR_NW(2, lw);
}
inline string VL_CVT_PACK_STR_NN(const string& lhs) {
return lhs;
}
inline string VL_CVT_PACK_STR_NI(IData lhs) {
IData lw[1]; lw[0] = lhs;
return VL_CVT_PACK_STR_NW(1, lw);
}
inline string VL_CONCATN_NNN(const string& lhs, const string& rhs) {
return lhs+rhs;
}
inline string VL_REPLICATEN_NNQ(int,int,int, const string& lhs, IData rep) {
string out; out.reserve(lhs.length() * rep);
for (unsigned times=0; times<rep; times++) out += lhs;
return out;
}
inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs, IData rep) {
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
}
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
extern string VL_SFORMATF_NX(const char* formatp, ...);
#endif // Guard
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2015 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.
+7 -6
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
// Copyright 2001-2015 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.
//
@@ -17,8 +17,6 @@
/// \file
/// \brief C++ Tracing in VCD Format
///
/// AUTHOR: Wilson Snyder
///
//=============================================================================
#include "verilatedos.h"
@@ -62,8 +60,9 @@ bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t siz
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
if (VL_UNLIKELY(readDiffers(datap,size))) {
string fn = filename();
string msg = (string)"Can't deserialize save-restore file as was made from different model";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
return *this; // For function chaining
@@ -82,8 +81,9 @@ void VerilatedSerialize::header() {
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 fn = filename();
string msg = (string)"Can't deserialize; file has wrong header signature";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
@@ -98,8 +98,9 @@ void VerilatedSerialize::trailer() {
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 fn = filename();
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
}
+1 -3
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2012-2013 by Wilson Snyder. This program is free software;
// Copyright 2012-2015 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.
//
@@ -17,8 +17,6 @@
/// \file
/// \brief Save-restore serialization of verilated modules
///
/// AUTHOR: Wilson Snyder
///
//=============================================================================
#ifndef _VERILATED_SAVE_C_H_
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2015 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.
+11 -9
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -45,19 +45,20 @@ struct VerilatedCStrCmp {
//===========================================================================
/// Verilator range
// See also V3Ast::VNumRange
class VerilatedRange {
int m_lhs;
int m_rhs;
int m_left;
int m_right;
protected:
friend class VerilatedVar;
friend class VerilatedScope;
VerilatedRange() : m_lhs(0), m_rhs(0) {}
void sets(int lhs, int rhs) { m_lhs=lhs; m_rhs=rhs; }
VerilatedRange() : m_left(0), m_right(0) {}
void sets(int left, int right) { m_left=left; m_right=right; }
public:
~VerilatedRange() {}
int lhs() const { return m_lhs; }
int rhs() const { return m_rhs; }
int bits() const { return (VL_LIKELY(m_lhs>=m_rhs)?(m_lhs-m_rhs+1):(m_rhs-m_lhs+1)); }
int left() const { return m_left; }
int right() const { return m_right; }
int elements() const { return (VL_LIKELY(m_left>=m_right)?(m_left-m_right+1):(m_right-m_left+1)); }
};
//===========================================================================
@@ -92,7 +93,8 @@ public:
//======================================================================
/// Types
struct VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
class VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
public:
VerilatedVarNameMap() {}
~VerilatedVarNameMap() {}
};
+73 -22
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
// Copyright 2001-2015 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.
//
@@ -17,8 +17,6 @@
/// \file
/// \brief C++ Tracing in VCD Format
///
/// AUTHOR: Wilson Snyder
///
//=============================================================================
// SPDIFF_OFF
@@ -57,7 +55,7 @@ vector<VerilatedVcd*> VerilatedVcd::s_vcdVecp; ///< List of all created traces
// VerilatedVcdCallInfo
/// Internal callback routines for each module being traced.
////
/// Each SystemPerl module that wishes to be traced registers a set of
/// Each module that wishes to be traced registers a set of
/// callbacks stored in this class. When the trace file is being
/// constructed, this class provides the callback routines to be executed.
@@ -76,11 +74,48 @@ protected:
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {};
};
//=============================================================================
//=============================================================================
//=============================================================================
// VerilatedVcdFile
bool VerilatedVcdFile::open(const string& name) {
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK, 0666);
return (m_fd>=0);
}
void VerilatedVcdFile::close() {
::close(m_fd);
}
ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) {
return ::write(m_fd, bufp, len);
}
//=============================================================================
//=============================================================================
//=============================================================================
// Opening/Closing
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
: m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
// Not in header to avoid link issue if header is included without this .cpp file
m_fileNewed = (filep == NULL);
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
m_namemapp = NULL;
m_timeRes = m_timeUnit = 1e-9;
m_timeLastDump = 0;
m_sigs_oldvalp = NULL;
m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility
m_fullDump = true;
m_wrChunkSize = 8*1024;
m_wrBufp = new char [m_wrChunkSize*8];
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
m_writep = m_wrBufp;
m_wroteBytes = 0;
}
void VerilatedVcd::open (const char* filename) {
if (isOpen()) return;
@@ -142,9 +177,7 @@ void VerilatedVcd::openNext (bool incFilename) {
assert(0); // Not supported yet.
} else {
// cppcheck-suppress duplicateExpression
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
, 0666);
if (m_fd<0) {
if (!m_filep->open(m_filename)) {
// User code can check isOpen()
m_isOpen = false;
return;
@@ -172,8 +205,8 @@ void VerilatedVcd::makeNameMap() {
// This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str();
if (hiername[0] == '\t') nullScope=true;
const string& hiername = it->first;
if (hiername.size() >= 1 && hiername[0] == '\t') nullScope=true;
}
if (nullScope) {
NameMap* newmapp = new NameMap;
@@ -199,6 +232,7 @@ VerilatedVcd::~VerilatedVcd() {
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
deleteNameMap();
if (m_filep && m_fileNewed) { delete m_filep; m_filep = NULL; }
// Remove from list of traces
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
@@ -209,7 +243,7 @@ void VerilatedVcd::closePrev () {
bufferFlush();
m_isOpen = false;
::close(m_fd);
m_filep->close();
}
void VerilatedVcd::closeErr () {
@@ -219,7 +253,7 @@ void VerilatedVcd::closeErr () {
// No buffer flush, just fclose
m_isOpen = false;
::close(m_fd); // May get error, just ignore it
m_filep->close(); // May get error, just ignore it
}
void VerilatedVcd::close() {
@@ -261,6 +295,20 @@ void VerilatedVcd::printTime (vluint64_t timeui) {
printQuad(timeui);
}
void VerilatedVcd::bufferResize(vluint64_t minsize) {
// minsize is size of largest write. We buffer at least 8 times as much data,
// writing when we are 3/4 full (with thus 2*minsize remaining free)
if (VL_UNLIKELY(minsize > m_wrChunkSize)) {
char* oldbufp = m_wrBufp;
m_wrChunkSize = minsize*2;
m_wrBufp = new char [m_wrChunkSize * 8];
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
m_writep = m_wrBufp + (m_writep - oldbufp);
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
delete oldbufp; oldbufp=NULL;
}
}
void VerilatedVcd::bufferFlush () {
// We add output data to m_writep.
// When it gets nearly full we dump it using this routine which calls write()
@@ -271,7 +319,7 @@ void VerilatedVcd::bufferFlush () {
ssize_t remaining = (m_writep - wp);
if (remaining==0) break;
errno = 0;
ssize_t got = write (m_fd, wp, remaining);
ssize_t got = m_filep->write(wp, remaining);
if (got>0) {
wp += got;
m_wroteBytes += got;
@@ -294,13 +342,11 @@ void VerilatedVcd::bufferFlush () {
// Simple methods
void VerilatedVcd::set_time_unit (const char* unitp) {
string unitstr (unitp);
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeUnit = timescaleToDouble(unitp);
}
void VerilatedVcd::set_time_resolution (const char* unitp) {
string unitstr (unitp);
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeRes = timescaleToDouble(unitp);
}
@@ -352,7 +398,8 @@ void VerilatedVcd::dumpHeader () {
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
printStr("$timescale ");
printStr(doubleToTimescale(m_timeRes).c_str());
const string& timeResStr = doubleToTimescale(m_timeRes);
printStr(timeResStr.c_str());
printStr(" $end\n");
makeNameMap();
@@ -370,10 +417,11 @@ void VerilatedVcd::dumpHeader () {
// Print the signal names
const char* lastName = "";
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str();
const char* decl = (*it).second.c_str();
const string& hiernamestr = it->first;
const string& decl = it->second;
// Determine difference between the old and new names
const char* hiername = hiernamestr.c_str();
const char* lp = lastName;
const char* np = hiername;
lastName = hiername;
@@ -408,7 +456,7 @@ void VerilatedVcd::dumpHeader () {
}
printIndent(0);
printStr(decl);
printStr(decl.c_str());
}
while (m_modDepth>1) {
@@ -424,7 +472,7 @@ void VerilatedVcd::dumpHeader () {
deleteNameMap();
}
void VerilatedVcd::module (string name) {
void VerilatedVcd::module (const string& name) {
m_modName = name;
}
@@ -442,6 +490,9 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
}
// Make sure write buffer is large enough (one character per bit), plus header
bufferResize(bits+1024);
// Save declaration info
VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
m_sigs.push_back(sig);
@@ -520,7 +571,7 @@ void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
(*((double*)&m_sigs_oldvalp[code])) = newval;
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
// Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", newval);
m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n';
@@ -528,7 +579,7 @@ void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
}
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
(*((float*)&m_sigs_oldvalp[code])) = newval;
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
// Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", (double)newval);
m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n';
@@ -701,5 +752,5 @@ main() {
//********************************************************************
// Local Variables:
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && g++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && c++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
// End:
+28 -24
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
// Copyright 2001-2015 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.
//
@@ -17,8 +17,6 @@
/// \file
/// \brief C++ Tracing in VCD Format
///
/// AUTHOR: Wilson Snyder
///
//=============================================================================
// SPDIFF_OFF
@@ -36,6 +34,22 @@ class VerilatedVcd;
class VerilatedVcdCallInfo;
// SPDIFF_ON
//=============================================================================
// VerilatedFile
/// File handling routines, which can be overrode for e.g. socket I/O
class VerilatedVcdFile {
private:
int m_fd; ///< File descriptor we're writing to
public:
// METHODS
VerilatedVcdFile() : m_fd(0) {}
virtual ~VerilatedVcdFile() {}
virtual bool open(const string& name);
virtual void close();
virtual ssize_t write(const char* bufp, ssize_t len);
};
//=============================================================================
// VerilatedVcdSig
/// Internal data on one signal being traced.
@@ -62,9 +76,10 @@ typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluin
class VerilatedVcd {
private:
VerilatedVcdFile* m_filep; ///< File we're writing to
bool m_fileNewed; ///< m_filep needs destruction
bool m_isOpen; ///< True indicates open file
bool m_evcd; ///< True for evcd format
int m_fd; ///< File descriptor we're writing to
string m_filename; ///< Filename we're writing to (if open)
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
char m_scopeEscape; ///< Character to separate scope components
@@ -77,7 +92,9 @@ private:
vluint64_t m_timeLastDump; ///< Last time we did a dump
char* m_wrBufp; ///< Output buffer
char* m_wrFlushp; ///< Output buffer flush trigger location
char* m_writep; ///< Write pointer into output buffer
vluint64_t m_wrChunkSize; ///< Output buffer size
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
@@ -87,13 +104,12 @@ private:
NameMap* m_namemapp; ///< List of names for the header
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
inline static size_t bufferInsertSize() { return 16*1024; }
void bufferResize(vluint64_t minsize);
void bufferFlush();
void bufferCheck() {
inline void 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_writep > (m_wrBufp+(bufferSize()-bufferInsertSize())))) {
if (VL_UNLIKELY(m_writep > m_wrFlushp)) {
bufferFlush();
}
}
@@ -134,19 +150,7 @@ protected:
public:
// CREATORS
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
m_wrBufp = new char [bufferSize()];
m_writep = m_wrBufp;
m_namemapp = NULL;
m_timeRes = m_timeUnit = 1e-9;
m_timeLastDump = 0;
m_sigs_oldvalp = NULL;
m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility
m_wroteBytes = 0;
m_fd = 0;
m_fullDump = true;
}
VerilatedVcd(VerilatedVcdFile* filep=NULL);
~VerilatedVcd();
// ACCESSORS
@@ -188,7 +192,7 @@ public:
void* userthis);
/// Inside dumping routines, declare a module
void module (const string name);
void module (const string& name);
/// Inside dumping routines, declare a signal
void declBit (vluint32_t code, const char* name, int arraynum);
void declBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
@@ -392,10 +396,10 @@ public:
/// Create a VCD dump file in C standalone (no SystemC) simulations.
class VerilatedVcdC {
VerilatedVcd m_sptrace; ///< SystemPerl trace file being created
VerilatedVcd m_sptrace; ///< Trace file being created
public:
// CONSTRUCTORS
VerilatedVcdC() {}
VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
~VerilatedVcdC() {}
// ACCESSORS
/// Is file open?
+2 -4
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
// Copyright 2001-2015 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.
//
@@ -15,9 +15,7 @@
//=============================================================================
///
/// \file
/// \brief SystemPerl Tracing in VCD Format
///
/// AUTHOR: Wilson Snyder
/// \brief Verilator tracing in VCD Format
///
//=============================================================================
// SPDIFF_OFF
+2 -4
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2013 by Wilson Snyder. This program is free software;
// Copyright 2001-2015 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.
//
@@ -15,9 +15,7 @@
//=============================================================================
///
/// \file
/// \brief SystemPerl tracing in VCD format
///
/// AUTHOR: Wilson Snyder
/// \brief Verilator tracing in VCD format
///
//=============================================================================
// SPDIFF_OFF
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2015 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.
+191 -91
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2015 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.
@@ -38,7 +38,7 @@
// Internal macros
#define _VL_VPI_INTERNAL VerilatedVpi::error_info()->setMessage(vpiInternal)->setMessage
#define _VL_VPI_SYSTEM VerilatedVpi::error_info()->setMessage(vpiSystem )->setMessage
#define _VL_VPI_SYSTEM VerilatedVpi::error_info()->setMessage(vpiSystem )->setMessage
#define _VL_VPI_ERROR VerilatedVpi::error_info()->setMessage(vpiError )->setMessage
#define _VL_VPI_WARNING VerilatedVpi::error_info()->setMessage(vpiWarning )->setMessage
#define _VL_VPI_NOTICE VerilatedVpi::error_info()->setMessage(vpiNotice )->setMessage
@@ -52,6 +52,8 @@
// Implementation
#include <set>
#include <list>
#include <map>
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
#define VL_VPI_LINE_SIZE 8192
@@ -94,6 +96,9 @@ public:
virtual const char* name() { return "<null>"; }
virtual const char* fullname() { return "<null>"; }
virtual const char* defname() { return "<null>"; }
virtual const vluint32_t type() { return 0; }
virtual const vluint32_t size() const { return 0; }
virtual const VerilatedRange* rangep() const { return NULL; }
virtual vpiHandle dovpi_scan() { return 0; }
};
@@ -112,6 +117,7 @@ public:
}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiCallback; }
vluint32_t reason() const { return m_cbData.reason; }
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
t_cb_data* cb_datap() { return &(m_cbData); }
@@ -124,19 +130,20 @@ public:
VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
virtual ~VerilatedVpioConst() {}
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiUndefined; }
vlsint32_t num() const { return m_num; }
};
class VerilatedVpioRange : public VerilatedVpio {
vlsint32_t m_lhs; // Ranges can be signed
vlsint32_t m_rhs;
bool m_iteration;
const VerilatedRange* m_range;
vlsint32_t m_iteration;
public:
VerilatedVpioRange(vlsint32_t lhs, vlsint32_t rhs) : m_lhs(lhs), m_rhs(rhs), m_iteration(0) {}
VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
virtual ~VerilatedVpioRange() {}
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
vlsint32_t lhs() const { return m_lhs; }
vlsint32_t rhs() const { return m_rhs; }
virtual const vluint32_t type() { return vpiRange; }
virtual const vluint32_t size() const { return m_range->elements(); }
virtual const VerilatedRange* rangep() const { return m_range; }
int iteration() const { return m_iteration; }
void iterationInc() { ++m_iteration; }
virtual vpiHandle dovpi_scan() {
@@ -157,6 +164,7 @@ public:
: m_scopep(scopep) {}
virtual ~VerilatedVpioScope() {}
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiScope; }
const VerilatedScope* scopep() const { return m_scopep; }
virtual const char* name() { return m_scopep->name(); }
virtual const char* fullname() { return m_scopep->name(); }
@@ -174,11 +182,15 @@ class VerilatedVpioVar : public VerilatedVpio {
protected:
void* m_varDatap; // varp()->datap() adjusted for array entries
vlsint32_t m_index;
const VerilatedRange& get_range() const {
// Determine number of dimensions and return outermost
return (m_varp->dims()>1) ? m_varp->array() : m_varp->range();
}
public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp(varp), m_scopep(scopep), m_index(0) {
m_prevDatap = NULL;
m_mask.u32 = VL_MASK_I(varp->range().bits());
m_mask.u32 = VL_MASK_I(varp->range().elements());
m_entSize = varp->entSize();
m_varDatap = varp->datap();
}
@@ -191,6 +203,13 @@ public:
vluint32_t mask() const { return m_mask.u32; }
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
vluint32_t entSize() const { return m_entSize; }
const vluint32_t index() { return m_index; }
virtual const vluint32_t type() {
if (varp()->vldir() != vpiNoDirection) return vpiPort;
return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
}
virtual const vluint32_t size() const { return get_range().elements(); }
virtual const VerilatedRange* rangep() const { return &get_range(); }
virtual const char* name() { return m_varp->name(); }
virtual const char* fullname() {
VL_STATIC_OR_THREAD string out;
@@ -207,16 +226,19 @@ public:
}
};
class VerilatedVpioVarIndex : public VerilatedVpioVar {
class VerilatedVpioMemoryWord : public VerilatedVpioVar {
public:
VerilatedVpioVarIndex(const VerilatedVar* varp, const VerilatedScope* scopep,
VerilatedVpioMemoryWord(const VerilatedVar* varp, const VerilatedScope* scopep,
vlsint32_t index, int offset)
: VerilatedVpioVar(varp, scopep) {
m_index = index;
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
}
virtual ~VerilatedVpioVarIndex() {}
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
virtual ~VerilatedVpioMemoryWord() {}
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiMemoryWord; }
virtual const vluint32_t size() const { return varp()->range().elements(); }
virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
virtual const char* fullname() {
VL_STATIC_OR_THREAD string out;
char num[20]; sprintf(num,"%d",m_index);
@@ -234,12 +256,14 @@ public:
: m_scopep(scopep), m_started(false) { }
virtual ~VerilatedVpioVarIter() {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiIterator; }
virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) {
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
VerilatedVarNameMap* varsp = m_scopep->varsp();
if (VL_UNLIKELY(!m_started)) { m_it = varsp->begin(); m_started=true; }
else if (VL_UNLIKELY(m_it == varsp->end())) return 0;
else ++m_it;
if (m_it == m_scopep->varsp()->end()) return 0;
if (m_it == varsp->end()) return 0;
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
->castVpiHandle());
} else {
@@ -248,6 +272,28 @@ public:
}
};
class VerilatedVpioMemoryWordIter : public VerilatedVpio {
const vpiHandle m_handle;
const VerilatedVar* m_varp;
vlsint32_t m_iteration;
vlsint32_t m_direction;
bool m_done;
public:
VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp)
: m_handle(handle), m_varp(varp), m_iteration(varp->array().right()), m_direction(VL_LIKELY(varp->array().left()>varp->array().right())?1:-1), m_done(false) { }
virtual ~VerilatedVpioMemoryWordIter() {}
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiIterator; }
void iterationInc() { if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction; }
virtual vpiHandle dovpi_scan() {
vpiHandle result;
if (m_done) return 0;
result = vpi_handle_by_index(m_handle, m_iteration);
iterationInc();
return result;
}
};
//======================================================================
struct VerilatedVpiTimedCbsCmp {
@@ -260,14 +306,19 @@ struct VerilatedVpiTimedCbsCmp {
}
};
struct VerilatedVpiError;
class VerilatedVpiError;
class VerilatedVpi {
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
typedef set<VerilatedVpioCb*> VpioCbSet;
typedef list<VerilatedVpioCb*> VpioCbList;
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
struct product_info {
PLI_BYTE8* product;
PLI_BYTE8* version;
};
VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
VpioTimedCbs m_timedCbs; // Time based callbacks
VerilatedVpiError* m_errorInfop; // Container for vpi error info
@@ -283,16 +334,17 @@ public:
}
}
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
s_s.m_cbObjSets[vop->reason()].insert(vop);
s_s.m_cbObjLists[vop->reason()].push_back(vop);
}
static void cbTimedAdd(VerilatedVpioCb* vop) {
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
}
static void cbReasonRemove(VerilatedVpioCb* cbp) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
VpioCbSet::iterator it=cbObjSet.find(cbp);
if (VL_LIKELY(it != cbObjSet.end())) {
cbObjSet.erase(it);
VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
// We do not remove it now as we may be iterating the list,
// instead set to NULL and will cleanup later
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end(); ++it) {
if (*it == cbp) *it = NULL;
}
}
static void cbTimedRemove(VerilatedVpioCb* cbp) {
@@ -322,19 +374,26 @@ public:
}
}
static void callCbs(vluint32_t reason) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
VerilatedVpioCb* vop = *it;
++it; // iterator may be deleted by callback
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
it = cbObjList.erase(it);
continue;
}
VerilatedVpioCb* vop = *it++;
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
(vop->cb_rtnp()) (vop->cb_datap());
}
}
static void callValueCbs() {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
VerilatedVpioCb* vop = *it;
++it; // iterator may be deleted by callback
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
set<VerilatedVpioVar*> update; // set of objects to update after callbacks
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
it = cbObjList.erase(it);
continue;
}
VerilatedVpioCb* vop = *it++;
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
void* newDatap = varop->varDatap();
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
@@ -344,12 +403,15 @@ public:
if (memcmp(prevDatap, newDatap, varop->entSize())) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize());
update.insert(varop);
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp()) (vop->cb_datap());
}
}
}
for (set<VerilatedVpioVar*>::iterator it=update.begin(); it!=update.end(); ++it) {
memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
}
}
static VerilatedVpiError* error_info(); // getter for vpi error info
@@ -369,15 +431,10 @@ class VerilatedVpiError {
t_vpi_error_info m_errorInfo;
bool m_flag;
char m_buff[VL_VPI_LINE_SIZE];
void setError(PLI_BYTE8 *message, PLI_BYTE8 *file, PLI_INT32 line) {
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
m_errorInfo.message = message;
m_errorInfo.file = file;
m_errorInfo.line = line;
m_errorInfo.code = NULL;
do_callbacks();
}
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
setError( message, file, line);
m_errorInfo.code = code;
do_callbacks();
}
@@ -393,6 +450,7 @@ class VerilatedVpiError {
public:
VerilatedVpiError() : m_flag(false) {
m_buff[0] = '\0';
m_errorInfo.product = (PLI_BYTE8*)Verilated::productName();
}
~VerilatedVpiError() {}
@@ -402,14 +460,11 @@ public:
return this;
}
void setMessage(string file, PLI_INT32 line, string message, ...) {
static VL_THREAD string filehold;
_VL_VPI_ERROR_SET;
m_errorInfo.state = vpiPLI;
setError((PLI_BYTE8*)m_buff, (PLI_BYTE8*)file.c_str(), line);
}
void setMessage(PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line, string message, ...) {
_VL_VPI_ERROR_SET;
m_errorInfo.state = vpiPLI;
setError((PLI_BYTE8*)message.c_str(), code, file, line);
filehold = file;
setError((PLI_BYTE8*)m_buff, NULL, (PLI_BYTE8*)filehold.c_str(), line);
}
p_vpi_error_info getError() {
if (m_flag) return &m_errorInfo;
@@ -545,15 +600,15 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
_VL_VPI_ERROR_RESET(); // reset vpi error status
if (VL_LIKELY(varop)) {
if (varop->varp()->dims()<2) return 0;
if (VL_LIKELY(varop->varp()->array().lhs() >= varop->varp()->array().rhs())) {
if (VL_UNLIKELY(indx > varop->varp()->array().lhs() || indx < varop->varp()->array().rhs())) return 0;
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().rhs()))
if (VL_LIKELY(varop->varp()->array().left() >= varop->varp()->array().right())) {
if (VL_UNLIKELY(indx > varop->varp()->array().left() || indx < varop->varp()->array().right())) return 0;
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().right()))
->castVpiHandle();
} else {
if (VL_UNLIKELY(indx < varop->varp()->array().lhs() || indx > varop->varp()->array().rhs())) return 0;
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().lhs()))
if (VL_UNLIKELY(indx < varop->varp()->array().left() || indx > varop->varp()->array().right())) return 0;
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().left()))
->castVpiHandle();
}
} else {
@@ -568,21 +623,32 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object););
_VL_VPI_ERROR_RESET(); // reset vpi error status
switch (type) {
case vpiLeftRange: // FALLTHRU
case vpiLeftRange: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (VL_UNLIKELY(!vop->rangep())) return 0;
return (new VerilatedVpioConst(vop->rangep()->left()))->castVpiHandle();
}
case vpiRightRange: {
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
vluint32_t num = ((type==vpiLeftRange)
? vop->varp()->range().lhs()
: vop->varp()->range().rhs());
return (new VerilatedVpioConst(num))->castVpiHandle();
} else if (VerilatedVpioRange* vop = VerilatedVpioRange::castp(object)) {
vluint32_t num = ((type==vpiLeftRange)
? vop->lhs()
: vop->rhs());
return (new VerilatedVpioConst(num))->castVpiHandle();
} else {
return 0;
}
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (VL_UNLIKELY(!vop->rangep())) return 0;
return (new VerilatedVpioConst(vop->rangep()->right()))->castVpiHandle();
}
case vpiIndex: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return (new VerilatedVpioConst(vop->index()))->castVpiHandle();
}
case vpiScope: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return (new VerilatedVpioScope(vop->scopep()))->castVpiHandle();
}
case vpiParent: {
VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return (new VerilatedVpioVar(vop->varp(), vop->scopep()))->castVpiHandle();
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
@@ -600,13 +666,25 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
_VL_VPI_ERROR_RESET(); // reset vpi error status
switch (type) {
case vpiMemoryWord: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims() < 2) return 0;
if (vop->varp()->dims() > 2) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims());
}
return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle();
}
case vpiRange: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims() < 2) return 0;
// Unsupported is multidim list
return ((new VerilatedVpioRange(vop->varp()->array().lhs(),
vop->varp()->array().rhs()))
->castVpiHandle());
if (vop->varp()->dims() > 2) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims());
}
return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle());
}
case vpiReg: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
@@ -639,9 +717,9 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
return VL_TIME_PRECISION;
}
case vpiType: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
VerilatedVpio* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return ((vop->varp()->dims()>1) ? vpiMemory : vpiReg);
return vop->type();
}
case vpiDirection: {
// By forthought, the directions already are vpi enumerated
@@ -649,11 +727,16 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
if (VL_UNLIKELY(!vop)) return 0;
return vop->varp()->vldir();
}
case vpiScalar: // FALLTHRU
case vpiVector: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims()==0) return 0;
else return 1;
return (property==vpiVector)^(vop->varp()->dims()==0);
}
case vpiSize: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return vop->size();
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
@@ -704,6 +787,7 @@ void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
static VL_THREAD char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination
// cppcheck-suppress variableScope
static VL_THREAD int outStrSz = sizeof(outStr)-1;
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
_VL_VPI_ERROR_RESET(); // reset vpi error status
@@ -730,7 +814,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
out[0].bval = 0;
return;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().bits());
int words = VL_WORDS_I(vop->varp()->range().elements());
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
}
@@ -763,7 +847,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bits = vop->varp()->range().bits();
int bits = vop->varp()->range().elements();
CData* datap = ((CData*)(vop->varDatap()));
int i;
if (bits > outStrSz) {
@@ -792,8 +876,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().bits()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->range().bits());
int chars = (vop->varp()->range().elements()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->range().elements());
CData* datap = ((CData*)(vop->varDatap()));
int i;
if (chars > outStrSz) {
@@ -815,7 +899,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
if (i==(chars-1)) {
// most signifcant char, mask off non existant bits when vector
// size is not a multiple of 3
unsigned int rem = vop->varp()->range().bits() % 3;
unsigned int rem = vop->varp()->range().elements() % 3;
if (rem) {
// generate bit mask & zero non existant bits
val &= (1<<rem)-1;
@@ -836,9 +920,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
value_p->value.str = outStr;
switch (vop->varp()->vltype()) {
// outStrSz does not include NULL termination so add one
case VLVT_UINT8 : snprintf(outStr, outStrSz+1, "%hhu", (unsigned int)*((CData*)(vop->varDatap()))); return;
case VLVT_UINT16: snprintf(outStr, outStrSz+1, "%hu", (unsigned int)*((SData*)(vop->varDatap()))); return;
case VLVT_UINT32: snprintf(outStr, outStrSz+1, "%u", (unsigned int)*((IData*)(vop->varDatap()))); return;
case VLVT_UINT8 : snprintf(outStr, outStrSz+1, "%hhu", (unsigned char )*((CData*)(vop->varDatap()))); return;
case VLVT_UINT16: snprintf(outStr, outStrSz+1, "%hu", (unsigned short)*((SData*)(vop->varDatap()))); return;
case VLVT_UINT32: snprintf(outStr, outStrSz+1, "%u", (unsigned int )*((IData*)(vop->varDatap()))); return;
case VLVT_UINT64: snprintf(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return;
default:
strcpy(outStr, "-1");
@@ -854,7 +938,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().bits()+3)>>2;
int chars = (vop->varp()->range().elements()+3)>>2;
CData* datap = ((CData*)(vop->varDatap()));
int i;
if (chars > outStrSz) {
@@ -869,7 +953,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
if (i==(chars-1)) {
// most signifcant char, mask off non existant bits when vector
// size is not a multiple of 4
unsigned int rem = vop->varp()->range().bits() & 3;
unsigned int rem = vop->varp()->range().elements() & 3;
if (rem) {
// generate bit mask & zero non existant bits
val &= (1<<rem)-1;
@@ -893,7 +977,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bytes = VL_BYTES_I(vop->varp()->range().bits());
int bytes = VL_BYTES_I(vop->varp()->range().elements());
CData* datap = ((CData*)(vop->varDatap()));
int i;
if (bytes > outStrSz) {
@@ -936,6 +1020,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return;
}
} else if (value_p->format == vpiSuppressVal) {
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
@@ -984,7 +1070,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
*((IData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
return object;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().bits());
int words = VL_WORDS_I(vop->varp()->range().elements());
WDataOutP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
datap[i] = value_p->value.vector[i].aval;
@@ -1013,7 +1099,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bits = vop->varp()->range().bits();
int bits = vop->varp()->range().elements();
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
for (int i=0; i<bits; i++) {
@@ -1040,8 +1126,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().bits()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->range().bits());
int chars = (vop->varp()->range().elements()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
div_t idx;
@@ -1126,7 +1212,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().bits()+3)>>2;
int chars = (vop->varp()->range().elements()+3)>>2;
CData* datap = ((CData*)(vop->varDatap()));
char* val = value_p->value.str;
// skip hex ident if one is detected at the start of the string
@@ -1173,7 +1259,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bytes = VL_BYTES_I(vop->varp()->range().bits());
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
for (int i=0; i<bytes; i++) {
@@ -1227,7 +1313,21 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
// time processing
void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
_VL_VPI_UNIMP(); return;
if (VL_UNLIKELY(!time_p)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer");
return;
}
if (time_p->type == vpiSimTime) {
QData qtime = VL_TIME_Q();
IData itime[2];
VL_SET_WQ(itime, qtime);
time_p->low = itime[0];
time_p->high = itime[1];
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)",
VL_FUNC, time_p->type);
return;
}
// I/O routines
+28 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -95,6 +95,23 @@
// This is not necessarily the same as #UL, depending on what the IData typedef is.
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
//=========================================================================
// C++-2011
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
# define VL_HAS_UNIQUE_PTR
# define VL_UNIQUE_PTR unique_ptr
#else
# define VL_UNIQUE_PTR auto_ptr
#endif
//=========================================================================
// Optimization
#ifndef VL_INLINE_OPT
# define VL_INLINE_OPT ///< "inline" if compiling all objects in single compiler run
#endif
//=========================================================================
// Warning disabled
@@ -161,6 +178,7 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
#else // Linux or compliant Unix flavors, -m64
# include <stdint.h> // Linux and most flavors
# include <unistd.h> // Linux ssize_t
# include <inttypes.h> // Solaris
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
@@ -189,6 +207,15 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#endif
//=========================================================================
// File system functions
#ifdef _WIN32
# define VL_DEV_NULL "nul"
#else // Linux or compliant Unix flavors
# define VL_DEV_NULL "/dev/null"
#endif
//=========================================================================
// Integer size macros
+3 -3
View File
@@ -29,7 +29,7 @@ typedef signed __int8 int8_t;
#include <stdint.h>
#elif defined(__APPLE__)
#include <stdint.h>
#elif defined(__linux)
#elif defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
#include <inttypes.h>
#else
#include <sys/types.h>
@@ -155,7 +155,7 @@ XXTERN void svGetPartselBit(svBitVecVal* d, const svBitVecVal* s, int i, int w);
XXTERN void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
XXTERN void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w);
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal s, int i, int w);
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
/*
* Open array querying functions
@@ -427,7 +427,7 @@ XXTERN void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s,
/* actual <-- canonical */
XXTERN void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s,
int i, int w);
XXTERN void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32 s,
XXTERN void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32* s,
int i, int w);
/*
+1 -1
View File
@@ -37,7 +37,7 @@ typedef signed __int32 int32_t;
typedef signed __int8 int8_t;
#elif defined(__MINGW32__)
#include <stdint.h>
#elif defined(__linux)
#elif defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
#include <inttypes.h>
#else
#include <sys/types.h>
+64 -27
View File
@@ -40,7 +40,7 @@ Verilator then performs many additional edits and optimizations on the
hierarchical design. This includes coverage, assertions, X elimination,
inlining, constant propagation, and dead code elimination.
References in the design are then psudo-flattened. Each module's variables
References in the design are then pseudo-flattened. Each module's variables
and functions get "Scope" references. A scope reference is an occurrence of
that un-flattened variable in the flattened hierarchy. A module that occurs
only once in the hierarchy will have a single scope and single VarScope for
@@ -49,7 +49,7 @@ occurrence, and two VarScopes for each variable. This allows optimizations
to proceed across the flattened design, while still preserving the
hierarchy.
Additional edits and optimizations proceed on the psudo-flat design. These
Additional edits and optimizations proceed on the pseudo-flat design. These
include module references, function inlining, loop unrolling, variable
lifetime analysis, lookup table creation, always splitting, and logic gate
simplifications (pushing inverters, etc).
@@ -80,8 +80,8 @@ 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
C<AstIf> node (for C<if> statements), C<ifsp> calls C<op2p> to give the
pointer to the AST for the "then" block, while C<elsesp> calls C<op3p> to
give the pointer to the AST for the "else" block, or NULL if there is not
one.
@@ -97,7 +97,7 @@ 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>
=item C<AstNVisitor>
The passes are implemented by AST visitor classes (see L</Visitor
Functions>). These are implemented by subclasses of the abstract class,
@@ -119,7 +119,7 @@ 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
used in dot output. Typically users provide derived classes from
C<V3GraphVertex> which will reimplement these methods.
Iterators are provided to access in and out edges. Typically these are used in
@@ -219,7 +219,7 @@ and optimization passes. This allows separation of the pass algorithm from
the AST on which it operates. Wikipedia provides an introduction to the
concept at L<http://en.wikipedia.org/wiki/Visitor_pattern>.
As noted above, all visitors are derived classes of C<AstNvisitor>. All
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
@@ -262,7 +262,7 @@ exiting the lower for will lose the upper for's setting.
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
C<AstNUser>) using the C<user1p()> through C<user5p()> methods (a common
technique lifted from graph traversal packages).
A visitor first clears the one it wants to use by calling
@@ -290,7 +290,7 @@ module.
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
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.)
@@ -301,10 +301,10 @@ as it slows the program down to have to pass vup everywhere.)
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
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.
Functions>, but its use is now deprecated and should I<not> be used for new
visitor classes.
=over 4
@@ -341,6 +341,37 @@ C<op4p> in turn.
=back
=head3 Caution on Using Iterators When Child Changes
Visitors often replace one node with another node; V3Width and V3Const are
major examples. A visitor which is the parent of such a replacement needs
to be aware that calling iteration may cause the children to change. For
example:
// nodep->lhsp() is 0x1234000
nodep->lhsp()->iterateAndNext(...); // and under covers nodep->lhsp() changes
// nodep->lhsp() is 0x5678400
nodep->lhsp()->iterateAndNext(...);
Will work fine, as even if the first iterate causes a new node to take the
place of the lhsp(), that edit will update nodep->lhsp() and the second
call will correctly see the change. Alternatively:
lp = nodep->lhsp();
// nodep->lhsp() is 0x1234000, lp is 0x1234000
lp->iterateAndNext(...); **lhsp=NULL;** // and under covers nodep->lhsp() changes
// nodep->lhsp() is 0x5678400, lp is 0x1234000
lp->iterateAndNext(...);
This will cause bugs or a core dump, as lp is a dangling pointer. Thus it
is advisable to set lhsp=NULL shown in the *'s above to make sure these
dangles are avoided. Another alternative used in special cases mostly in
V3Width is to use acceptSubtreeReturnEdits, which operates on a single node
and returns the new pointer if any. Note acceptSubtreeReturnEdits does not
follow nextp() links.
lp = lp->acceptSubtreeReturnEdits()
=head2 Identifying derived classes
A common requirement is to identify the specific C<AstNode> class we are
@@ -372,10 +403,22 @@ Verilator primary manual.
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,
Tests that fail should by convention 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.
=head2 Preparing to Run Tests
For all tests to pass you must install the following packages:
* SystemC to compile the SystemC outputs, see http://systemc.org
* Parallel::Forker from CPAN to run tests in parallel, you can install this
with e.g. "sudo cpan install Parallel::Forker".
* vcddiff to find differences in VCD outputs. See the readme at
https://github.com/veripool/vcddiff
=head2 Controlling the Test Driver
Test drivers are written in PERL. All invoke the main test driver script,
@@ -388,7 +431,7 @@ For convenience, a summary of the most commonly used features is provided
here. All drivers require a call to C<compile> subroutine to compile the
test. For run-time tests, this is followed by a call to the C<execute>
subroutine. Both of these functions can optionally be provided with a hash
table as argument specifying additonal options.
table as argument specifying additional options.
The test driver assumes by default that the source Verilog file name
matches the PERL driver name. So a test whose driver is C<t/t_mytest.pl>
@@ -442,10 +485,10 @@ 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.
In addition to the standard C, SystemC tests also run the tests in the
C<test_verilated> and C<test_regress> directories when using I<make test>.
This is disabled by default as SystemC installation problems would
otherwise falsely indicate a Verilator problem.
=back
@@ -460,12 +503,6 @@ There are some traps to avoid when running regression tests
=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.
@@ -608,8 +645,8 @@ Shows the value of the node's user1p...user5p, if non-NULL.
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:
If a data type is present and is numeric, it then prints the width of the
item. This field is a sequence of flag characters and width data as follows:
C<s> if the node is signed.
@@ -748,7 +785,7 @@ in C<src/Makefile_obj.in> and reconfigure.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2008-2013 by Wilson Snyder. Verilator is free software; you can
Copyright 2008-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2013 by Wilson Snyder. This package is free software; you
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2013 by Wilson Snyder. This package is free software; you
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2013 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2013 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2013 by Wilson Snyder. This package is free software; you
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -183,7 +183,7 @@ Runs a specific test stage (see the script).
=head1 DISTRIBUTION
Copyright 2009-2013 by Wilson Snyder. This package is free software; you
Copyright 2009-2015 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2013 by Wilson Snyder. This package is free software; you
Copyright 2005-2015 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2007-2013 by Wilson Snyder. This package is free software; you
Copyright 2007-2015 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2013 by Wilson Snyder. This package is free software; you
Copyright 2005-2015 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+2 -2
View File
@@ -8,7 +8,7 @@ use strict;
#======================================================================
# main
eval `modulecmd perl add synopsys-vcs`;
eval `modulecmd perl add synopsys-vcs_mx`;
exec('vcs',@ARGV);
#######################################################################
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2013 by Wilson Snyder. This package is free software; you
Copyright 2005-2015 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
-141
View File
@@ -1,141 +0,0 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2010-2013 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
#
# This program 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.
#
######################################################################
# DESCRIPTION: Diff Verilator includes against SystemPerl include files
use Getopt::Long;
use IO::File;
use strict;
our $Debug;
our $Bad;
if (! GetOptions (
#"help" => \&usage,
"debug" => sub { $Debug = 1; },
)) {
die "usage();"
}
diff("$ARGV[0]/include/verilated_vcd_c.h", "$ARGV[1]/src/SpTraceVcdC.h");
diff("$ARGV[0]/include/verilated_vcd_sc.h", "$ARGV[1]/src/SpTraceVcd.h");
diff("$ARGV[0]/include/verilated_vcd_c.cpp", "$ARGV[1]/src/SpTraceVcdC.cpp");
diff("$ARGV[0]/include/verilated_vcd_sc.cpp", "$ARGV[1]/src/SpTraceVcd.cpp");
exit(10) if $Bad;
sub diff {
my $a=shift;
my $b=shift;
my $ta = "/tmp/spdiff.$$.a";
my $tb = "/tmp/spdiff.$$.b";
prep($a,$ta);
prep($b,$tb);
system("diff -u -w $ta $tb");
}
sub prep {
my $filename = shift;
my $wfilename = shift;
my $sp;
if ($filename =~ m!src/Sp!) {
$sp = "Sp";
} elsif ($filename =~ m!include/verilated!) {
} else {
die "%Error: Not sure if Sp/Verilated: $filename,\n";
}
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
my @wf;
my $off;
while (defined(my $line = $fh->getline)) {
if ($line =~ m!// *SPDIFF_OFF!) {
$off = 1;
next;
} elsif ($line =~ m!// *SPDIFF_ON!) {
$off = 0;
next;
}
next if $off;
next if $line =~ /compile-command:/;
$line =~ s/SP_ABORT.*// if $sp;
$line =~ s/SP_NOTICE.*// if $sp;
$line =~ s/vl_fatal.*// if !$sp;
$line =~ s/VL_PRINT.*// if !$sp;
$line =~ s/Copyright \d+-\d+/Copyright #-#/g;
push @wf, $line;
my $check = $line;
$check =~ s/\bspace//i;
$check =~ s/\bsplit//i;
$check =~ s/"SP_TRACE"//;
if ($sp && $check =~ /Verilat/i
&& $check !~ /and newer/) {
warn "%Warning: $filename:$.: Verilator text in Sp version: $line";
$Bad = 1;
} elsif (!$sp && $check =~ /\b(Sp|SP)/
) {
warn "%Warning: $filename:$.: Sp text in Verilator version: $line";
$Bad = 1;
} elsif (!$sp && $check =~ /\<uint[0-9]+_t/) {
warn "%Warning: $filename:$.: uint in Verilator version: $line";
$Bad = 1;
}
}
!$off or die "%Error: $filename: SPDIFF_OFF block never terminated\n";
my $wholefile = join('',@wf);
if ($sp) {
$wholefile =~ s/SPTRACEVCDC_VERSION/VERILATED_VCD_VERSION/g;
$wholefile =~ s/SPTRACEVCDC_/VERILATED_VCD_C_/g;
$wholefile =~ s/SPTRACEVCD_TEST/VERILATED_VCD_TEST/g;
$wholefile =~ s/SPTRACEVCD_/VERILATED_VCD_SC_/g;
#
$wholefile =~ s/\bSpTraceFile\b/VerilatedVcdSc/g;
$wholefile =~ s/\bSpTraceFileC\b/VerilatedVcdC/g;
$wholefile =~ s/\bSpTraceVcd\b/VerilatedVcd/g;
$wholefile =~ s/\bSpTraceVcdCFile\b/VerilatedVcdC/g;
#
$wholefile =~ s/\bSpTraceCallInfo\b/VerilatedVcdCallInfo/g;
$wholefile =~ s/\bSpTraceCallback_t/VerilatedVcdCallback_t/g;
$wholefile =~ s/\bSpTraceVcd_/VerilatedVcd_/g;
$wholefile =~ s/\bSpTraceVcdSig\b/VerilatedVcdSig/g;
$wholefile =~ s/\bSpScBvExposer/VlScBvExposer/g;
#
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
$wholefile =~ s/%ll/%" VL_PRI64 "/g;
$wholefile =~ s/\(long long unsigned\)n/ n/g; # printQuad
#
$wholefile =~ s/\bSP_SC_BV/VL_SC_BV/g;
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
}
$fho->print($wholefile);
}
# Local Variables:
# compile-command: "./spdiff $SYP $V4"
# End:
+1 -1
View File
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2013 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,6 +1,6 @@
# DESCRIPTION: Verilator: GDB startup file with useful defines
#
# Copyright 2012-2013 by Wilson Snyder. This program is free software; you can
# Copyright 2012-2015 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.
+7 -3
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -46,7 +46,7 @@ obj_opt:
obj_dbg:
mkdir $@
.PHONY: ../verilator_bin ../verilator_bin_dbg
.PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
opt: ../verilator_bin
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
@@ -59,11 +59,15 @@ else
cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
endif
dbg: ../verilator_bin_dbg
dbg: ../verilator_bin_dbg ../verilator_coverage_bin_dbg
../verilator_bin_dbg: obj_dbg prefiles
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
../verilator_coverage_bin_dbg: obj_dbg prefiles
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 VL_VLCOV=1 -f ../Makefile_obj serial_vlcov
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 VL_VLCOV=1 -f ../Makefile_obj
prefiles::
prefiles:: config_rev.h
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
+31 -15
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -62,6 +62,8 @@ CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CPPFLAGS += @CPPFLAGS@
LDFLAGS += @LDFLAGS@
EXEEXT = @EXEEXT@
CFG_CXXFLAGS_SRC = @CFG_CXXFLAGS_SRC@
CFG_CXXFLAGS_PARSER = @CFG_CXXFLAGS_PARSER@
#### End of system configuration section. ####
@@ -85,7 +87,8 @@ endif
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
# -lfl not needed as Flex invoked with %nowrap option
LIBS = -lm
# -lstdc++ needed for clang, believed harmless with gcc
LIBS = -lm -lstdc++
CPPFLAGS += -MMD
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
@@ -94,11 +97,11 @@ CPPFLAGS += -DYYDEBUG # Required to get nice error messages
CPPFLAGS += $(COPT)
CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
#CPPFLAGS += -pedantic-errors
endif
CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
@@ -127,6 +130,7 @@ HEADERS = $(wildcard V*.h v*.h)
ASTGEN = $(srcdir)/astgen
BISONPRE = $(srcdir)/bisonpre
FLEXFIX = $(srcdir)/flexfix
VLCOVGEN = $(srcdir)/vlcovgen
######################################################################
#### Top level
@@ -186,6 +190,7 @@ RAW_OBJS = \
V3Error.o \
V3Expand.o \
V3File.o \
V3FileLine.o \
V3Gate.o \
V3GenClk.o \
V3Graph.o \
@@ -210,6 +215,7 @@ RAW_OBJS = \
V3Number.o \
V3Options.o \
V3Order.o \
V3Os.o \
V3Param.o \
V3PreShell.o \
V3Premit.o \
@@ -233,26 +239,30 @@ RAW_OBJS = \
V3WidthSel.o \
# Non-concatable
OBJS += \
NC_OBJS += \
V3ParseImp.o \
V3ParseGrammar.o \
V3ParseLex.o \
V3PreProc.o \
# verilator_coverage
VLCOV_OBJS = \
VlcMain.o \
#### Linking
ifeq ($(VL_DEBUG),)
# Building with fewer objects to better optimize
#OBJS += V3__CONCAT.o
OBJS += $(RAW_OBJS)
ifeq ($(VL_VLCOV),)
PREDEP_H = V3Ast__gen_classes.h
OBJS += $(RAW_OBJS) $(NC_OBJS)
else
OBJS += $(RAW_OBJS)
PREDEP_H =
OBJS += $(VLCOV_OBJS)
endif
V3__CONCAT.cpp: $(addsuffix .cpp, $(basename $(RAW_OBJS)))
$(PERL) $(srcdir)/../bin/verilator_includer $^ > $@
$(TGT): V3Ast__gen_classes.h $(OBJS)
$(TGT): $(PREDEP_H) $(OBJS)
@echo " Linking $@..."
-rm -rf $@ [email protected]
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
@@ -271,22 +281,28 @@ V3Number_test: V3Number_test.o
$(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
$(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
V3ParseGrammar.o: V3ParseGrammar.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
$(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
V3ParseImp.o: V3ParseImp.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
$(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
$(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
#### Generated files
# Target rule called before parallel build to make generated files
serial:: V3Ast__gen_classes.h V3ParseBison.c
serial_vlcov:: vlcovgen.d
vlcovgen.d: $(VLCOVGEN) $(srcdir)/include/verilated_cov_key.h
$(PERL) $(VLCOVGEN) --srcdir $(srcdir)
touch $@
V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
$(PERL) $(ASTGEN) -I$(srcdir) --classes
+14 -9
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -163,7 +163,7 @@ public:
class ActiveDlyVisitor : public ActiveBaseVisitor {
public:
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL };
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
private:
CheckType m_check; // Combo logic or other
AstNode* m_alwaysp; // Always we're under
@@ -175,6 +175,8 @@ private:
UINFO(5," ASSIGNDLY "<<nodep<<endl);
if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
} else if (m_check == CT_LATCH) {
// Suppress. Shouldn't matter that the interior of the latch races
} else {
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
}
@@ -291,7 +293,7 @@ private:
}
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
if (!m_scopeFinalp) {
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep());
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final_"+m_namer.scopep()->nameDotless(), m_namer.scopep());
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
m_scopeFinalp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
m_scopeFinalp->dontCombine(true);
@@ -306,7 +308,7 @@ private:
}
// METHODS
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp) {
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp, VAlwaysKwd kwd) {
// Move always to appropriate ACTIVE based on its sense list
if (oldsensesp
&& oldsensesp->sensesp()
@@ -326,12 +328,10 @@ private:
bool sequent = m_itemSequent;
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
#ifndef NEW_ORDERING
if (combo && sequent) {
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
sequent = false;
}
#endif
AstActive* wantactivep = NULL;
if (combo && !sequent) {
@@ -360,7 +360,11 @@ private:
// Warn and/or convert any delayed assignments
if (combo && !sequent) {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
if (kwd == VAlwaysKwd::ALWAYS_LATCH) {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_LATCH);
} else {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO);
}
}
else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
@@ -376,13 +380,13 @@ private:
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
visitAlways(nodep, nodep->sensesp());
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
}
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
visitAlways(nodep, nodep->sensesp());
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
}
virtual void visit(AstSenGate* nodep, AstNUser*) {
AstSenItem* subitemp = nodep->sensesp();
@@ -432,4 +436,5 @@ public:
void V3Active::activeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("active.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+2 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -160,4 +160,5 @@ public:
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveTopVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("activetop.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+76 -45
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2015 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.
@@ -56,15 +56,18 @@ private:
+":"+cvtToStr(nodep->fileline()->lineno())
+": Assertion failed in %m"
+((message != "")?": ":"")+message
+"\\n");
+"\n");
}
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
nodep->displayType(AstDisplayType::DT_WRITE);
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
// cppcheck-suppress nullPointer
timesp = timesp->addNext(new AstTime(nodep->fileline()));
nodep->fmtp()->exprsp(timesp);
AstNode* timenewp = new AstTime(nodep->fileline());
if (AstNode* timesp = nodep->fmtp()->exprsp()) {
timesp->unlinkFrBackWithNext();
timenewp->addNext(timesp);
}
nodep->fmtp()->exprsp(timenewp);
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
}
@@ -73,25 +76,16 @@ private:
AstNode* newIfAssertOn(AstNode* nodep) {
// Add a internal if to check assertions are on.
// Don't make this a AND term, as it's unlikely to need to test this.
return new AstIf (nodep->fileline(),
// If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
nodep, NULL);
}
AstNode* newIfCoverageOn(AstNode* nodep) {
// Add a internal if to check coverage is on
// Don't make this a AND term, as it's unlikely to need to test this.
return new AstIf (nodep->fileline(),
// If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.coverage()
? (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicTrue()))
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
nodep, NULL);
AstNode* newp
= new AstIf (nodep->fileline(),
// If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
nodep, NULL);
newp->user1(true); // Don't assert/cover this if
return newp;
}
AstNode* newFireAssert(AstNode* nodep, const string& message) {
@@ -122,19 +116,13 @@ private:
if (message!="") covincp->declp()->comment(message);
bodysp = covincp;
}
} else if (nodep->castPslAssert()) {
bodysp = newFireAssert(nodep,message);
// We assert the property is always true... so report when it fails
// (Note this is opposite the behavior of coverage statements.)
// Need: 'never' operator: not hold in current or any future cycle
propp = new AstLogNot (nodep->fileline(), propp);
} else {
nodep->v3fatalSrc("Unknown node type");
}
if (stmtsp) bodysp = bodysp->addNext(stmtsp);
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
//
AstNode* newp = new AstAlways (nodep->fileline(),
VAlwaysKwd::ALWAYS,
@@ -174,6 +162,62 @@ private:
// Bye
pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstIf* nodep, AstNUser*) {
if (nodep->user1SetOnce()) return;
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
AstNodeIf* ifp = nodep;
AstNode* propp = NULL;
bool hasDefaultElse = false;
do {
// If this statement ends with 'else if', then nextIf will point to the
// nextIf statement. Otherwise it will be null.
AstNodeIf* nextifp = dynamic_cast<AstNodeIf*>(ifp->elsesp());
ifp->condp()->iterateAndNext(*this);
// Recurse into the true case.
ifp->ifsp()->iterateAndNext(*this);
// If the last else is not an else if, recurse into that too.
if (ifp->elsesp() && !nextifp) {
ifp->elsesp()->iterateAndNext(*this);
}
// Build a bitmask of the true predicates
AstNode* predp = ifp->condp()->cloneTree(false);
if (propp) {
propp = new AstConcat(nodep->fileline(), predp, propp);
} else {
propp = predp;
}
// Record if this ends with an 'else' that does not have an if
if (ifp->elsesp() && !nextifp) {
hasDefaultElse = true;
}
ifp = nextifp;
} while (ifp);
AstNode *newifp = nodep->cloneTree(false);
bool allow_none = nodep->unique0Pragma();
// Note: if this ends with an 'else', then we don't need to validate that one of the
// predicates evaluates to true.
AstNode* ohot = ((allow_none || hasDefaultElse)
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
: (new AstOneHot (nodep->fileline(), propp))->castNode());
AstIf* checkifp = new AstIf (nodep->fileline(),
new AstLogNot (nodep->fileline(), ohot),
newFireAssert(nodep, "'unique if' statement violated"),
newifp);
checkifp->branchPred(AstBranchPred::BP_UNLIKELY);
nodep->replaceWith(checkifp);
pushDeletep(nodep);
} else {
nodep->iterateChildren(*this);
}
}
// VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) {
@@ -244,12 +288,6 @@ private:
nodep->stmtsp(), nodep->name()); nodep=NULL;
++m_statAsCover;
}
virtual void visit(AstPslAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this);
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
NULL, nodep->name()); nodep=NULL;
++m_statAsPsl;
}
virtual void visit(AstVAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this);
newVAssertion(nodep, nodep->propp()); nodep=NULL;
@@ -274,14 +312,6 @@ private:
m_beginp = lastp;
}
// VISITORS //========== Temporal Layer
// VISITORS //========== Boolean Layer
virtual void visit(AstPslBool* nodep, AstNUser*) {
nodep->replaceWith(nodep->exprp()->unlinkFrBack());
pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
@@ -307,4 +337,5 @@ public:
void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("assert.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+2 -16
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2015 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.
@@ -73,14 +73,6 @@ private:
}
// VISITORS //========== Statements
virtual void visit(AstPslDefClock* nodep, AstNUser*) {
nodep->iterateChildren(*this);
// Store the new default clock, reset on new module
m_seniDefaultp = nodep->sensesp();
// Trash it
nodep->unlinkFrBack();
pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstClocking* nodep, AstNUser*) {
UINFO(8," CLOCKING"<<nodep<<endl);
// Store the new default clock, reset on new module
@@ -101,13 +93,6 @@ private:
nodep->sentreep(newSenTree(nodep));
clearAssertInfo();
}
virtual void visit(AstPslAssert* nodep, AstNUser*) {
if (nodep->sentreep()) return; // Already processed
clearAssertInfo();
nodep->iterateChildren(*this);
nodep->sentreep(newSenTree(nodep));
clearAssertInfo();
}
virtual void visit(AstPslClocked* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_senip) {
@@ -152,4 +137,5 @@ public:
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertPreVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("assertpre.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2015 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.
+50 -46
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -176,6 +176,10 @@ string AstNode::prettyName(const string& namein) {
pretty += ".";
pos += 7;
}
else if (0==strncmp(pos,"->",2)) {
pretty += ".";
pos += 2;
}
else if (0==strncmp(pos,"__PVT__",7)) {
pretty += "";
pos += 7;
@@ -203,31 +207,6 @@ string AstNode::prettyTypeName() const {
return string(typeName())+" '"+prettyName()+"'";
}
string AstNode::quoteName(const string& namein) {
// Encode control chars into C style escapes
// Reverse is V3Parse::deQuote
const char* start = namein.c_str();
string out;
for (const char* pos = start; *pos; pos++) {
if (pos[0]=='\\' || pos[0]=='"') {
out += string("\\")+pos[0];
} else if (pos[0]=='\n') {
out += "\\n";
} else if (pos[0]=='\r') {
out += "\\r";
} else if (pos[0]=='\t') {
out += "\\t";
} else if (isprint(pos[0])) {
out += pos[0];
} else {
// This will also cover \a etc
char octal[10]; sprintf(octal,"\\%03o",pos[0]);
out += octal;
}
}
return out;
}
//######################################################################
// Insertion
@@ -239,6 +218,9 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// // Commenting out the section below may crash, as the tree state
// // between edits is not always consistent for printing
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
// if (next||1) this->dumpTreeAndNext(cout, prefix);
// else this->dumpTree(cout, prefix);
@@ -561,7 +543,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
if (linkerp->m_iterpp) {
// If we're iterating over a next() link, we need to follow links off the
// NEW node. Thus we pass iteration information via a pointer in the node.
// This adds a unfortunate 4 bytes to every AstNode, but is faster than passing
// This adds a unfortunate hot 8 bytes to every AstNode, but is faster than passing
// across every function.
// If anyone has a cleaner way, I'd be grateful.
*(linkerp->m_iterpp) = newp;
@@ -750,6 +732,20 @@ void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) {
if (m_op4p) m_op4p->iterateAndNext(v, vup);
}
void AstNode::iterateChildrenConst(AstNVisitor& v, AstNUser* vup) {
// This is a very hot function
if (!this) return;
ASTNODE_PREFETCH(m_op1p);
ASTNODE_PREFETCH(m_op2p);
ASTNODE_PREFETCH(m_op3p);
ASTNODE_PREFETCH(m_op4p);
// if () not needed since iterateAndNext accepts null this, but faster with it.
if (m_op1p) m_op1p->iterateAndNextConst(v, vup);
if (m_op2p) m_op2p->iterateAndNextConst(v, vup);
if (m_op3p) m_op3p->iterateAndNextConst(v, vup);
if (m_op4p) m_op4p->iterateAndNextConst(v, vup);
}
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
// This is a very hot function
// IMPORTANT: If you replace a node that's the target of this iterator,
@@ -764,16 +760,18 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
while (nodep) {
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
ASTNODE_PREFETCH(nodep->m_nextp);
// Desirable check, but many places where multiple iterations are OK
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
// cppcheck-suppress nullPointer
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;
if (!niterp) return; // Perhaps node deleted inside accept
niterp->m_iterpp = NULL;
if (VL_UNLIKELY(niterp!=nodep)) { // Edited it
if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept
nodep = niterp;
} else { // Same node, just loop
} else { // Unchanged node, just continue loop
nodep = niterp->m_nextp;
}
}
@@ -799,11 +797,12 @@ void AstNode::iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup) {
this->op4p()->iterateListBackwards(v,vup);
}
void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
void AstNode::iterateAndNextConst(AstNVisitor& v, AstNUser* vup) {
// Keep following the current list even if edits change it
if (!this) return;
for (AstNode* nodep=this; nodep; ) {
AstNode* nnextp = nodep->m_nextp;
ASTNODE_PREFETCH(nnextp);
nodep->accept(v, vup);
nodep = nnextp;
}
@@ -864,24 +863,21 @@ void AstNode::cloneRelinkTree() {
//======================================================================
// Comparison
bool AstNode::sameTree(AstNode* node2p) {
return sameTreeIter(node2p, true);
}
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
// Return true if the two trees are identical
if (this==NULL && node2p==NULL) return true;
if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type()
|| this->dtypep() != node2p->dtypep()
|| !this->same(node2p)) {
|| !this->same(node2p)
|| (gateOnly && !this->isGateOptimizable())) {
return false;
}
return (this->op1p()->sameTreeIter(node2p->op1p(),false)
&& this->op2p()->sameTreeIter(node2p->op2p(),false)
&& this->op3p()->sameTreeIter(node2p->op3p(),false)
&& this->op4p()->sameTreeIter(node2p->op4p(),false)
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false))
return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
&& this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
&& this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
&& this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
);
}
@@ -895,8 +891,8 @@ ostream& operator<<(ostream& os, V3Hash rhs) {
V3Hash::V3Hash(const string& name) {
uint32_t val = 0;
for (const char* c=name.c_str(); *c; c++) {
val = val*31 + *c;
for (string::const_iterator it = name.begin(); it!=name.end(); ++it) {
val = val*31 + *it;
}
setBoth(1,val);
}
@@ -965,6 +961,14 @@ void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
v3Global.rootp()->dumpTreeFile(filename);
}
void AstNode::checkIter() const {
if (m_iterpp) {
dumpPtrs(cout);
// Perhaps something forgot to clear m_iterpp?
this->v3fatalSrc("Iteration link should be NULL");
}
}
void AstNode::dumpPtrs(ostream& os) const {
os<<"This="<<typeName()<<" "<<(void*)this;
os<<" back="<<(void*)backp();
@@ -1008,8 +1012,8 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
}
}
void AstNode::dumpTreeFile(const string& filename, bool append) {
if (v3Global.opt.dumpTree()) {
void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
if (doDump) {
{ // Write log & close
UINFO(2,"Dumping "<<filename<<endl);
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
+165 -55
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -23,6 +23,7 @@
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3FileLine.h"
#include "V3Number.h"
#include "V3Global.h"
#include <vector>
@@ -38,6 +39,9 @@ class VFlagLogicPacked {};
class VFlagBitPacked {};
class VFlagChildDType {}; // Used by parser.y to select constructor that sets childDType
// For broken() function, return error string if have a match
#define BROKEN_RTN(test) do { if (VL_UNLIKELY(test)) return # test; } while(0)
//######################################################################
class AstType {
@@ -89,6 +93,8 @@ public:
else if (signst==signedst_SIGNED) m_e=SIGNED;
else m_e=NOSIGN;
}
static inline AstNumeric fromBool (bool isSigned) { // Factory method
return isSigned ? AstNumeric(SIGNED) : AstNumeric(UNSIGNED); }
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
inline bool isSigned() const { return m_e==SIGNED; }
@@ -231,6 +237,15 @@ public:
DIM_SIZE, // V3Width processes
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
//
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
//
ENUM_FIRST, // V3Width processes
ENUM_LAST, // V3Width processes
ENUM_NUM, // V3Width processes
ENUM_NEXT, // V3Width processes
ENUM_PREV, // V3Width processes
ENUM_NAME, // V3Width processes
//
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
//
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@@ -242,7 +257,9 @@ public:
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
VAR_SFORMAT, // V3LinkParse moves to AstVar::attrSFormat
VAR_CLOCKER, // V3LinkParse moves to AstVar::attrClocker
VAR_NO_CLOCKER // V3LinkParse moves to AstVar::attrClocker
};
enum en m_e;
const char* ascii() const {
@@ -250,10 +267,13 @@ public:
"%E-AT",
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
"DT_PUBLIC",
"ENUM_FIRST", "ENUM_LAST", "ENUM_NUM", "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME",
"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"
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER",
"VAR_NO_CLOCKER"
};
return names[m_e];
};
@@ -375,9 +395,8 @@ public:
bool isOpaque() const { // IE not a simple number we can bit optimize
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
}
bool isDouble() const {
return (m_e==DOUBLE);
}
bool isDouble() const { return m_e==DOUBLE; }
bool isString() const { return m_e==STRING; }
};
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); }
@@ -407,7 +426,8 @@ public:
BLOCKTEMP,
MODULETEMP,
STMTTEMP,
XTEMP
XTEMP,
IFACEREF // Used to link Interfaces between modules
};
enum en m_e;
inline AstVarType () : m_e(UNKNOWN) {}
@@ -421,7 +441,8 @@ public:
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE",
"TRIWIRE","TRI0","TRI1",
"PORT",
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
"IFACEREF"};
return names[m_e]; }
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE
|| m_e==TRIWIRE
@@ -467,6 +488,37 @@ public:
//######################################################################
class AstVarAttrClocker {
public:
enum en {
CLOCKER_UNKNOWN=0,
CLOCKER_YES,
CLOCKER_NO,
_ENUM_END
};
enum en m_e;
// CONSTRUCTOR - note defaults to *UNKNOWN*
inline AstVarAttrClocker () : m_e(CLOCKER_UNKNOWN) {}
inline AstVarAttrClocker (en _e) : m_e(_e) {}
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
AstVarAttrClocker invert() const {
if (m_e==CLOCKER_YES) return CLOCKER_NO;
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
else return m_e;
}
const char* ascii() const {
static const char* names[] = {
"","clker","non_clker"};
return names[m_e]; }
};
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstVarAttrClocker::en lhs, AstVarAttrClocker rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstVarAttrClocker rhs) { return os<<rhs.ascii(); }
//######################################################################
class VAlwaysKwd {
public:
enum en {
@@ -491,22 +543,23 @@ public:
//######################################################################
class AstCaseType {
class VCaseType {
public:
enum en {
CT_CASE,
CT_CASEX,
CT_CASEZ
CT_CASEZ,
CT_CASEINSIDE
};
enum en m_e;
inline AstCaseType () : m_e(CT_CASE) {}
inline AstCaseType (en _e) : m_e(_e) {}
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
inline VCaseType () : m_e(CT_CASE) {}
inline VCaseType (en _e) : m_e(_e) {}
explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
};
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); }
inline bool operator== (VCaseType lhs, VCaseType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (VCaseType lhs, VCaseType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (VCaseType::en lhs, VCaseType rhs) { return (lhs == rhs.m_e); }
//######################################################################
@@ -600,13 +653,16 @@ struct VNumRange {
int lo() const { return m_lo; }
int left() const { return littleEndian()?lo():hi(); } // How to show a declaration
int right() const { return littleEndian()?hi():lo(); }
int leftToRightInc() const { return littleEndian()?1:-1; }
int elements() const { return hi()-lo()+1; }
bool ranged() const { return m_ranged; }
bool littleEndian() const { return m_littleEndian; }
int hiMaxSelect() const { return (lo()<0 ? hi()-lo() : hi()); } // Maximum value a [] select may index
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
{ return (!m_ranged || (m_lo==0 && m_hi>=1 && !m_littleEndian)); }
void dump(ostream& str) const { if (ranged()) str<<"["<<left()<<":"<<right()<<"]"; else str<<"[norg]"; }
};
inline ostream& operator<<(ostream& os, VNumRange rhs) { rhs.dump(os); return os; }
//######################################################################
@@ -921,7 +977,7 @@ class AstNode {
AstNode* cloneTreeIterList();
void checkTreeIter(AstNode* backp);
void checkTreeIterList(AstNode* backp);
bool sameTreeIter(AstNode* node2p, bool ignNext);
bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
void deleteTreeIter();
void deleteNode();
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
@@ -993,6 +1049,7 @@ public:
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics
static int instrCountString() { return 100; } ///< Instruction cycles to do string ops
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
@@ -1002,13 +1059,13 @@ public:
virtual string verilogKwd() const { return ""; }
string shortName() const; // Name with __PVT__ removed for concatenating scopes
static string dedotName(const string& namein); // Name with dots removed
static string quoteName(const string& namein); // Name with control chars quoted
static string prettyName(const string& namein); // Name for printing out to the user
static string encodeName(const string& namein); // Encode user name into internal C representation
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
static string vcdName(const string& namein); // Name for printing out to vcd files
string prettyName() const { return prettyName(name()); }
string prettyTypeName() const; // "VARREF name" for error messages
string prettyTypeName() const; // "VARREF" for error messages
virtual string prettyOperatorName() const { return "operator "+prettyTypeName(); }
FileLine* fileline() const { return m_fileline; }
void fileline(FileLine* fl) { m_fileline=fl; }
bool width1() const;
@@ -1027,6 +1084,7 @@ public:
bool isWide() const { return (width()>VL_QUADSIZE); }
bool isDouble() const;
bool isSigned() const;
bool isString() const;
AstNUser* user1p() const {
// Slows things down measurably, so disabled by default
@@ -1104,6 +1162,7 @@ public:
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
void dtypeSetDouble() { dtypep(findDoubleDType()); }
void dtypeSetString() { dtypep(findStringDType()); }
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
@@ -1111,6 +1170,7 @@ public:
// Data type locators
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); }
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
@@ -1146,14 +1206,17 @@ public:
// METHODS - Iterate on a tree
AstNode* cloneTree(bool cloneNextLink);
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
void deleteTree(); // Always deletes the next link
void checkTree(); // User Interface version
void checkIter() const;
void clearIter() { m_iterpp=NULL; }
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);
void dumpTreeFile(const string& filename, bool append=false, bool doDump=true);
static void dumpTreeFileGdb(const char* filenamep=NULL);
// METHODS - queries
@@ -1171,15 +1234,17 @@ public:
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; }
virtual const char* broken() const { return NULL; }
// INVOKERS
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
void iterate(AstNVisitor& v, AstNUser* vup=NULL) { this->accept(v,vup); } // Does this; excludes following this->next
void iterateAndNext(AstNVisitor& v, AstNUser* vup=NULL);
void iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup=NULL);
void iterateAndNextConst(AstNVisitor& v, AstNUser* vup=NULL);
void iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup=NULL) { iterateAndNextConst(v, vup); }
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
void iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
void iterateChildrenConst(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
AstNode* acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup=NULL); // Return edited nodep; see comments in V3Ast.cpp
// CONVERSION
@@ -1200,8 +1265,9 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
virtual ~Ast ##name() {} \
Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##name(); }
struct AstNodeMath : public AstNode {
class AstNodeMath : public AstNode {
// Math -- anything that's part of an expression tree
public:
AstNodeMath(FileLine* fl)
: AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeMath)
@@ -1216,8 +1282,9 @@ struct AstNodeMath : public AstNode {
bool isOpaque() { return castCvtPackString()!=NULL; }
};
struct AstNodeTermop : public AstNodeMath {
class AstNodeTermop : public AstNodeMath {
// Terminal operator -- a operator with no "inputs"
public:
AstNodeTermop(FileLine* fl)
: AstNodeMath(fl) {}
ASTNODE_BASE_FUNCS(NodeTermop)
@@ -1227,8 +1294,9 @@ struct AstNodeTermop : public AstNodeMath {
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
};
struct AstNodeUniop : public AstNodeMath {
class AstNodeUniop : public AstNodeMath {
// Unary math
public:
AstNodeUniop(FileLine* fl, AstNode* lhsp)
: AstNodeMath(fl) {
dtypeFrom(lhsp);
@@ -1240,15 +1308,17 @@ struct AstNodeUniop : public AstNodeMath {
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0;
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; }
};
struct AstNodeBiop : public AstNodeMath {
class AstNodeBiop : public AstNodeMath {
// Binary math
public:
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); }
@@ -1263,15 +1333,17 @@ struct AstNodeBiop : public AstNodeMath {
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; }
};
struct AstNodeTriop : public AstNodeMath {
class AstNodeTriop : public AstNodeMath {
// Trinary math
public:
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
@@ -1295,20 +1367,23 @@ struct AstNodeTriop : public AstNodeMath {
virtual bool same(AstNode*) const { return true; }
};
struct AstNodeBiCom : public AstNodeBiop {
class AstNodeBiCom : public AstNodeBiop {
// Binary math with commutative properties
public:
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiop(fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiCom)
};
struct AstNodeBiComAsv : public AstNodeBiCom {
class AstNodeBiComAsv : public AstNodeBiCom {
// Binary math with commutative & associative properties
public:
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiCom(fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiComAsv)
};
struct AstNodeCond : public AstNodeTriop {
class AstNodeCond : public AstNodeTriop {
public:
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop(fl, condp, expr1p, expr2p) {
if (expr1p) dtypeFrom(expr1p);
@@ -1330,8 +1405,9 @@ struct AstNodeCond : public AstNodeTriop {
virtual int instrCount() const { return instrCountBranch(); }
};
struct AstNodePreSel : public AstNode {
class AstNodePreSel : public AstNode {
// Something that becomes an AstSel
public:
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNode(fl) {
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
@@ -1350,8 +1426,9 @@ struct AstNodePreSel : public AstNode {
virtual bool same(AstNode*) const { return true; }
};
struct AstNodeStmt : public AstNode {
class AstNodeStmt : public AstNode {
// Statement -- anything that's directly under a function
public:
AstNodeStmt(FileLine* fl)
: AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeStmt)
@@ -1360,7 +1437,8 @@ struct AstNodeStmt : public AstNode {
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
};
struct AstNodeAssign : public AstNodeStmt {
class AstNodeAssign : public AstNodeStmt {
public:
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt(fl) {
setOp1p(rhsp); setOp2p(lhsp);
@@ -1381,7 +1459,8 @@ struct AstNodeAssign : public AstNodeStmt {
virtual string verilogKwd() const { return "="; }
};
struct AstNodeFor : public AstNodeStmt {
class AstNodeFor : public AstNodeStmt {
public:
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* incsp, AstNode* bodysp)
: AstNodeStmt(fileline) {
@@ -1398,7 +1477,7 @@ struct AstNodeFor : public AstNodeStmt {
virtual bool same(AstNode* samep) const { return true; }
};
struct AstNodeIf : public AstNodeStmt {
class AstNodeIf : public AstNodeStmt {
private:
AstBranchPred m_branchPred; // Branch prediction as taken/untaken?
public:
@@ -1422,7 +1501,8 @@ public:
AstBranchPred branchPred() const { return m_branchPred; }
};
struct AstNodeCase : public AstNodeStmt {
class AstNodeCase : public AstNodeStmt {
public:
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
: AstNodeStmt(fl) {
setOp1p(exprp); addNOp2p(casesp);
@@ -1436,8 +1516,9 @@ struct AstNodeCase : public AstNodeStmt {
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
};
struct AstNodeSenItem : public AstNode {
class AstNodeSenItem : public AstNode {
// An AstSenItem or AstSenGate
public:
AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeSenItem)
virtual bool isClocked() const = 0;
@@ -1472,7 +1553,7 @@ public:
}
ASTNODE_BASE_FUNCS(NodeVarRef)
virtual bool hasDType() const { return true; }
virtual bool broken() const;
virtual const char* broken() const;
virtual int instrCount() const { return widthInstrs(); }
virtual void cloneRelink();
virtual string name() const { return m_name; } // * = Var name
@@ -1495,7 +1576,7 @@ public:
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
};
struct AstNodeText : public AstNode {
class AstNodeText : public AstNode {
private:
string m_text;
public:
@@ -1512,11 +1593,11 @@ public:
const string& text() const { return m_text; }
};
struct AstNodeDType : public AstNode {
private:
class AstNodeDType : public AstNode {
// 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
private:
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
@@ -1534,7 +1615,9 @@ public:
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 AstNodeDType* skipRefp() const = 0; // recurses over typedefs/const/enum to next non-typeref type
virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type
virtual AstNodeDType* skipRefToEnump() const = 0; // recurses over typedefs/const to next non-typeref-or-enum/struct 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; }
@@ -1564,7 +1647,7 @@ public:
static int uniqueNumInc() { return ++s_uniqueNum; }
};
struct AstNodeClassDType : public AstNodeDType {
class AstNodeClassDType : public AstNodeDType {
private:
// TYPES
typedef map<string,AstMemberDType*> MemberNameMap;
@@ -1579,17 +1662,20 @@ public:
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
}
ASTNODE_BASE_FUNCS(NodeClassDType)
virtual bool broken() const;
virtual const char* 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 AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() 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; }
bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs
void clearCache() { m_members.clear(); }
void repairMemberCache();
AstMemberDType* findMember(const string& name) const {
@@ -1601,7 +1687,7 @@ public:
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
};
struct AstNodeArrayDType : public AstNodeDType {
class AstNodeArrayDType : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds)
@@ -1615,8 +1701,8 @@ public:
ASTNODE_BASE_FUNCS(NodeArrayDType)
virtual void dump(ostream& str);
virtual void dumpSmall(ostream& str);
virtual bool broken() const { return !((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep())); }
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep()))); return NULL; }
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
m_refDTypep = m_refDTypep->clonep()->castNodeDType();
}}
@@ -1638,6 +1724,8 @@ public:
// METHODS
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
int msb() const;
@@ -1646,8 +1734,9 @@ public:
VNumRange declRange() const;
};
struct AstNodeSel : public AstNodeBiop {
class AstNodeSel : public AstNodeBiop {
// Single bit range extraction, perhaps with non-constant selection or array selection
public:
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeBiop(fl, fromp, bitp) {}
ASTNODE_BASE_FUNCS(NodeSel)
@@ -1659,10 +1748,21 @@ struct AstNodeSel : public AstNodeBiop {
virtual bool hasDType() const { return true; }
};
class AstNodeStream : public AstNodeBiop {
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
public:
AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp->dtypep()) {
dtypeSetLogicSized(lhsp->dtypep()->width(), lhsp->dtypep()->width(), AstNumeric::UNSIGNED);
}
}
ASTNODE_BASE_FUNCS(NodeStream)
};
//######################################################################
// Tasks/functions common handling
struct AstNodeFTask : public AstNode {
class AstNodeFTask : public AstNode {
private:
string m_name; // Name of task
string m_cname; // Name of task if DPI import
@@ -1720,7 +1820,7 @@ public:
bool pure() const { return m_pure; }
};
struct AstNodeFTaskRef : public AstNode {
class AstNodeFTaskRef : public AstNode {
// A reference to a task (or function)
private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
@@ -1740,7 +1840,7 @@ public:
addNOp2p(pinsp);
}
ASTNODE_BASE_FUNCS(NodeFTaskRef)
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; }
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
m_taskp = m_taskp->clonep()->castNodeFTask();
}}
@@ -1766,7 +1866,7 @@ public:
void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
};
struct AstNodeModule : public AstNode {
class AstNodeModule : public AstNode {
// A module, package, program or interface declaration;
// something that can live directly under the TOP,
// excluding $unit package stuff
@@ -1780,12 +1880,13 @@ private:
bool m_internal:1; // Internally created
int m_level; // 1=top module, 2=cell off top module, ...
int m_varNum; // Incrementing variable number
int m_typeNum; // Incrementing implicit type 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_dead(false), m_internal(false)
,m_level(0), m_varNum(0) { }
,m_level(0), m_varNum(0), m_typeNum(0) { }
ASTNODE_BASE_FUNCS(NodeModule)
virtual void dump(ostream& str);
virtual bool maybePointedTo() const { return true; }
@@ -1805,6 +1906,7 @@ public:
int level() const { return m_level; }
bool isTop() const { return level()==1; }
int varNumGetInc() { return ++m_varNum; }
int typeNumGetInc() { return ++m_typeNum; }
void modPublic(bool flag) { m_modPublic = flag; }
bool modPublic() const { return m_modPublic; }
void modTrace(bool flag) { m_modTrace = flag; }
@@ -1831,6 +1933,7 @@ inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() :
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::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
@@ -1838,6 +1941,8 @@ inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(node2p, true, false); }
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(node2p, true, true); }
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
@@ -1847,4 +1952,9 @@ inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); }
inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
inline void AstIfaceRefDType::cloneRelink() {
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep()->castCell();
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep()->castIface();
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep()->castModport(); }
#endif // Guard
+33
View File
@@ -0,0 +1,33 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Ast node structure
//
// Code available from: http://www.veripool.org/verilator
//
//*************************************************************************
//
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3ASTCONSTONLY_H_
#define _V3ASTCONSTONLY_H_ 1
// Include only in visitors that do not not edit nodes, so should use constant iterators
#define iterateAndNext error_use_iterateAndNextConst
#define iterateChildren error_use_iterateChildrenConst
#define addNext error_no_addNext_in_ConstOnlyVisitor
#define replaceWith error_no_replaceWith_in_ConstOnlyVisitor
#define deleteTree error_no_deleteTree_in_ConstOnlyVisitor
#define unlinkFrBack error_no_unlinkFrBack_in_ConstOnlyVisitor
#endif // Guard
+139 -20
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -35,8 +35,22 @@
// Special methods
// We need these here, because the classes they point to aren't defined when we declare the class
bool AstNodeVarRef::broken() const { return ((m_varScopep && !m_varScopep->brokeExists())
|| (m_varp && !m_varp->brokeExists())); }
const char* AstIfaceRefDType::broken() const {
BROKEN_RTN(m_ifacep && !m_ifacep->brokeExists());
BROKEN_RTN(m_cellp && !m_cellp->brokeExists());
BROKEN_RTN(m_modportp && !m_modportp->brokeExists());
return NULL;
}
AstIface* AstIfaceRefDType::ifaceViaCellp() const {
return ((m_cellp && m_cellp->modp()) ? m_cellp->modp()->castIface() : m_ifacep);
}
const char* AstNodeVarRef::broken() const {
BROKEN_RTN(m_varScopep && !m_varScopep->brokeExists());
BROKEN_RTN(m_varp && !m_varp->brokeExists());
return NULL;
}
void AstNodeVarRef::cloneRelink() {
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep()->castVar(); }
@@ -54,18 +68,18 @@ void AstNodeClassDType::repairMemberCache() {
}
}
bool AstNodeClassDType::broken() const {
const char* 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()) {
if (VL_UNLIKELY(exists.find(it->second) == exists.end())) {
this->v3error("Internal: Structure member broken: "<<it->first);
return true;
return "member broken";
}
}
return false;
return NULL;
}
int AstBasicDType::widthAlignBytes() const {
@@ -98,6 +112,35 @@ int AstNodeClassDType::widthAlignBytes() const {
else return 8;
}
AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
if (lhsp->isDouble() && rhsp->isDouble()) {
return new AstEqD(fl, lhsp, rhsp);
} else {
return new AstEq(fl, lhsp, rhsp);
}
}
AstNodeBiop* AstGte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
if (lhsp->isDouble() && rhsp->isDouble()) {
return new AstGteD(fl, lhsp, rhsp);
} else if (lhsp->isSigned() && rhsp->isSigned()) {
return new AstGteS(fl, lhsp, rhsp);
} else {
return new AstGte(fl, lhsp, rhsp);
}
}
AstNodeBiop* AstLte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
if (lhsp->isDouble() && rhsp->isDouble()) {
return new AstLteD(fl, lhsp, rhsp);
} else if (lhsp->isSigned() && rhsp->isSigned()) {
return new AstLteS(fl, lhsp, rhsp);
} else {
return new AstLte(fl, lhsp, rhsp);
}
}
bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
}
@@ -157,7 +200,7 @@ string AstVar::verilogKwd() const {
}
}
string AstVar::vlArgType(bool named, bool forReturn) const {
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
if (forReturn) named=false;
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
string arg;
@@ -190,7 +233,7 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
arg += " (& "+name();
arg += ")["+cvtToStr(widthWords())+"]";
} else {
if (isOutput() || (strtype && isInput())) arg += "&";
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
if (named) arg += " "+name();
}
return arg;
@@ -307,6 +350,27 @@ string AstVar::scType() const {
}
}
AstVar* AstVar::scVarRecurse(AstNode* nodep) {
// See if this is a SC assignment; if so return that type
// Historically sc variables are identified by a variable
// attribute. TODO it would better be a data type attribute.
if (AstVar* anodep = nodep->castVar()) {
if (anodep->isSc()) return anodep;
else return NULL;
}
else if (nodep->castVarRef()) {
if (nodep->castVarRef()->varp()->isSc()) return nodep->castVarRef()->varp();
else return NULL;
}
else if (nodep->castArraySel()) {
if (nodep->op1p()) if (AstVar* p = scVarRecurse(nodep->op1p())) return p;
if (nodep->op2p()) if (AstVar* p = scVarRecurse(nodep->op2p())) return p;
if (nodep->op3p()) if (AstVar* p = scVarRecurse(nodep->op3p())) return p;
if (nodep->op4p()) if (AstVar* p = scVarRecurse(nodep->op4p())) return p;
}
return NULL;
}
AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
// dimension passed from AstArraySel::dimension
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
@@ -419,10 +483,12 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable
return nodep;
}
bool AstScope::broken() const {
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|| !m_modp || !m_modp->brokeExists());
const char* AstScope::broken() const {
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
BROKEN_RTN(!m_modp);
BROKEN_RTN(m_modp && !m_modp->brokeExists());
return NULL;
}
void AstScope::cloneRelink() {
@@ -470,6 +536,24 @@ string AstScopeName::scopeSymName() const {
return out;
}
string AstScopeName::scopeDpiName() const {
string out;
for (AstText* textp=scopeEntrp(); textp; textp=textp->nextp()->castText()) {
out += textp->text();
}
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
if (out.substr(0,1) == ".") out.replace(0,1,"");
string::size_type pos;
while ((pos=out.find(".")) != string::npos) {
out.replace(pos, 1, "__");
}
while ((pos=out.find("__DOT__")) != string::npos) {
out.replace(pos, 7, "__");
}
return out;
}
bool AstSenTree::hasClocked() {
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
@@ -674,7 +758,10 @@ void AstNode::dump(ostream& str) {
} else { // V3Broken will throw an error
if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep();
}
if (name()!="") str<<" "<<AstNode::quoteName(name());
if (name()!="") {
if (castConst()) str<<" "<<name(); // Already quoted
else str<<" "<<V3Number::quoteNameControls(name());
}
}
void AstAlways::dump(ostream& str) {
@@ -718,18 +805,48 @@ void AstEnumItemRef::dump(ostream& str) {
if (itemp()) { itemp()->dump(str); }
else { str<<"UNLINKED"; }
}
void AstIfaceRefDType::dump(ostream& str) {
this->AstNode::dump(str);
if (cellName()!="") { str<<" cell="<<cellName(); }
if (ifaceName()!="") { str<<" if="<<ifaceName(); }
if (modportName()!="") { str<<" mp="<<modportName(); }
if (cellp()) { str<<" -> "; cellp()->dump(str); }
else if (ifacep()) { str<<" -> "; ifacep()->dump(str); }
else { str<<" -> UNLINKED"; }
}
void AstIfaceRefDType::dumpSmall(ostream& str) {
this->AstNodeDType::dumpSmall(str);
str<<"iface";
}
void AstJumpGo::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> ";
if (labelp()) { labelp()->dump(str); }
else { str<<"%Error:UNLINKED"; }
}
void AstModportFTaskRef::dump(ostream& str) {
this->AstNode::dump(str);
if (isExport()) str<<" EXPORT";
if (isImport()) str<<" IMPORT";
if (ftaskp()) { str<<" -> "; ftaskp()->dump(str); }
else { str<<" -> UNLINKED"; }
}
void AstModportVarRef::dump(ostream& str) {
this->AstNode::dump(str);
str<<" "<<varType();
if (varp()) { str<<" -> "; varp()->dump(str); }
else { str<<" -> UNLINKED"; }
}
void AstPin::dump(ostream& str) {
this->AstNode::dump(str);
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]";
}
void AstTypedef::dump(ostream& str) {
this->AstNode::dump(str);
if (attrPublic()) str<<" [PUBLIC]";
}
void AstRange::dump(ostream& str) {
this->AstNode::dump(str);
if (littleEndian()) str<<" [LITTLE]";
@@ -757,18 +874,21 @@ void AstNodeDType::dumpSmall(ostream& str) {
<<((isSigned()&&!isDouble())?"s":"")
<<(isNosign()?"n":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
<<(isString()?"str":"");
if (!isDouble() && !isString()) {
str<<"w"<<(widthSized()?"":"u")<<width();
}
if (!widthSized()) str<<"/"<<widthMin();
str<<")";
}
void AstNodeArrayDType::dumpSmall(ostream& str) {
this->AstNodeDType::dumpSmall(str);
if (castPackArrayDType()) str<<"p"; else str<<"u";
str<<"["<<declRange().left()<<":"<<declRange().right()<<"]";
str<<declRange();
}
void AstNodeArrayDType::dump(ostream& str) {
this->AstNodeDType::dump(str);
str<<" ["<<declRange().left()<<":"<<declRange().right()<<"]";
str<<" "<<declRange();
}
void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str);
@@ -784,7 +904,7 @@ void AstPackageImport::dump(ostream& str) {
void AstSel::dump(ostream& str) {
this->AstNode::dump(str);
if (declRange().ranged()) {
str<<" decl["<<declRange().left()<<":"<<declRange().right()<<"]";
str<<" decl"<<declRange()<<"]";
if (declElWidth()!=1) str<<"/"<<declElWidth();
}
}
@@ -819,7 +939,6 @@ void AstTypeTable::dump(ostream& str) {
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);
}
@@ -839,7 +958,7 @@ void AstVarXRef::dump(ostream& str) {
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
str<<dotted()<<". - ";
if (inlinedDots()!="") str<<" flat.="<<inlinedDots()<<" - ";
if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
if (varScopep()) { varScopep()->dump(str); }
else if (varp()) { varp()->dump(str); }
else { str<<"UNLINKED"; }
+932 -402
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -271,4 +271,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
V3Global::dumpCheckGlobalTree("begin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+44 -9
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -21,6 +21,9 @@
// At each IF/(IF else).
// Count underneath $display/$stop statements.
// If more on if than else, this branch is unlikely, or vice-versa.
// At each FTASKREF,
// Count calls into the function
// Then, if FTASK is called only once, add inline attribute
//
//*************************************************************************
@@ -40,9 +43,18 @@
class BranchVisitor : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
// AstFTask::user1() -> int. Number of references
AstUser1InUse m_inuser1;
// TYPES
typedef vector<AstCFunc*> CFuncVec;
// STATE
int m_likely; // Excuses for branch likely taken
int m_unlikely; // Excuses for branch likely not taken
CFuncVec m_cfuncsp; // List of all tasks
// METHODS
static int debug() {
@@ -55,6 +67,12 @@ private:
m_likely = false;
m_unlikely = false;
}
void checkUnlikely(AstNode* nodep) {
if (nodep->isUnlikely()) {
UINFO(4," UNLIKELY: "<<nodep<<endl);
m_unlikely++;
}
}
// VISITORS
virtual void visit(AstNodeIf* nodep, AstNUser*) {
@@ -83,20 +101,37 @@ private:
m_likely = lastLikely;
m_unlikely = lastUnlikely;
}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
if (nodep->isUnlikely()) {
UINFO(4," UNLIKELY: "<<nodep<<endl);
m_unlikely++;
}
virtual void visit(AstCCall* nodep, AstNUser*) {
checkUnlikely(nodep);
nodep->funcp()->user1Inc();
nodep->iterateChildren(*this);
}
virtual void visit(AstCFunc* nodep, AstNUser*) {
checkUnlikely(nodep);
m_cfuncsp.push_back(nodep);
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep, AstNUser*) {
checkUnlikely(nodep);
nodep->iterateChildren(*this);
}
// METHODS
void calc_tasks() {
for (CFuncVec::iterator it=m_cfuncsp.begin(); it!=m_cfuncsp.end(); ++it) {
AstCFunc* nodep = *it;
if (!nodep->dontInline()) {
nodep->isInline(true);
}
}
}
public:
// CONSTUCTORS
BranchVisitor(AstNetlist* rootp) {
BranchVisitor(AstNetlist* nodep) {
reset();
rootp->iterateChildren(*this);
nodep->iterateChildren(*this);
calc_tasks();
}
virtual ~BranchVisitor() {}
};
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+15 -11
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -37,6 +37,9 @@
#include "V3Broken.h"
#include "V3Ast.h"
// This visitor does not edit nodes, and is called at error-exit, so should use constant iterators
#include "V3AstConstOnly.h"
//######################################################################
class BrokenTable : public AstNVisitor {
@@ -47,11 +50,11 @@ private:
typedef map<const AstNode*,int> NodeMap;
static NodeMap s_nodes; // Set of all nodes that exist
// BITMASK
static const int FLAG_ALLOCATED = 0x01; // new() and not delete()ed
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
static const int FLAG_LEAKED = 0x08; // Known to have been leaked
static const int FLAG_UNDER_NOW = 0x10; // Is in tree as parent of current node
enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed
enum { FLAG_IN_TREE = 0x02 }; // Is in netlist tree
enum { FLAG_LINKABLE = 0x04 }; // Is in netlist tree, can be linked to
enum { FLAG_LEAKED = 0x08 }; // Known to have been leaked
enum { FLAG_UNDER_NOW = 0x10 }; // Is in tree as parent of current node
public:
// METHODS
static void deleted(const AstNode* nodep) {
@@ -71,7 +74,8 @@ public:
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
}
if (iter == s_nodes.end()) {
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2
s_nodes.insert(make_pair(nodep,flags));
}
}
static void setUnder(const AstNode* nodep, bool flag) {
@@ -185,7 +189,7 @@ private:
// VISITORS
virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
nodep->iterateChildren(*this);
nodep->iterateChildrenConst(*this);
}
public:
// CONSTUCTORS
@@ -202,8 +206,8 @@ class BrokenCheckVisitor : public AstNVisitor {
private:
virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::setUnder(nodep,true);
if (nodep->broken()) {
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)");
if (const char* whyp=nodep->broken()) {
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
}
if (nodep->dtypep()) {
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
@@ -228,7 +232,7 @@ private:
nodep->v3fatalSrc("Width != WidthMin");
}
}
nodep->iterateChildren(*this);
nodep->iterateChildrenConst(*this);
BrokenTable::setUnder(nodep,false);
}
public:
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+28 -18
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -97,7 +97,8 @@ private:
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
// Don't sweat it, we already complained about casex in general
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
} else if (m_caseExprp->castCase() && (m_caseExprp->castCase()->casez()
|| m_caseExprp->castCase()->caseInside())) {
if (nodep->num().isUnknown()) {
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
}
@@ -322,36 +323,42 @@ private:
icondNextp = icondp->nextp();
icondp->unlinkFrBack();
AstNode* and1p;
AstNode* and2p;
AstNode* condp = NULL; // Default is to use and1p/and2p
AstConst* iconstp = icondp->castConst();
if (iconstp && neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
// For simplicity, make expression that is not equal, and let later
// optimizations remove it
and1p = new AstConst(itemp->fileline(), AstConst::LogicFalse());
and2p = new AstConst(itemp->fileline(), AstConst::LogicTrue());
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
} else if (AstInsideRange* irangep = icondp->castInsideRange()) {
// Similar logic in V3Width::visit(AstInside)
AstNode* ap = AstGte::newTyped(itemp->fileline(),
cexprp->cloneTree(false),
irangep->lhsp()->unlinkFrBack());
AstNode* bp = AstLte::newTyped(itemp->fileline(),
cexprp->cloneTree(false),
irangep->rhsp()->unlinkFrBack());
condp = new AstAnd(itemp->fileline(), ap, bp);
} else if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez())) {
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
new AstConst(itemp->fileline(), nummask));
and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
new AstConst(itemp->fileline(), nummask));
AstNode* and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else {
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
and1p = cexprp->cloneTree(false);
and2p = icondp;
AstNode* and1p = cexprp->cloneTree(false);
AstNode* and2p = icondp;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
}
AstNodeBiop* condp = (and1p->isDouble()
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
if (!ifexprp) {
ifexprp = condp;
} else {
@@ -404,6 +411,7 @@ private:
AstNode* itemexprp = ifexprp; ifexprp=NULL;
if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
itemexprp->deleteTree(); itemexprp=NULL;
// cppcheck-suppress redundantAssignment
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
}
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
@@ -435,7 +443,7 @@ private:
bool neverItem(AstCase* casep, AstConst* itemp) {
// Xs in case or casez are impossible due to two state simulations
if (casep->casex()) {
} else if (casep->casez()) {
} else if (casep->casez() || casep->caseInside()) {
if (itemp->num().isUnknown()) return true;
} else {
if (itemp->num().isFourState()) return true;
@@ -455,6 +463,7 @@ private:
replaceCaseFast(nodep); nodep=NULL;
} else {
++m_statCaseSlow;
// cppcheck-supporess uselessAssignmentPtrArg
replaceCaseComplicated(nodep); nodep=NULL;
}
}
@@ -482,6 +491,7 @@ public:
void V3Case::caseAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CaseVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("case.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Case::caseLint(AstNodeCase* nodep) {
UINFO(4,__FUNCTION__<<": "<<endl);
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+3 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2004-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -149,6 +149,7 @@ private:
if (!nodep->lvalue()
&& !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath()
&& !nodep->backp()->castArraySel()
&& nodep->backp()->width()
&& castSize(nodep) != castSize(nodep->varp())) {
// Cast vars to IData first, else below has upper bits wrongly set
@@ -187,4 +188,5 @@ public:
void V3Cast::castAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CastVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("cast.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2004-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+3 -2
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -526,7 +526,7 @@ private:
}
}
}
sort(report.begin(), report.end());
stable_sort(report.begin(), report.end());
for (deque<string>::iterator it = report.begin(); it!=report.end(); ++it) {
*ofp << *it;
}
@@ -712,6 +712,7 @@ private:
virtual void visit(AstInitial* nodep, AstNUser*) { }
virtual void visit(AstTraceInc* nodep, AstNUser*) { }
virtual void visit(AstCoverToggle* nodep, AstNUser*) { }
virtual void visit(AstNodeDType* nodep, AstNUser*) { }
//--------------------
// Default
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+143 -78
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -43,6 +43,130 @@
#include "V3Changed.h"
#include "V3EmitCBase.h"
//######################################################################
class ChangedState {
public:
// STATE
AstNodeModule* m_topModp; // Top module
AstScope* m_scopetopp; // Scope under TOPSCOPE
AstCFunc* m_chgFuncp; // Change function we're building
ChangedState() {
m_topModp = NULL;
m_chgFuncp = NULL;
m_scopetopp = NULL;
}
~ChangedState() {}
};
//######################################################################
// Utility visitor to find elements to be compared
class ChangedInsertVisitor : public AstNVisitor {
private:
// STATE
ChangedState* m_statep; // Shared state across visitors
AstVarScope* m_vscp; // Original (non-change) variable we're change-detecting
AstVarScope* m_newvscp; // New (change detect) variable we're change-detecting
AstNode* m_varEqnp; // Original var's equation to get var value
AstNode* m_newLvEqnp; // New var's equation to read value
AstNode* m_newRvEqnp; // New var's equation to set value
uint32_t m_detects; // # detects created
// CONSTANTS
enum MiscConsts {
DETECTARRAY_MAX_INDEXES = 256 // How many indexes before error
// Ok to increase this, but may result in much slower model
};
void newChangeDet() {
if (++m_detects > DETECTARRAY_MAX_INDEXES) {
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than "<<cvtToStr(DETECTARRAY_MAX_INDEXES)
<<" array indexes (probably with UNOPTFLAT warning suppressed): "<<m_vscp->prettyName()<<endl
<<m_vscp->warnMore()
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl);
return;
}
AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(),
m_varEqnp->cloneTree(true),
m_newRvEqnp->cloneTree(true), false);
m_statep->m_chgFuncp->addStmtsp(changep);
AstAssign* initp = new AstAssign (m_vscp->fileline(),
m_newLvEqnp->cloneTree(true),
m_varEqnp->cloneTree(true));
m_statep->m_chgFuncp->addFinalsp(initp);
}
virtual void visit(AstBasicDType* nodep, AstNUser*) {
newChangeDet();
}
virtual void visit(AstPackArrayDType* nodep, AstNUser*) {
newChangeDet();
}
virtual void visit(AstUnpackArrayDType* nodep, AstNUser*) {
for (int index=0; index < nodep->elementsConst(); ++index) {
AstNode* origVEp = m_varEqnp;
AstNode* origNLEp = m_newLvEqnp;
AstNode* origNREp = m_newRvEqnp;
m_varEqnp = new AstArraySel(nodep->fileline(), m_varEqnp->cloneTree(true), index);
m_newLvEqnp = new AstArraySel(nodep->fileline(), m_newLvEqnp->cloneTree(true), index);
m_newRvEqnp = new AstArraySel(nodep->fileline(), m_newRvEqnp->cloneTree(true), index);
nodep->subDTypep()->skipRefp()->accept(*this);
m_varEqnp->deleteTree();
m_newLvEqnp->deleteTree();
m_newRvEqnp->deleteTree();
m_varEqnp = origVEp;
m_newLvEqnp = origNLEp;
m_newRvEqnp = origNREp;
}
}
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
if (nodep->packedUnsup()) {
newChangeDet();
} else {
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-class-");
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-");
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
}
public:
// CONSTUCTORS
ChangedInsertVisitor(AstVarScope* vscp, ChangedState* statep) {
m_statep = statep;
m_vscp = vscp;
m_detects = 0;
{
AstVar* varp = m_vscp->varp();
string newvarname = "__Vchglast__"+m_vscp->scopep()->nameDotless()+"__"+varp->shortName();
// Create: VARREF(_last)
// ASSIGN(VARREF(_last), VARREF(var))
// ...
// CHANGEDET(VARREF(_last), VARREF(var))
AstVar* newvarp = new AstVar (varp->fileline(), AstVarType::MODULETEMP, newvarname, varp);
m_statep->m_topModp->addStmtp(newvarp);
m_newvscp = new AstVarScope(m_vscp->fileline(), m_statep->m_scopetopp, newvarp);
m_statep->m_scopetopp->addVarp(m_newvscp);
m_varEqnp = new AstVarRef(m_vscp->fileline(), m_vscp, false);
m_newLvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, true);
m_newRvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, false);
}
vscp->dtypep()->skipRefp()->accept(*this);
m_varEqnp->deleteTree();
m_newLvEqnp->deleteTree();
m_newRvEqnp->deleteTree();
}
virtual ~ChangedInsertVisitor() {}
};
//######################################################################
// Changed state, as a visitor of each AstNode
@@ -54,15 +178,7 @@ private:
AstUser1InUse m_inuser1;
// STATE
AstNodeModule* m_topModp; // Top module
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
};
ChangedState* m_statep; // Shared state across visitors
// METHODS
static int debug() {
@@ -71,70 +187,16 @@ 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);
AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
AstStructDType *structp = varp->dtypeSkipRefp()->castStructDType();
bool isArray = arrayp;
bool isStruct = structp && structp->packed();
int elements = isArray ? arrayp->elementsConst() : 1;
if (isArray && (elements > 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(elements));
} else if (!isArray && !isStruct
&& !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)
// ASSIGN(VARREF(_last), VARREF(var))
// ...
// CHANGEDET(VARREF(_last), VARREF(var))
AstVar* newvarp = new AstVar (varp->fileline(), AstVarType::MODULETEMP, newvarname, varp);
m_topModp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp);
m_scopetopp->addVarp(newvscp);
for (int index=0; index<elements; ++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);
}
}
ChangedInsertVisitor visitor (vscp, m_statep);
}
// VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) {
UINFO(4," MOD "<<nodep<<endl);
if (nodep->isTop()) {
m_topModp = nodep;
m_statep->m_topModp = nodep;
}
nodep->iterateChildren(*this);
}
@@ -145,15 +207,15 @@ private:
// Create the change detection function
AstScope* scopep = nodep->scopep();
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
m_scopetopp = scopep;
m_statep->m_scopetopp = scopep;
// Create change detection function
m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "IData");
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_chgFuncp->symProlog(true);
m_chgFuncp->declPrivate(true);
m_scopetopp->addActivep(m_chgFuncp);
m_statep->m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
m_statep->m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_statep->m_chgFuncp->symProlog(true);
m_statep->m_chgFuncp->declPrivate(true);
m_statep->m_scopetopp->addActivep(m_statep->m_chgFuncp);
// We need at least one change detect so we know to emit the correct code
m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
//
nodep->iterateChildren(*this);
}
@@ -165,6 +227,9 @@ private:
}
}
}
virtual void visit(AstNodeMath* nodep, AstNUser*) {
// Short-circuit
}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) {
@@ -173,10 +238,8 @@ private:
public:
// CONSTUCTORS
ChangedVisitor(AstNetlist* nodep) {
m_topModp = NULL;
m_chgFuncp = NULL;
m_scopetopp = NULL;
ChangedVisitor(AstNetlist* nodep, ChangedState* statep) {
m_statep = statep;
nodep->accept(*this);
}
virtual ~ChangedVisitor() {}
@@ -187,5 +250,7 @@ public:
void V3Changed::changedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ChangedVisitor visitor (nodep);
ChangedState state;
ChangedVisitor visitor (nodep, &state);
V3Global::dumpCheckGlobalTree("changed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+6 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -238,6 +238,10 @@ private:
nodep->iterateChildren(*this);
insureCleanAndNext (nodep->valuep());
}
virtual void visit(AstTypedef* nodep, AstNUser*) {
// No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this);
}
// Control flow operators
virtual void visit(AstNodeCond* nodep, AstNUser*) {
@@ -288,4 +292,5 @@ public:
void V3Clean::cleanAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CleanVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clean.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+2 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2008-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2008-2015 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.
@@ -914,4 +914,5 @@ void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
// While the gater does well at some modules, it seems to slow down many others
UINFO(5,"ClkGater is disabled due to performance issues\n");
//GaterVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clkgater.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+16 -156
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -99,18 +99,6 @@ private:
UINFO(4,"New Last: "<<newvscp<<endl);
return newvscp;
}
AstVarScope* getCreateLocalVar(FileLine* fl, const string& name, AstVar* examplep, int width) {
AstVar* newvarp;
if (width) {
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, VFlagLogicPacked(), width);
} else {
newvarp = new AstVar (fl, AstVarType::BLOCKTEMP, name, examplep); // No range; 1 bit.
}
m_modp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(fl, m_scopep, newvarp);
m_scopep->addVarp(newvscp);
return newvscp;
}
AstNode* createSenItemEquation(AstSenItem* nodep) {
// We know the var is clean, and one bit, so we use binary ops
// for speed instead of logical ops.
@@ -320,40 +308,14 @@ private:
}
nodep->deleteTree(); nodep = NULL;
}
void moveInitial(AstActive* nodep) {
// Change to CFunc
AstNode* stmtsp = nodep->stmtsp();
if (stmtsp) {
if (!m_scopep) nodep->v3fatalSrc("Initial Active not under scope\n");
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_initial__"+m_scopep->nameDotless(),
m_scopep);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->symProlog(true);
funcp->slow(true);
stmtsp->unlinkFrBackWithNext();
funcp->addStmtsp(stmtsp);
nodep->replaceWith(funcp);
// Add top level call to it
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
callp->argTypes("vlSymsp");
m_initFuncp->addStmtsp(callp);
} else {
nodep->unlinkFrBack();
}
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstCFunc* nodep, AstNUser*) {
nodep->iterateChildren(*this);
// Link to global function
if (nodep->formCallTree()) {
if (nodep->name() == "_final") {
UINFO(4, " formCallTree "<<nodep<<endl);
AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
callp->argTypes("vlSymsp");
m_finalFuncp->addStmtsp(callp);
} else {
nodep->v3fatalSrc("Unknown CFunc name. Make code more generic, with a map of func names");
}
UINFO(4, " formCallTree "<<nodep<<endl);
AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
callp->argTypes("vlSymsp");
m_finalFuncp->addStmtsp(callp);
}
}
virtual void visit(AstSenTree* nodep, AstNUser*) {
@@ -369,13 +331,14 @@ private:
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_settleFuncp->addStmtsp(stmtsp); // else add to top level function
}
void addToInitial(AstNode* stmtsp) {
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
}
virtual void visit(AstActive* nodep, AstNUser*) {
// Careful if adding variables here, ACTIVES can be under other ACTIVES
// Need to save and restore any member state in AstUntilStable block
if (nodep->hasInitial()) {
moveInitial(nodep);
}
else if (!m_topScopep || !nodep->stmtsp()) {
if (!m_topScopep || !nodep->stmtsp()) {
// Not at the top or empty block...
// Only empty blocks should be leftover on the non-top. Killem.
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
@@ -385,6 +348,7 @@ private:
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
if (nodep->hasClocked()) {
// Remember the latest sensitivity so we can compare it next time
if (nodep->hasInitial()) nodep->v3fatalSrc("Initial block should not have clock sensitivity");
if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) {
UINFO(4," sameSenseTree\n");
} else {
@@ -396,6 +360,10 @@ private:
}
// Move statements to if
m_lastIfp->addIfsp(stmtsp);
} else if (nodep->hasInitial()) {
// Don't need to: clearLastSen();, as we're adding it to different cfunc
// Move statements to function
addToInitial(stmtsp);
} else if (nodep->hasSettle()) {
// Don't need to: clearLastSen();, as we're adding it to different cfunc
// Move statements to function
@@ -410,115 +378,6 @@ private:
}
}
#ifdef NEW_ORDERING
virtual void visit(AstUntilStable* nodep, AstNUser*) {
// Process any sub ACTIVE statements first
UINFO(4," UNTILSTABLE "<<nodep<<endl);
{
// Keep vars if in middle of other stable
AstUntilStable* lastUntilp = m_untilp;
AstSenTree* lastSenp = m_lastSenp;
AstIf* lastIfp = m_lastIfp;
m_untilp = nodep;
m_lastSenp = NULL;
m_lastIfp = NULL;
nodep->iterateChildren(*this);
m_untilp = lastUntilp;
m_lastSenp = lastSenp;
m_lastIfp = lastIfp;
}
// Set "unstable" to 100. (non-stabilization count)
// int __VclockLoop = 0
// IData __Vchange = 1
// while (__Vchange) {
// Save old values of each until stable variable
// Evaluate the body
// __Vchange = {change_detect} contribution
// if (++__VclockLoop > 100) converge_error
if (debug()>4) nodep->dumpTree(cout, " UntilSt-old: ");
FileLine* fl = nodep->fileline();
if (nodep->bodysp()) fl = nodep->bodysp()->fileline(); // Point to applicable code...
m_stableNum++;
AstNode* origBodysp = nodep->bodysp(); if (origBodysp) origBodysp->unlinkFrBackWithNext();
AstVarScope* changeVarp = getCreateLocalVar(fl, "__Vchange"+cvtToStr(m_stableNum), NULL, 32);
AstVarScope* countVarp = getCreateLocalVar(fl, "__VloopCount"+cvtToStr(m_stableNum), NULL, 32);
AstWhile* untilp = new AstWhile(fl, new AstVarRef(fl, changeVarp, false), NULL);
AstNode* preUntilp = new AstComment(fl, "Change loop "+cvtToStr(m_stableNum));
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, changeVarp, true),
new AstConst(fl, 1)));
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
new AstConst(fl, 0)));
// Add stable variables & preinits
AstNode* setChglastp = NULL;
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
AstVarScope* cmpvscp = getCreateLocalVar(varrefp->varp()->fileline(),
"__Vchglast"+cvtToStr(m_stableNum)+"__"+varrefp->name(),
varrefp->varp(), 0);
varrefp->varScopep()->user2p(cmpvscp);
setChglastp = setChglastp->addNext(
new AstAssign(fl, new AstVarRef(fl, cmpvscp, true),
new AstVarRef(fl, varrefp->varScopep(), false)));
}
if (!setChglastp) nodep->v3fatalSrc("UntilStable without any variables");
untilp->addBodysp(setChglastp);
untilp->addBodysp(new AstComment(fl, "Change Loop body begin"));
if (origBodysp) untilp->addBodysp(origBodysp);
untilp->addBodysp(new AstComment(fl, "Change Loop body end"));
// Add stable checks
// The order of the variables doesn't matter, but it's more expensive to test
// wide variables, and more so 64 bit wide ones. Someday it might be faster to
// set the changed variable in a "distributed" fashion over the code, IE,
// logic... logic.... a=....; Changed |= (a ^ old_a); more logic... Changed |=...
// But then, one hopes users don't have much unoptimized logic
AstNode* changeExprp = NULL;
int doublecount = 0;
for (int wide=0; wide<3; wide++) { // Adding backwards; wide, quad, then normal
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
if (wide== ( varrefp->isQuad()?0:(varrefp->isWide() ? 1:2))) {
AstVarScope* cmpvscp = (AstVarScope*)(varrefp->varScopep()->user2p());
if (!cmpvscp) varrefp->v3fatalSrc("should have created above");
AstChangeXor* changep
= new AstChangeXor (fl,
new AstVarRef(fl, varrefp->varScopep(), false),
new AstVarRef(fl, cmpvscp, false));
if (!changeExprp) changeExprp = changep;
else if (doublecount++ > DOUBLE_OR_RATE) {
doublecount = 0;
changeExprp = new AstLogOr (fl, changep, changeExprp);
} else {
changeExprp = new AstOr (fl, changep, changeExprp);
}
}
}
}
if (!changeExprp) nodep->v3fatalSrc("UntilStable without any variables");
changeExprp = new AstAssign(fl, new AstVarRef(fl, changeVarp, true),
changeExprp);
untilp->addBodysp(changeExprp);
//
// Final body
AstNode* ifstmtp = new AstAssign(fl, new AstVarRef(fl, countVarp, true),
new AstAdd(fl, new AstConst(fl, 1),
new AstVarRef(fl, countVarp, false)));
ifstmtp->addNext(new AstIf(fl,
new AstLt (fl, new AstConst(fl, 100),
new AstVarRef(fl, countVarp, false)),
(new AstDisplay (fl, AstDisplayType::DT_DISPLAY,
"%%Error: Verilated model didn't converge", NULL, NULL))
->addNext(new AstStop (fl)),
NULL));
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
new AstVarRef(fl, changeVarp, false)),
ifstmtp, NULL));
//
// Replace it
preUntilp->addNext(untilp);
if (debug()>4) preUntilp->dumpTreeAndNext(cout, " UntilSt-new: ");
nodep->replaceWith(preUntilp); nodep->deleteTree(); nodep=NULL;
}
#endif
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) {
@@ -548,4 +407,5 @@ public:
void V3Clock::clockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ClockVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+2 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -474,4 +474,5 @@ public:
void V3Combine::combineAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CombineVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("combine.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2010-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+2 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2010-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2015 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.
@@ -24,6 +24,7 @@
#include "verilatedos.h"
#include <string>
#include "V3Error.h"
#include "V3FileLine.h"
//######################################################################
+333 -47
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -106,7 +106,8 @@ private:
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
AstNodeModule* m_modp; // Current module
AstArraySel* m_selp; // Current select
AstNode* m_scopep; // Current scope
AstAttrOf* m_attrp; // Current attribute
@@ -172,6 +173,16 @@ private:
if (rnodep->width() != bnodep->width()) return false;
return rnodep->lhsp()->castConst();
}
static bool operandSubAdd(AstNode* nodep) {
// SUB( ADD(CONSTx,y), CONSTz) -> ADD(SUB(CONSTx,CONSTz), y)
AstNodeBiop* np = nodep->castNodeBiop();
AstNodeBiop* lp = np->lhsp()->castNodeBiop();
return (lp
&& lp->lhsp()->castConst()
&& np->rhsp()->castConst()
&& lp->width()==np->width());
}
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)
@@ -233,16 +244,19 @@ private:
}
bool operandHugeShiftL(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst()
&& !nodep->rhsp()->castConst()->num().isFourState()
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width())
&& isTPure(nodep->lhsp()));
}
bool operandHugeShiftR(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst()
&& !nodep->rhsp()->castConst()->num().isFourState()
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width())
&& isTPure(nodep->lhsp()));
}
bool operandIsTwo(AstNode* nodep) {
return (nodep->castConst()
&& !nodep->castConst()->num().isFourState()
&& nodep->width() <= VL_QUADSIZE
&& nodep->castConst()->toUQuad()==2);
}
@@ -270,6 +284,8 @@ private:
// We can only get rid of a<<b>>c or a<<b<<c, with constant b & c
// because bits may be masked in that process, or (b+c) may exceed the word width.
if (!(nodep->rhsp()->castConst() && lhsp->rhsp()->castConst())) return false;
if (nodep->rhsp()->castConst()->num().isFourState()
|| lhsp->rhsp()->castConst()->num().isFourState()) return false;
if (nodep->width()!=lhsp->width()) return false;
if (nodep->width()!=lhsp->lhsp()->width()) return false;
return true;
@@ -327,27 +343,27 @@ private:
}
bool operandBiExtendConst(AstNodeBiop* nodep) {
// Loop unrolling likes standalone compares
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
// Loop unrolling favors standalone compares
// EQ(const{width32}, EXTEND(xx{width3})) -> EQ(const{3}, xx{3})
// Beware that the constant must have zero bits (+ 1 if signed) or compare
// would be incorrect
AstExtend* extendp = nodep->lhsp()->castExtend();
AstExtend* extendp = nodep->rhsp()->castExtend();
if (!extendp) return false;
AstNode* smallerp = extendp->lhsp();
int subsize = smallerp->width();
AstConst* constp = nodep->rhsp()->castConst();
AstConst* constp = nodep->lhsp()->castConst();
if (!constp) return false;
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
//
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
smallerp->unlinkFrBack();
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
nodep->lhsp(smallerp);
nodep->rhsp(smallerp);
constp->unlinkFrBack();
V3Number num (constp->fileline(), subsize);
num.opAssign(constp->num());
nodep->rhsp(new AstConst(constp->fileline(), num));
nodep->lhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); constp=NULL;
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
return true;
@@ -412,12 +428,12 @@ private:
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic
if (node1p->castConst() && node2p->castConst()) {
return node1p->sameTree(node2p);
return node1p->sameGateTree(node2p);
}
else if (node1p->castVarRef() && node2p->castVarRef()) {
// Avoid comparing widthMin's, which results in lost optimization attempts
// If cleanup sameTree to be smarter, this can be restored.
//return node1p->sameTree(node2p);
// If cleanup sameGateTree to be smarter, this can be restored.
//return node1p->sameGateTree(node2p);
return node1p->same(node2p);
} else {
return false;
@@ -433,7 +449,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->sameTree(elsevarp)) return false;
if (!ifvarp->sameGateTree(elsevarp)) return false;
return true;
}
bool operandIfIf(AstNodeIf* nodep) {
@@ -444,6 +460,89 @@ private:
if (afterComment(lowerIfp->elsesp())) return false;
return true;
}
bool ifConcatMergeableBiop(AstNode* nodep) {
return (nodep->castAnd()
|| nodep->castOr()
|| nodep->castXor()
|| nodep->castXnor());
}
bool ifAdjacentSel(AstSel* lhsp, AstSel* rhsp) {
if (!v3Global.opt.oAssemble()) return false; // opt disabled
if (!lhsp || !rhsp) return false;
AstNode* lfromp = lhsp->fromp();
AstNode* rfromp = rhsp->fromp();
if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
AstConst* lstart = lhsp->lsbp()->castConst();
AstConst* rstart = rhsp->lsbp()->castConst();
AstConst* lwidth = lhsp->widthp()->castConst();
AstConst* rwidth = rhsp->widthp()->castConst();
if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated
int rend = (rstart->toSInt() + rwidth->toSInt());
if (rend == lstart->toSInt()) return true;
return false;
}
bool ifMergeAdjacent(AstNode* lhsp, AstNode* rhsp) {
// called by concatmergeable to determine if {lhsp, rhsp} make sense
if (!v3Global.opt.oAssemble()) return false; // opt disabled
// two same varref
if (operandsSame(lhsp, rhsp)) return true;
AstSel* lselp = lhsp->castSel();
AstSel* rselp = rhsp->castSel();
// a[i:0] a
if (lselp && !rselp && rhsp->sameGateTree(lselp->fromp()))
rselp = new AstSel(rhsp->fileline(), rhsp->cloneTree(false), 0, rhsp->width());
// a[i:j] {a[j-1:k], b}
if (lselp && !rselp && rhsp->castConcat())
return ifMergeAdjacent(lhsp, rhsp->castConcat()->lhsp());
// a a[msb:j]
if (rselp && !lselp && lhsp->sameGateTree(rselp->fromp()))
lselp = new AstSel(lhsp->fileline(), lhsp->cloneTree(false), 0, lhsp->width());
// {b, a[j:k]} a[k-1:i]
if (rselp && !lselp && lhsp->castConcat())
return ifMergeAdjacent(lhsp->castConcat()->rhsp(), rhsp);
if (!lselp || !rselp) return false;
// a[a:b] a[b-1:c] are adjacent
AstNode* lfromp = lselp->fromp();
AstNode* rfromp = rselp->fromp();
if (!lfromp || !rfromp || !lfromp->sameGateTree(rfromp)) return false;
AstConst* lstart = lselp->lsbp()->castConst();
AstConst* rstart = rselp->lsbp()->castConst();
AstConst* lwidth = lselp->widthp()->castConst();
AstConst* rwidth = rselp->widthp()->castConst();
if (!lstart || !rstart || !lwidth || !rwidth) return false; // too complicated
int rend = (rstart->toSInt() + rwidth->toSInt());
// a[i:j] a[j-1:k]
if (rend == lstart->toSInt()) return true;
// a[i:0] a[msb:j]
if (rend == rfromp->width() && lstart->toSInt() == 0) return true;
return false;
}
bool concatMergeable(AstNode* lhsp, AstNode* rhsp) {
// determine if {a OP b, c OP d} => {a, c} OP {b, d} is advantagous
if (!v3Global.opt.oAssemble()) return false; // opt disabled
if (lhsp->type() != rhsp->type()) return false;
if (!ifConcatMergeableBiop(lhsp)) return false;
AstNodeBiop* lp = lhsp->castNodeBiop();
AstNodeBiop* rp = rhsp->castNodeBiop();
if (!lp || !rp) return false;
// {a[]&b[], a[]&b[]}
bool lad = ifMergeAdjacent(lp->lhsp(), rp->lhsp());
bool rad = ifMergeAdjacent(lp->rhsp(), rp->rhsp());
if (lad && rad) return true;
// {a[] & b[]&c[], a[] & b[]&c[]}
else if (lad && concatMergeable(lp->rhsp(), rp->rhsp())) return true;
// {a[]&b[] & c[], a[]&b[] & c[]}
else if (rad && concatMergeable(lp->lhsp(), rp->lhsp())) return true;
else {
// {(a[]&b[])&(c[]&d[]), (a[]&b[])&(c[]&d[])}
if (concatMergeable(lp->lhsp(), rp->lhsp())
&& concatMergeable(lp->rhsp(), rp->rhsp()))
return true;
}
return false;
}
//----------------------------------------
// Constant Replacement functions.
@@ -525,7 +624,7 @@ private:
void replaceConstString (AstNode* oldp, const string& num) {
// Replace oldp node with a constant set to specified value
UASSERT (oldp, "Null old\n");
AstNode* newp = new AstConstString(oldp->fileline(), num);
AstNode* newp = new AstConst(oldp->fileline(), AstConst::String(), num);
if (debug()>5) oldp->dumpTree(cout," const_old: ");
if (debug()>5) newp->dumpTree(cout," _new: ");
oldp->replaceWith(newp);
@@ -538,6 +637,8 @@ private:
void replaceWChild(AstNode* nodep, AstNode* childp) {
// NODE(..., CHILD(...)) -> CHILD(...)
childp->unlinkFrBackWithNext();
// If replacing a SEL for example, the data type comes from the parent (is less wide).
// This may adversly affect the operation of the node being replaced.
childp->dtypeFrom(nodep);
nodep->replaceWith(childp);
nodep->deleteTree(); nodep=NULL;
@@ -660,6 +761,45 @@ private:
rrp->deleteTree();
//nodep->dumpTree(cout, " repShiftSame_new: ");
}
void replaceConcatSel(AstConcat* nodep) {
// {a[1], a[0]} -> a[1:0]
AstSel* lselp = nodep->lhsp()->unlinkFrBack()->castSel();
AstSel* rselp = nodep->rhsp()->unlinkFrBack()->castSel();
int lstart = lselp->lsbConst();
int lwidth = lselp->widthConst();
int rstart = rselp->lsbConst();
int rwidth = rselp->widthConst();
if ((rstart + rwidth) != lstart) nodep->v3fatalSrc("tried to merge two selects which are not adjacent");
AstSel* newselp = new AstSel(lselp->fromp()->fileline(), rselp->fromp()->cloneTree(false), rstart, lwidth+rwidth);
UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
nodep->replaceWith(newselp);
lselp->deleteTree(); lselp = NULL;
rselp->deleteTree(); rselp = NULL;
nodep->deleteTree(); nodep = NULL;
}
void replaceConcatMerge(AstConcat* nodep) {
AstNodeBiop* lp = nodep->lhsp()->castNodeBiop();
AstNodeBiop* rp = nodep->rhsp()->castNodeBiop();
AstNode* llp = lp->lhsp()->cloneTree(false);
AstNode* lrp = lp->rhsp()->cloneTree(false);
AstNode* rlp = rp->lhsp()->cloneTree(false);
AstNode* rrp = rp->rhsp()->cloneTree(false);
if (concatMergeable(lp, rp)) {
AstConcat* newlp = new AstConcat(rlp->fileline(), llp, rlp);
AstConcat* newrp = new AstConcat(rrp->fileline(), lrp, rrp);
// use the lhs to replace the parent concat
lp->lhsp()->replaceWith(newlp);
lp->rhsp()->replaceWith(newrp);
lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::fromBool(true));
UINFO(5, "merged "<< nodep <<endl);
rp->unlinkFrBack()->deleteTree(); rp = NULL;
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); nodep = NULL;
lp->lhsp()->accept(*this);
lp->rhsp()->accept(*this);
} else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
}
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
// -> EXTEND(nodep)
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
@@ -722,9 +862,15 @@ private:
AstNode* ap = lhsp->lhsp()->unlinkFrBack();
AstNode* shift1p = lhsp->rhsp()->unlinkFrBack();
AstNode* shift2p = nodep->rhsp()->unlinkFrBack();
// Shift1p and shift2p may have different sizes, both are self-determined so sum with infinite width
if (nodep->type()==lhsp->type()) {
int shift1 = shift1p->castConst()->toUInt();
int shift2 = shift2p->castConst()->toUInt();
int newshift = shift1+shift2;
shift1p->deleteTree(); shift1p=NULL;
shift2p->deleteTree(); shift2p=NULL;
nodep->lhsp(ap);
nodep->rhsp(new AstAdd(nodep->fileline(), shift1p, shift2p));
nodep->rhsp(new AstConst(nodep->fileline(), newshift));
nodep->accept(*this); // Further reduce, either node may have more reductions.
} else {
// We know shift amounts are constant, but might be a mixed left/right shift
@@ -732,7 +878,7 @@ private:
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
int newshift = shift1+shift2;
shift1p->deleteTree(); shift1p=NULL;
shift2p->deleteTree(); shift1p=NULL;
shift2p->deleteTree(); shift2p=NULL;
AstNode* newp;
V3Number mask1 (nodep->fileline(), nodep->width());
V3Number ones (nodep->fileline(), nodep->width());
@@ -778,7 +924,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->sameTree(varref2p)) return false;
if (!varref1p->sameGateTree(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
@@ -815,9 +961,10 @@ private:
bool varNotReferenced(AstNode* nodep, AstVar* varp, int level=0) {
// Return true if varp never referenced under node.
// Return false if referenced, or tree too deep to be worth it
// Return false if referenced, or tree too deep to be worth it, or side effects
if (!nodep) return true;
if (level>2) return false;
if (nodep->isPure()) return false; // For example a $fgetc can't be reordered
if (nodep->castNodeVarRef() && nodep->castNodeVarRef()->varp()==varp) return false;
return (varNotReferenced (nodep->nextp(),varp,level+1)
&& varNotReferenced(nodep->op1p(),varp,level+1)
@@ -865,10 +1012,10 @@ private:
}
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
// Unlink the stuff
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
AstNode* conp = nodep->lhsp()->castConcat()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
AstNode* conp = nodep->lhsp()->castConcat()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* rhs2p = rhsp->cloneTree(false);
// Calc widths
int lsb2 = 0;
@@ -937,6 +1084,64 @@ private:
// Further reduce, either node may have more reductions.
return true;
}
else if (m_doV && nodep->rhsp()->castStreamR()) {
// The right-streaming operator on rhs of assignment does not
// change the order of bits. Eliminate stream but keep its lhsp
// Unlink the stuff
AstNode* srcp = nodep->rhsp()->castStreamR()->lhsp()->unlinkFrBack();
AstNode* sizep = nodep->rhsp()->castStreamR()->rhsp()->unlinkFrBack();
AstNode* streamp = nodep->rhsp()->castStreamR()->unlinkFrBack();
nodep->rhsp(srcp);
// Cleanup
sizep->deleteTree(); sizep=NULL;
streamp->deleteTree(); streamp=NULL;
// Further reduce, any of the nodes may have more reductions.
return true;
}
else if (m_doV && nodep->lhsp()->castStreamL()) {
// Push the stream operator to the rhs of the assignment statement
int dWidth = nodep->lhsp()->castStreamL()->lhsp()->width();
int sWidth = nodep->rhsp()->width();
// Unlink the stuff
AstNode* dstp = nodep->lhsp()->castStreamL()->lhsp()->unlinkFrBack();
AstNode* streamp = nodep->lhsp()->castStreamL()->unlinkFrBack();
AstNode* srcp = nodep->rhsp()->unlinkFrBack();
// Connect the rhs to the stream operator and update its width
streamp->castStreamL()->lhsp(srcp);
streamp->dtypeSetLogicSized((srcp->width()),
(srcp->widthMin()),
AstNumeric::UNSIGNED);
// Shrink the RHS if necessary
if (sWidth > dWidth) {
streamp = new AstSel(streamp->fileline(), streamp, sWidth-dWidth, dWidth);
}
// Link the nodes back in
nodep->lhsp(dstp);
nodep->rhsp(streamp);
return true;
}
else if (m_doV && nodep->lhsp()->castStreamR()) {
// The right stream operator on lhs of assignment statement does
// not reorder bits. However, if the rhs is wider than the lhs,
// then we select bits from the left-most, not the right-most.
int dWidth = nodep->lhsp()->castStreamR()->lhsp()->width();
int sWidth = nodep->rhsp()->width();
// Unlink the stuff
AstNode* dstp = nodep->lhsp()->castStreamR()->lhsp()->unlinkFrBack();
AstNode* sizep = nodep->lhsp()->castStreamR()->rhsp()->unlinkFrBack();
AstNode* streamp = nodep->lhsp()->castStreamR()->unlinkFrBack();
AstNode* srcp = nodep->rhsp()->unlinkFrBack();
if (sWidth > dWidth) {
srcp = new AstSel(streamp->fileline(), srcp, sWidth-dWidth, dWidth);
}
nodep->lhsp(dstp);
nodep->rhsp(srcp);
// Cleanup
sizep->deleteTree(); sizep=NULL;
streamp->deleteTree(); streamp=NULL;
// Further reduce, any of the nodes may have more reductions.
return true;
}
else if (replaceAssignMultiSel(nodep)) {
return true;
}
@@ -1218,25 +1423,60 @@ private:
nodep->iterateChildren(*this);
m_attrp = oldAttr;
}
virtual void visit(AstArraySel* nodep, AstNUser*) {
nodep->bitp()->iterateAndNext(*this);
if (nodep->bitp()->castConst()
&& nodep->fromp()->castVarRef()
// Need to make sure it's an array object so don't mis-allow a constant (bug509.)
&& nodep->fromp()->castVarRef()->varp()
&& nodep->fromp()->castVarRef()->varp()->valuep()->castInitArray()) {
m_selp = nodep; // Ask visit(AstVarRef) to replace varref with const
}
nodep->fromp()->iterateAndNext(*this);
if (nodep->fromp()->castConst()) { // It did.
if (!m_selp) {
nodep->v3error("Illegal assignment of constant to unpacked array");
} else {
nodep->replaceWith(nodep->fromp()->unlinkFrBack());
}
}
m_selp = NULL;
}
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() && !m_attrp) {
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
nodep->varp()->valuep()->iterateAndNext(*this);
if (operandConst(nodep->varp()->valuep())
&& !nodep->lvalue()
if (m_doV && nodep->varp()->valuep() && !m_attrp) {
//if (debug()) valuep->dumpTree(cout," visitvaref: ");
nodep->varp()->valuep()->iterateAndNext(*this); // May change nodep->varp()->valuep()
AstNode* valuep = nodep->varp()->valuep();
if (!nodep->lvalue()
&& ((!m_params // Can reduce constant wires into equations
&& m_doNConst
&& v3Global.opt.oConst()
&& !(nodep->varp()->isFuncLocal() // Default value, not a "known" constant for this usage
&& nodep->varp()->isInput())
&& !nodep->varp()->noSubst()
&& !nodep->varp()->isSigPublic())
|| nodep->varp()->isParam())) {
AstConst* constp = nodep->varp()->valuep()->castConst();
const V3Number& num = constp->num();
//UINFO(2,"constVisit "<<(void*)constp<<" "<<num<<endl);
replaceNum(nodep, num); nodep=NULL;
did=true;
if (operandConst(valuep)) {
const V3Number& num = valuep->castConst()->num();
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
replaceNum(nodep, num); nodep=NULL;
did=true;
}
else if (m_selp && valuep->castInitArray()) {
int bit = m_selp->bitConst();
AstNode* itemp = valuep->castInitArray()->initsp();
for (int n=0; n<bit && itemp; ++n, itemp=itemp->nextp()) {}
if (itemp->castConst()) {
const V3Number& num = itemp->castConst()->num();
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
replaceNum(nodep, num); nodep=NULL;
did=true;
}
}
}
}
if (!did && m_required) {
@@ -1413,7 +1653,7 @@ private:
for (AstNodeSenItem* senp = nodep->sensesp()->castNodeSenItem(); senp; senp=senp->nextp()->castNodeSenItem()) {
vec.push_back(senp);
}
sort(vec.begin(), vec.end(), SenItemCmp());
stable_sort(vec.begin(), vec.end(), SenItemCmp());
for (vector<AstNodeSenItem*>::iterator it=vec.begin(); it!=vec.end(); ++it) {
(*it)->unlinkFrBack();
}
@@ -1432,7 +1672,7 @@ private:
AstSenItem* litemp = senp->castSenItem();
AstSenItem* ritemp = cmpp->castSenItem();
if (litemp && ritemp) {
if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameTree(ritemp->varrefp()))
if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameGateTree(ritemp->varrefp()))
|| (!litemp->varrefp() && !ritemp->varrefp())) {
// We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders
if (( litemp->edgeType()==AstEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY
@@ -1466,6 +1706,9 @@ private:
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
// Don't perform any optimizations, keep the alias around
}
virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
// Don't perform any optimizations, the node won't be linked yet
}
virtual void visit(AstAssignW* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_doNConst && replaceNodeAssign(nodep)) return;
@@ -1586,8 +1829,9 @@ private:
string fmt = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
string text = nodep->text();
for (string::const_iterator it = text.begin(); it!=text.end(); ++it) {
char ch = *it;
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
@@ -1640,7 +1884,10 @@ private:
replaceWithSimulation(nodep);
}
}
virtual void visit(AstArg* nodep, AstNUser*) {
// replaceWithSimulation on the Arg's parent FuncRef replaces these
nodep->iterateChildren(*this);
}
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_doNConst) {
@@ -1655,6 +1902,10 @@ private:
}
}
}
virtual void visit(AstInitArray* nodep, AstNUser*) {
// Constant if all children are constant
nodep->iterateChildren(*this);
}
// These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
@@ -1700,6 +1951,12 @@ private:
//-----
// Below lines are magic expressions processed by astgen
// TREE_SKIP_VISIT("AstNODETYPE") # Rename normal visit to visitGen and don't iterate
//-----
TREE_SKIP_VISIT("ArraySel");
//-----
// "AstNODETYPE { # bracket not paren
// $accessor_name, ...
// # ,, gets replaced with a , rather than &&
@@ -1740,8 +1997,14 @@ private:
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPow {$rhsp.isZero}", "replaceNum(nodep, 1)"); // Overrides lhs zero rule
TREEOP ("AstPowSS {$rhsp.isZero}", "replaceNum(nodep, 1)"); // Overrides lhs zero rule
TREEOP ("AstPowSU {$rhsp.isZero}", "replaceNum(nodep, 1)"); // Overrides lhs zero rule
TREEOP ("AstPowUS {$rhsp.isZero}", "replaceNum(nodep, 1)"); // Overrides lhs zero rule
TREEOP ("AstPow {$lhsp.isZero, !$rhsp.isZero}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPowSU {$lhsp.isZero, !$rhsp.isZero}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPowUS {$lhsp.isZero, !$rhsp.isZero}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPowSU {$lhsp.isZero, !$rhsp.isZero}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
@@ -1780,7 +2043,7 @@ private:
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP ("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP ("AstSub {$lhsp.castAdd, operandSubAdd(nodep)}", "AstAdd{AstSub{$lhsp->castAdd()->lhsp(),$rhsp}, $lhsp->castAdd()->rhsp()}"); // ((a+x)-y) -> (a+(x-y))
// Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
@@ -1803,6 +2066,14 @@ private:
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
TREEOP ("AstLt {!$lhsp.castConst,$rhsp.castConst}", "AstGt {$rhsp,$lhsp}");
TREEOP ("AstLtS {!$lhsp.castConst,$rhsp.castConst}", "AstGtS {$rhsp,$lhsp}");
TREEOP ("AstLte {!$lhsp.castConst,$rhsp.castConst}", "AstGte {$rhsp,$lhsp}");
TREEOP ("AstLteS {!$lhsp.castConst,$rhsp.castConst}", "AstGteS{$rhsp,$lhsp}");
TREEOP ("AstGt {!$lhsp.castConst,$rhsp.castConst}", "AstLt {$rhsp,$lhsp}");
TREEOP ("AstGtS {!$lhsp.castConst,$rhsp.castConst}", "AstLtS {$rhsp,$lhsp}");
TREEOP ("AstGte {!$lhsp.castConst,$rhsp.castConst}", "AstLte {$rhsp,$lhsp}");
TREEOP ("AstGteS {!$lhsp.castConst,$rhsp.castConst}", "AstLteS{$rhsp,$lhsp}");
// v--- *1* as These ops are always first, as we warn before replacing
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
@@ -1814,7 +2085,7 @@ private:
TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)");
// Two level bubble pushing
TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==$lhsp->castNot()->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x
TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x
TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->op1p())"); // LOGNOT(LOGNOT(x))->x
TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
@@ -1852,12 +2123,12 @@ private:
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
// Compress out EXTENDs to appease loop unroller
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstEq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstNeq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
// Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon
@@ -1871,22 +2142,28 @@ private:
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqN {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtN {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteN {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtN {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteN {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqN {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
@@ -1927,6 +2204,9 @@ private:
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
// CONCAT(a[1],a[0]) -> a[1:0]
TREEOPV("AstConcat{$lhsp->castSel(), $rhsp->castSel(), ifAdjacentSel($lhsp->castSel(),,$rhsp->castSel())}", "replaceConcatSel(nodep)");
TREEOPV("AstConcat{ifConcatMergeableBiop($lhsp), concatMergeable($lhsp,,$rhsp)}", "replaceConcatMerge(nodep)");
// Common two-level operations that can be simplified
TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
@@ -1934,11 +2214,12 @@ private:
TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
TREEOP ("AstXnor{operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
// "AstXnor{operandShiftSame(nodep)}", // Cannot ShiftSame as the shifted-in zeros might create a one
// Note can't simplify a extend{extends}, extends{extend}, as the sign bits end up in the wrong places
TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, nodep->lhsp()->castExtend()->lhsp())");
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())");
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
TREEOPV("AstReplicateN{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
// Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy.
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
@@ -2019,6 +2300,7 @@ public:
m_warn = false;
m_wremove = true; // Overridden in visitors
m_modp = NULL;
m_selp = NULL;
m_scopep = NULL;
m_attrp = NULL;
//
@@ -2101,12 +2383,14 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const_cpp.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
AstNode* V3Const::constifyEdit(AstNode* nodep) {
@@ -2122,6 +2406,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Const::constifyAll(AstNetlist* nodep) {
@@ -2129,6 +2414,7 @@ void V3Const::constifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+72 -14
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -60,10 +60,16 @@ private:
}
};
// NODE STATE
// Entire netlist:
// AstIf::user1() -> bool. True indicates ifelse processed
AstUser1InUse m_inuser1;
// STATE
bool m_checkBlock; // Should this block get covered?
AstNodeModule* m_modp; // Current module to add statement to
bool m_checkBlock; // Should this block get covered?
AstNodeModule* m_modp; // Current module to add statement to
bool m_inToggleOff; // In function/task etc
bool m_inModOff; // In module with no coverage
FileMap m_fileps; // Column counts for each fileline
string m_beginHier; // AstBegin hier name for user coverage points
@@ -124,9 +130,11 @@ private:
// VISITORS - BOTH
virtual void visit(AstNodeModule* nodep, AstNUser*) {
m_modp = nodep;
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
m_fileps.clear();
nodep->iterateChildren(*this);
m_modp = NULL;
m_inModOff = true;
}
// VISITORS - TOGGLE COVERAGE
@@ -140,7 +148,7 @@ private:
}
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_modp && !m_inToggleOff
if (m_modp && !m_inModOff && !m_inToggleOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
const char* disablep = varIgnoreToggle(nodep);
if (disablep) {
@@ -210,7 +218,7 @@ private:
}
}
else if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb()+1; ++index_docs) {
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
int index_code = index_docs - adtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code),
@@ -221,6 +229,50 @@ private:
newent.cleanup();
}
}
else if (AstPackArrayDType* adtypep = dtypep->castPackArrayDType()) {
for (int index_docs=adtypep->lsb(); index_docs<=adtypep->msb(); ++index_docs) {
AstNodeDType* subtypep = adtypep->subDTypep()->skipRefp();
int index_code = index_docs - adtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code*subtypep->width(), subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code*subtypep->width(), subtypep->width()));
toggleVarRecurse(adtypep->subDTypep()->skipRefp(), depth+1,
newent,
varp, chgVarp);
newent.cleanup();
}
}
else if (AstStructDType* adtypep = dtypep->castStructDType()) {
// For now it's packed, so similar to array
for (AstMemberDType* itemp = adtypep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
int index_code = itemp->lsb();
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
new AstSel(varp->fileline(), above.m_varRefp->cloneTree(true),
index_code, subtypep->width()),
new AstSel(varp->fileline(), above.m_chgRefp->cloneTree(true),
index_code, subtypep->width()));
toggleVarRecurse(subtypep, depth+1,
newent,
varp, chgVarp);
newent.cleanup();
}
}
else if (AstUnionDType* adtypep = dtypep->castUnionDType()) {
// Arbitrarially handle only the first member of the union
if (AstMemberDType* itemp = adtypep->membersp()) {
AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
ToggleEnt newent (above.m_comment+string(".")+itemp->name(),
above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true));
toggleVarRecurse(subtypep, depth+1,
newent,
varp, chgVarp);
newent.cleanup();
}
}
else {
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "<<dtypep->prettyTypeName());
}
@@ -230,12 +282,18 @@ private:
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
UINFO(4," IF: "<<nodep<<endl);
if (m_checkBlock) {
// An else-if. When we iterate the if, use "elsif" marking
bool elsif = (nodep->elsesp()->castIf()
&& !nodep->elsesp()->castIf()->nextp());
if (elsif) nodep->elsesp()->castIf()->user1(true);
//
nodep->ifsp()->iterateAndNext(*this);
if (m_checkBlock
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
if (!nodep->backp()->castIf()
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
UINFO(4," COVER: "<<nodep<<endl);
UINFO(4," COVER: "<<nodep<<endl);
if (nodep->user1()) {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif"));
} else {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if"));
}
}
@@ -243,12 +301,10 @@ private:
if (nodep->elsesp()) {
m_checkBlock = true;
nodep->elsesp()->iterateAndNext(*this);
if (m_checkBlock
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
if (nodep->elsesp()->castIf()) {
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "elsif"));
} else {
if (!elsif) { // elsif done inside if()
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "else"));
}
}
@@ -258,7 +314,7 @@ private:
}
virtual void visit(AstCaseItem* nodep, AstNUser*) {
UINFO(4," CASEI: "<<nodep<<endl);
if (m_checkBlock
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
nodep->bodysp()->iterateAndNext(*this);
if (m_checkBlock) { // if the case body didn't disable it
@@ -327,6 +383,7 @@ public:
m_checkBlock = true;
m_beginHier = "";
m_inToggleOff = false;
m_inModOff = true;
rootp->iterateChildren(*this);
}
virtual ~CoverageVisitor() {}
@@ -338,4 +395,5 @@ public:
void V3Coverage::coverage(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
CoverageVisitor visitor (rootp);
V3Global::dumpCheckGlobalTree("coverage.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+2 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
@@ -135,4 +135,5 @@ public:
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
CoverageJoinVisitor visitor (rootp);
V3Global::dumpCheckGlobalTree("coveragejoin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+26 -3
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -81,6 +81,7 @@ private:
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE
AstNodeModule* m_modp; // Current module
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
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
@@ -103,13 +104,21 @@ private:
}
void checkDType(AstNodeDType* nodep) {
if (!nodep->generic() // Don't remove generic types
&& m_elimDTypes) { // dtypes stick around until post-widthing
&& m_elimDTypes // dtypes stick around until post-widthing
&& !nodep->castMemberDType() // Keep member names iff upper type exists
) {
m_varEtcsp.push_back(nodep);
}
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
}
// VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) {
m_modp = nodep;
nodep->iterateChildren(*this);
checkAll(nodep);
m_modp = NULL;
}
virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
@@ -156,6 +165,13 @@ private:
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstTypedef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
// Don't let packages with only public variables disappear
// Normal modules may disappear, e.g. if they are parameterized then removed
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
}
virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
@@ -166,6 +182,7 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
if (mightElim(nodep)) {
m_varEtcsp.push_back(nodep);
}
@@ -221,7 +238,9 @@ private:
bool mightElim(AstVar* nodep) {
return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO()
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
&& (nodep->isTemp()
|| (nodep->isParam() && !nodep->isTrace())
|| m_elimUserVars)); // Post-Trace can kill most anything
}
void deadCheckVar() {
// Delete any unused varscopes
@@ -249,6 +268,7 @@ private:
public:
// CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
m_modp = NULL;
m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes;
m_sideEffect = false;
@@ -271,12 +291,15 @@ public:
void V3Dead::deadifyModules(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, false);
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true);
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true);
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 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.
+14 -11
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2013 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -118,18 +118,20 @@ private:
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<<nodep->varp()->prettyName());
}
}
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) {
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/, AstNodeDType* newdtypep) {
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
AstVar* varp;
AstNodeModule* addmodp = oldvarscp->scopep()->modp();
// We need a new AstVar, but only one for all scopes, to match the new AstVarScope
VarMap::iterator iter = m_modVarMap.find(make_pair(addmodp,name));
if (iter != m_modVarMap.end()) {
VarMap::iterator it = m_modVarMap.find(make_pair(addmodp,name));
if (it != m_modVarMap.end()) {
// Created module's AstVar earlier under some other scope
varp = iter->second;
varp = it->second;
} else {
if (width==0) {
if (newdtypep) {
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, newdtypep);
} else if (width==0) {
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
varp->dtypeFrom(oldvarscp);
} else { // Used for vset and dimensions, so can zero init
@@ -219,7 +221,7 @@ private:
} else {
string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension)
+"__"+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width());
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), NULL);
AstAssign* bitassignp
= new AstAssign (nodep->fileline(),
new AstVarRef(nodep->fileline(), bitvscp, true),
@@ -237,7 +239,7 @@ private:
bitreadp = lsbvaluep;
} else {
string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width());
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width(), NULL);
AstAssign* bitassignp = new AstAssign (nodep->fileline(),
new AstVarRef(nodep->fileline(), bitvscp, true),
lsbvaluep);
@@ -252,7 +254,7 @@ private:
valreadp = nodep->rhsp()->unlinkFrBack();
} else {
string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, nodep->rhsp()->width());
AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, 0, nodep->rhsp()->dtypep());
newlhsp = new AstVarRef(nodep->fileline(), valvscp, true);
valreadp = new AstVarRef(nodep->fileline(), valvscp, false);
}
@@ -270,7 +272,7 @@ private:
++m_statSharedSet;
} else { // Create new one
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, NULL);
setinitp = new AstAssignPre (nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true),
new AstConst(nodep->fileline(), 0));
@@ -399,7 +401,7 @@ private:
}
if (!dlyvscp) { // First use of this delayed variable
string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
dlyvscp = createVarSc(oldvscp, newvarname, 0);
dlyvscp = createVarSc(oldvscp, newvarname, 0, NULL);
AstNodeAssign* prep
= new AstAssignPre (nodep->fileline(),
new AstVarRef(nodep->fileline(), dlyvscp, true),
@@ -469,4 +471,5 @@ public:
void V3Delayed::delayedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DelayedVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("delayed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

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