Compare commits

...
294 Commits
Author SHA1 Message Date
Wilson Snyder 5f21385e41 Version bump - commentary fix 2015-08-12 21:40:55 -04:00
Wilson Snyder 94fed93f54 Version bump 2015-08-12 21:34:59 -04:00
Wilson Snyder a950e4816d Support extraction of enum bits, bug951. 2015-08-12 21:33:40 -04:00
Wilson Snyder c87c66efb1 Fix size casts as second argument of cast item, bug950. 2015-08-12 19:37:25 -04:00
Jie Xu 5a5a0006fe Fix parameters with function parameter arguments, bug952.
Signed-off-by: Wilson Snyder <[email protected]>
2015-08-12 19:29:06 -04:00
Wilson Snyder 60b48a6830 Fix coverage documentation, bug954. 2015-08-12 19:18:58 -04:00
Wilson Snyder 5e41350588 Fix makefile with --coverage, bug953. 2015-08-12 19:06:15 -04:00
Wilson Snyder ff9f5b62ac bug951 testcase 2015-08-12 08:36:23 -04:00
Wilson Snyder 882913f0ca Add tracing_on, etc to vlt files, bug932. 2015-07-22 20:14:58 -04:00
Wilson Snyder 2062f7e97b Fix hashed error with typedef inside block, bug948. 2015-07-22 19:52:11 -04:00
Wilson Snyder 445c83a60d Fix with SV string, bug947. 2015-07-21 18:36:27 -04:00
Wilson Snyder 1891cfd79a Fix rounding in trace , bug946. 2015-07-21 13:22:08 -04:00
Wilson Snyder 06d5a7b2bf Internals: Allow hashing nulls; misc cleanup 2015-07-06 19:37:20 -04:00
Wilson Snyder 5af8a8aa4c Internals: Hash nulls 2015-07-05 20:31:30 -04:00
Wilson Snyder dc6b085d8b Fix MinGW compiler error, bug927. 2015-06-21 21:01:02 -04:00
Wilson Snyder 00759f777e Fix dpi imports inside generates. 2015-06-16 19:27:18 -04:00
Wilson Snyder 95ac0e61b2 Fix MinGW compiler error, bug927. 2015-06-16 07:13:45 -04:00
Wilson Snyder 6c5884853f Fix string-to-int space conversion, bug931. 2015-06-12 07:28:44 -04:00
Wilson Snyder 7578ef889f Fix .c files to be treated as .cpp, bug930. 2015-06-09 07:28:51 -04:00
Wilson Snyder da254af8d5 Fix MinGW compiler error, bug929. 2015-06-08 07:24:04 -04:00
Wilson Snyder 98123dc422 Verison fix 2015-06-06 14:02:06 -04:00
Wilson Snyder 466909b3d9 devel release 2015-06-06 14:00:23 -04:00
Wilson Snyder 0d4305192a Version bump 2015-06-06 13:58:26 -04:00
Wilson Snyder 9e61b9f696 Fix width propagation on sized casts, bug925. 2015-06-06 13:43:14 -04:00
Wilson Snyder 491539ff32 Fix MSVC++ compiler error, bug927. 2015-06-04 19:37:03 -04:00
Wilson Snyder 4c29a13a6e Fix include, part of bug919. 2015-05-16 18:08:20 -04:00
Wilson Snyder b66e1bdb9e Fix Ubuntu 15.04 compile warning. 2015-05-15 20:03:29 -04:00
Wilson Snyder 7312de6bc2 Fix sign extension in large localparams, bug910. 2015-05-14 21:46:07 -04:00
Wilson Snyder 1d6bcda014 Add pkg-config .pc file, bug919. 2015-05-13 21:21:29 -04:00
Wilson Snyder 5a747bad7d Fix width extension on mis-width ports, bug918. 2015-05-13 20:59:13 -04:00
Wilson Snyder 9542783a7e Internals: Refactor V3Inst static class. No functional change. 2015-05-13 20:56:16 -04:00
Wilson Snyder a59639413d Fix part-select in constant function, bug916. 2015-05-09 14:01:54 -04:00
Wilson Snyder d5eb92a071 Fix preprocessing stringified newline escapes, bug915. 2015-05-07 21:41:54 -04:00
Wilson Snyder 994cde57af Fix Cygwin uint32 compile, bug914. 2015-05-07 20:41:53 -04:00
Wilson Snyder 238a5809bf Fix truncation warning with -pins-bv, bug912. 2015-04-28 21:31:25 -04:00
Wilson Snyder 49fa65c0dd Match Verilog-Perl: Fix Preproc loop under Perl-Tk, bug913. 2015-04-28 15:54:34 -04:00
Wilson Snyder 49123f169c Fix core dump in sync-async warnings, bug911. 2015-04-27 06:47:29 -04:00
Wilson Snyder 4dc64c387f Part of prev commit, fix installing missing manpages, bug908. 2015-04-27 06:47:15 -04:00
Wilson Snyder 98a63711dd Fix installing missing manpages, bug908. 2015-04-09 19:03:01 -04:00
Wilson Snyder cb95cf4745 devel release 2015-04-09 19:00:02 -04:00
Wilson Snyder acd48fa61d Commentary, bug907. 2015-04-09 18:58:01 -04:00
Wilson Snyder cb7abcbaea Commentary 2015-04-09 18:57:25 -04:00
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
593 changed files with 20176 additions and 6317 deletions
+2
View File
@@ -23,3 +23,5 @@ gdbrun*
internals.txt internals.txt
verilator.txt verilator.txt
verilator_bin* verilator_bin*
verilator_coverage_bin*
verilator.pc
+330 -8
View File
@@ -3,6 +3,328 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.876 2015-08-12
*** Add tracing_on, etc to vlt files, bug932. [Frederic Requin]
**** Support extraction of enum bits, bug951. [Jonathon Donaldson]
**** Fix MinGW compiler error, bug927, bug929. [Hans Tichelaar]
**** Fix .c files to be treated as .cpp, bug930. [Jonathon Donaldson]
**** Fix string-to-int space conversion, bug931. [Fabrizio Ferrandi]
**** Fix dpi imports inside generates. [Michael Tresidder]
**** Fix rounding in trace $timescale, bug946. [Frederic Requin]
**** Fix $fopen with SV string, bug947. [Sven Stucki]
**** Fix hashed error with typedef inside block, bug948. [Sven Stucki]
**** Fix makefile with --coverage, bug953. [Eivind Liland]
**** Fix coverage documentation, bug954. [Thomas J Whatson]
**** Fix parameters with function parameter arguments, bug952. [Jie Xu]
**** Fix size casts as second argument of cast item, bug950. [Jonathon Donaldson]
* Verilator 3.874 2015-06-06
*** Add pkg-config .pc file, bug919. [Stefan Wallentowitz]
**** Fix installing missing manpages, bug908. [Ahmed El-Mahmoudy]
**** Fix sign extension in large localparams, bug910. [Mike Thyer]
**** Fix core dump in sync-async warnings, bug911. [Sebastian Dressler]
**** Fix truncation warning with -pins-bv, bug912. [Alfonso Martinez]
**** Fix Cygwin uint32 compile, bug914. [Matthew Barr]
**** Fix preprocessing stringified newline escapes, bug915. [Anton Rapp]
**** Fix part-select in constant function, bug916. [Andrew Bardsley]
**** Fix width extension on mis-width ports, bug918. [Patrick Maupin]
**** Fix width propagation on sized casts, bug925. [Jonathon Donaldson]
**** Fix MSVC++ compiler error, bug927. [Hans Tichelaar]
* 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 * Verilator 3.853 2013-09-30
@@ -53,17 +375,17 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.847 2013-05-11 * Verilator 3.847 2013-05-11
*** Add ALWCOMBORDER warning. [KC Buckenmaier] *** Add ALWCOMBORDER warning. [KC Buckenmaier]
*** Add --pins-sc-uint and --pins-sc-biguint, bug638. [Alex Hornung] *** Add --pins-sc-uint and --pins-sc-biguint, bug638. [Alex Hornung]
**** Support "signal[vec]++". **** Support "signal[vec]++".
**** Fix simulation error when inputs and MULTIDRIVEN, bug634. [Ted Campbell] **** Fix simulation error when inputs and MULTIDRIVEN, bug634. [Ted Campbell]
**** Fix module resolution with __, bug631. [Jason McMullan] **** Fix module resolution with __, bug631. [Jason McMullan]
**** Fix packed array non-zero right index select crash, bug642. [Krzysztof Jankowski] **** Fix packed array non-zero right index select crash, bug642. [Krzysztof Jankowski]
**** Fix nested union crash, bug643. [Krzysztof Jankowski] **** Fix nested union crash, bug643. [Krzysztof Jankowski]
@@ -379,7 +701,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 $fopen and I/O with integer instead of `verilator_file_descriptor.
*** Support coverage in -cc and -sc output modes. [John Li] *** 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] **** Fix vpi_register_cb using bad s_cb_data, bug370. [by Thomas Watts]
@@ -2279,7 +2601,7 @@ of input ports exists for tracing.
This uses outline mode in Emacs. See C-h m [M-x describe-mode]. This uses outline mode in Emacs. See C-h m [M-x describe-mode].
Copyright 2001-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 can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+3
View File
@@ -12,6 +12,7 @@
.*\.tex .*\.tex
.*\.key .*\.key
.*\.vcd .*\.vcd
.*\.1
/obj_dir/ /obj_dir/
/obj_dbg/ /obj_dbg/
/obj_opt/ /obj_opt/
@@ -27,7 +28,9 @@ config.cache$
config.status$ config.status$
verilator.log verilator.log
verilator.tex verilator.tex
verilator.pc$
verilator_bin.* verilator_bin.*
verilator_coverage_bin.*
.vcsmx_rebuild$ .vcsmx_rebuild$
autom4te\.cache/ autom4te\.cache/
nodist/ nodist/
+40 -30
View File
@@ -3,13 +3,11 @@
# #
# This file is part of Verilator. # This file is part of Verilator.
# #
# Author: Wilson Snyder <[email protected]>
#
# Code available from: http://www.veripool.org/verilator # 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 # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -86,6 +84,10 @@ infodir = @infodir@
# Generally ${prefix}/share/verilator # Generally ${prefix}/share/verilator
pkgdatadir = @pkgdatadir@ pkgdatadir = @pkgdatadir@
# Directory in which to install pkgconfig file
# Generall ${prefix}/share/pkgconfig
pkgconfigdir = @pkgconfigdir@
# Directory in which to install data across multiple architectures # Directory in which to install data across multiple architectures
datarootdir = @datarootdir@ datarootdir = @datarootdir@
@@ -100,10 +102,11 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
SHELL = /bin/sh 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 \ 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.pdf \
$(VL_INST_MAN_FILES)
# Files that can be generated, but should be up to date for a distribution. # Files that can be generated, but should be up to date for a distribution.
DISTDEP = info Makefile DISTDEP = info Makefile
@@ -120,7 +123,9 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
include/.*ignore \ include/.*ignore \
include/vltstd/*.[chv]* \ include/vltstd/*.[chv]* \
.*attributes */.*attributes */*/.*attributes \ .*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/.gdbinit \
src/*.pl src/*.pod \ src/*.pl src/*.pod \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \ test_*/.*ignore test_*/Makefile* test_*/*.cpp \
@@ -139,6 +144,7 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
INST_PROJ_FILES = \ INST_PROJ_FILES = \
bin/verilator \ bin/verilator \
bin/verilator_coverage \
bin/verilator_includer \ bin/verilator_includer \
bin/verilator_profcfunc \ bin/verilator_profcfunc \
include/verilated.mk \ include/verilated.mk \
@@ -148,6 +154,7 @@ INST_PROJ_FILES = \
INST_PROJ_BIN_FILES = \ INST_PROJ_BIN_FILES = \
verilator_bin \ verilator_bin \
verilator_bin_dbg \ verilator_bin_dbg \
verilator_coverage_bin_dbg \
DISTFILES := $(DISTFILES_INC) DISTFILES := $(DISTFILES_INC)
@@ -164,7 +171,8 @@ all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
.PHONY:verilator_exe .PHONY:verilator_exe
.PHONY:verilator_bin .PHONY:verilator_bin
.PHONY:verilator_bin_dbg .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 ------------------------------------------------------------
@echo "making verilator in src" ; \ @echo "making verilator in src" ; \
(cd src && $(MAKE) $(OBJCACHE_JOBS) ) (cd src && $(MAKE) $(OBJCACHE_JOBS) )
@@ -178,17 +186,15 @@ msg_test: all_nomsg
.PHONY:test .PHONY:test
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users 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 else
test: test_c test_sc test_sp test: test_c test_sc
endif endif
@echo "Tests passed!" @echo "Tests passed!"
@echo @echo
@echo "Type 'make install' to install documentation." @echo "Type 'make install' to install documentation."
@echo @echo
test_vcs: all_nomsg
@(cd test_vcs && $(MAKE))
test_c: all_nomsg test_c: all_nomsg
@(cd test_c && $(MAKE)) @(cd test_c && $(MAKE))
test_c_debug: all_nomsg test_c_debug: all_nomsg
@@ -197,10 +203,6 @@ test_sc: all_nomsg
@(cd test_sc && $(MAKE)) @(cd test_sc && $(MAKE))
test_sc_debug: all_nomsg test_sc_debug: all_nomsg
@(cd test_sc && $(MAKE) test_debug) @(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 test_verilated: all_nomsg
@(cd test_verilated && $(MAKE)) @(cd test_verilated && $(MAKE))
test_regress: all_nomsg test_regress: all_nomsg
@@ -209,7 +211,7 @@ test_regress: all_nomsg
info: $(INFOS) info: $(INFOS)
# Use --no-split to avoid creating filenames > 14 chars. # Use --no-split to avoid creating filenames > 14 chars.
verilator.1: ${srcdir}/bin/verilator %.1: ${srcdir}/bin/%
pod2man $< $@ pod2man $< $@
verilator.txt: ${srcdir}/bin/verilator verilator.txt: ${srcdir}/bin/verilator
@@ -227,16 +229,16 @@ verilator.pdf: ${srcdir}/bin/verilator Makefile
pdflatex verilator.tex pdflatex verilator.tex
-rm -f verilator.toc verilator.aux verilator.idx verilator.out -rm -f verilator.toc verilator.aux verilator.idx verilator.out
README: readme.pod README: README.pod
-rm -f $@ -rm -f $@
$(POD2TEXT) --loose $< > $@ $(POD2TEXT) --loose $< > $@
README.html: readme.pod README.html: README.pod
pod2html $< >$@ pod2html $< >$@
# PDF needs DIST variables; but having configure.ac as dependency isn't detected # PDF needs DIST variables; but having configure.ac as dependency isn't detected
README.pdf: readme.pod Makefile README.pdf: README.pod Makefile
pod2latex --full --out README.tex readme.pod pod2latex --full --out README.tex README.pod
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE) README File" "${DISTDATE}" < README.tex > README2.tex $(PERL) $(POD2LATEXFIX) "$(DISTTITLE) README File" "${DISTDATE}" < README.tex > README2.tex
mv README2.tex README.tex mv README2.tex README.tex
pdflatex README.tex pdflatex README.tex
@@ -260,13 +262,13 @@ internals.pdf: internals.pod Makefile
-rm -f internals.toc internals.aux internals.idx internals.out -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 # 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 \ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg \
verilator_includer verilator_profcfunc verilator_coverage verilator_includer verilator_profcfunc
# Some scripts go into both the search path and pkgdatadir, # Some scripts go into both the search path and pkgdatadir,
# so they can be found by the user, and under $VERILATOR_ROOT. # 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 # 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 verilator_profcfunc.1
VL_INST_INC_BLDDIR_FILES = \ VL_INST_INC_BLDDIR_FILES = \
include/verilated.mk \ include/verilated.mk \
@@ -280,14 +282,15 @@ VL_INST_DATA_SRCDIR_FILES = \
test_v/*.[chv]* \ test_v/*.[chv]* \
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \ test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \ test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
test_sp/Makefile test_sp/Makefile_obj \
installbin: installbin:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir) $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator ) ( 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 ) ( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin ) ( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg ) ( $(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 $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer ) ( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
@@ -295,7 +298,7 @@ installbin:
# So important we use $< so VPATH is searched # So important we use $< so VPATH is searched
installman: $(VL_INST_MAN_FILES) installman: $(VL_INST_MAN_FILES)
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1 $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
for p in $< ; do \ for p in $^ ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \ $(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
done done
@@ -310,12 +313,13 @@ installdata:
done done
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sp
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v
cd $(srcdir) \ cd $(srcdir) \
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \ ; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \ $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
done done
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgconfigdir)
$(INSTALL_DATA) verilator.pc $(DESTDIR)$(pkgconfigdir)
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files # We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
uninstall: uninstall:
@@ -325,6 +329,7 @@ uninstall:
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES) -cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES) -cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES) -cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
-rm $(DESTDIR)$(pkgconfigdir)/verilator.pc
-rmdir $(DESTDIR)$(pkgdatadir)/bin -rmdir $(DESTDIR)$(pkgdatadir)/bin
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd -rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
-rmdir $(DESTDIR)$(pkgdatadir)/include -rmdir $(DESTDIR)$(pkgdatadir)/include
@@ -334,6 +339,7 @@ uninstall:
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v -rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
-rmdir $(DESTDIR)$(pkgdatadir)/examples -rmdir $(DESTDIR)$(pkgdatadir)/examples
-rmdir $(DESTDIR)$(pkgdatadir) -rmdir $(DESTDIR)$(pkgdatadir)
-rmdir $(DESTDIR)$(pkgconfigdir)
install: all_nomsg install-all install: all_nomsg install-all
install-all: installbin installman installdata install-msg install-all: installbin installman installdata install-msg
@@ -350,6 +356,7 @@ INST_PROJ_CVS = cp_if_cvs_diff
install-project: dist install-project: dist
@echo "Install-project to $(DIRPROJECT)" @echo "Install-project to $(DIRPROJECT)"
strip verilator_bin* strip verilator_bin*
strip verilator_coverage_bin*
$(MAKE) install-project-quick $(MAKE) install-project-quick
for p in $(VL_INST_MAN_FILES) ; do \ for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \ $(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
@@ -373,6 +380,7 @@ endif
install-cadtools: dist install-cadtools: dist
@echo "Install-project to $(CAD_DIR)" @echo "Install-project to $(CAD_DIR)"
strip verilator_bin* strip verilator_bin*
strip verilator_coverage_bin*
$(MAKE) install-cadtools-quick $(MAKE) install-cadtools-quick
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1 $(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
for p in $(VL_INST_MAN_FILES) ; do \ for p in $(VL_INST_MAN_FILES) ; do \
@@ -400,8 +408,9 @@ endif
endif endif
# Use --xml flag to see the cppcheck code to use for suppression # Use --xml flag to see the cppcheck code to use for suppression
CPPCHECK = cppcheck CPPCHECK = src/cppcheck_filtered
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject --suppress=cstyleCast CPPCHECK_FLAGS = --enable=all --inline-suppr \
--suppress=unusedScopedObject --suppress=cstyleCast --suppress=useInitializationList
CPPCHECK_FLAGS += --xml CPPCHECK_FLAGS += --xml
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp) CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP)) CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
@@ -416,7 +425,7 @@ ftp: info
install-msg: install-msg:
@echo "Installed!" @echo "Installed!"
@echo @echo
@echo "Fod documentation see 'man verilator' or 'verilator --help'" @echo "For documentation see 'man verilator' or 'verilator --help'"
@echo "For forums and to report bugs see http://www.veripool.org/verilator" @echo "For forums and to report bugs see http://www.veripool.org/verilator"
@echo @echo
@@ -458,7 +467,8 @@ clean mostlyclean distclean maintainer-clean::
rm -f *.tex rm -f *.tex
distclean maintainer-clean:: 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 rm -f include/verilated.mk include/verilated_config.h
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \ TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
+6 -14
View File
@@ -5,11 +5,13 @@
=head1 NAME =head1 NAME
This is the Verilator Package README file. This is the Verilator package README file.
=head1 DISTRIBUTION =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/>.) L<http://www.veripool.org/>.)
Verilator is free software; you can redistribute it and/or modify it under Verilator is free software; you can redistribute it and/or modify it under
@@ -76,14 +78,6 @@ instead.)
=item =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.
=item
You will need the C<flex> and C<bison> packages installed. You will need the C<flex> and C<bison> packages installed.
=item =item
@@ -95,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. 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, Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC_INCLUDE,
SYSTEMC_LIBDIR, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the and SYSTEMC_LIBDIR as defaults into the executable, so try to have them
executable, so try to have them correct before configuring. correct before configuring.
=over 4 =over 4
@@ -198,8 +192,6 @@ The directories in the kit after de-taring are as follows:
test_v => Example Verilog code for other test dirs test_v => Example Verilog code for other test dirs
test_c => Example Verilog->C++ conversion test_c => Example Verilog->C++ conversion
test_sc => Example Verilog->SystemC 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_verilated => Internal tests
test_regress => Internal tests test_regress => Internal tests
Regular → Executable
+2 -16
View File
@@ -1,6 +1,6 @@
// DESCRIPTION: Verilator: List of To Do issues. // 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -30,21 +30,6 @@ Configure/Make/Install
* Full MSVC++ compilation (does scons support this?) (4.000?) * Full MSVC++ compilation (does scons support this?) (4.000?)
* Distribute with flex/bison already expanded? * Distribute with flex/bison already expanded?
Flex library not needed. Probably too difficult to be worth it. 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: Testing:
* Move test_c/sp/v/verilated into test_regress format (4.000?) * Move test_c/sp/v/verilated into test_regress format (4.000?)
@@ -53,6 +38,7 @@ Testing:
* New random program generator * New random program generator
* Better graph viewer with search and zoom * Better graph viewer with search and zoom
* Port and test against opencores.org code * Port and test against opencores.org code
* // verilator debug in code so can see only tree affecting those nodes
Usability: Usability:
* Detect and pre-remove most UNOPTFLATs (4.000) * Detect and pre-remove most UNOPTFLATs (4.000)
+293 -222
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0; 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 # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -24,14 +24,10 @@ BEGIN {
} }
} }
use File::Path;
use File::Basename;
use Getopt::Long; use Getopt::Long;
use FindBin qw($RealBin $RealScript); use FindBin qw($RealBin $RealScript);
use IO::File; use IO::File;
use Pod::Usage; use Pod::Usage;
use Config;
use Cwd qw(abs_path getcwd);
use strict; use strict;
use vars qw ($Debug @Opt_Verilator_Sw); use vars qw ($Debug @Opt_Verilator_Sw);
@@ -209,17 +205,13 @@ Verilator - Convert Verilog code to C++/SystemC
=head1 DESCRIPTION =head1 DESCRIPTION
Verilator converts synthesizable (not behavioral) Verilog code, plus some Verilator converts synthesizable (not behavioral) Verilog code, plus some
Synthesis, SystemVerilog and a small subset of Verilog AMS and Sugar/PSL Synthesis, SystemVerilog and a small subset of Verilog AMS assertions, into
assertions, into C++, SystemC or SystemPerl code. It is not a complete C++ or SystemC code. It is not a complete simulator, but a compiler.
simulator, just a compiler.
Verilator is invoked with parameters similar to GCC, Cadence Verilator is invoked with parameters similar to GCC, Cadence
Verilog-XL/NC-Verilog, or Synopsys's VCS. It reads the specified Verilog Verilog-XL/NC-Verilog, or Synopsys's VCS. It reads the specified Verilog
code, lints it, and optionally adds coverage and waveform tracing code. code, lints it, and optionally adds coverage and waveform tracing code.
For C++ and SystemC formats, it outputs .cpp and .h files. For SystemPerl For C++ and SystemC formats, it outputs .cpp and .h files.
format, it outputs .sp files for the SystemPerl preprocessor, which greatly
simplifies writing SystemC code and is available at
L<http://www.veripool.org>.
The files created by Verilator are then compiled with C++. The user writes 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 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 -CFLAGS <flags> C++ Compiler flags for makefile
--cc Create C++ output --cc Create C++ output
--cdc Clock domain crossing analysis --cdc Clock domain crossing analysis
--clk <signal-name> Mark specified signal as clock
--compiler <compiler-name> Tune for specified C++ compiler --compiler <compiler-name> Tune for specified C++ compiler
--converge-limit <loops> Tune convergence settle time --converge-limit <loops> Tune convergence settle time
--coverage Enable all coverage --coverage Enable all coverage
--coverage-line Enable line coverage --coverage-line Enable line coverage
--coverage-toggle Enable toggle 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 --coverage-underscore Enable coverage of _signals
-D<var>[=<value>] Set preprocessor define -D<var>[=<value>] Set preprocessor define
--debug Enable debugging --debug Enable debugging
@@ -267,9 +260,10 @@ descriptions in the next sections for more information.
--debugi <level> Enable debugging at a specified level --debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level --debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse --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-tree Enable dumping .tree files
--dump-treei <level> Enable dumping .tree files at a level --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 -E Preprocess, but do not compile
--error-limit <value> Abort after this number of errors --error-limit <value> Abort after this number of errors
--exe Link to create executable --exe Link to create executable
@@ -292,6 +286,7 @@ descriptions in the next sections for more information.
--MP Create phony dependency targets --MP Create phony dependency targets
--Mdir <directory> Name of output object directory --Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes --mod-prefix <topname> Name to prepend to lower classes
--no-clk <signal-name> Prevent marking specified signal as clock
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs --no-pins64 Don't use vluint64_t's for 33-64 bit sigs
--no-skip-identical Disable skipping identical output --no-skip-identical Disable skipping identical output
+notimingchecks Ignored +notimingchecks Ignored
@@ -303,6 +298,7 @@ descriptions in the next sections for more information.
--output-split <bytes> Split .cpp files into pieces --output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .cpp functions --output-split-cfuncs <statements> Split .cpp functions
--output-split-ctrace <statements> Split tracing 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-bv <bits> Specify types for top level ports
--pins-sc-uint Specify types for top level ports --pins-sc-uint Specify types for top level ports
--pins-sc-biguint Specify types for top level ports --pins-sc-biguint Specify types for top level ports
@@ -311,13 +307,12 @@ descriptions in the next sections for more information.
--prefix <topname> Name of top level class --prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling --profile-cfuncs Name functions for profiling
--private Debugging; see docs --private Debugging; see docs
--psl Enable PSL parsing
--public Debugging; see docs --public Debugging; see docs
--report-unoptflat Extra diagnostics for UNOPTFLAT --report-unoptflat Extra diagnostics for UNOPTFLAT
--savable Enable model save-restore --savable Enable model save-restore
--sc Create SystemC output --sc Create SystemC output
--sp Create SystemPerl output
--stats Create statistics file --stats Create statistics file
--stats-vars Provide statistics on variables
-sv Enable SystemVerilog parsing -sv Enable SystemVerilog parsing
+systemverilogext+<ext> Synonym for +1800-2012ext+<ext> +systemverilogext+<ext> Synonym for +1800-2012ext+<ext>
--top-module <topname> Name of top level input module --top-module <topname> Name of top level input module
@@ -325,6 +320,8 @@ descriptions in the next sections for more information.
--trace-depth <levels> Depth of tracing --trace-depth <levels> Depth of tracing
--trace-max-array <depth> Maximum bit width for tracing --trace-max-array <depth> Maximum bit width for tracing
--trace-max-width <width> Maximum array depth 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 --trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define -U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations --unroll-count <loops> Tune maximum loop iterations
@@ -408,8 +405,7 @@ C<+1364-1995ext+> etc. specify both the syntax I<and> semantics to be used.
=item --assert =item --assert
Enable all assertions, includes enabling the --psl flag. (If psl is not Enable all assertions.
desired, but other assertions are, use --assert --nopsl.)
See also --x-assign and --x-initial-edge; setting "--x-assign unique" See also --x-assign and --x-initial-edge; setting "--x-assign unique"
and/or "--x-initial-edge" may be desirable. and/or "--x-initial-edge" may be desirable.
@@ -451,7 +447,7 @@ run on the generated makefile these will be passed to the C++ compiler
=item --cc =item --cc
Specifies C++ without SystemC output mode; see also --sc and --sp. Specifies C++ without SystemC output mode; see also --sc.
=item --cdc =item --cdc
@@ -463,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 Currently only checks some items that other CDC tools missed; if you have
interest in adding more traditional CDC checks, please contact the authors. 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> =item --compiler I<compiler-name>
Enables tunings and work-arounds for the specified C++ compiler. Enables tunings and work-arounds for the specified C++ compiler.
=over 4 =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 =item gcc
Tune for Gnu C++, although generated code should work on almost any Tune for Gnu C++, although generated code should work on almost any
@@ -555,24 +574,26 @@ signals are not covered. See also --trace-underscore.
=item --coverage-user =item --coverage-user
Enables user inserted functional coverage. Currently, all functional Enables user inserted functional coverage. Currently, all functional
coverage points are specified using PSL which must be separately enabled coverage points are specified using SVA which must be separately enabled
with --psl. 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": the comment "DefaultClock":
// psl default clock = posedge clk; DefaultClock: cover property (@(posedge clk) cyc==3);
// psl cover {cyc==9} report "DefaultClock,expect=1";
=item -DI<var>=I<value> =item -DI<var>=I<value>
Defines the given preprocessor symbol. Same as +define; +define is fairly Defines the given preprocessor symbol, without allowing. Similar to
standard across Verilog tools while -D is an alias for GCC compatibility. +define; +define is fairly standard across Verilog tools while -D is an
alias for GCC compatibility.
=item --debug =item --debug
Select the debug built image of Verilator (if available), and enable more Select the debug built image of Verilator (if available), and enable more
internal assertions, 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 =item --debug-check
@@ -584,9 +605,9 @@ changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi-<srcfile> <level> =item --debugi-<srcfile> <level>
Rarely needed - for developer use. Set internal debugging level globally 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 to the specified debug level (1-10) or set the specified Verilator source
specified level. Higher levels produce more detailed messages (plain file to the specified level (e.g. C<--debugi-V3Width 9>). Higher levels
C<--debug> is equivalent to C<--debugi 4>). produce more detailed messages.
=item --default-language I<value> =item --default-language I<value>
@@ -607,10 +628,13 @@ used.
If no language is specified, either by this flag or +I<lang>ext+ options, If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used. 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 =item +define+I<var>=I<value>+I<var2>=I<value2>...
standard across Verilog tools while -D is an alias for GCC compatibility.
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 =item --dump-tree
@@ -622,8 +646,12 @@ large and not desired.
=item --dump-treei <level> =item --dump-treei <level>
Rarely needed. Enable writing .tree debug files with a specific dumping =item --dump-treei-<srcfile> <level>
level, 0 disbles dumps and is equivelent to "--no-dump-tree". Level 9
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. enables dumping of every stage.
=item -E =item -E
@@ -748,13 +776,19 @@ to gcc -MP option.
=item --Mdir I<directory> =item --Mdir I<directory>
Specifies the name of the Make object directory. All generated files will 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> =item --mod-prefix I<topname>
Specifies the name to prepend to all lower level classes. Defaults to Specifies the name to prepend to all lower level classes. Defaults to
the same as --prefix. the same as --prefix.
=item --no-clk <signal-name>
Prevent the specified signal from being marked as clock. See C<--clk>.
=item --no-pins64 =item --no-pins64
Backward compatible alias for "--pins-bv 33". Backward compatible alias for "--pins-bv 33".
@@ -774,8 +808,10 @@ Disables optimization of the model.
=item -O3 =item -O3
Enables slow optimizations. This may reduce simulation runtimes at the Enables slow optimizations for the code Verilator itself generates (as
cost of compile time. This currently sets --inline-mult -1. 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> =item -OI<optimization-letter>
@@ -823,6 +859,11 @@ function.
Enables splitting trace functions in the output .cpp/.sp files into Enables splitting trace functions in the output .cpp/.sp files into
multiple functions. Defaults to same setting as --output-split-cfuncs. 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 =item --pins64
Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64. Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
@@ -893,12 +934,6 @@ statements.
Opposite of --public. Is the default; this option exists for backwards Opposite of --public. Is the default; this option exists for backwards
compatibility. 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 =item --public
This is only for historical debug use. Using it may result in This is only for historical debug use. Using it may result in
@@ -920,7 +955,7 @@ break the loop.
In addition produces a GraphViz DOT file of the entire strongly connected In addition produces a GraphViz DOT file of the entire strongly connected
components within the source associated with each loop. This is produced components within the source associated with each loop. This is produced
irrespective of whether --dump-tree is set. Such graphs may help in 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 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 the I<dot> command can be used to convert a DOT file to a PDF for
@@ -954,16 +989,18 @@ other data the process needs saved/restored. For example:
=item --sc =item --sc
Specifies SystemC output mode; see also --cc and -sp. Specifies SystemC output mode; see also --cc.
=item --sp
Specifies SystemPerl output mode; see also --cc and -sc.
=item --stats =item --stats
Creates a dump file with statistics on the design in {prefix}__stats.txt. 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 =item -sv
Specifies SystemVerilog language features should be enabled; equivalent to Specifies SystemVerilog language features should be enabled; equivalent to
@@ -1013,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 traced. Defaults to 256, as tracing large vectors may greatly slow traced
simulations. 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 =item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these Enable tracing of signals that start with an underscore. Normally, these
@@ -1076,15 +1124,17 @@ supports which the older version does not support.
=item -Wno-I<message> =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 =item -Wno-lint
Disable all lint related warning messages, and all style warnings. This is Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-ALWCOMBORDER -Wno-CASEINCOMPLETE -Wno-CASEOVERLAP equivalent to "-Wno-ALWCOMBORDER -Wno-CASEINCOMPLETE -Wno-CASEOVERLAP
-Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT -Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT
-Wno-LITENDIAN -Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-LITENDIAN -Wno-PINCONNECTEMPTY -Wno-PINMISSING -Wno-SYNCASYNCNET
-Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for Wno-style. -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 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 option, it is only intended to be use when running test-cases of code
@@ -1094,8 +1144,8 @@ received from third parties.
Disable all code style related warning messages (note by default they are Disable all code style related warning messages (note by default they are
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-PINNOCONNECT -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-INCABSPATH -Wno-PINCONNECTEMPTY -Wno-PINNOCONNECT -Wno-SYNCASYNCNET
-Wno-UNUSED -Wno-VARHIDDEN". -Wno-UNDRIVEN -Wno-UNUSED -Wno-VARHIDDEN".
=item -Wno-fatal =item -Wno-fatal
@@ -1174,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 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 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>. ensure that X E<rarr> 1 triggers a C<posedge>.
B<Note.> Some users have reported that using this option can affect B<Note.> Some users have reported that using this option can affect
@@ -1263,7 +1313,7 @@ the test_c directory in the distribution for an example.
=head1 EXAMPLE SYSTEMC EXECUTION =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 mkdir test_our_sc
cd test_our_sc cd test_our_sc
@@ -1298,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. Now we run Verilator on our little example.
verilator -Wall --sp our.v verilator -Wall --sc 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.)
We then can compile it We then can compile it
@@ -1319,6 +1359,7 @@ And link with SystemC. Note your path to the libraries may vary,
depending on the operating system. depending on the operating system.
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
export LD_LIBRARY_PATH=$SYSTEMC_LIBDIR:$LD_LIBRARY_PATH
# Might be needed if SystemC 2.3.0 # Might be needed if SystemC 2.3.0
export SYSTEMC_CXX_FLAGS=-pthread export SYSTEMC_CXX_FLAGS=-pthread
@@ -1337,7 +1378,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, 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 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 =head1 BENCHMARKING & OPTIMIZATION
@@ -1395,6 +1436,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 both compilation and link. Note LTO may cause excessive compile times on
large designs. 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. 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 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. either oprofile or gprof to see where in the C++ code the time is spent.
@@ -1422,11 +1467,6 @@ For -cc and -sc mode, it also creates:
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files {prefix}{each_verilog_module}.cpp // Lower level internal C++ files
{prefix}{each_verilog_module}.h // Lower level internal header files {prefix}{each_verilog_module}.h // Lower level internal header files
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: In certain optimization modes, it also creates:
{prefix}__Dpi.h // DPI import and export declarations {prefix}__Dpi.h // DPI import and export declarations
@@ -1459,6 +1499,12 @@ After running Make, the C++ compiler should produce the following:
=over 4 =over 4
=item LD_LIBRARY_PATH
A generic Linux/OS variable specifying what directories have shared object
(.so) files. This path should include SystemC and any other shared objects
needed at runtime.
=item OBJCACHE =item OBJCACHE
Optionally specifies a caching or distribution program to place in front of Optionally specifies a caching or distribution program to place in front of
@@ -1501,21 +1547,6 @@ specified, it will come from a default optionally specified at configure
time (before Verilator was compiled), or computed from time (before Verilator was compiled), or computed from
SYSTEMC/lib-SYSTEMC_ARCH. 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 =item VCS_HOME
If set, specifies the directory containing the Synopsys VCS distribution. If set, specifies the directory containing the Synopsys VCS distribution.
@@ -1892,27 +1923,40 @@ The grammar of configuration commands is as follows:
Take remaining text up the the next `verilog mode switch and treat it as Take remaining text up the the next `verilog mode switch and treat it as
Verilator configuration commands. Verilator configuration commands.
=item coverage_on [-file "<filename>" [-lines <line> [ - <line> ]]]
=item coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]] =item coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
Disable coverage for the specified filename (or wildcard with '*' or '?', Enable/disable coverage for the specified filename (or wildcard with '*' or
or all files if omitted) and range of line numbers (or all lines if '?', or all files if omitted) and range of line numbers (or all lines if
omitted). Often used to ignore an entire module for coverage analysis omitted). Often used to ignore an entire module for coverage analysis
purposes. purposes.
=item lint_on [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
=item lint_off [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]] =item lint_off [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
Disables the specified lint warning, in the specified filename (or wildcard Enable/disables the specified lint warning, in the specified filename (or
with '*' or '?', or all files if omitted) and range of line numbers (or all wildcard with '*' or '?', or all files if omitted) and range of line
lines if omitted). numbers (or all lines if omitted).
If the -msg is omitted, all lint warnings are disabled. This will override With lint_off using '*' will override any lint_on directives in the source,
all later lint warning enables for the specified region. i.e. the warning will still not be printed.
If the -msg is omitted, all lint warnings are enabled/disabled. This will
override all later lint warning enables for the specified region.
=item tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
=item tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]] =item tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
Disable waveform tracing for all future signals declared in the specified Enable/disable waveform tracing for all future signals declared in the
filename (or wildcard with '*' or '?', or all files if omitted) and range specified filename (or wildcard with '*' or '?', or all files if omitted)
of line numbers (or all lines if omitted). and range of line numbers (or all lines if omitted).
For tracing_off, cells below any module in the files/ranges specified will
also not be traced.
=back =back
@@ -1959,7 +2003,7 @@ please file a bug if a feature you need is missing.
Verilator implements a very small subset of Verilog AMS (Verilog Analog and Verilator implements a very small subset of Verilog AMS (Verilog Analog and
Mixed-Signal Extensions) with the subset corresponding to those VMS 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. languages.
AMS parsing is enabled with "--language VAMS" or "--language 1800+VAMS". AMS parsing is enabled with "--language VAMS" or "--language 1800+VAMS".
@@ -1967,34 +2011,6 @@ AMS parsing is enabled with "--language VAMS" or "--language 1800+VAMS".
At present Verilator implements ceil, exp, floor, ln, log, pow, sqrt, At present Verilator implements ceil, exp, floor, ln, log, pow, sqrt,
string, and wreal. 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 =head2 Synthesis Directive Assertion Support
With the --assert switch, Verilator reads any "//synopsys full_case" or With the --assert switch, Verilator reads any "//synopsys full_case" or
@@ -2007,8 +2023,8 @@ appropriate code to detect failing cases at runtime and print an "Assertion
failed" error message. failed" error message.
Verilator likewise also asserts any "unique" or "priority" SystemVerilog Verilator likewise also asserts any "unique" or "priority" SystemVerilog
keywords on case statements. However, "unique if" and "priority if" are keywords on case statement, as well as "unique" on if statements.
currently simply ignored. However, "priority if" is currently simply ignored.
=head1 LANGUAGE EXTENSIONS =head1 LANGUAGE EXTENSIONS
@@ -2035,13 +2051,6 @@ supported by Verilator since 2006!)
This will report an error when encountered, like C++'s #error. 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>, ...); =item $c(I<string>, ...);
The string will be embedded directly in the output C++ code at the point The string will be embedded directly in the output C++ code at the point
@@ -2163,6 +2172,15 @@ scheduling algorithm, sometimes required for correct clock behavior, and
always improving performance. It's also a good idea to enable the always improving performance. It's also a good idea to enable the
IMPERFECTSCH warning, to insure all clock enables are properly recognized. 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*/ =item /*verilator coverage_block_off*/
Specifies the entire begin/end block should be ignored for coverage Specifies the entire begin/end block should be ignored for coverage
@@ -2185,8 +2203,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 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 small loss of trace visibility and modularity. Note signals under inlined
submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not
allow "." in signal names. SystemPerl when tracing such signals will allow "." in signal names. When tracing such signals the tracing routines
replace the __DOT__ with the period. will replace the __DOT__ with the period.
=item /*verilator isolate_assignments*/ =item /*verilator isolate_assignments*/
@@ -2260,6 +2278,14 @@ reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself. be pure; they cannot reference any variables outside the task itself.
=item /*verilator public*/ (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) =item /*verilator public*/ (variable)
Used after an input, output, register, or wire declaration to indicate the Used after an input, output, register, or wire declaration to indicate the
@@ -2347,12 +2373,14 @@ behavior. See the test_regress/t/t_dpi_display.v file for an example.
=item /*verilator tracing_off*/ =item /*verilator tracing_off*/
Disable waveform tracing for all future signals that are declared in this 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 module, or cells below this module. Often this is placed just after a
that the entire module is not traced. primitive's module statement, so that the entire module and cells below it
are not traced.
=item /*verilator tracing_on*/ =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 =back
@@ -2455,7 +2483,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. practice, just setting all variables to one at startup finds most problems.
B<Note.> --x-assign applies to variables explicitly initialized or assigned to 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. variables are initialized to a random value.
Event driven simulators will generally trigger an edge on a transition from X Event driven simulators will generally trigger an edge on a transition from X
@@ -2631,8 +2659,9 @@ All specify blocks and timing checks are ignored.
=item string =item string
String is supported only to the point that they can be passed to DPI String is supported only to the point that they can be assigned,
imports. concatenated, compared, and passed to DPI imports. Standard method calls
on strings are not supported.
=item timeunit, timeprecision =item timeunit, timeprecision
@@ -2868,6 +2897,16 @@ With --cdc only, warns that asynchronous flop reset terms come from other
than primary inputs or flopped outputs, creating the potential for reset than primary inputs or flopped outputs, creating the potential for reset
glitches. 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 recommended to check the warning as this may degrade the performance of
the Verilated model.
=item CMPCONST =item CMPCONST
Warns that you are comparing a value in a way that will always be constant. Warns that you are comparing a value in a way that will always be constant.
@@ -2981,8 +3020,8 @@ simulators.
Warns that an `include filename specifies an absolute path. This means the 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. code will not work on any other system with a different file system layout.
Instead of using absolute paths, relative paths (preferably without any Instead of using absolute paths, relative paths (preferably without any
directory specified whatever) should be used, and +include used on the directory specified whatever) should be used, and +incdir used on the
command line to specify the top include source directory. command line to specify the top include source directories.
Disabled by default as this is a code style warning; it will simulate Disabled by default as this is a code style warning; it will simulate
correctly. correctly.
@@ -3033,11 +3072,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 unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y. 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 =item PINMISSING
Warns that a module has a pin which is not mentioned in a cell 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 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 Ignoring this warning will only suppress the lint check, it will simulate
correctly. correctly.
@@ -3101,10 +3150,9 @@ simulators.
=item SYMRSVDWORD =item SYMRSVDWORD
Error that a symbol matches a C++ reserved word and using this as a symbol 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 error name would result in odd C compiler errors. You may disable this warning,
message as you would disable warnings, but the symbol will be renamed by but the symbol will be renamed by Verilator to avoid the conflict.
Verilator to avoid the conflict.
=item SYNCASYNCNET =item SYNCASYNCNET
@@ -3225,6 +3273,13 @@ section for more details.
Ignoring this warning will only slow simulations, it will simulate Ignoring this warning will only slow simulations, it will simulate
correctly. 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 =item UNSIGNED
Warns that you are comparing a unsigned value in a way that implies it is Warns that you are comparing a unsigned value in a way that implies it is
@@ -3386,7 +3441,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 synthesis interpretation, so this is a good thing for getting working
silicon. 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 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 the "GNU *Lesser* Public License Version 3" instead of the more typical
@@ -3438,10 +3493,6 @@ flag.
Note you can also call ->trace on multiple Verilated objects with the same 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. 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" #include "verilated_vcd_c.h"
... ...
int main(int argc, char **argv, char **env) { int main(int argc, char **argv, char **env) {
@@ -3464,7 +3515,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 include verilated_vcd_sc.h. Then call Verilated::traceEverOn(true). Then
create a VerilatedVcdSc object as you would create a normal SystemC trace create a VerilatedVcdSc object as you would create a normal SystemC trace
file. For an example, see the call to VerilatedVcdSc in the 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 Alternatively you may use the C++ trace mechanism described in the previous
question, however the timescale and timeprecision will not inherited from question, however the timescale and timeprecision will not inherited from
@@ -3516,22 +3567,24 @@ network disk. Network disks are generally far slower.
=item How do I do coverage analysis? =item How do I do coverage analysis?
Verilator supports both block (line) coverage and user inserted functional Verilator supports both block (line) coverage and user inserted functional
coverage. Both require the SystemPerl package to be installed but do not coverage.
require use of the SystemPerl output mode.
First, run verilator with the --coverage option. If you're using your own 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 makefile, compile the model with the GCC flag -DVM_COVERAGE (if using
using Verilator's, it will do this for you.) Verilator's, it will do this for you.)
Run your tests in different directories. Each test will create a At the end of your test, call VerilatedCov::write passing the name of the
coverage data file (typically "logs/coverage.dat").
Run each of your tests in different directories. Each test will create a
logs/coverage.pl file. logs/coverage.pl file.
After running all of your tests, the vcoverage utility (from the SystemPerl After running all of your tests, verilator_coverage is executed.
package) is executed. Vcoverage reads the logs/coverage.pl file(s), and Verilator_coverage reads the logs/coverage.pl file(s), and creates an
creates an annotated source code listing showing code coverage details. annotated source code listing showing code coverage details.
For an example, after running 'make test' in the Verilator distribution, 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. with '%' to see what lines Verilator believes need more coverage.
=item Where is the translate_off command? (How do I ignore a construct?) =item Where is the translate_off command? (How do I ignore a construct?)
@@ -3760,70 +3813,88 @@ as the need arises. Verilator is now about 3x faster than in 2002, and is
faster than many popular commercial simulators. 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 =head1 AUTHORS
When possible, please instead report bugs to L<http://www.veripool.org/>. When possible, please instead report bugs to L<http://www.veripool.org/>.
Wilson Snyder <[email protected]> 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 =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, 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>. 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 redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0. General Public License Version 3 or the Perl Artistic License Version 2.0.
+6 -2
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0; if 0;
# DESCRIPTION: Print include statements for each ARGV # DESCRIPTION: Print include statements for each ARGV
# #
# Copyright 2003-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 # redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0. # General Public License Version 3 or the Perl Artistic License Version 2.0.
###################################################################### ######################################################################
@@ -12,5 +12,9 @@ require 5.005;
use warnings; use warnings;
print "// DESCR"."IPTION: Generated by verilator_includer via makefile\n"; print "// DESCR"."IPTION: Generated by verilator_includer via makefile\n";
foreach my $param (@ARGV) { 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{type}{"Common code under $design"} += $pct;
$groups{design}{$design} += $pct; $groups{design}{$design} += $pct;
$groups{module}{$design." common code"} += $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 { } else {
$vfunc = sprintf("C++ %s", $func); $vfunc = sprintf("C++ %s", $func);
$groups{type}{'C++'} += $pct; $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; my $missing = 100;
foreach (sort (keys %{$groups{$type}})) { foreach (sort (keys %{$groups{$type}})) {
$missing -= $groups{$type}{$_}; $missing -= $groups{$type}{$_};
@@ -150,8 +162,10 @@ sub profcfunc {
print("Verilog code profile:\n"); print("Verilog code profile:\n");
print(" These are split into three categories:\n"); print(" These are split into three categories:\n");
print(" C++: Time in non-Verilated C++ code\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(" 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(" 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("\n");
print(" % cumulative self \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/>. 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 redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0. General Public License Version 3 or the Perl Artistic License Version 2.0.
+38 -13
View File
@@ -1,14 +1,16 @@
# DESCRIPTION: Process this file with autoconf to produce a configure script. # 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 # redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0. # General Public License Version 3 or the Perl Artistic License Version 2.0.
#AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel]) #AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.853 2013-09-30]) AC_INIT([Verilator],[3.876 2015-08-12])
# When releasing, also update header of Changes file
AC_CONFIG_HEADER(src/config_build.h) AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h) AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc)
AC_MSG_RESULT([configuring for $PACKAGE_STRING]) AC_MSG_RESULT([configuring for $PACKAGE_STRING])
@@ -107,30 +109,51 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options [# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
ACO_SAVE_CXXFLAGS="$CXXFLAGS" ACO_SAVE_CXXFLAGS="$CXXFLAGS"
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems # -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
CXXFLAGS="$CXXFLAGS $1 -Werror" CXXFLAGS="$CXXFLAGS $2 -Werror"
AC_MSG_CHECKING([whether $CXX accepts $1]) AC_MSG_CHECKING([whether $CXX accepts $2])
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],[])], [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]) [_my_result=no])
AC_MSG_RESULT($_my_result) AC_MSG_RESULT($_my_result)
if test "$_my_result" = "yes" ; then if test "$_my_result" = "yes" ; then
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1" $1="$$1 $2"
fi fi
CXXFLAGS="$ACO_SAVE_CXXFLAGS" CXXFLAGS="$ACO_SAVE_CXXFLAGS"
])# _MY_CXX_CHECK_OPT ])# _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 # 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 # 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. # 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. # 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-div-by-zero)
_MY_CXX_CHECK_OPT(-Wno-sign-compare) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-sign-compare)
_MY_CXX_CHECK_OPT(-Wno-uninitialized) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
_MY_CXX_CHECK_OPT(-Wno-unused-parameter) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-but-set-variable)
_MY_CXX_CHECK_OPT(-Wno-unused-variable) _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(-Wno-unused-but-set-variable) _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) AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Checks for library functions. # Checks for library functions.
@@ -140,6 +163,8 @@ AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Other install directories # Other install directories
pkgdatadir=${datadir}/verilator pkgdatadir=${datadir}/verilator
AC_SUBST(pkgdatadir) AC_SUBST(pkgdatadir)
pkgconfigdir=${datadir}/pkgconfig
AC_SUBST(pkgconfigdir)
AC_OUTPUT AC_OUTPUT
-2
View File
@@ -635,9 +635,7 @@ INPUT = doxygen-mainpage \
test_c \ test_c \
test_regress \ test_regress \
test_sc \ test_sc \
test_sp \
test_v \ test_v \
test_vcs \
test_verilated test_verilated
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
+109 -38
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -74,6 +74,9 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
Verilated::gotFinish(true); Verilated::gotFinish(true);
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg); VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
Verilated::flushCall(); Verilated::flushCall();
VL_PRINTF("Aborting...\n");
Verilated::flushCall(); // Second flush in case VL_PRINTF does something needing a flush
abort(); abort();
} }
#endif #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 vluint32_t vn[VL_MULS_MAX_WORDS+1]; // v normalized
// Zero for ease of debugging and to save having to zero for shifts // 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 // Algorithm requires divisor MSB to be set
// Copy and shift to normalize divisor so MSB of vn[vw-1] is 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; output += cstrp;
break; 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 'e':
case 'f': case 'f':
case 'g': { case 'g': {
@@ -466,7 +476,7 @@ static inline void _vl_vsss_advance(FILE* fp, int& floc) {
if (fp) fgetc(fp); if (fp) fgetc(fp);
else floc -= 8; 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 // Get a character without advancing
if (fp) { if (fp) {
int data = fgetc(fp); int data = fgetc(fp);
@@ -476,23 +486,26 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
} else { } else {
if (floc < 0) return EOF; if (floc < 0) return EOF;
floc = floc & ~7; // Align to closest character floc = floc & ~7; // Align to closest character
int data = (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff; if (fromp == NULL) {
return data; 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) { 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; if (c==EOF || !isspace(c)) return;
_vl_vsss_advance(fp, floc); _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) { char* tmpp, const char* acceptp) {
// Read into tmp, consisting of characters from acceptp list // Read into tmp, consisting of characters from acceptp list
char* cp = tmpp; char* cp = tmpp;
while (1) { 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 (c==EOF || isspace(c)) break;
if (acceptp!=NULL // String - allow anything if (acceptp!=NULL // String - allow anything
&& NULL==strchr(acceptp, c)) break; && 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 IData _vl_vsscanf(FILE* fp, // If a fscanf
int fbits, WDataInP fromp, // Else if a sscanf int fbits, WDataInP fromp, // Else if a sscanf
const string& fstr, // if a sscanf to string
const char* formatp, va_list ap) { const char* formatp, va_list ap) {
// Read a Verilog $sscanf/$fscanf style format into the output list // Read a Verilog $sscanf/$fscanf style format into the output list
// The format must be pre-processed (and lower cased) by Verilator // 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; bool inPct = false;
const char* pos = formatp; const char* pos = formatp;
for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) { 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]=='%') { if (!inPct && pos[0]=='%') {
inPct = true; inPct = true;
} else if (!inPct && isspace(pos[0])) { // Format spaces } else if (!inPct && isspace(pos[0])) { // Format spaces
while (isspace(pos[1])) pos++; while (isspace(pos[1])) pos++;
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
} else if (!inPct) { // Expected Format } else if (!inPct) { // Expected Format
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
int c = _vl_vsss_peek(fp,floc,fromp); int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c != pos[0]) goto done; if (c != pos[0]) goto done;
else _vl_vsss_advance(fp,floc); else _vl_vsss_advance(fp,floc);
} else { // Format character } else { // Format character
@@ -564,7 +578,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
char fmt = pos[0]; char fmt = pos[0];
switch (fmt) { switch (fmt) {
case '%': { case '%': {
int c = _vl_vsss_peek(fp,floc,fromp); int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c != '%') goto done; if (c != '%') goto done;
else _vl_vsss_advance(fp,floc); else _vl_vsss_advance(fp,floc);
break; 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; for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = 0;
switch (fmt) { switch (fmt) {
case 'c': { case 'c': {
int c = _vl_vsss_peek(fp,floc,fromp); int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c==EOF) goto done; if (c==EOF) goto done;
else _vl_vsss_advance(fp,floc); else _vl_vsss_advance(fp,floc);
owp[0] = c; owp[0] = c;
break; break;
} }
case 's': { case 's': {
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, NULL); _vl_vsss_read(fp,floc,fromp,fstr, tmp, NULL);
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
int pos = ((int)strlen(tmp))-1; int pos = ((int)strlen(tmp))-1;
int lsb = 0; int lsb = 0;
@@ -599,8 +613,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break; break;
} }
case 'd': { // Signed decimal case 'd': { // Signed decimal
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
vlsint64_t ld; vlsint64_t ld;
sscanf(tmp,"%30" VL_PRI64 "d",&ld); sscanf(tmp,"%30" VL_PRI64 "d",&ld);
@@ -610,8 +624,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
case 'f': case 'f':
case 'e': case 'e':
case 'g': { // Real number case 'g': { // Real number
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
union { double r; vlsint64_t ld; } u; union { double r; vlsint64_t ld; } u;
u.r = strtod(tmp, NULL); u.r = strtod(tmp, NULL);
@@ -620,8 +634,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
} }
case 't': // FALLTHRU // Time case 't': // FALLTHRU // Time
case 'u': { // Unsigned decimal case 'u': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xXzZ?_"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
QData ld; QData ld;
sscanf(tmp,"%30" VL_PRI64 "u",&ld); sscanf(tmp,"%30" VL_PRI64 "u",&ld);
@@ -629,22 +643,22 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break; break;
} }
case 'b': { case 'b': {
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, "01xXzZ?_"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "01xXzZ?_");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
_vl_vsss_based(owp,obits, 1, tmp, 0, (int)strlen(tmp)); _vl_vsss_based(owp,obits, 1, tmp, 0, (int)strlen(tmp));
break; break;
} }
case 'o': { case 'o': {
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xXzZ?_"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "01234567xXzZ?_");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
_vl_vsss_based(owp,obits, 3, tmp, 0, (int)strlen(tmp)); _vl_vsss_based(owp,obits, 3, tmp, 0, (int)strlen(tmp));
break; break;
} }
case 'x': { case 'x': {
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefABCDEFxXzZ?_"); _vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789abcdefABCDEFxXzZ?_");
if (!tmp[0]) goto done; if (!tmp[0]) goto done;
_vl_vsss_based(owp,obits, 4, tmp, 0, (int)strlen(tmp)); _vl_vsss_based(owp,obits, 4, tmp, 0, (int)strlen(tmp));
break; break;
@@ -694,8 +708,8 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
start = false; // Drop leading 0s start = false; // Drop leading 0s
} }
} }
*destp++ = '\0'; // Terminate *destp = '\0'; // Terminate
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
} }
void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) { void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
@@ -736,6 +750,11 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
return got; return got;
} }
IData VL_FOPEN_NI(const string& filename, IData mode) {
char modez[5];
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
return VL_FOPEN_S(filename.c_str(), modez);
}
IData VL_FOPEN_QI(QData filename, IData mode) { IData VL_FOPEN_QI(QData filename, IData mode) {
IData fnw[2]; VL_SET_WQ(fnw, filename); IData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode); return VL_FOPEN_WI(2, fnw, mode);
@@ -758,6 +777,50 @@ void VL_FCLOSE_I(IData fdi) {
VerilatedImp::fdDelete(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, ...) { void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed VL_STATIC_OR_THREAD string output; // static only for speed
output = ""; output = "";
@@ -770,6 +833,7 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
} }
void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) { void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
if (obits_ignored) {}
output = ""; output = "";
va_list ap; va_list ap;
va_start(ap,formatp); va_start(ap,formatp);
@@ -820,7 +884,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
va_list ap; va_list ap;
va_start(ap,formatp); 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); va_end(ap);
return got; return got;
} }
@@ -830,7 +894,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
va_list ap; va_list ap;
va_start(ap,formatp); 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); va_end(ap);
return got; return got;
} }
@@ -839,14 +903,21 @@ IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
va_list ap; va_list ap;
va_start(ap,formatp); 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); va_end(ap);
return got; return got;
} }
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) { IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
va_list ap; va_list ap;
va_start(ap,formatp); 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); va_end(ap);
return got; return got;
} }
@@ -1248,9 +1319,9 @@ void VerilatedScope::scopeDump() const {
m_callbacksp[i], VerilatedImp::exportName(i)); m_callbacksp[i], VerilatedImp::exportName(i));
} }
} }
if (varsp()) { if (VerilatedVarNameMap* varsp = this->varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp()->begin(); for (VerilatedVarNameMap::const_iterator it = varsp->begin();
it != varsp()->end(); ++it) { it != varsp->end(); ++it) {
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first); VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
} }
} }
+182 -19
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -357,6 +357,7 @@ extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
extern IData VL_FOPEN_QI(QData ofilename, IData mode); extern IData VL_FOPEN_QI(QData ofilename, IData mode);
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); } inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
extern void VL_FCLOSE_I(IData fdi); extern void VL_FCLOSE_I(IData fdi);
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
@@ -375,6 +376,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_IQX(int lbits, QData ld, const char* formatp, ...);
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, 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 void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...);
extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs); extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs);
@@ -590,13 +595,13 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
#define VL_ASSIGN_SWI(obits,svar,rd) { \ #define VL_ASSIGN_SWI(obits,svar,rd) { \
sc_bv<obits> _bvtemp; \ sc_bv<obits> _bvtemp; \
_bvtemp.set_word(0,rd); \ _bvtemp.set_word(0,(rd)); \
svar.write(_bvtemp); \ svar.write(_bvtemp); \
} }
#define VL_ASSIGN_SWQ(obits,svar,rd) { \ #define VL_ASSIGN_SWQ(obits,svar,rd) { \
sc_bv<obits> _bvtemp; \ sc_bv<obits> _bvtemp; \
_bvtemp.set_word(0,rd); \ _bvtemp.set_word(0,(IData)(rd)); \
_bvtemp.set_word(1,rd>>VL_WORDSIZE); \ _bvtemp.set_word(1,(IData)((rd)>>VL_WORDSIZE)); \
svar.write(_bvtemp); \ svar.write(_bvtemp); \
} }
#define VL_ASSIGN_SWW(obits,svar,rwp) { \ #define VL_ASSIGN_SWW(obits,svar,rwp) { \
@@ -1128,7 +1133,9 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
int words = VL_WORDS_I(lbits); int words = VL_WORDS_I(lbits);
IData lsign = VL_SIGN_I(lbits,lwp[words-1]); IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[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 IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
IData rwstore[VL_MULS_MAX_WORDS]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
@@ -1147,7 +1154,9 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
int words = VL_WORDS_I(lbits); int words = VL_WORDS_I(lbits);
IData lsign = VL_SIGN_I(lbits,lwp[words-1]); IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[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 IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
IData rwstore[VL_MULS_MAX_WORDS]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
@@ -1163,7 +1172,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) { 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; if (VL_UNLIKELY(lhs==0)) return 0;
IData power = lhs; IData power = lhs;
IData out = 1; IData out = 1;
@@ -1173,10 +1185,8 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
} }
return out; 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) { 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; if (VL_UNLIKELY(lhs==0)) return 0;
QData power = lhs; QData power = lhs;
QData out = VL_ULL(1); QData out = VL_ULL(1);
@@ -1187,6 +1197,36 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
return out; 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 // Concat/replication
@@ -1327,6 +1367,120 @@ static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP ow
return(owp); 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. // 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. // 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. // Note the bit shifts are always constants, so the adds in these constify out.
@@ -1413,7 +1567,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) { static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
int word_shift = VL_BITWORD_I(rd); int word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_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; 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) } else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
for (int i=0; i < word_shift; i++) owp[i] = 0; for (int i=0; i < word_shift; i++) owp[i] = 0;
@@ -1431,7 +1585,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) { 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 word_shift = VL_BITWORD_I(rd); // Maybe 0
int bit_shift = VL_BITBIT_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; 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) } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift); int copy_words = (VL_WORDS_I(obits)-word_shift);
@@ -1455,29 +1609,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; // 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! // Note the C standard does not specify the >> operator as a arithmetic shift!
IData sign = -(lhs >> (obits-1)); // ffff_ffff if negative // IEEE says signed if output signed, but bit position from lbits;
IData signext = ~(VL_MASK_I(obits) >> rhs); // One with bits where we've shifted "past" // 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)); return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
} }
static inline QData VL_SHIFTRS_QQI(int obits, int, int, QData lhs, IData rhs) { static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) {
QData sign = -(lhs >> (obits-1)); QData sign = -(lhs >> (lbits-1));
QData signext = ~(VL_MASK_Q(obits) >> rhs); QData signext = ~(VL_MASK_Q(lbits) >> rhs);
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext)); 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 word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_I(rd); int bit_shift = VL_BITBIT_I(rd);
int lmsw = VL_WORDS_I(obits)-1; int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(obits,lwp[lmsw]); IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
if ((int)rd >= obits) { if (rd >= (IData)obits) { // Shifting past end, sign in all of lbits
for (int i=0; i <= lmsw; i++) owp[i] = sign; 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) } else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift); int copy_words = (VL_WORDS_I(obits)-word_shift);
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+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; 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; for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} else { } else {
int loffset = rd & VL_SIZEBITS_I; int loffset = rd & VL_SIZEBITS_I;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0) int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
@@ -1492,6 +1654,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); if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign; for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} }
return(owp); return(owp);
} }
@@ -1507,7 +1670,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) { static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) {
int word = VL_BITWORD_I(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. 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. // We return all 1's as that's more likely to find bugs (?) than 0's.
} else { } else {
+9 -10
View File
@@ -2,7 +2,7 @@
###################################################################### ######################################################################
# DESCRIPTION: Makefile commands for all verilated target files # 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 # redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0. # General Public License Version 3 or the Perl Artistic License Version 2.0.
###################################################################### ######################################################################
@@ -23,7 +23,9 @@ CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
# Programs # Programs
SP_PREPROC = sp_preproc 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 # Make checks
@@ -43,14 +45,14 @@ VK_CPPFLAGS_ALWAYS += \
-DVL_PRINTF=printf \ -DVL_PRINTF=printf \
-DVM_TRACE=$(VM_TRACE) \ -DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \ -DVM_COVERAGE=$(VM_COVERAGE) \
$(CFG_CXXFLAGS_NO_UNUSED) \
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
VK_CPPFLAGS_WALL += -Wall \ VK_CPPFLAGS_WALL += -Wall \
$(CFG_CXXFLAGS_NO_UNUSED) \
-Werror -Werror
endif endif
CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL) CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
VPATH += .. VPATH += ..
VPATH += $(VERILATOR_ROOT)/include VPATH += $(VERILATOR_ROOT)/include
@@ -118,10 +120,6 @@ ifeq ($(VM_SP),1)
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \ $(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
--preproc $(VK_CLASSES_SP) --preproc $(VK_CLASSES_SP)
else else
ifeq ($(VM_COVERAGE),1)
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
VPATH += $(SYSTEMPERL_INCLUDE)
endif
preproc: preproc:
endif endif
@@ -157,9 +155,9 @@ ifneq ($(VM_PARALLEL_BUILDS),1)
VK_OBJS += $(VM_PREFIX)__ALLcls.o $(VM_PREFIX)__ALLsup.o VK_OBJS += $(VM_PREFIX)__ALLcls.o $(VM_PREFIX)__ALLsup.o
all_cpp: $(VM_PREFIX)__ALLcls.cpp $(VM_PREFIX)__ALLsup.cpp all_cpp: $(VM_PREFIX)__ALLcls.cpp $(VM_PREFIX)__ALLsup.cpp
$(VM_PREFIX)__ALLcls.cpp: $(VK_CLASSES_CPP) $(VM_PREFIX)__ALLcls.cpp: $(VK_CLASSES_CPP)
$(SP_INCLUDER) $^ > $@ $(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
$(VM_PREFIX)__ALLsup.cpp: $(VK_SUPPORT_CPP) $(VM_PREFIX)__ALLsup.cpp: $(VK_SUPPORT_CPP)
$(SP_INCLUDER) $^ > $@ $(VERILATOR_INCLUDER) -DVL_INCLUDE_OPT=include $^ > $@
else else
#Slow way of building... Each .cpp file by itself #Slow way of building... Each .cpp file by itself
VK_OBJS += $(addsuffix .o, $(VM_CLASSES) $(VM_SUPPORT)) VK_OBJS += $(addsuffix .o, $(VM_CLASSES) $(VM_SUPPORT))
@@ -195,6 +193,7 @@ debug-make::
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW) @echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST) @echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW) @echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
@echo CPPFLAGS: $(CPPFLAGS)
@echo @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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+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" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -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) { void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w) {
_VL_SVDPI_UNIMP(); _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(); _VL_SVDPI_UNIMP();
} }
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+15 -2
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -41,14 +41,27 @@ inline string VL_CVT_PACK_STR_NQ(QData lhs) {
IData lw[2]; VL_SET_WQ(lw, lhs); IData lw[2]; VL_SET_WQ(lw, lhs);
return VL_CVT_PACK_STR_NW(2, lw); return VL_CVT_PACK_STR_NW(2, lw);
} }
inline string VL_CVT_PACK_STR_NQ(string lhs) { inline string VL_CVT_PACK_STR_NN(const string& lhs) {
return lhs; return lhs;
} }
inline string VL_CVT_PACK_STR_NI(IData lhs) { inline string VL_CVT_PACK_STR_NI(IData lhs) {
IData lw[1]; lw[0] = lhs; IData lw[1]; lw[0] = lhs;
return VL_CVT_PACK_STR_NW(1, lw); 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_FOPEN_NI(const string& filename, IData mode);
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...); extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
extern string VL_SFORMATF_NX(const char* formatp, ...); extern string VL_SFORMATF_NX(const char* formatp, ...);
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+7 -6
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // 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 // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -17,8 +17,6 @@
/// \file /// \file
/// \brief C++ Tracing in VCD Format /// \brief C++ Tracing in VCD Format
/// ///
/// AUTHOR: Wilson Snyder
///
//============================================================================= //=============================================================================
#include "verilatedos.h" #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) { VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
if (VL_UNLIKELY(readDiffers(datap,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"; 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(); close();
} }
return *this; // For function chaining return *this; // For function chaining
@@ -82,8 +81,9 @@ void VerilatedSerialize::header() {
void VerilatedDeserialize::header() { void VerilatedDeserialize::header() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) { 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"; 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(); close();
} }
os.read(Verilated::serializedPtr(), Verilated::serializedSize()); os.read(Verilated::serializedPtr(), Verilated::serializedSize());
@@ -98,8 +98,9 @@ void VerilatedSerialize::trailer() {
void VerilatedDeserialize::trailer() { void VerilatedDeserialize::trailer() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) { 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"; 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(); close();
} }
} }
+1 -3
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // 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 // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -17,8 +17,6 @@
/// \file /// \file
/// \brief Save-restore serialization of verilated modules /// \brief Save-restore serialization of verilated modules
/// ///
/// AUTHOR: Wilson Snyder
///
//============================================================================= //=============================================================================
#ifndef _VERILATED_SAVE_C_H_ #ifndef _VERILATED_SAVE_C_H_
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- mode: C++; c-file-style: "cc-mode" -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+74 -23
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // 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 // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -17,8 +17,6 @@
/// \file /// \file
/// \brief C++ Tracing in VCD Format /// \brief C++ Tracing in VCD Format
/// ///
/// AUTHOR: Wilson Snyder
///
//============================================================================= //=============================================================================
// SPDIFF_OFF // SPDIFF_OFF
@@ -57,7 +55,7 @@ vector<VerilatedVcd*> VerilatedVcd::s_vcdVecp; ///< List of all created traces
// VerilatedVcdCallInfo // VerilatedVcdCallInfo
/// Internal callback routines for each module being traced. /// 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 /// callbacks stored in this class. When the trace file is being
/// constructed, this class provides the callback routines to be executed. /// 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) {}; : 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 // 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) { void VerilatedVcd::open (const char* filename) {
if (isOpen()) return; if (isOpen()) return;
@@ -142,9 +177,7 @@ void VerilatedVcd::openNext (bool incFilename) {
assert(0); // Not supported yet. assert(0); // Not supported yet.
} else { } else {
// cppcheck-suppress duplicateExpression // cppcheck-suppress duplicateExpression
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK if (!m_filep->open(m_filename)) {
, 0666);
if (m_fd<0) {
// User code can check isOpen() // User code can check isOpen()
m_isOpen = false; m_isOpen = false;
return; return;
@@ -172,8 +205,8 @@ void VerilatedVcd::makeNameMap() {
// This comes from user instantiations with no name - IE Vtop(""). // This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false; bool nullScope = false;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) { for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str(); const string& hiername = it->first;
if (hiername[0] == '\t') nullScope=true; if (hiername.size() >= 1 && hiername[0] == '\t') nullScope=true;
} }
if (nullScope) { if (nullScope) {
NameMap* newmapp = new NameMap; NameMap* newmapp = new NameMap;
@@ -199,6 +232,7 @@ VerilatedVcd::~VerilatedVcd() {
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; } if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; } if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
deleteNameMap(); deleteNameMap();
if (m_filep && m_fileNewed) { delete m_filep; m_filep = NULL; }
// Remove from list of traces // Remove from list of traces
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this); vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); } if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
@@ -209,7 +243,7 @@ void VerilatedVcd::closePrev () {
bufferFlush(); bufferFlush();
m_isOpen = false; m_isOpen = false;
::close(m_fd); m_filep->close();
} }
void VerilatedVcd::closeErr () { void VerilatedVcd::closeErr () {
@@ -219,7 +253,7 @@ void VerilatedVcd::closeErr () {
// No buffer flush, just fclose // No buffer flush, just fclose
m_isOpen = false; m_isOpen = false;
::close(m_fd); // May get error, just ignore it m_filep->close(); // May get error, just ignore it
} }
void VerilatedVcd::close() { void VerilatedVcd::close() {
@@ -261,6 +295,20 @@ void VerilatedVcd::printTime (vluint64_t timeui) {
printQuad(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 () { void VerilatedVcd::bufferFlush () {
// We add output data to m_writep. // We add output data to m_writep.
// When it gets nearly full we dump it using this routine which calls write() // 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); ssize_t remaining = (m_writep - wp);
if (remaining==0) break; if (remaining==0) break;
errno = 0; errno = 0;
ssize_t got = write (m_fd, wp, remaining); ssize_t got = m_filep->write(wp, remaining);
if (got>0) { if (got>0) {
wp += got; wp += got;
m_wroteBytes += got; m_wroteBytes += got;
@@ -294,13 +342,11 @@ void VerilatedVcd::bufferFlush () {
// Simple methods // Simple methods
void VerilatedVcd::set_time_unit (const char* unitp) { void VerilatedVcd::set_time_unit (const char* unitp) {
string unitstr (unitp);
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl; //cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeUnit = timescaleToDouble(unitp); m_timeUnit = timescaleToDouble(unitp);
} }
void VerilatedVcd::set_time_resolution (const char* unitp) { void VerilatedVcd::set_time_resolution (const char* unitp) {
string unitstr (unitp);
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl; //cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeRes = timescaleToDouble(unitp); m_timeRes = timescaleToDouble(unitp);
} }
@@ -332,7 +378,7 @@ string VerilatedVcd::doubleToTimescale (double value) {
else if (value>=1e-12) { suffixp="ps"; value *= 1e12; } else if (value>=1e-12) { suffixp="ps"; value *= 1e12; }
else if (value>=1e-15) { suffixp="fs"; value *= 1e15; } else if (value>=1e-15) { suffixp="fs"; value *= 1e15; }
else if (value>=1e-18) { suffixp="as"; value *= 1e18; } else if (value>=1e-18) { suffixp="as"; value *= 1e18; }
char valuestr[100]; sprintf(valuestr,"%d%s",(int)(value), suffixp); char valuestr[100]; sprintf(valuestr,"%3.0f%s", value, suffixp);
return valuestr; // Gets converted to string, so no ref to stack return valuestr; // Gets converted to string, so no ref to stack
} }
@@ -352,7 +398,8 @@ void VerilatedVcd::dumpHeader () {
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n"); printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
printStr("$timescale "); printStr("$timescale ");
printStr(doubleToTimescale(m_timeRes).c_str()); const string& timeResStr = doubleToTimescale(m_timeRes);
printStr(timeResStr.c_str());
printStr(" $end\n"); printStr(" $end\n");
makeNameMap(); makeNameMap();
@@ -370,10 +417,11 @@ void VerilatedVcd::dumpHeader () {
// Print the signal names // Print the signal names
const char* lastName = ""; const char* lastName = "";
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) { for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str(); const string& hiernamestr = it->first;
const char* decl = (*it).second.c_str(); const string& decl = it->second;
// Determine difference between the old and new names // Determine difference between the old and new names
const char* hiername = hiernamestr.c_str();
const char* lp = lastName; const char* lp = lastName;
const char* np = hiername; const char* np = hiername;
lastName = hiername; lastName = hiername;
@@ -408,7 +456,7 @@ void VerilatedVcd::dumpHeader () {
} }
printIndent(0); printIndent(0);
printStr(decl); printStr(decl.c_str());
} }
while (m_modDepth>1) { while (m_modDepth>1) {
@@ -424,7 +472,7 @@ void VerilatedVcd::dumpHeader () {
deleteNameMap(); deleteNameMap();
} }
void VerilatedVcd::module (string name) { void VerilatedVcd::module (const string& name) {
m_modName = 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 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 // Save declaration info
VerilatedVcdSig sig = VerilatedVcdSig(code, bits); VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
m_sigs.push_back(sig); 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) { void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
(*((double*)&m_sigs_oldvalp[code])) = 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); sprintf(m_writep, "r%.16g", newval);
m_writep += strlen(m_writep); m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n'; *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) { void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
(*((float*)&m_sigs_oldvalp[code])) = 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); sprintf(m_writep, "r%.16g", (double)newval);
m_writep += strlen(m_writep); m_writep += strlen(m_writep);
*m_writep++=' '; printCode(code); *m_writep++='\n'; *m_writep++=' '; printCode(code); *m_writep++='\n';
@@ -701,5 +752,5 @@ main() {
//******************************************************************** //********************************************************************
// Local Variables: // 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: // End:
+28 -24
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // 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 // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -17,8 +17,6 @@
/// \file /// \file
/// \brief C++ Tracing in VCD Format /// \brief C++ Tracing in VCD Format
/// ///
/// AUTHOR: Wilson Snyder
///
//============================================================================= //=============================================================================
// SPDIFF_OFF // SPDIFF_OFF
@@ -36,6 +34,22 @@ class VerilatedVcd;
class VerilatedVcdCallInfo; class VerilatedVcdCallInfo;
// SPDIFF_ON // 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 // VerilatedVcdSig
/// Internal data on one signal being traced. /// Internal data on one signal being traced.
@@ -62,9 +76,10 @@ typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluin
class VerilatedVcd { class VerilatedVcd {
private: 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_isOpen; ///< True indicates open file
bool m_evcd; ///< True for evcd format 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) string m_filename; ///< Filename we're writing to (if open)
vluint64_t m_rolloverMB; ///< MB of file size to rollover at vluint64_t m_rolloverMB; ///< MB of file size to rollover at
char m_scopeEscape; ///< Character to separate scope components char m_scopeEscape; ///< Character to separate scope components
@@ -77,7 +92,9 @@ private:
vluint64_t m_timeLastDump; ///< Last time we did a dump vluint64_t m_timeLastDump; ///< Last time we did a dump
char* m_wrBufp; ///< Output buffer char* m_wrBufp; ///< Output buffer
char* m_wrFlushp; ///< Output buffer flush trigger location
char* m_writep; ///< Write pointer into output buffer 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 vluint64_t m_wroteBytes; ///< Number of bytes written to this file
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
@@ -87,13 +104,12 @@ private:
NameMap* m_namemapp; ///< List of names for the header NameMap* m_namemapp; ///< List of names for the header
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation void bufferResize(vluint64_t minsize);
inline static size_t bufferInsertSize() { return 16*1024; }
void bufferFlush(); void bufferFlush();
void bufferCheck() { inline void bufferCheck() {
// Flush the write buffer if there's not enough space left for new information // 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 // 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(); bufferFlush();
} }
} }
@@ -134,19 +150,7 @@ protected:
public: public:
// CREATORS // CREATORS
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) { VerilatedVcd(VerilatedVcdFile* filep=NULL);
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(); ~VerilatedVcd();
// ACCESSORS // ACCESSORS
@@ -188,7 +192,7 @@ public:
void* userthis); void* userthis);
/// Inside dumping routines, declare a module /// Inside dumping routines, declare a module
void module (const string name); void module (const string& name);
/// Inside dumping routines, declare a signal /// Inside dumping routines, declare a signal
void declBit (vluint32_t code, const char* name, int arraynum); void declBit (vluint32_t code, const char* name, int arraynum);
void declBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb); 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. /// Create a VCD dump file in C standalone (no SystemC) simulations.
class VerilatedVcdC { class VerilatedVcdC {
VerilatedVcd m_sptrace; ///< SystemPerl trace file being created VerilatedVcd m_sptrace; ///< Trace file being created
public: public:
// CONSTRUCTORS // CONSTRUCTORS
VerilatedVcdC() {} VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
~VerilatedVcdC() {} ~VerilatedVcdC() {}
// ACCESSORS // ACCESSORS
/// Is file open? /// Is file open?
+2 -4
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // 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 // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -15,9 +15,7 @@
//============================================================================= //=============================================================================
/// ///
/// \file /// \file
/// \brief SystemPerl Tracing in VCD Format /// \brief Verilator tracing in VCD Format
///
/// AUTHOR: Wilson Snyder
/// ///
//============================================================================= //=============================================================================
// SPDIFF_OFF // SPDIFF_OFF
+2 -4
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // 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 // you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
// //
@@ -15,9 +15,7 @@
//============================================================================= //=============================================================================
/// ///
/// \file /// \file
/// \brief SystemPerl tracing in VCD format /// \brief Verilator tracing in VCD format
///
/// AUTHOR: Wilson Snyder
/// ///
//============================================================================= //=============================================================================
// SPDIFF_OFF // SPDIFF_OFF
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
+79 -49
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -38,7 +38,7 @@
// Internal macros // Internal macros
#define _VL_VPI_INTERNAL VerilatedVpi::error_info()->setMessage(vpiInternal)->setMessage #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_ERROR VerilatedVpi::error_info()->setMessage(vpiError )->setMessage
#define _VL_VPI_WARNING VerilatedVpi::error_info()->setMessage(vpiWarning )->setMessage #define _VL_VPI_WARNING VerilatedVpi::error_info()->setMessage(vpiWarning )->setMessage
#define _VL_VPI_NOTICE VerilatedVpi::error_info()->setMessage(vpiNotice )->setMessage #define _VL_VPI_NOTICE VerilatedVpi::error_info()->setMessage(vpiNotice )->setMessage
@@ -52,6 +52,8 @@
// Implementation // Implementation
#include <set> #include <set>
#include <list>
#include <map>
#define VL_DEBUG_IF_PLI VL_DEBUG_IF #define VL_DEBUG_IF_PLI VL_DEBUG_IF
#define VL_VPI_LINE_SIZE 8192 #define VL_VPI_LINE_SIZE 8192
@@ -95,8 +97,8 @@ public:
virtual const char* fullname() { return "<null>"; } virtual const char* fullname() { return "<null>"; }
virtual const char* defname() { return "<null>"; } virtual const char* defname() { return "<null>"; }
virtual const vluint32_t type() { return 0; } virtual const vluint32_t type() { return 0; }
virtual const vluint32_t size() { return 0; } virtual const vluint32_t size() const { return 0; }
virtual const VerilatedRange* rangep() { return 0; } virtual const VerilatedRange* rangep() const { return NULL; }
virtual vpiHandle dovpi_scan() { return 0; } virtual vpiHandle dovpi_scan() { return 0; }
}; };
@@ -134,7 +136,7 @@ public:
class VerilatedVpioRange : public VerilatedVpio { class VerilatedVpioRange : public VerilatedVpio {
const VerilatedRange* m_range; const VerilatedRange* m_range;
bool m_iteration; vlsint32_t m_iteration;
public: public:
VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {} VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
virtual ~VerilatedVpioRange() {} virtual ~VerilatedVpioRange() {}
@@ -180,6 +182,10 @@ class VerilatedVpioVar : public VerilatedVpio {
protected: protected:
void* m_varDatap; // varp()->datap() adjusted for array entries void* m_varDatap; // varp()->datap() adjusted for array entries
vlsint32_t m_index; 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: public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep) VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp(varp), m_scopep(scopep), m_index(0) { : m_varp(varp), m_scopep(scopep), m_index(0) {
@@ -198,10 +204,12 @@ public:
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; } vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
vluint32_t entSize() const { return m_entSize; } vluint32_t entSize() const { return m_entSize; }
const vluint32_t index() { return m_index; } const vluint32_t index() { return m_index; }
virtual const vluint32_t type() { return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */ } virtual const vluint32_t type() {
virtual const vluint32_t size() { return range().elements(); } if (varp()->vldir() != vpiNoDirection) return vpiPort;
const VerilatedRange& range() { return m_varp->dims()?m_varp->array():m_varp->range(); } return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
virtual const VerilatedRange* rangep() { return &range(); } }
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* name() { return m_varp->name(); }
virtual const char* fullname() { virtual const char* fullname() {
VL_STATIC_OR_THREAD string out; VL_STATIC_OR_THREAD string out;
@@ -229,8 +237,8 @@ public:
virtual ~VerilatedVpioMemoryWord() {} virtual ~VerilatedVpioMemoryWord() {}
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); } static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiMemoryWord; } virtual const vluint32_t type() { return vpiMemoryWord; }
virtual const vluint32_t size() { return varp()->range().elements(); } virtual const vluint32_t size() const { return varp()->range().elements(); }
virtual const VerilatedRange* rangep() { return &(varp()->range()); } virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
virtual const char* fullname() { virtual const char* fullname() {
VL_STATIC_OR_THREAD string out; VL_STATIC_OR_THREAD string out;
char num[20]; sprintf(num,"%d",m_index); char num[20]; sprintf(num,"%d",m_index);
@@ -251,10 +259,11 @@ public:
virtual const vluint32_t type() { return vpiIterator; } virtual const vluint32_t type() { return vpiIterator; }
virtual vpiHandle dovpi_scan() { virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) { if (VL_LIKELY(m_scopep->varsp())) {
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; } VerilatedVarNameMap* varsp = m_scopep->varsp();
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0; 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; 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)) return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
->castVpiHandle()); ->castVpiHandle());
} else { } else {
@@ -275,7 +284,7 @@ public:
virtual ~VerilatedVpioMemoryWordIter() {} virtual ~VerilatedVpioMemoryWordIter() {}
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); } static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiIterator; } virtual const vluint32_t type() { return vpiIterator; }
void iterationInc() { if (!(m_done = m_iteration == m_varp->array().left())) m_iteration+=m_direction; } void iterationInc() { if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction; }
virtual vpiHandle dovpi_scan() { virtual vpiHandle dovpi_scan() {
vpiHandle result; vpiHandle result;
if (m_done) return 0; if (m_done) return 0;
@@ -301,7 +310,7 @@ class VerilatedVpiError;
class VerilatedVpi { class VerilatedVpi {
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason 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; typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
struct product_info { struct product_info {
@@ -309,7 +318,7 @@ class VerilatedVpi {
PLI_BYTE8* version; PLI_BYTE8* version;
}; };
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
VpioTimedCbs m_timedCbs; // Time based callbacks VpioTimedCbs m_timedCbs; // Time based callbacks
VerilatedVpiError* m_errorInfop; // Container for vpi error info VerilatedVpiError* m_errorInfop; // Container for vpi error info
@@ -325,16 +334,17 @@ public:
} }
} }
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large"); 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) { static void cbTimedAdd(VerilatedVpioCb* vop) {
s_s.m_timedCbs.insert(make_pair(vop->time(), vop)); s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
} }
static void cbReasonRemove(VerilatedVpioCb* cbp) { static void cbReasonRemove(VerilatedVpioCb* cbp) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()]; VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
VpioCbSet::iterator it=cbObjSet.find(cbp); // We do not remove it now as we may be iterating the list,
if (VL_LIKELY(it != cbObjSet.end())) { // instead set to NULL and will cleanup later
cbObjSet.erase(it); for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end(); ++it) {
if (*it == cbp) *it = NULL;
} }
} }
static void cbTimedRemove(VerilatedVpioCb* cbp) { static void cbTimedRemove(VerilatedVpioCb* cbp) {
@@ -364,19 +374,26 @@ public:
} }
} }
static void callCbs(vluint32_t reason) { static void callCbs(vluint32_t reason) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason]; VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) { for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
VerilatedVpioCb* vop = *it; if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
++it; // iterator may be deleted by callback it = cbObjList.erase(it);
continue;
}
VerilatedVpioCb* vop = *it++;
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop);); VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
(vop->cb_rtnp()) (vop->cb_datap()); (vop->cb_rtnp()) (vop->cb_datap());
} }
} }
static void callValueCbs() { static void callValueCbs() {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange]; VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) { set<VerilatedVpioVar*> update; // set of objects to update after callbacks
VerilatedVpioCb* vop = *it; for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
++it; // iterator may be deleted by callback if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
it = cbObjList.erase(it);
continue;
}
VerilatedVpioCb* vop = *it++;
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) { if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
void* newDatap = varop->varDatap(); void* newDatap = varop->varDatap();
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
@@ -386,12 +403,15 @@ public:
if (memcmp(prevDatap, newDatap, varop->entSize())) { if (memcmp(prevDatap, newDatap, varop->entSize())) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n", VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap));); vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize()); update.insert(varop);
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value); vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp()) (vop->cb_datap()); (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 static VerilatedVpiError* error_info(); // getter for vpi error info
@@ -401,7 +421,7 @@ public:
do { \ do { \
va_list args; \ va_list args; \
va_start(args, message); \ va_start(args, message); \
vsnprintf(m_buff, sizeof(m_buff), message.c_str(), args); \ VL_VSNPRINTF(m_buff, sizeof(m_buff), message.c_str(), args); \
va_end(args); \ va_end(args); \
} while (0) } while (0)
@@ -411,15 +431,10 @@ class VerilatedVpiError {
t_vpi_error_info m_errorInfo; t_vpi_error_info m_errorInfo;
bool m_flag; bool m_flag;
char m_buff[VL_VPI_LINE_SIZE]; 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.message = message;
m_errorInfo.file = file; m_errorInfo.file = file;
m_errorInfo.line = line; 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; m_errorInfo.code = code;
do_callbacks(); do_callbacks();
} }
@@ -435,6 +450,7 @@ class VerilatedVpiError {
public: public:
VerilatedVpiError() : m_flag(false) { VerilatedVpiError() : m_flag(false) {
m_buff[0] = '\0';
m_errorInfo.product = (PLI_BYTE8*)Verilated::productName(); m_errorInfo.product = (PLI_BYTE8*)Verilated::productName();
} }
~VerilatedVpiError() {} ~VerilatedVpiError() {}
@@ -444,14 +460,11 @@ public:
return this; return this;
} }
void setMessage(string file, PLI_INT32 line, string message, ...) { void setMessage(string file, PLI_INT32 line, string message, ...) {
static VL_THREAD string filehold;
_VL_VPI_ERROR_SET; _VL_VPI_ERROR_SET;
m_errorInfo.state = vpiPLI; m_errorInfo.state = vpiPLI;
setError((PLI_BYTE8*)m_buff, (PLI_BYTE8*)file.c_str(), line); filehold = file;
} setError((PLI_BYTE8*)m_buff, NULL, (PLI_BYTE8*)filehold.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);
} }
p_vpi_error_info getError() { p_vpi_error_info getError() {
if (m_flag) return &m_errorInfo; if (m_flag) return &m_errorInfo;
@@ -774,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) { 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 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; static VL_THREAD int outStrSz = sizeof(outStr)-1;
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object);); VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
_VL_VPI_ERROR_RESET(); // reset vpi error status _VL_VPI_ERROR_RESET(); // reset vpi error status
@@ -906,10 +920,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
value_p->value.str = outStr; value_p->value.str = outStr;
switch (vop->varp()->vltype()) { switch (vop->varp()->vltype()) {
// outStrSz does not include NULL termination so add one // 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_UINT8 : VL_SNPRINTF(outStr, outStrSz+1, "%hhu", (unsigned char )*((CData*)(vop->varDatap()))); return;
case VLVT_UINT16: snprintf(outStr, outStrSz+1, "%hu", (unsigned int)*((SData*)(vop->varDatap()))); return; case VLVT_UINT16: VL_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_UINT32: VL_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; case VLVT_UINT64: VL_SNPRINTF(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return;
default: default:
strcpy(outStr, "-1"); strcpy(outStr, "-1");
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits",
@@ -1006,6 +1020,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return; return;
} }
} else if (value_p->format == vpiSuppressVal) {
return;
} }
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
@@ -1297,7 +1313,21 @@ void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
// time processing // time processing
void vpi_get_time(vpiHandle object, p_vpi_time time_p) { 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 // I/O routines
+41 -2
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*- // -*- 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -95,6 +95,23 @@
// This is not necessarily the same as #UL, depending on what the IData typedef is. // 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 #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 // Warning disabled
@@ -122,7 +139,7 @@ typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward comp
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility) typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef unsigned char vluint8_t; ///< 8-bit unsigned type typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
# ifdef __uint32_t_defined // Newer Cygwin uint32_t in stdint.h as an unsigned int # if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
typedef int32_t vlsint32_t; ///< 32-bit signed type typedef int32_t vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type typedef uint32_t vluint32_t; ///< 32-bit unsigned type
# else // Older Cygwin has long==uint32_t # else // Older Cygwin has long==uint32_t
@@ -161,6 +178,7 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
#else // Linux or compliant Unix flavors, -m64 #else // Linux or compliant Unix flavors, -m64
# include <stdint.h> // Linux and most flavors # include <stdint.h> // Linux and most flavors
# include <unistd.h> // Linux ssize_t
# include <inttypes.h> // Solaris # include <inttypes.h> // Solaris
typedef uint8_t vluint8_t; ///< 32-bit unsigned type typedef uint8_t vluint8_t; ///< 32-bit unsigned type
typedef uint16_t vluint16_t; ///< 32-bit unsigned type typedef uint16_t vluint16_t; ///< 32-bit unsigned type
@@ -189,6 +207,27 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif # endif
#endif #endif
#if defined(_WIN32) && defined(_MSC_VER)
# if (_MSC_VER < 1900)
# define VL_SNPRINTF _snprintf
# else
# define VL_SNPRINTF snprintf
# endif
# define VL_VSNPRINTF vsnprintf
#else
# define VL_SNPRINTF snprintf
# define VL_VSNPRINTF vsnprintf
#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 // Integer size macros
+3 -3
View File
@@ -29,7 +29,7 @@ typedef signed __int8 int8_t;
#include <stdint.h> #include <stdint.h>
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include <stdint.h> #include <stdint.h>
#elif defined(__linux) #elif defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
#include <inttypes.h> #include <inttypes.h>
#else #else
#include <sys/types.h> #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 svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
XXTERN void svPutPartselBit(svBitVecVal* d, const svBitVecVal 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 * Open array querying functions
@@ -427,7 +427,7 @@ XXTERN void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s,
/* actual <-- canonical */ /* actual <-- canonical */
XXTERN void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s, XXTERN void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32 s,
int i, int w); int i, int w);
XXTERN void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32 s, XXTERN void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32* s,
int i, int w); int i, int w);
/* /*
+1 -1
View File
@@ -37,7 +37,7 @@ typedef signed __int32 int32_t;
typedef signed __int8 int8_t; typedef signed __int8 int8_t;
#elif defined(__MINGW32__) #elif defined(__MINGW32__)
#include <stdint.h> #include <stdint.h>
#elif defined(__linux) #elif defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
#include <inttypes.h> #include <inttypes.h>
#else #else
#include <sys/types.h> #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, hierarchical design. This includes coverage, assertions, X elimination,
inlining, constant propagation, and dead code 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 and functions get "Scope" references. A scope reference is an occurrence of
that un-flattened variable in the flattened hierarchy. A module that occurs 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 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 to proceed across the flattened design, while still preserving the
hierarchy. 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 include module references, function inlining, loop unrolling, variable
lifetime analysis, lookup table creation, always splitting, and logic gate lifetime analysis, lookup table creation, always splitting, and logic gate
simplifications (pushing inverters, etc). simplifications (pushing inverters, etc).
@@ -80,8 +80,8 @@ classes).
Each C<AstNode> has pointers to up to four children, accessed by the 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 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 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 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<op2p> to 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 give the pointer to the AST for the "else" block, or NULL if there is not
one. 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 By convention, each function/method uses the variable C<nodep> as a pointer
to the C<AstNode> currently being processed. to the C<AstNode> currently being processed.
=item C<AstNVistor> =item C<AstNVisitor>
The passes are implemented by AST visitor classes (see L</Visitor The passes are implemented by AST visitor classes (see L</Visitor
Functions>). These are implemented by subclasses of the abstract class, 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. 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 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. C<V3GraphVertex> which will reimplement these methods.
Iterators are provided to access in and out edges. Typically these are used in 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 the AST on which it operates. Wikipedia provides an introduction to the
concept at L<http://en.wikipedia.org/wiki/Visitor_pattern>. 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 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 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 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) 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 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<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). technique lifted from graph traversal packages).
A visitor first clears the one it wants to use by calling 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" 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 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 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, was nearly the first module written. Someday this scheme may be removed,
as it slows the program down to have to pass vup everywhere.) 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 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 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 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 Functions>, but its use is now deprecated and should I<not> be used for new
classes. visitor classes.
=over 4 =over 4
@@ -341,6 +341,37 @@ C<op4p> in turn.
=back =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 =head2 Identifying derived classes
A common requirement is to identify the specific C<AstNode> class we are 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 It is important to add tests for failures as well as success (for example to
check that an error message is correctly triggered). 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 and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
appropriate. 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 =head2 Controlling the Test Driver
Test drivers are written in PERL. All invoke the main test driver script, 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 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> 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 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 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> 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 =item --enable-longtests
In addition to the standard C, SystemC and SystemPerl tests also run the In addition to the standard C, SystemC tests also run the tests in the
tests in the C<test_vcs>, C<test_verilated> and C<test_regress> directories C<test_verilated> and C<test_regress> directories when using I<make test>.
when using I<make test>. This is disabled by default as SystemC/SystemPerl This is disabled by default as SystemC installation problems would
installation problems would otherwise falsely indicate a Verilator problem. otherwise falsely indicate a Verilator problem.
=back =back
@@ -460,12 +503,6 @@ There are some traps to avoid when running regression tests
=item * =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 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. 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 Many nodes have an explicit data type. "@dt=0x..." indicates the address
of the data type (AstNodeDType) this node uses. of the data type (AstNodeDType) this node uses.
If a data type is present and is numberic, it then prints the width of the If a data type is present and is numeric, it then prints the width of the
item. This field is a squence of flag characters and width data as follows: item. This field is a sequence of flag characters and width data as follows:
C<s> if the node is signed. 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/>. 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 redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2007-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 # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2007-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 # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+1 -1
View File
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-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 redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-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 redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2007-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 # can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+1 -1
View File
@@ -183,7 +183,7 @@ Runs a specific test stage (see the script).
=head1 DISTRIBUTION =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 can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-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 can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2007-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 can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-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 can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+2 -2
View File
@@ -8,7 +8,7 @@ use strict;
#====================================================================== #======================================================================
# main # main
eval `modulecmd perl add synopsys-vcs`; eval `modulecmd perl add synopsys-vcs_mx`;
exec('vcs',@ARGV); exec('vcs',@ARGV);
####################################################################### #######################################################################
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
=head1 DISTRIBUTION =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 can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
-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 =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 redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0. General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,6 +1,6 @@
# DESCRIPTION: Verilator: GDB startup file with useful defines # DESCRIPTION: Verilator: GDB startup file with useful defines
# #
# Copyright 2012-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 # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
+7 -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 # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -46,7 +46,7 @@ obj_opt:
obj_dbg: obj_dbg:
mkdir $@ mkdir $@
.PHONY: ../verilator_bin ../verilator_bin_dbg .PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
opt: ../verilator_bin opt: ../verilator_bin
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
@@ -59,11 +59,15 @@ else
cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
endif endif
dbg: ../verilator_bin_dbg dbg: ../verilator_bin_dbg ../verilator_coverage_bin_dbg
../verilator_bin_dbg: obj_dbg prefiles ../verilator_bin_dbg: obj_dbg prefiles
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial 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 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::
prefiles:: config_rev.h prefiles:: config_rev.h
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users 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 # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -62,6 +62,8 @@ CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CPPFLAGS += @CPPFLAGS@ CPPFLAGS += @CPPFLAGS@
LDFLAGS += @LDFLAGS@ LDFLAGS += @LDFLAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
CFG_CXXFLAGS_SRC = @CFG_CXXFLAGS_SRC@
CFG_CXXFLAGS_PARSER = @CFG_CXXFLAGS_PARSER@
#### End of system configuration section. #### #### End of system configuration section. ####
@@ -85,7 +87,8 @@ endif
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl #CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
# -lfl not needed as Flex invoked with %nowrap option # -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 += -MMD
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
@@ -94,11 +97,11 @@ CPPFLAGS += -DYYDEBUG # Required to get nice error messages
CPPFLAGS += $(COPT) CPPFLAGS += $(COPT)
CPPFLAGS += -MP # Only works on recent GCC versions CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
#CPPFLAGS += -pedantic-errors #CPPFLAGS += -pedantic-errors
endif endif
CPPFLAGSWALL = $(CPPFLAGS) CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
@@ -127,6 +130,7 @@ HEADERS = $(wildcard V*.h v*.h)
ASTGEN = $(srcdir)/astgen ASTGEN = $(srcdir)/astgen
BISONPRE = $(srcdir)/bisonpre BISONPRE = $(srcdir)/bisonpre
FLEXFIX = $(srcdir)/flexfix FLEXFIX = $(srcdir)/flexfix
VLCOVGEN = $(srcdir)/vlcovgen
###################################################################### ######################################################################
#### Top level #### Top level
@@ -186,6 +190,7 @@ RAW_OBJS = \
V3Error.o \ V3Error.o \
V3Expand.o \ V3Expand.o \
V3File.o \ V3File.o \
V3FileLine.o \
V3Gate.o \ V3Gate.o \
V3GenClk.o \ V3GenClk.o \
V3Graph.o \ V3Graph.o \
@@ -210,6 +215,7 @@ RAW_OBJS = \
V3Number.o \ V3Number.o \
V3Options.o \ V3Options.o \
V3Order.o \ V3Order.o \
V3Os.o \
V3Param.o \ V3Param.o \
V3PreShell.o \ V3PreShell.o \
V3Premit.o \ V3Premit.o \
@@ -233,26 +239,30 @@ RAW_OBJS = \
V3WidthSel.o \ V3WidthSel.o \
# Non-concatable # Non-concatable
OBJS += \ NC_OBJS += \
V3ParseImp.o \ V3ParseImp.o \
V3ParseGrammar.o \ V3ParseGrammar.o \
V3ParseLex.o \ V3ParseLex.o \
V3PreProc.o \ V3PreProc.o \
# verilator_coverage
VLCOV_OBJS = \
VlcMain.o \
#### Linking #### Linking
ifeq ($(VL_DEBUG),) ifeq ($(VL_VLCOV),)
# Building with fewer objects to better optimize PREDEP_H = V3Ast__gen_classes.h
#OBJS += V3__CONCAT.o OBJS += $(RAW_OBJS) $(NC_OBJS)
OBJS += $(RAW_OBJS)
else else
OBJS += $(RAW_OBJS) PREDEP_H =
OBJS += $(VLCOV_OBJS)
endif endif
V3__CONCAT.cpp: $(addsuffix .cpp, $(basename $(RAW_OBJS))) V3__CONCAT.cpp: $(addsuffix .cpp, $(basename $(RAW_OBJS)))
$(PERL) $(srcdir)/../bin/verilator_includer $^ > $@ $(PERL) $(srcdir)/../bin/verilator_includer $^ > $@
$(TGT): V3Ast__gen_classes.h $(OBJS) $(TGT): $(PREDEP_H) $(OBJS)
@echo " Linking $@..." @echo " Linking $@..."
-rm -rf $@ [email protected] -rm -rf $@ [email protected]
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS} ${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
@@ -271,22 +281,28 @@ V3Number_test: V3Number_test.o
$(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $< $(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
V3ParseGrammar.o: V3ParseGrammar.cpp V3ParseBison.c V3ParseGrammar.o: V3ParseGrammar.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
V3ParseImp.o: V3ParseImp.cpp V3ParseBison.c V3ParseImp.o: V3ParseImp.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSPARSER} -c $<
#### Generated files #### Generated files
# Target rule called before parallel build to make generated files # Target rule called before parallel build to make generated files
serial:: V3Ast__gen_classes.h V3ParseBison.c 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 V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
$(PERL) $(ASTGEN) -I$(srcdir) --classes $(PERL) $(ASTGEN) -I$(srcdir) --classes
+13 -8
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -163,7 +163,7 @@ public:
class ActiveDlyVisitor : public ActiveBaseVisitor { class ActiveDlyVisitor : public ActiveBaseVisitor {
public: public:
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL }; enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
private: private:
CheckType m_check; // Combo logic or other CheckType m_check; // Combo logic or other
AstNode* m_alwaysp; // Always we're under AstNode* m_alwaysp; // Always we're under
@@ -175,6 +175,8 @@ private:
UINFO(5," ASSIGNDLY "<<nodep<<endl); UINFO(5," ASSIGNDLY "<<nodep<<endl);
if (m_check == CT_INITIAL) { if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=)."); 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 { } else {
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=)."); nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
} }
@@ -306,7 +308,7 @@ private:
} }
// METHODS // 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 // Move always to appropriate ACTIVE based on its sense list
if (oldsensesp if (oldsensesp
&& oldsensesp->sensesp() && oldsensesp->sensesp()
@@ -326,12 +328,10 @@ private:
bool sequent = m_itemSequent; bool sequent = m_itemSequent;
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*) if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
#ifndef NEW_ORDERING
if (combo && sequent) { if (combo && sequent) {
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list"); nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
sequent = false; sequent = false;
} }
#endif
AstActive* wantactivep = NULL; AstActive* wantactivep = NULL;
if (combo && !sequent) { if (combo && !sequent) {
@@ -360,7 +360,11 @@ private:
// Warn and/or convert any delayed assignments // Warn and/or convert any delayed assignments
if (combo && !sequent) { 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) { else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ); ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
@@ -376,13 +380,13 @@ private:
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return; return;
} }
visitAlways(nodep, nodep->sensesp()); visitAlways(nodep, nodep->sensesp(), nodep->keyword());
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// Move always to appropriate ACTIVE based on its sense list // Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl); UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: "); //if (debug()>=9) nodep->dumpTree(cout," Alw: ");
visitAlways(nodep, nodep->sensesp()); visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
} }
virtual void visit(AstSenGate* nodep, AstNUser*) { virtual void visit(AstSenGate* nodep, AstNUser*) {
AstSenItem* subitemp = nodep->sensesp(); AstSenItem* subitemp = nodep->sensesp();
@@ -432,4 +436,5 @@ public:
void V3Active::activeAll(AstNetlist* nodep) { void V3Active::activeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ActiveVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -160,4 +160,5 @@ public:
void V3ActiveTop::activeTopAll(AstNetlist* nodep) { void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ActiveTopVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+76 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -56,15 +56,18 @@ private:
+":"+cvtToStr(nodep->fileline()->lineno()) +":"+cvtToStr(nodep->fileline()->lineno())
+": Assertion failed in %m" +": Assertion failed in %m"
+((message != "")?": ":"")+message +((message != "")?": ":"")+message
+"\\n"); +"\n");
} }
void replaceDisplay(AstDisplay* nodep, const string& prefix) { void replaceDisplay(AstDisplay* nodep, const string& prefix) {
nodep->displayType(AstDisplayType::DT_WRITE); nodep->displayType(AstDisplayType::DT_WRITE);
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text())); nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
AstNode* timesp = nodep->fmtp()->exprsp(); if (timesp) timesp->unlinkFrBack();
// cppcheck-suppress nullPointer // cppcheck-suppress nullPointer
timesp = timesp->addNext(new AstTime(nodep->fileline())); AstNode* timenewp = new AstTime(nodep->fileline());
nodep->fmtp()->exprsp(timesp); if (AstNode* timesp = nodep->fmtp()->exprsp()) {
timesp->unlinkFrBackWithNext();
timenewp->addNext(timesp);
}
nodep->fmtp()->exprsp(timenewp);
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) { if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline())); nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
} }
@@ -73,25 +76,16 @@ private:
AstNode* newIfAssertOn(AstNode* nodep) { AstNode* newIfAssertOn(AstNode* nodep) {
// Add a internal if to check assertions are on. // 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. // Don't make this a AND term, as it's unlikely to need to test this.
return new AstIf (nodep->fileline(), AstNode* newp
// If assertions are off, have constant propagation rip them out later = new AstIf (nodep->fileline(),
// This allows syntax errors and such to be detected normally. // If assertions are off, have constant propagation rip them out later
(v3Global.opt.assertOn() // This allows syntax errors and such to be detected normally.
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1)) (v3Global.opt.assertOn()
: (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))), ? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
nodep, NULL); : (AstNode*)(new AstConst(nodep->fileline(), AstConst::LogicFalse()))),
} nodep, NULL);
newp->user1(true); // Don't assert/cover this if
AstNode* newIfCoverageOn(AstNode* nodep) { return newp;
// 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* newFireAssert(AstNode* nodep, const string& message) { AstNode* newFireAssert(AstNode* nodep, const string& message) {
@@ -122,19 +116,13 @@ private:
if (message!="") covincp->declp()->comment(message); if (message!="") covincp->declp()->comment(message);
bodysp = covincp; 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 { } else {
nodep->v3fatalSrc("Unknown node type"); nodep->v3fatalSrc("Unknown node type");
} }
if (stmtsp) bodysp = bodysp->addNext(stmtsp); if (stmtsp) bodysp = bodysp->addNext(stmtsp);
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL); AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp; bodysp = ifp;
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY); if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
// //
AstNode* newp = new AstAlways (nodep->fileline(), AstNode* newp = new AstAlways (nodep->fileline(),
VAlwaysKwd::ALWAYS, VAlwaysKwd::ALWAYS,
@@ -174,6 +162,62 @@ private:
// Bye // Bye
pushDeletep(nodep); nodep=NULL; 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 // VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) { virtual void visit(AstCase* nodep, AstNUser*) {
@@ -244,12 +288,6 @@ private:
nodep->stmtsp(), nodep->name()); nodep=NULL; nodep->stmtsp(), nodep->name()); nodep=NULL;
++m_statAsCover; ++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*) { virtual void visit(AstVAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newVAssertion(nodep, nodep->propp()); nodep=NULL; newVAssertion(nodep, nodep->propp()); nodep=NULL;
@@ -274,14 +312,6 @@ private:
m_beginp = lastp; 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*) { virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -307,4 +337,5 @@ public:
void V3Assert::assertAll(AstNetlist* nodep) { void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
AssertVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -73,14 +73,6 @@ private:
} }
// VISITORS //========== Statements // 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*) { virtual void visit(AstClocking* nodep, AstNUser*) {
UINFO(8," CLOCKING"<<nodep<<endl); UINFO(8," CLOCKING"<<nodep<<endl);
// Store the new default clock, reset on new module // Store the new default clock, reset on new module
@@ -101,13 +93,6 @@ private:
nodep->sentreep(newSenTree(nodep)); nodep->sentreep(newSenTree(nodep));
clearAssertInfo(); 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*) { virtual void visit(AstPslClocked* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_senip) { if (m_senip) {
@@ -152,4 +137,5 @@ public:
void V3AssertPre::assertPreAll(AstNetlist* nodep) { void V3AssertPre::assertPreAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
AssertPreVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+42 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -176,6 +176,10 @@ string AstNode::prettyName(const string& namein) {
pretty += "."; pretty += ".";
pos += 7; pos += 7;
} }
else if (0==strncmp(pos,"->",2)) {
pretty += ".";
pos += 2;
}
else if (0==strncmp(pos,"__PVT__",7)) { else if (0==strncmp(pos,"__PVT__",7)) {
pretty += ""; pretty += "";
pos += 7; pos += 7;
@@ -203,31 +207,6 @@ string AstNode::prettyTypeName() const {
return string(typeName())+" '"+prettyName()+"'"; 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 // 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<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) { //if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl; // 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: "); // v3Global.rootp()->dumpTree(cout,"-treeChange: ");
// if (next||1) this->dumpTreeAndNext(cout, prefix); // if (next||1) this->dumpTreeAndNext(cout, prefix);
// else this->dumpTree(cout, prefix); // else this->dumpTree(cout, prefix);
@@ -561,7 +543,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
if (linkerp->m_iterpp) { if (linkerp->m_iterpp) {
// If we're iterating over a next() link, we need to follow links off the // 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. // 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. // across every function.
// If anyone has a cleaner way, I'd be grateful. // If anyone has a cleaner way, I'd be grateful.
*(linkerp->m_iterpp) = newp; *(linkerp->m_iterpp) = newp;
@@ -750,6 +732,20 @@ void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) {
if (m_op4p) m_op4p->iterateAndNext(v, 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) { void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
// This is a very hot function // This is a very hot function
// IMPORTANT: If you replace a node that's the target of this iterator, // IMPORTANT: If you replace a node that's the target of this iterator,
@@ -764,16 +760,18 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
while (nodep) { while (nodep) {
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
ASTNODE_PREFETCH(nodep->m_nextp); ASTNODE_PREFETCH(nodep->m_nextp);
// Desirable check, but many places where multiple iterations are OK
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
// cppcheck-suppress nullPointer // cppcheck-suppress nullPointer
niterp->m_iterpp = &niterp; niterp->m_iterpp = &niterp;
niterp->accept(v, vup); niterp->accept(v, vup);
// accept may do a replaceNode and change niterp on us... // accept may do a replaceNode and change niterp on us...
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast //if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
if (!niterp) return; if (!niterp) return; // Perhaps node deleted inside accept
niterp->m_iterpp = NULL; niterp->m_iterpp = NULL;
if (VL_UNLIKELY(niterp!=nodep)) { // Edited it if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept
nodep = niterp; nodep = niterp;
} else { // Same node, just loop } else { // Unchanged node, just continue loop
nodep = niterp->m_nextp; nodep = niterp->m_nextp;
} }
} }
@@ -799,11 +797,12 @@ void AstNode::iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup) {
this->op4p()->iterateListBackwards(v,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 // Keep following the current list even if edits change it
if (!this) return; if (!this) return;
for (AstNode* nodep=this; nodep; ) { for (AstNode* nodep=this; nodep; ) {
AstNode* nnextp = nodep->m_nextp; AstNode* nnextp = nodep->m_nextp;
ASTNODE_PREFETCH(nnextp);
nodep->accept(v, vup); nodep->accept(v, vup);
nodep = nnextp; nodep = nnextp;
} }
@@ -864,24 +863,21 @@ void AstNode::cloneRelinkTree() {
//====================================================================== //======================================================================
// Comparison // Comparison
bool AstNode::sameTree(AstNode* node2p) { bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
return sameTreeIter(node2p, true);
}
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
// Return true if the two trees are identical // Return true if the two trees are identical
if (this==NULL && node2p==NULL) return true; if (this==NULL && node2p==NULL) return true;
if (this==NULL || node2p==NULL) return false; if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type() if (this->type() != node2p->type()
|| this->dtypep() != node2p->dtypep() || this->dtypep() != node2p->dtypep()
|| !this->same(node2p)) { || !this->same(node2p)
|| (gateOnly && !this->isGateOptimizable())) {
return false; return false;
} }
return (this->op1p()->sameTreeIter(node2p->op1p(),false) return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
&& this->op2p()->sameTreeIter(node2p->op2p(),false) && this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
&& this->op3p()->sameTreeIter(node2p->op3p(),false) && this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
&& this->op4p()->sameTreeIter(node2p->op4p(),false) && this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false)) && (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
); );
} }
@@ -895,8 +891,8 @@ ostream& operator<<(ostream& os, V3Hash rhs) {
V3Hash::V3Hash(const string& name) { V3Hash::V3Hash(const string& name) {
uint32_t val = 0; uint32_t val = 0;
for (const char* c=name.c_str(); *c; c++) { for (string::const_iterator it = name.begin(); it!=name.end(); ++it) {
val = val*31 + *c; val = val*31 + *it;
} }
setBoth(1,val); setBoth(1,val);
} }
@@ -1016,8 +1012,8 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
} }
} }
void AstNode::dumpTreeFile(const string& filename, bool append) { void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
if (v3Global.opt.dumpTree()) { if (doDump) {
{ // Write log & close { // Write log & close
UINFO(2,"Dumping "<<filename<<endl); UINFO(2,"Dumping "<<filename<<endl);
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append)); const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
+147 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -23,6 +23,7 @@
#include "config_build.h" #include "config_build.h"
#include "verilatedos.h" #include "verilatedos.h"
#include "V3Error.h" #include "V3Error.h"
#include "V3FileLine.h"
#include "V3Number.h" #include "V3Number.h"
#include "V3Global.h" #include "V3Global.h"
#include <vector> #include <vector>
@@ -92,6 +93,8 @@ public:
else if (signst==signedst_SIGNED) m_e=SIGNED; else if (signst==signedst_SIGNED) m_e=SIGNED;
else m_e=NOSIGN; 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)) {} explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
inline bool isSigned() const { return m_e==SIGNED; } inline bool isSigned() const { return m_e==SIGNED; }
@@ -234,6 +237,16 @@ public:
DIM_SIZE, // V3Width processes DIM_SIZE, // V3Width processes
DIM_UNPK_DIMENSIONS, // V3Width converts to constant DIM_UNPK_DIMENSIONS, // V3Width converts to constant
// //
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
//
ENUM_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
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 MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
// //
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@@ -245,7 +258,9 @@ public:
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv 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; enum en m_e;
const char* ascii() const { const char* ascii() const {
@@ -253,10 +268,13 @@ public:
"%E-AT", "%E-AT",
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT", "DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS", "DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
"DT_PUBLIC",
"ENUM_BASE", "ENUM_FIRST", "ENUM_LAST", "ENUM_NUM", "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME",
"MEMBER_BASE", "MEMBER_BASE",
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW", "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]; return names[m_e];
}; };
@@ -378,9 +396,8 @@ public:
bool isOpaque() const { // IE not a simple number we can bit optimize 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); return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
} }
bool isDouble() const { bool isDouble() const { return m_e==DOUBLE; }
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 rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); } inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); }
@@ -472,6 +489,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 { class VAlwaysKwd {
public: public:
enum en { enum en {
@@ -496,22 +544,23 @@ public:
//###################################################################### //######################################################################
class AstCaseType { class VCaseType {
public: public:
enum en { enum en {
CT_CASE, CT_CASE,
CT_CASEX, CT_CASEX,
CT_CASEZ CT_CASEZ,
CT_CASEINSIDE
}; };
enum en m_e; enum en m_e;
inline AstCaseType () : m_e(CT_CASE) {} inline VCaseType () : m_e(CT_CASE) {}
inline AstCaseType (en _e) : m_e(_e) {} inline VCaseType (en _e) : m_e(_e) {}
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
}; };
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); } inline bool operator== (VCaseType lhs, VCaseType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); } inline bool operator== (VCaseType lhs, VCaseType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); } inline bool operator== (VCaseType::en lhs, VCaseType rhs) { return (lhs == rhs.m_e); }
//###################################################################### //######################################################################
@@ -605,13 +654,16 @@ struct VNumRange {
int lo() const { return m_lo; } int lo() const { return m_lo; }
int left() const { return littleEndian()?lo():hi(); } // How to show a declaration int left() const { return littleEndian()?lo():hi(); } // How to show a declaration
int right() const { return littleEndian()?hi():lo(); } int right() const { return littleEndian()?hi():lo(); }
int leftToRightInc() const { return littleEndian()?1:-1; }
int elements() const { return hi()-lo()+1; } int elements() const { return hi()-lo()+1; }
bool ranged() const { return m_ranged; } bool ranged() const { return m_ranged; }
bool littleEndian() const { return m_littleEndian; } bool littleEndian() const { return m_littleEndian; }
int hiMaxSelect() const { return (lo()<0 ? hi()-lo() : hi()); } // Maximum value a [] select may index 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] 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)); } { 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; }
//###################################################################### //######################################################################
@@ -926,7 +978,7 @@ class AstNode {
AstNode* cloneTreeIterList(); AstNode* cloneTreeIterList();
void checkTreeIter(AstNode* backp); void checkTreeIter(AstNode* backp);
void checkTreeIterList(AstNode* backp); void checkTreeIterList(AstNode* backp);
bool sameTreeIter(AstNode* node2p, bool ignNext); bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
void deleteTreeIter(); void deleteTreeIter();
void deleteNode(); void deleteNode();
static void relinkOneLink(AstNode*& pointpr, AstNode* newp); static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
@@ -998,6 +1050,7 @@ public:
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics 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 instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
@@ -1007,13 +1060,13 @@ public:
virtual string verilogKwd() const { return ""; } virtual string verilogKwd() const { return ""; }
string shortName() const; // Name with __PVT__ removed for concatenating scopes string shortName() const; // Name with __PVT__ removed for concatenating scopes
static string dedotName(const string& namein); // Name with dots removed 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 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 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 encodeNumber(vlsint64_t numin); // Encode number into internal C representation
static string vcdName(const string& namein); // Name for printing out to vcd files static string vcdName(const string& namein); // Name for printing out to vcd files
string prettyName() const { return prettyName(name()); } 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; } FileLine* fileline() const { return m_fileline; }
void fileline(FileLine* fl) { m_fileline=fl; } void fileline(FileLine* fl) { m_fileline=fl; }
bool width1() const; bool width1() const;
@@ -1027,11 +1080,13 @@ public:
//TODO stomp these width functions out, and call via dtypep() instead //TODO stomp these width functions out, and call via dtypep() instead
int width() const; int width() const;
int widthMin() const; int widthMin() const;
int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); }
int widthWords() const { return VL_WORDS_I(width()); } int widthWords() const { return VL_WORDS_I(width()); }
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); } bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); } bool isWide() const { return (width()>VL_QUADSIZE); }
bool isDouble() const; bool isDouble() const;
bool isSigned() const; bool isSigned() const;
bool isString() const;
AstNUser* user1p() const { AstNUser* user1p() const {
// Slows things down measurably, so disabled by default // Slows things down measurably, so disabled by default
@@ -1109,6 +1164,7 @@ public:
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); } void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); } void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
void dtypeSetDouble() { dtypep(findDoubleDType()); } void dtypeSetDouble() { dtypep(findDoubleDType()); }
void dtypeSetString() { dtypep(findStringDType()); }
void dtypeSetSigned32() { dtypep(findSigned32DType()); } void dtypeSetSigned32() { dtypep(findSigned32DType()); }
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
@@ -1116,6 +1172,7 @@ public:
// Data type locators // Data type locators
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); } AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); } AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); }
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); } AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
@@ -1151,6 +1208,7 @@ public:
// METHODS - Iterate on a tree // METHODS - Iterate on a tree
AstNode* cloneTree(bool cloneNextLink); AstNode* cloneTree(bool cloneNextLink);
bool sameTree(AstNode* node2p); // Does tree of this == node2p? 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 deleteTree(); // Always deletes the next link
void checkTree(); // User Interface version void checkTree(); // User Interface version
void checkIter() const; void checkIter() const;
@@ -1160,7 +1218,7 @@ public:
void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); } void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
void dumpTreeGdb(); // For GDB only void dumpTreeGdb(); // For GDB only
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0); 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); static void dumpTreeFileGdb(const char* filenamep=NULL);
// METHODS - queries // METHODS - queries
@@ -1184,9 +1242,11 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0; 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 iterate(AstNVisitor& v, AstNUser* vup=NULL) { this->accept(v,vup); } // Does this; excludes following this->next
void iterateAndNext(AstNVisitor& v, AstNUser* vup=NULL); 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 iterateChildren(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
void iterateChildrenBackwards(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 AstNode* acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup=NULL); // Return edited nodep; see comments in V3Ast.cpp
// CONVERSION // CONVERSION
@@ -1207,8 +1267,9 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
virtual ~Ast ##name() {} \ virtual ~Ast ##name() {} \
Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##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 // Math -- anything that's part of an expression tree
public:
AstNodeMath(FileLine* fl) AstNodeMath(FileLine* fl)
: AstNode(fl) {} : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeMath) ASTNODE_BASE_FUNCS(NodeMath)
@@ -1223,8 +1284,9 @@ struct AstNodeMath : public AstNode {
bool isOpaque() { return castCvtPackString()!=NULL; } bool isOpaque() { return castCvtPackString()!=NULL; }
}; };
struct AstNodeTermop : public AstNodeMath { class AstNodeTermop : public AstNodeMath {
// Terminal operator -- a operator with no "inputs" // Terminal operator -- a operator with no "inputs"
public:
AstNodeTermop(FileLine* fl) AstNodeTermop(FileLine* fl)
: AstNodeMath(fl) {} : AstNodeMath(fl) {}
ASTNODE_BASE_FUNCS(NodeTermop) ASTNODE_BASE_FUNCS(NodeTermop)
@@ -1234,8 +1296,9 @@ struct AstNodeTermop : public AstNodeMath {
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
struct AstNodeUniop : public AstNodeMath { class AstNodeUniop : public AstNodeMath {
// Unary math // Unary math
public:
AstNodeUniop(FileLine* fl, AstNode* lhsp) AstNodeUniop(FileLine* fl, AstNode* lhsp)
: AstNodeMath(fl) { : AstNodeMath(fl) {
dtypeFrom(lhsp); dtypeFrom(lhsp);
@@ -1247,15 +1310,17 @@ struct AstNodeUniop : public AstNodeMath {
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0; virtual bool cleanLhs() = 0;
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size 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 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 int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeBiop : public AstNodeMath { class AstNodeBiop : public AstNodeMath {
// Binary math // Binary math
public:
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs) AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeMath(fl) { : AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); } setOp1p(lhs); setOp2p(rhs); }
@@ -1270,15 +1335,17 @@ struct AstNodeBiop : public AstNodeMath {
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero 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 sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs 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 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 int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeTriop : public AstNodeMath { class AstNodeTriop : public AstNodeMath {
// Trinary math // Trinary math
public:
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNodeMath(fl) { : AstNodeMath(fl) {
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); } setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
@@ -1302,20 +1369,23 @@ struct AstNodeTriop : public AstNodeMath {
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeBiCom : public AstNodeBiop { class AstNodeBiCom : public AstNodeBiop {
// Binary math with commutative properties // Binary math with commutative properties
public:
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs) AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiop(fl, lhs, rhs) {} : AstNodeBiop(fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiCom) ASTNODE_BASE_FUNCS(NodeBiCom)
}; };
struct AstNodeBiComAsv : public AstNodeBiCom { class AstNodeBiComAsv : public AstNodeBiCom {
// Binary math with commutative & associative properties // Binary math with commutative & associative properties
public:
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs) AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiCom(fl, lhs, rhs) {} : AstNodeBiCom(fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiComAsv) ASTNODE_BASE_FUNCS(NodeBiComAsv)
}; };
struct AstNodeCond : public AstNodeTriop { class AstNodeCond : public AstNodeTriop {
public:
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop(fl, condp, expr1p, expr2p) { : AstNodeTriop(fl, condp, expr1p, expr2p) {
if (expr1p) dtypeFrom(expr1p); if (expr1p) dtypeFrom(expr1p);
@@ -1337,8 +1407,9 @@ struct AstNodeCond : public AstNodeTriop {
virtual int instrCount() const { return instrCountBranch(); } virtual int instrCount() const { return instrCountBranch(); }
}; };
struct AstNodePreSel : public AstNode { class AstNodePreSel : public AstNode {
// Something that becomes an AstSel // Something that becomes an AstSel
public:
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNode(fl) { : AstNode(fl) {
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); } setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
@@ -1357,8 +1428,9 @@ struct AstNodePreSel : public AstNode {
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
}; };
struct AstNodeStmt : public AstNode { class AstNodeStmt : public AstNode {
// Statement -- anything that's directly under a function // Statement -- anything that's directly under a function
public:
AstNodeStmt(FileLine* fl) AstNodeStmt(FileLine* fl)
: AstNode(fl) {} : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeStmt) ASTNODE_BASE_FUNCS(NodeStmt)
@@ -1367,7 +1439,8 @@ struct AstNodeStmt : public AstNode {
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here 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) AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt(fl) { : AstNodeStmt(fl) {
setOp1p(rhsp); setOp2p(lhsp); setOp1p(rhsp); setOp2p(lhsp);
@@ -1388,7 +1461,8 @@ struct AstNodeAssign : public AstNodeStmt {
virtual string verilogKwd() const { return "="; } virtual string verilogKwd() const { return "="; }
}; };
struct AstNodeFor : public AstNodeStmt { class AstNodeFor : public AstNodeStmt {
public:
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp, AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* incsp, AstNode* bodysp) AstNode* incsp, AstNode* bodysp)
: AstNodeStmt(fileline) { : AstNodeStmt(fileline) {
@@ -1405,7 +1479,7 @@ struct AstNodeFor : public AstNodeStmt {
virtual bool same(AstNode* samep) const { return true; } virtual bool same(AstNode* samep) const { return true; }
}; };
struct AstNodeIf : public AstNodeStmt { class AstNodeIf : public AstNodeStmt {
private: private:
AstBranchPred m_branchPred; // Branch prediction as taken/untaken? AstBranchPred m_branchPred; // Branch prediction as taken/untaken?
public: public:
@@ -1429,7 +1503,8 @@ public:
AstBranchPred branchPred() const { return m_branchPred; } AstBranchPred branchPred() const { return m_branchPred; }
}; };
struct AstNodeCase : public AstNodeStmt { class AstNodeCase : public AstNodeStmt {
public:
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp) AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
: AstNodeStmt(fl) { : AstNodeStmt(fl) {
setOp1p(exprp); addNOp2p(casesp); setOp1p(exprp); addNOp2p(casesp);
@@ -1443,8 +1518,9 @@ struct AstNodeCase : public AstNodeStmt {
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
}; };
struct AstNodeSenItem : public AstNode { class AstNodeSenItem : public AstNode {
// An AstSenItem or AstSenGate // An AstSenItem or AstSenGate
public:
AstNodeSenItem(FileLine* fl) : AstNode(fl) {} AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeSenItem) ASTNODE_BASE_FUNCS(NodeSenItem)
virtual bool isClocked() const = 0; virtual bool isClocked() const = 0;
@@ -1502,7 +1578,7 @@ public:
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
struct AstNodeText : public AstNode { class AstNodeText : public AstNode {
private: private:
string m_text; string m_text;
public: public:
@@ -1519,11 +1595,11 @@ public:
const string& text() const { return m_text; } const string& text() const { return m_text; }
}; };
struct AstNodeDType : public AstNode { class AstNodeDType : public AstNode {
private:
// Ideally width() would migrate to BasicDType as that's where it makes sense, // 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. // but it's currently so prevalent in the code we leave it here.
// Note the below members are included in AstTypeTable::Key lookups // Note the below members are included in AstTypeTable::Key lookups
private:
int m_width; // (also in AstTypeTable::Key) Bit width of operation int m_width; // (also in AstTypeTable::Key) Bit width of operation
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
@@ -1541,7 +1617,9 @@ public:
virtual void dumpSmall(ostream& str); virtual void dumpSmall(ostream& str);
virtual bool hasDType() const { return true; } virtual bool hasDType() const { return true; }
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type 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 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 int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
@@ -1571,7 +1649,7 @@ public:
static int uniqueNumInc() { return ++s_uniqueNum; } static int uniqueNumInc() { return ++s_uniqueNum; }
}; };
struct AstNodeClassDType : public AstNodeDType { class AstNodeClassDType : public AstNodeDType {
private: private:
// TYPES // TYPES
typedef map<string,AstMemberDType*> MemberNameMap; typedef map<string,AstMemberDType*> MemberNameMap;
@@ -1591,12 +1669,15 @@ public:
// For basicp() we reuse the size to indicate a "fake" basic type of same size // 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 AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } 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 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,... virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// op1 = members // op1 = members
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
void addMembersp(AstNode* nodep) { addNOp1p(nodep); } void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
bool packed() const { return m_packed; } 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 clearCache() { m_members.clear(); }
void repairMemberCache(); void repairMemberCache();
AstMemberDType* findMember(const string& name) const { AstMemberDType* findMember(const string& name) const {
@@ -1608,7 +1689,7 @@ public:
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); } 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]" // Array data type, ie "some_dtype var_name [2:0]"
// Children: DTYPE (moved to refDTypep() in V3Width) // Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds) // Children: RANGE (array bounds)
@@ -1645,6 +1726,8 @@ public:
// METHODS // METHODS
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } 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 widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); } virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
int msb() const; int msb() const;
@@ -1653,8 +1736,9 @@ public:
VNumRange declRange() const; VNumRange declRange() const;
}; };
struct AstNodeSel : public AstNodeBiop { class AstNodeSel : public AstNodeBiop {
// Single bit range extraction, perhaps with non-constant selection or array selection // Single bit range extraction, perhaps with non-constant selection or array selection
public:
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp) AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
:AstNodeBiop(fl, fromp, bitp) {} :AstNodeBiop(fl, fromp, bitp) {}
ASTNODE_BASE_FUNCS(NodeSel) ASTNODE_BASE_FUNCS(NodeSel)
@@ -1666,10 +1750,21 @@ struct AstNodeSel : public AstNodeBiop {
virtual bool hasDType() const { return true; } 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 // Tasks/functions common handling
struct AstNodeFTask : public AstNode { class AstNodeFTask : public AstNode {
private: private:
string m_name; // Name of task string m_name; // Name of task
string m_cname; // Name of task if DPI import string m_cname; // Name of task if DPI import
@@ -1727,7 +1822,7 @@ public:
bool pure() const { return m_pure; } bool pure() const { return m_pure; }
}; };
struct AstNodeFTaskRef : public AstNode { class AstNodeFTaskRef : public AstNode {
// A reference to a task (or function) // A reference to a task (or function)
private: private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
@@ -1773,7 +1868,7 @@ public:
void scopeNamep(AstNode* nodep) { setNOp3p(nodep); } void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
}; };
struct AstNodeModule : public AstNode { class AstNodeModule : public AstNode {
// A module, package, program or interface declaration; // A module, package, program or interface declaration;
// something that can live directly under the TOP, // something that can live directly under the TOP,
// excluding $unit package stuff // excluding $unit package stuff
@@ -1787,12 +1882,13 @@ private:
bool m_internal:1; // Internally created bool m_internal:1; // Internally created
int m_level; // 1=top module, 2=cell off top module, ... int m_level; // 1=top module, 2=cell off top module, ...
int m_varNum; // Incrementing variable number int m_varNum; // Incrementing variable number
int m_typeNum; // Incrementing implicit type number
public: public:
AstNodeModule(FileLine* fl, const string& name) AstNodeModule(FileLine* fl, const string& name)
: AstNode (fl) : AstNode (fl)
,m_name(name), m_origName(name) ,m_name(name), m_origName(name)
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false) ,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) ASTNODE_BASE_FUNCS(NodeModule)
virtual void dump(ostream& str); virtual void dump(ostream& str);
virtual bool maybePointedTo() const { return true; } virtual bool maybePointedTo() const { return true; }
@@ -1812,6 +1908,7 @@ public:
int level() const { return m_level; } int level() const { return m_level; }
bool isTop() const { return level()==1; } bool isTop() const { return level()==1; }
int varNumGetInc() { return ++m_varNum; } int varNumGetInc() { return ++m_varNum; }
int typeNumGetInc() { return ++m_typeNum; }
void modPublic(bool flag) { m_modPublic = flag; } void modPublic(bool flag) { m_modPublic = flag; }
bool modPublic() const { return m_modPublic; } bool modPublic() const { return m_modPublic; }
void modTrace(bool flag) { m_modTrace = flag; } void modTrace(bool flag) { m_modTrace = flag; }
@@ -1838,6 +1935,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 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 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::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::isSigned() const { return dtypep() && dtypep()->isSigned(); }
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); } inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
@@ -1845,6 +1943,8 @@ inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); } inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); } inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); } inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(node2p, true, false); }
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(node2p, true, true); }
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); } inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
+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
+79 -13
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -112,6 +112,35 @@ int AstNodeClassDType::widthAlignBytes() const {
else return 8; 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 { bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar())); return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
} }
@@ -171,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) named=false;
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument"); if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
string arg; string arg;
@@ -204,7 +233,7 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
arg += " (& "+name(); arg += " (& "+name();
arg += ")["+cvtToStr(widthWords())+"]"; arg += ")["+cvtToStr(widthWords())+"]";
} else { } else {
if (isOutput() || (strtype && isInput())) arg += "&"; if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
if (named) arg += " "+name(); if (named) arg += " "+name();
} }
return arg; return arg;
@@ -321,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) { AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
// dimension passed from AstArraySel::dimension // dimension passed from AstArraySel::dimension
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar, // Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
@@ -456,9 +506,9 @@ string AstScope::nameDotless() const {
return out; return out;
} }
string AstScopeName::scopePrettyName() const { string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const {
string out; string out;
for (AstText* textp=scopeAttrp(); textp; textp=textp->nextp()->castText()) { for (AstText* textp=scopeTextp; textp; textp=textp->nextp()->castText()) {
out += textp->text(); out += textp->text();
} }
// TOP will be replaced by top->name() // TOP will be replaced by top->name()
@@ -468,9 +518,9 @@ string AstScopeName::scopePrettyName() const {
return AstNode::prettyName(out); return AstNode::prettyName(out);
} }
string AstScopeName::scopeSymName() const { string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const {
string out; string out;
for (AstText* textp=scopeAttrp(); textp; textp=textp->nextp()->castText()) { for (AstText* textp=scopeTextp; textp; textp=textp->nextp()->castText()) {
out += textp->text(); out += textp->text();
} }
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,""); if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
@@ -690,7 +740,10 @@ void AstNode::dump(ostream& str) {
} else { // V3Broken will throw an error } else { // V3Broken will throw an error
if (dtypep()) str<<" %Error-dtype-exp=null,got="<<(void*)dtypep(); 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) { void AstAlways::dump(ostream& str) {
@@ -753,6 +806,13 @@ void AstJumpGo::dump(ostream& str) {
if (labelp()) { labelp()->dump(str); } if (labelp()) { labelp()->dump(str); }
else { str<<"%Error:UNLINKED"; } 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) { void AstModportVarRef::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
str<<" "<<varType(); str<<" "<<varType();
@@ -765,6 +825,10 @@ void AstPin::dump(ostream& str) {
else { str<<" ->UNLINKED"; } else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]"; if (svImplicit()) str<<" [.SV]";
} }
void AstTypedef::dump(ostream& str) {
this->AstNode::dump(str);
if (attrPublic()) str<<" [PUBLIC]";
}
void AstRange::dump(ostream& str) { void AstRange::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (littleEndian()) str<<" [LITTLE]"; if (littleEndian()) str<<" [LITTLE]";
@@ -792,18 +856,21 @@ void AstNodeDType::dumpSmall(ostream& str) {
<<((isSigned()&&!isDouble())?"s":"") <<((isSigned()&&!isDouble())?"s":"")
<<(isNosign()?"n":"") <<(isNosign()?"n":"")
<<(isDouble()?"d":"") <<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width(); <<(isString()?"str":"");
if (!isDouble() && !isString()) {
str<<"w"<<(widthSized()?"":"u")<<width();
}
if (!widthSized()) str<<"/"<<widthMin(); if (!widthSized()) str<<"/"<<widthMin();
str<<")"; str<<")";
} }
void AstNodeArrayDType::dumpSmall(ostream& str) { void AstNodeArrayDType::dumpSmall(ostream& str) {
this->AstNodeDType::dumpSmall(str); this->AstNodeDType::dumpSmall(str);
if (castPackArrayDType()) str<<"p"; else str<<"u"; if (castPackArrayDType()) str<<"p"; else str<<"u";
str<<"["<<declRange().left()<<":"<<declRange().right()<<"]"; str<<declRange();
} }
void AstNodeArrayDType::dump(ostream& str) { void AstNodeArrayDType::dump(ostream& str) {
this->AstNodeDType::dump(str); this->AstNodeDType::dump(str);
str<<" ["<<declRange().left()<<":"<<declRange().right()<<"]"; str<<" "<<declRange();
} }
void AstNodeModule::dump(ostream& str) { void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
@@ -819,7 +886,7 @@ void AstPackageImport::dump(ostream& str) {
void AstSel::dump(ostream& str) { void AstSel::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (declRange().ranged()) { if (declRange().ranged()) {
str<<" decl["<<declRange().left()<<":"<<declRange().right()<<"]"; str<<" decl"<<declRange()<<"]";
if (declElWidth()!=1) str<<"/"<<declElWidth(); if (declElWidth()!=1) str<<"/"<<declElWidth();
} }
} }
@@ -854,7 +921,6 @@ void AstTypeTable::dump(ostream& str) {
for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) { for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) {
AstBasicDType* dtypep = it->second; AstBasicDType* dtypep = it->second;
str<<endl; // Newline from caller, so newline first str<<endl; // Newline from caller, so newline first
stringstream nsstr;
str<<"\t\tdetailed -> "; str<<"\t\tdetailed -> ";
dtypep->dump(str); dtypep->dump(str);
} }
+798 -387
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -271,4 +271,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
if (state.anyFuncInBegin()) { if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -21,6 +21,9 @@
// At each IF/(IF else). // At each IF/(IF else).
// Count underneath $display/$stop statements. // Count underneath $display/$stop statements.
// If more on if than else, this branch is unlikely, or vice-versa. // 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 { class BranchVisitor : public AstNVisitor {
private: private:
// NODE STATE
// Entire netlist:
// AstFTask::user1() -> int. Number of references
AstUser1InUse m_inuser1;
// TYPES
typedef vector<AstCFunc*> CFuncVec;
// STATE // STATE
int m_likely; // Excuses for branch likely taken int m_likely; // Excuses for branch likely taken
int m_unlikely; // Excuses for branch likely not taken int m_unlikely; // Excuses for branch likely not taken
CFuncVec m_cfuncsp; // List of all tasks
// METHODS // METHODS
static int debug() { static int debug() {
@@ -55,6 +67,12 @@ private:
m_likely = false; m_likely = false;
m_unlikely = false; m_unlikely = false;
} }
void checkUnlikely(AstNode* nodep) {
if (nodep->isUnlikely()) {
UINFO(4," UNLIKELY: "<<nodep<<endl);
m_unlikely++;
}
}
// VISITORS // VISITORS
virtual void visit(AstNodeIf* nodep, AstNUser*) { virtual void visit(AstNodeIf* nodep, AstNUser*) {
@@ -83,20 +101,37 @@ private:
m_likely = lastLikely; m_likely = lastLikely;
m_unlikely = lastUnlikely; m_unlikely = lastUnlikely;
} }
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstCCall* nodep, AstNUser*) {
// Default: Just iterate checkUnlikely(nodep);
if (nodep->isUnlikely()) { nodep->funcp()->user1Inc();
UINFO(4," UNLIKELY: "<<nodep<<endl);
m_unlikely++;
}
nodep->iterateChildren(*this); 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: public:
// CONSTUCTORS // CONSTUCTORS
BranchVisitor(AstNetlist* rootp) { BranchVisitor(AstNetlist* nodep) {
reset(); reset();
rootp->iterateChildren(*this); nodep->iterateChildren(*this);
calc_tasks();
} }
virtual ~BranchVisitor() {} 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+21 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -37,6 +37,9 @@
#include "V3Broken.h" #include "V3Broken.h"
#include "V3Ast.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 { class BrokenTable : public AstNVisitor {
@@ -47,11 +50,11 @@ private:
typedef map<const AstNode*,int> NodeMap; typedef map<const AstNode*,int> NodeMap;
static NodeMap s_nodes; // Set of all nodes that exist static NodeMap s_nodes; // Set of all nodes that exist
// BITMASK // BITMASK
static const int FLAG_ALLOCATED = 0x01; // new() and not delete()ed enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree enum { FLAG_IN_TREE = 0x02 }; // Is in netlist tree
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to enum { FLAG_LINKABLE = 0x04 }; // Is in netlist tree, can be linked to
static const int FLAG_LEAKED = 0x08; // Known to have been leaked enum { 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_UNDER_NOW = 0x10 }; // Is in tree as parent of current node
public: public:
// METHODS // METHODS
static void deleted(const AstNode* nodep) { static void deleted(const AstNode* nodep) {
@@ -71,7 +74,8 @@ public:
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n"); ((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
} }
if (iter == s_nodes.end()) { 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) { static void setUnder(const AstNode* nodep, bool flag) {
@@ -185,7 +189,7 @@ private:
// VISITORS // VISITORS
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::addInTree(nodep, nodep->maybePointedTo()); BrokenTable::addInTree(nodep, nodep->maybePointedTo());
nodep->iterateChildren(*this); nodep->iterateChildrenConst(*this);
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
@@ -200,6 +204,12 @@ public:
class BrokenCheckVisitor : public AstNVisitor { class BrokenCheckVisitor : public AstNVisitor {
private: private:
void checkWidthMin(AstNode* nodep) {
if (nodep->width() != nodep->widthMin()
&& v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH) {
nodep->v3fatalSrc("Width != WidthMin");
}
}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::setUnder(nodep,true); BrokenTable::setUnder(nodep,true);
if (const char* whyp=nodep->broken()) { if (const char* whyp=nodep->broken()) {
@@ -216,19 +226,10 @@ private:
if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName()); if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName());
} }
if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed"); if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed");
if (AstNodeDType* dnodep = nodep->castNodeDType()) { if (AstNodeDType* dnodep = nodep->castNodeDType()) checkWidthMin(dnodep);
if (dnodep->width() != dnodep->widthMin()
&& v3Global.assertWidthsMatch()) {
dnodep->v3fatalSrc("Width != WidthMin");
}
}
} }
if (v3Global.assertWidthsMatch()) { checkWidthMin(nodep);
if (nodep->width() != nodep->widthMin()) { nodep->iterateChildrenConst(*this);
nodep->v3fatalSrc("Width != WidthMin");
}
}
nodep->iterateChildren(*this);
BrokenTable::setUnder(nodep,false); BrokenTable::setUnder(nodep,false);
} }
public: 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+28 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -97,7 +97,8 @@ private:
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')"); 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()) { } else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
// Don't sweat it, we already complained about casex in general // 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()) { if (nodep->num().isUnknown()) {
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)"); nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
} }
@@ -322,36 +323,42 @@ private:
icondNextp = icondp->nextp(); icondNextp = icondp->nextp();
icondp->unlinkFrBack(); icondp->unlinkFrBack();
AstNode* and1p; AstNode* condp = NULL; // Default is to use and1p/and2p
AstNode* and2p;
AstConst* iconstp = icondp->castConst(); AstConst* iconstp = icondp->castConst();
if (iconstp && neverItem(nodep, iconstp)) { if (iconstp && neverItem(nodep, iconstp)) {
// X in casez can't ever be executed // X in casez can't ever be executed
icondp->deleteTree(); icondp=NULL; iconstp=NULL; icondp->deleteTree(); icondp=NULL; iconstp=NULL;
// For simplicity, make expression that is not equal, and let later // For simplicity, make expression that is not equal, and let later
// optimizations remove it // optimizations remove it
and1p = new AstConst(itemp->fileline(), AstConst::LogicFalse()); condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
and2p = new AstConst(itemp->fileline(), AstConst::LogicTrue()); } 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() } else if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez())) { && (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask (itemp->fileline(), iconstp->width()); V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num()); nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width()); V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num()); numval.opBitsOne(iconstp->num());
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false), AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
new AstConst(itemp->fileline(), nummask)); new AstConst(itemp->fileline(), nummask));
and2p = new AstAnd(itemp->fileline(), AstNode* and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval), new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask)); new AstConst(itemp->fileline(), nummask));
icondp->deleteTree(); icondp=NULL; iconstp=NULL; icondp->deleteTree(); icondp=NULL; iconstp=NULL;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else { } else {
// Not a caseX mask, we can simply build CASEEQ(cexpr icond) // Not a caseX mask, we can simply build CASEEQ(cexpr icond)
and1p = cexprp->cloneTree(false); AstNode* and1p = cexprp->cloneTree(false);
and2p = icondp; 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) { if (!ifexprp) {
ifexprp = condp; ifexprp = condp;
} else { } else {
@@ -404,6 +411,7 @@ private:
AstNode* itemexprp = ifexprp; ifexprp=NULL; AstNode* itemexprp = ifexprp; ifexprp=NULL;
if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
itemexprp->deleteTree(); itemexprp=NULL; itemexprp->deleteTree(); itemexprp=NULL;
// cppcheck-suppress redundantAssignment
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue()); itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
} }
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL); AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
@@ -435,7 +443,7 @@ private:
bool neverItem(AstCase* casep, AstConst* itemp) { bool neverItem(AstCase* casep, AstConst* itemp) {
// Xs in case or casez are impossible due to two state simulations // Xs in case or casez are impossible due to two state simulations
if (casep->casex()) { if (casep->casex()) {
} else if (casep->casez()) { } else if (casep->casez() || casep->caseInside()) {
if (itemp->num().isUnknown()) return true; if (itemp->num().isUnknown()) return true;
} else { } else {
if (itemp->num().isFourState()) return true; if (itemp->num().isFourState()) return true;
@@ -455,6 +463,7 @@ private:
replaceCaseFast(nodep); nodep=NULL; replaceCaseFast(nodep); nodep=NULL;
} else { } else {
++m_statCaseSlow; ++m_statCaseSlow;
// cppcheck-supporess uselessAssignmentPtrArg
replaceCaseComplicated(nodep); nodep=NULL; replaceCaseComplicated(nodep); nodep=NULL;
} }
} }
@@ -482,6 +491,7 @@ public:
void V3Case::caseAll(AstNetlist* nodep) { void V3Case::caseAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
CaseVisitor visitor (nodep); CaseVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("case.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
void V3Case::caseLint(AstNodeCase* nodep) { void V3Case::caseLint(AstNodeCase* nodep) {
UINFO(4,__FUNCTION__<<": "<<endl); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+3 -1
View File
@@ -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -149,6 +149,7 @@ private:
if (!nodep->lvalue() if (!nodep->lvalue()
&& !nodep->backp()->castCCast() && !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath() && nodep->backp()->castNodeMath()
&& !nodep->backp()->castArraySel()
&& nodep->backp()->width() && nodep->backp()->width()
&& castSize(nodep) != castSize(nodep->varp())) { && castSize(nodep) != castSize(nodep->varp())) {
// Cast vars to IData first, else below has upper bits wrongly set // Cast vars to IData first, else below has upper bits wrongly set
@@ -187,4 +188,5 @@ public:
void V3Cast::castAll(AstNetlist* nodep) { void V3Cast::castAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
CastVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -712,6 +712,7 @@ private:
virtual void visit(AstInitial* nodep, AstNUser*) { } virtual void visit(AstInitial* nodep, AstNUser*) { }
virtual void visit(AstTraceInc* nodep, AstNUser*) { } virtual void visit(AstTraceInc* nodep, AstNUser*) { }
virtual void visit(AstCoverToggle* nodep, AstNUser*) { } virtual void visit(AstCoverToggle* nodep, AstNUser*) { }
virtual void visit(AstNodeDType* nodep, AstNUser*) { }
//-------------------- //--------------------
// Default // 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -43,6 +43,130 @@
#include "V3Changed.h" #include "V3Changed.h"
#include "V3EmitCBase.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 // Changed state, as a visitor of each AstNode
@@ -54,15 +178,7 @@ private:
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
// STATE // STATE
AstNodeModule* m_topModp; // Top module ChangedState* m_statep; // Shared state across visitors
AstScope* m_scopetopp; // Scope under TOPSCOPE
AstCFunc* m_chgFuncp; // Change function we're building
// CONSTANTS
enum MiscConsts {
DETECTARRAY_MAX_INDEXES = 256 // How many indexes before error
// Ok to increase this, but may result in much slower model
};
// METHODS // METHODS
static int debug() { static int debug() {
@@ -71,70 +187,16 @@ private:
return level; 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) { 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); vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType(); ChangedInsertVisitor visitor (vscp, m_statep);
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);
}
}
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep, AstNUser*) {
UINFO(4," MOD "<<nodep<<endl); UINFO(4," MOD "<<nodep<<endl);
if (nodep->isTop()) { if (nodep->isTop()) {
m_topModp = nodep; m_statep->m_topModp = nodep;
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -145,15 +207,15 @@ private:
// Create the change detection function // Create the change detection function
AstScope* scopep = nodep->scopep(); AstScope* scopep = nodep->scopep();
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n"); if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
m_scopetopp = scopep; m_statep->m_scopetopp = scopep;
// Create change detection function // Create change detection function
m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "IData"); m_statep->m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar()); m_statep->m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_chgFuncp->symProlog(true); m_statep->m_chgFuncp->symProlog(true);
m_chgFuncp->declPrivate(true); m_statep->m_chgFuncp->declPrivate(true);
m_scopetopp->addActivep(m_chgFuncp); m_statep->m_scopetopp->addActivep(m_statep->m_chgFuncp);
// We need at least one change detect so we know to emit the correct code // 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); nodep->iterateChildren(*this);
} }
@@ -165,6 +227,9 @@ private:
} }
} }
} }
virtual void visit(AstNodeMath* nodep, AstNUser*) {
// Short-circuit
}
//-------------------- //--------------------
// Default: Just iterate // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
@@ -173,10 +238,8 @@ private:
public: public:
// CONSTUCTORS // CONSTUCTORS
ChangedVisitor(AstNetlist* nodep) { ChangedVisitor(AstNetlist* nodep, ChangedState* statep) {
m_topModp = NULL; m_statep = statep;
m_chgFuncp = NULL;
m_scopetopp = NULL;
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~ChangedVisitor() {} virtual ~ChangedVisitor() {}
@@ -187,5 +250,7 @@ public:
void V3Changed::changedAll(AstNetlist* nodep) { void V3Changed::changedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+6 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -238,6 +238,10 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureCleanAndNext (nodep->valuep()); insureCleanAndNext (nodep->valuep());
} }
virtual void visit(AstTypedef* nodep, AstNUser*) {
// No cleaning, or would loose pointer to enum
nodep->iterateChildren(*this);
}
// Control flow operators // Control flow operators
virtual void visit(AstNodeCond* nodep, AstNUser*) { virtual void visit(AstNodeCond* nodep, AstNUser*) {
@@ -288,4 +292,5 @@ public:
void V3Clean::cleanAll(AstNetlist* nodep) { void V3Clean::cleanAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
CleanVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -914,4 +914,5 @@ void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
// While the gater does well at some modules, it seems to slow down many others // 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"); UINFO(5,"ClkGater is disabled due to performance issues\n");
//GaterVisitor visitor (nodep); //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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+12 -148
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -99,18 +99,6 @@ private:
UINFO(4,"New Last: "<<newvscp<<endl); UINFO(4,"New Last: "<<newvscp<<endl);
return newvscp; 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) { AstNode* createSenItemEquation(AstSenItem* nodep) {
// We know the var is clean, and one bit, so we use binary ops // We know the var is clean, and one bit, so we use binary ops
// for speed instead of logical ops. // for speed instead of logical ops.
@@ -320,28 +308,6 @@ private:
} }
nodep->deleteTree(); nodep = NULL; 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*) { virtual void visit(AstCFunc* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Link to global function // Link to global function
@@ -365,13 +331,14 @@ private:
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_settleFuncp->addStmtsp(stmtsp); // else add to top level function 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*) { virtual void visit(AstActive* nodep, AstNUser*) {
// Careful if adding variables here, ACTIVES can be under other ACTIVES // Careful if adding variables here, ACTIVES can be under other ACTIVES
// Need to save and restore any member state in AstUntilStable block // Need to save and restore any member state in AstUntilStable block
if (nodep->hasInitial()) { if (!m_topScopep || !nodep->stmtsp()) {
moveInitial(nodep);
}
else if (!m_topScopep || !nodep->stmtsp()) {
// Not at the top or empty block... // Not at the top or empty block...
// Only empty blocks should be leftover on the non-top. Killem. // Only empty blocks should be leftover on the non-top. Killem.
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active"); if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
@@ -381,6 +348,7 @@ private:
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext(); AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
if (nodep->hasClocked()) { if (nodep->hasClocked()) {
// Remember the latest sensitivity so we can compare it next time // 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)) { if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) {
UINFO(4," sameSenseTree\n"); UINFO(4," sameSenseTree\n");
} else { } else {
@@ -392,6 +360,10 @@ private:
} }
// Move statements to if // Move statements to if
m_lastIfp->addIfsp(stmtsp); 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()) { } else if (nodep->hasSettle()) {
// Don't need to: clearLastSen();, as we're adding it to different cfunc // Don't need to: clearLastSen();, as we're adding it to different cfunc
// Move statements to function // Move statements to function
@@ -406,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 // Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
@@ -544,4 +407,5 @@ public:
void V3Clock::clockAll(AstNetlist* nodep) { void V3Clock::clockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ClockVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -474,4 +474,5 @@ public:
void V3Combine::combineAll(AstNetlist* nodep) { void V3Combine::combineAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
CombineVisitor visitor (nodep); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+5 -5
View File
@@ -6,7 +6,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -144,12 +144,12 @@ V3ConfigIgnores V3ConfigIgnores::s_singleton;
//###################################################################### //######################################################################
// V3Config // V3Config
void V3Config::addIgnore(V3ErrorCode code, string filename, int min, int max) { void V3Config::addIgnore(V3ErrorCode code, bool on, string filename, int min, int max) {
if (filename=="*") { if (filename=="*") {
FileLine::globalWarnOff(code,true); FileLine::globalWarnOff(code,!on);
} else { } else {
V3ConfigIgnores::singleton().addIgnore(code, filename, min, false); V3ConfigIgnores::singleton().addIgnore(code, filename, min, on);
if (max) V3ConfigIgnores::singleton().addIgnore(code, filename, max, true); if (max) V3ConfigIgnores::singleton().addIgnore(code, filename, max, !on);
} }
} }
+3 -2
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -24,12 +24,13 @@
#include "verilatedos.h" #include "verilatedos.h"
#include <string> #include <string>
#include "V3Error.h" #include "V3Error.h"
#include "V3FileLine.h"
//###################################################################### //######################################################################
class V3Config { class V3Config {
public: public:
static void addIgnore(V3ErrorCode code, string filename, int min, int max); static void addIgnore(V3ErrorCode code, bool on, string filename, int min, int max);
static void applyIgnores(FileLine* filelinep); static void applyIgnores(FileLine* filelinep);
}; };
+321 -44
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -106,7 +106,8 @@ private:
bool m_doShort; // Remove expressions that short circuit bool m_doShort; // Remove expressions that short circuit
bool m_doV; // Verilog, not C++ conversion bool m_doV; // Verilog, not C++ conversion
bool m_doGenerate; // Postpone width checking inside generate 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 AstNode* m_scopep; // Current scope
AstAttrOf* m_attrp; // Current attribute AstAttrOf* m_attrp; // Current attribute
@@ -172,6 +173,16 @@ private:
if (rnodep->width() != bnodep->width()) return false; if (rnodep->width() != bnodep->width()) return false;
return rnodep->lhsp()->castConst(); 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) { static bool operandAndOrSame(AstNode* nodep) {
// OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y)) // OR( AND(VAL,x), AND(VAL,y)) -> AND(VAL,OR(x,y))
// OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL) // OR( AND(x,VAL), AND(y,VAL)) -> AND(OR(x,y),VAL)
@@ -233,16 +244,19 @@ private:
} }
bool operandHugeShiftL(AstNodeBiop* nodep) { bool operandHugeShiftL(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst() return (nodep->rhsp()->castConst()
&& !nodep->rhsp()->castConst()->num().isFourState()
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()) && nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width())
&& isTPure(nodep->lhsp())); && isTPure(nodep->lhsp()));
} }
bool operandHugeShiftR(AstNodeBiop* nodep) { bool operandHugeShiftR(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst() return (nodep->rhsp()->castConst()
&& !nodep->rhsp()->castConst()->num().isFourState()
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()) && nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width())
&& isTPure(nodep->lhsp())); && isTPure(nodep->lhsp()));
} }
bool operandIsTwo(AstNode* nodep) { bool operandIsTwo(AstNode* nodep) {
return (nodep->castConst() return (nodep->castConst()
&& !nodep->castConst()->num().isFourState()
&& nodep->width() <= VL_QUADSIZE && nodep->width() <= VL_QUADSIZE
&& nodep->castConst()->toUQuad()==2); && 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 // 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. // 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() && 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->width()) return false;
if (nodep->width()!=lhsp->lhsp()->width()) return false; if (nodep->width()!=lhsp->lhsp()->width()) return false;
return true; return true;
@@ -327,27 +343,27 @@ private:
} }
bool operandBiExtendConst(AstNodeBiop* nodep) { bool operandBiExtendConst(AstNodeBiop* nodep) {
// Loop unrolling likes standalone compares // Loop unrolling favors standalone compares
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3}) // EQ(const{width32}, EXTEND(xx{width3})) -> EQ(const{3}, xx{3})
// Beware that the constant must have zero bits (+ 1 if signed) or compare // Beware that the constant must have zero bits (+ 1 if signed) or compare
// would be incorrect // would be incorrect
AstExtend* extendp = nodep->lhsp()->castExtend(); AstExtend* extendp = nodep->rhsp()->castExtend();
if (!extendp) return false; if (!extendp) return false;
AstNode* smallerp = extendp->lhsp(); AstNode* smallerp = extendp->lhsp();
int subsize = smallerp->width(); int subsize = smallerp->width();
AstConst* constp = nodep->rhsp()->castConst(); AstConst* constp = nodep->lhsp()->castConst();
if (!constp) return false; if (!constp) return false;
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false; if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
// //
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:"); if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
smallerp->unlinkFrBack(); smallerp->unlinkFrBack();
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp. extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
nodep->lhsp(smallerp); nodep->rhsp(smallerp);
constp->unlinkFrBack(); constp->unlinkFrBack();
V3Number num (constp->fileline(), subsize); V3Number num (constp->fileline(), subsize);
num.opAssign(constp->num()); num.opAssign(constp->num());
nodep->rhsp(new AstConst(constp->fileline(), num)); nodep->lhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); constp=NULL; constp->deleteTree(); constp=NULL;
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:"); if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
return true; return true;
@@ -412,12 +428,12 @@ private:
static bool operandsSame(AstNode* node1p, AstNode* node2p) { static bool operandsSame(AstNode* node1p, AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic // For now we just detect constants & simple vars, though it could be more generic
if (node1p->castConst() && node2p->castConst()) { if (node1p->castConst() && node2p->castConst()) {
return node1p->sameTree(node2p); return node1p->sameGateTree(node2p);
} }
else if (node1p->castVarRef() && node2p->castVarRef()) { else if (node1p->castVarRef() && node2p->castVarRef()) {
// Avoid comparing widthMin's, which results in lost optimization attempts // Avoid comparing widthMin's, which results in lost optimization attempts
// If cleanup sameTree to be smarter, this can be restored. // If cleanup sameGateTree to be smarter, this can be restored.
//return node1p->sameTree(node2p); //return node1p->sameGateTree(node2p);
return node1p->same(node2p); return node1p->same(node2p);
} else { } else {
return false; return false;
@@ -433,7 +449,7 @@ private:
AstVarRef* elsevarp = elsep->lhsp()->castVarRef(); AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
if (!ifvarp || !elsevarp) return false; if (!ifvarp || !elsevarp) return false;
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
if (!ifvarp->sameTree(elsevarp)) return false; if (!ifvarp->sameGateTree(elsevarp)) return false;
return true; return true;
} }
bool operandIfIf(AstNodeIf* nodep) { bool operandIfIf(AstNodeIf* nodep) {
@@ -444,6 +460,89 @@ private:
if (afterComment(lowerIfp->elsesp())) return false; if (afterComment(lowerIfp->elsesp())) return false;
return true; 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. // Constant Replacement functions.
@@ -525,7 +624,7 @@ private:
void replaceConstString (AstNode* oldp, const string& num) { void replaceConstString (AstNode* oldp, const string& num) {
// Replace oldp node with a constant set to specified value // Replace oldp node with a constant set to specified value
UASSERT (oldp, "Null old\n"); 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) oldp->dumpTree(cout," const_old: ");
if (debug()>5) newp->dumpTree(cout," _new: "); if (debug()>5) newp->dumpTree(cout," _new: ");
oldp->replaceWith(newp); oldp->replaceWith(newp);
@@ -538,6 +637,8 @@ private:
void replaceWChild(AstNode* nodep, AstNode* childp) { void replaceWChild(AstNode* nodep, AstNode* childp) {
// NODE(..., CHILD(...)) -> CHILD(...) // NODE(..., CHILD(...)) -> CHILD(...)
childp->unlinkFrBackWithNext(); 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); childp->dtypeFrom(nodep);
nodep->replaceWith(childp); nodep->replaceWith(childp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
@@ -660,6 +761,45 @@ private:
rrp->deleteTree(); rrp->deleteTree();
//nodep->dumpTree(cout, " repShiftSame_new: "); //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) { void replaceExtend (AstNode* nodep, AstNode* arg0p) {
// -> EXTEND(nodep) // -> EXTEND(nodep)
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node // like a AstExtend{$rhsp}, but we need to set the width correctly from base node
@@ -722,9 +862,15 @@ private:
AstNode* ap = lhsp->lhsp()->unlinkFrBack(); AstNode* ap = lhsp->lhsp()->unlinkFrBack();
AstNode* shift1p = lhsp->rhsp()->unlinkFrBack(); AstNode* shift1p = lhsp->rhsp()->unlinkFrBack();
AstNode* shift2p = nodep->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()) { 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->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. nodep->accept(*this); // Further reduce, either node may have more reductions.
} else { } else {
// We know shift amounts are constant, but might be a mixed left/right shift // 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 shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
int newshift = shift1+shift2; int newshift = shift1+shift2;
shift1p->deleteTree(); shift1p=NULL; shift1p->deleteTree(); shift1p=NULL;
shift2p->deleteTree(); shift1p=NULL; shift2p->deleteTree(); shift2p=NULL;
AstNode* newp; AstNode* newp;
V3Number mask1 (nodep->fileline(), nodep->width()); V3Number mask1 (nodep->fileline(), nodep->width());
V3Number ones (nodep->fileline(), nodep->width()); V3Number ones (nodep->fileline(), nodep->width());
@@ -778,7 +924,7 @@ private:
AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false; AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false;
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false; AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false;
AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) 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* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false;
AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false; AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
// We need to make sure there's no self-references involved in either // We need to make sure there's no self-references involved in either
@@ -866,10 +1012,10 @@ private:
} }
if (debug()>=9) nodep->dumpTree(cout," Ass_old: "); if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
// Unlink the stuff // Unlink the stuff
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack(); AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack(); AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
AstNode* conp = nodep->lhsp()->castConcat()->unlinkFrBack(); AstNode* conp = nodep->lhsp()->castConcat()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* rhs2p = rhsp->cloneTree(false); AstNode* rhs2p = rhsp->cloneTree(false);
// Calc widths // Calc widths
int lsb2 = 0; int lsb2 = 0;
@@ -938,6 +1084,64 @@ private:
// Further reduce, either node may have more reductions. // Further reduce, either node may have more reductions.
return true; 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)) { else if (replaceAssignMultiSel(nodep)) {
return true; return true;
} }
@@ -1219,27 +1423,60 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_attrp = oldAttr; 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*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->varp()) nodep->v3fatalSrc("Not linked"); if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
bool did=false; bool did=false;
if (m_doV && nodep->varp()->hasSimpleInit() && !m_attrp) { if (m_doV && nodep->varp()->valuep() && !m_attrp) {
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: "); //if (debug()) valuep->dumpTree(cout," visitvaref: ");
nodep->varp()->valuep()->iterateAndNext(*this); nodep->varp()->valuep()->iterateAndNext(*this); // May change nodep->varp()->valuep()
if (operandConst(nodep->varp()->valuep()) AstNode* valuep = nodep->varp()->valuep();
&& !nodep->lvalue() if (!nodep->lvalue()
&& ((!m_params // Can reduce constant wires into equations && ((!m_params // Can reduce constant wires into equations
&& m_doNConst && m_doNConst
&& v3Global.opt.oConst() && v3Global.opt.oConst()
&& !(nodep->varp()->isFuncLocal() // Default value, not a "known" constant for this usage && !(nodep->varp()->isFuncLocal() // Default value, not a "known" constant for this usage
&& nodep->varp()->isInput()) && nodep->varp()->isInput())
&& !nodep->varp()->noSubst()
&& !nodep->varp()->isSigPublic()) && !nodep->varp()->isSigPublic())
|| nodep->varp()->isParam())) { || nodep->varp()->isParam())) {
AstConst* constp = nodep->varp()->valuep()->castConst(); if (operandConst(valuep)) {
const V3Number& num = constp->num(); const V3Number& num = valuep->castConst()->num();
//UINFO(2,"constVisit "<<(void*)constp<<" "<<num<<endl); //UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
replaceNum(nodep, num); nodep=NULL; replaceNum(nodep, num); nodep=NULL;
did=true; 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) { if (!did && m_required) {
@@ -1435,7 +1672,7 @@ private:
AstSenItem* litemp = senp->castSenItem(); AstSenItem* litemp = senp->castSenItem();
AstSenItem* ritemp = cmpp->castSenItem(); AstSenItem* ritemp = cmpp->castSenItem();
if (litemp && ritemp) { 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())) { || (!litemp->varrefp() && !ritemp->varrefp())) {
// We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders // 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 if (( litemp->edgeType()==AstEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY
@@ -1592,8 +1829,9 @@ private:
string fmt = ""; string fmt = "";
bool inPct = false; bool inPct = false;
AstNode* argp = nodep->exprsp(); AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) { string text = nodep->text();
char ch = *inp; // Breaks with iterators... for (string::const_iterator it = text.begin(); it!=text.end(); ++it) {
char ch = *it;
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
@@ -1664,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 // These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any
// If output of a presel didn't get consted, chances are V3Param didn't visit properly // If output of a presel didn't get consted, chances are V3Param didn't visit properly
@@ -1709,6 +1951,12 @@ private:
//----- //-----
// Below lines are magic expressions processed by astgen // 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 // "AstNODETYPE { # bracket not paren
// $accessor_name, ... // $accessor_name, ...
// # ,, gets replaced with a , rather than && // # ,, gets replaced with a , rather than &&
@@ -1749,8 +1997,14 @@ private:
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstPow {$rhsp.isZero}", "replaceNum(nodep, 1)"); // Overrides lhs zero rule
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); 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 ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)"); TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
@@ -1789,7 +2043,7 @@ private:
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n 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 ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a 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 // Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump! // Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)"); TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
@@ -1812,6 +2066,14 @@ private:
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)"); TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)"); TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(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 // v--- *1* as These ops are always first, as we warn before replacing
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)"); TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)"); TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
@@ -1823,7 +2085,7 @@ private:
TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)"); TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)");
// Two level bubble pushing // Two level bubble pushing
TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==$lhsp->castNot()->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x 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()}"); TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEqCase}", "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()}"); TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
@@ -1861,12 +2123,12 @@ private:
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)"); TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)"); TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
// Compress out EXTENDs to appease loop unroller // Compress out EXTENDs to appease loop unroller
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE"); TREEOPV("AstEq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE"); TREEOPV("AstNeq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE"); TREEOPV("AstGt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE"); TREEOPV("AstGte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE"); TREEOPV("AstLt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE"); TREEOPV("AstLte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
// Identical operands on both sides // Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules // AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon // AstAdd->ShiftL(#,1) but uncommon
@@ -1880,22 +2142,28 @@ private:
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP ("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 ("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 ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtD {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 ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteD {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 ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtD {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 ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteD {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 ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {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 ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
@@ -1936,6 +2204,9 @@ private:
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c})) // CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)"); TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())"); 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 // Common two-level operations that can be simplified
TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)"); TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
@@ -1943,11 +2214,12 @@ private:
TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
TREEOP ("AstXor {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 // 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("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, nodep->lhsp()->castExtend()->lhsp())");
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->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("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 // Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy. // to pins, even when the widths are exactly the same across the hierarchy.
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE"); TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
@@ -2028,6 +2300,7 @@ public:
m_warn = false; m_warn = false;
m_wremove = true; // Overridden in visitors m_wremove = true; // Overridden in visitors
m_modp = NULL; m_modp = NULL;
m_selp = NULL;
m_scopep = NULL; m_scopep = NULL;
m_attrp = NULL; m_attrp = NULL;
// //
@@ -2110,12 +2383,14 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_WARN); ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
void V3Const::constifyCpp(AstNetlist* nodep) { void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_CPP); ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const_cpp.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
AstNode* V3Const::constifyEdit(AstNode* nodep) { AstNode* V3Const::constifyEdit(AstNode* nodep) {
@@ -2131,6 +2406,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_LIVE); ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
void V3Const::constifyAll(AstNetlist* nodep) { void V3Const::constifyAll(AstNetlist* nodep) {
@@ -2138,6 +2414,7 @@ void V3Const::constifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE); ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) { 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+64 -10
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -60,9 +60,14 @@ private:
} }
}; };
// NODE STATE
// Entire netlist:
// AstIf::user1() -> bool. True indicates ifelse processed
AstUser1InUse m_inuser1;
// STATE // STATE
bool m_checkBlock; // Should this block get covered? bool m_checkBlock; // Should this block get covered?
AstNodeModule* m_modp; // Current module to add statement to AstNodeModule* m_modp; // Current module to add statement to
bool m_inToggleOff; // In function/task etc bool m_inToggleOff; // In function/task etc
bool m_inModOff; // In module with no coverage bool m_inModOff; // In module with no coverage
FileMap m_fileps; // Column counts for each fileline FileMap m_fileps; // Column counts for each fileline
@@ -213,7 +218,7 @@ private:
} }
} }
else if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) { 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(); int index_code = index_docs - adtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]", ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code), new AstArraySel(varp->fileline(), above.m_varRefp->cloneTree(true), index_code),
@@ -224,6 +229,50 @@ private:
newent.cleanup(); 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 { else {
dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "<<dtypep->prettyTypeName()); dtypep->v3fatalSrc("Unexpected node data type in toggle coverage generation: "<<dtypep->prettyTypeName());
} }
@@ -233,12 +282,18 @@ private:
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
UINFO(4," IF: "<<nodep<<endl); UINFO(4," IF: "<<nodep<<endl);
if (m_checkBlock) { if (m_checkBlock) {
// An else-if. When we iterate the if, use "elsif" marking
bool elsif = (nodep->elsesp()->castIf()
&& !nodep->elsesp()->castIf()->nextp());
if (elsif) nodep->elsesp()->castIf()->user1(true);
//
nodep->ifsp()->iterateAndNext(*this); nodep->ifsp()->iterateAndNext(*this);
if (m_checkBlock && !m_inModOff if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it && nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
if (!nodep->backp()->castIf() UINFO(4," COVER: "<<nodep<<endl);
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier if (nodep->user1()) {
UINFO(4," COVER: "<<nodep<<endl); nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif"));
} else {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if")); nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if"));
} }
} }
@@ -249,9 +304,7 @@ private:
if (m_checkBlock && !m_inModOff if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it && nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
UINFO(4," COVER: "<<nodep<<endl); UINFO(4," COVER: "<<nodep<<endl);
if (nodep->elsesp()->castIf()) { if (!elsif) { // elsif done inside if()
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "elsif"));
} else {
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "else")); nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "else"));
} }
} }
@@ -342,4 +395,5 @@ public:
void V3Coverage::coverage(AstNetlist* rootp) { void V3Coverage::coverage(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
CoverageVisitor visitor (rootp); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -135,4 +135,5 @@ public:
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) { void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
CoverageJoinVisitor visitor (rootp); 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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+26 -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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -81,6 +81,7 @@ private:
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap; typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE // STATE
AstNodeModule* m_modp; // Current module
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree 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 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 AssignMap m_assignMap; // List of all simple assignments for each variable
@@ -103,13 +104,21 @@ private:
} }
void checkDType(AstNodeDType* nodep) { void checkDType(AstNodeDType* nodep) {
if (!nodep->generic() // Don't remove generic types if (!nodep->generic() // Don't remove generic types
&& m_elimDTypes) { // dtypes stick around until post-widthing && m_elimDTypes // dtypes stick around until post-widthing
&& !nodep->castMemberDType() // Keep member names iff upper type exists
) {
m_varEtcsp.push_back(nodep); m_varEtcsp.push_back(nodep);
} }
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc(); if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep, AstNUser*) {
m_modp = nodep;
nodep->iterateChildren(*this);
checkAll(nodep);
m_modp = NULL;
}
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
@@ -156,6 +165,13 @@ private:
nodep->packagep()->user1Inc(); 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*) { virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
@@ -166,6 +182,7 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep); checkAll(nodep);
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
if (mightElim(nodep)) { if (mightElim(nodep)) {
m_varEtcsp.push_back(nodep); m_varEtcsp.push_back(nodep);
} }
@@ -221,7 +238,9 @@ private:
bool mightElim(AstVar* nodep) { bool mightElim(AstVar* nodep) {
return (!nodep->isSigPublic() // Can't elim publics! return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO() && !nodep->isIO()
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars)); && (nodep->isTemp()
|| (nodep->isParam() && !nodep->isTrace())
|| m_elimUserVars)); // Post-Trace can kill most anything
} }
void deadCheckVar() { void deadCheckVar() {
// Delete any unused varscopes // Delete any unused varscopes
@@ -249,6 +268,7 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) { DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
m_modp = NULL;
m_elimUserVars = elimUserVars; m_elimUserVars = elimUserVars;
m_elimDTypes = elimDTypes; m_elimDTypes = elimDTypes;
m_sideEffect = false; m_sideEffect = false;
@@ -271,12 +291,15 @@ public:
void V3Dead::deadifyModules(AstNetlist* nodep) { void V3Dead::deadifyModules(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, false); DeadVisitor visitor (nodep, false, false);
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
} }
void V3Dead::deadifyDTypes(AstNetlist* nodep) { void V3Dead::deadifyDTypes(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true); DeadVisitor visitor (nodep, false, true);
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
} }
void V3Dead::deadifyAll(AstNetlist* nodep) { void V3Dead::deadifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true); DeadVisitor visitor (nodep, true, true);
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+11 -8
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 // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -118,7 +118,7 @@ private:
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<<nodep->varp()->prettyName()); 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 // Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped"); if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
AstVar* varp; AstVar* varp;
@@ -129,7 +129,9 @@ private:
// Created module's AstVar earlier under some other scope // Created module's AstVar earlier under some other scope
varp = it->second; varp = it->second;
} else { } 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 = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
varp->dtypeFrom(oldvarscp); varp->dtypeFrom(oldvarscp);
} else { // Used for vset and dimensions, so can zero init } else { // Used for vset and dimensions, so can zero init
@@ -219,7 +221,7 @@ private:
} else { } else {
string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension) string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension)
+"__"+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); +"__"+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width()); AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), NULL);
AstAssign* bitassignp AstAssign* bitassignp
= new AstAssign (nodep->fileline(), = new AstAssign (nodep->fileline(),
new AstVarRef(nodep->fileline(), bitvscp, true), new AstVarRef(nodep->fileline(), bitvscp, true),
@@ -237,7 +239,7 @@ private:
bitreadp = lsbvaluep; bitreadp = lsbvaluep;
} else { } else {
string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); 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(), AstAssign* bitassignp = new AstAssign (nodep->fileline(),
new AstVarRef(nodep->fileline(), bitvscp, true), new AstVarRef(nodep->fileline(), bitvscp, true),
lsbvaluep); lsbvaluep);
@@ -252,7 +254,7 @@ private:
valreadp = nodep->rhsp()->unlinkFrBack(); valreadp = nodep->rhsp()->unlinkFrBack();
} else { } else {
string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); 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); newlhsp = new AstVarRef(nodep->fileline(), valvscp, true);
valreadp = new AstVarRef(nodep->fileline(), valvscp, false); valreadp = new AstVarRef(nodep->fileline(), valvscp, false);
} }
@@ -270,7 +272,7 @@ private:
++m_statSharedSet; ++m_statSharedSet;
} else { // Create new one } else { // Create new one
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1); setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, NULL);
setinitp = new AstAssignPre (nodep->fileline(), setinitp = new AstAssignPre (nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true), new AstVarRef(nodep->fileline(), setvscp, true),
new AstConst(nodep->fileline(), 0)); new AstConst(nodep->fileline(), 0));
@@ -399,7 +401,7 @@ private:
} }
if (!dlyvscp) { // First use of this delayed variable if (!dlyvscp) { // First use of this delayed variable
string newvarname = (string("__Vdly__")+nodep->varp()->shortName()); string newvarname = (string("__Vdly__")+nodep->varp()->shortName());
dlyvscp = createVarSc(oldvscp, newvarname, 0); dlyvscp = createVarSc(oldvscp, newvarname, 0, NULL);
AstNodeAssign* prep AstNodeAssign* prep
= new AstAssignPre (nodep->fileline(), = new AstAssignPre (nodep->fileline(),
new AstVarRef(nodep->fileline(), dlyvscp, true), new AstVarRef(nodep->fileline(), dlyvscp, true),
@@ -469,4 +471,5 @@ public:
void V3Delayed::delayedAll(AstNetlist* nodep) { void V3Delayed::delayedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
DelayedVisitor visitor (nodep); 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