Compare commits

...
349 Commits
Author SHA1 Message Date
Wilson Snyder a8432ed4a4 Version bump 2012-03-07 22:50:13 -05:00
Wilson Snyder 04f910b747 Fix V3Tristate t_tri_select crash 2012-03-07 22:42:47 -05:00
Wilson Snyder 1c3de70155 Internals: Debug merge. No functional change 2012-03-07 21:48:02 -05:00
Wilson Snyder b73642f8a8 Report ENDLABEL on mismatching end labels, bug450. 2012-03-07 20:14:18 -05:00
Wilson Snyder 479b497528 Tests: Add new tests from Iztok Jeras, bug446, bug450. 2012-03-07 20:00:09 -05:00
Wilson Snyder 31b55d3844 Tests: Fix running different simulators simultaneously 2012-03-06 20:58:23 -05:00
Wilson Snyder dbf4e08d09 Tests 2012-03-06 20:12:47 -05:00
Wilson Snyder 274359e6ee Tests: Bit extraction from non-logic types 2012-03-04 17:17:57 -05:00
Wilson Snyder 8687dcbce1 Internals: Add isRanged, more debug. No functional change. 2012-03-04 16:18:41 -05:00
Wilson Snyder 03dfbdb7b1 Fix inheriting signed type across untyped parameters. 2012-03-03 21:03:34 -05:00
Wilson Snyder 3c8519f245 Fix inheriting real type across untyped parameters. 2012-03-03 16:29:06 -05:00
Wilson Snyder 4d2cc3ebdd Tests: New param value test 2012-03-03 15:44:56 -05:00
Wilson Snyder 6e2758ae26 Internals: Minor refactorings from dtype branch. No functional change. 2012-03-03 12:10:29 -05:00
Wilson Snyder 4637e06ad2 Fix backward widths in function output warning 2012-03-03 12:09:01 -05:00
Wilson Snyder 764399256c Internals: Rename gdb dump utilities, add fileline dump 2012-03-03 11:29:09 -05:00
Wilson Snyder f4ca4edc64 Debug: Add default .gdbinit file 2012-03-02 20:59:47 -05:00
Wilson Snyder 872a1216a7 Internals: Fix enum widthTotalBytes. 2012-03-02 06:58:19 -05:00
Wilson Snyder 8c75674591 Internals: V3Dead: Avoid iterating over vars we can't remove. 2012-02-29 23:05:11 -05:00
Wilson Snyder e6244ca204 Internals: Move dimension accessors from AstVar to AstNodeDType. 2012-02-28 21:33:17 -05:00
Wilson Snyder f540362e36 Fix expansion of back-slashed escaped macros, bug441. 2012-02-25 21:31:36 -05:00
Wilson Snyder 2be6699a6a Internals: Make covergroup parsing closer to normal types 2012-02-23 22:09:51 -05:00
Wilson Snyder 09c10492ab Fix hang on recursive substitution `defines, bug443. 2012-02-23 21:54:37 -05:00
Wilson Snyder c8e4b1fc84 Fix functions inside generate for block. 2012-02-21 22:23:06 -05:00
Wilson Snyder 0de7cece5b Fix hang when functions inside begin block. 2012-02-21 21:25:11 -05:00
Wilson Snyder a3413a6749 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2012-02-21 08:03:07 -05:00
Wilson Snyder b104ab9491 Internals: AstRefDType points to type _below_ AstTyperef. No functional change 2012-02-21 07:27:17 -05:00
Wilson Snyder 269c5dce60 Internals: Use dtypeChgLogicBool(). No functional change. 2012-02-20 20:51:24 -05:00
Wilson Snyder a39c81c63f Internals: Remove width() on AstCaseItem. No functional change. 2012-02-20 16:48:52 -05:00
Wilson Snyder d699247269 Internals: In AstBasicDType avoid use of Range for constants. No functional change. 2012-02-20 11:48:31 -05:00
Wilson Snyder 7caafb4014 Internals: Use dtype functions; changes to integer to match spec 2012-02-20 09:55:20 -05:00
Wilson Snyder f1546abf09 Fix error when using UDPs without --bbox-unsup 2012-02-20 09:02:59 -05:00
Wilson Snyder 3083562f6f tests: Avoid massive make parallelism. 2012-02-17 21:40:52 -05:00
Wilson Snyder da2ee70462 Makefile: Print build done in right parallel spot 2012-02-16 20:39:13 -05:00
Wilson Snyder 7e9dda3c5e Fix false command not found warning in Makefiles. 2012-02-16 07:17:08 -05:00
Wilson Snyder 0b96f88875 Fix bisonpre documentation 2012-02-12 20:53:43 -05:00
Wilson Snyder f13ffe2098 Internals: Merge from VHDL branch. Minor stuff, no functional change. 2012-02-11 20:40:58 -05:00
Wilson Snyder bca5d26583 Backout ca927fe5; snps isn't supported in DC. 2012-02-10 22:36:19 -05:00
Wilson Snyder 660bc757f1 Tests: Remove debug 2012-02-04 20:00:36 -05:00
Wilson Snyder ca927fe587 Support snps directives 2012-02-02 10:26:45 -05:00
Wilson Snyder 9df8966f4a Support arrayed SystemC I/O pins. 2012-02-01 20:20:43 -05:00
Wilson Snyder 3429f41489 Typo 2012-01-29 18:26:39 -05:00
Wilson Snyder 0c7c4924ee Fix core dump with over 100 deep UNOPTFLAT, bug432. 2012-01-26 20:20:23 -05:00
Wilson Snyder 8f40d6617e For generated variables, opt towards 2-state so zero init 2012-01-26 08:29:55 -05:00
Wilson Snyder af9e85bda1 Fix memory delayed assignments from multiple clock domains. 2012-01-26 08:10:50 -05:00
Wilson Snyder 717f45d117 Devel version 2012-01-25 19:23:58 -05:00
Wilson Snyder 35c53865fb Check c style array 2012-01-25 19:23:41 -05:00
Wilson Snyder a1d1d6d3d4 Version bump 2012-01-20 07:02:39 -05:00
Wilson Snyder d17f812827 Fix BLKSEQ warnings on variables declared inside always. 2012-01-19 21:15:21 -05:00
Wilson Snyder 3916758529 readme.texi is very old 2012-01-19 20:32:32 -05:00
Wilson Snyder 2396181bc5 Add SYSTEMC_INCLUDE and SYSTEMC_LIBDIR 2012-01-19 20:30:41 -05:00
Wilson Snyder 6e8640bf1b SystemC 2.3.0 support 2012-01-19 19:48:37 -05:00
Wilson Snyder c2c7c7bd9a Copyright year update 2012-01-15 10:26:28 -05:00
Wilson Snyder 071a1c4adb Internals: Fix cppcheck warning 2011-12-27 12:15:20 -05:00
Wilson Snyder d5b2dda2e8 Fix loop iterator 2011-12-26 18:32:40 -05:00
Wilson Snyder 2ac281eb3e Commentary 2011-12-23 19:32:56 -05:00
Wilson Snyder 5e81543448 Internals: Use width when widthMin is the same. No functional change intended 2011-12-22 21:10:28 -05:00
Wilson Snyder b32f925468 Internals: remove extra width sets 2011-12-22 19:08:49 -05:00
Wilson Snyder fdeb6bcae0 Internals: Progress towards proper short-circuit evaluation 2011-12-22 08:33:16 -05:00
Wilson Snyder 76232cd9e7 Internals: Separate pure from branching. No functional change. 2011-12-15 22:23:11 -05:00
Wilson Snyder 4da9b5e491 Internals: Rename isSplittable->isPure. No functional change 2011-12-15 19:13:54 -05:00
Wilson Snyder c4504a9221 tests: Fix t_dist_install breaking corunning test 2011-12-15 18:39:51 -05:00
Wilson Snyder 65de8359e7 Internals: Comment out unused code, no funtional change 2011-12-15 18:39:29 -05:00
Wilson Snyder f6fab74436 tests: GHDL test driver support 2011-12-09 19:58:14 -05:00
Wilson Snyder 350ba264e8 Internals: Create bools/doubles with dtypeChg functions. No functional change. 2011-11-30 19:32:33 -05:00
Wilson Snyder 29e24818a1 Internals: Rename and cleanup some width() usages. No functional change. 2011-11-30 18:50:21 -05:00
Wilson Snyder 71cd6f7b90 Spelling fixes 2011-11-30 18:20:19 -05:00
Wilson Snyder 84ba253791 Last commit - don't allow error overrides if not lint 2011-11-30 18:07:11 -05:00
Wilson Snyder fce158b8ad Make DETECTARRAY so can turn off for lint 2011-11-30 16:20:43 -05:00
Wilson Snyder da13ba6c67 Internals: Use elementsConst for AstRange width. 2011-11-30 07:51:05 -05:00
Wilson Snyder 7618133298 Internals: Renames towards common dtype. No functional change. 2011-11-29 22:36:51 -05:00
Wilson Snyder 0d1698f81d Internals: Allow v3Global in V3Ast.h. No functional change. 2011-11-29 22:29:16 -05:00
Wilson Snyder 362d642c87 Support "generate for (genvar i=0; ...". 2011-11-29 18:23:18 -05:00
Wilson Snyder e4c96d5be5 Fix array of instantiations with sub-range output, bug414. 2011-11-28 22:10:43 -05:00
Wilson Snyder f488701adc Fix dpi exports with > 32 bit but < 64 bit args, bug423. 2011-11-28 21:15:57 -05:00
Wilson Snyder 8ff2bf51c5 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-11-28 09:48:14 -05:00
Wilson Snyder a2490a55a9 tests: Test $countones on other simulators 2011-11-28 09:48:01 -05:00
Wilson Snyder 20189f5191 Fix empty generate region, bug422. 2011-11-28 07:49:36 -05:00
Wilson Snyder 06b796c6bd Suppress VARHIDDEN on dpi import arguments. 2011-11-27 12:03:22 -05:00
Wilson Snyder ad4edf6c68 Postrelease 2011-11-27 10:39:30 -05:00
Wilson Snyder 4100f20a69 Version bump 2011-11-27 10:37:23 -05:00
Wilson Snyder bedf946fb2 Support V-AMS wreal 2011-11-27 10:31:06 -05:00
Wilson Snyder b9e67157c6 With "--language VAMS" support a touch of Verilog AMS. 2011-11-25 00:49:38 -05:00
Wilson Snyder b30b2a183b Support . 2011-11-20 02:01:48 -05:00
Wilson Snyder 9ab3bcdde3 Support with %g. 2011-11-20 01:01:02 -05:00
Wilson Snyder 5df3bbe188 Fix $display with %d following %g. 2011-11-20 00:45:59 -05:00
Wilson Snyder 8cf12416c0 Commentary 2011-11-18 13:33:31 -05:00
Wilson Snyder b7c2c83c88 Fix bad result with if-else-return optimization, bug420. 2011-11-12 08:07:30 -05:00
Wilson Snyder 3b6da93331 Reuse goto labels inside functions, bug420a 2011-11-10 19:13:32 -05:00
Wilson Snyder b4642d3fd4 Show examples with timestamps as 64 bits 2011-11-06 11:54:17 -05:00
Wilson Snyder 88a2b0b911 Support constants in sensitivity lists, bug412. 2011-11-02 18:34:17 -04:00
Wilson Snyder 954e127f1d Commentary: Report children node types 2011-11-01 19:33:11 -04:00
Wilson Snyder 7654add5e5 Indicate 'exiting due to errors' if errors, not warnings. 2011-10-31 21:39:15 -04:00
Wilson Snyder 85a37ea53f Search for user -y paths before default current directory. 2011-10-28 18:57:40 -04:00
Wilson Snyder b337acebcc When multiple tops, show example 2011-10-28 18:19:04 -04:00
Wilson Snyder fb9ca54c95 Fix reporting not found modules if generate-off, bug403. 2011-10-27 20:56:38 -04:00
Wilson Snyder 1a15d41523 Support jumps in program modules 2011-10-27 19:13:24 -04:00
Wilson Snyder e378cc5791 Add sc_bv attribute to force bit vectors, bug402. 2011-10-26 08:57:27 -04:00
Wilson Snyder 748c189c79 Devel version 2011-10-25 19:11:45 -04:00
Wilson Snyder b89be6c4b9 Version bump 2011-10-25 18:59:40 -04:00
Wilson Snyder df207807b6 Add ASSIGNIN as suppressable error. 2011-10-25 18:57:49 -04:00
Wilson Snyder 1f2b40cff1 Fix 3.823 constructor core dump on Debian, bug401. 2011-10-25 18:41:04 -04:00
Wilson Snyder 734400fd37 Fix version number mistake 2011-10-25 18:11:06 -04:00
Wilson Snyder f19979d928 Fix "always @ (* )", bug403, bug404. 2011-10-25 18:08:24 -04:00
Wilson Snyder 19be7a53da List unsupported on delays 2011-10-21 07:13:38 -04:00
Wilson Snyder e56af34fb0 Post release 2011-10-20 21:18:16 -04:00
Wilson Snyder 7737aa20e8 Version bump 2011-10-20 21:13:42 -04:00
Wilson Snyder ead046201c Fix make info tex warning 2011-10-20 21:13:33 -04:00
Wilson Snyder 0aa7c3f659 Add -Wall reporting ASSIGNDLY on assignment delays. 2011-10-20 20:50:42 -04:00
Wilson Snyder 4aa7222022 tests: use verilator_flags and skip more widely 2011-10-12 23:03:53 -04:00
Wilson Snyder 86e3c78776 configure: Test for compiler flags, and remove old config checks 2011-10-12 19:04:57 -04:00
Wilson Snyder 40076287ea Internals: In .tree files show filename as letter 2011-10-11 07:17:39 -04:00
Wilson Snyder ca81db8edf Remove dead node types; make report of node usage. No functional change 2011-10-10 18:13:42 -04:00
Wilson Snyder ae68a80e98 Fix fflush 2011-10-10 18:13:17 -04:00
Wilson Snyder beb7c58375 Fix DPI import false BLKSEQ warnings. 2011-10-07 20:04:15 -04:00
Wilson Snyder e080b9d565 Fix DPI import output of 64 bits, bug398. 2011-10-07 19:47:10 -04:00
Wilson Snyder ca2db37039 Fix UNDRIVEN warnings inside DPI import functions. 2011-10-07 08:29:34 -04:00
Wilson Snyder 194825f78e Add configure options for cc warnings and extended tests. 2011-10-07 06:48:40 -04:00
Wilson Snyder 55bd765ea0 Find config_rev when under git in remote config dir 2011-10-05 18:36:44 -04:00
Wilson Snyder b03d61e2cf Use EXEEXT to fix make warning 2011-10-05 17:07:10 -04:00
Wilson Snyder 6fc0e5167b Commentary 2011-10-05 17:06:08 -04:00
Wilson Snyder 0065be011f Fix errors when building from git outside of kit directory 2011-10-05 10:47:05 -04:00
Wilson Snyder 3f7cbce58c Move version to configure.ac 2011-10-05 09:50:14 -04:00
Wilson Snyder 246b62e322 Tests: Add runtime 2011-10-05 09:50:00 -04:00
Wilson Snyder 7c2fdd1ee9 Fix --help output to go to stderr, not stdout, bug397. 2011-10-04 10:08:16 -04:00
Wilson Snyder f77aa2623c Fix autoconf suggestions 2011-10-04 10:07:46 -04:00
Wilson Snyder 20847a3ff5 Fix autoconf warnings, bug396. 2011-10-04 08:48:37 -04:00
Wilson Snyder eb6d42acf9 Support $ceil, $floor, etc. 2011-09-28 21:35:26 -04:00
Wilson Snyder 094d676a8b Fix MSVC compile warning with trunc/round, bug394. 2011-09-21 09:08:05 -04:00
Wilson Snyder 71306ceb1d Devel version 2011-09-14 21:44:54 -04:00
Wilson Snyder 8bbfc7fc22 Version bump 2011-09-14 21:12:40 -04:00
Wilson Snyder 19baba12b1 Commentary 2011-09-14 21:11:14 -04:00
Wilson Snyder 15b8819136 Avoid warning on older flex/gcc systems (lion) 2011-09-12 20:26:34 -04:00
Wilson Snyder 3fae8ade05 Fix PowerPC runtime error, bug288 2011-08-22 21:02:09 -04:00
Wilson Snyder f9bbf31d65 Fix internal error on integer casts, bug374. 2011-08-09 19:56:22 -04:00
Wilson Snyder df1da3dda9 Internals: Fix cppcheck warnings; no functional change intended 2011-08-04 21:58:45 -04:00
Wilson Snyder c83f2a4abd Internals: Fix preincrements to reduce cppcheck warnings 2011-08-04 21:15:24 -04:00
Wilson Snyder ad53833040 Version bump 2011-07-28 19:53:54 -04:00
Wilson Snyder bc8c85668a Support coverage in -cc and -sc output modes. 2011-07-28 19:41:05 -04:00
Wilson Snyder d12a3dde45 Fix cast compile warning 2011-07-28 07:59:30 -04:00
Wilson Snyder 301c878c0f Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-28 07:56:44 -04:00
Wilson Snyder bd55bfa071 Support more vpi file functions 2011-07-28 07:05:40 -04:00
Wilson Snyder 6d2f09b579 Fix vpi_register_cb using bad s_cb_data, bug370. 2011-07-27 13:03:49 -04:00
Wilson Snyder 4bfea7f54d Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-26 18:30:25 -04:00
Wilson Snyder 55906486d8 Support 'real' numbers and related functions. 2011-07-24 15:01:51 -04:00
Wilson Snyder d5478e6e08 tests: Print status to stderr 2011-07-24 15:01:36 -04:00
Wilson Snyder d88d85c172 Internals: Real2: Create numeric class; no functional change intended 2011-07-23 19:58:34 -04:00
Wilson Snyder 59c3c536c7 Internals: Real1: properly lex doubles 2011-07-23 08:25:41 -04:00
Wilson Snyder a007458cb8 Internals: Rename float/double to match real branch. No functional change. 2011-07-21 22:10:25 -04:00
Wilson Snyder d051912f21 Internals: Rename functions to match real branch. No functional change. 2011-07-21 21:32:31 -04:00
Wilson Snyder a547158a50 bisonpre: Merge from Verilog-Perl 2011-07-21 20:34:33 -04:00
Wilson Snyder 95f2351aa0 Tests: %t formatting 2011-07-21 19:37:53 -04:00
Wilson Snyder 698aaffb0b Fix missing leading zeros in %0d, bug367 2011-07-14 07:39:11 -04:00
Wilson Snyder 73eccecbf8 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-11 08:10:28 -04:00
Wilson Snyder ae4a261463 Internals: Rename UnaryMin to Negate. No functional change. 2011-07-08 06:03:07 -04:00
Wilson Snyder c9f0d0cec2 Recognize pragma synthesys to match vhier 2011-07-07 13:30:27 -04:00
Wilson Snyder 4fa1e45d45 Internals: Move width internals to inside class; move WidthCommit. No functional change 2011-07-06 19:03:40 -04:00
Wilson Snyder 1b3d252bfe Internals: Cleanup Dead code 2011-07-06 18:46:41 -04:00
Wilson Snyder a9ba4a9fcd Internals: Cleanups in V3Signed towards reals; no functional change 2011-07-05 21:05:35 -04:00
Wilson Snyder 7f49619875 Fix VL_FCLOSE declaration, broke two commits ago, bug363 2011-07-05 20:42:33 -04:00
Wilson Snyder 696660639a Support 'const' variables in limited cases; similar to enums. 2011-07-02 12:45:26 -04:00
Wilson Snyder da4323062d Commentary 2011-07-01 15:23:09 -04:00
Wilson Snyder a901e171b2 Support $fopen and I/O with integer instead of `verilator_file_descriptor. 2011-07-01 13:41:21 -04:00
Wilson Snyder 6e41d532fe Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++. 2011-06-29 19:19:01 -04:00
Wilson Snyder 4fc78ffb58 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-06-29 14:22:59 -04:00
Wilson Snyder 8137f41fc3 Support disable for loop escapes. 2011-06-28 21:26:49 -04:00
Wilson Snyder 2e9471797d Version to devel 2011-06-28 21:11:29 -04:00
Wilson Snyder 344248cea0 Version bump 2011-06-28 20:52:04 -04:00
Wilson Snyder 2789e3dba5 Fix 96 bit DPI input/outputs, bug359 2011-06-28 20:45:50 -04:00
Wilson Snyder cca759a41e Tests: Example embedding 2011-05-22 08:43:36 -04:00
Wilson Snyder 4f7b3d8882 Fix out of memory on slice syntax error, bug354. 2011-05-21 08:19:33 -04:00
Wilson Snyder 2b330b78b7 Support bit vectors > 64 bits wide in DPI import and exports. 2011-05-20 21:33:31 -04:00
Wilson Snyder d47ca1912b tests: Fix invocation scripts for new site standard 2011-05-20 20:47:15 -04:00
Wilson Snyder 3fd2108b10 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 15:34:30 -04:00
Wilson Snyder 96e2a407f4 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 13:40:18 -04:00
Wilson Snyder cdf18c96f4 driver: Allow getting verilator flags in tests 2011-05-19 21:25:23 -04:00
Wilson Snyder 53acaa05b8 Commentary 2011-05-18 07:10:12 -04:00
Wilson Snyder fb85679068 Fix DPI bit vector compile errors, bug347. 2011-05-12 07:35:28 -04:00
Wilson Snyder 9558e14479 Fix DPI undeclared svBitVecVal compile error, bug346. Additional change. 2011-05-12 06:59:13 -04:00
Wilson Snyder 4af0af93bf Fix DPI undeclared svBitVecVal compile error, bug346. 2011-05-12 06:32:29 -04:00
Wilson Snyder df4bc950fe Cleanup trailing whitespace 2011-05-09 23:58:38 -04:00
Wilson Snyder 250394f72b Fix compiler warnings on SPARC, bug288 2011-05-09 23:49:17 -04:00
Wilson Snyder ca83fd6dc1 CDC: edge report under debug 2011-04-20 10:11:35 -04:00
Wilson Snyder d5e9e7cd2b Remove dead code 2011-04-19 19:02:03 -05:00
Wilson Snyder 9a96f621ef Fix CDCRSTLOGIC report showing endpoint flops without resets. 2011-04-18 10:47:02 -04:00
Wilson Snyder 5d7ce096c6 Fix error on enum references to other packages, bug339. 2011-04-13 19:34:14 -04:00
Wilson Snyder c9f8109c06 Pre-version 2011-04-13 19:33:58 -04:00
Wilson Snyder a20b4f2864 Version bump 2011-04-06 07:33:44 -04:00
Wilson Snyder 44a19d2a0a Fix missing test files 2011-04-06 07:33:32 -04:00
Wilson Snyder 02f3beb8db Add V3Number rotate functions; unused as yet 2011-03-30 21:31:29 -04:00
Wilson Snyder 3269cc3d90 Add +libext+.sv default 2011-03-30 21:30:36 -04:00
Wilson Snyder fb70a1f4ab Add --Wno-fatal to turn off abort on warnings. 2011-03-22 18:09:39 -04:00
Wilson Snyder df0aa483ce Support ${...} and $(...) env variables in .vc files 2011-03-21 12:25:31 -04:00
Wilson Snyder c83f12a55c Support simple cast operators, bug335. 2011-03-17 22:25:49 -04:00
Wilson Snyder 9704f59566 Internals: Rename AstCast to AstCCast 2011-03-17 21:09:52 -04:00
Wilson Snyder 2923893d34 Support loop unrolling on width mismatches, bug 333 2011-03-12 07:45:04 -05:00
Wilson Snyder 890dab0742 Write logfile on each failure 2011-03-12 07:44:29 -05:00
Wilson Snyder 607e26b041 Commentary 2011-03-08 06:49:45 -05:00
Wilson Snyder ea75290f65 Add error on circular parameter definitions, bug329 2011-03-07 20:44:19 -05:00
Wilson Snyder a176054118 Add --trace-max-width and --trace-max-array, bug 319. 2011-02-23 21:58:27 -05:00
Wilson Snyder 9a697dc5f5 Accelerate bit-selected inversions. 2011-02-23 21:36:38 -05:00
Wilson Snyder cfdb852843 Fix concatenates and vectored bufif1, bug326. 2011-02-23 21:21:59 -05:00
Wilson Snyder 2e67a91982 Support $bits(data_type), bug327. 2011-02-23 19:04:15 -05:00
Wilson Snyder 074ca9330d Make width violation on function outputs a fatal error 2011-02-18 20:52:26 -05:00
Wilson Snyder f0d7cdcb20 Commentary 2011-02-18 07:11:03 -05:00
Wilson Snyder 40d961e059 Version bump 2011-02-14 19:05:55 -05:00
Wilson Snyder e5de759236 Report error on function call output tied to constant.
Fix internal error on functions called as SV tasks.
2011-02-14 19:25:30 -05:00
Wilson Snyder e26a75c59d Fix internal error on non-inlined inout pins. 2011-02-07 19:15:58 -05:00
Wilson Snyder 8701145b40 Fix error on constants connected to outputs, bug323. 2011-01-31 07:05:04 -05:00
Wilson Snyder a2558886c8 Report errors on empty pins, bug321 2011-01-29 18:00:48 -05:00
Wilson Snyder f818ee86ae Report errors on duplicated pins, bug321. 2011-01-29 17:01:06 -05:00
Wilson Snyder ad0dbdaa9c CDC: Print nice net names instead of ___5f 2011-01-19 11:44:23 -05:00
Wilson Snyder a9f14b294f Internals: Cdc notes; marking submodules won't work 2011-01-18 21:37:53 -05:00
Wilson Snyder a435ae98f9 Throw UNUSED/UNDRIVEN only once per net in a parametrized module. 2011-01-18 21:28:51 -05:00
Wilson Snyder 481b261458 Internals: add a few userIncs, No functional change 2011-01-18 21:19:12 -05:00
Wilson Snyder 48df52d743 Reduce use of CRELINE so line numbers more closely match first parsed location 2011-01-18 21:12:31 -05:00
Wilson Snyder 0af0d3b171 Cleanup CDC reports, remove TOP-> signal prefixes 2011-01-17 14:58:58 -05:00
Wilson Snyder 8287cf35e7 Fix warnings to point to lowest net usage, not upper level ports. 2011-01-17 14:10:01 -05:00
Wilson Snyder fab7924cc2 Fix block comment not separating identifiers, bug311. 2011-01-11 18:46:21 -05:00
Wilson Snyder 0ab739e8b1 Fix false BLKSEQ on non-unrolled for loop indexes. 2011-01-06 06:46:19 -05:00
Wilson Snyder 2dcd4d171b Version bump 2011-01-03 13:32:16 -05:00
Wilson Snyder e7f4d18c3d First test is verilator -V 2011-01-03 13:30:33 -05:00
Wilson Snyder 1611362c22 Add --unused-regexp 2011-01-01 19:43:22 -05:00
Wilson Snyder 2327698160 driver: Allow --site specific tests 2011-01-01 19:18:32 -05:00
Wilson Snyder 71c1f00ec2 Copyright year update 2011-01-01 18:21:19 -05:00
Wilson Snyder 6574a126ef spdiff: Ignore copyright differences 2011-01-01 18:20:30 -05:00
Wilson Snyder 1e68086355 Fix defparam test failing after make clean 2011-01-01 18:12:29 -05:00
Wilson Snyder 326cc8fd67 Fix DLYSYNC with for loop variables 2010-12-31 20:18:21 -05:00
Wilson Snyder 4afcb421bd With --Wall, add BLKSEQ warning on blocking assignments in seq blocks. 2010-12-31 18:36:29 -05:00
Wilson Snyder 8d21917035 Add SYNCASYNCNET 2010-12-31 07:51:14 -05:00
Wilson Snyder 4ca7f8834c Fix test ignores 2010-12-30 21:20:58 -05:00
Wilson Snyder b43299c8da Fix suppression of messages under debug 2010-12-30 08:41:23 -05:00
Wilson Snyder b763809f5e Fix last commit; allow multiple exprs 2010-12-30 08:26:36 -05:00
Wilson Snyder 2cb97f7475 For UNUSED, ignore black boxed sys calls 2010-12-30 07:55:31 -05:00
Wilson Snyder 6283df7491 Vlt lint off now has optional msgname 2010-12-30 06:58:02 -05:00
Wilson Snyder acc4490370 For UNUSED, skip primitive tables 2010-12-29 20:24:31 -05:00
Wilson Snyder f85c1a995a For UNUSED, better by-bit warnings 2010-12-29 19:59:07 -05:00
Wilson Snyder 809e5fda8a Ignore DECLFILENAME on library files 2010-12-29 19:34:33 -05:00
Wilson Snyder dce245da5a Allow wildcards in vlt config files 2010-12-29 19:14:49 -05:00
Wilson Snyder d261c4cd27 For UNUSED warning, ignore genvars 2010-12-29 18:10:02 -05:00
Wilson Snyder c33299d542 Add UNUSED and UNDRIVEN warnings 2010-12-29 08:06:05 -05:00
Wilson Snyder ebdf8a5f3c Internals: Constify tristates with ConstLive, unused so no functional change 2010-12-29 07:56:22 -05:00
Wilson Snyder c8852d183f Internals: Add V3Const preserving liveness, no functional change 2010-12-28 21:23:16 -05:00
Wilson Snyder 9f161b20ef Internals: Avoid passing vars from V3Const visitor; no functional change 2010-12-28 20:46:13 -05:00
Wilson Snyder 40f9d64973 Commentary 2010-12-27 17:25:28 -05:00
Wilson Snyder 4a2e68a0fd Avoid -wall 2010-12-26 15:26:04 -05:00
Wilson Snyder bcd90d3401 Constify LSB subtractions immediately, no functional change intended 2010-12-26 15:20:57 -05:00
Wilson Snyder 114af7d33f Make UNUSED/UNDRIVEN -Wall only 2010-12-26 10:17:35 -05:00
Wilson Snyder 7b83d2de49 Commentary 2010-12-26 09:40:17 -05:00
Wilson Snyder 850de5913d With --Wall, add IFDEPTH warning on deep if statements. 2010-12-26 09:31:09 -05:00
Wilson Snyder bb9ee46f40 Use 'suggest' in INCABSPATH warning 2010-12-26 08:19:45 -05:00
Wilson Snyder e94fc1305b Support unique0; track internally with new attributes 2010-12-26 08:09:25 -05:00
Wilson Snyder 3e4e8feb29 With --Wall, add DECLFILENAME warning on modules not matching filename. 2010-12-25 16:31:22 -05:00
Wilson Snyder fedf347b1a With --Wall, add INCABSPATH warning on `include with absolute paths. 2010-12-25 15:50:07 -05:00
Wilson Snyder 285277a50b Add -Wall; move VARHIDDEN to style warnings 2010-12-25 15:28:13 -05:00
Wilson Snyder 323c96f42f Add -Wwarn-style, -Wno-style, and DEFPARAM warnings 2010-12-25 15:13:56 -05:00
Wilson Snyder 7dee344ea9 Add limited support for VPI access to public signals, see docs. 2010-12-25 14:39:41 -05:00
Wilson Snyder 65bce588e4 Add fatalSrc debug dump check 2010-12-24 13:15:46 -05:00
Wilson Snyder 233ff1b744 --gdbbt now documented, and uses return-child-results
Use this in first test_c to backtrace if any problems.
2010-12-17 20:14:25 -05:00
Wilson Snyder 0837e39787 With -V, print VERILATOR_BIN env var 2010-12-17 19:40:08 -05:00
Wilson Snyder 86db565a21 Fix extra / in binary name 2010-12-14 18:08:41 -05:00
Wilson Snyder d6ac5e5001 Support ++,--,+= etc as standalone statements. 2010-12-07 20:18:47 -05:00
Wilson Snyder e6443f1981 Fix manifest tsub error, broke earlier 2010-12-07 11:45:31 -05:00
Wilson Snyder d13e6c73db When running with VERILATOR_ROOT, optionally find binaries under bin. 2010-12-07 11:43:43 -05:00
Wilson Snyder 79ca7f3cb5 Commentary 2010-12-07 09:30:52 -05:00
Wilson Snyder cfd07ccd34 Suppress WIDTH warnings when adding/subtracting 1'b1. 2010-12-02 14:00:43 -05:00
Wilson Snyder 48047d523a Remove dead code ifdef, bug299 2010-11-03 12:38:26 -04:00
Wilson Snyder eeb8fc2626 Add -F option to read relative option files, bug297. 2010-11-03 07:21:34 -04:00
Wilson Snyder 3d1baf3f2f Version bump 2010-11-02 21:11:02 -04:00
Wilson Snyder 4e382d6765 tests: add --golden flag 2010-11-02 21:10:52 -04:00
Wilson Snyder 582963375d tests: fix pipe bad golden 2010-11-02 21:10:44 -04:00
Wilson Snyder 56c7c1bcc8 Add warning when directory contains spaces, msg378 2010-10-28 09:51:36 -04:00
Wilson Snyder f88e57ddb8 Fix DPI export name not found, msg369. 2010-10-22 13:10:31 -04:00
Wilson Snyder 9d98e012e4 Fix segfault on SystemVerilog "output wire foo=0", bug291. 2010-10-04 07:48:09 -04:00
Wilson Snyder d305a774f0 Fix wrong filename on include file errors, bug289 2010-09-28 09:33:59 -04:00
Wilson Snyder 16b0c8d353 Commentary 2010-09-25 07:59:18 -04:00
Wilson Snyder 55da4fdbf6 Typo fixes. 2010-09-25 07:46:09 -04:00
Wilson Snyder ed2fbd8f25 Version bump 2010-09-20 15:46:17 -04:00
Wilson Snyder 42199bc8e5 Fix preprocessor `` of existing base define, bug283. 2010-09-20 15:20:16 -04:00
Wilson Snyder 7c5318768c Reduce debug verbosity (match Verilog-Perl) 2010-09-20 13:13:31 -04:00
Wilson Snyder aba25aab19 On core dump, print debug suggestions. 2010-09-20 09:21:29 -04:00
Wilson Snyder f99bd33f91 Support tracing/coverage of underscore signals, bug280. 2010-08-29 19:28:46 -04:00
Wilson Snyder a6a6ce83f0 Internals: Use branch prediction in asserts 2010-08-10 11:19:45 -04:00
Wilson Snyder f4908a9758 Increase define recursions before error 2010-08-10 11:18:53 -04:00
Wilson Snyder 5e4ca4b76a Version bump 2010-07-10 18:41:23 -04:00
Wilson Snyder 1e938d0e90 Update preprocessor to match next Verilog-Perl version.
Fix preprocessor preservation of newlines across macro substitutions.
Fix preprocessor stringification of nested macros.
Fix preprocessor whitespace on define arguments
2010-07-10 18:30:16 -04:00
Wilson Snyder f3704f4c05 Tests: Rename includes to .vh extensions 2010-07-08 20:51:54 -04:00
Wilson Snyder 8800efe953 Internals: Rename incLineno to match Verilog-Perl, no functional change. 2010-07-08 20:31:41 -04:00
Wilson Snyder a320c4584e Fix do {...} while() not requiring final semicolon. 2010-07-07 19:15:51 -04:00
Wilson Snyder 3841850168 Preproc: fix pass-through of `line enter-exit codes.
Internals: Merge Verilog-Perl preproc changes through d450722.
2010-07-06 20:29:12 -04:00
Wilson Snyder beb3885840 Add t_clk_2in test 2010-06-21 20:40:34 -04:00
Wilson Snyder 06967c0c46 Fix some constant parameter functions causing crash, bug253. 2010-05-25 19:37:45 -04:00
Wilson Snyder 9a382c572c Commentary, bug251 2010-05-02 06:29:02 -04:00
Wilson Snyder 44b6c371db Version bump 2010-05-01 14:18:56 -04:00
Wilson Snyder 00970be996 Fix bit reductions on multi-packed dimensions, bug227/patch0004. 2010-04-22 09:40:53 -04:00
Wilson Snyder aca4ab015f Fix removing if assigned to unused var, bug248. 2010-04-19 19:38:22 -04:00
Wilson Snyder 68b63d5783 Increase unrollStmts, bug247, due to unreleased change. 2010-04-19 13:59:15 -04:00
Wilson Snyder 4b499f2bb1 Commentary, bug246 2010-04-19 09:44:48 -04:00
Wilson Snyder ed17581f92 Fix loop unroller out of memory; change --unroll-stmts. 2010-04-17 08:01:22 -04:00
Wilson Snyder a46c4ec912 Accelerate and reduce memory usage of V3Expand 2010-04-15 21:05:21 -04:00
Wilson Snyder 930cbeec17 Internals: Create user#Inc routines 2010-04-15 20:56:54 -04:00
Wilson Snyder 10689ffaba Fix carrage return purging, broke in pre-release only 2010-04-10 09:11:52 -04:00
Wilson Snyder 29b0ea0af9 Debug: Allow --debugi-V3PreShell to turn on flex debug 2010-04-10 08:20:28 -04:00
Wilson Snyder 57d00946be Fix MSVC compile issues 2010-04-10 06:46:24 -04:00
Wilson Snyder ef51de72c9 Fix word size to match uint64_t on -m64 systems, bug238. 2010-04-09 21:51:15 -04:00
Wilson Snyder c807bf1e0e Internals: Fix useless rule and flex warning 2010-04-09 21:06:16 -04:00
Byron Bradley 2525b3fb05 Fix bit reductions on multi-packed dimensions, bug227
Signed-off-by: Wilson Snyder <[email protected]>
2010-04-09 21:05:46 -04:00
Byron Bradley 9163ce0f6e Internals: modify AstVar::dimensions() to return a pair, bug227
Signed-off-by: Wilson Snyder <[email protected]>
2010-04-09 20:43:25 -04:00
Byron Bradley d776638f53 Internals: Mark packed dimensions in arrays, bug227
Signed-off-by: Wilson Snyder <[email protected]>
2010-04-09 20:40:41 -04:00
Wilson Snyder 83fff41312 Fix installing data files as non-executable, bug168. 2010-04-09 20:21:00 -04:00
Wilson Snyder dd7d9bc95b Fix some spelling mistakes in verilator executable & manpage, bug240 2010-04-09 19:45:46 -04:00
Wilson Snyder f8eabbc100 From Verilog-Perl: Fix parsing single files > 2GB. 2010-04-06 20:20:44 -04:00
Wilson Snyder 7ed18ac62d Internals: Track Verilog-Perl 3.240 parser changes 2010-04-06 18:55:54 -04:00
Wilson Snyder 3ac707c645 Tests: Fix vpi_user addition failure 2010-04-06 18:43:24 -04:00
Wilson Snyder 8e9a1e0bf3 Add standard vpi_user.h file 2010-04-05 20:08:13 -04:00
Wilson Snyder bc31b5d27a Commentary 2010-04-05 20:08:07 -04:00
Wilson Snyder 936738b750 Add /*verilator public_flat_rw*/ for timing-specific public access. 2010-04-05 20:01:17 -04:00
Wilson Snyder 7c3048ab9c Report errors when extra underscores used in meta-comments. 2010-03-24 22:08:59 -04:00
Wilson Snyder 64719f3ace Makefile: Add local install-cadtools rule 2010-03-24 16:09:29 -04:00
Wilson Snyder a11a5f04d5 Default Verilated::debug() to off 2010-03-23 20:31:22 -04:00
Wilson Snyder eb5c035dde Internals: Fix some missing branch prediction 2010-03-22 19:07:03 -04:00
Wilson Snyder c3887efbf3 Internals: Remove dead code 2010-03-22 19:06:30 -04:00
Wilson Snyder 495585830d Fix trace files with empty modules crashing some viewers. 2010-03-22 18:38:24 -04:00
Wilson Snyder 6715cb9880 Improve error handling on slices of arrays, bug226. 2010-03-20 21:29:16 -04:00
Wilson Snyder 41b167d23c Fix DPI display bogus error 2010-03-20 07:13:52 -04:00
Wilson Snyder 7ea8b54210 Tests: Support atsim and cleanup verilator-only tests 2010-03-18 12:03:08 -04:00
Wilson Snyder bcea39a858 Fix "make install" with configure outside srcdir. 2010-03-17 20:20:40 -04:00
Wilson Snyder fb560abac4 Commentary 2010-03-17 19:57:38 -04:00
Wilson Snyder ba93a08b40 Support runtime access to public signal names 2010-03-17 08:22:49 -04:00
Wilson Snyder 2be6b3481c Pre-version 2010-03-17 08:05:07 -04:00
Wilson Snyder 6ef44a6fbb Version bump 2010-03-17 07:59:12 -04:00
Wilson Snyder 2afe40a0b5 verilated: Add debug pointers to scopeDump() 2010-03-16 19:28:29 -04:00
Wilson Snyder e57d004718 Fix clock-gates with non-AND complex logic, bug220. 2010-03-16 18:50:26 -04:00
Wilson Snyder d780d0aabb Fix flushing VCD buffers on . 2010-03-12 20:00:08 -05:00
Wilson Snyder 0f9e3f0767 Cleanup flex compiles again - remove yyleng from preproc.cpp 2010-03-05 12:02:56 -05:00
Wilson Snyder 381972c923 Fix Mac OS-X compile issues, bug217. 2010-02-26 19:50:44 -05:00
Wilson Snyder 845d7ad718 Commentary 2010-02-26 18:57:34 -05:00
Wilson Snyder f1b6c0c559 Support "`default_nettype none|wire". 2010-02-23 09:27:16 -05:00
Wilson Snyder e39eddf3fe Fix parametrized defines with empty arguments. 2010-02-21 07:20:39 -05:00
Wilson Snyder 72218fb475 Defines with // comments still need continuation - spec ambiguity 2010-02-18 20:57:46 -05:00
Wilson Snyder 9a3e497c22 Fix specparam defaults 2010-02-18 08:43:16 -05:00
Wilson Snyder 85d510cd48 Fix vl_mc_scan_plusarg returning stack based pointer 2010-02-16 11:54:39 -05:00
Wilson Snyder 786c65ea5f Makefile: reconfigure when src/*.in changes 2010-02-15 07:34:55 -05:00
Wilson Snyder 10e6f61125 Commentary 2010-02-14 19:23:29 -05:00
Wilson Snyder cdd06e7236 Support "break", "continue", "return". 2010-02-14 10:01:21 -05:00
Wilson Snyder 48603c0ee2 Commentary 2010-02-10 08:50:41 -05:00
Wilson Snyder 63f30492be Skip SystemC tests if not installed. 2010-02-08 20:51:43 -05:00
Wilson Snyder 0e8772290d Fix make uninstall, bug216 2010-02-08 09:28:40 -05:00
Wilson Snyder 6cfc5798b0 Tests: Move sc_main.cpp as there's more sc than sp users 2010-02-08 08:10:07 -05:00
Wilson Snyder 6be275f5d4 Post release version bump 2010-02-08 06:27:07 -05:00
578 changed files with 21151 additions and 4861 deletions
+431 -1
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -1,5 +1,6 @@
^CVS/ ^CVS/
/CVS/ /CVS/
\.gdbinit$
\.git/ \.git/
\.svn/ \.svn/
\.(bak|old)/ \.(bak|old)/
@@ -24,6 +25,8 @@ src/Makefile_obj$
include/verilated.mk$ include/verilated.mk$
config.cache$ config.cache$
config.status$ config.status$
verilator.log
verilator.tex
verilator_bin.* verilator_bin.*
.vcsmx_rebuild$ .vcsmx_rebuild$
autom4te\.cache/ autom4te\.cache/
+134 -60
View File
@@ -9,7 +9,7 @@
# #
#***************************************************************************** #*****************************************************************************
# #
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can # Copyright 2003-2012 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.
@@ -88,7 +88,10 @@ pkgdatadir = @pkgdatadir@
datarootdir = @datarootdir@ datarootdir = @datarootdir@
# Compile options # Compile options
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@ CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
PACKAGE_VERSION = @PACKAGE_VERSION@
#### End of system configuration section. #### #### End of system configuration section. ####
###################################################################### ######################################################################
@@ -101,8 +104,6 @@ INFOS = README internals.txt verilator.txt verilator.html verilator.1 verilator.
# 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
# Files to distribute.
DISTBIN = $(wildcard bin/verilator-*)
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
*.in *.ac \ *.in *.ac \
@@ -118,8 +119,9 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
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/*.pl src/*.pod \ src/*.pl src/*.pod \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \ test_*/.*ignore test_*/Makefile* test_*/*.cpp \
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \ test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
test_verilated/vgen*.pl \ test_verilated/vgen*.pl \
test_regress/t/tsub/*.v* \
test_regress/t/*.cpp \ test_regress/t/*.cpp \
test_regress/t/*.h \ test_regress/t/*.h \
test_regress/t/*.dat \ test_regress/t/*.dat \
@@ -128,16 +130,14 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
test_regress/t/*.pl \ test_regress/t/*.pl \
test_regress/t/*.pf \ test_regress/t/*.pf \
test_regress/t/*.v* \ test_regress/t/*.v* \
verilator.* \
INST_PROJ_FILES = \ INST_PROJ_FILES = \
bin/verilator \ bin/verilator \
bin/verilator_includer \ bin/verilator_includer \
bin/verilator_profcfunc \ bin/verilator_profcfunc \
include/verilated.[chv]* \
include/verilated.mk \ include/verilated.mk \
include/verilatedos.[chv]* \ include/*.[chv]* \
include/verilated_*.[chv]* \ include/vltstd/*.[chv]* \
INST_PROJ_BIN_FILES = \ INST_PROJ_BIN_FILES = \
verilator_bin \ verilator_bin \
@@ -145,8 +145,6 @@ INST_PROJ_BIN_FILES = \
DISTFILES := $(DISTFILES_INC) DISTFILES := $(DISTFILES_INC)
VL_INST_MAN_FILES = verilator.1
ifeq ($(OBJCACHE_JOBS),) ifeq ($(OBJCACHE_JOBS),)
ifneq ($(OBJCACHE_HOSTS),) ifneq ($(OBJCACHE_HOSTS),)
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)") export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
@@ -166,14 +164,14 @@ verilator_exe verilator_bin verilator_bin_dbg:
(cd src && $(MAKE) $(OBJCACHE_JOBS) ) (cd src && $(MAKE) $(OBJCACHE_JOBS) )
.PHONY:msg_test .PHONY:msg_test
msg_test: msg_test: all_nomsg
@echo "Build complete!" @echo "Build complete!"
@echo @echo
@echo "Type 'make test' to test." @echo "Type 'make test' to test."
@echo @echo
.PHONY:test .PHONY:test
ifeq ($(VERILATOR_AUTHOR_SITE),1) # 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_vcs test_c test_sc test_sp test_verilated test_regress
else else
test: test_c test_sc test_sp test: test_c test_sc test_sp
@@ -205,17 +203,18 @@ 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: bin/verilator verilator.1: ${srcdir}/bin/verilator
pod2man $< $@ pod2man $< $@
verilator.txt: bin/verilator verilator.txt: ${srcdir}/bin/verilator
$(POD2TEXT) $< $@ $(POD2TEXT) $< $@
verilator.html: bin/verilator verilator.html: ${srcdir}/bin/verilator
pod2html $< >$@ pod2html $< >$@
verilator.pdf: bin/verilator $(DISTCONFIG) # PDF needs DIST variables; but having configure.ac as dependency isn't detected
pod2latex --full --out verilator.tex bin/verilator verilator.pdf: ${srcdir}/bin/verilator Makefile
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
cat < verilator.tex \ cat < verilator.tex \
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \ | sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \ | sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
@@ -238,11 +237,29 @@ internals.txt: internals.pod
-rm -f $@ -rm -f $@
$(POD2TEXT) --loose $< > $@ $(POD2TEXT) --loose $< > $@
# See uninstall also # See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
verilator_includer verilator_profcfunc 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
VL_INST_MAN_FILES = verilator.1
VL_INST_INC_BLDDIR_FILES = \
include/verilated.mk \
# Files under srcdir, instead of build time
VL_INST_INC_SRCDIR_FILES = \
include/*.[chv]* \
include/vltstd/*.[chv]* \
VL_INST_DATA_SRCDIR_FILES = \
test_v/*.[chv]* \
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
test_sp/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 )
@@ -252,37 +269,68 @@ installbin:
$(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 )
# Man files can either be part of the original kit, or built in current directory
# 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 $(VL_INST_MAN_FILES) ; do \ for p in $< ; do \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(mandir)/man1/$$p; \ $(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
done done
installdata: installdata:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd $(DESTDIR)$(pkgdatadir)/examples $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd
cp -r include/*.* $(DESTDIR)$(pkgdatadir)/include for p in $(VL_INST_INC_BLDDIR_FILES) ; do \
cp -r ${srcdir}/include/*.* $(DESTDIR)$(pkgdatadir)/include $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
cp -r ${srcdir}/include/vltstd/*.* $(DESTDIR)$(pkgdatadir)/include/vltstd done
cp -r ${srcdir}/test_c $(DESTDIR)$(pkgdatadir)/examples cd $(srcdir) \
cp -r ${srcdir}/test_sc $(DESTDIR)$(pkgdatadir)/examples ; for p in $(VL_INST_INC_SRCDIR_FILES) ; do \
cp -r ${srcdir}/test_sp $(DESTDIR)$(pkgdatadir)/examples $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
cp -r ${srcdir}/test_v $(DESTDIR)$(pkgdatadir)/examples done
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sp
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v
cd $(srcdir) \
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
done
VL_INST_DATA_FILES = verilator.1 # We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
install: all_nomsg installbin installman installdata install-msg uninstall:
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_BIN_FILES)
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
-rmdir $(DESTDIR)$(pkgdatadir)/bin
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
-rmdir $(DESTDIR)$(pkgdatadir)/include
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_c
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sc
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sp
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
-rmdir $(DESTDIR)$(pkgdatadir)/examples
-rmdir $(DESTDIR)$(pkgdatadir)
install: all_nomsg install-all
install-all: installbin installman installdata install-msg
install-here: installman ftp install-here: installman ftp
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
DISTNAMEREV = $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q ${srcdir}/src/config_rev.h)
DIRPROJECT := $(shell project_dir --project) DIRPROJECT := $(shell project_dir --project)
VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH)
INST_PROJ_CVS = cp_if_cvs_diff 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*
$(MAKE) install-project-quick $(MAKE) install-project-quick
for p in verilator.1 ; do \ for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \ $(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
done done
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz $(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
rm $(DISTNAME).tgz rm $(DISTNAME).tgz
@@ -299,44 +347,72 @@ endif
for p in $(INST_PROJ_BIN_FILES) ; do \ for p in $(INST_PROJ_BIN_FILES) ; do \
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p-$(DIRPROJECT_ARCH); \ $(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p-$(DIRPROJECT_ARCH); \
done done
install-cadtools: dist
@echo "Install-project to $(CAD_DIR)"
strip verilator_bin*
$(MAKE) install-cadtools-quick
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_DATA) $$p $(VERILATOR_CAD_DIR)/man/man1/$$p; \
done
$(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz
rm $(DISTNAME).tgz
install-cadtools-quick:
ifeq ($(CFG_WITH_DEFENV),yes)
@echo "%Error: Reconfigure with './configure --disable-defenv' to avoid hardcoded paths."
false
endif endif
@echo "Install-cadtools-quick (no strip) to $(VERILATOR_CAD_DIR)"
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/include/vltstd
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/bin
for p in $(INST_PROJ_FILES) ; do \
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
done
for p in $(INST_PROJ_BIN_FILES) ; do \
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
done
# VERILATOR_AUTHOR_SITE
endif
CPPCHECK = cppcheck
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
cppcheck: $(CPPCHECK_DEP)
%.cppcheck: %.cpp
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -I$(srcdir)/include -I$(srcdir)/src $<
ftp: info ftp: info
install-msg: install-msg:
@echo "Installed!" @echo "Installed!"
@echo @echo
@echo "Add to your startup file (for bash or csh, as appropriate):" @echo "Fod documentation see 'man verilator' or 'verilator --help'"
@echo " export VERILATOR_ROOT="`pwd` @echo "For forums and to report bugs see http://www.veripool.org/verilator"
@echo " setenv VERILATOR_ROOT "`pwd` " ; export VERILATOR_ROOT "
@echo
@echo "See 'verilator.txt' for documentation."
@echo @echo
uninstall: IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
-rm -f $(DESTDIR)$(pkgdatadir)
# autoheader might not change config_build.h.in, so touch a stamp file. # autoheader might not change config_build.h.in, so touch it
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \ ${srcdir}/config_build.h: ${srcdir}/config_build.h.in configure
*.in */*.in */*.in
${srcdir}/config_build.h.in: stamp-h.in
${srcdir}/stamp-h.in: configure.ac $(wildcard $(IN_WILD))
cd ${srcdir} && autoheader cd ${srcdir} && autoheader
echo timestamp > ${srcdir}/stamp-h.in touch $@
config_build.h: stamp-h Makefile: Makefile.in config.status $(IN_WILD)
stamp-h: config_build.h.in config.status
./config.status
Makefile: Makefile.in config.status
./config.status
src/Makefile: src/Makefile.in config.status
./config.status ./config.status
src/Makefile: src/Makefile.in Makefile
config.status: configure config.status: configure
./config.status --recheck ./config.status --recheck
configure: configure.ac configure: configure.ac
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
autoconf --warnings=all
else
autoconf autoconf
endif
maintainer-clean:: maintainer-clean::
@echo "This command is intended for maintainers to use;" @echo "This command is intended for maintainers to use;"
@@ -377,14 +453,12 @@ dist-file-list:
###################################################################### ######################################################################
# Distributions # Distributions
DISTCONFIG = ${srcdir}/src/config_build.h.in DISTTITLE := Verilator $(word 1,$(PACKAGE_VERSION))
DISTNAME := verilator-$(word 1,$(PACKAGE_VERSION))
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG)) DISTDATEPRE := $(word 2,$(PACKAGE_VERSION))
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG)) DISTDATE := $(subst /,-,$(DISTDATEPRE))
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME))) DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
DISTDATE := $(subst /,-,$(DISTDATEPRE))
tag: tag:
svnorcvs tag $(DISTTAGNAME) svnorcvs tag $(DISTTAGNAME)
+99 -90
View File
@@ -1,134 +1,143 @@
// DESCRIPTION: Verilator: List of To Do issues. // DESCRIPTION: Verilator: List of To Do issues.
// //
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can // Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // 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.
Features: Language support:
Latch optimizations {Need here} * Fix ordering of each bit separately in a signal (mips)
Task I/Os connecting to non-simple variables.
Fix ordering of each bit separately in a signal (mips)
assign b[3:0] = b[7:4]; assign b[7:4] = in; assign b[3:0] = b[7:4]; assign b[7:4] = in;
Support gate primitives/ cell libraries from xilinx, etc * Support UDP gate primitives/ cell libraries
Assign dont_care value to an 1'bzzz assignment (have code for combos - problem is sequential udps)
Function to eval combo logic after /*verilator public*/ functions [gwaters] * Function to eval combo logic after /*verilator public*/ functions [gwaters]
Support generated clocks (correctness) * Support generated clocks (correctness)
?gcov coverage * Real numbers
Selectable SystemC types based on widths (see notes below) * Recursive functions
Coverage * Verilog configuration files
Points should be per-scope like everything else rather then per-module * Structs/unions (have starting point)
Expression coverage (see notes) * DPI to define C/C++ calls from Verilog
Constant functions for widths, etc, IE "input [log2(PARAM):0] xx;" * Expression coverage (see notes)
More Verilog 2001 Support * Better tristate support
(* *) Attributes (just ignore -- preprocessor?)
Real numbers (NEVER)
Recursive functions (NEVER)
Verilog configuration files (NEVER)
DPI to define C/C++ calls from Verilog
Long-term Features Long-term Features
Assertions * Assertions
VHDL parser [Philips] * Tristate support
Tristate support * Multithreaded execution
SystemPerl integration
Multithreaded execution Configure/Make/Install
* Full MSVC++ compilation (does scons support this?) (4.000?)
* Distribute with flex/bison already expanded?
Flex library not needed. Probably too difficult to be worth it.
* Integrate SystemPerl coverage
(Note in /usr/include there are no upper cased include files.)
Coverage.pm -- Need all functionality, but in C?
Coverage/Item.pm -- Need all functionality, but in C?
Coverage/ItemKey.pm -- Need all functionality, but in C?
sp_preproc -- Some steps in here need to be moved to generated C
src/Sp.cpp -- n/a
src/SpCommon.h -- mostly overlaps verilatedos.h
src/SpCoverage.cpp/h -- All needed
src/SpFunctor.cpp/h -- No longer used
src/SpTraceVcd.cpp/h -- MOVED
src/SpTraceVcdC.cpp/h -- MOVED
src/sp_log.cpp/h -- Not needed
src/systemperl.h -- some stuff may be cut
vcoverage -- Need all functionality, but in C?
Testing: Testing:
Capture all inputs into global "rerun it" file * Move test_c/sp/v/verilated into test_regress format (4.000?)
Code to make wrapper that sets signals, so can do comparison checks * Capture all inputs into global "rerun it" file
New random program generator * Code to make wrapper that sets signals, so can do comparison checks
Better graph viewer with search and zoom * New random program generator
Port and test against opencores.org code * Better graph viewer with search and zoom
* Port and test against opencores.org code
Usability: Usability:
Better reporting of unopt problems, including what lines of code * Detect and pre-remove most UNOPTFLATs (4.000)
Report more errors (all of them?) before exiting [Eugene Weber] * Better reporting of unopt problems, including what lines of code
* Report more errors (all of them?) before exiting [Eugene Weber]
* Auto-create scons config files
* Print version/etc message at runtime. (4.000?)
Include number of lines of code, percent comments, code complexity measurement
<-80chars------------------------------------------------------------------->
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2012.
Verilated #### modules, #### instances, ##### sigs,
#### non-comment lines, ##### ops, ### KB model size
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
Lint:
* CDCRSTLOGIC should allow filtering with paths
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
Internal Code: Internal Code:
Eliminate the AstNUser* passed to all visitors; its only needed in V3Width, * Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
and removing it will speed up and simplify all the other code. and removing it will speed up and simplify all the other code.
V3Graph should be templated container type, taking in Vertex + Edge types * V3Graph should be templated container type, taking in Vertex + Edge types
* Rename V3PreLex etc to match VerilogPerl filenames
* Instead of string, have an VEncodedString/VIdString which contains __DOT__ish
things, to reduce bugs. Also add _20 trailing space to \ encoded names. (4.000)
Runtime:
* New evalulation loop ~/src/verilator/notes/event_loop.txt (4.000?)
* Remove all private internal functions from top level wrapper header, move
to new level (4.000?)
* Completely standalone simulation (4.000)
main() records arguments for $test$plusvars
instantiates top,
does tracing (support $dump?)
calls top->simulateForever()
exits
Performance: Performance:
Constant propagation * Latch optimizations
* Constant propagation
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF)) Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
Extra shift (perhaps due to clean): if (1 & CAST (VARREF >> #)) Extra shift (perhaps due to clean): if (1 & CAST (VARREF >> #))
Gated clock and latch conversion to flops. [JeanPaul Vanitegem] * Gated clock and latch conversion to flops. [JeanPaul Vanitegem]
Could propagate the AND into pos/negedges and let domaining optimize. Could propagate the AND into pos/negedges and let domaining optimize.
Negedge reset * Negedge reset
Switch to remove negedges that don't matter Switch to remove negedges that don't matter
Can't remove async resets from control flops (like in syncronizers) Can't remove async resets from control flops (like in syncronizers)
If all references to array have a constant index, blow up into separate signals-per-index * If all references to array have a constant index, blow up into separate signals-per-index
Multithreaded execution * Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings. * Move _last sets and all other combo logic inside master
Move _last sets and all other combo logic inside master
if() that triggers on all possible sense items if() that triggers on all possible sense items
Rewrite and combine V3Life, V3Subst * Rewrite and combine V3Life, V3Subst
If block temp only ever set in one place to constant, propagate it If block temp only ever set in one place to constant, propagate it
Used in t_mem for array delayed assignments Used in t_mem for array delayed assignments
Replace variables if set later in same cfunc branch Replace variables if set later in same cfunc branch
See for example duplicate sets of _narrow in cycle 90/91 of t_select_plusloop See for example duplicate sets of _narrow in cycle 90/91 of t_select_plusloop
Same assignment on both if branches * Same assignment on both if branches
"if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..." "if (a) { ... b=2; } else { ... b=2;}" -> "b=2; if ..."
Careful though, as b could appear in the statement or multiple times in statement Careful though, as b could appear in the statement or multiple times in statement
(Could just require exatly two 'b's in statement) (Could just require exatly two 'b's in statement)
Simplify XOR/XNOR/AND/OR bit selection trees * Simplify XOR/XNOR/AND/OR bit selection trees
Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 ) Foo = A[1] ^ A[2] ^ A[3] etc are better as ^ ( A & 32'b...1110 )
Combine variables into wider elements * Combine variables into wider elements
Parallel statements on different bits should become single signal Parallel statements on different bits should become single signal
Variables that are always consumed in "parallel" can be joined Variables that are always consumed in "parallel" can be joined
Duplicate assignments in gate optimization * Duplicate assignments in gate optimization
Common to have many separate posedge blocks, each with identical Common to have many separate posedge blocks, each with identical
reset_r <= rst_in reset_r <= rst_in
*If signal is used only once (not counting trace), always gate substitute * If signal is used only once (not counting trace), always gate substitute
Don't merge if any combining would form circ logic (out goes back to in) Don't merge if any combining would form circ logic (out goes back to in)
Multiple assignments each bit can become single assign with concat * Multiple assignments each bit can become single assign with concat
Make sure a SEL of a CONCAT can get the single bit back. Make sure a SEL of a CONCAT can get the single bit back.
Usually blocks/values * Usually blocks/values
Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out
Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching * Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
Allow Split of case statements without a $display/$stop * Allow Split of case statements without a $display/$stop
I-cache packing improvements (what/how?) * I-cache packing improvements (what/how?)
Data cache organization (order of vars in class) * Data cache organization (order of vars in class)
First have clocks, First have clocks,
then bools instead of uint32_t's then bools instead of uint32_t's
then based on what sense list they come from, all outputs, then all inputs then based on what sense list they come from, all outputs, then all inputs
finally have any signals part of a "usually" block, or constant. finally have any signals part of a "usually" block, or constant.
Rather then tracking widths, have a MSB...LSB of this expression * Rather then tracking widths, have a MSB...LSB of this expression
(or better, a bitmask of bits relevant in this expression) (or better, a bitmask of bits relevant in this expression)
Track recirculation and convert into clock-enables * Track recirculation and convert into clock-enables
Clock enables should become new clocking domains for speed * Clock enables should become new clocking domains for speed
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b). * If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal) * Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
All of the temp vars that get set, exp pre_ vars and never feedback
(not flops) don't need to be stored in the structs, but instead can
be per-invocation, and even better register-colored-like to reuse
the space. This will greatly reduce the data footprint.
//**********************************************************************
//* Eventual tristate bus Stuff allowed (old verilator)
1) Tristate assignments must be continuous assignments
The RHS of a tristate assignment can be the following
a) a node (tristate or non-tristate)
b) a constant (must be all or no z's)
x'b0, x'bz, x{x'bz}, x{x'b0} -> are allowed
c) a conditional whose possible values are (a) or (b)
2) One can lose that fact that a node is a tristate node. This happens
if a tristate node is assigned to a 'standard' node, or is used on
RHS of a conditional. The following infer tristate signals:
a) inout <SIGNAL>
b) tri <SIGNAL>
c) assigning to 'Z' (maybe through a conditional)
Note: tristate-ness of an output port determined only by
statements in the module (not the instances it calls)
4) Tristate variables can't be multidimensional arrays
5) Only check tristate contention between modules (not within!)
6) Only simple compares with 'Z' are allowed (===)
+608 -168
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -99,7 +99,7 @@ sub filter {
next if $line =~ / This=/; next if $line =~ / This=/;
$line =~ s/0x[a-f0-9]+/0x/g; $line =~ s/0x[a-f0-9]+/0x/g;
$line =~ s/<e[0-9]+\#?>/<e>/g; $line =~ s/<e[0-9]+\#?>/<e>/g;
$line =~ s/{\d+}/{}/g if !$Opt_Lineno; $line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
print $f2 $line; print $f2 $line;
} }
$f1->close; $f1->close;
@@ -109,7 +109,7 @@ sub filter {
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -177,7 +177,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-2010 by Wilson Snyder. This package is free software; you can Copyright 2005-2012 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.
@@ -193,5 +193,5 @@ C<verilator>
###################################################################### ######################################################################
### Local Variables: ### Local Variables:
### compile-command: "$V4/bin/verilator_difftree $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree" ### compile-command: "$V4/bin/verilator_difftree {$V4D,$V4}/test_regress/obj_dir/t_EXAMPLE/V*_03_*.tree"
### End: ### End:
+1 -1
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0; if 0;
# DESCRIPTION: Print include statements for each ARGV # DESCRIPTION: Print include statements for each ARGV
# #
# Copyright 2003-2010 by Wilson Snyder. This package is free software; you can # Copyright 2003-2012 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.
###################################################################### ######################################################################
+2 -2
View File
@@ -39,7 +39,7 @@ profcfunc($Opt_File);
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -208,7 +208,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-2010 by Wilson Snyder. Verilator is free software; you can Copyright 2007-2012 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.
+100 -31
View File
@@ -1,35 +1,83 @@
dnl DESCRIPTION: Process this file with autoconf to produce a configure script. # DESCRIPTION: Process this file with autoconf to produce a configure script.
dnl #
dnl Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can # Copyright 2003-2012 by Wilson Snyder. Verilator is free software; you can
dnl 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
dnl 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(src/Verilator.cpp) AC_INIT([Verilator],[3.832 2012-03-07])
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)
dnl Special Substitutions AC_MSG_RESULT([configuring for $PACKAGE_STRING])
AC_ARG_ENABLE(defenv,
[AS_HELP_STRING([--disable-defenv], [disable hardcoded default environment variables])], # Special Substitutions - CFG_WITH_DEFENV
CFG_WITH_DEFENV=$enableval, AC_MSG_CHECKING(whether to disable hardcoded paths)
CFG_WITH_DEFENV=yes) AC_ARG_ENABLE([defenv],
[AS_HELP_STRING([--disable-defenv],
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
[case "${enableval}" in
yes) CFG_WITH_DEFENV=yes ;;
no) CFG_WITH_DEFENV=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --disable-defenv]) ;;
esac],
CFG_WITH_DEFENV=yes)
AC_SUBST(CFG_WITH_DEFENV) AC_SUBST(CFG_WITH_DEFENV)
AC_MSG_RESULT($CFG_WITH_DEFENV)
dnl Compiler flags # Special Substitutions - CFG_WITH_CCWARN
AC_MSG_CHECKING(whether to show and stop on compilation warnings)
AC_ARG_ENABLE([ccwarn],
[AS_HELP_STRING([--enable-ccwarn],
[enable showing and stopping on compilation warnings])],
[case "${enableval}" in
yes) CFG_WITH_CCWARN=yes ;;
no) CFG_WITH_CCWARN=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ccwarn]) ;;
esac],
[case "x${VERILATOR_AUTHOR_SITE}" in
x) CFG_WITH_CCWARN=no ;;
*) CFG_WITH_CCWARN=yes ;;
esac]
)
AC_SUBST(CFG_WITH_CCWARN)
AC_MSG_RESULT($CFG_WITH_CCWARN)
# Special Substitutions - CFG_WITH_LONGTESTS
AC_MSG_CHECKING(whether to run long tests)
AC_ARG_ENABLE([longtests],
[AS_HELP_STRING([--enable-longtests],
[enable running long developer tests])],
[case "${enableval}" in
yes) CFG_WITH_LONGTESTS=yes ;;
no) CFG_WITH_LONGTESTS=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-longtests]) ;;
esac],
[case "x${VERILATOR_AUTHOR_SITE}" in
x) CFG_WITH_LONGTESTS=no ;;
*) CFG_WITH_LONGTESTS=yes ;;
esac]
)
AC_SUBST(CFG_WITH_LONGTESTS)
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
# Compiler flags
CFLAGS=-I${includedir} CFLAGS=-I${includedir}
CPPFLAGS=-I${includedir} CPPFLAGS=-I${includedir}
CXXFLAGS=-I${includedir} CXXFLAGS=-I${includedir}
LDFLAGS=-L${libdir} LDFLAGS=-L${libdir}
dnl Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_CXX AC_PROG_CXX
AC_PROG_INSTALL AC_PROG_INSTALL
AC_LANG_PUSH(C++) AC_LANG_PUSH(C++)
AC_MSG_CHECKING([that C++ compiler can compile simple program]) AC_MSG_CHECKING([that C++ compiler can compile simple program])
AC_TRY_RUN([int main() { return 0; }], AC_RUN_IFELSE(
[AC_LANG_SOURCE([int main() { return 0; }])],
AC_MSG_RESULT(yes), AC_MSG_RESULT(yes),
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required])) AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
AC_MSG_RESULT(yes))
AC_PATH_PROG(PERL,perl) AC_PATH_PROG(PERL,perl)
if test "x$PERL" = "x" ; then if test "x$PERL" = "x" ; then
@@ -44,33 +92,54 @@ if test "x$YACC" = "x" ; then
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it]) AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
fi fi
dnl Checks for libraries. # Checks for libraries.
dnl Checks for header files. # Checks for typedefs, structures
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(fcntl.h unistd.h inttypes.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
dnl Checks for typedefs, structures
AC_CHECK_TYPE(size_t,unsigned int) AC_CHECK_TYPE(size_t,unsigned int)
AC_CHECK_TYPE(uint_t,unsigned int)
AC_CHECK_TYPE(ulong_t,unsigned long)
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
AC_STRUCT_TM
dnl Checks for compiler characteristics. # Checks for compiler characteristics.
AC_C_INLINE AC_C_INLINE
dnl Checks for library functions. AC_DEFUN([_MY_CXX_CHECK_OPT],
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
CXXFLAGS="$CXXFLAGS $1 -Werror"
AC_MSG_CHECKING([whether $CXX accepts $1])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],[])],
[_my_result=yes],
[_my_result=no])
AC_MSG_RESULT($_my_result)
if test "$_my_result" = "yes" ; then
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1"
fi
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
])# _MY_CXX_CHECK_OPT
dnl Checks for system services # For example, -Wno-div-by-zero isn't in 4.1.2
_MY_CXX_CHECK_OPT(-Wno-char-subscripts)
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
# without this flag, even though there's a conditional to prevent the divide.
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
_MY_CXX_CHECK_OPT(-Wno-sign-compare)
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
dnl Other install directories # Checks for library functions.
# Checks for system services
# Other install directories
pkgdatadir=${datadir}/verilator pkgdatadir=${datadir}/verilator
AC_SUBST(pkgdatadir) AC_SUBST(pkgdatadir)
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk) AC_OUTPUT
AC_MSG_RESULT([]) AC_MSG_RESULT([])
AC_MSG_RESULT([Now type 'gmake']) AC_MSG_RESULT([Now type 'make' (or sometimes 'gmake') to build Verilator.])
AC_MSG_RESULT([]) AC_MSG_RESULT([])
+180 -23
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,15 +26,18 @@
#define _VERILATED_CPP_ #define _VERILATED_CPP_
#include "verilated_imp.h" #include "verilated_imp.h"
#include <cctype> #include <cctype>
#include <vector>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING #define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
//=========================================================================== //===========================================================================
// Global variables // Global variables
// Slow path variables
int Verilated::s_randReset = 0; int Verilated::s_randReset = 0;
int Verilated::s_debug = 1; VerilatedVoidCb Verilated::s_flushCb = NULL;
// Keep below together in one cache line
int Verilated::s_debug = 0;
bool Verilated::s_calcUnusedSigs = false; bool Verilated::s_calcUnusedSigs = false;
bool Verilated::s_gotFinish = false; bool Verilated::s_gotFinish = false;
bool Verilated::s_assertOn = true; bool Verilated::s_assertOn = true;
@@ -53,6 +56,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) {
VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum); VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum);
if (Verilated::gotFinish()) { if (Verilated::gotFinish()) {
VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum); VL_PRINTF("- %s:%d: Second verilog $finish, exiting\n", filename, linenum);
Verilated::flushCall();
exit(0); exit(0);
} }
Verilated::gotFinish(true); Verilated::gotFinish(true);
@@ -62,6 +66,7 @@ void vl_finish (const char* filename, int linenum, const char* hier) {
#ifndef VL_USER_STOP // Define this to override this function #ifndef VL_USER_STOP // Define this to override this function
void vl_stop (const char* filename, int linenum, const char* hier) { void vl_stop (const char* filename, int linenum, const char* hier) {
Verilated::gotFinish(true); Verilated::gotFinish(true);
Verilated::flushCall();
vl_fatal (filename,linenum,hier,"Verilog $stop"); vl_fatal (filename,linenum,hier,"Verilog $stop");
} }
#endif #endif
@@ -71,6 +76,7 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
if (0 && hier) {} if (0 && hier) {}
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();
abort(); abort();
} }
#endif #endif
@@ -278,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
// Note also assumes variables < 64 are not wide, this assumption is // Note also assumes variables < 64 are not wide, this assumption is
// sometimes not true in low-level routines written here in verilated.cpp // sometimes not true in low-level routines written here in verilated.cpp
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH]; static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false; bool inPct = false;
bool widthSet = false; bool widthSet = false;
int width = 0; int width = 0;
const char* pos = formatp; const char* pos = formatp;
for (; *pos; ++pos) { for (; *pos; ++pos) {
if (!inPct && pos[0]=='%') { if (!inPct && pos[0]=='%') {
pctp = pos;
inPct = true; inPct = true;
widthSet = false; widthSet = false;
width = 0; width = 0;
@@ -305,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
widthSet = true; widthSet = true;
width = width*10 + (fmt - '0'); width = width*10 + (fmt - '0');
break; break;
case '.':
inPct = true; // Get more digits
break;
case '%': case '%':
output += '%'; output += '%';
break; break;
@@ -318,6 +330,18 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += cstrp; output += cstrp;
break; break;
} }
case 'e':
case 'f':
case 'g': {
const int lbits = va_arg(ap, int);
double d = va_arg(ap, double);
if (lbits) {} // UNUSED - always 64
strncpy(tmpf, pctp, pos-pctp+1);
tmpf[pos-pctp+1] = '\0';
sprintf(tmp, tmpf, d);
output += tmp;
break;
}
default: { default: {
// Deal with all read-and-print somethings // Deal with all read-and-print somethings
const int lbits = va_arg(ap, int); const int lbits = va_arg(ap, int);
@@ -351,14 +375,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
case 'd': { // Signed decimal case 'd': { // Signed decimal
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld))); int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
int needmore = width-digits; int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp; output += tmp;
break; break;
} }
case 'u': { // Unsigned decimal case 'u': { // Unsigned decimal
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld); int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
int needmore = width-digits; int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp; output += tmp;
break; break;
} }
@@ -562,6 +598,17 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
VL_SET_WQ(owp,ld); VL_SET_WQ(owp,ld);
break; break;
} }
case 'f':
case 'e':
case 'g': { // Real number
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done;
union { double r; vlsint64_t ld; } u;
u.r = strtod(tmp, NULL);
VL_SET_WQ(owp,u.ld);
break;
}
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);
@@ -621,6 +668,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
//=========================================================================== //===========================================================================
// File I/O // File I/O
FILE* VL_CVT_I_FP(IData lhs) {
return VerilatedImp::fdToFp(lhs);
}
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) { void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
// See also VL_DATA_TO_STRING_NW // See also VL_DATA_TO_STRING_NW
int lsb=obits-1; int lsb=obits-1;
@@ -648,8 +699,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
for (; i<bytes; i++) { *op++ = 0; } for (; i<bytes; i++) { *op++ = 0; }
} }
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) { IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
// The string needs to be padded with 0's in unused spaces in front of // The string needs to be padded with 0's in unused spaces in front of
@@ -676,16 +727,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
return got; return got;
} }
QData 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);
} }
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) { IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
char modez[5]; char modez[5];
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode); _VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
return VL_CVT_FP_Q(fopen(filenamez,modez)); return VL_FOPEN_S(filenamez,modez);
}
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
return VerilatedImp::fdNew(fopen(filenamep,modep));
}
void VL_FCLOSE_I(IData fdi) {
FILE* fp = VL_CVT_I_FP(fdi);
if (VL_UNLIKELY(!fp)) return;
fclose(fp);
VerilatedImp::fdDelete(fdi);
} }
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) { void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
@@ -719,8 +780,8 @@ void VL_WRITEF(const char* formatp, ...) {
VL_PRINTF("%s", output.c_str()); VL_PRINTF("%s", output.c_str());
} }
void VL_FWRITEF(QData fpq, const char* formatp, ...) { void VL_FWRITEF(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return; if (VL_UNLIKELY(!fp)) return;
va_list ap; va_list ap;
@@ -732,8 +793,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
fputs(output.c_str(), fp); fputs(output.c_str(), fp);
} }
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) { IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
va_list ap; va_list ap;
@@ -826,7 +887,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
} else { } else {
needinc = true; needinc = true;
//printf(" Value width=%d @%x = %c\n", width, addr, c); //printf(" Value width=%d @%x = %c\n", width, addr, c);
if (addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb)) { if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) {
vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array"); vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array");
} else { } else {
int entry = addr - array_lsb; int entry = addr - array_lsb;
@@ -854,7 +915,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift); _VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
datap[0] |= value; datap[0] |= value;
} }
if (value>=(1<<shift)) { if (VL_UNLIKELY(value>=(1<<shift))) {
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters"); vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
} }
} }
@@ -871,11 +932,22 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
// Final checks // Final checks
fclose(fp); fclose(fp);
if (end != VL_UL(0xffffffff) && addr != (end+1)) { if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address"); vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address");
} }
} }
IData VL_SYSTEM_IQ(QData lhs) {
IData lhsw[2]; VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(2, lhsw);
}
IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, filenamep);
int code = system(filenamez);
return code >> 8; // Want exit status
}
IData VL_TESTPLUSARGS_I(const char* formatp) { IData VL_TESTPLUSARGS_I(const char* formatp) {
string match = VerilatedImp::argPlusMatch(formatp); string match = VerilatedImp::argPlusMatch(formatp);
if (match == "") return 0; if (match == "") return 0;
@@ -920,8 +992,12 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
const char* vl_mc_scan_plusargs(const char* prefixp) { const char* vl_mc_scan_plusargs(const char* prefixp) {
string match = VerilatedImp::argPlusMatch(prefixp); string match = VerilatedImp::argPlusMatch(prefixp);
if (match == "") return 0; static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
else return match.c_str()+strlen(prefixp)+1; // +1 to skip the "+" if (match == "") return NULL;
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
VL_VALUE_STRING_MAX_WIDTH);
outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
return outstr;
} }
//=========================================================================== //===========================================================================
@@ -967,6 +1043,15 @@ const char* Verilated::catName(const char* n1, const char* n2) {
return strp; return strp;
} }
void Verilated::flushCb(VerilatedVoidCb cb) {
if (s_flushCb == cb) {} // Ok - don't duplicate
else if (!s_flushCb) { s_flushCb=cb; }
else {
// Someday we may allow multiple callbacks ala atexit(), but until then
vl_fatal("unknown",0,"", "Verilated::flushCb called twice with different callbacks");
}
}
void Verilated::commandArgs(int argc, const char** argv) { void Verilated::commandArgs(int argc, const char** argv) {
VerilatedImp::commandArgs(argc,argv); VerilatedImp::commandArgs(argc,argv);
} }
@@ -975,6 +1060,10 @@ void Verilated::scopesDump() {
VerilatedImp::scopesDump(); VerilatedImp::scopesDump();
} }
const VerilatedScope* Verilated::scopeFind(const char* namep) {
return VerilatedImp::scopeFind(namep);
}
int Verilated::exportFuncNum(const char* namep) { int Verilated::exportFuncNum(const char* namep) {
return VerilatedImp::exportFind(namep); return VerilatedImp::exportFind(namep);
} }
@@ -990,6 +1079,23 @@ VerilatedModule::~VerilatedModule() {
if (m_namep) free((void*)m_namep); m_namep=NULL; if (m_namep) free((void*)m_namep); m_namep=NULL;
} }
//======================================================================
// VerilatedVar:: Methods
vluint32_t VerilatedVar::entSize() const {
vluint32_t size = 1;
switch (vltype()) {
case VLVT_PTR: size=sizeof(void*); break;
case VLVT_UINT8: size=sizeof(CData); break;
case VLVT_UINT16: size=sizeof(SData); break;
case VLVT_UINT32: size=sizeof(IData); break;
case VLVT_UINT64: size=sizeof(QData); break;
case VLVT_WDATA: size=VL_WORDS_I(range().bits())*sizeof(IData); break;
default: size=0; break;
}
return size;
}
//====================================================================== //======================================================================
// VerilatedScope:: Methods // VerilatedScope:: Methods
@@ -997,12 +1103,15 @@ VerilatedScope::VerilatedScope() {
m_callbacksp = NULL; m_callbacksp = NULL;
m_namep = NULL; m_namep = NULL;
m_funcnumMax = 0; m_funcnumMax = 0;
m_symsp = NULL;
m_varsp = NULL;
} }
VerilatedScope::~VerilatedScope() { VerilatedScope::~VerilatedScope() {
VerilatedImp::scopeErase(this); VerilatedImp::scopeErase(this);
if (m_namep) { delete [] m_namep; m_namep = NULL; } if (m_namep) { delete [] m_namep; m_namep = NULL; }
if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; } if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; }
if (m_varsp) { delete m_varsp; m_varsp = NULL; }
m_funcnumMax = 0; // Force callback table to empty m_funcnumMax = 0; // Force callback table to empty
} }
@@ -1027,10 +1136,10 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
// Alternative is to dynamically stretch the array, which is more code, and slower. // Alternative is to dynamically stretch the array, which is more code, and slower.
if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; } if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
} else { } else {
if (funcnum >= m_funcnumMax) { if (VL_UNLIKELY(funcnum >= m_funcnumMax)) {
vl_fatal(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum"); vl_fatal(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum");
} }
if (!m_callbacksp) { // First allocation if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
m_callbacksp = new void* [m_funcnumMax]; m_callbacksp = new void* [m_funcnumMax];
memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*)); memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
} }
@@ -1038,6 +1147,47 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
} }
} }
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
VerilatedVarType vltype, int vlflags, int dims, ...) {
// Grab dimensions
// In the future we may just create a large table at emit time and statically construct from that.
if (!finalize) return;
if (!m_varsp) m_varsp = new VerilatedVarNameMap();
VerilatedVar var (namep, datap, vltype, (VerilatedVarFlags)vlflags, dims);
va_list ap;
va_start(ap,dims);
for (int i=0; i<dims; ++i) {
int msb = va_arg(ap,int);
int lsb = va_arg(ap,int);
if (i==0) {
var.m_range.m_lhs = msb;
var.m_range.m_rhs = lsb;
} else if (i==1) {
var.m_array.m_lhs = msb;
var.m_array.m_rhs = lsb;
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
vl_fatal(__FILE__,__LINE__,"",(string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
}
}
va_end(ap);
m_varsp->insert(make_pair(namep,var));
}
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
if (VL_LIKELY(m_varsp)) {
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
if (VL_LIKELY(it != m_varsp->end())) {
return &(it->second);
}
}
return NULL;
}
void* VerilatedScope::exportFindNullError(int funcnum) const { void* VerilatedScope::exportFindNullError(int funcnum) const {
// Slowpath - Called only when find has failed // Slowpath - Called only when find has failed
string msg = (string("Testbench C called '") string msg = (string("Testbench C called '")
@@ -1058,10 +1208,17 @@ void* VerilatedScope::exportFindError(int funcnum) const {
} }
void VerilatedScope::scopeDump() const { void VerilatedScope::scopeDump() const {
VL_PRINTF(" SCOPE: %s\n", name()); VL_PRINTF(" SCOPE %p: %s\n", this, name());
for (int i=0; i<m_funcnumMax; i++) { for (int i=0; i<m_funcnumMax; i++) {
if (m_callbacksp && m_callbacksp[i]) { if (m_callbacksp && m_callbacksp[i]) {
VL_PRINTF(" DPI-EXPORT: %s\n", VerilatedImp::exportName(i)); VL_PRINTF(" DPI-EXPORT %p: %s\n",
m_callbacksp[i], VerilatedImp::exportName(i));
}
}
if (varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp()->begin();
it != varsp()->end(); ++it) {
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
} }
} }
} }
+97 -34
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -35,6 +35,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cmath>
// <iostream> avoided to reduce compile time // <iostream> avoided to reduce compile time
// <string> avoided and instead in verilated_heavy.h to reduce compile time // <string> avoided and instead in verilated_heavy.h to reduce compile time
using namespace std; using namespace std;
@@ -62,11 +63,37 @@ typedef vluint32_t WData; ///< Verilated pack data, >64 bits, as an array
typedef const WData* WDataInP; ///< Array input to a function typedef const WData* WDataInP; ///< Array input to a function
typedef WData* WDataOutP; ///< Array output from a function typedef WData* WDataOutP; ///< Array output from a function
typedef void (*VerilatedVoidCb)(void);
class SpTraceVcd; class SpTraceVcd;
class SpTraceVcdCFile; class SpTraceVcdCFile;
class VerilatedVar;
class VerilatedVarNameMap;
class VerilatedVcd; class VerilatedVcd;
class VerilatedVcdC; class VerilatedVcdC;
enum VerilatedVarType {
VLVT_UNKNOWN=0,
VLVT_PTR, // Pointer to something
VLVT_UINT8, // AKA CData
VLVT_UINT16, // AKA SData
VLVT_UINT32, // AKA IData
VLVT_UINT64, // AKA QData
VLVT_WDATA, // AKA WData
VLVT_STRING // C++ string
};
enum VerilatedVarFlags {
VLVD_IN=1, // == vpiInput
VLVD_OUT=2, // == vpiOutput
VLVD_INOUT=3, // == vpiInOut
VLVD_NODIR=5, // == vpiNoDirection
VLVF_MASK_DIR=7, // Bit mask for above directions
// Flags
VLVF_PUB_RD=(1<<8), // Public readable
VLVF_PUB_RW=(1<<9) // Public writable
};
//========================================================================= //=========================================================================
/// Base class for all Verilated module classes /// Base class for all Verilated module classes
@@ -136,6 +163,9 @@ public:
#ifndef VL_PRINTF #ifndef VL_PRINTF
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired # define VL_PRINTF printf ///< Print ala printf; may redefine if desired
#endif #endif
#ifndef VL_VPRINTF
# define VL_VPRINTF vprintf ///< Print ala vprintf; may redefine if desired
#endif
//=========================================================================== //===========================================================================
/// Verilator symbol table base class /// Verilator symbol table base class
@@ -149,19 +179,25 @@ class VerilatedSyms {
class VerilatedScope { class VerilatedScope {
// Fastpath: // Fastpath:
VerilatedSyms* m_symsp; ///< Symbol table VerilatedSyms* m_symsp; ///< Symbol table
void** m_callbacksp; ///< Callback table pointer (Fastpath) void** m_callbacksp; ///< Callback table pointer (Fastpath)
int m_funcnumMax; ///< Maxium function number stored (Fastpath) int m_funcnumMax; ///< Maxium function number stored (Fastpath)
// 4 bytes padding (on -m64), for rent. // 4 bytes padding (on -m64), for rent.
const char* m_namep; ///< Scope name (Slowpath) VerilatedVarNameMap* m_varsp; ///< Variable map
const char* m_namep; ///< Scope name (Slowpath)
public: // But internals only - called from VerilatedModule's public: // But internals only - called from VerilatedModule's
VerilatedScope(); VerilatedScope();
~VerilatedScope(); ~VerilatedScope();
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp); void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp);
void exportInsert(int finalize, const char* namep, void* cb); void exportInsert(int finalize, const char* namep, void* cb);
void varInsert(int finalize, const char* namep, void* datap,
VerilatedVarType vltype, int vlflags, int dims, ...);
// ACCESSORS // ACCESSORS
const char* name() const { return m_namep; } const char* name() const { return m_namep; }
inline VerilatedSyms* symsp() const { return m_symsp; } inline VerilatedSyms* symsp() const { return m_symsp; }
VerilatedVar* varFind(const char* namep) const;
VerilatedVarNameMap* varsp() const { return m_varsp; }
void* exportFindError(int funcnum) const; void* exportFindError(int funcnum) const;
void* exportFindNullError(int funcnum) const; void* exportFindNullError(int funcnum) const;
void scopeDump() const; void scopeDump() const;
@@ -182,7 +218,11 @@ public: // But internals only - called from VerilatedModule's
struct Verilated { struct Verilated {
// MEMBERS // MEMBERS
private: private:
// Slow path variables
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
static VerilatedVoidCb s_flushCb; ///< Flush callback function
// Fast path
static int s_debug; ///< See accessors... only when VL_DEBUG set static int s_debug; ///< See accessors... only when VL_DEBUG set
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
static bool s_gotFinish; ///< A $finish statement executed static bool s_gotFinish; ///< A $finish statement executed
@@ -224,6 +264,9 @@ public:
/// Enable/disable assertions /// Enable/disable assertions
static void assertOn(bool flag) { s_assertOn=flag; } static void assertOn(bool flag) { s_assertOn=flag; }
static bool assertOn() { return s_assertOn; } static bool assertOn() { return s_assertOn; }
/// Flush callback for VCD waves
static void flushCb(VerilatedVoidCb cb);
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs /// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
static void commandArgs(int argc, const char** argv); static void commandArgs(int argc, const char** argv);
@@ -237,6 +280,8 @@ public:
// METHODS - INTERNAL USE ONLY // METHODS - INTERNAL USE ONLY
// Internal: Create a new module name by concatenating two strings // Internal: Create a new module name by concatenating two strings
static const char* catName(const char* n1, const char* n2); // Returns new'ed data static const char* catName(const char* n1, const char* n2); // Returns new'ed data
// Internal: Find scope
static const VerilatedScope* scopeFind(const char* namep);
// Internal: Get and set DPI context // Internal: Get and set DPI context
static const VerilatedScope* dpiScope() { return t_dpiScopep; } static const VerilatedScope* dpiScope() { return t_dpiScopep; }
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; } static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
@@ -277,11 +322,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus); extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
/// File I/O /// File I/O
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq); extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode); extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
extern QData VL_FOPEN_QI(QData ofilename, IData mode); extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,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); }
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,
WDataInP ofilename, void* memp, IData start, IData end); WDataInP ofilename, void* memp, IData start, IData end);
@@ -292,15 +340,19 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); } VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...); extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(QData fpq, const char* formatp, ...); extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...); extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...); 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, 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_IQ(QData lhs);
inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); }
extern IData VL_TESTPLUSARGS_I(const char* formatp); extern IData VL_TESTPLUSARGS_I(const char* formatp);
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp); extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
@@ -320,15 +372,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) )) #define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) ) #define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
/// Return FILE* from IData
extern FILE* VL_CVT_I_FP(IData lhs);
// Use a union to avoid cast-to-different-size warnings // Use a union to avoid cast-to-different-size warnings
/// Return FILE* from QData
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return void* from QData /// Return void* from QData
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; } static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return QData from FILE*
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
/// Return QData from void* /// Return QData from void*
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; } static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
/// Return double from QData (bits, not numerically)
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
/// Return QData from double (bits, not numerically)
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
/// Return double from QData (numeric)
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
/// Return QData from double (numeric)
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(VL_TRUNC(lhs))); }
/// Return QData from double (numeric)
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUND(lhs))); }
// Sign extend such that if MSB set, we get ffff_ffff, else 0s // Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input) // (Requires clean input)
@@ -347,6 +408,9 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
//========================================================================= //=========================================================================
// Pli macros // Pli macros
#ifndef VL_TIME_PRECISION
# define VL_TIME_PRECISION -12 ///< Timescale units only for for VPI return - picoseconds
#endif
#ifndef VL_TIME_MULTIPLIER #ifndef VL_TIME_MULTIPLIER
# define VL_TIME_MULTIPLIER 1 # define VL_TIME_MULTIPLIER 1
#endif #endif
@@ -355,9 +419,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000) #if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER)) # define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER)) # define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
#else #else
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER)) # define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER)) # define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
extern double sc_time_stamp(); extern double sc_time_stamp();
#endif #endif
@@ -898,16 +964,13 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
return(owp); return(owp);
} }
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround // Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
#if 1 //defined(__GNUC__) && __GNUC__ < 3 // we can't just
static inline IData VL_UNARYMIN_I(IData data) { return -data; } //# define VL_NEGATE_I(data) (-(data))
static inline QData VL_UNARYMIN_Q(QData data) { return -data; } static inline IData VL_NEGATE_I(IData data) { return -data; }
#else static inline QData VL_NEGATE_Q(QData data) { return -data; }
# define VL_UNARYMIN_I(IData data) (-(data))
# define VL_UNARYMIN_Q(QData data) (-(data))
#endif
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){ static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
QData carry = 0; QData carry = 0;
for (int i=0; i<words; i++) { for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~lwp[i]); carry = carry + (QData)(IData)(~lwp[i]);
@@ -954,18 +1017,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
IData lneg = VL_SIGN_I(lbits,lwp[words-1]); IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
if (lneg) { // Negate lhs if (lneg) { // Negate lhs
lwusp = lwstore; lwusp = lwstore;
VL_UNARYMIN_W(words, lwstore, lwp); VL_NEGATE_W(words, lwstore, lwp);
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
} }
IData rneg = VL_SIGN_I(lbits,rwp[words-1]); IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
if (rneg) { // Negate rhs if (rneg) { // Negate rhs
rwusp = rwstore; rwusp = rwstore;
VL_UNARYMIN_W(words, rwstore, rwp); VL_NEGATE_W(words, rwstore, rwp);
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
} }
VL_MUL_W(words,owp,lwusp,rwusp); VL_MUL_W(words,owp,lwusp,rwusp);
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp) if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0; QData carry = 0;
for (int i=0; i<words; i++) { for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~owp[i]); carry = carry + (QData)(IData)(~owp[i]);
@@ -1012,12 +1075,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
IData rwstore[VL_MULS_MAX_WORDS]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); } if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); } if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if ((lsign && !rsign) || (!lsign && rsign)) { if ((lsign && !rsign) || (!lsign && rsign)) {
IData qNoSign[VL_MULS_MAX_WORDS]; IData qNoSign[VL_MULS_MAX_WORDS];
VL_DIV_WWW(lbits,qNoSign,ltup,rtup); VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign)); _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp; return owp;
} else { } else {
return VL_DIV_WWW(lbits,owp,ltup,rtup); return VL_DIV_WWW(lbits,owp,ltup,rtup);
@@ -1031,12 +1094,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
IData rwstore[VL_MULS_MAX_WORDS]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); } if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); } if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if (lsign) { // Only dividend sign matters for modulus if (lsign) { // Only dividend sign matters for modulus
IData qNoSign[VL_MULS_MAX_WORDS]; IData qNoSign[VL_MULS_MAX_WORDS];
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup); VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign)); _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp; return owp;
} else { } else {
return VL_MODDIV_WWW(lbits,owp,ltup,rtup); return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
@@ -1589,6 +1652,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
#undef _END #undef _END
// Debugging //======================================================================
#endif /*_VERILATED_H_*/ #endif /*_VERILATED_H_*/
+23 -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-2010 by Wilson Snyder. Verilator is free software; you can # Copyright 2003-2012 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.
###################################################################### ######################################################################
@@ -13,12 +13,25 @@ LINK = @CXX@
AR = ar AR = ar
RANLIB = ranlib RANLIB = ranlib
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
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 = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
######################################################################
# Make checks
ifneq ($(words $(CURDIR)),1)
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
endif
###################################################################### ######################################################################
# C Preprocessor flags # C Preprocessor flags
@@ -31,13 +44,9 @@ VK_CPPFLAGS_ALWAYS += \
-DVM_TRACE=$(VM_TRACE) \ -DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \ -DVM_COVERAGE=$(VM_COVERAGE) \
ifeq ($(VERILATOR_AUTHOR_SITE),1) # 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 \
-Wno-char-subscripts \ $(CFG_CXXFLAGS_NO_UNUSED) \
-Wno-sign-compare \
-Wno-unused-parameter \
-Wno-unused-variable \
-Wno-uninitialized \
-Werror -Werror
endif endif
@@ -84,10 +93,10 @@ VM_SUPPORT += $(VM_SUPPORT_FAST) $(VM_SUPPORT_SLOW)
##### SystemC or SystemPerl builds ##### SystemC or SystemPerl builds
ifeq ($(VM_SP_OR_SC),1) ifeq ($(VM_SP_OR_SC),1)
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC)/include CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH) LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
SC_LIBS = -lsystemc SC_LIBS = -lsystemc
ifneq ($(wildcard $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/*numeric_bit*),) ifneq ($(wildcard $(SYSTEMC_LIBDIR)/*numeric_bit*),)
# Systemc 1.2.1beta # Systemc 1.2.1beta
SC_LIBS += -lnumeric_bit -lqt SC_LIBS += -lnumeric_bit -lqt
endif endif
@@ -109,6 +118,10 @@ 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
+3 -7
View File
@@ -5,7 +5,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -27,11 +27,7 @@
`define coverage_block_off `define coverage_block_off
`endif `endif
// Hide file descriptor difference // Hide file descriptor difference - deprecated - for older versions
`ifdef verilator `define verilator_file_descriptor integer
`define verilator_file_descriptor reg [63:0]
`else
`define verilator_file_descriptor integer
`endif
`endif // guard `endif // guard
+2 -1
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can // Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License. // Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0. // Version 2.0.
@@ -25,6 +25,7 @@
#define _VERILATED_DPI_CPP_ #define _VERILATED_DPI_CPP_
#include "verilatedos.h" #include "verilatedos.h"
#include "verilated_dpi.h"
#include "verilated_imp.h" #include "verilated_imp.h"
// On MSVC++ we need svdpi.h to declare exports, not imports // On MSVC++ we need svdpi.h to declare exports, not imports
+64
View File
@@ -0,0 +1,64 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
///
/// \file
/// \brief Verilator: Common include for all Verilated C files that use DPI
///
/// This file is included automatically by Verilator at the top of
/// all C++ files it generates where DPI is used. It contains
/// DPI interface functions required by the Verilated code.
///
/// Code available from: http://www.veripool.org/verilator
///
//*************************************************************************
#ifndef _VERILATED_DPI_H_
#define _VERILATED_DPI_H_ 1 ///< Header Guard
#include "verilated.h" // Presumed done by caller
#include "svdpi.h"
//===================================================================
// SETTING OPERATORS
/// Return svBitVecVal from WData
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
}
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
}
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
// Note we ignore X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
}
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
// Note we don't create X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words; i++) owp[i].bval=0;
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
}
//======================================================================
#endif // _VERILATED_DPI_H_
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can // Copyright 2010-2012 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 -10
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can // Copyright 2009-2012 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.
@@ -31,9 +31,11 @@
#include "verilatedos.h" #include "verilatedos.h"
#include "verilated.h" #include "verilated.h"
#include "verilated_heavy.h" #include "verilated_heavy.h"
#include "verilated_syms.h"
#include <map> #include <map>
#include <vector> #include <vector>
#include <deque>
#include <string> #include <string>
class VerilatedScope; class VerilatedScope;
@@ -41,13 +43,6 @@ class VerilatedScope;
//====================================================================== //======================================================================
// Types // Types
struct VerilatedCStrCmp {
// For ordering maps keyed by const char*'s
bool operator() (const char *a, const char *b) const {
return std::strcmp(a, b) < 0;
}
};
class VerilatedImp { class VerilatedImp {
// Whole class is internal use only - Global information shared between verilated*.cpp files. // Whole class is internal use only - Global information shared between verilated*.cpp files.
@@ -55,7 +50,7 @@ class VerilatedImp {
typedef vector<string> ArgVec; typedef vector<string> ArgVec;
typedef map<pair<const void*,void*>,void*> UserMap; typedef map<pair<const void*,void*>,void*> UserMap;
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap; typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
typedef map<const char*, int> ExportNameMap; typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
// MEMBERS // MEMBERS
static VerilatedImp s_s; ///< Static Singleton; One and only static this static VerilatedImp s_s; ///< Static Singleton; One and only static this
@@ -68,9 +63,18 @@ class VerilatedImp {
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number> ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
int m_exportNext; ///< Next export funcnum int m_exportNext; ///< Next export funcnum
// File I/O
vector<FILE*> m_fdps; ///< File descriptors
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
public: // But only for verilated*.cpp public: // But only for verilated*.cpp
// CONSTRUCTORS // CONSTRUCTORS
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {} VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
m_fdps.resize(3);
m_fdps[0] = stdin;
m_fdps[1] = stdout;
m_fdps[2] = stderr;
}
~VerilatedImp() {} ~VerilatedImp() {}
// METHODS - arguments // METHODS - arguments
@@ -190,6 +194,34 @@ public: // But only for verilated*.cpp
} }
// We don't free up m_exportMap until the end, because we can't be sure // We don't free up m_exportMap until the end, because we can't be sure
// what other models are using the assigned funcnum's. // what other models are using the assigned funcnum's.
public: // But only for verilated*.cpp
// METHODS - file IO
static IData fdNew(FILE* fp) {
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
if (s_s.m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start*2);
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
}
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
s_s.m_fdps[idx] = fp;
return (idx | (1UL<<31)); // bit 31 indicates not MCD
}
static void fdDelete(IData fdi) {
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
s_s.m_fdps[idx] = NULL;
s_s.m_fdFree.push_back(idx);
}
static inline FILE* fdToFp(IData fdi) {
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
return s_s.m_fdps[idx];
}
}; };
#endif // Guard #endif // Guard
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can // Copyright 2009-2012 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.
+100
View File
@@ -0,0 +1,100 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
///
/// \file
/// \brief Verilator: Include to allow symbol inspection
///
/// This file is for inclusion by files that need to inspect
/// the symbol table. It is not included in verilated.h
/// as it requires some heavyweight C++ classes.
///
/// Code available from: http://www.veripool.org/verilator
///
//*************************************************************************
#ifndef _VERILATED_SYMS_H_
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
#include "verilated_heavy.h"
#include <map>
//======================================================================
// Types
struct VerilatedCStrCmp {
/// Ordering maps keyed by const char*'s
bool operator() (const char *a, const char *b) const {
return std::strcmp(a, b) < 0;
}
};
//===========================================================================
/// Verilator range
class VerilatedRange {
int m_lhs;
int m_rhs;
protected:
friend class VerilatedVar;
friend class VerilatedScope;
VerilatedRange() : m_lhs(0), m_rhs(0) {}
void sets(int lhs, int rhs) { m_lhs=lhs; m_rhs=rhs; }
public:
~VerilatedRange() {}
int lhs() const { return m_lhs; }
int rhs() const { return m_rhs; }
int bits() const { return (VL_LIKELY(m_lhs>=m_rhs)?(m_lhs-m_rhs+1):(m_rhs-m_lhs+1)); }
};
//===========================================================================
/// Verilator variable
class VerilatedVar {
void* m_datap; // Location of data
VerilatedVarType m_vltype; // Data type
VerilatedVarFlags m_vlflags; // Direction
VerilatedRange m_range; // First range
VerilatedRange m_array; // Array
int m_dims; // Dimensions
const char* m_namep; // Name - slowpath
protected:
friend class VerilatedScope;
VerilatedVar(const char* namep, void* datap,
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
: m_datap(datap), m_vltype(vltype), m_vlflags(vlflags), m_dims(dims), m_namep(namep) {}
public:
~VerilatedVar() {}
void* datap() const { return m_datap; }
VerilatedVarType vltype() const { return m_vltype; }
VerilatedVarFlags vldir() const { return (VerilatedVarFlags)((int)m_vlflags & VLVF_MASK_DIR); }
vluint32_t entSize() const;
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
const VerilatedRange& range() const { return m_range; }
const VerilatedRange& array() const { return m_array; }
const char* name() const { return m_namep; }
int dims() const { return m_dims; }
};
//======================================================================
/// Types
struct VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
VerilatedVarNameMap() {}
~VerilatedVarNameMap() {}
};
#endif // Guard
+45 -13
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2010 by Wilson Snyder. This program is free software; // Copyright 2001-2012 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // 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.
// //
@@ -88,6 +88,11 @@ void VerilatedVcd::open (const char* filename) {
m_filename = filename; m_filename = filename;
s_vcdVecp.push_back(this); s_vcdVecp.push_back(this);
// SPDIFF_OFF
// Set callback so an early exit will flush us
Verilated::flushCb(&flush_all);
// SPDIFF_ON
openNext (m_rolloverMB!=0); openNext (m_rolloverMB!=0);
if (!isOpen()) return; if (!isOpen()) return;
@@ -149,6 +154,39 @@ void VerilatedVcd::openNext (bool incFilename) {
m_wroteBytes = 0; m_wroteBytes = 0;
} }
void VerilatedVcd::makeNameMap() {
// Take signal information from each module and build m_namemapp
m_namemapp = new NameMap;
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
VerilatedVcdCallInfo *cip = m_callbacks[ent];
cip->m_code = nextCode();
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
}
// Though not speced, it's illegal to generate a vcd with signals
// not under any module - it crashes at least two viewers.
// If no scope was specified, prefix everything with a "top"
// This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str();
if (hiername[0] == '\t') nullScope=true;
}
if (nullScope) {
NameMap* newmapp = new NameMap;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const string& hiername = it->first;
const string& decl = it->second;
string newname = string("top");
if (hiername[0] != '\t') newname += ' ';
newname += hiername;
newmapp->insert(make_pair(newname,decl));
}
delete m_namemapp; m_namemapp=NULL;
m_namemapp = newmapp;
}
}
VerilatedVcd::~VerilatedVcd() { VerilatedVcd::~VerilatedVcd() {
close(); close();
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; } if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
@@ -196,7 +234,7 @@ void VerilatedVcd::printStr (const char* str) {
void VerilatedVcd::printQuad (vluint64_t n) { void VerilatedVcd::printQuad (vluint64_t n) {
char buf [100]; char buf [100];
sprintf(buf,"%" VL_PRI64 "u",(long long unsigned)n); sprintf(buf,"%" VL_PRI64 "u", n);
printStr(buf); printStr(buf);
} }
@@ -222,10 +260,10 @@ void VerilatedVcd::bufferFlush () {
if (VL_UNLIKELY(!isOpen())) return; if (VL_UNLIKELY(!isOpen())) return;
char* wp = m_wrBufp; char* wp = m_wrBufp;
while (1) { while (1) {
size_t remaining = (m_writep - wp); ssize_t remaining = (m_writep - wp);
if (remaining==0) break; if (remaining==0) break;
errno = 0; errno = 0;
int got = write (m_fd, wp, remaining); ssize_t got = write (m_fd, wp, remaining);
if (got>0) { if (got>0) {
wp += got; wp += got;
m_wroteBytes += got; m_wroteBytes += got;
@@ -309,13 +347,7 @@ void VerilatedVcd::dumpHeader () {
printStr(doubleToTimescale(m_timeRes).c_str()); printStr(doubleToTimescale(m_timeRes).c_str());
printStr(" $end\n"); printStr(" $end\n");
// Take signal information from each module and build m_namemapp makeNameMap();
m_namemapp = new NameMap;
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
VerilatedVcdCallInfo *cip = m_callbacks[ent];
cip->m_code = nextCode();
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
}
// Signal header // Signal header
assert (m_modDepth==0); assert (m_modDepth==0);
@@ -341,7 +373,7 @@ void VerilatedVcd::dumpHeader () {
// Skip common prefix, it must break at a space or tab // Skip common prefix, it must break at a space or tab
for (; *np && (*np == *lp); np++, lp++) {} for (; *np && (*np == *lp); np++, lp++) {}
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; } while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; }
//cout <<"hier "<<hiername<<endl<<" lp "<<lp<<endl<<" np "<<np<<endl; //printf("hier %s\n lp=%s\n np=%s\n",hiername,lp,np);
// Any extra spaces in last name are scope ups we need to do // Any extra spaces in last name are scope ups we need to do
bool first = true; bool first = true;
@@ -389,7 +421,7 @@ void VerilatedVcd::module (string name) {
} }
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep, void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
int arraynum, bool tri, bool bussed, int msb, int lsb) { int arraynum, bool tri, bool bussed, int msb, int lsb) {
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); } if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1; int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
+8 -4
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2010 by Wilson Snyder. This program is free software; // Copyright 2001-2012 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // 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.
// //
@@ -86,8 +86,8 @@ 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 size_t bufferSize() { return 256*1024; } // See below for slack calculation inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
inline size_t bufferInsertSize() { return 16*1024; } inline static size_t bufferInsertSize() { return 16*1024; }
void bufferFlush(); void bufferFlush();
void bufferCheck() { 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
@@ -99,6 +99,7 @@ private:
void closePrev(); void closePrev();
void closeErr(); void closeErr();
void openNext(); void openNext();
void makeNameMap();
void printIndent (int levelchange); void printIndent (int levelchange);
void printStr (const char* str); void printStr (const char* str);
void printQuad (vluint64_t n); void printQuad (vluint64_t n);
@@ -109,6 +110,7 @@ private:
void dumpHeader(); void dumpHeader();
void dumpPrep (vluint64_t timeui); void dumpPrep (vluint64_t timeui);
void dumpFull (vluint64_t timeui); void dumpFull (vluint64_t timeui);
// cppcheck-suppress functionConst
void dumpDone (); void dumpDone ();
inline void printCode (vluint32_t code) { inline void printCode (vluint32_t code) {
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33)); if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
@@ -116,7 +118,7 @@ private:
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33)); if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
*m_writep++ = ((char)((code)%94+33)); *m_writep++ = ((char)((code)%94+33));
} }
string stringCode (vluint32_t code) { static string stringCode (vluint32_t code) {
string out; string out;
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33)); if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
if (code>=(94*94)) out += ((char)((code/94/94)%94+33)); if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
@@ -140,6 +142,8 @@ public:
m_evcd = false; m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility m_scopeEscape = '.'; // Backward compatibility
m_wroteBytes = 0; m_wroteBytes = 0;
m_fd = 0;
m_fullDump = true;
} }
~VerilatedVcd(); ~VerilatedVcd();
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2010 by Wilson Snyder. This program is free software; // Copyright 2001-2012 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // 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.
// //
+3 -1
View File
@@ -3,7 +3,7 @@
// //
// THIS MODULE IS PUBLICLY LICENSED // THIS MODULE IS PUBLICLY LICENSED
// //
// Copyright 2001-2010 by Wilson Snyder. This program is free software; // Copyright 2001-2012 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU // 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.
// //
@@ -76,6 +76,8 @@ private:
#ifdef NC_SYSTEMC #ifdef NC_SYSTEMC
// Cadence Incisive has these as abstract functions so we must create them // Cadence Incisive has these as abstract functions so we must create them
virtual void set_time_unit( int exponent10_seconds ) {} // deprecated virtual void set_time_unit( int exponent10_seconds ) {} // deprecated
#endif
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION>=20111100)
virtual void set_time_unit( double v, sc_time_unit tu ) {} virtual void set_time_unit( double v, sc_time_unit tu ) {}
#endif #endif
+33
View File
@@ -0,0 +1,33 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//=========================================================================
///
/// \file
/// \brief Verilator: VPI implementation code
///
/// This file must be compiled and linked against all objects
/// created from Verilator or called by Verilator that use the VPI.
///
/// Code available from: http://www.veripool.org/verilator
///
//=========================================================================
#include "verilated_vpi.h"
//======================================================================
VerilatedVpi VerilatedVpi::s_s; // Singleton
vluint8_t* VerilatedVpio::s_freeHead = NULL;
//======================================================================
+857
View File
@@ -0,0 +1,857 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//=========================================================================
///
/// \file
/// \brief Verilator: VPI implementation code
///
/// This file must be compiled and linked against all objects
/// created from Verilator or called by Verilator that use the VPI.
///
/// "//-" indicates features that are as yet unimplemented.
///
/// Code available from: http://www.veripool.org/verilator
///
//=========================================================================
#ifndef CHPI_VERILATED_VPI_H
#define CHPI_VERILATED_VPI_H 1
#include "verilated.h"
#include "verilated_syms.h"
//======================================================================
// From IEEE 1800-2009 annex K
#include "vltstd/vpi_user.h"
//======================================================================
// Internal macros
// Not supported yet
#define _VL_VPI_UNIMP() \
vl_fatal(__FILE__,__LINE__,"",Verilated::catName("Unsupported VPI function: ",VL_FUNC))
//======================================================================
// Implementation
#include <set>
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
// Base VPI handled object
class VerilatedVpio {
// MEM MANGLEMENT
static vluint8_t* s_freeHead;
public:
// CONSTRUCTORS
VerilatedVpio() {}
virtual ~VerilatedVpio() {}
inline static void* operator new(size_t size) {
// We new and delete tons of vpi structures, so keep them around
// To simplify our free list, we use a size large enough for all derived types
// We reserve word zero for the next pointer, as that's safer in case a
// dangling reference to the original remains around.
static size_t chunk = 96;
if (VL_UNLIKELY(size>chunk)) vl_fatal(__FILE__,__LINE__,"", "increase chunk");
if (VL_LIKELY(s_freeHead)) {
vluint8_t* newp = s_freeHead;
s_freeHead = *((vluint8_t**)newp);
return newp+8;
} else {
// +8: 8 bytes for next
vluint8_t* newp = (vluint8_t*)(::operator new(chunk+8));
return newp+8;
}
}
inline static void operator delete(void* obj, size_t size) {
vluint8_t* oldp = ((vluint8_t*)obj)-8;
*((void**)oldp) = s_freeHead;
s_freeHead = oldp;
}
// MEMBERS
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
inline vpiHandle castVpiHandle() { return (vpiHandle)(this); }
// ACCESSORS
virtual const char* name() { return "<null>"; }
virtual const char* fullname() { return "<null>"; }
virtual const char* defname() { return "<null>"; }
virtual vpiHandle dovpi_scan() { return 0; }
};
typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
class VerilatedVpioCb : public VerilatedVpio {
t_cb_data m_cbData;
s_vpi_value m_value;
QData m_time;
public:
// cppcheck-suppress uninitVar // m_value
VerilatedVpioCb(const t_cb_data* cbDatap, QData time)
: m_cbData(*cbDatap), m_time(time) {
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
vluint32_t reason() const { return m_cbData.reason; }
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
t_cb_data* cb_datap() { return &(m_cbData); }
QData time() const { return m_time; }
};
class VerilatedVpioConst : public VerilatedVpio {
vlsint32_t m_num;
public:
VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
virtual ~VerilatedVpioConst() {}
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
vlsint32_t num() const { return m_num; }
};
class VerilatedVpioRange : public VerilatedVpio {
vlsint32_t m_lhs; // Ranges can be signed
vlsint32_t m_rhs;
bool m_iteration;
public:
VerilatedVpioRange(vlsint32_t lhs, vlsint32_t rhs) : m_lhs(lhs), m_rhs(rhs), m_iteration(0) {}
virtual ~VerilatedVpioRange() {}
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
vlsint32_t lhs() const { return m_lhs; }
vlsint32_t rhs() const { return m_rhs; }
int iteration() const { return m_iteration; }
void iterationInc() { ++m_iteration; }
virtual vpiHandle dovpi_scan() {
if (!iteration()) {
VerilatedVpioRange* nextp = new VerilatedVpioRange(*this);
nextp->iterationInc();
return ((nextp)->castVpiHandle());
} else {
return 0; // End of list - only one deep
}
}
};
class VerilatedVpioScope : public VerilatedVpio {
const VerilatedScope* m_scopep;
public:
VerilatedVpioScope(const VerilatedScope* scopep)
: m_scopep(scopep) {}
virtual ~VerilatedVpioScope() {}
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
const VerilatedScope* scopep() const { return m_scopep; }
virtual const char* name() { return m_scopep->name(); }
virtual const char* fullname() { return m_scopep->name(); }
};
class VerilatedVpioVar : public VerilatedVpio {
const VerilatedVar* m_varp;
const VerilatedScope* m_scopep;
vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange
vluint32_t m_mask; // memoized variable mask
vluint32_t m_entSize; // memoized variable size
protected:
void* m_varDatap; // varp()->datap() adjusted for array entries
vlsint32_t m_index;
public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp(varp), m_scopep(scopep), m_index(0) {
m_prevDatap = NULL;
m_mask = VL_MASK_I(varp->range().bits());
m_entSize = varp->entSize();
m_varDatap = varp->datap();
}
virtual ~VerilatedVpioVar() {
if (m_prevDatap) { delete [] m_prevDatap; m_prevDatap = NULL; }
}
static inline VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVar*>((VerilatedVpio*)h); }
const VerilatedVar* varp() const { return m_varp; }
const VerilatedScope* scopep() const { return m_scopep; }
vluint32_t mask() const { return m_mask; }
vluint32_t entSize() const { return m_entSize; }
virtual const char* name() { return m_varp->name(); }
virtual const char* fullname() {
static VL_THREAD string out;
out = string(m_scopep->name())+"."+name();
return out.c_str();
}
void* prevDatap() const { return m_prevDatap; }
void* varDatap() const { return m_varDatap; }
void createPrevDatap() {
if (VL_UNLIKELY(!m_prevDatap)) {
m_prevDatap = new vluint8_t [entSize()];
memcpy(prevDatap(), varp()->datap(), entSize());
}
}
};
class VerilatedVpioVarIndex : public VerilatedVpioVar {
public:
VerilatedVpioVarIndex(const VerilatedVar* varp, const VerilatedScope* scopep,
vlsint32_t index, int offset)
: VerilatedVpioVar(varp, scopep) {
m_index = index;
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
}
virtual ~VerilatedVpioVarIndex() {}
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
virtual const char* fullname() {
static VL_THREAD string out;
char num[20]; sprintf(num,"%d",m_index);
out = string(scopep()->name())+"."+name()+"["+num+"]";
return out.c_str();
}
};
class VerilatedVpioVarIter : public VerilatedVpio {
const VerilatedScope* m_scopep;
VerilatedVarNameMap::iterator m_it;
bool m_started;
public:
VerilatedVpioVarIter(const VerilatedScope* scopep)
: m_scopep(scopep), m_started(false) { }
virtual ~VerilatedVpioVarIter() {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) {
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
else ++m_it;
if (m_it == m_scopep->varsp()->end()) return 0;
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
->castVpiHandle());
} else {
return 0; // End of list - only one deep
}
}
};
//======================================================================
struct VerilatedVpiTimedCbsCmp {
/// Ordering sets keyed by time, then callback descriptor
bool operator() (const pair<QData,VerilatedVpioCb*>& a,
const pair<QData,VerilatedVpioCb*>& b) const {
if (a.first < b.first) return 1;
if (a.first > b.first) return 0;
return a.second < b.second;
}
};
class VerilatedVpi {
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
typedef set<VerilatedVpioCb*> VpioCbSet;
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
VpioTimedCbs m_timedCbs; // Time based callbacks
static VerilatedVpi s_s; // Singleton
public:
VerilatedVpi() {}
~VerilatedVpi() {}
static void cbReasonAdd(VerilatedVpioCb* vop) {
if (vop->reason() == cbValueChange) {
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
varop->createPrevDatap();
}
}
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
s_s.m_cbObjSets[vop->reason()].insert(vop);
}
static void cbTimedAdd(VerilatedVpioCb* vop) {
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
}
static void cbReasonRemove(VerilatedVpioCb* cbp) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
VpioCbSet::iterator it=cbObjSet.find(cbp);
if (VL_LIKELY(it != cbObjSet.end())) {
cbObjSet.erase(it);
}
}
static void cbTimedRemove(VerilatedVpioCb* cbp) {
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
s_s.m_timedCbs.erase(it);
}
}
static void callTimedCbs() {
QData time = VL_TIME_Q();
for (VpioTimedCbs::iterator it=s_s.m_timedCbs.begin(); it!=s_s.m_timedCbs.end(); ) {
if (VL_UNLIKELY(it->first <= time)) {
VerilatedVpioCb* vop = it->second;
++it; // iterator may be deleted by callback
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: timed_callback %p\n",vop););
(vop->cb_rtnp()) (vop->cb_datap());
}
else { ++it; }
}
}
static QData cbNextDeadline() {
VpioTimedCbs::iterator it=s_s.m_timedCbs.begin();
if (VL_LIKELY(it!=s_s.m_timedCbs.end())) {
return it->first;
} else {
return ~VL_ULL(0); // maxquad
}
}
static void callCbs(vluint32_t reason) {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
VerilatedVpioCb* vop = *it;
++it; // iterator may be deleted by callback
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
(vop->cb_rtnp()) (vop->cb_datap());
}
}
static void callValueCbs() {
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
VerilatedVpioCb* vop = *it;
++it; // iterator may be deleted by callback
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
void* newDatap = varop->varDatap();
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_test %s v[0]=%d/%d %p %p\n",
varop->fullname(), *((CData*)newDatap), *((CData*)prevDatap),
newDatap, prevDatap););
if (memcmp(prevDatap, newDatap, varop->entSize())) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize());
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp()) (vop->cb_datap());
}
}
}
}
};
// callback related
vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
if (VL_UNLIKELY(!cb_data_p)) return NULL;
switch (cb_data_p->reason) {
case cbAfterDelay: {
QData time = 0;
if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time);
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p delay=%" VL_PRI64 "d\n",cb_data_p->reason,vop,time););
VerilatedVpi::cbTimedAdd(vop);
return vop->castVpiHandle();
}
case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp
case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp
case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp
case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp
case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object
case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object
case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0);
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop););
VerilatedVpi::cbReasonAdd(vop);
return vop->castVpiHandle();
}
default:
_VL_VPI_UNIMP(); return NULL;
};
}
PLI_INT32 vpi_remove_cb(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_remove_cb %p\n",object););
VerilatedVpioCb* vop = VerilatedVpioCb::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->cb_datap()->reason == cbAfterDelay) {
VerilatedVpi::cbTimedRemove(vop);
} else {
VerilatedVpi::cbReasonRemove(vop);
}
return 1;
}
//-void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// for obtaining handles
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
if (VL_UNLIKELY(!namep)) return NULL;
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_name %s %p\n",namep,scope););
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
const VerilatedVar* varp;
const VerilatedScope* scopep;
string scopeAndName = namep;
if (voScopep) {
scopeAndName = string(voScopep->fullname()) + "." + namep;
namep = (PLI_BYTE8*)scopeAndName.c_str();
}
{
// This doesn't yet follow the hierarchy in the proper way
scopep = Verilated::scopeFind(namep);
if (scopep) { // Whole thing found as a scope
return (new VerilatedVpioScope(scopep))->castVpiHandle();
}
const char* baseNamep = scopeAndName.c_str();
string scopename;
const char* dotp = strrchr(namep, '.');
if (VL_LIKELY(dotp)) {
baseNamep = dotp+1;
scopename = string(namep,dotp-namep);
}
scopep = Verilated::scopeFind(scopename.c_str());
if (!scopep) return NULL;
varp = scopep->varFind(baseNamep);
}
if (!varp) return NULL;
return (new VerilatedVpioVar(varp, scopep))->castVpiHandle();
}
vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
// Used to get array entries
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_index %p %d\n",object, indx););
VerilatedVpioVar* varop = VerilatedVpioVar::castp(object);
if (VL_LIKELY(varop)) {
if (varop->varp()->dims()<2) return 0;
if (VL_LIKELY(varop->varp()->array().lhs() >= varop->varp()->array().rhs())) {
if (VL_UNLIKELY(indx > varop->varp()->array().lhs() || indx < varop->varp()->array().rhs())) return 0;
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().rhs()))
->castVpiHandle();
} else {
if (VL_UNLIKELY(indx < varop->varp()->array().lhs() || indx > varop->varp()->array().rhs())) return 0;
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().lhs()))
->castVpiHandle();
}
} else {
_VL_VPI_UNIMP(); return 0;
}
}
// for traversing relationships
vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object););
switch (type) {
case vpiLeftRange: // FALLTHRU
case vpiRightRange: {
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
vluint32_t num = ((type==vpiLeftRange)
? vop->varp()->range().lhs()
: vop->varp()->range().rhs());
return (new VerilatedVpioConst(num))->castVpiHandle();
} else if (VerilatedVpioRange* vop = VerilatedVpioRange::castp(object)) {
vluint32_t num = ((type==vpiLeftRange)
? vop->lhs()
: vop->rhs());
return (new VerilatedVpioConst(num))->castVpiHandle();
} else {
return 0;
}
}
default:
_VL_VPI_UNIMP();
return 0;
}
}
//-vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHandle2, ... ) {
//- _VL_VPI_UNIMP(); return 0;
//-}
vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_iterate %d %p\n",type,object););
switch (type) {
case vpiMemoryWord: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims() < 2) return 0;
// Unsupported is multidim list
return ((new VerilatedVpioRange(vop->varp()->array().lhs(),
vop->varp()->array().rhs()))
->castVpiHandle());
}
case vpiReg: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return ((new VerilatedVpioVarIter(vop->scopep()))
->castVpiHandle());
}
case vpiIODecl: // Skipping - we'll put under reg
case vpiNet: // Skipping - we'll put under reg
return 0;
default:
_VL_VPI_UNIMP(); return 0;
}
}
vpiHandle vpi_scan(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_scan %p\n",object););
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return NULL;
return vop->dovpi_scan();
}
// for processing properties
PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
// Leave this in the header file - in many cases the compiler can constant propagate "object"
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get %d %p\n",property,object););
switch (property) {
case vpiTimePrecision: {
return VL_TIME_PRECISION;
}
case vpiType: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return ((vop->varp()->dims()>1) ? vpiMemory : vpiReg);
}
case vpiDirection: {
// By forthought, the directions already are vpi enumerated
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
return vop->varp()->vldir();
}
case vpiVector: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
if (vop->varp()->dims()==0) return 0;
else return 1;
}
default:
_VL_VPI_UNIMP();
return 0;
}
}
//-PLI_INT64 vpi_get64(PLI_INT32 property, vpiHandle object) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_str %d %p\n",property,object););
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return NULL;
switch (property) {
case vpiName: {
return (PLI_BYTE8*)vop->name();
}
case vpiFullName: {
return (PLI_BYTE8*)vop->fullname();
}
case vpiDefName: {
return (PLI_BYTE8*)vop->defname();
}
default:
_VL_VPI_UNIMP();
return 0;
}
}
// delay processing
//-void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// value processing
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
if (VL_UNLIKELY(!value_p)) return;
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
if (value_p->format == vpiVectorVal) {
// Vector pointer must come from our memory pool
// It only needs to persist until the next vpi_get_value
static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2];
value_p->value.vector = out;
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
out[0].aval = *((CData*)(vop->varDatap()));
out[0].bval = 0;
return;
case VLVT_UINT16:
out[0].aval = *((SData*)(vop->varDatap()));
out[0].bval = 0;
return;
case VLVT_UINT32:
out[0].aval = *((IData*)(vop->varDatap()));
out[0].bval = 0;
return;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().bits());
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
}
WDataInP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
out[i].aval = datap[i];
out[i].bval = 0;
}
return;
}
case VLVT_UINT64: {
QData data = *((QData*)(vop->varDatap()));
out[1].aval = (IData)(data>>VL_ULL(32));
out[1].bval = 0;
out[0].aval = (IData)(data);
out[0].bval = 0;
return;
}
default: {
_VL_VPI_UNIMP();
return;
}
}
} else {
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
value_p->value.integer = *((CData*)(vop->varDatap()));
return;
case VLVT_UINT16:
value_p->value.integer = *((SData*)(vop->varDatap()));
return;
case VLVT_UINT32:
value_p->value.integer = *((IData*)(vop->varDatap()));
return;
case VLVT_WDATA:
case VLVT_UINT64:
// Not legal
value_p->value.integer = 0;
default:
_VL_VPI_UNIMP();
return;
}
}
}
else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
value_p->value.integer = vop->num();
return;
}
_VL_VPI_UNIMP();
}
vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
p_vpi_time time_p, PLI_INT32 flags) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value %p %p\n",object, value_p););
if (VL_UNLIKELY(!value_p)) return 0;
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value name=%s fmt=%d vali=%d\n",
vop->fullname(), value_p->format, value_p->value.integer);
VL_PRINTF("-vltVpi: varp=%p putatp=%p\n",
vop->varp()->datap(), vop->varDatap()););
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
VL_PRINTF("%%Warning: Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: %s\n",
vop->fullname());
return 0;
}
if (value_p->format == vpiVectorVal) {
if (VL_UNLIKELY(!value_p->value.vector)) return NULL;
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
*((CData*)(vop->varDatap())) = value_p->value.vector[0].aval;
return object;
case VLVT_UINT16:
*((SData*)(vop->varDatap())) = value_p->value.vector[0].aval;
return object;
case VLVT_UINT32:
*((IData*)(vop->varDatap())) = value_p->value.vector[0].aval;
return object;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().bits());
WDataOutP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
datap[i] = value_p->value.vector[i].aval;
}
return object;
}
case VLVT_UINT64: {
*((QData*)(vop->varDatap())) = _VL_SET_QII(
value_p->value.vector[1].aval,
value_p->value.vector[0].aval);
return object;
}
default: {
_VL_VPI_UNIMP();
return NULL;
}
}
} else {
switch (vop->varp()->vltype()) {
case VLVT_UINT8:
*((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_UINT16:
*((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_UINT32:
*((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_WDATA: // FALLTHRU
case VLVT_UINT64: // FALLTHRU
default:
_VL_VPI_UNIMP();
return 0;
}
}
}
_VL_VPI_UNIMP(); return NULL;
}
//-void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
//- PLI_INT32 *index_p, PLI_UINT32 num) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
//- PLI_INT32 *index_p, PLI_UINT32 num) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// time processing
//-void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
//- _VL_VPI_UNIMP();
//-}
// I/O routines
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
return VL_FOPEN_S(filenamep,"wb");
}
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
VL_FCLOSE_I(mcd); return 0;
}
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
va_list ap;
va_start(ap,formatp);
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
va_end(ap);
return chars;
}
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
va_list ap;
va_start(ap,formatp);
int chars = vpi_vprintf(formatp, ap);
va_end(ap);
return chars;
}
PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
return VL_VPRINTF(formatp, ap);
}
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
FILE* fp = VL_CVT_I_FP(mcd);
if (VL_UNLIKELY(!fp)) return 0;
int chars = vfprintf(fp, format, ap);
return chars;
}
PLI_INT32 vpi_flush(void) {
Verilated::flushCall();
return 0;
}
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
FILE* fp = VL_CVT_I_FP(mcd);
if (VL_UNLIKELY(!fp)) return 1;
fflush(fp);
return 0;
}
// utility routines
//-PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_free_object(vpiHandle object) {
return vpi_release_handle(object); // Deprecated
}
PLI_INT32 vpi_release_handle (vpiHandle object) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_release_handle %p\n",object););
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return 0;
vpi_remove_cb(object); // May not be a callback, but that's ok
delete vop;
return 1;
}
//-PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) {
//- _VL_VPI_UNIMP(); return 0;
//-}
// routines added with 1364-2001
//-PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-void *vpi_get_userdata(vpiHandle obj) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_control %d\n",operation););
switch (operation) {
case vpiFinish: {
vl_finish(__FILE__,__LINE__,"*VPI*");
return 1;
}
case vpiStop: {
vl_stop(__FILE__,__LINE__,"*VPI*");
return 1;
}
}
_VL_VPI_UNIMP(); return 0;
}
//-vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index, PLI_INT32 *index_array) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//======================================================================
#endif // Guard
+37 -3
View File
@@ -1,7 +1,7 @@
// -*- C++ -*- // -*- C++ -*-
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -126,8 +126,13 @@ typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibili
typedef long vlsint32_t; ///< 32-bit signed type typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type typedef unsigned long vluint32_t; ///< 32-bit unsigned type
# endif # endif
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else
typedef long long vlsint64_t; ///< 64-bit signed type typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#elif defined(_WIN32) && defined(_MSC_VER) #elif defined(_WIN32) && defined(_MSC_VER)
@@ -141,6 +146,14 @@ typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
typedef signed __int64 vlsint64_t; ///< 64-bit signed type typedef signed __int64 vlsint64_t; ///< 64-bit signed type
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
# ifndef _SSIZE_T_DEFINED
# ifdef _WIN64
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
# else
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
# endif
# endif
#else // Linux or compliant Unix flavors, -m64 #else // Linux or compliant Unix flavors, -m64
# include <stdint.h> // Linux and most flavors # include <stdint.h> // Linux and most flavors
@@ -149,8 +162,13 @@ typedef uint8_t vluint8_t; ///< 32-bit unsigned type
typedef uint16_t vluint16_t; ///< 32-bit unsigned type typedef uint16_t vluint16_t; ///< 32-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type typedef int vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit signed type typedef uint32_t vluint32_t; ///< 32-bit signed type
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
typedef long vlsint64_t; ///< 64-bit signed type
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
# else
typedef long long vlsint64_t; ///< 64-bit signed type typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# endif
#endif #endif
//========================================================================= //=========================================================================
@@ -160,7 +178,11 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#ifdef _WIN32 #ifdef _WIN32
# define VL_PRI64 "I64" # define VL_PRI64 "I64"
#else // Linux or compliant Unix flavors #else // Linux or compliant Unix flavors
# define VL_PRI64 "ll" # if defined(__WORDSIZE) && (__WORDSIZE == 64)
# define VL_PRI64 "l"
# else
# define VL_PRI64 "ll"
# endif
#endif #endif
//========================================================================= //=========================================================================
@@ -199,6 +221,18 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long #define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad #define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
//=========================================================================
// Floating point
// #defines, to avoid requiring math.h on all compile runs
#ifdef _MSC_VER
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
#else
# define VL_TRUNC(n) trunc(n)
# define VL_ROUND(n) round(n)
#endif
//========================================================================= //=========================================================================
#endif /*guard*/ #endif /*guard*/
File diff suppressed because it is too large Load Diff
+137 -42
View File
@@ -40,70 +40,96 @@ Modify the later visitor functions to process the new feature as needed.
=back =back
=head1 DEBUG OUTPUT/ TREE FILES =head1 CODE FLOWS
When you run with --debug there are two primary output file types placed into =head2 Verilator Flow
the obj_dir, .tree and .dot files.
=head2 .dot output The main flow of Verilator can be followed by reading the Verilator.cpp
process() function:
Dot files are dumps of internal graphs in Graphviz First, the files specified on the command line are read. Reading involves
L<http://www.graphviz.org/> dot format. When a dot file is dumped, preprocessing, then lexical analysis with Flex and parsing with Bison.
Verilator will also print a line on stdout that can be used to format the This produces an abstract syntax tree (AST) representation of the design,
output, for example: which is what is visible in the .tree files described below.
dot -Tps -o ~/a.ps obj_dir/Vtop_foo.dot Cells are then linked, which will read and parse additional files as above.
You can then print a.ps. You may prefer gif format, which doesn't get Functions, variable and other references are linked to their definitions.
scaled so can be more useful with large graphs.
For dynamic graph viewing consider ZGRViewer Parameters are resolved and the design is elaborated.
L<http://zvtm.sourceforge.net/zgrviewer.html>. If you know of better
viewers let us know; ZGRViewer isn't great for large graphs.
=head2 .tree output Verilator then performs many additional edits and optimizations on the
hierarchical design. This includes coverage, assertions, X elimination,
inlining, constant propagation, and dead code elimination.
Tree files are dumps of the AST Tree and are produced between every major References in the design are then psudo-flattened. Each module's variables
algorithmic stage. An example: and functions get "Scope" references. A scope reference is an occurrence of
that un-flattened variable in the flattened hierarchy. A module that occurs
only once in the hierarchy will have a single scope and single VarScope for
each variable. A module that occurs twice will have a scope for each
occurrence, and two VarScopes for each variable. This allows optimizations
to proceed across the flattened design, while still preserving the
hierarchy.
NETLIST 0x90fb00 <e1> {0} w0 Additional edits and optimizations proceed on the psudo-flat design. These
1: MODULE 0x912b20 <e8822> {8} w0 top L2 [P] include module references, function inlining, loop unrolling, variable
*1:2: VAR 0x91a780 <e74#> {22} w70 out_wide [O] WIRE lifetime analysis, lookup table creation, always splitting, and logic gate
1:2:1: BASICDTYPE 0x91a3c0 <e73> {22} w70 [logic] simplifications (pushing inverters, etc).
=over 4 Verilator orders the code. Best case, this results in a single "eval"
function which has all always statements flowing from top to bottom with no
loops.
"1:2:" indicates the hierarchy the VAR is op2p under the MODULE. Verilator mostly removes the flattening, so that code may be shared between
multiple invocations of the same module. It localizes variables, combines
identical functions, expands macros to C primitives, adds branch prediction
hints, and performs additional constant propagation.
"VAR" is the AstNodeType. Verilator finally writes the C++ modules.
"0x91a780" is the address of this node. =head2 Verilated Flow
"<e74>" means the 74th edit to the netlist was the last modification to The evaluation loop outputted by Verilator is designed to allow a single
this node. A trailing # indicates this node changed since the last tree function to perform evaluation under most situations.
dump was made. You can gdb break on this edit; see below.
"{22}" indicates this node is related to line 22 in the source. On the first evaluation, the Verilated code calls initial blocks, and then
"settles" the modules, by evaluating functions (from always statements)
until all signals are stable.
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits. On other evaluations, the Verilated code detects what input signals have
changes. If any are clocks, it calls the appropriate sequential functions
(from always @ posedge statements). Interspersed with sequential functions
it calls combo functions (from always @*). After this is complete, it
detects any changes due to combo loops or internally generated clocks, and
if one is found must reevaluate the model again.
"out_wide" is the name of the node, in this case the name of the variable. For SystemC code, the eval() function is wrapped in a SystemC SC_METHOD,
sensitive to all inputs. (Ideally it would only be sensitive to clocks and
combo inputs, but tracing requires all signals to cause evaluation, and the
performance difference is small.)
"[O]" are flags which vary with the type of node, in this case it means the If tracing is enabled, a callback examines all variables in the design for
variable is an output. changes, and writes the trace for each change. To accelerate this process
the evaluation process records a bitmask of variables that might have
changed; if clear, checking those signals for changes may be skipped.
=back =head1 CODING CONVENTIONS
=head1 TESTING =head2 Indentation style
To write a test see notes in the forum and in the verilator.txt manual. To match the indentation of Verilator C++ sources, use 4 spaces per level,
and leave tabs at 8 columns, so every other indent level is a tab stop.
Note you can run the regression tests in parallel; see the In Emacs, use in your ~/.emacs
test_regress/driver.pl script -j flag.
=head1 VISITOR FUNCTIONS (add-hook 'c-mode-common-hook '(lambda ()
(c-set-style "cc-mode"))))
=head2 Passing Variables This sets indentation to the cc-mode defaults. (Verilator predates a
CC-mode change of several years ago which overrides the defaults with GNU
style indentation; the c-set-style undoes that.)
=head2 Visitor Functions
There's three ways data is passed between visitor functions. There's three ways data is passed between visitor functions.
@@ -146,7 +172,71 @@ more messy than the above and is deprecated. (V3Width was nearly the first
module written. Someday this scheme may be removed, as it slows the module written. Someday this scheme may be removed, as it slows the
program down to have to pass vup everywhere.) program down to have to pass vup everywhere.)
=head1 DEBUGGING WITH GDB =head1 TESTING
To write a test see notes in the forum and in the verilator.txt manual.
Note you can run the regression tests in parallel; see the
test_regress/driver.pl script -j flag.
=head1 DEBUGGING
=head2 --debug
When you run with --debug there are two primary output file types placed into
the obj_dir, .tree and .dot files.
=head2 .dot output
Dot files are dumps of internal graphs in Graphviz
L<http://www.graphviz.org/> dot format. When a dot file is dumped,
Verilator will also print a line on stdout that can be used to format the
output, for example:
dot -Tps -o ~/a.ps obj_dir/Vtop_foo.dot
You can then print a.ps. You may prefer gif format, which doesn't get
scaled so can be more useful with large graphs.
For dynamic graph viewing consider ZGRViewer
L<http://zvtm.sourceforge.net/zgrviewer.html>. If you know of better
viewers let us know; ZGRViewer isn't great for large graphs.
=head2 .tree output
Tree files are dumps of the AST Tree and are produced between every major
algorithmic stage. An example:
NETLIST 0x90fb00 <e1> {a0} w0
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
=over 4
"1:2:" indicates the hierarchy the VAR is op2p under the MODULE.
"VAR" is the AstNodeType.
"0x91a780" is the address of this node.
"<e74>" means the 74th edit to the netlist was the last modification to
this node. A trailing # indicates this node changed since the last tree
dump was made. You can gdb break on this edit; see below.
"{a22}" indicates this node is related to line 22 in the source filename
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
"out_wide" is the name of the node, in this case the name of the variable.
"[O]" are flags which vary with the type of node, in this case it means the
variable is an output.
=back
=head2 Debugging with GDB
The test_regress/driver.pl script accepts --debug --gdb to start Verilator The test_regress/driver.pl script accepts --debug --gdb to start Verilator
under gdb. You can also use --debug --gdbbt to just backtrace and then under gdb. You can also use --debug --gdbbt to just backtrace and then
@@ -157,11 +247,16 @@ what made a <e####> line in the tree dumps):
watch AstNode::s_editCntGbl==#### watch AstNode::s_editCntGbl==####
To print a node:
call nodep->dumpGdb() # aliased to "pn" in .gdbinit
call nodep->dumpTreeGdb() # aliased to "pnt" in .gdbinit
=head1 DISTRIBUTION =head1 DISTRIBUTION
The latest version is available from L<http://www.veripool.org/>. The latest version is available from L<http://www.veripool.org/>.
Copyright 2008-2010 by Wilson Snyder. Verilator is free software; you can Copyright 2008-2012 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-2010 by Wilson Snyder. This package is free software; you # Copyright 2007-2012 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-2010 by Wilson Snyder. This package is free software; you # Copyright 2007-2012 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
@@ -38,7 +38,7 @@ cwrite ("graph_export.cpp");
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can Copyright 2005-2012 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.
+2 -2
View File
@@ -43,7 +43,7 @@ dotwrite();
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can Copyright 2005-2012 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-2010 by Wilson Snyder. This package is free software; you # Copyright 2007-2012 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.
+79 -13
View File
@@ -12,17 +12,23 @@ use vars qw ($Debug);
#====================================================================== #======================================================================
# main # main
our $Opt_Stage = 0;
our $Opt_Jobs = calc_jobs();
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev"); Getopt::Long::config ("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions (
"debug" => sub { $Debug = 1; }, "debug" => sub { $Debug = 1; },
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; }, "<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
"stage=i" => \$Opt_Stage,
"j=i" => \$Opt_Jobs,
)) { )) {
die "%Error: Bad usage, try 'install_test --help'\n"; die "%Error: Bad usage, try 'install_test --help'\n";
} }
test(); test();
exit(0);
####################################################################### #######################################################################
@@ -37,33 +43,74 @@ sub test {
my $srcdir = getcwd(); my $srcdir = getcwd();
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld"; my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix"; my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
my $testdir = $srcdir."/test_regress/obj_dir/install_test_test"; my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp";
if (1) { my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
if ($Opt_Stage <= 0) {
run("/bin/rm -rf $blddir"); run("/bin/rm -rf $blddir");
run("/bin/mkdir -p $blddir"); run("/bin/mkdir -p $blddir");
run("cd $blddir && $srcdir/configure --prefix $prefix"); run("cd $blddir && $srcdir/configure --prefix $prefix");
run("cd $blddir && make -j"); run("cd $blddir && make -j $Opt_Jobs");
} }
# Install it under the prefix # Install it under the prefix
if (1) { if ($Opt_Stage <= 1) {
run("/bin/rm -rf $prefix"); run("/bin/rm -rf $prefix");
run("/bin/mkdir -p $prefix"); run("/bin/mkdir -p $prefix");
run("cd $blddir && make install"); run("cd $blddir && make install");
run("test -e $prefix/share/man/man1/verilator.1");
run("test -e $prefix/share/verilator/examples/test_c/Makefile");
run("test -e $prefix/share/verilator/include/verilated.h");
run("test -e $prefix/bin/verilator");
run("test -e $prefix/bin/verilator_bin");
run("test -e $prefix/bin/verilator_bin_dbg");
run("test -e $prefix/bin/verilator_profcfunc");
} }
# Run a test using just the path # Run a test using just the path
if (1) { if ($Opt_Stage <= 2) {
run("/bin/rm -rf $testdir"); my $dir = $testdirp;
run("/bin/mkdir -p $testdir"); run("/bin/rm -rf $dir");
run("/bin/mkdir -p $dir");
my $bin1 = $prefix."/bin"; my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin"; my $bin2 = $prefix."/share/bin";
IO::File->new(">$testdir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); end endmodule'."\n"); write_verilog($dir);
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc --exe foo.v"); run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
run("cd $testdir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk"); run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
#Need .c file for this to work run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
#run("cd $testdir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
} }
# Run a test using exact path to binary
if ($Opt_Stage <= 3) {
my $dir = $testdirn;
run("/bin/rm -rf $dir");
run("/bin/mkdir -p $dir");
write_verilog($dir);
my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin";
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
run("cd $dir/obj_dir && make -f Vfoo.mk");
run("cd $dir/obj_dir && ./Vfoo");
}
}
sub write_verilog {
my $dir = shift;
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
my $fh = IO::File->new(">$dir/foo.cpp");
$fh->print('#include "Vfoo.h"' ,"\n");
$fh->print('unsigned int main_time = 0;' ,"\n");
$fh->print('double sc_time_stamp () {' ,"\n");
$fh->print(' return main_time;' ,"\n");
$fh->print('}' ,"\n");
$fh->print('int main() {' ,"\n");
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
$fh->print(' top->eval();' ,"\n");
$fh->print(' main_time++;' ,"\n");
$fh->print(' }' ,"\n");
$fh->print(' top->final();' ,"\n");
$fh->print('}' ,"\n");
} }
sub cleanenv { sub cleanenv {
@@ -77,6 +124,16 @@ sub cleanenv {
####################################################################### #######################################################################
sub calc_jobs {
my $ok = eval "
use Unix::Processors;
return Unix::Processors->new->max_online;
";
$ok && !$@ or return 1;
print "driver.pl: Found $ok cores, using -j ",$ok+1,"\n" if $Debug;
return $ok + 1;
}
sub run { sub run {
# Run a system command, check errors # Run a system command, check errors
my $command = shift; my $command = shift;
@@ -113,11 +170,20 @@ required.
Displays this message and program version and exits. Displays this message and program version and exits.
=item -j I<jobs>
Specify make -j flag. Defaults to number of cores + 1 if Perl's
Unix::Processors is installed, else 1.
=item -stage I<stage>
Runs a specific test stage (see the script).
=back =back
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2009-2010 by Wilson Snyder. This package is free software; you Copyright 2009-2012 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.
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/perl -w
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
use strict;
#======================================================================
# main
eval `modulecmd perl add axiom-athdl`;
exec('atsim',@ARGV);
#######################################################################
__END__
=pod
=head1 NAME
invoke_atsim - Invoke tool under "modules" command
=head1 SYNOPSIS
invoke_atsim {ncv arguments}
=head1 DESCRIPTION
=head1 DISTRIBUTION
Copyright 2005-2012 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./invoke_atsim -help"
### End:
+2 -14
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add cds-ius`;
_setup_modules();
module('add','cadence-ius');
exec('iccr',@ARGV); exec('iccr',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
####################################################################### #######################################################################
__END__ __END__
@@ -40,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2007-2010 by Wilson Snyder. This package is free software; you Copyright 2007-2012 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 -14
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add cds-ius`;
_setup_modules();
module('add','cadence-ius');
exec('ncverilog',@ARGV); exec('ncverilog',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
####################################################################### #######################################################################
__END__ __END__
@@ -40,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. This package is free software; you Copyright 2005-2012 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 -14
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add synopsys-vcs`;
_setup_modules();
module('add','synopsys-vcs');
exec('vcs',@ARGV); exec('vcs',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "$ENV{MODULESHOME}/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
####################################################################### #######################################################################
__END__ __END__
@@ -40,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. This package is free software; you Copyright 2005-2012 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0. Version 2.0.
+3 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
###################################################################### ######################################################################
# #
# Copyright 2010-2010 by Wilson Snyder. This package is free software; you # Copyright 2010-2012 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.
@@ -81,6 +81,7 @@ sub prep {
$line =~ s/SP_NOTICE.*// if $sp; $line =~ s/SP_NOTICE.*// if $sp;
$line =~ s/vl_fatal.*// if !$sp; $line =~ s/vl_fatal.*// if !$sp;
$line =~ s/VL_PRINT.*// if !$sp; $line =~ s/VL_PRINT.*// if !$sp;
$line =~ s/Copyright \d+-\d+/Copyright #-#/g;
push @wf, $line; push @wf, $line;
@@ -126,6 +127,7 @@ sub prep {
# #
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g; $wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
$wholefile =~ s/%ll/%" VL_PRI64 "/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_SC_BV/VL_SC_BV/g;
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g; $wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
+3 -3
View File
@@ -40,7 +40,7 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -256,7 +256,7 @@ sub gentree {
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; }, 'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; }, 'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
'UNARYMIN' => sub { p " -";p1; }, 'NEGATE' => sub { p " -";p1; },
'VAR' => sub { p_var(); }, 'VAR' => sub { p_var(); },
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'VARREF' => sub { a1; }, 'VARREF' => sub { a1; },
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION =head1 DISTRIBUTION
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can Copyright 2005-2012 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.
+48 -22
View File
@@ -9,7 +9,7 @@ This is the Verilator Package README file.
=head1 DISTRIBUTION =head1 DISTRIBUTION
This package is Copyright 2003-2010 by Wilson Snyder. (Report bugs to This package is Copyright 2003-2012 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
@@ -72,15 +72,10 @@ Download the latest package from that site, and decompress.
If you will be using SystemC (vs straight C++ output), download SystemC If you will be using SystemC (vs straight C++ output), download SystemC
2.0.1 from L<http://www.systemc.org>. Follow their installation 2.0.1 from L<http://www.systemc.org>. Follow their installation
instructions. As described in the System-Perl README, you will need to set instructions. You will need to set SYSTEMC_INCLUDE to point to the
SYSTEMC and/or SYSTEMC_KIT to point to this download. Also, set include directory with systemc.h in it, and SYSTEMC_LIBDIR to points
SYSTEMC_ARCH to the architecture name you used with SystemC, generally to the directory with libsystemc.a in it. (Older installations may
'linux' or 'cygwin'. set SYSTEMC and SYSTEMC_ARCH instead.)
=item
If you will be using SystemPerl or coverage, download and install
Verilog-Perl, L<http://www.veripool.org/verilog-perl>.
=item =item
@@ -92,26 +87,59 @@ headers.
=item =item
You will need the C<flex> and C<bison> packages installed.
=item
C<cd> to the Verilator directory containing this README. C<cd> to the Verilator directory containing this README.
=item =item
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,
SYSTEMC_LIBDIR, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
executable, so try to have them correct before configuring.
=over 4
=item 1.
Our personal favorite is to always run Verilator from the kit directory. Our personal favorite is to always run Verilator from the kit directory.
This allows the easiest experimentation and upgrading. It's also how most This allows the easiest experimentation and upgrading. It's also how most
EDA tools operate; you just point to the tarball. EDA tools operate; to run any of them you point to the tarball.
export VERILATOR_ROOT=`pwd` # if your shell is bash export VERILATOR_ROOT=`pwd` # if your shell is bash
setenv VERILATOR_ROOT `pwd` # if your shell is csh setenv VERILATOR_ROOT `pwd` # if your shell is csh
./configure ./configure
=item 2.
To install globally onto a "cad" disk with multiple versions of every tool,
and add it to path using Modules/modulecmd:
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
# For the tarball, use the version number instead of git describe
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
After installing you'll want a module file like the following:
set install_root /CAD_DISK/verilator/{version-number-used-above}
setenv VERILATOR_ROOT $install_root
prepend-path PATH $install_root/bin
prepend-path MANPATH $install_root/man
=item 3.
The next option is to install it globally, using the normal system paths: The next option is to install it globally, using the normal system paths:
unset VERILATOR_ROOT # if your shell is bash unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh unsetenv VERILATOR_ROOT # if your shell is csh
./configure ./configure
=item 4.
Alternatively you can configure a prefix that install will populate, as Alternatively you can configure a prefix that install will populate, as
most GNU tools support: most GNU tools support:
@@ -119,11 +147,10 @@ most GNU tools support:
unsetenv VERILATOR_ROOT # if your shell is csh unsetenv VERILATOR_ROOT # if your shell is csh
./configure --prefix /opt/verilator-VERSION ./configure --prefix /opt/verilator-VERSION
Finally, if you are configuring Verilator to be part of a RPM or other Then after installing you will need to add /opt/verilator-VERSION/bin to
distribution package system, you may want to tune the various install PATH.
directories and use the --enable-defenv configure flag. This will take the
current value of VERILATOR_ROOT, SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and =back
SYSTEMPERL_INCLUDE and build them as defaults into the executable.
=item =item
@@ -141,16 +168,15 @@ unsigned long uint32_t;}.
=item =item
If you used the VERILATOR_ROOT sheme you're done. Programs should set the If you used the VERILATOR_ROOT scheme you're done. Programs should set the
environment variable VERILATOR_ROOT to point to this distribution, then environment variable VERILATOR_ROOT to point to this distribution, then
execute $VERILATOR_ROOT/bin/verilator, which will find the path to all execute $VERILATOR_ROOT/bin/verilator, which will find the path to all
needed files. needed files.
If you used the prefix scheme, now do a C<make install>. If you used the prefix scheme, now do a C<make install>. To run verilator,
have the verilator binary directory in your PATH (this should already be
Verilator assumes you did a make in the SystemC kit directory. If not, you true if using the default configure), and make sure VERILATOR_ROOT is not
will need to populate C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux> set.
appropriately.
=back =back
-197
View File
@@ -1,197 +0,0 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename readme.info
@settitle Verilator Installation
@c %**end of header
@c DESCRIPTION: TexInfo: DOCUMENT source run through texinfo to produce README file
@c Use 'make README' to produce the output file
@c Before release, run C-u C-c C-u C-a (texinfo-all-menus-update)
@node Top, Copyright, (dir), (dir)
@chapter Verilator
This is the Verilator Package.
@menu
* Copyright::
* Description::
* Obtaining Distribution::
* Directory Structure::
* Supported Systems::
* Installation::
* Limitations::
@end menu
@node Copyright, Description, Top, Top
@section Copyright
This package is Copyright 2003-2010 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
Verilator is free software; you can redistribute it and/or modify it
under the terms of either the GNU Lesser General Public License
Version 3 or the Perl Artistic License Version 2.0. (See the
documentation for more details.)
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.
@node Description, Obtaining Distribution, Copyright, Top
@section Description
Verilator converts synthesizable (not behavioral) Verilog code into C++ or
SystemC code. It is not a complete simulator, just a translator.
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
reads the specified Verilog code, lints it, and optionally adds coverage
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
it outputs .sp files for the SystemPerl preprocessor available at
http://www.veripool.org.
The resulting files are then compiled with C++. The user writes a little
C++ wrapper file, which instantiates the top level module. This is
compiled in C++, and linked with the Verilated files.
The resulting executable will perform the actual simulation.
@node Obtaining Distribution, Directory Structure, Description, Top
@section Obtaining Distribution
The latest version is available at
@uref{http://www.veripool.org/verilator}
Download the latest package from that site, and decompress.
@samp{tar xvzf verilator_version.tgz}
@node Directory Structure, Supported Systems, Obtaining Distribution, Top
@section Directory Structure
The directories after de-taring are as follows:
@itemize @bullet
@item bin/verilator => Compiler Wrapper invoked on user Verilog code
@item include/ => Files that should be in your -I compiler path
@item include/verilated.cpp => Global routines to link into your simulator
@item include/verilated.h => Global headers
@item include/verilated.v => Stub defines for linting
@item include/verilated.mk => Common makefile
@item src/ => Translator source code
@item test_v => Example Verilog code for other test dirs
@item test_c => Example Verilog->C++ conversion
@item test_sc => Example Verilog->SystemC conversion
@item test_sp => Example Verilog->SystemPerl conversion
@item test_vcs => Example Verilog->VCS conversion (test the test)
@item test_verilated => Internal tests
@item test_regress => Internal tests
@end itemize
@node Supported Systems, Installation, Directory Structure, Top
@section Supported Systems
This version of verilator has been built and tested on:
@itemize @bullet
@item SuSE AMD64 i686-linux-2.6.5
@end itemize
Other users report success with Redhat Linux 2.4, Windows under
Cygwin, HPUX and Solaris. It should run with minor porting on any
Unix system.
@node Installation, Limitations, Supported Systems, Top
@section Installation
@enumerate
@item
If you will be using SystemC (vs straight C++ output), download
SystemC 2.0.1 from @url{http://www.systemc.org}. Follow their
installation instructions. As described in the System-Perl README,
you will need to set SYSTEMC and/or SYSTEMC_KIT to point to this
download. Also, set SYSTEMC_ARCH to the architecture name you used
with SystemC, generally 'linux' or 'cygwin'.
@item
If you will be using SystemC, download and install Verilog-Perl,
@url{http://search.cpan.org/search?module=Verilog::Language}.
@item
If you will be using SystemC, download and install System-Perl,
@url{http://search.cpan.org/search?module=SystemC::Netlist}. Note
you'll need to set a @samp{SYSTEMPERL} environment variable to point
to the downloaded kit. Optionally also set @samp{SYSTEMPERL_INCLUDE}
to point to the installed headers.
@item
@code{cd} to the Verilator directory containing this README.
@item
Type @samp{./configure} to configure Verilator for your system.
If you are configuring Verilator to be part of a RPM or other
distribution package system, you may want to use the --enable-defenv
configure flag. This will take the current value of VERILATOR_ROOT,
SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE and build
them as defaults into the executable.
@item
Type @samp{make} to compile Verilator.
On Cygwin (Windows) you may get a error about libperl.a not being
found. You need to copy your perl libraries as follows.
@enumerate
@item
Type @samp{perl -MExtUtils::Embed -e ldopts}
@item
It will show a directory name ending in /CORE. cd to that directory.
@item
@samp{cp libperl5_6_1.a libperl.a}
@item
@samp{cp libperl5_6_1.dll libperl.dll}
@item
@samp{cp libperl5_6_1.def libperl.def}
@end enumerate
@item
Type @samp{make test} to check the compilation.
You may get a error about the Bit::Vector perl package. You will need to install
it if you want the tests to pass. (Try @samp{make test_c} for a smaller test that
doesn't require it.)
You may get a error about a typedef conflict for uint32_t. Edit verilated.h to change
the typedef to work, probably to @samp{typedef unsigned long uint32_t;}.
If you get warnings, you might want to edit @samp{include/verilated.mk} to delete the
lines that define VK_CPPFLAGS_WALL.
@item
There is no installation at present; this package runs from the
distribution directory. Programs should set the environment variable
VERILATOR_ROOT to point to this distribution, then execute
$VERILATOR_ROOT/bin/verilator, which will find the path to all needed
files.
Verilator assumes you did a make in the SystemC kit directory. If not, you will need
to populate @samp{$SYSTEMC/include} and @samp{$SYSTEMC/lib-linux} appropriately.
If you will be modifying Verilator, you will probably want a second
stable copy of this kit for others to use while you experiment.
@item
Detailed documentation and the man page can be seen by running:
bin/verilator --help
or reading verilator.txt in the same directory as this README.
@end enumerate
@node Limitations, , Installation, Top
@section Limitations
See verilator.txt (or execute @samp{bin/verilator --help}) for limitations.
+20
View File
@@ -0,0 +1,20 @@
# DESCRIPTION: Verilator: GDB startup file with useful defines
#
# Copyright 2012-2012 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
define pn
call $arg0->dumpGdb()
end
document pn
Verilator: Print single AstNode NODEP
end
define pnt
call $arg0->dumpTreeGdb()
end
document pnt
Verilator: Print AstNode NODEP's tree
end
+16 -23
View File
@@ -7,7 +7,7 @@
# #
#***************************************************************************** #*****************************************************************************
# #
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can # Copyright 2003-2012 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,6 +24,7 @@
srcdir = @srcdir@ srcdir = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
PERL = @PERL@ PERL = @PERL@
EXEEXT = @EXEEXT@
#### End of system configuration section. #### #### End of system configuration section. ####
@@ -32,21 +33,11 @@ default: dbg opt
debug: dbg debug: dbg
optimize: opt optimize: opt
ifeq ($(OBJCACHE_HOSTS),) ifneq ($(words $(CURDIR)),1)
ifneq ($(SLCHOOSED_HOST),) $(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
ifeq ($(VERILATOR_AUTHOR_SITE),1)
export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnames)
endif
endif
endif endif
ifeq ($(OBJCACHE_JOBS),) UNDER_GIT = $(wildcard ${srcdir}/../.git/logs/HEAD)
ifneq ($(OBJCACHE_HOSTS),)
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
endif
endif
UNDER_GIT = $(wildcard ../.git/logs/HEAD)
#********************************************************************* #*********************************************************************
@@ -61,26 +52,25 @@ 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
../verilator_bin: ../verilator_bin_dbg ../verilator_bin: ../verilator_bin_dbg
-rm -rf $@ $@.exe -rm -rf $@ $@.exe
-cp -p $< $@ -cp -p $<$(EXEEXT) $@$(EXEEXT)
-cp -p $<.exe $@.exe
else else
../verilator_bin: obj_opt prefiles ../verilator_bin: obj_opt prefiles
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
cd obj_opt && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ -f ../Makefile_obj cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
endif endif
dbg: ../verilator_bin_dbg dbg: ../verilator_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) $(OBJCACHE_JOBS) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
prefiles:: prefiles::
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
prefiles:: config_rev.h prefiles:: config_rev.h
# This output goes into srcdir, as we need to distribute it as part of the kit. # This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
config_rev.h: config_rev.pl ../.git/logs/HEAD config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
$(PERL) config_rev.pl . >$@ $(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
endif endif
maintainer-copy:: maintainer-copy::
@@ -92,3 +82,6 @@ clean mostlyclean distclean maintainer-clean::
distclean maintainer-clean:: distclean maintainer-clean::
-rm -f Makefile Makefile_obj config_build.h -rm -f Makefile Makefile_obj config_build.h
maintainer-clean::
-rm -f config_rev.h
+26 -21
View File
@@ -7,7 +7,7 @@
# #
#***************************************************************************** #*****************************************************************************
# #
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can # Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
@@ -27,7 +27,7 @@ config_srcdir = @srcdir@
ifeq ($(config_srcdir),.) ifeq ($(config_srcdir),.)
srcdir = .. srcdir = ..
else # Run an experiment else # Run an experiment
ifeq ($(shell -e $(config_srcdir)/../Makefile_obj.in),) ifeq ($(wildcard $(config_srcdir)/../Makefile_obj.in),)
srcdir = $(config_srcdir) srcdir = $(config_srcdir)
else else
srcdir = $(config_srcdir)/.. srcdir = $(config_srcdir)/..
@@ -57,9 +57,11 @@ datarootdir = @datarootdir@
pkgdatadir = @pkgdatadir@ pkgdatadir = @pkgdatadir@
# Compile options # Compile options
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@ CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CPPFLAGSNOWALL += @CPPFLAGS@ CPPFLAGS += @CPPFLAGS@
LDFLAGS += @LDFLAGS@ LDFLAGS += @LDFLAGS@
EXEEXT = @EXEEXT@
#### End of system configuration section. #### #### End of system configuration section. ####
@@ -85,17 +87,18 @@ endif
# -lfl not needed as Flex invoked with %nowrap option # -lfl not needed as Flex invoked with %nowrap option
LIBS = -lm LIBS = -lm
CPPFLAGSNOWALL += -MMD CPPFLAGS += -MMD
CPPFLAGSNOWALL += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages CPPFLAGS += -DYYDEBUG # Required to get nice error messages
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool #CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
CPPFLAGSNOWALL += $(COPT) CPPFLAGS += $(COPT)
CPPFLAGS = $(CPPFLAGSNOWALL) CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
CPPFLAGSNOWALL += -MP # Only works on recent GCC versions
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
#CPPFLAGS += -pedantic-errors #CPPFLAGS += -pedantic-errors
endif endif
CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused
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
@@ -108,6 +111,8 @@ endif
ifeq ($(CFG_WITH_DEFENV),yes) ifeq ($(CFG_WITH_DEFENV),yes)
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\" CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\" CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
CPPFLAGS += -DDEFENV_SYSTEMC_INCLUDE=\"$(SYSTEMC_INCLUDE)\"
CPPFLAGS += -DDEFENV_SYSTEMC_LIBDIR=\"$(SYSTEMC_LIBDIR)\"
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\" CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\" CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
@@ -121,6 +126,7 @@ HEADERS = $(wildcard V*.h v*.h)
ASTGEN = $(srcdir)/astgen ASTGEN = $(srcdir)/astgen
BISONPRE = $(srcdir)/bisonpre BISONPRE = $(srcdir)/bisonpre
FLEXFIX = $(srcdir)/flexfix
###################################################################### ######################################################################
#### Top level #### Top level
@@ -194,8 +200,9 @@ RAW_OBJS = \
V3Link.o \ V3Link.o \
V3LinkCells.o \ V3LinkCells.o \
V3LinkDot.o \ V3LinkDot.o \
V3LinkLevel.o \ V3LinkJump.o \
V3LinkLValue.o \ V3LinkLValue.o \
V3LinkLevel.o \
V3LinkParse.o \ V3LinkParse.o \
V3LinkResolve.o \ V3LinkResolve.o \
V3Localize.o \ V3Localize.o \
@@ -207,7 +214,6 @@ RAW_OBJS = \
V3PreShell.o \ V3PreShell.o \
V3Premit.o \ V3Premit.o \
V3Scope.o \ V3Scope.o \
V3Signed.o \
V3Slice.o \ V3Slice.o \
V3Split.o \ V3Split.o \
V3SplitAs.o \ V3SplitAs.o \
@@ -219,6 +225,7 @@ RAW_OBJS = \
V3Trace.o \ V3Trace.o \
V3TraceDecl.o \ V3TraceDecl.o \
V3Tristate.o \ V3Tristate.o \
V3Undriven.o \
V3Unknown.o \ V3Unknown.o \
V3Unroll.o \ V3Unroll.o \
V3Width.o \ V3Width.o \
@@ -248,8 +255,6 @@ $(TGT): V3Ast__gen_classes.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}
@-(cp [email protected] $@ || true)
# ok if cp failes on linux, it's there to insure executable works on NT
V3Number_test: V3Number_test.o V3Number_test: V3Number_test.o
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS} ${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
@@ -260,9 +265,9 @@ V3Number_test: V3Number_test.o
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp $(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
%.o: %.cpp %.o: %.cpp
$(OBJCACHE) ${CXX} ${CPPFLAGS} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSWALL} -c $<
%.o: %.c %.o: %.c
$(OBJCACHE) ${CC} ${CPPFLAGS} -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} ${CPPFLAGSNOWALL} -c $<
@@ -295,15 +300,15 @@ V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS)
${LEX} --version ${LEX} --version
${LEX} ${LFLAGS} -o$@ $< ${LEX} ${LFLAGS} -o$@ $<
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp $(FLEXFIX)
$(PERL) $(srcdir)/flexfix <$< >$@ $(PERL) $(FLEXFIX) V3Lexer <$< >$@
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS) V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
${LEX} --version ${LEX} --version
${LEX} ${LFLAGS} -o$@ $< ${LEX} ${LFLAGS} -o$@ $<
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
$(PERL) $(srcdir)/flexfix <$< >$@ $(PERL) $(FLEXFIX) V3PreLex <$< >$@
###################################################################### ######################################################################
###################################################################### ######################################################################
+83 -38
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -148,7 +148,11 @@ public:
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
ActiveNamer() {} ActiveNamer() {
m_scopep = NULL;
m_iActivep = NULL;
m_cActivep = NULL;
}
virtual ~ActiveNamer() {} virtual ~ActiveNamer() {}
void main(AstScope* nodep) { void main(AstScope* nodep) {
nodep->accept(*this); nodep->accept(*this);
@@ -160,26 +164,58 @@ public:
class ActiveDlyVisitor : public ActiveBaseVisitor { class ActiveDlyVisitor : public ActiveBaseVisitor {
private: private:
bool m_combo; // Combo logic
AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign
// VISITORS // VISITORS
virtual void visit(AstAssignDly* nodep, AstNUser*) { virtual void visit(AstAssignDly* nodep, AstNUser*) {
// Convert to a non-delayed assignment if (m_combo) {
UINFO(5," ASSIGNDLY "<<nodep<<endl); // Convert to a non-delayed assignment
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) blocks should be non-delayed assignments (=)."); UINFO(5," ASSIGNDLY "<<nodep<<endl);
AstNode* newp = new AstAssign (nodep->fileline(), nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
nodep->lhsp()->unlinkFrBack(), AstNode* newp = new AstAssign (nodep->fileline(),
nodep->rhsp()->unlinkFrBack()); nodep->lhsp()->unlinkFrBack(),
nodep->replaceWith(newp); nodep->rhsp()->unlinkFrBack());
nodep->deleteTree(); nodep = NULL; nodep->replaceWith(newp);
nodep->deleteTree(); nodep = NULL;
}
}
virtual void visit(AstAssign* nodep, AstNUser*) {
if (!m_combo) {
AstNode* las = m_assignp;
m_assignp = nodep;
nodep->lhsp()->iterateAndNext(*this);
m_assignp = las;
}
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
AstVar* varp=nodep->varp();
if (!m_combo
&& m_assignp
&& !varp->isUsedLoopIdx() // Ignore loop indicies
&& !varp->isTemp()
) {
// Allow turning off warnings on the always, or the variable also
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
) {
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
nodep->v3warn(BLKSEQ,"Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).");
}
}
} }
// Empty visitors, speed things up
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
//-------------------- //--------------------
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
ActiveDlyVisitor(AstNode* nodep) { ActiveDlyVisitor(AstNode* nodep, bool combo) {
m_alwaysp = nodep;
m_combo = combo;
m_assignp = NULL;
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~ActiveDlyVisitor() {} virtual ~ActiveDlyVisitor() {}
@@ -197,7 +233,6 @@ private:
// STATE // STATE
ActiveNamer m_namer; // Tracking of active names ActiveNamer m_namer; // Tracking of active names
AstCFunc* m_scopeFinalp; // Final function for this scope AstCFunc* m_scopeFinalp; // Final function for this scope
AstAlways* m_alwaysp; // Under always
bool m_itemCombo; // Found a SenItem combo bool m_itemCombo; // Found a SenItem combo
bool m_itemSequent; // Found a SenItem sequential bool m_itemSequent; // Found a SenItem sequential
@@ -264,32 +299,22 @@ private:
} }
// METHODS // METHODS
virtual void visit(AstAlways* nodep, AstNUser*) { void visitAlways(AstNode* nodep, AstSenTree* oldsensesp) {
// Move always to appropriate ACTIVE based on its sense list // Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl); if (oldsensesp
//if (debug()>=9) nodep->dumpTree(cout," Alw: "); && oldsensesp->sensesp()
&& oldsensesp->sensesp()->castSenItem()
if (!nodep->bodysp()) { && oldsensesp->sensesp()->castSenItem()->isNever()) {
// Empty always. Kill it.
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
if (nodep->sensesp()
&& nodep->sensesp()->sensesp()
&& nodep->sensesp()->sensesp()->castSenItem()
&& nodep->sensesp()->sensesp()->castSenItem()->isNever()) {
// Never executing. Kill it. // Never executing. Kill it.
if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated."); if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return; return;
} }
// Read sensitivitues // Read sensitivitues
m_alwaysp = nodep;
m_itemCombo = false; m_itemCombo = false;
m_itemSequent = false; m_itemSequent = false;
nodep->sensesp()->iterateAndNext(*this); oldsensesp->iterateAndNext(*this);
m_alwaysp = NULL;
bool combo = m_itemCombo; bool combo = m_itemCombo;
bool sequent = m_itemSequent; bool sequent = m_itemSequent;
@@ -311,15 +336,15 @@ private:
// always (posedge RESET) { if (RESET).... } we know RESET is true. // always (posedge RESET) { if (RESET).... } we know RESET is true.
// Summarize a long list of combo inputs as just "combo" // Summarize a long list of combo inputs as just "combo"
#ifndef __COVERITY__ // Else dead code on next line. #ifndef __COVERITY__ // Else dead code on next line.
if (combo) nodep->sensesp()->addSensesp if (combo) oldsensesp->addSensesp
(new AstSenItem(nodep->fileline(),AstSenItem::Combo())); (new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
#endif #endif
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp()); wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
} }
// Delete sensitivity list // Delete sensitivity list
if (AstNode* oldsense = nodep->sensesp()) { if (oldsensesp) {
oldsense->unlinkFrBackWithNext()->deleteTree(); oldsense=NULL; oldsensesp->unlinkFrBackWithNext()->deleteTree(); oldsensesp=NULL;
} }
// Move node to new active // Move node to new active
@@ -328,8 +353,29 @@ 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 dlyvisitor (nodep, true);
} }
else if (!combo && sequent) {
ActiveDlyVisitor dlyvisitor (nodep, false);
}
}
virtual void visit(AstAlways* nodep, AstNUser*) {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
if (!nodep->bodysp()) {
// Empty always. Kill it.
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
return;
}
visitAlways(nodep, nodep->sensesp());
}
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
visitAlways(nodep, nodep->sensesp());
} }
virtual void visit(AstSenGate* nodep, AstNUser*) { virtual void visit(AstSenGate* nodep, AstNUser*) {
AstSenItem* subitemp = nodep->sensesp(); AstSenItem* subitemp = nodep->sensesp();
@@ -348,7 +394,7 @@ private:
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} else if (nodep->varrefp()) { } else if (nodep->varrefp()) {
// V3LinkResolve should have cleaned most of these up // V3LinkResolve should have cleaned most of these up
if (nodep->varrefp()->width()>1) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: " if (!nodep->varrefp()->width1()) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
<<nodep->varrefp()->prettyName()); <<nodep->varrefp()->prettyName());
m_itemSequent = true; m_itemSequent = true;
nodep->varrefp()->varp()->usedClock(true); nodep->varrefp()->varp()->usedClock(true);
@@ -366,7 +412,6 @@ public:
// CONSTUCTORS // CONSTUCTORS
ActiveVisitor(AstNetlist* nodep) { ActiveVisitor(AstNetlist* nodep) {
m_scopeFinalp = NULL; m_scopeFinalp = NULL;
m_alwaysp = NULL;
m_itemCombo = false; m_itemCombo = false;
m_itemSequent = false; m_itemSequent = false;
nodep->accept(*this); nodep->accept(*this);
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+4 -1
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -133,6 +133,9 @@ private:
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep, AstNUser*) {
nodep->v3fatalSrc("Node should have been under ACTIVE"); nodep->v3fatalSrc("Node should have been under ACTIVE");
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstFinal* nodep, AstNUser*) { virtual void visit(AstFinal* nodep, AstNUser*) {
nodep->v3fatalSrc("Node should have been deleted"); nodep->v3fatalSrc("Node should have been deleted");
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -11
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can // Copyright 2005-2012 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.
@@ -177,24 +177,23 @@ private:
// VISITORS //========== Case assertions // VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) { virtual void visit(AstCase* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->user1()) { if (!nodep->user1Inc()) {
nodep->user1(true);
bool has_default=false; bool has_default=false;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
if (itemp->isDefault()) has_default=true; if (itemp->isDefault()) has_default=true;
} }
if (nodep->fullPragma()) { if (nodep->fullPragma() || nodep->priorityPragma()) {
// Simply need to add a default if there isn't one already // Simply need to add a default if there isn't one already
m_statAsFull++; ++m_statAsFull;
if (!has_default) { if (!has_default) {
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/, nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
newFireAssert(nodep, "synthesis full_case, but non-match found"))); newFireAssert(nodep, "synthesis full_case, but non-match found")));
} }
} }
if (nodep->parallelPragma()) { if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
// Need to check that one, and only one of the case items match at any moment // Need to check that one, and only one of the case items match at any moment
// If there's a default, we allow none to match, else exactly one must match // If there's a default, we allow none to match, else exactly one must match
m_statAsFull++; ++m_statAsFull;
if (!has_default && !nodep->itemsp()) { if (!has_default && !nodep->itemsp()) {
// Not parallel, but harmlessly so. // Not parallel, but harmlessly so.
} else { } else {
@@ -208,7 +207,8 @@ private:
else propp = onep; else propp = onep;
} }
} }
AstNode* ohot = (has_default bool allow_none = has_default || nodep->unique0Pragma();
AstNode* ohot = (allow_none
? (new AstOneHot0(nodep->fileline(), propp))->castNode() ? (new AstOneHot0(nodep->fileline(), propp))->castNode()
: (new AstOneHot (nodep->fileline(), propp))->castNode()); : (new AstOneHot (nodep->fileline(), propp))->castNode());
AstIf* ifp = new AstIf (nodep->fileline(), AstIf* ifp = new AstIf (nodep->fileline(),
@@ -241,18 +241,18 @@ private:
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name()); if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
nodep->stmtsp(), nodep->name()); nodep=NULL; nodep->stmtsp(), nodep->name()); nodep=NULL;
m_statAsCover++; ++m_statAsCover;
} }
virtual void visit(AstPslAssert* nodep, AstNUser*) { virtual void visit(AstPslAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
NULL, nodep->name()); nodep=NULL; NULL, nodep->name()); nodep=NULL;
m_statAsPsl++; ++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;
m_statAsSV++; ++m_statAsSV;
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep, AstNUser*) {
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can // Copyright 2005-2012 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
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can // Copyright 2005-2012 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
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can // Copyright 2005-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+27 -7
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,7 +74,9 @@ void AstNode::init() {
m_clonep = NULL; m_clonep = NULL;
m_cloneCnt = 0; m_cloneCnt = 0;
// Attributes // Attributes
m_signed = false; m_numeric = (int)AstNumeric::UNSIGNED;
m_didWidth = false;
m_doingWidth = false;
m_width = 0; m_width = 0;
m_widthMin = 0; m_widthMin = 0;
m_user1p = NULL; m_user1p = NULL;
@@ -192,6 +194,7 @@ string AstNode::prettyName(const string& namein) {
} }
} }
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,""); if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
return pretty; return pretty;
} }
@@ -242,7 +245,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
// Called on all major tree changers. // Called on all major tree changers.
// Only for use for those really nasty bugs relating to internals // Only for use for those really nasty bugs relating to internals
// Note this may be null. // Note this may be null.
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<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;
// v3Global.rootp()->dumpTree(cout,"-treeChange: "); // v3Global.rootp()->dumpTree(cout,"-treeChange: ");
@@ -427,7 +430,7 @@ void AstNode::replaceWith(AstNode* newp) {
repHandle.relink(newp); repHandle.relink(newp);
} }
void AstNRelinker::dump(ostream& str) { void AstNRelinker::dump(ostream& str) const {
str<<" BK="<<(uint32_t*)m_backp; str<<" BK="<<(uint32_t*)m_backp;
str<<" ITER="<<(uint32_t*)m_iterpp; str<<" ITER="<<(uint32_t*)m_iterpp;
str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":""); str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":"");
@@ -716,6 +719,7 @@ void AstNode::deleteTree() {
if (!this) return; if (!this) return;
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n"); UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
this->debugTreeChange("-delTree: ", __LINE__, true); this->debugTreeChange("-delTree: ", __LINE__, true);
this->editCountInc();
// MUST be depth first! // MUST be depth first!
deleteTreeIter(); deleteTreeIter();
} }
@@ -813,7 +817,7 @@ void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) { AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
// Some visitors perform tree edits (such as V3Const), and may even // Some visitors perform tree edits (such as V3Const), and may even
// replace/delete the exact nodep that the visitor is called with. If // replace/delete the exact nodep that the visitor is called with. If
// this happens, the parent will loose the handle to the node that was // this happens, the parent will lose the handle to the node that was
// processed. // processed.
// To solve this, this function returns the pointer to the replacement node, // To solve this, this function returns the pointer to the replacement node,
// which in many cases is just the same node that was passed in. // which in many cases is just the same node that was passed in.
@@ -872,7 +876,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
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->width() != node2p->width() || this->width() != node2p->width()
|| this->isSigned() != node2p->isSigned() || this->numeric() != node2p->numeric()
|| !this->same(node2p)) { || !this->same(node2p)) {
return false; return false;
} }
@@ -944,7 +948,23 @@ void AstNode::checkTree() {
} }
} }
void AstNode::dumpPtrs(ostream& os) { void AstNode::dumpGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader();
cout<<" "; dump(cout); cout<<endl;
}
void AstNode::dumpTreeGdb() { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpGdbHeader();
dumpTree(cout);
}
void AstNode::dumpGdbHeader() const { // For GDB only
if (!this) { cout<<"This=NULL"<<endl; return; }
dumpPtrs(cout);
cout<<" Fileline = "<<fileline()<<endl;
}
void AstNode::dumpPtrs(ostream& os) const {
os<<"This="<<typeName()<<" "<<(void*)this; os<<"This="<<typeName()<<" "<<(void*)this;
os<<" back="<<(void*)backp(); os<<" back="<<(void*)backp();
if (nextp()) os<<" next="<<(void*)nextp(); if (nextp()) os<<" next="<<(void*)nextp();
+140 -40
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,7 +26,10 @@
#include "verilatedos.h" #include "verilatedos.h"
#include "V3Error.h" #include "V3Error.h"
#include "V3Number.h" #include "V3Number.h"
#include "V3Global.h"
#include <vector> #include <vector>
#include <cmath>
#include <map>
#include "V3Ast__gen_classes.h" // From ./astgen #include "V3Ast__gen_classes.h" // From ./astgen
// Things like: // Things like:
@@ -34,6 +37,7 @@
// Hint class so we can choose constructors // Hint class so we can choose constructors
class AstLogicPacked {}; class AstLogicPacked {};
class AstBitPacked {};
//###################################################################### //######################################################################
@@ -56,9 +60,40 @@ public:
//###################################################################### //######################################################################
class AstNumeric {
public:
enum en {
UNSIGNED,
SIGNED,
DOUBLE
// Limited to 2 bits, unless change V3Ast's packing function
};
enum en m_e;
const char* ascii() const {
static const char* names[] = {
"UNSIGNED","SIGNED","DOUBLE"
};
return names[m_e];
};
inline AstNumeric () : m_e(UNSIGNED) {}
inline AstNumeric (en _e) : m_e(_e) {}
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
inline bool isDouble() const { return m_e==DOUBLE; }
inline bool isSigned() const { return m_e==SIGNED; }
inline bool isUnsigned() const { return m_e==UNSIGNED; }
};
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
//######################################################################
class AstPragmaType { class AstPragmaType {
public: public:
enum en { enum en {
ILLEGAL,
COVERAGE_BLOCK_OFF, COVERAGE_BLOCK_OFF,
INLINE_MODULE, INLINE_MODULE,
NO_INLINE_MODULE, NO_INLINE_MODULE,
@@ -67,7 +102,7 @@ public:
PUBLIC_TASK PUBLIC_TASK
}; };
enum en m_e; enum en m_e;
inline AstPragmaType () {} inline AstPragmaType () : m_e(ILLEGAL) {}
inline AstPragmaType (en _e) : m_e(_e) {} inline AstPragmaType (en _e) : m_e(_e) {}
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -90,7 +125,7 @@ public:
TRACE_CHANGE_SUB TRACE_CHANGE_SUB
}; };
enum en m_e; enum en m_e;
inline AstCFuncType () {} inline AstCFuncType () : m_e(FT_NORMAL) {}
inline AstCFuncType (en _e) : m_e(_e) {} inline AstCFuncType (en _e) : m_e(_e) {}
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -158,7 +193,7 @@ public:
}; };
return names[m_e]; return names[m_e];
}; };
inline AstEdgeType () {} inline AstEdgeType () : m_e(ET_ILLEGAL) {}
inline AstEdgeType (en _e) : m_e(_e) {} inline AstEdgeType (en _e) : m_e(_e) {}
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -172,6 +207,7 @@ public:
class AstAttrType { class AstAttrType {
public: public:
enum en { enum en {
ILLEGAL,
EXPR_BITS, // V3Const converts to constant EXPR_BITS, // V3Const converts to constant
// //
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@@ -179,19 +215,23 @@ public:
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
}; };
enum en m_e; enum en m_e;
const char* ascii() const { const char* ascii() const {
static const char* names[] = { static const char* names[] = {
"EXPR_BITS", "VAR_BASE", "%E-AT", "EXPR_BITS", "VAR_BASE",
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_PUBLIC_FLAT", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT" "VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
}; };
return names[m_e]; return names[m_e];
}; };
inline AstAttrType () {} inline AstAttrType () : m_e(ILLEGAL) {}
inline AstAttrType (en _e) : m_e(_e) {} inline AstAttrType (en _e) : m_e(_e) {}
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -205,8 +245,9 @@ public:
class AstBasicDTypeKwd { class AstBasicDTypeKwd {
public: public:
enum en { enum en {
UNKNOWN,
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT, BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
REAL, REALTIME, SHORTINT, SHORTREAL, TIME, DOUBLE, SHORTINT, FLOAT, TIME,
// Closer to a class type, but limited usage // Closer to a class type, but limited usage
STRING, STRING,
// Internal types for mid-steps // Internal types for mid-steps
@@ -217,8 +258,9 @@ public:
enum en m_e; enum en m_e;
const char* ascii() const { const char* ascii() const {
static const char* names[] = { static const char* names[] = {
"%E-unk",
"bit", "byte", "chandle", "int", "integer", "logic", "longint", "bit", "byte", "chandle", "int", "integer", "logic", "longint",
"real", "realtime", "shortint", "shortreal", "time", "real", "shortint", "shortreal", "time",
"string", "string",
"VerilatedScope*", "char*", "VerilatedScope*", "char*",
"LOGIC_IMPLICIT" "LOGIC_IMPLICIT"
@@ -227,15 +269,16 @@ public:
}; };
const char* dpiType() const { const char* dpiType() const {
static const char* names[] = { static const char* names[] = {
"%E-unk",
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long", "unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
"double", "double", "short int", "float", "long long", "double", "short int", "float", "long long",
"const char*", "const char*",
"dpiScope", "const char*", "dpiScope", "const char*",
"" ""
}; };
return names[m_e]; return names[m_e];
}; };
inline AstBasicDTypeKwd () {} inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
inline AstBasicDTypeKwd (en _e) : m_e(_e) {} inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -248,9 +291,13 @@ public:
case INTEGER: return 32; case INTEGER: return 32;
case LOGIC: return 1; case LOGIC: return 1;
case LONGINT: return 64; case LONGINT: return 64;
case DOUBLE: return 64; // opaque
case FLOAT: return 32; // opaque
case SHORTINT: return 16; case SHORTINT: return 16;
case TIME: return 64; case TIME: return 64;
case STRING: return 64; // Just the pointer, for today case STRING: return 64; // opaque // Just the pointer, for today
case SCOPEPTR: return 0; // opaque
case CHARPTR: return 0; // opaque
default: return 0; default: return 0;
} }
} }
@@ -262,19 +309,22 @@ public:
} }
bool isZeroInit() const { // Otherwise initializes to X bool isZeroInit() const { // Otherwise initializes to X
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|| m_e==STRING); || m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
} }
bool isSloppy() const { // Don't be as anal about width warnings bool isSloppy() const { // Don't be as anal about width warnings
return !(m_e==LOGIC || m_e==BIT); return !(m_e==LOGIC || m_e==BIT);
} }
bool isBitLogic() const { // Don't be as anal about width warnings bool isBitLogic() const { // Bit/logic vector types; can form a packed array
return (m_e==LOGIC || m_e==BIT); return (m_e==LOGIC || m_e==BIT);
} }
bool isDpiUnsupported() const { bool isDpiUnsupported() const {
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME); return (m_e==LOGIC || m_e==TIME);
} }
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); return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
}
bool isDouble() const {
return (m_e==DOUBLE);
} }
}; };
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); }
@@ -285,7 +335,7 @@ public:
enum AstSignedState { enum AstSignedState {
// This can't be in the fancy class as the lexer union will get upset // This can't be in the fancy class as the lexer union will get upset
signedst_NOP=0, signedst_SIGNED=1, signedst_UNSIGNED=2 signedst_NOSIGNED=0, signedst_UNSIGNED=1, signedst_SIGNED=2
}; };
//###################################################################### //######################################################################
@@ -313,7 +363,7 @@ public:
XTEMP XTEMP
}; };
enum en m_e; enum en m_e;
inline AstVarType () {} inline AstVarType () : m_e(UNKNOWN) {}
inline AstVarType (en _e) : m_e(_e) {} inline AstVarType (en _e) : m_e(_e) {}
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -371,7 +421,7 @@ public:
CT_CASEZ CT_CASEZ
}; };
enum en m_e; enum en m_e;
inline AstCaseType () {} inline AstCaseType () : m_e(CT_CASE) {}
inline AstCaseType (en _e) : m_e(_e) {} inline AstCaseType (en _e) : m_e(_e) {}
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -393,7 +443,7 @@ public:
DT_FATAL DT_FATAL
}; };
enum en m_e; enum en m_e;
inline AstDisplayType () {} inline AstDisplayType () : m_e(DT_DISPLAY) {}
inline AstDisplayType (en _e) : m_e(_e) {} inline AstDisplayType (en _e) : m_e(_e) {}
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -603,7 +653,7 @@ public:
AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;} AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
void relink(AstNode* newp); void relink(AstNode* newp);
AstNode* oldp() const { return m_oldp; } AstNode* oldp() const { return m_oldp; }
void dump(ostream& str=cout); void dump(ostream& str=cout) const;
}; };
inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;} inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;}
@@ -681,7 +731,9 @@ class AstNode {
static int s_cloneCntGbl; // Count of which userp is set static int s_cloneCntGbl; // Count of which userp is set
// Attributes // Attributes
bool m_signed:1; // Node is signed uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
bool m_didWidth:1; // Did V3Width computation
bool m_doingWidth:1; // Inside V3Width
// // Space for more bools here // // Space for more bools here
int m_width; // Bit width of operation int m_width; // Bit width of operation
@@ -714,6 +766,7 @@ class AstNode {
void deleteTreeIter(); void deleteTreeIter();
void deleteNode(); void deleteNode();
static void relinkOneLink(AstNode*& pointpr, AstNode* newp); static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
// cppcheck-suppress functionConst
void debugTreeChange(const char* prefix, int lineno, bool next); void debugTreeChange(const char* prefix, int lineno, bool next);
protected: protected:
@@ -761,6 +814,7 @@ public:
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); } AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
bool brokeExists() const; bool brokeExists() const;
bool brokeExistsAbove() const;
// CONSTRUCTORS // CONSTRUCTORS
virtual ~AstNode(); virtual ~AstNode();
@@ -776,6 +830,9 @@ public:
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics
static int 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
@@ -803,12 +860,21 @@ public:
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; } bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
void width(int width, int sized) { m_width=width; m_widthMin=sized; } void width(int width, int sized) { m_width=width; m_widthMin=sized; }
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }} void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); } void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }} void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
void isSigned(bool flag) { m_signed=flag; } void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
bool isSigned() const { return m_signed; } AstNumeric numeric() const { return AstNumeric(m_numeric); }
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
bool isUnsigned() const { return numeric().isUnsigned(); }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false;}
void doingWidth(bool flag) { m_doingWidth=flag; }
bool doingWidth() const { return m_doingWidth; }
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 isSigned() const;
AstNUser* user1p() const { AstNUser* user1p() const {
// Slows things down measurably, so disabled by default // Slows things down measurably, so disabled by default
@@ -818,6 +884,7 @@ public:
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; } void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
int user1() const { return user1p()->castInt(); } int user1() const { return user1p()->castInt(); }
void user1(int val) { user1p(AstNUser::fromInt(val)); } void user1(int val) { user1p(AstNUser::fromInt(val)); }
int user1Inc() { int v=user1(); user1(v+1); return v; }
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
AstNUser* user2p() const { AstNUser* user2p() const {
@@ -826,6 +893,7 @@ public:
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; } void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
int user2() const { return user2p()->castInt(); } int user2() const { return user2p()->castInt(); }
void user2(int val) { user2p(AstNUser::fromInt(val)); } void user2(int val) { user2p(AstNUser::fromInt(val)); }
int user2Inc() { int v=user2(); user2(v+1); return v; }
static void user2ClearTree() { AstUser2InUse::clear(); } static void user2ClearTree() { AstUser2InUse::clear(); }
AstNUser* user3p() const { AstNUser* user3p() const {
@@ -834,6 +902,7 @@ public:
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; } void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
int user3() const { return user3p()->castInt(); } int user3() const { return user3p()->castInt(); }
void user3(int val) { user3p(AstNUser::fromInt(val)); } void user3(int val) { user3p(AstNUser::fromInt(val)); }
int user3Inc() { int v=user3(); user3(v+1); return v; }
static void user3ClearTree() { AstUser3InUse::clear(); } static void user3ClearTree() { AstUser3InUse::clear(); }
AstNUser* user4p() const { AstNUser* user4p() const {
@@ -842,6 +911,7 @@ public:
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; } void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
int user4() const { return user4p()->castInt(); } int user4() const { return user4p()->castInt(); }
void user4(int val) { user4p(AstNUser::fromInt(val)); } void user4(int val) { user4p(AstNUser::fromInt(val)); }
int user4Inc() { int v=user4(); user4(v+1); return v; }
static void user4ClearTree() { AstUser4InUse::clear(); } static void user4ClearTree() { AstUser4InUse::clear(); }
AstNUser* user5p() const { AstNUser* user5p() const {
@@ -850,6 +920,7 @@ public:
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; } void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
int user5() const { return user5p()->castInt(); } int user5() const { return user5p()->castInt(); }
void user5(int val) { user5p(AstNUser::fromInt(val)); } void user5(int val) { user5p(AstNUser::fromInt(val)); }
int user5Inc() { int v=user5(); user5(v+1); return v; }
static void user5ClearTree() { AstUser5InUse::clear(); } static void user5ClearTree() { AstUser5InUse::clear(); }
vluint64_t editCount() const { return m_editCount; } vluint64_t editCount() const { return m_editCount; }
@@ -866,14 +937,26 @@ public:
bool isAllOnes(); bool isAllOnes();
bool isAllOnesV(); // Verilog width rules apply bool isAllOnesV(); // Verilog width rules apply
// METHODS // METHODS - data type changes especially for initial creation
void dtypeChgLogicBool() { numeric(AstNumeric::UNSIGNED); width(1,1); }
void dtypeChgDouble() { numeric(AstNumeric::DOUBLE); }
void dtypeChgSigned32() { numeric(AstNumeric::SIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
void dtypeChgUInt32() { numeric(AstNumeric::UNSIGNED); width(VL_WORDSIZE,VL_WORDSIZE); }
void dtypeChgUInt64() { numeric(AstNumeric::UNSIGNED); width(VL_QUADSIZE,VL_QUADSIZE); }
// METHODS - dump and error
void v3errorEnd(ostringstream& str) const;
virtual void dump(ostream& str=cout);
void dumpGdb(); // For GDB only
void dumpGdbHeader() const;
// METHODS - Tree modifications
AstNode* addNext(AstNode* newp); // Returns this, adds to end of list AstNode* addNext(AstNode* newp); // Returns this, adds to end of list
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK
void addNextHere(AstNode* newp); // Adds after speced node void addNextHere(AstNode* newp); // Adds after speced node
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
void replaceWith(AstNode* newp); // Replace current node in tree with new node void replaceWith(AstNode* newp); // Replace current node in tree with new node
void v3errorEnd(ostringstream& str) const;
virtual void dump(ostream& str=cout);
AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it. AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it.
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node
void swapWith(AstNode* bp); void swapWith(AstNode* bp);
@@ -888,13 +971,15 @@ public:
bool sameTree(AstNode* node2p); // Does tree of this == node2p? bool sameTree(AstNode* node2p); // Does tree of this == node2p?
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 dumpPtrs(ostream& str=cout); void dumpPtrs(ostream& str=cout) const;
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0); void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
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);
// METHODS - queries // METHODS - queries
virtual bool isSplittable() const { return true; } // Else a $display, etc, that must be ordered with other displays virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations
virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out
virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out
virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input
@@ -955,6 +1040,7 @@ struct AstNodeTermop : public AstNodeMath {
ASTNODE_BASE_FUNCS(NodeTermop) ASTNODE_BASE_FUNCS(NodeTermop)
// Know no children, and hot function, so skip iterator for speed // Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children // See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
@@ -966,10 +1052,13 @@ struct AstNodeUniop : public AstNodeMath {
setOp1p(lhsp); } setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop) ASTNODE_BASE_FUNCS(NodeUniop)
AstNode* lhsp() const { return op1p()->castNode(); } AstNode* lhsp() const { return op1p()->castNode(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
// METHODS // METHODS
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
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 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; }
@@ -992,6 +1081,7 @@ struct AstNodeBiop : public AstNodeMath {
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 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 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; }
@@ -1058,7 +1148,7 @@ struct AstNodeCond : public AstNodeTriop {
}; };
struct AstNodePreSel : public AstNode { struct AstNodePreSel : public AstNode {
// Something that becomes a AstSel // Something that becomes an AstSel
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); }
@@ -1182,16 +1272,18 @@ private:
string m_name; // Name of variable string m_name; // Name of variable
string m_hiername; // Scope converted into name-> for emitting string m_hiername; // Scope converted into name-> for emitting
bool m_hierThis; // Hiername points to "this" function bool m_hierThis; // Hiername points to "this" function
void init();
public: public:
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue) AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL), : AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
m_packagep(NULL), m_name(name), m_hierThis(false) { m_packagep(NULL), m_name(name), m_hierThis(false) {
init();
} }
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue) AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL), : AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
m_packagep(NULL), m_name(name), m_hierThis(false) { m_packagep(NULL), m_name(name), m_hierThis(false) {
// May have varp==NULL // May have varp==NULL
if (m_varp) widthSignedFrom((AstNode*)m_varp); init();
} }
ASTNODE_BASE_FUNCS(NodeVarRef) ASTNODE_BASE_FUNCS(NodeVarRef)
virtual bool broken() const; virtual bool broken() const;
@@ -1213,6 +1305,7 @@ public:
void packagep(AstPackage* nodep) { m_packagep=nodep; } void packagep(AstPackage* nodep) { m_packagep=nodep; }
// Know no children, and hot function, so skip iterator for speed // Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children // See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
@@ -1238,10 +1331,15 @@ struct AstNodeDType : public AstNode {
AstNodeDType(FileLine* fl) : AstNode(fl) {} AstNodeDType(FileLine* fl) : AstNode(fl) {}
ASTNODE_BASE_FUNCS(NodeDType) ASTNODE_BASE_FUNCS(NodeDType)
// Accessors // Accessors
virtual void dump(ostream& str);
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 to next non-typeref type
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int 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; }
AstNodeDType* dtypeDimensionp(int depth);
pair<uint32_t,uint32_t> dimensions();
uint32_t arrayElements(); // 1, or total multiplication of all dimensions
}; };
struct AstNodeSel : public AstNodeBiop { struct AstNodeSel : public AstNodeBiop {
@@ -1264,7 +1362,6 @@ 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
bool m_taskPublic:1; // Public task bool m_taskPublic:1; // Public task
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_attrIsolateAssign:1;// User isolate_assignments attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_prototype:1; // Just a prototype bool m_prototype:1; // Just a prototype
bool m_dpiExport:1; // DPI exported bool m_dpiExport:1; // DPI exported
@@ -1275,7 +1372,7 @@ private:
public: public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp) AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline) : AstNode(fileline)
, m_name(name), m_taskPublic(false), m_didSigning(false) , m_name(name), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false) , m_attrIsolateAssign(false), m_prototype(false)
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false) , m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
, m_dpiTask(false), m_pure(false) { , m_dpiTask(false), m_pure(false) {
@@ -1302,8 +1399,6 @@ public:
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; } void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; } bool taskPublic() const { return m_taskPublic; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; } bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; } void prototype(bool flag) { m_prototype = flag; }
@@ -1420,10 +1515,15 @@ public:
//###################################################################### //######################################################################
// Inline ACCESSORS // Inline ACCESSORS
inline bool AstNode::isDouble() const { return numeric().isDouble(); }
inline bool AstNode::isSigned() const { return numeric().isSigned(); }
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); } inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); } inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
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()->num().isEqAllOnes(this->width())); } inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->num().isEqAllOnes(this->widthMin())); } inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
inline void AstNodeVarRef::init() { if (m_varp) widthSignedFrom((AstNode*)m_varp); }
#endif // Guard #endif // Guard
+92 -30
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -70,7 +70,7 @@ bool AstVar::isScQuad() const {
} }
bool AstVar::isScBv() const { bool AstVar::isScBv() const {
return (isSc() && width() >= v3Global.opt.pinsBv()); return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv);
} }
void AstVar::combineType(AstVarType type) { void AstVar::combineType(AstVarType type) {
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
arg += "const char*"; arg += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) { } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
arg += "const VerilatedScope*"; arg += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
arg += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
arg += "float";
} else if (strtype) { } else if (strtype) {
if (isInOnly()) arg += "const "; if (isInOnly()) arg += "const ";
arg += "string"; arg += "string";
@@ -137,6 +141,43 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
return arg; return arg;
} }
string AstVar::vlEnumType() const {
string arg;
AstBasicDType* bdtypep = basicp();
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
return "VLVT_PTR";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
return "VLVT_PTR";
} else if (strtype) {
arg += "VLVT_STRING";
} else if (widthMin() <= 8) {
arg += "VLVT_UINT8";
} else if (widthMin() <= 16) {
arg += "VLVT_UINT16";
} else if (widthMin() <= VL_WORDSIZE) {
arg += "VLVT_UINT32";
} else if (isQuad()) {
arg += "VLVT_UINT64";
} else if (isWide()) {
arg += "VLVT_WDATA";
}
// else return "VLVT_UNKNOWN"
return arg;
}
string AstVar::vlEnumDir() const {
if (isInout()) {
return "VLVD_INOUT";
} else if (isInOnly()) {
return "VLVD_IN";
} else if (isOutOnly()) {
return "VLVD_OUT";
} else {
return "VLVD_NODIR";
}
}
string AstVar::cPubArgType(bool named, bool forReturn) const { string AstVar::cPubArgType(bool named, bool forReturn) const {
if (forReturn) named=false; if (forReturn) named=false;
string arg; string arg;
@@ -148,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
} else if (isWide()) { } else if (isWide()) {
arg += "uint32_t"; // []'s added later arg += "uint32_t"; // []'s added later
} else { } else {
arg += "uint64_t"; arg += "vluint64_t";
} }
if (isWide()) { if (isWide()) {
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead"); if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
@@ -165,7 +206,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
if (forReturn) named=false; if (forReturn) named=false;
string arg; string arg;
if (!basicp()) arg = "UNKNOWN"; if (!basicp()) arg = "UNKNOWN";
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
if (basicp()->isBitLogic()) { if (basicp()->isBitLogic()) {
if (widthMin() == 1) { if (widthMin() == 1) {
arg = "unsigned char"; arg = "unsigned char";
@@ -201,11 +241,11 @@ string AstVar::scType() const {
return "uint32_t"; return "uint32_t";
} }
} else { } else {
return "uint64_t"; return "vluint64_t";
} }
} }
AstNodeDType* AstVar::dtypeDimensionp(int dimension) const { 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,
// which is the lowest in the dtype list. // which is the lowest in the dtype list.
@@ -218,7 +258,7 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT)))) // *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0 // SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
int dim = 0; int dim = 0;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) { for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) { if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
if ((dim++)==dimension) { if ((dim++)==dimension) {
@@ -229,7 +269,7 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
} }
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) { else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
// AstBasicDType - nothing below, return null // AstBasicDType - nothing below, return null
if (adtypep->rangep()) { if (adtypep->isRanged()) {
if ((dim++) == dimension) { if ((dim++) == dimension) {
return adtypep; return adtypep;
} }
@@ -242,9 +282,9 @@ AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
return NULL; return NULL;
} }
uint32_t AstVar::arrayElements() const { uint32_t AstNodeDType::arrayElements() {
uint32_t entries=1; uint32_t entries=1;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) { for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) { if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
entries *= adtypep->elementsConst(); entries *= adtypep->elementsConst();
@@ -258,13 +298,15 @@ uint32_t AstVar::arrayElements() const {
return entries; return entries;
} }
uint32_t AstVar::dimensions() const { pair<uint32_t,uint32_t> AstNodeDType::dimensions() {
// How many array dimensions does this Var have? // How many array dimensions (packed,unpacked) does this Var have?
uint32_t dim = 0; uint32_t packed = 0;
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) { uint32_t unpacked = 0;
for (AstNodeDType* dtypep=this; dtypep; ) {
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstArrayDType* adtypep = dtypep->castArrayDType()) { if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
dim += 1; if (adtypep->isPacked()) packed += 1;
else unpacked += 1;
dtypep = adtypep->dtypep(); dtypep = adtypep->dtypep();
} }
else { else {
@@ -272,7 +314,7 @@ uint32_t AstVar::dimensions() const {
break; break;
} }
} }
return dim; return make_pair(packed, unpacked);
} }
// Special operators // Special operators
@@ -348,6 +390,8 @@ string AstScopeName::scopeSymName() const {
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,"");
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
if (out.substr(0,1) == ".") out.replace(0,1,"");
string::size_type pos; string::size_type pos;
while ((pos=out.find(".")) != string::npos) { while ((pos=out.find(".")) != string::npos) {
out.replace(pos, 1, "__"); out.replace(pos, 1, "__");
@@ -452,18 +496,23 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
//====================================================================== //======================================================================
// Per-type Debugging // Per-type Debugging
void AstNode::dump(ostream& os) { void AstNode::dump(ostream& str) {
os<<typeName()<<" "<<(void*)this str<<typeName()<<" "<<(void*)this
//<<" "<<(void*)this->m_backp //<<" "<<(void*)this->m_backp
<<" <e"<<dec<<editCount() <<" <e"<<dec<<editCount()
<<((editCount()>=editCountLast())?"#>":">") <<((editCount()>=editCountLast())?"#>":">")
<<" {"<<dec<<fileline()->lineno()<<"}" <<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"") <<" "<<(isSigned()?"s":"")
<<"w"<<(widthSized()?"":"u")<<width(); <<(isDouble()?"d":"")
if (!widthSized()) os<<"/"<<widthMin(); <<"w"<<(widthSized()?"":"u")<<width();
if (name()!="") os<<" "<<AstNode::quoteName(name()); if (!widthSized()) str<<"/"<<widthMin();
if (name()!="") str<<" "<<AstNode::quoteName(name());
} }
void AstArrayDType::dump(ostream& str) {
this->AstNodeDType::dump(str);
if (isPacked()) str<<" [PACKED]";
}
void AstArraySel::dump(ostream& str) { void AstArraySel::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
str<<" [start:"<<start()<<"] [length:"<<length()<<"]"; str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
@@ -473,11 +522,12 @@ void AstAttrOf::dump(ostream& str) {
str<<" ["<<attrType().ascii()<<"]"; str<<" ["<<attrType().ascii()<<"]";
} }
void AstBasicDType::dump(ostream& str) { void AstBasicDType::dump(ostream& str) {
this->AstNode::dump(str); this->AstNodeDType::dump(str);
str<<" ["<<keyword().ascii()<<"]"; str<<" kwd="<<keyword().ascii();
if (isRanged() && !rangep()) str<<" range=["<<msb()<<":"<<lsb()<<"]";
if (implicit()) str<<" [IMPLICIT]"; if (implicit()) str<<" [IMPLICIT]";
} }
void AstCast::dump(ostream& str) { void AstCCast::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
str<<" sz"<<size(); str<<" sz"<<size();
} }
@@ -494,6 +544,12 @@ void AstDisplay::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
//str<<" "<<displayType().ascii(); //str<<" "<<displayType().ascii();
} }
void AstJumpGo::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> ";
if (labelp()) { labelp()->dump(str); }
else { str<<"%Error:UNLINKED"; }
}
void AstEnumItemRef::dump(ostream& str) { void AstEnumItemRef::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
str<<" -> "; str<<" -> ";
@@ -511,7 +567,7 @@ void AstRange::dump(ostream& str) {
if (littleEndian()) str<<" [LITTLE]"; if (littleEndian()) str<<" [LITTLE]";
} }
void AstRefDType::dump(ostream& str) { void AstRefDType::dump(ostream& str) {
this->AstNode::dump(str); this->AstNodeDType::dump(str);
if (defp()) { str<<" -> "; defp()->dump(str); } if (defp()) { str<<" -> "; defp()->dump(str); }
else { str<<" -> UNLINKED"; } else { str<<" -> UNLINKED"; }
} }
@@ -525,6 +581,9 @@ void AstVarXRef::dump(ostream& str) {
else if (varp()) { varp()->dump(str); } else if (varp()) { varp()->dump(str); }
else { str<<"UNLINKED"; } else { str<<"UNLINKED"; }
} }
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
}
void AstNodeModule::dump(ostream& str) { void AstNodeModule::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
str<<" L"<<level(); str<<" L"<<level();
@@ -558,8 +617,10 @@ void AstVar::dump(ostream& str) {
else if (isInput()) str<<" [I]"; else if (isInput()) str<<" [I]";
else if (isOutput()) str<<" [O]"; else if (isOutput()) str<<" [O]";
} }
if (isUsedClock()) str<<" [C]"; if (isConst()) str<<" [CONST]";
if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]"; if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]";
if (attrClockEn()) str<<" [aCLKEN]"; if (attrClockEn()) str<<" [aCLKEN]";
if (attrIsolateAssign()) str<<" [aISO]"; if (attrIsolateAssign()) str<<" [aISO]";
if (attrFileDescr()) str<<" [aFD]"; if (attrFileDescr()) str<<" [aFD]";
@@ -603,6 +664,7 @@ void AstNodeFTask::dump(ostream& str) {
void AstBegin::dump(ostream& str) { void AstBegin::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (unnamed()) str<<" [UNNAMED]"; if (unnamed()) str<<" [UNNAMED]";
if (hidden()) str<<" [HIDDEN]";
} }
void AstCoverDecl::dump(ostream& str) { void AstCoverDecl::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
+804 -186
View File
File diff suppressed because it is too large Load Diff
+119 -62
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -45,14 +45,37 @@
//###################################################################### //######################################################################
class BeginState {
private:
// NODE STATE
//Entire netlist:
// AstNodeFTask::user1 -> bool, 1=processed
AstUser1InUse m_inuser1;
bool m_anyFuncInBegin;
public:
BeginState() {
m_anyFuncInBegin = false;
}
~BeginState() {}
void userMarkChanged(AstNodeFTask* nodep) {
nodep->user1(true);
m_anyFuncInBegin = true;
}
bool anyFuncInBegin() const { return m_anyFuncInBegin; }
};
//######################################################################
class BeginVisitor : public AstNVisitor { class BeginVisitor : public AstNVisitor {
private: private:
// STATE // STATE
BeginState* m_statep; // Current global state
AstNodeModule* m_modp; // Current module AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task AstNodeFTask* m_ftaskp; // Current function/task
string m_namedScope; // Name of begin blocks above us string m_namedScope; // Name of begin blocks above us
string m_unnamedScope; // Name of begin blocks, including unnamed blocks string m_unnamedScope; // Name of begin blocks, including unnamed blocks
int m_repeatNum; // Repeat counter int m_repeatNum; // Repeat counter
int m_ifDepth; // Current if depth
// METHODS // METHODS
static int debug() { static int debug() {
@@ -69,9 +92,27 @@ private:
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep, AstNUser*) {
m_ftaskp = nodep; UINFO(8," "<<nodep<<endl);
nodep->iterateChildren(*this); // Rename it
m_ftaskp = NULL; if (m_unnamedScope != "") {
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
UINFO(8," rename to "<<nodep->name()<<endl);
m_statep->userMarkChanged(nodep);
}
// BEGIN wrapping a function rename that function, but don't affect the inside function's variables
// We then restart with empty naming; so that any begin's inside the function will rename inside the function
// Process children
string oldScope = m_namedScope;
string oldUnnamed = m_unnamedScope;
{
m_namedScope = "";
m_unnamedScope = "";
m_ftaskp = nodep;
nodep->iterateChildren(*this);
m_ftaskp = NULL;
}
m_namedScope = oldScope;
m_unnamedScope = oldUnnamed;
} }
virtual void visit(AstBegin* nodep, AstNUser*) { virtual void visit(AstBegin* nodep, AstNUser*) {
// Begin blocks were only useful in variable creation, change names and delete // Begin blocks were only useful in variable creation, change names and delete
@@ -79,7 +120,7 @@ private:
string oldScope = m_namedScope; string oldScope = m_namedScope;
string oldUnnamed = m_unnamedScope; string oldUnnamed = m_unnamedScope;
{ {
//UINFO(8,"nname "<<m_namedScope<<endl); UINFO(8,"nname "<<m_namedScope<<endl);
if (nodep->name() != "") { // Else unneeded unnamed block if (nodep->name() != "") { // Else unneeded unnamed block
// Create data for dotted variable resolution // Create data for dotted variable resolution
string dottedname = nodep->name() + "__DOT__"; // So always found string dottedname = nodep->name() + "__DOT__"; // So always found
@@ -101,18 +142,31 @@ private:
} }
// Remap var names and replace lower Begins // Remap var names and replace lower Begins
nodep->iterateChildren(*this); nodep->stmtsp()->iterateAndNext(*this);
if (AstNode* stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
nodep->replaceWith(stmtsp);
} else {
nodep->unlinkFrBack();
}
pushDeletep(nodep); nodep=NULL;
} }
m_namedScope = oldScope; m_namedScope = oldScope;
m_unnamedScope = oldUnnamed; m_unnamedScope = oldUnnamed;
// Don't change var names of generate FOR() variables, but do recurse into a child FOR
nodep->flatsp()->iterateAndNext(*this);
// Cleanup
AstNode* addsp = NULL;
if (AstNode* stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = addsp->addNextNull(stmtsp);
}
if (AstNode* stmtsp = nodep->flatsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = addsp->addNextNull(stmtsp);
}
if (addsp) {
nodep->replaceWith(addsp);
} else {
nodep->unlinkFrBack();
}
pushDeletep(nodep); nodep=NULL;
} }
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
if (m_unnamedScope != "") { if (m_unnamedScope != "") {
@@ -135,53 +189,6 @@ private:
m_modp->addStmtp(nodep); m_modp->addStmtp(nodep);
} }
} }
virtual void visit(AstFor* nodep, AstNUser*) {
// So later optimizations don't need to deal with them,
// FOR(init,cond,assign,body) -> init,WHILE(cond) { body, assign }
AstNode* initsp = nodep->initsp(); if (initsp) initsp->unlinkFrBackWithNext();
AstNode* condp = nodep->condp(); if (condp) condp->unlinkFrBackWithNext();
AstNode* incsp = nodep->incsp(); if (incsp) incsp->unlinkFrBackWithNext();
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
bodysp = bodysp->addNext(incsp);
AstNode* newp = new AstWhile(nodep->fileline(),
condp,
bodysp);
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstRepeat* nodep, AstNUser*) {
// So later optimizations don't need to deal with them,
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
// Note var can be signed or unsigned based on original number.
AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), countp->width());
m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
countp);
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1)));
AstNode* condp;
if (countp->isSigned()) {
condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 0));
} else {
condp = new AstGt (nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 0));
}
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
bodysp = bodysp->addNext(decp);
AstNode* newp = new AstWhile(nodep->fileline(),
condp,
bodysp);
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstScopeName* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline // Similar code in V3Inline
@@ -199,24 +206,74 @@ private:
// any BEGINs, but V3Coverage adds them all under the module itself. // any BEGINs, but V3Coverage adds them all under the module itself.
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// VISITORS - LINT CHECK
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
// Check IFDEPTH warning - could be in other transform files if desire
int prevIfDepth = m_ifDepth;
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
} else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) {
m_ifDepth = -1;
} else if (++m_ifDepth > v3Global.opt.ifDepth()) {
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
m_ifDepth = -1;
}
nodep->iterateChildren(*this);
m_ifDepth = prevIfDepth;
}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
BeginVisitor(AstNetlist* nodep) { BeginVisitor(AstNetlist* nodep, BeginState* statep) {
m_statep = statep;
m_modp = NULL; m_modp = NULL;
m_ftaskp = NULL; m_ftaskp = NULL;
m_repeatNum = 0; m_repeatNum = 0;
m_ifDepth = 0;
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~BeginVisitor() {} virtual ~BeginVisitor() {}
}; };
//######################################################################
class BeginRelinkVisitor : public AstNVisitor {
// Replace tasks with new pointer
private:
// NODE STATE
// Input:
// AstNodeFTask::user1p // Node replaced, rename it
// VISITORS
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (nodep->taskp()->user1()) { // It was converted
UINFO(9, " relinkFTask "<<nodep<<endl);
nodep->name(nodep->taskp()->name());
}
nodep->iterateChildren(*this);
}
//--------------------
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) {
nodep->accept(*this);
}
virtual ~BeginRelinkVisitor() {}
};
//###################################################################### //######################################################################
// Task class functions // Task class functions
void V3Begin::debeginAll(AstNetlist* nodep) { void V3Begin::debeginAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
BeginVisitor bvisitor (nodep); BeginState state;
{ BeginVisitor bvisitor (nodep,&state); }
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+33 -7
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -52,6 +52,7 @@ private:
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
static const int FLAG_LEAKED = 0x08; // Known to have been leaked static const int FLAG_LEAKED = 0x08; // Known to have been leaked
static const int 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) {
@@ -74,6 +75,15 @@ public:
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED)); s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
} }
} }
static void setUnder(const AstNode* nodep, bool flag) {
// Called by BrokenCheckVisitor when each node entered/exited
if (!okIfLinkedTo(nodep)) return;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter!=s_nodes.end()) {
iter->second &= ~FLAG_UNDER_NOW;
if (flag) iter->second |= FLAG_UNDER_NOW;
}
}
static void addInTree(AstNode* nodep, bool linkable) { static void addInTree(AstNode* nodep, bool linkable) {
#ifndef VL_LEAK_CHECKS #ifndef VL_LEAK_CHECKS
if (!linkable) return; // save some time, else the map will get huge! if (!linkable) return; // save some time, else the map will get huge!
@@ -111,6 +121,14 @@ public:
if (!(iter->second & FLAG_LINKABLE)) return false; if (!(iter->second & FLAG_LINKABLE)) return false;
return true; return true;
} }
static bool okIfBelow(const AstNode* nodep) {
// Must be linked to and below current node
if (!okIfLinkedTo(nodep)) return false;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) return false;
if (!(iter->second & FLAG_UNDER_NOW)) return false;
return true;
}
static void prepForTree() { static void prepForTree() {
#ifndef VL_LEAK_CHECKS #ifndef VL_LEAK_CHECKS
s_nodes.clear(); s_nodes.clear();
@@ -152,6 +170,10 @@ bool AstNode::brokeExists() const {
// Called by node->broken() routines to do table lookup // Called by node->broken() routines to do table lookup
return BrokenTable::okIfLinkedTo(this); return BrokenTable::okIfLinkedTo(this);
} }
bool AstNode::brokeExistsAbove() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::okIfBelow(this);
}
//###################################################################### //######################################################################
@@ -180,18 +202,22 @@ public:
class BrokenCheckVisitor : public AstNVisitor { class BrokenCheckVisitor : public AstNVisitor {
private: private:
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::setUnder(nodep,true);
if (nodep->broken()) { if (nodep->broken()) {
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)\n"); nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)");
} }
if (v3Global.assertWidthsSame()) { if (v3Global.assertDTypesResolved()) {
if (nodep->width() != nodep->widthMin()) {
nodep->v3fatalSrc("Width != WidthMin\n");
}
if (!nodep->width() && nodep->castNodeMath()) { if (!nodep->width() && nodep->castNodeMath()) {
nodep->v3fatalSrc("Math node has no assigned width\n"); nodep->v3fatalSrc("Math node has no assigned width");
}
}
if (v3Global.assertWidthsMatch()) {
if (nodep->width() != nodep->widthMin()) {
nodep->v3fatalSrc("Width != WidthMin");
} }
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
BrokenTable::setUnder(nodep,false);
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
+9 -5
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -148,17 +148,19 @@ private:
bool isCaseTreeFast(AstCase* nodep) { bool isCaseTreeFast(AstCase* nodep) {
int width = 0; int width = 0;
bool opaque = false;
m_caseItems = 0; m_caseItems = 0;
m_caseNoOverlapsAllCovered = true; m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width(); if (icondp->width() > width) width = icondp->width();
if (icondp->isDouble()) opaque = true;
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++; m_caseItems++;
} }
} }
m_caseWidth = width; m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH) { if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
m_caseNoOverlapsAllCovered = false; m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis return false; // Too wide for analysis
} }
@@ -348,7 +350,9 @@ private:
and1p = cexprp->cloneTree(false); and1p = cexprp->cloneTree(false);
and2p = icondp; and2p = icondp;
} }
AstEq* condp = new AstEq(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 {
@@ -448,10 +452,10 @@ private:
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) { if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
// It's a simple priority encoder or complete statement // It's a simple priority encoder or complete statement
// we can make a tree of statements to avoid extra comparisons // we can make a tree of statements to avoid extra comparisons
m_statCaseFast++; ++m_statCaseFast;
replaceCaseFast(nodep); nodep=NULL; replaceCaseFast(nodep); nodep=NULL;
} else { } else {
m_statCaseSlow++; ++m_statCaseSlow;
replaceCaseComplicated(nodep); nodep=NULL; replaceCaseComplicated(nodep); nodep=NULL;
} }
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+7 -7
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can // Copyright 2004-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // 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.
@@ -77,7 +77,7 @@ private:
AstNRelinker relinkHandle; AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle); nodep->unlinkFrBack(&relinkHandle);
// //
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize); AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
castp->width(needsize, nodep->widthMin()); castp->width(needsize, nodep->widthMin());
relinkHandle.relink(castp); relinkHandle.relink(castp);
//if (debug()>8) castp->dumpTree(cout,"-castins: "); //if (debug()>8) castp->dumpTree(cout,"-castins: ");
@@ -97,13 +97,13 @@ private:
insertCast(nodep, castSize(nodep->backp())); insertCast(nodep, castSize(nodep->backp()));
} }
} }
void insureLower32Cast(AstCast* nodep) { void insureLower32Cast(AstCCast* nodep) {
// If we have uint64 = CAST(uint64(x)) then the upcasting // If we have uint64 = CAST(uint64(x)) then the upcasting
// really needs to be CAST(uint64(CAST(uint32(x))). // really needs to be CAST(uint64(CAST(uint32(x))).
// Otherwise a (uint64)(a>b) would return wrong value, as // Otherwise a (uint64)(a>b) would return wrong value, as
// less than has undeterministic signedness. // less than has undeterministic signedness.
if (nodep->isQuad() && !nodep->lhsp()->isQuad() if (nodep->isQuad() && !nodep->lhsp()->isQuad()
&& !nodep->lhsp()->castCast()) { && !nodep->lhsp()->castCCast()) {
insertCast(nodep->lhsp(), VL_WORDSIZE); insertCast(nodep->lhsp(), VL_WORDSIZE);
} }
} }
@@ -130,12 +130,12 @@ private:
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp()); if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp()); if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
} }
virtual void visit(AstCast* nodep, AstNUser*) { virtual void visit(AstCCast* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureLower32Cast(nodep); insureLower32Cast(nodep);
nodep->user1(1); nodep->user1(1);
} }
virtual void visit(AstUnaryMin* nodep, AstNUser*) { virtual void visit(AstNegate* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1()); nodep->user1(nodep->lhsp()->user1());
if (nodep->lhsp()->widthMin()==1) { if (nodep->lhsp()->widthMin()==1) {
@@ -149,7 +149,7 @@ private:
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->lvalue() if (!nodep->lvalue()
&& !nodep->backp()->castCast() && !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath() && nodep->backp()->castNodeMath()
&& nodep->backp()->width() && nodep->backp()->width()
&& castSize(nodep) != castSize(nodep->varp())) { && castSize(nodep) != castSize(nodep->varp())) {
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can // Copyright 2004-2012 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.
+49 -17
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -46,6 +46,8 @@
#include "V3EmitV.h" #include "V3EmitV.h"
#include "V3File.h" #include "V3File.h"
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
//###################################################################### //######################################################################
class CdcBaseVisitor : public AstNVisitor { class CdcBaseVisitor : public AstNVisitor {
@@ -65,9 +67,9 @@ class CdcEitherVertex : public V3GraphVertex {
AstNode* m_nodep; AstNode* m_nodep;
AstSenTree* m_srcDomainp; AstSenTree* m_srcDomainp;
AstSenTree* m_dstDomainp; AstSenTree* m_dstDomainp;
bool m_srcDomainSet; bool m_srcDomainSet:1;
bool m_dstDomainSet; bool m_dstDomainSet:1;
bool m_asyncPath; bool m_asyncPath:1;
public: public:
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep) CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep) : V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
@@ -109,11 +111,12 @@ public:
}; };
class CdcLogicVertex : public CdcEitherVertex { class CdcLogicVertex : public CdcEitherVertex {
bool m_hazard; bool m_hazard:1;
bool m_isFlop; bool m_isFlop:1;
public: public:
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep) CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
: CdcEitherVertex(graphp,scopep,nodep), m_hazard(false), m_isFlop(false) : CdcEitherVertex(graphp,scopep,nodep)
, m_hazard(false), m_isFlop(false)
{ srcDomainp(sensenodep); dstDomainp(sensenodep); } { srcDomainp(sensenodep); dstDomainp(sensenodep); }
virtual ~CdcLogicVertex() {} virtual ~CdcLogicVertex() {}
// Accessors // Accessors
@@ -132,7 +135,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
private: private:
// NODE STATE // NODE STATE
//Entire netlist: //Entire netlist:
// {statement}Node::user3p -> bool, indicating not hazard // {statement}Node::user3 -> bool, indicating not hazard
ofstream* m_ofp; // Output file ofstream* m_ofp; // Output file
string m_prefix; string m_prefix;
@@ -290,9 +293,12 @@ private:
void setNodeHazard(AstNode* nodep) { void setNodeHazard(AstNode* nodep) {
// Need to not clear if warnings are off (rather than when report it) // Need to not clear if warnings are off (rather than when report it)
// as bypassing this warning may turn up another path that isn't warning off'ed. // as bypassing this warning may turn up another path that isn't warning off'ed.
// We can't modifyWarnOff here, as one instantiation might not be an issue until we find a hitting flop
// Furthermore, a module like a "Or" module would only get flagged once,
// even though the signals feeding it are radically different.
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though) if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) { if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
UINFO(9,"Set hazard "<<nodep<<endl); UINFO(8,"Set hazard "<<nodep<<endl);
m_logicVertexp->setHazard(nodep); m_logicVertexp->setHazard(nodep);
} }
} }
@@ -310,7 +316,9 @@ private:
UINFO(3,__FUNCTION__<<": "<<endl); UINFO(3,__FUNCTION__<<": "<<endl);
//if (debug()>6) m_graph.dump(); //if (debug()>6) m_graph.dump();
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre"); if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue); //
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
//
m_graph.dumpDotFilePrefixed("cdc_simp"); m_graph.dumpDotFilePrefixed("cdc_simp");
// //
analyzeReset(); analyzeReset();
@@ -335,7 +343,7 @@ private:
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) { if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
if (vvertexp->cntAsyncRst()) { if (vvertexp->cntAsyncRst()) {
m_userGeneration++; // Effectively a userClearVertices() m_userGeneration++; // Effectively a userClearVertices()
UINFO(9, " Trace One async: "<<vvertexp<<endl); UINFO(8, " Trace One async: "<<vvertexp<<endl);
// Twice, as we need to detect, then propagate // Twice, as we need to detect, then propagate
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false); CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
if (markp) { // Mark is non-NULL if something bad on this path if (markp) { // Mark is non-NULL if something bad on this path
@@ -351,7 +359,8 @@ private:
} }
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) { CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
// Return vertex of any hazardous stuff attached, or NULL if OK // First pass: Return vertex of any hazardous stuff attached, or NULL if OK
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
vertexp->user(m_userGeneration); vertexp->user(m_userGeneration);
@@ -406,12 +415,15 @@ private:
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top(); CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
if (!eToVertexp) targetp = eToVertexp; if (!eToVertexp) targetp = eToVertexp;
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) { if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
if (vvertexp->isFlop()) { if (vvertexp->isFlop() // IE the target flop that is upsetting us
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
targetp = eToVertexp; targetp = eToVertexp;
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
break; break;
} }
} // else it might be random logic that's not relevant } // else it might be random logic that's not relevant
} }
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName()); warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
dumpAsyncRecurse(targetp, "", " ",0); dumpAsyncRecurse(targetp, "", " ",0);
} }
@@ -464,6 +476,12 @@ private:
void edgeReport() { void edgeReport() {
// Make report of all signal names and what clock edges they have // Make report of all signal names and what clock edges they have
//
// Due to flattening, many interesting direct-connect signals are
// lost, so we can't make a report showing I/Os for a low level
// module. Disabling flattening though makes us consider each
// signal in it's own unique clock domain.
UINFO(3,__FUNCTION__<<": "<<endl); UINFO(3,__FUNCTION__<<": "<<endl);
// Trace all sources and sinks // Trace all sources and sinks
@@ -493,6 +511,10 @@ private:
ostringstream os; ostringstream os;
os.setf(ios::left); os.setf(ios::left);
// Module name - doesn't work due to flattening having lost the original
// so we assume the modulename matches the filebasename
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
os<<" "<<setw(20)<<fname;
os<<" "<<setw(8)<<whatp; os<<" "<<setw(8)<<whatp;
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName(); os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
os<<" SRC="; os<<" SRC=";
@@ -613,8 +635,9 @@ private:
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n"); if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
CdcVarVertex* varvertexp = makeVarVertex(varscp); CdcVarVertex* varvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl); UINFO(5," VARREF to "<<varscp<<endl);
// We use weight of one; if we ref the var more than once, when we simplify, // We use weight of one for normal edges,
// the weight will increase // Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
// When simplify we'll take the MAX weight
if (nodep->lvalue()) { if (nodep->lvalue()) {
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1); new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
if (m_inDly) { if (m_inDly) {
@@ -623,7 +646,13 @@ private:
varvertexp->srcDomainSet(true); varvertexp->srcDomainSet(true);
} }
} else { } else {
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1); if (varvertexp->cntAsyncRst()) {
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
} else {
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
}
} }
} }
} }
@@ -642,6 +671,9 @@ private:
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep, AstNUser*) {
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// CDC doesn't care about public variables
}
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep, AstNUser*) {
iterateNewStmt(nodep); iterateNewStmt(nodep);
} }
@@ -717,7 +749,7 @@ public:
nodep->accept(*this); nodep->accept(*this);
analyze(); analyze();
//edgeReport(); // Not useful at the moment if (debug()>=1) edgeReport(); // Not useful to users at the moment
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; } if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -4
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -73,7 +73,7 @@ private:
AstVar* varp = vscp->varp(); AstVar* varp = vscp->varp();
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp); vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
if (!varp->dtypeSkipRefp()->castBasicDType()) { if (!varp->dtypeSkipRefp()->castBasicDType()) {
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName()); vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
} else { } else {
string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName(); string newvarname = "__Vchglast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName();
// Create: VARREF(_last) // Create: VARREF(_last)
@@ -128,8 +128,7 @@ private:
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep, AstNUser*) {
if (nodep->isCircular()) { if (nodep->isCircular()) {
UINFO(8," CIRC "<<nodep<<endl); UINFO(8," CIRC "<<nodep<<endl);
if (!nodep->user1()) { if (!nodep->user1Inc()) {
nodep->user1(true);
genChangeDet(nodep); genChangeDet(nodep);
} }
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+3 -3
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,7 +24,7 @@
// For each math operator, if it requires a clean operand, // For each math operator, if it requires a clean operand,
// and the operand is dirty, insert a CLEAN node. // and the operand is dirty, insert a CLEAN node.
// Resize operands to C++ 32/64/wide types. // Resize operands to C++ 32/64/wide types.
// Copy all width() values to minWidth() so RANGE, etc can still see orig widths // Copy all width() values to widthMin() so RANGE, etc can still see orig widths
// //
//************************************************************************* //*************************************************************************
@@ -47,7 +47,7 @@ private:
// NODE STATE // NODE STATE
// Entire netlist: // Entire netlist:
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN // AstNode::user() -> CleanState. For this node, 0==UNKNOWN
// AstNode::user2() -> bool. True indicates minWidth has been propagated // AstNode::user2() -> bool. True indicates widthMin has been propagated
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2; AstUser2InUse m_inuser2;
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+6 -6
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2008-2010 by Wilson Snyder. This program is free software; you can // Copyright 2008-2012 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.
@@ -315,6 +315,7 @@ public:
m_exprp = exprp; m_exprp = exprp;
m_original = original; m_original = original;
m_state = STATE_UNKNOWN; m_state = STATE_UNKNOWN;
m_cloning = false;
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: "); if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
nodep->bodysp()->iterateAndNext(*this); nodep->bodysp()->iterateAndNext(*this);
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: "); if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
@@ -696,7 +697,7 @@ class GaterVisitor : public GaterBaseVisitor {
// Blow old statements from new body // Blow old statements from new body
GaterBodyVisitor(alwp,exprp,false); GaterBodyVisitor(alwp,exprp,false);
m_statGaters++; ++m_statGaters;
if (debug()>=9) alwp->dumpTree(cout," new: "); if (debug()>=9) alwp->dumpTree(cout," new: ");
} }
@@ -704,8 +705,7 @@ class GaterVisitor : public GaterBaseVisitor {
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep, AstNUser*) {
if (debug()>=9) cout<<endl<<endl<<endl; if (debug()>=9) cout<<endl<<endl<<endl;
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl); UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
if (nodep->user4()) return; if (nodep->user4Inc()) return;
nodep->user4(1);
clear(); clear();
@@ -862,9 +862,9 @@ class GaterVisitor : public GaterBaseVisitor {
m_stmtVscp = NULL; m_stmtVscp = NULL;
m_stmtInPli = false; m_stmtInPli = false;
} }
if (!nodep->isSplittable()) { if (!nodep->isPure() || nodep->isBrancher()) {
// May also be a new statement (above if); if so we mark it immediately // May also be a new statement (above if); if so we mark it immediately
UINFO(9," NotSplittable "<<nodep<<endl); UINFO(9," NotPure "<<nodep<<endl);
scoreboardPli(nodep); scoreboardPli(nodep);
} }
{ {
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -3
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
@@ -83,10 +83,9 @@ private:
AstVarScope* getCreateLastClk(AstVarScope* vscp) { AstVarScope* getCreateLastClk(AstVarScope* vscp) {
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p()); if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
AstVar* varp = vscp->varp(); AstVar* varp = vscp->varp();
if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName()); if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName()); string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1); AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, AstLogicPacked(), 1);
newvarp->width(1,1);
m_modp->addStmtp(newvarp); m_modp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp); AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
vscp->user1p(newvscp); vscp->user1p(newvscp);
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -5
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -70,8 +70,8 @@ protected:
virtual ~CombBaseVisitor() {} virtual ~CombBaseVisitor() {}
//***** optimization levels //***** optimization levels
bool emptyFunctionDeletion() { return true; } static bool emptyFunctionDeletion() { return true; }
bool duplicateFunctionCombine() { return true; } static bool duplicateFunctionCombine() { return true; }
// Note this is disabled, it still needed work // Note this is disabled, it still needed work
// Also repair it for DPI functions; when make __common need to insure proper // Also repair it for DPI functions; when make __common need to insure proper
// flags get inherited from the old to new AstCFunc, and that AstText doesn't // flags get inherited from the old to new AstCFunc, and that AstText doesn't
@@ -146,7 +146,9 @@ private:
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
CombCallVisitor() {} CombCallVisitor() {
m_find = false;
}
virtual ~CombCallVisitor() {} virtual ~CombCallVisitor() {}
void main(AstNetlist* nodep) { void main(AstNetlist* nodep) {
nodep->accept(*this); nodep->accept(*this);
@@ -257,7 +259,7 @@ private:
UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl); UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl);
UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl); UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
// Mark user3p on entire old tree, so we don't process it more // Mark user3p on entire old tree, so we don't process it more
m_statCombs++; ++m_statCombs;
CombMarkVisitor visitor(oldfuncp); CombMarkVisitor visitor(oldfuncp);
m_call.replaceFunc(oldfuncp, newfuncp); m_call.replaceFunc(oldfuncp, newfuncp);
oldfuncp->unlinkFrBack(); oldfuncp->unlinkFrBack();
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -17
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can // Copyright 2010-2012 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,7 +60,8 @@ class V3ConfigIgnores {
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
IgnLines::const_iterator m_lastEnd; // Point with end() IgnLines::const_iterator m_lastEnd; // Point with end()
IgnFiles m_ignFiles; // Ignores for each filename IgnFiles m_ignWilds; // Ignores for each wildcarded filename
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow) static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
@@ -68,13 +69,13 @@ class V3ConfigIgnores {
~V3ConfigIgnores() {} ~V3ConfigIgnores() {}
// METHODS // METHODS
inline IgnLines* findLines(const string& filename) { inline IgnLines* findWilds(const string& wildname) {
IgnFiles::iterator it = m_ignFiles.find(filename); IgnFiles::iterator it = m_ignWilds.find(wildname);
if (it != m_ignFiles.end()) { if (it != m_ignWilds.end()) {
return &(it->second); return &(it->second);
} else { } else {
m_ignFiles.insert(make_pair(filename, IgnLines())); m_ignWilds.insert(make_pair(wildname, IgnLines()));
it = m_ignFiles.find(filename); it = m_ignWilds.find(wildname);
return &(it->second); return &(it->second);
} }
} }
@@ -82,23 +83,35 @@ class V3ConfigIgnores {
// Given a filename, find all wildcard matches against it and build // Given a filename, find all wildcard matches against it and build
// hash with the specific filename. This avoids having to wildmatch // hash with the specific filename. This avoids having to wildmatch
// more than once against any filename. // more than once against any filename.
IgnLines* linesp = findLines(filename); IgnFiles::iterator it = m_ignFiles.find(filename);
m_lastIt = linesp->begin(); if (it == m_ignFiles.end()) {
m_lastEnd = linesp->end(); // Haven't seen this filename before
m_ignFiles.insert(make_pair(filename, IgnLines()));
it = m_ignFiles.find(filename);
// Make new list for this file of all matches
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
it->second.insert(*lit);
}
}
}
}
m_lastIt = it->second.begin();
m_lastEnd = it->second.end();
} }
public: public:
inline static V3ConfigIgnores& singleton() { return s_singleton; } inline static V3ConfigIgnores& singleton() { return s_singleton; }
void addIgnore(V3ErrorCode code, string filename, int lineno, bool on) { void addIgnore(V3ErrorCode code, string wildname, int lineno, bool on) {
// Insert // Insert
IgnLines* linesp = findLines(filename); IgnLines* linesp = findWilds(wildname);
UINFO(9,"config addIgnore "<<filename<<":"<<lineno<<", "<<code<<", "<<on<<endl); UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
linesp->insert(V3ConfigLine(code, lineno, on)); linesp->insert(V3ConfigLine(code, lineno, on));
if (m_lastFilename == filename) { // Flush the match cache, due to a change in the rules.
// Flush the match cache, due to a change in the rules. m_ignFiles.clear();
m_lastFilename = " "; m_lastFilename = " ";
}
} }
inline void applyIgnores(FileLine* filelinep) { inline void applyIgnores(FileLine* filelinep) {
// HOT routine, called each parsed token line // HOT routine, called each parsed token line
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can // Copyright 2010-2012 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.
+444 -223
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,7 +37,6 @@
#include "V3Const.h" #include "V3Const.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h"
#include "V3Simulate.h" #include "V3Simulate.h"
//###################################################################### //######################################################################
@@ -93,17 +92,20 @@ public:
class ConstVisitor : public AstNVisitor { class ConstVisitor : public AstNVisitor {
private: private:
// NODE STATE // NODE STATE
// ** only when m_warn/m_expensive is set. If state is needed other times, // ** only when m_warn/m_doExpensive is set. If state is needed other times,
// ** must track down everywhere V3Const is called and make sure no overlaps. // ** must track down everywhere V3Const is called and make sure no overlaps.
// AstVar::user4p -> Used by ConstVarMarkVisitor/ConstVarFindVisitor // AstVar::user4p -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
// AstJumpLabel::user4 -> bool. Set when AstJumpGo uses this label
// STATE // STATE
bool m_params; // If true, propogate parameterized and true numbers only bool m_params; // If true, propogate parameterized and true numbers only
bool m_required; // If true, must become a constant bool m_required; // If true, must become a constant
bool m_wremove; // Inside scope, no assignw removal bool m_wremove; // Inside scope, no assignw removal
bool m_warn; // Output warnings bool m_warn; // Output warnings
bool m_cpp; // C++ conversions only bool m_doExpensive; // Enable computationally expensive optimizations
bool m_expensive; // Enable computationally expensive optimizations bool m_doNConst; // Enable non-constant-child simplifications
bool m_doShort; // Remove expressions that short circuit
bool m_doV; // Verilog, not C++ conversion
AstNodeModule* m_modp; // Current module AstNodeModule* m_modp; // Current module
AstNode* m_scopep; // Current scope AstNode* m_scopep; // Current scope
@@ -227,11 +229,13 @@ private:
} }
bool operandHugeShiftL(AstNodeBiop* nodep) { bool operandHugeShiftL(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst() return (nodep->rhsp()->castConst()
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width())); && nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width())
&& isTPure(nodep->lhsp()));
} }
bool operandHugeShiftR(AstNodeBiop* nodep) { bool operandHugeShiftR(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst() return (nodep->rhsp()->castConst()
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width())); && nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width())
&& isTPure(nodep->lhsp()));
} }
bool operandIsTwo(AstNode* nodep) { bool operandIsTwo(AstNode* nodep) {
return (nodep->castConst() return (nodep->castConst()
@@ -288,13 +292,61 @@ private:
// SEL(EXTEND(any,width,...),(width-1),0) -> ... // SEL(EXTEND(any,width,...),(width-1),0) -> ...
// Since select's return unsigned, this is always an extend // Since select's return unsigned, this is always an extend
AstExtend* extendp = nodep->fromp()->castExtend(); AstExtend* extendp = nodep->fromp()->castExtend();
return (!m_cpp if (!(m_doV
&& extendp && extendp
&& nodep->lsbp()->castConst() && nodep->lsbp()->castConst()
&& nodep->widthp()->castConst() && nodep->widthp()->castConst()
&& nodep->lsbConst()==0 && nodep->lsbConst()==0
&& (int)nodep->widthConst()==extendp->lhsp()->width() && (int)nodep->widthConst()==extendp->lhsp()->width()
); )) return false;
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
return true;
}
bool operandSelBiLower(AstSel* nodep) {
// SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b))
// Add or any operation which doesn't care if we discard top bits
AstNodeBiop* bip = nodep->fromp()->castNodeBiop();
if (!(m_doV
&& bip
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
)) return false;
if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:");
AstNode* bilhsp = bip->lhsp()->unlinkFrBack();
AstNode* birhsp = bip->rhsp()->unlinkFrBack();
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
replaceWChild(nodep, bip); nodep=NULL;
return true;
}
bool operandBiExtendConst(AstNodeBiop* nodep) {
// Loop unrolling likes standalone compares
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
// Beware that the constant must have zero bits (+ 1 if signed) or compare
// would be incorrect
AstExtend* extendp = nodep->lhsp()->castExtend();
if (!extendp) return false;
AstNode* smallerp = extendp->lhsp();
int subsize = smallerp->width();
AstConst* constp = nodep->rhsp()->castConst();
if (!constp) return false;
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
//
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
smallerp->unlinkFrBack();
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
nodep->lhsp(smallerp);
constp->unlinkFrBack();
V3Number num (constp->fileline(), subsize);
num.opAssign(constp->num());
nodep->rhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); constp=NULL;
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
return true;
} }
AstNode* afterComment(AstNode* nodep) { AstNode* afterComment(AstNode* nodep) {
@@ -304,6 +356,14 @@ private:
return nodep; return nodep;
} }
bool isTPure(AstNode* nodep) {
// Pure checks - if this node and all nodes under it are free of
// side effects can do this optimization
// Eventually we'll recurse through tree when unknown, memoizing results so far,
// but for now can disable en-mass until V3Purify takes effect.
return m_doShort || nodep->castVarRef() || nodep->castConst();
}
// Extraction checks // Extraction checks
bool warnSelect(AstSel* nodep) { bool warnSelect(AstSel* nodep) {
AstNode* basefromp = AstArraySel::baseFromp(nodep); AstNode* basefromp = AstArraySel::baseFromp(nodep);
@@ -314,7 +374,7 @@ private:
if (m_warn if (m_warn
&& nodep->lsbp()->castConst() && nodep->lsbp()->castConst()
&& nodep->widthp()->castConst() && nodep->widthp()->castConst()
&& (!bdtypep->rangep() || bdtypep->msb())) { // else it's non-resolvable parameterized && (!bdtypep->isRanged() || bdtypep->msb())) { // else it's non-resolvable parameterized
if (nodep->lsbp()->castConst()->num().isFourState() if (nodep->lsbp()->castConst()->num().isFourState()
|| nodep->widthp()->castConst()->num().isFourState()) { || nodep->widthp()->castConst()->num().isFourState()) {
nodep->v3error("Selection index is constantly unknown or tristated: " nodep->v3error("Selection index is constantly unknown or tristated: "
@@ -406,6 +466,21 @@ private:
void replaceZero(AstNode* nodep) { void replaceZero(AstNode* nodep) {
replaceNum(nodep, 0); nodep=NULL; replaceNum(nodep, 0); nodep=NULL;
} }
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
// For example, "0 * n" -> 0 if n has no side effects
// Else strength reduce it to 0 & n.
// If ever change the operation note AstAnd rule specially ignores this created pattern
if (isTPure(checkp)) {
replaceNum(nodep, 0); nodep=NULL;
} else {
AstNode* newp = new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(), 0),
checkp->unlinkFrBack());
newp->widthSignedFrom(nodep);
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
}
void replaceAllOnes (AstNode* nodep) { void replaceAllOnes (AstNode* nodep) {
V3Number ones (nodep->fileline(), nodep->width(), 0); V3Number ones (nodep->fileline(), nodep->width(), 0);
ones.setMask(nodep->width()); ones.setMask(nodep->width());
@@ -723,7 +798,7 @@ private:
return true; return true;
} }
} }
else if (!m_cpp && nodep->lhsp()->castConcat()) { else if (m_doV && nodep->lhsp()->castConcat()) {
bool need_temp = false; bool need_temp = false;
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS? if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
// Note only do this (need user4) when m_warn, which is // Note only do this (need user4) when m_warn, which is
@@ -772,7 +847,9 @@ private:
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign(); AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1); asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1); asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1ap); newp = newp->addNext(asn1ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2ap); newp = newp->addNext(asn2ap);
} else { } else {
if (!m_modp) nodep->v3fatalSrc("Not under module"); if (!m_modp) nodep->v3fatalSrc("Not under module");
@@ -803,12 +880,16 @@ private:
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1); asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1); asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
// This order matters // This order matters
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1ap); newp = newp->addNext(asn1ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2ap); newp = newp->addNext(asn2ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1bp); newp = newp->addNext(asn1bp);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2bp); newp = newp->addNext(asn2bp);
} }
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: "); if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
nodep->addNextHere(newp); nodep->addNextHere(newp);
// Cleanup // Cleanup
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
@@ -854,10 +935,10 @@ private:
// Run it - may be unoptimizable due to large for loop, etc // Run it - may be unoptimizable due to large for loop, etc
simvis.mainParamEmulate(nodep); simvis.mainParamEmulate(nodep);
if (!simvis.optimizable()) { if (!simvis.optimizable()) {
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep; AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
nodep->v3error("Expecting expression to be constant, but can't determine constant for " nodep->v3error("Expecting expression to be constant, but can't determine constant for "
<<nodep->prettyTypeName()<<endl <<nodep->prettyTypeName()<<endl
<<V3Error::msgPrefix()<<errorp->fileline()<<"... Location of non-constant " <<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage()); <<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
replaceZero(nodep); nodep=NULL; replaceZero(nodep); nodep=NULL;
} else { } else {
@@ -1059,16 +1140,50 @@ private:
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL; nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
} }
void replaceSelIntoBiop(AstSel* nodep) {
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
if (!fromp) nodep->v3fatalSrc("Called on non biop");
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->rhsp(new AstSel(nodep->fileline(),
birhsp, lsbp, widthp));
fromp->widthSignedFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
void replaceSelIntoUniop(AstSel* nodep) {
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop();
if (!fromp) nodep->v3fatalSrc("Called on non biop");
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
fromp->widthSignedFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstVarRef* nodep, AstNUser*) { 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_cpp && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) { if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: "); //if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
nodep->varp()->valuep()->iterateAndNext(*this); nodep->varp()->valuep()->iterateAndNext(*this);
if (operandConst(nodep->varp()->valuep()) if (operandConst(nodep->varp()->valuep())
&& !nodep->lvalue() && !nodep->lvalue()
&& ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations && ((!m_params // Can reduce constant wires into equations
&& m_doNConst
&& v3Global.opt.oConst()
&& !nodep->varp()->isSigPublic()) && !nodep->varp()->isSigPublic())
|| nodep->varp()->isParam())) { || nodep->varp()->isParam())) {
AstConst* constp = nodep->varp()->valuep()->castConst(); AstConst* constp = nodep->varp()->valuep()->castConst();
@@ -1105,7 +1220,7 @@ private:
// Someday if lower is constant, convert to quoted "string". // Someday if lower is constant, convert to quoted "string".
virtual void visit(AstAttrOf* nodep, AstNUser*) { virtual void visit(AstAttrOf* nodep, AstNUser*) {
// Don't iterate children, don't want to loose VarRef. // Don't iterate children, don't want to lose VarRef.
if (nodep->attrType()==AstAttrType::EXPR_BITS) { if (nodep->attrType()==AstAttrType::EXPR_BITS) {
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression"); if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin()); V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
@@ -1120,8 +1235,9 @@ private:
} }
virtual void visit(AstSenItem* nodep, AstNUser*) { virtual void visit(AstSenItem* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->sensp()->castConst() if (m_doNConst
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) { && (nodep->sensp()->castConst()
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
// Constants in sensitivity lists may be removed (we'll simplify later) // Constants in sensitivity lists may be removed (we'll simplify later)
if (nodep->isClocked()) { // A constant can never get a pos/negexge if (nodep->isClocked()) { // A constant can never get a pos/negexge
if (onlySenItemInSenTree(nodep)) { if (onlySenItemInSenTree(nodep)) {
@@ -1134,7 +1250,7 @@ private:
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo())); nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
} }
} else if (nodep->sensp()->castNot()) { } else if (m_doNConst && nodep->sensp()->castNot()) {
// V3Gate may propagate NOTs into clocks... Just deal with it // V3Gate may propagate NOTs into clocks... Just deal with it
AstNode* sensp = nodep->sensp(); AstNode* sensp = nodep->sensp();
AstNode* lastSensp = sensp; AstNode* lastSensp = sensp;
@@ -1201,7 +1317,7 @@ private:
virtual void visit(AstSenTree* nodep, AstNUser*) { virtual void visit(AstSenTree* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_expensive) { if (m_doExpensive) {
//cout<<endl; nodep->dumpTree(cout,"ssin: "); //cout<<endl; nodep->dumpTree(cout,"ssin: ");
// Optimize ideas for the future: // Optimize ideas for the future:
// SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b)) // SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b))
@@ -1304,22 +1420,21 @@ private:
// Zero elimination // Zero elimination
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
replaceNodeAssign(nodep); if (m_doNConst && replaceNodeAssign(nodep)) return;
} }
virtual void visit(AstAssignAlias* nodep, AstNUser*) { virtual void visit(AstAssignAlias* nodep, AstNUser*) {
// Don't perform any optimizations, keep the alias around // Don't perform any optimizations, keep the alias around
} }
virtual void visit(AstAssignW* nodep, AstNUser*) { virtual void visit(AstAssignW* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (replaceNodeAssign(nodep)) return; if (m_doNConst && replaceNodeAssign(nodep)) return;
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
if (m_wremove if (m_wremove && !m_params && m_doNConst
&& m_modp && operandConst(nodep->rhsp()) && m_modp && operandConst(nodep->rhsp())
&& !nodep->rhsp()->castConst()->num().isFourState() && !nodep->rhsp()->castConst()->num().isFourState()
&& varrefp // Don't do messes with BITREFs/ARRAYREFs && varrefp // Don't do messes with BITREFs/ARRAYREFs
&& !varrefp->varp()->valuep() // Not already constified && !varrefp->varp()->valuep() // Not already constified
&& !varrefp->varScopep() // Not scoped (or each scope may have different initial value) && !varrefp->varScopep()) { // Not scoped (or each scope may have different initial value)
&& !m_params) {
// ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) ) // ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) )
UINFO(4,"constAssignW "<<nodep<<endl); UINFO(4,"constAssignW "<<nodep<<endl);
// Make a initial assignment // Make a initial assignment
@@ -1339,77 +1454,79 @@ private:
virtual void visit(AstNodeIf* nodep, AstNUser*) { virtual void visit(AstNodeIf* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (AstConst* constp = nodep->condp()->castConst()) { if (m_doNConst) {
AstNode* keepp = NULL; if (AstConst* constp = nodep->condp()->castConst()) {
if (constp->isZero()) { AstNode* keepp = NULL;
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl); if (constp->isZero()) {
keepp = nodep->elsesp(); UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
} else { keepp = nodep->elsesp();
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl); } else {
keepp = nodep->ifsp(); UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
keepp = nodep->ifsp();
}
if (keepp) {
keepp->unlinkFrBackWithNext();
nodep->replaceWith(keepp);
} else {
nodep->unlinkFrBack();
}
nodep->deleteTree(); nodep=NULL;
} }
if (keepp) { else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
keepp->unlinkFrBackWithNext(); // Empty block, remove it
nodep->replaceWith(keepp); // Note if we support more C++ then there might be side effects in the condition itself
} else { nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
nodep->unlinkFrBack(); }
else if (!afterComment(nodep->ifsp())) {
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
AstNode* condp = nodep->condp();
AstNode* elsesp = nodep->elsesp();
condp->unlinkFrBackWithNext();
elsesp->unlinkFrBackWithNext();
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
nodep->addIfsp(elsesp);
}
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|| (nodep->condp()->castLogNot()))
&& nodep->ifsp() && nodep->elsesp()) {
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (ifSameAssign(nodep)) {
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
ifp->unlinkFrBack();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* truep = ifp->rhsp()->unlinkFrBack();
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
ifp->rhsp(new AstCond(truep->fileline(),
condp, truep, falsep));
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
&& operandIfIf(nodep)) {
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
condp, lowerCondp));
lowerIfp->replaceWith(lowerIfsp);
lowerIfp->deleteTree(); lowerIfp=NULL;
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
} }
nodep->deleteTree(); nodep=NULL;
}
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
// Empty block, remove it
// Note if we support more C++ then there might be side effects in the condition itself
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
else if (!afterComment(nodep->ifsp())) {
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
AstNode* condp = nodep->condp();
AstNode* elsesp = nodep->elsesp();
condp->unlinkFrBackWithNext();
elsesp->unlinkFrBackWithNext();
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
nodep->addIfsp(elsesp);
}
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|| (nodep->condp()->castLogNot()))
&& nodep->ifsp() && nodep->elsesp()) {
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (ifSameAssign(nodep)) {
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
ifp->unlinkFrBack();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* truep = ifp->rhsp()->unlinkFrBack();
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
ifp->rhsp(new AstCond(truep->fileline(),
condp, truep, falsep));
nodep->replaceWith(ifp);
nodep->deleteTree(); nodep=NULL;
}
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
&& operandIfIf(nodep)) {
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
AstNode* condp = nodep->condp()->unlinkFrBack();
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
condp, lowerCondp));
lowerIfp->replaceWith(lowerIfsp);
lowerIfp->deleteTree(); lowerIfp=NULL;
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
} }
} }
@@ -1422,7 +1539,7 @@ private:
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) { for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
if (argp->castConst()) { anyconst=true; break; } if (argp->castConst()) { anyconst=true; break; }
} }
if (anyconst) { if (m_doNConst && anyconst) {
//UINFO(9," Display in "<<nodep->text()<<endl); //UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = ""; string dispout = "";
string fmt = ""; string fmt = "";
@@ -1433,7 +1550,7 @@ private:
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
} else if (inPct && isdigit(ch)) { } else if (inPct && (isdigit(ch) || ch=='.')) {
fmt += ch; fmt += ch;
} else if (inPct) { } else if (inPct) {
inPct = false; inPct = false;
@@ -1449,7 +1566,7 @@ private:
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl); UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
{ // fmt = out w/ replace % with %% as it must be literal. { // fmt = out w/ replace % with %% as it must be literal.
fmt = ""; fmt = "";
for (string::iterator pos = out.begin(); pos != out.end(); pos++) { for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
if (*pos == '%') fmt += '%'; if (*pos == '%') fmt += '%';
fmt += *pos; fmt += *pos;
} }
@@ -1485,13 +1602,16 @@ private:
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->condp()->isZero()) { if (m_doNConst) {
UINFO(4,"WHILE(0) => nop "<<nodep<<endl); if (nodep->condp()->isZero()) {
nodep->unlinkFrBack(); UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
nodep->deleteTree(); nodep=NULL; if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
} else nodep->unlinkFrBack();
else if (operandBoolShift(nodep->condp())) { nodep->deleteTree(); nodep=NULL;
replaceBoolShift(nodep->condp()); }
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
}
} }
} }
@@ -1499,6 +1619,44 @@ private:
// If output of a presel didn't get consted, chances are V3Param didn't visit properly // If output of a presel didn't get consted, chances are V3Param didn't visit properly
virtual void visit(AstNodePreSel* nodep, AstNUser*) {} virtual void visit(AstNodePreSel* nodep, AstNUser*) {}
// Ignored, can eliminate early
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_doNConst) {
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
}
// Simplify
virtual void visit(AstBasicDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->cvtRangeConst();
}
//-----
// Jump elimination
virtual void visit(AstJumpGo* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_doExpensive) { nodep->labelp()->user4(true); }
}
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
// Because JumpLabels disable many optimizations,
// remove JumpLabels that are not pointed to by any AstJumpGos
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
nodep->iterateChildren(*this);
// AstJumpGo's below here that point to this node will set user4
if (m_doExpensive && !nodep->user4()) {
UINFO(4,"JUMPLABEL => unused "<<nodep<<endl);
AstNode* underp = NULL;
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
if (underp) nodep->replaceWith(underp);
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
}
}
//----- //-----
// Below lines are magic expressions processed by astgen // Below lines are magic expressions processed by astgen
// "AstNODETYPE { # bracket not paren // "AstNODETYPE { # bracket not paren
@@ -1520,78 +1678,81 @@ private:
// Lint Checks // Lint Checks
// v--- *1* These ops are always first, as we warn before replacing // v--- *1* These ops are always first, as we warn before replacing
// v--- *V* This op is a verilog op, ignore when in m_cpp mode // v--- *V* This op is a verilog op, only in m_doV mode
// v--- *C* This op works on all constant children, allowed in m_doConst mode
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER"); TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
// Generic constants on both side. Do this first to avoid other replacements // Generic constants on both side. Do this first to avoid other replacements
TREEOP("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)"); TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
TREEOP("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)"); TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
// Zero on one side or the other // Zero on one side or the other
TREEOP("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstAnd {$lhsp.isZero, $rhsp, isTPure($rhsp)}", "replaceZero(nodep)"); // Can't use replaceZeroChkPure as we make this pattern in ChkPure
TREEOP("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZeroChkPure(nodep,$rhsp)");
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}"); TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}"); TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
TREEOP("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
TREEOP("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstMul {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
TREEOP("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstMulS {$lhsp, $rhsp.isZero}", "replaceZeroChkPure(nodep,$lhsp)");
TREEOP("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}"); TREEOP ("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
// Non-zero on one side or the other // Non-zero on one side or the other
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes TREEOP ("AstOr {$lhsp.isAllOnes, $rhsp, isTPure($rhsp)}", "replaceWLhs(nodep)"); //->allOnes
TREEOP("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)"); TREEOP ("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
TREEOP("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)"); TREEOP ("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
TREEOP("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)"); TREEOP ("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes, isTPure($lhsp)}", "replaceWRhs(nodep)"); //->allOnes
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)"); TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero, isTPure($lhsp)}", "replaceNum(nodep,1)");
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}"); TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)"); TREEOP ("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)"); TREEOP ("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n TREEOP ("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 ("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
// 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)");
TREEOP("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)"); TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
TREEOP("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)"); TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
TREEOP("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}"); TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a|b TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b
TREEOP("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())"); TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstLogOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a||b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstLogAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&&b
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift // Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)"); TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)"); TREEOP ("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
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)");
// 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)");
@@ -1640,33 +1801,46 @@ private:
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)"); TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
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
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
// Identical operands on both sides // 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
TREEOP("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)"); TREEOP ("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)"); TREEOP ("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)"); TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
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("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP ("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
///=== Verilog operators ///=== Verilog operators
// Comparison against 1'b0/1'b1; must be careful about widths. // Comparison against 1'b0/1'b1; must be careful about widths.
// These use Not, so must be Verilog only // These use Not, so must be Verilog only
@@ -1696,9 +1870,9 @@ private:
TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)"); TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)");
TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)"); TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)");
// Binary AND/OR is faster than logical and/or (usually) // Binary AND/OR is faster than logical and/or (usually)
TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1}", "AstAnd{$lhsp,$rhsp}"); TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1, isTPure($lhsp), isTPure($rhsp)}", "AstAnd{$lhsp,$rhsp}");
TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1}", "AstOr{$lhsp,$rhsp}"); TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1, isTPure($lhsp), isTPure($rhsp)}", "AstOr{$lhsp,$rhsp}");
TREEOPV("AstLogNot{$lhsp.width1}", "AstNot{$lhsp}"); TREEOPV("AstLogNot{$lhsp.width1, isTPure($lhsp)}", "AstNot{$lhsp}");
// CONCAT(CONCAT({a},{b}),{c}) -> CONCAT({a},CONCAT({b},{c})) // CONCAT(CONCAT({a},{b}),{c}) -> CONCAT({a},CONCAT({b},{c}))
// 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)");
@@ -1717,18 +1891,33 @@ private:
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
// 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)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())"); TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())"); TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)"); TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
TREEOPV("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)"); TREEOPV("AstSel{$fromp.castAdd, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)"); TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)"); TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
// V3Tristate requires selects below BufIf1.
// Also do additional operators that are bit-independent, but only definite
// win if bit select is a constant (otherwise we may need to compute bit index several times)
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
// Conversions // Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}"); TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
// Strings // Strings
TREEOP ("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())"); TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
// Possible futures: // Possible futures:
@@ -1755,15 +1944,38 @@ private:
} }
public: public:
// Processing Mode Enum
enum ProcMode {
PROC_PARAMS,
PROC_LIVE,
PROC_V_WARN,
PROC_V_NOWARN,
PROC_V_EXPENSIVE,
PROC_CPP
};
// CONSTUCTORS // CONSTUCTORS
ConstVisitor(bool params, bool expensive, bool warn, bool cpp) { ConstVisitor(ProcMode pmode) {
m_params = params; m_required = params; m_params = false;
m_expensive = expensive; m_required = false;
m_warn = warn; m_doExpensive = false;
m_cpp = cpp; m_doNConst = false;
m_wremove = true; m_doShort = true; // Presently always done
m_doV = false;
m_warn = false;
m_wremove = true; // Overridden in visitors
m_modp = NULL; m_modp = NULL;
m_scopep = NULL; m_scopep = NULL;
//
switch (pmode) {
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
case PROC_LIVE: break;
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
case PROC_V_EXPENSIVE: m_doV = true; m_doNConst = true; m_doExpensive = true; break;
case PROC_CPP: m_doV = false; m_doNConst = true; break;
default: v3fatalSrc("Bad case"); break;
}
} }
virtual ~ConstVisitor() {} virtual ~ConstVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) { AstNode* mainAcceptEdit(AstNode* nodep) {
@@ -1780,7 +1992,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
// Resize even if the node already has a width, because burried in the treee we may // Resize even if the node already has a width, because burried in the treee we may
// have a node we just created with signing, etc, that isn't sized yet. // have a node we just created with signing, etc, that isn't sized yet.
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
ConstVisitor visitor (true,false,false,false); ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
if (AstVar* varp=nodep->castVar()) { if (AstVar* varp=nodep->castVar()) {
// If a var wants to be constified, it's really a param, and // If a var wants to be constified, it's really a param, and
// we want the value to be constant. We aren't passed just the // we want the value to be constant. We aren't passed just the
@@ -1794,34 +2006,43 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
return nodep; return nodep;
} }
void V3Const::constifyAll(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,true,false,false);
(void)visitor.mainAcceptEdit(nodep);
}
void V3Const::constifyAllLint(AstNetlist* nodep) { void V3Const::constifyAllLint(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s // Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,false,true,false); ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
} }
void V3Const::constifyCpp(AstNetlist* nodep) { void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,false,false,true); ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep); (void)visitor.mainAcceptEdit(nodep);
} }
AstNode* V3Const::constifyEdit(AstNode* nodep) { AstNode* V3Const::constifyEdit(AstNode* nodep) {
ConstVisitor visitor (false,false,false,false); ConstVisitor visitor (ConstVisitor::PROC_V_NOWARN);
nodep = visitor.mainAcceptEdit(nodep); nodep = visitor.mainAcceptEdit(nodep);
return nodep; return nodep;
} }
void V3Const::constifyAllLive(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
// This only pushes constants up, doesn't make any other edits
// IE doesn't prune dead statements, as we need to do some usability checks after this
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep);
}
void V3Const::constifyAll(AstNetlist* nodep) {
// Only call from Verilator.cpp, as it uses user#'s
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep);
}
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) { AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
ConstVisitor visitor (false,true,false,false); ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
nodep = visitor.mainAcceptEdit(nodep); nodep = visitor.mainAcceptEdit(nodep);
return nodep; return nodep;
} }
+3 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -34,6 +34,8 @@ public:
// Force this cell node's parameter list to become a constant // Force this cell node's parameter list to become a constant
// Return new node that may have replaced nodep // Return new node that may have replaced nodep
static AstNode* constifyParamsEdit(AstNode* nodep); static AstNode* constifyParamsEdit(AstNode* nodep);
// Only do constant pushing, without removing dead logic
static void constifyAllLive(AstNetlist* nodep);
// Everything that's possible // Everything that's possible
static void constifyAll(AstNetlist* nodep); static void constifyAll(AstNetlist* nodep);
// Also, warn // Also, warn
+9 -7
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,11 +81,13 @@ private:
string prettyName = nodep->prettyName(); string prettyName = nodep->prettyName();
if (!nodep->isToggleCoverable()) if (!nodep->isToggleCoverable())
return "Not relevant signal type"; return "Not relevant signal type";
if (prettyName.c_str()[0] == '_') if (!v3Global.opt.coverageUnderscore()) {
return "Leading underscore"; if (prettyName.c_str()[0] == '_')
if (prettyName.find("._") != string::npos) return "Leading underscore";
return "Inlined leading underscore"; if (prettyName.find("._") != string::npos)
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits"; return "Inlined leading underscore";
}
if ((nodep->width()*nodep->dtypep()->arrayElements()) > 256) return "Wide bus/array > 256 bits";
// We allow this, though tracing doesn't // We allow this, though tracing doesn't
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array"; // if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
return NULL; return NULL;
@@ -191,7 +193,7 @@ private:
const ToggleEnt& above, const ToggleEnt& above,
AstVar* varp, AstVar* chgVarp) { // Constant AstVar* varp, AstVar* chgVarp) { // Constant
if (AstBasicDType* bdtypep = dtypep->castBasicDType()) { if (AstBasicDType* bdtypep = dtypep->castBasicDType()) {
if (bdtypep->rangep()) { if (bdtypep->isRanged()) {
for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) { for (int index_docs=bdtypep->lsb(); index_docs<bdtypep->msb()+1; index_docs++) {
int index_code = index_docs - bdtypep->lsb(); int index_code = index_docs - bdtypep->lsb();
ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]", ToggleEnt newent (above.m_comment+string("[")+cvtToStr(index_docs)+"]",
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -2
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,7 @@ private:
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL; removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
// Remove node from comparison so don't hit it again // Remove node from comparison so don't hit it again
hashed.erase(dupit); hashed.erase(dupit);
m_statToggleJoins++; ++m_statToggleJoins;
} }
} }
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
+40 -22
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -70,16 +70,16 @@ class DeadVisitor : public AstNVisitor {
private: private:
// NODE STATE // NODE STATE
// Entire Netlist: // Entire Netlist:
// AstNodeModule::user() -> int. Count of number of cells referencing this module. // AstNodeModule::user1() -> int. Count of number of cells referencing this module.
// AstVar::user() -> int. Count of number of references // AstVar::user1() -> int. Count of number of references
// AstVarScope::user() -> int. Count of number of references // AstVarScope::user1() -> int. Count of number of references
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
// TYPES // TYPES
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap; typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE // STATE
vector<AstVar*> m_varsp; // 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
bool m_elimUserVars; // Allow removal of user's vars bool m_elimUserVars; // Allow removal of user's vars
@@ -91,44 +91,63 @@ private:
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__); if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level; return level;
} }
void checkAll(AstNode* nodep) {
}
// VISITORS // VISITORS
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->modp()->user1(nodep->modp()->user1() + 1); checkAll(nodep);
nodep->modp()->user1Inc();
} }
virtual void visit(AstNodeVarRef* nodep, AstNUser*) { virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->varScopep()) { if (nodep->varScopep()) {
nodep->varScopep()->user1(nodep->varScopep()->user1() + 1); nodep->varScopep()->user1Inc();
nodep->varScopep()->varp()->user1(nodep->varScopep()->varp()->user1() + 1); nodep->varScopep()->varp()->user1Inc();
} }
if (nodep->varp()) { if (nodep->varp()) {
nodep->varp()->user1(nodep->varp()->user1() + 1); nodep->varp()->user1Inc();
} }
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1); nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1); nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstRefDType* nodep, AstNUser*) { virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->packagep()) { if (nodep->packagep()) {
nodep->packagep()->user1(nodep->packagep()->user1() + 1); nodep->packagep()->user1Inc();
}
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
checkAll(nodep);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_vscsp.push_back(nodep); checkAll(nodep);
if (mightElim(nodep->varp())) {
m_vscsp.push_back(nodep);
}
} }
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_varsp.push_back(nodep); checkAll(nodep);
if (mightElim(nodep)) {
m_varEtcsp.push_back(nodep);
}
} }
virtual void visit(AstNodeAssign* nodep, AstNUser*) { virtual void visit(AstNodeAssign* nodep, AstNUser*) {
@@ -144,15 +163,14 @@ private:
} else { // Track like any other statement } else { // Track like any other statement
nodep->lhsp()->iterateAndNext(*this); nodep->lhsp()->iterateAndNext(*this);
} }
} checkAll(nodep);
virtual void visit(AstUCFunc* nodep, AstNUser*) {
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
nodep->iterateChildren(*this);
} }
//----- //-----
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
if (nodep->isOutputter()) m_sideEffect=true;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
checkAll(nodep);
} }
// METHODS // METHODS
@@ -177,7 +195,7 @@ private:
} }
} }
} }
bool canElim(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() || m_elimUserVars));
@@ -186,7 +204,7 @@ private:
// Delete any unused varscopes // Delete any unused varscopes
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) { for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
AstVarScope* vscp = *it; AstVarScope* vscp = *it;
if (vscp->user1() == 0 && canElim(vscp->varp())) { if (vscp->user1() == 0) {
UINFO(4," Dead "<<vscp<<endl); UINFO(4," Dead "<<vscp<<endl);
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp); pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) { for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
@@ -197,8 +215,8 @@ private:
vscp->unlinkFrBack()->deleteTree(); vscp=NULL; vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
} }
} }
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) { for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
if ((*it)->user1() == 0 && canElim((*it))) { if ((*it)->user1() == 0) {
UINFO(4," Dead "<<(*it)<<endl); UINFO(4," Dead "<<(*it)<<endl);
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL; (*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
} }
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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 -47
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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,14 +74,15 @@ private:
// NODE STATE // NODE STATE
// Cleared each module: // Cleared each module:
// AstVarScope::user1p() -> AstVarScope*. Points to temp var created. // AstVarScope::user1p() -> AstVarScope*. Points to temp var created.
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal // AstVarScope::user2p() -> AstActive*. Points to activity block of signal (valid when AstVarScope::user1p is valid)
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable // AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage // AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
// AstVar::user2() -> bool. Set true if already made warning // AstVar::user2() -> bool. Set true if already made warning
// AstVar::user4() -> int. Vector number, for assignment creation // AstVar::user4() -> int. Vector number, for assignment creation
// AstVarRef::user2() -> bool. Set true if already processed // AstVarRef::user2() -> bool. Set true if already processed
// AstAlwaysPost::user2() -> ActActive*. Points to activity block of signal (valid when AstAlwaysPost::user4p is valid)
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost // AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
// Cleared each scope: // Cleared each scope/active:
// AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign // AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign
// AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF // AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
@@ -132,8 +133,8 @@ private:
if (width==0) { if (width==0) {
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp()); varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, oldvarscp->varp());
varp->widthSignedFrom(oldvarscp); varp->widthSignedFrom(oldvarscp);
} else { } else { // Used for vset and dimensions, so can zero init
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstLogicPacked(), width); varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, AstBitPacked(), width);
} }
addmodp->addStmtp(varp); addmodp->addStmtp(varp);
m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp)); m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp));
@@ -144,6 +145,40 @@ private:
return varscp; return varscp;
} }
AstActive* createActivePost(AstVarRef* varrefp) {
AstActive* newactp = new AstActive (varrefp->fileline(), "sequentdly",
m_activep->sensesp());
m_activep->addNext(newactp);
return newactp;
}
void checkActivePost(AstVarRef* varrefp, AstActive* oldactivep) {
// Check for MULTIDRIVEN, and if so make new sentree that joins old & new sentree
if (!oldactivep) varrefp->v3fatalSrc("<= old dly assignment not put under sensitivity block");
if (oldactivep->sensesp() != m_activep->sensesp()) {
if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
&& !varrefp->varp()->user2()) {
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName());
varrefp->v3warn(MULTIDRIVEN,"... Location of first driving block");
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
varrefp->varp()->user2(true);
}
UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
UINFO(4," Act: "<<m_activep<<endl);
UINFO(4," Act: "<<oldactivep<<endl);
// Make a new sensitivity list, which is the combination of both blocks
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
if (senb) treep->addSensesp(senb);
if (AstSenTree* storep = oldactivep->sensesStorep()) {
storep->unlinkFrBack();
pushDeletep(storep);
}
oldactivep->sensesStorep(treep);
oldactivep->sensesp(treep);
}
}
AstNode* createDlyArray(AstAssignDly* nodep, AstNode* lhsp) { AstNode* createDlyArray(AstAssignDly* nodep, AstNode* lhsp) {
// Create delayed assignment // Create delayed assignment
// See top of this file for transformation // See top of this file for transformation
@@ -224,25 +259,22 @@ private:
} }
// //
//=== Setting/not setting boolean: __Vdlyvset__ //=== Setting/not setting boolean: __Vdlyvset__
bool sharedVset = false;
AstVarScope* setvscp; AstVarScope* setvscp;
AstAssignPre* setinitp = NULL;
if (nodep->user3p()) { if (nodep->user3p()) {
// Simplistic optimization. If the previous statement in same scope was also a =>, // Simplistic optimization. If the previous statement in same scope was also a =>,
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one. // then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
// This is good for code like: // This is good for code like:
// for (i=0; i<5; i++) vector[i] <= something; // for (i=0; i<5; i++) vector[i] <= something;
sharedVset = true;
setvscp = nodep->user3p()->castNode()->castVarScope(); setvscp = nodep->user3p()->castNode()->castVarScope();
m_statSharedSet++; ++m_statSharedSet;
} else { // Create new one } else { // Create new one
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1); setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
AstAssignPre* setinitp setinitp = new AstAssignPre (nodep->fileline(),
= 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));
m_activep->addStmtsp(setinitp);
AstAssign* setassignp AstAssign* setassignp
= new AstAssign (nodep->fileline(), = new AstAssign (nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, true), new AstVarRef(nodep->fileline(), setvscp, true),
@@ -271,11 +303,18 @@ private:
UINFO(9," For "<<setvscp<<endl); UINFO(9," For "<<setvscp<<endl);
UINFO(9," & "<<varrefp<<endl); UINFO(9," & "<<varrefp<<endl);
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost(); AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
if (!finalp) { if (finalp) {
AstActive* oldactivep = finalp->user2p()->castNode()->castActive();
checkActivePost(varrefp, oldactivep);
if (setinitp) oldactivep->addStmtsp(setinitp);
} else { // first time we've dealt with this memory
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/); finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
UINFO(9," Created "<<finalp<<endl); UINFO(9," Created "<<finalp<<endl);
m_activep->addStmtsp(finalp); AstActive* newactp = createActivePost(varrefp);
newactp->addStmtsp(finalp);
varrefp->varScopep()->user4p(finalp); varrefp->varScopep()->user4p(finalp);
finalp->user2p(newactp);
if (setinitp) newactp->addStmtsp(setinitp);
} }
AstIf* postLogicp; AstIf* postLogicp;
if (finalp->user3p()->castNode() == setvscp) { if (finalp->user3p()->castNode() == setvscp) {
@@ -294,7 +333,6 @@ private:
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
} }
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp)); postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
return newlhsp; return newlhsp;
} }
@@ -318,6 +356,7 @@ private:
m_activep = nodep; m_activep = nodep;
bool oldinit = m_inInitial; bool oldinit = m_inInitial;
m_inInitial = nodep->hasInitial(); m_inInitial = nodep->hasInitial();
AstNode::user3ClearTree(); // Two sets to same variable in different actives must use different vars.
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_inInitial = oldinit; m_inInitial = oldinit;
} }
@@ -344,10 +383,9 @@ private:
m_inDly = false; m_inDly = false;
m_nextDlyp = NULL; m_nextDlyp = NULL;
} }
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->user2()) { // Not done yet
nodep->user2(true);
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->user2Inc()) { // Not done yet
if (m_inDly && nodep->lvalue()) { if (m_inDly && nodep->lvalue()) {
UINFO(4,"AssignDlyVar: "<<nodep<<endl); UINFO(4,"AssignDlyVar: "<<nodep<<endl);
markVarUsage(nodep->varScopep(), VU_DLY); markVarUsage(nodep->varScopep(), VU_DLY);
@@ -358,30 +396,7 @@ private:
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope(); AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
if (dlyvscp) { // Multiple use of delayed variable if (dlyvscp) { // Multiple use of delayed variable
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive(); AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
if (!oldactivep) nodep->v3fatalSrc("<= old dly assignment not put under sensitivity block"); checkActivePost(nodep, oldactivep);
if (oldactivep->sensesp() != m_activep->sensesp()) {
if (!nodep->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
&& !nodep->varp()->user2()) {
nodep->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<nodep->varp()->prettyName());
nodep->v3warn(MULTIDRIVEN,"... Location of first driving block");
oldactivep->v3warn(MULTIDRIVEN,"... Location of other driving block");
nodep->varp()->user2(true);
}
UINFO(4,"AssignDupDlyVar: "<<nodep<<endl);
UINFO(4," Act: "<<m_activep<<endl);
UINFO(4," Act: "<<oldactivep<<endl);
// Make a new sensitivity list, which is the combination of both blocks
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
if (senb) treep->addSensesp(senb);
if (AstSenTree* storep = oldactivep->sensesStorep()) {
storep->unlinkFrBack();
pushDeletep(storep);
}
oldactivep->sensesStorep(treep);
oldactivep->sensesp(treep);
}
} }
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());
@@ -397,12 +412,10 @@ private:
postp->lhsp()->user2(true); // Don't detect this assignment postp->lhsp()->user2(true); // Don't detect this assignment
oldvscp->user1p(dlyvscp); // So we can find it later oldvscp->user1p(dlyvscp); // So we can find it later
// Make new ACTIVE with identical sensitivity tree // Make new ACTIVE with identical sensitivity tree
AstActive* newactp = new AstActive (nodep->fileline(), "sequentdly", AstActive* newactp = createActivePost(nodep);
m_activep->sensesp()); dlyvscp->user2p(newactp);
newactp->addStmtsp(prep); // Add to FRONT of statements newactp->addStmtsp(prep); // Add to FRONT of statements
newactp->addStmtsp(postp); newactp->addStmtsp(postp);
m_activep->addNext(newactp);
dlyvscp->user2p(newactp);
} }
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true); AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
newrefp->user2(true); // No reason to do it again newrefp->user2(true); // No reason to do it again
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -68,6 +68,7 @@ private:
// Width, not widthMin, as we may be in middle of BITSEL expression which // Width, not widthMin, as we may be in middle of BITSEL expression which
// though it's one bit wide, needs the mask in the upper bits. // though it's one bit wide, needs the mask in the upper bits.
// (Someday we'll have a valid bitmask instead of widths....) // (Someday we'll have a valid bitmask instead of widths....)
// See t_func_crc for an example test that requires this
AstLogicPacked(), nodep->width()); AstLogicPacked(), nodep->width());
if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function"); if (!m_funcp) nodep->v3fatalSrc("Deep expression not under a function");
m_funcp->addInitsp(varp); m_funcp->addInitsp(varp);
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License // Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0. // Version 2.0.
+134 -48
View File
@@ -7,7 +7,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.
@@ -55,9 +55,9 @@ public:
} }
// ACCESSORS // ACCESSORS
int splitFilenum() { return m_splitFilenum; } int splitFilenum() const { return m_splitFilenum; }
int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; } int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; }
int splitSize() { return m_splitSize; } int splitSize() const { return m_splitSize; }
void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); } void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); }
bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1 bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1
&& v3Global.opt.outputSplit() < splitSize()); } && v3Global.opt.outputSplit() < splitSize()); }
@@ -127,6 +127,7 @@ public:
nodep->lhsp()->iterateAndNext(*this); puts(", "); nodep->lhsp()->iterateAndNext(*this); puts(", ");
} else if (nodep->isWide() } else if (nodep->isWide()
&& nodep->lhsp()->castVarRef() && nodep->lhsp()->castVarRef()
&& !nodep->rhsp()->castCMath()
&& !nodep->rhsp()->castVarRef() && !nodep->rhsp()->castVarRef()
&& !nodep->rhsp()->castArraySel()) { && !nodep->rhsp()->castArraySel()) {
// Wide functions assign into the array directly, don't need separate assign statement // Wide functions assign into the array directly, don't need separate assign statement
@@ -149,6 +150,8 @@ public:
if (decind) ofp()->blockDec(); if (decind) ofp()->blockDec();
if (!m_suppressSemi) puts(";\n"); if (!m_suppressSemi) puts(";\n");
} }
virtual void visit(AstAlwaysPublic*, AstNUser*) {
}
virtual void visit(AstCCall* nodep, AstNUser*) { virtual void visit(AstCCall* nodep, AstNUser*) {
puts(nodep->hiername()); puts(nodep->hiername());
puts(nodep->funcp()->name()); puts(nodep->funcp()->name());
@@ -319,7 +322,7 @@ public:
AstVarRef* varrefp = nodep->memp()->castVarRef(); AstVarRef* varrefp = nodep->memp()->castVarRef();
if (!varrefp) { nodep->v3error("Readmem loading non-variable"); } if (!varrefp) { nodep->v3error("Readmem loading non-variable"); }
else if (AstArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castArrayDType()) { else if (AstArrayDType* adtypep = varrefp->varp()->dtypeSkipRefp()->castArrayDType()) {
puts(cvtToStr(varrefp->varp()->arrayElements())); puts(cvtToStr(varrefp->varp()->dtypep()->arrayElements()));
array_lsb = adtypep->lsb(); array_lsb = adtypep->lsb();
} }
else { else {
@@ -341,13 +344,11 @@ public:
puts(");\n"); puts(");\n");
} }
virtual void visit(AstFClose* nodep, AstNUser*) { virtual void visit(AstFClose* nodep, AstNUser*) {
puts("if ("); puts("VL_FCLOSE_I(");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(") { fclose (VL_CVT_Q_FP("); puts("); ");
nodep->filep()->iterateAndNext(*this);
puts(")); ");
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it. nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
puts("=0; }\n"); puts("=0;\n");
} }
virtual void visit(AstFFlush* nodep, AstNUser*) { virtual void visit(AstFFlush* nodep, AstNUser*) {
if (!nodep->filep()) { if (!nodep->filep()) {
@@ -355,17 +356,51 @@ public:
} else { } else {
puts("if ("); puts("if (");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP("); puts(") { fflush (VL_CVT_I_FP(");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(")); }\n"); puts(")); }\n");
} }
} }
virtual void visit(AstSystemT* nodep, AstNUser*) {
puts("(void)VL_SYSTEM_I");
emitIQW(nodep->lhsp());
puts("(");
if (nodep->lhsp()->isWide()) {
puts(cvtToStr(nodep->lhsp()->widthWords()));
putbs(", ");
}
checkMaxWords(nodep->lhsp());
nodep->lhsp()->iterateAndNext(*this);
puts(");\n");
}
virtual void visit(AstSystemF* nodep, AstNUser*) {
puts("VL_SYSTEM_I");
emitIQW(nodep->lhsp());
puts("(");
if (nodep->lhsp()->isWide()) {
puts(cvtToStr(nodep->lhsp()->widthWords()));
putbs(", ");
}
checkMaxWords(nodep->lhsp());
nodep->lhsp()->iterateAndNext(*this);
puts(")");
}
virtual void visit(AstJumpGo* nodep, AstNUser*) {
puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n");
}
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
puts("{\n");
nodep->stmtsp()->iterateAndNext(*this);
puts("}\n");
puts("__Vlabel"+cvtToStr(nodep->labelNum())+": ;\n");
}
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->precondsp()->iterateAndNext(*this); nodep->precondsp()->iterateAndNext(*this);
puts("while ("); puts("while (");
nodep->condp()->iterateAndNext(*this); nodep->condp()->iterateAndNext(*this);
puts(") {\n"); puts(") {\n");
nodep->bodysp()->iterateAndNext(*this); nodep->bodysp()->iterateAndNext(*this);
nodep->incsp()->iterateAndNext(*this);
nodep->precondsp()->iterateAndNext(*this); // Need to recompute before next loop nodep->precondsp()->iterateAndNext(*this); // Need to recompute before next loop
puts("}\n"); puts("}\n");
} }
@@ -463,7 +498,7 @@ public:
} }
visit(nodep->castNodeBiop(), vup); visit(nodep->castNodeBiop(), vup);
} }
virtual void visit(AstCast* nodep, AstNUser*) { virtual void visit(AstCCast* nodep, AstNUser*) {
// Extending a value of the same word width is just a NOP. // Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) { if (nodep->size()>VL_WORDSIZE) {
puts("(QData)("); puts("(QData)(");
@@ -517,7 +552,7 @@ public:
nodep->v3error("Unsupported: 4-state numbers in this context"); nodep->v3error("Unsupported: 4-state numbers in this context");
} else if (nodep->isWide()) { } else if (nodep->isWide()) {
putbs("VL_CONST_W_"); putbs("VL_CONST_W_");
puts(cvtToStr(VL_WORDS_I(nodep->num().minWidth()))); puts(cvtToStr(VL_WORDS_I(nodep->num().widthMin())));
puts("X("); puts("X(");
puts(cvtToStr(nodep->widthMin())); puts(cvtToStr(nodep->widthMin()));
puts(","); puts(",");
@@ -529,19 +564,22 @@ public:
} else { } else {
assigntop->iterateAndNext(*this); assigntop->iterateAndNext(*this);
} }
for (int word=VL_WORDS_I(nodep->num().minWidth())-1; word>0; word--) { for (int word=VL_WORDS_I(nodep->num().widthMin())-1; word>0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning // Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", (long long)(nodep->num().dataWord(word))); ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
} }
ofp()->printf(",0x%08" VL_PRI64 "x)", (long long)(nodep->num().dataWord(0))); ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
} else if (nodep->isDouble()) {
ofp()->printf("%.17g", nodep->num().toDouble());
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
vluint64_t num = nodep->toUQuad(); vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", (long long)num); if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", (long long)num); else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", num);
} else { } else {
uint32_t num = nodep->toUInt(); uint32_t num = nodep->toUInt();
// Only 32 bits - llx + long long here just to appease CPP format warning
if (num<10) puts(cvtToStr(num)); if (num<10) puts(cvtToStr(num));
else ofp()->printf("0x%" VL_PRI64 "x", (long long)num); else ofp()->printf("0x%" VL_PRI64 "x", (vluint64_t)num);
//Unneeded-Causes %lx format warnings: //Unneeded-Causes %lx format warnings:
// if (!nodep->num().isSigned() && (num & (1UL<<31))) puts("U"); // if (!nodep->num().isSigned() && (num & (1UL<<31))) puts("U");
} }
@@ -639,10 +677,10 @@ class EmitCImp : EmitCStmts {
puts(" | ("); puts(" | (");
} }
changep->lhsp()->iterateAndNext(*this); changep->lhsp()->iterateAndNext(*this);
if (changep->isWide()) puts("["+cvtToStr(word)+"]"); if (changep->lhsp()->isWide()) puts("["+cvtToStr(word)+"]");
puts(" ^ "); puts(" ^ ");
changep->rhsp()->iterateAndNext(*this); changep->rhsp()->iterateAndNext(*this);
if (changep->isWide()) puts("["+cvtToStr(word)+"]"); if (changep->lhsp()->isWide()) puts("["+cvtToStr(word)+"]");
puts(")"); puts(")");
} }
} }
@@ -816,6 +854,8 @@ class EmitCImp : EmitCStmts {
public: public:
EmitCImp() { EmitCImp() {
m_modp = NULL; m_modp = NULL;
m_slow = false;
m_fast = false;
} }
virtual ~EmitCImp() {} virtual ~EmitCImp() {}
void main(AstNodeModule* modp, bool slow, bool fast); void main(AstNodeModule* modp, bool slow, bool fast);
@@ -832,9 +872,6 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->isIO()) { if (nodep->isIO()) {
bool isArray = !nodep->dtypeSkipRefp()->castBasicDType(); bool isArray = !nodep->dtypeSkipRefp()->castBasicDType();
if (nodep->isSc()) { if (nodep->isSc()) {
if (isArray) {
nodep->v3error("Unsupported: SystemC inputs and outputs must be simple data types; no arrays");
}
m_ctorVarsVec.push_back(nodep); m_ctorVarsVec.push_back(nodep);
ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment
if (nodep->attrScClocked() && nodep->isInput()) { if (nodep->attrScClocked() && nodep->isInput()) {
@@ -849,6 +886,12 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(">\t"); puts(">\t");
} }
puts(nodep->name()); puts(nodep->name());
if (isArray) {
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]");
}
}
puts(";\n"); puts(";\n");
} else { // C++ signals } else { // C++ signals
ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(), ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(),
@@ -865,7 +908,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (isArray) { if (isArray) {
if (nodep->isWide()) puts("W"); if (nodep->isWide()) puts("W");
puts("("+nodep->name()); puts("("+nodep->name());
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) { for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]"); puts("["+cvtToStr(arrayp->elementsConst())+"]");
} }
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb())); puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
@@ -886,7 +930,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
// strings and other fundamental c types // strings and other fundamental c types
puts(nodep->vlArgType(true,false)); puts(nodep->vlArgType(true,false));
// This isn't very robust and may need cleanup for other data types // This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) { for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]"); puts("["+cvtToStr(arrayp->elementsConst())+"]");
} }
puts(";\n"); puts(";\n");
@@ -911,7 +956,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); } if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
puts(nodep->name()); puts(nodep->name());
// This isn't very robust and may need cleanup for other data types // This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) { for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
puts("["+cvtToStr(arrayp->elementsConst())+"]"); puts("["+cvtToStr(arrayp->elementsConst())+"]");
} }
puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb())); puts(","+cvtToStr(basicp->msb())+","+cvtToStr(basicp->lsb()));
@@ -921,22 +967,29 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
} }
void EmitCStmts::emitVarCtors() { void EmitCStmts::emitVarCtors() {
ofp()->indentInc(); if (!m_ctorVarsVec.empty()) {
bool first = true; ofp()->indentInc();
for (vector<AstVar*>::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) { puts("\n");
if (first) { puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer
first=false; bool first = true;
puts("\n"); for (vector<AstVar*>::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) {
puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer AstVar* varp = *it;
puts(" : "); bool isArray = !varp->dtypeSkipRefp()->castBasicDType();
if (isArray) {
puts("// Skipping array: ");
puts(varp->name());
puts("\n");
} else {
if (first) { puts(" : "); first=false; }
else puts(", ");
if (ofp()->exceededWidth()) puts("\n ");
puts(varp->name());
puts("("); putsQuoted(varp->name()); puts(")");
}
} }
else puts(", "); puts ("\n#endif\n");
if (ofp()->exceededWidth()) puts("\n "); ofp()->indentDec();
puts((*it)->name());
puts("("); putsQuoted((*it)->name()); puts(")");
} }
if (!first) puts ("\n#endif\n");
ofp()->indentDec();
} }
bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) { bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) {
@@ -1198,6 +1251,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
switch (tolower(pos[0])) { switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '.':
// Digits, like %5d, etc. // Digits, like %5d, etc.
vfmt += pos[0]; vfmt += pos[0];
inPct = true; // Get more digits inPct = true; // Get more digits
@@ -1216,6 +1270,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
case 'h': case 'h':
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break; case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break; case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
case 'm': { case 'm': {
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName"); if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
string suffix = scopenamep->scopePrettyName(); string suffix = scopenamep->scopePrettyName();
@@ -1309,7 +1366,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
puts(varp->name()); puts(varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]"); for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
if (zeroit) { if (zeroit) {
puts("= 0;\n"); puts(" = 0;\n");
} else { } else {
puts(" = VL_RAND_RESET_"); puts(" = VL_RAND_RESET_");
emitIQW(varp); emitIQW(varp);
@@ -1406,6 +1463,7 @@ void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
// Need implementation here. Be careful of alignment code; needs to be uniquified // Need implementation here. Be careful of alignment code; needs to be uniquified
// with module name to avoid multiple symbols. // with module name to avoid multiple symbols.
//emitVarList(modp->stmtsp(), EVL_ALL, modp->name()); //emitVarList(modp->stmtsp(), EVL_ALL, modp->name());
puts(""); // NOP for cppcheck, otherwise const function
} }
void EmitCImp::emitTextSection(AstType type) { void EmitCImp::emitTextSection(AstType type) {
@@ -1455,7 +1513,22 @@ void EmitCImp::emitSensitives() {
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstVar* varp = nodep->castVar()) { if (AstVar* varp = nodep->castVar()) {
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) { if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
puts("sensitive << "+varp->name()+";\n"); int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
int vecnum = vects++;
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
string ivar = string("__Vi")+cvtToStr(vecnum);
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(arrayp->lsb())+";");
puts(" for (; "+ivar+"<="+cvtToStr(arrayp->msb()));
puts("; ++"+ivar+") {\n");
}
puts("sensitive << "+varp->name());
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
puts(";\n");
for (int v=0; v<vects; ++v) puts( "}}\n");
} }
} }
} }
@@ -1606,7 +1679,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
puts("#include \""+topClassName()+"__Inlines.h\"\n"); puts("#include \""+topClassName()+"__Inlines.h\"\n");
} }
// No __Dpi.h needed, we've shimmed it all into the interface if (v3Global.dpi()) {
// do this before including our main .h file so that any references to
// types defined in svdpi.h are available
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
puts("\n");
}
// Declare foreign instances up front to make C++ happy // Declare foreign instances up front to make C++ happy
puts("class "+symClassName()+";\n"); puts("class "+symClassName()+";\n");
@@ -1784,8 +1862,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
// Us // Us
puts("#include \""+ symClassName() +".h\"\n"); puts("#include \""+ symClassName() +".h\"\n");
if (v3Global.dpi()) { if (v3Global.dpi()) {
puts("#include \""+ topClassName() +"__Dpi.h\"\n"); puts("\n");
puts("#include \"verilated_dpi.h\"\n");
} }
if (optSystemPerl() && (splitFilenum() || !m_fast)) { if (optSystemPerl() && (splitFilenum() || !m_fast)) {
@@ -1990,7 +2070,9 @@ class EmitCTrace : EmitCStmts {
return varp->isSc() && varp->isScBv(); return varp->isSc() && varp->isScBv();
} }
void emitTraceInitOne(AstTraceDecl* nodep) { void emitTraceInitOne(AstTraceDecl* nodep) {
if (nodep->isWide()) { if (nodep->isDouble()) {
puts("vcdp->declDouble");
} else if (nodep->isWide()) {
puts("vcdp->declArray"); puts("vcdp->declArray");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->declQuad "); puts("vcdp->declQuad ");
@@ -2008,7 +2090,8 @@ class EmitCTrace : EmitCStmts {
} else { } else {
puts(",-1"); puts(",-1");
} }
if (nodep->msbEndianed() || nodep->lsbEndianed()) { if (!nodep->isDouble() // When float/double no longer have widths this can go
&& (nodep->msbEndianed() || nodep->lsbEndianed())) {
puts(","+cvtToStr(nodep->msbEndianed())+","+cvtToStr(nodep->lsbEndianed())); puts(","+cvtToStr(nodep->msbEndianed())+","+cvtToStr(nodep->lsbEndianed()));
} }
puts(");"); puts(");");
@@ -2019,7 +2102,9 @@ class EmitCTrace : EmitCStmts {
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB) || m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
? "full":"chg"); ? "full":"chg");
if (nodep->isWide() || emitTraceIsScBv(nodep)) { if (nodep->isDouble()) {
puts("vcdp->"+full+"Double");
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
puts("vcdp->"+full+"Array"); puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad "); puts("vcdp->"+full+"Quad ");
@@ -2032,7 +2117,8 @@ class EmitCTrace : EmitCStmts {
+ ((arrayindex<0) ? 0 : (arrayindex*nodep->declp()->widthWords())))); + ((arrayindex<0) ? 0 : (arrayindex*nodep->declp()->widthWords()))));
puts(","); puts(",");
emitTraceValue(nodep, arrayindex); emitTraceValue(nodep, arrayindex);
if (nodep->declp()->msbEndianed() || nodep->declp()->lsbEndianed() || emitTraceIsScBv(nodep)) { if (!nodep->isDouble() // When float/double no longer have widths this can go
&& (nodep->declp()->msbEndianed() || nodep->declp()->lsbEndianed() || emitTraceIsScBv(nodep))) {
puts(","+cvtToStr(nodep->declp()->widthMin())); puts(","+cvtToStr(nodep->declp()->widthMin()));
} }
puts(");\n"); puts(");\n");
+1 -1
View File
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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
@@ -8,7 +8,7 @@
// //
//************************************************************************* //*************************************************************************
// //
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can // Copyright 2003-2012 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.

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