Compare commits

..
145 Commits
Author SHA1 Message Date
Wilson Snyder c8e437c45c Version bump 2018-08-22 18:09:06 -04:00
Wilson Snyder 4627716aa4 Remove extra space in generated func call. 2018-08-21 18:14:32 -04:00
Wilson Snyder 847dbbbaf0 Fix function inlining inside certain while loops, bug1330. 2018-08-21 18:09:40 -04:00
Wilson Snyder d90064eaee Change MODDUP errors to warnings, msg2588. 2018-07-23 18:57:34 -04:00
Wilson Snyder 8e646bc55f configure: Add URL 2018-07-22 19:44:03 -04:00
Wilson Snyder 3a777c2a37 Verilated: Always define VL_RDTSC, though unused; useful for benchmarking. 2018-07-22 11:53:35 -04:00
Wilson Snyder 237f4806bf Fix doxygen old dir refs. 2018-07-20 19:45:58 -04:00
Wilson Snyder dfe66a2b77 Fix whitespace after functions in generated files. 2018-07-18 22:42:05 -04:00
Wilson Snyder a0b09b6450 Remove tabs inside generated files/quotes. 2018-07-18 21:25:21 -04:00
Wilson Snyder 9e3a88c41d Inability to write a file is typically user, not internal error. 2018-07-14 19:22:50 -04:00
John Coiner 736bf75a50 tests: Allow cmdline args to override test args. 2018-07-05 18:52:25 -04:00
Wilson Snyder 129610821f Ignore automake flags passed by Ubuntu builds 2018-07-03 21:34:50 -04:00
Wilson Snyder 4cd0310516 Update error, bug1322. 2018-07-02 09:11:20 -04:00
Wilson Snyder 4f962bddd8 Fix std:: build error, bug1322. 2018-06-28 18:55:36 -04:00
Wilson Snyder 45eddfb335 Warn if using pre-C++11 so find out who needs it. 2018-06-26 07:33:55 -04:00
Wilson Snyder d4b9b5aba6 Fix to ignore Unicode UTF-8 BOM sequences, msg2576. 2018-06-26 07:11:56 -04:00
Wilson Snyder b1bf742544 Internals: rank() public for future optimizers. 2018-06-24 18:47:08 -04:00
Wilson Snyder cdd70ff8fc Commentary 2018-06-24 08:08:34 -04:00
Wilson Snyder 2b56acb39a Add git_untabify utility 2018-06-22 07:09:21 -04:00
Wilson Snyder 35a40b4930 Commentary 2018-06-22 06:35:27 -04:00
Wilson Snyder ae33a1ceb1 Tests: Add t_gate_tree test 2018-06-21 20:27:33 -04:00
Wilson Snyder d225e46e4a Fix define argument stringification, broke since 3.914. 2018-06-21 08:19:59 -04:00
John Coiner 43d07235c9 Tests: Fix sc_main compilation errors.
Signed-off-by: Wilson Snyder <[email protected]>
2018-06-20 19:01:19 -04:00
Wilson Snyder 047a08c999 Internals: Clean some UASSERTs. No functional change. 2018-06-16 18:00:21 -04:00
Wilson Snyder 1d74657bbb Internals: Remove dead code 2018-06-16 17:59:57 -04:00
Wilson Snyder 65bb93a6c5 Add OBJCACHE envvar support to examples and generated Makefiles. 2018-06-15 07:13:18 -04:00
Wilson Snyder 6e7f28785e Internals: Cleanup graph includes. No functional change. 2018-06-15 06:54:03 -04:00
Wilson Snyder 0eb1d0a84e Fix cppcheck warnings. No functional change intended. 2018-06-14 18:59:24 -04:00
Wilson Snyder 5d26bca55c Internals: Remove unneeded returns on asserts. 2018-06-13 18:05:00 -04:00
Wilson Snyder a15e6f68dd devel release 2018-06-12 21:22:01 -04:00
Wilson Snyder 77e7e2bf1c Version bump 2018-06-12 21:20:12 -04:00
Wilson Snyder 1c5c9e2435 cppcheck fixes 2018-06-12 21:14:20 -04:00
James Hutchinson f0ed4346b2 Fix to be in verilog 2005, bug1319.
Signed-off-by: Wilson Snyder <[email protected]>
2018-06-08 08:01:22 -04:00
John Coiner 94c8064798 Fix linear search; this is part of the fix for issue 1316. 2018-06-07 12:43:19 -04:00
Wilson Snyder cf0464c263 Internals: Cleanup V3EmitC common code. No functional change. From threads branch. 2018-05-29 19:55:42 -04:00
Wilson Snyder 6268db643c Commentary 2018-05-25 07:17:38 -04:00
Wilson Snyder fd98d231e4 Tests: Fix determinism of randomization. 2018-05-25 07:15:29 -04:00
Wilson Snyder 92649ba494 includes: Fix VL_RDTSC & misc stuff. 2018-05-24 22:17:44 -04:00
Wilson Snyder 0efe343494 Renamed --profile-cfuncs to --prof-cfuncs. 2018-05-20 09:12:29 -04:00
Wilson Snyder 84335b9580 Verilated: Cleanup command line parsing. Backport from pending v4 change. 2018-05-20 08:36:39 -04:00
Wilson Snyder e8b2c57610 Commentary 2018-05-19 14:50:28 -04:00
Wilson Snyder 5e22ca77ec Tests: Fix misc multithreaded issues, merge from threads branch. 2018-05-19 09:30:54 -04:00
Wilson Snyder b6e8133a4d When tracing, use scalars on single bit arrays to appease vcddiff. 2018-05-19 07:52:07 -04:00
Wilson Snyder 02a22c12ea Internals: Add missing [] to delete call in verilated_vcd_c.cpp, bug1309 2018-05-17 07:08:11 -04:00
Wilson Snyder fe917ba7f4 include: Merge misc thread runtime support. 2018-05-13 19:30:51 -04:00
Wilson Snyder 2c568603f6 Fix latex warning & misc Commentary 2018-05-13 19:21:08 -04:00
Wilson Snyder 51422e3ee8 Fix parsing error on bad missing #, bug1308. 2018-05-09 18:32:12 -04:00
Wilson Snyder 0ef3c10931 Pull some thread include changes from thread branch. 2018-05-08 21:43:32 -04:00
Wilson Snyder 35be80f789 Tests: Use vlt_all for any Verilator test. 2018-05-08 19:39:32 -04:00
Wilson Snyder c29e7619eb Tests: Support multiple scenario testing. 2018-05-07 20:42:28 -04:00
Wilson Snyder a265417727 Tests: Cleanup Perl indentations. No functional change. 2018-05-06 22:39:18 -04:00
Wilson Snyder b69af164f7 Commentary 2018-05-06 20:40:23 -04:00
Wilson Snyder ff61bb509c Tests: Fix race and dead code. 2018-05-05 07:44:52 -04:00
Wilson Snyder c8ba51581f Commentary 2018-04-30 20:34:52 -04:00
Wilson Snyder 29f1a9208e Commentary 2018-04-30 20:00:38 -04:00
Wilson Snyder 8b954dc381 Additional debug prints 2018-04-12 22:00:34 -04:00
John Coiner 767ac2547d Misc clang warning fixes.
Signed-off-by: Wilson Snyder <[email protected]>
2018-04-10 22:05:55 -04:00
Wilson Snyder a46aa2d62b Fix verilator_profcfunc on old gprofs. 2018-04-10 22:05:17 -04:00
Todd Strader 9219ddaece Report interface ports connected to wrong interface, bug1294. 2018-04-04 21:03:43 -04:00
Wilson Snyder c7c99d8553 Fix parsing "output signed" in V2K port list, msg2540. 2018-03-29 20:10:27 -04:00
Wilson Snyder e3354a0191 devel release 2018-03-17 12:01:59 -04:00
Wilson Snyder df3d1a4da9 Version bump 2018-03-17 11:56:37 -04:00
Wilson Snyder 3963fe4384 Fix GCC-8 compile error. 2018-03-17 11:33:47 -04:00
Wilson Snyder 38261ac649 Tests: Ignore history file. 2018-03-17 09:25:38 -04:00
Wilson Snyder e49539fb4c Internals: Put cell assigns near cell. No functional change intended except statement order. 2018-03-17 08:43:19 -04:00
Wilson Snyder 3cd96cf558 Tests: Print error line in summary file. 2018-03-16 19:54:25 -04:00
Wilson Snyder 1bcaaa0f0d Internals: Cleanup V3Inst unused argument. No functional change intended. 2018-03-15 23:19:43 -04:00
Wilson Snyder 7922a1de28 Internals: Misc cleanups related to V3LinkDot. No functional change intended. 2018-03-15 19:46:05 -04:00
John Coiner e897c862f2 Tests: t_foreach now checks that all foreach loops get unrolled and evaluated statically. 2018-03-15 19:06:32 -04:00
John Coiner f55040a38b Fix severe runtime performance bug in certain foreach loops. 2018-03-15 08:59:52 -04:00
Wilson Snyder 2d580e6939 Support IEEE 1800-2017 as default language. 2018-03-12 22:26:34 -04:00
John Coiner fc48008c1c Support 2018-03-12 16:44:01 -04:00
Wilson Snyder 4cf2e4024f verilator_difftree: Better error. 2018-03-11 16:49:40 -04:00
Wilson Snyder 57c7d77af3 Tests: Future reduction or test. 2018-03-11 16:33:38 -04:00
Wilson Snyder c8cf2afb15 Support assert properties, bug785, bug1290. 2018-03-11 10:37:20 -04:00
Wilson Snyder 770045676f Internals: Split some extremely long lines. No functional change. 2018-03-10 16:32:04 -05:00
Wilson Snyder 68cca0e114 Commentary, bug1288 2018-03-10 14:16:37 -05:00
Wilson Snyder 0a1b775ed6 Fix various small node leaks. 2018-03-10 14:10:41 -05:00
Wilson Snyder 54a101acbe Internals: Fix -DLEAK_CHECKS failing due to visitor destructor being too late. 2018-03-10 12:57:50 -05:00
John Coiner db1af07d72 On convergence errors, show activity. 2018-03-10 12:52:11 -05:00
John Coiner ff82f75023 Add --no-debug-leak to reduce memory use under debug. 2018-03-10 12:18:19 -05:00
Wilson Snyder 9ae54786e4 Commentary, bug1288. 2018-03-09 00:04:00 -05:00
Wilson Snyder 22ff760f0b Support calling system functions as tasks, bug1285. 2018-03-08 23:40:19 -05:00
John Coiner 86fe6ac3a8 Fix quoting of quoted arguments.
Signed-off-by: Wilson Snyder <[email protected]>
2018-03-08 22:43:29 -05:00
Tymoteusz Blazejczyk 9f52e23158 Fix verilator_coverage --annotate-min, bug1284. 2018-03-07 19:52:29 -05:00
Wilson Snyder e1410775fb Fix CC warning with flex 2.5.35. 2018-02-28 06:34:03 -05:00
John Coiner a7a790416e Internals: Fix passing bool as int. No functional change.
Signed-off-by: Wilson Snyder <[email protected]>
2018-02-27 07:16:16 -05:00
Patrick Stewart fe5c4df079 Support trig functions (() etc), bug1281.
Signed-off-by: Wilson Snyder <[email protected]>
2018-02-26 04:25:07 -05:00
Wilson Snyder 1376e5de92 Fix pullup/pulldowns on bit selects, bug1274. 2018-02-10 19:08:07 -05:00
Wilson Snyder 7f5b1a402c Internals: Part of last change, spacing. 2018-02-07 20:29:58 -05:00
Wilson Snyder 22573d238b Internals: Fix GCC8 cppcheck warnings. No functional change. 2018-02-07 20:16:53 -05:00
Wilson Snyder 32859d9fc2 Fix GCC 8.0 issues 2018-02-07 18:58:21 -05:00
Wilson Snyder 1b12800b8f devel release 2018-02-01 20:14:40 -05:00
Wilson Snyder 13d11b037a Version bump 2018-02-01 20:09:58 -05:00
Wilson Snyder 0ca0854cac Fix compile error with --public and interface bind, bug1264. 2018-02-01 20:07:46 -05:00
Wilson Snyder 1726c71649 Commentary 2018-02-01 19:20:08 -05:00
Wilson Snyder fd8c29f981 Commentary 2018-02-01 19:18:00 -05:00
Wilson Snyder e07ee559a0 Tests: Fix gcc7.2 warnings. 2018-01-31 19:27:42 -05:00
Wilson Snyder 097107bd0b Support 'assume' similar to 'assert', bug1269. 2018-01-31 07:33:10 -05:00
Wilson Snyder b40b152b87 Fix missing edge type in xml output, msg2480. 2018-01-31 07:29:14 -05:00
Wilson Snyder 3c7fef68c0 Internals: Sort EmitXml visitors. No functional change. 2018-01-31 07:25:10 -05:00
Wilson Snyder b2322ae873 Fix tracing example file output, bug1268. 2018-01-29 19:07:49 -05:00
Wilson Snyder e3f137875b Fix spacing of trace func decls. No functional change. 2018-01-29 19:04:37 -05:00
Wilson Snyder 71fcf45d73 Fix gate optimization out of memory, add --gate-stmts, bug1260. 2018-01-27 15:06:51 -05:00
Wilson Snyder 652b68a5a0 Fix compile error on public real parameters by suppressing, bug1261. 2018-01-24 22:30:30 -05:00
John Coiner 3e0401de1c Misc harmless cleanups from thread branch.
Signed-off-by: Wilson Snyder <[email protected]>
2018-01-24 20:20:26 -05:00
Stefan Wallentowitz c164024f38 Remove c++filt and fix status code of Makefile, bug1265
In the generated Makefile the linker output is piped through c++filt
which was very useful for older linkers. But unfortunately the status
code is lost during the piping. So when the make process is embedded
in a larger setup a failure will not manifest to the outside flow.

As modern linkers do the job of c++filt, this removes it from the
generated Makefile. It will also produce a proper status code then.

Signed-off-by: Wilson Snyder <[email protected]>
2018-01-18 21:25:43 -05:00
Wilson Snyder bd1f1e8699 Fix compile error on public real parameters by suppressing, bug1261. 2018-01-16 19:53:50 -05:00
Wilson Snyder 7ee6efab74 devel release 2018-01-02 18:13:45 -05:00
Wilson Snyder 3788e90644 Version bump 2018-01-02 18:06:05 -05:00
Wilson Snyder 8e65d93d6d Copyright year update. No functional change. 2018-01-02 18:05:06 -05:00
Wilson Snyder 4901668f13 Add INFINITELOOP warning, bug1254. 2017-12-26 21:35:08 -05:00
Wilson Snyder f98940e40a Fix cppcheck warnings. No functional change. 2017-12-17 18:44:35 -05:00
Wilson Snyder 49fe4d081c Support DPI open arrays, bug909, bug1245. 2017-12-17 16:28:58 -05:00
Wilson Snyder 3054b36a8d Internals: Avoid cleaning arrays in prep for openarrays. 2017-12-17 12:53:22 -05:00
Wilson Snyder b888158907 Fix DPI svGetBitselLogic and svPutPartselLogic. 2017-12-17 12:19:40 -05:00
Tymoteusz Blazejczyk 173f71dca6 Fix SystemC 2.3.2 compile error, bug1251.
Signed-off-by: Wilson Snyder <[email protected]>
2017-12-17 08:23:22 -05:00
Wilson Snyder 37a931feb4 Internals: Refactor some V3Task code in prep for openarrays. No functional change intended. 2017-12-16 15:46:21 -05:00
Wilson Snyder 79f5c7fbda Internals: Split verilated_syms.h and rename some methods. No functional change intended. 2017-12-16 10:52:43 -05:00
Wilson Snyder bf3f111ca4 Internals: Move VLVF flags to common function. No functional change. 2017-12-16 10:07:15 -05:00
Wilson Snyder 9a2a5d3155 Internals: Unroll V3Width task processing, in prep for openarrays. No functional change intended. 2017-12-16 09:36:07 -05:00
Wilson Snyder 2a7c61cd6d Commentary 2017-12-16 09:35:28 -05:00
Wilson Snyder 51787d68b9 Add error if always_comb has sensitivity list. 2017-12-13 19:49:37 -05:00
Wilson Snyder 33eb0db6f8 Fix resolving inline nested interface names, bug1250. 2017-12-13 19:42:49 -05:00
Wilson Snyder a0b2727c59 Use power-of-two number of members to align structs 2017-12-11 19:16:49 -05:00
Wilson Snyder d1b8f53711 Support DPI time and svLogicVal.
Note older version incorrectly assumed svBitVal even for logicals.
2017-12-09 20:17:37 -05:00
Wilson Snyder 27b5bfe9b1 DPI: Implement IEEE DPI copy routines. 2017-12-09 17:05:32 -05:00
Wilson Snyder ea91b10086 Internals: Add charIQWN. Proper capitalization. 2017-12-09 14:44:55 -05:00
Wilson Snyder 08da777b33 Tests: Fix illegal dpi return types, and other cleanups 2017-12-09 14:44:25 -05:00
Wilson Snyder 345657ab32 Workaround GCC/clang bug with huge compile times, bug1248. 2017-12-09 11:52:35 -05:00
Wilson Snyder 1b605ade94 Tests: Fix internal run scripts 2017-12-08 19:40:16 -05:00
Wilson Snyder b11fa372b1 Fix constant propagation across DPI imports of inout strings. 2017-12-07 20:10:27 -05:00
Wilson Snyder 662ebece71 Support string len() method. 2017-12-07 19:57:11 -05:00
Wilson Snyder 6b6e8dc83e Use VL_UNCOPYABLE in emitted code. No functional change intended. 2017-12-06 23:26:27 -05:00
Wilson Snyder d215149c7c Fix false ALWCOMBORDER on interface references, bug1247. 2017-12-06 21:29:10 -05:00
Wilson Snyder 895fc0911a Support > 64 bit decimal $display. 2017-12-02 22:10:58 -05:00
Wilson Snyder 754527edfd verilated internals: Add VL_BITRSHIFT_W. No functional change. 2017-12-02 08:17:20 -05:00
John Coiner f0217edef1 Internals: Keep a ptr to _eval in AstNetlist, make it easier to find.
Signed-off-by: Wilson Snyder <[email protected]>
2017-11-30 18:53:57 -05:00
Wilson Snyder 8f1798cc6f Fix modport outputs being treated as inputs, bug1246. 2017-11-28 19:11:41 -05:00
John Coiner 631bda395d Avoid duplicated scans of CFuncs.
Trace into non-entry-point functions (most of them) at their call
sites. We'll trace into entry-point functions (like eval) from their parent
scope. We must trace eval_ to reach the tree of calls beneath it.

Signed-off-by: Wilson Snyder <[email protected]>
2017-11-28 18:38:19 -05:00
John Coiner 791d02a753 Internals: Remove dead code. No functional change.
Signed-off-by: Wilson Snyder <[email protected]>
2017-11-28 18:29:14 -05:00
Wilson Snyder 54b3f92951 Commentary 2017-11-28 18:21:43 -05:00
Wilson Snyder 45de0599d7 Commentary 2017-11-27 20:11:34 -05:00
John Coiner 331ecdc2e7 Commentary
Signed-off-by: Wilson Snyder <[email protected]>
2017-11-27 19:23:55 -05:00
Wilson Snyder 339a7640a8 devel release 2017-11-27 18:50:14 -05:00
1276 changed files with 21350 additions and 6397 deletions
+1
View File
@@ -23,6 +23,7 @@ dddrun*
doxygen-doc
gdbrun*
gmon.out
ncverilog.history
internals.txt
verilator.txt
verilator_bin*
+109 -2
View File
@@ -2,6 +2,113 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 3.926 2018-08-22
**** Add OBJCACHE envvar support to examples and generated Makefiles.
**** Change MODDUP errors to warnings, msg2588. [Marshal Qiao]
**** Fix define argument stringification (`"), broke since 3.914. [Joe DErrico]
**** Fix to ignore Unicode UTF-8 BOM sequences, msg2576. [HyungKi Jeong]
**** Fix std:: build error, bug1322.
**** Fix function inlining inside certain while loops, bug1330. [Julien Margetts]
* Verilator 3.924 2018-06-12
*** Renamed --profile-cfuncs to --prof-cfuncs.
**** Report interface ports connected to wrong interface, bug1294. [Todd Strader]
**** When tracing, use scalars on single bit arrays to appease vcddiff.
**** Fix parsing "output signed" in V2K port list, msg2540. [James Jung]
**** Fix parsing error on bad missing #, bug1308. [Dan Kirkham]
**** Fix $clog2 to be in verilog 2005, bug1319. [James Hutchinson]
* Verilator 3.922 2018-03-17
** Support IEEE 1800-2017 as default language.
*** Support trig functions ($sin() etc), bug1281. [Patrick Stewart]
*** Support calling system functions as tasks, bug1285. [Joel Holdsworth]
*** Support assert properties, bug785, bug1290. [John Coiner, et al]
*** Support $writememh. [John Coiner]
*** Add --no-debug-leak to reduce memory use under debug. [John Coiner]
**** Fix severe runtime performance bug in certain foreach loops. [John Coiner]
**** On convergence errors, show activity. [John Coiner]
**** Fix GCC 8.0 issues, bug1273.
**** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard]
**** Fix verilator_coverage --annotate-min, bug1284. [Tymoteusz Blazejczyk]
**** Fix quoting of quoted arguments. [John Coiner]
* Verilator 3.920 2018-02-01
** Moving forward, use the git "stable" branch to track the latest release,
and git "v#.###" tags for specific releases.
*** Support 'assume' similar to 'assert', bug1269. [Dan Gisselquist]
**** Fix tracing example file output, bug1268. [Enzo Chi]
**** Fix gate optimization out of memory, add --gate-stmts, bug1260. [Alex Solomatnikov]
**** Fix compile error on public real parameters by suppressing, bug1261. [Alex Solomatnikov]
**** Fix input-only tristate comparisons, bug1267. [Alexis G]
**** Fix missing edge type in xml output, msg2480. [Alexis G]
**** Fix compile error with --public and interface bind, bug1264. [Alexis G]
**** Remove c++filt, bug1265. [Stefan Wallentowitz]
* Verilator 3.918 2018-01-02
*** Workaround GCC/clang bug with huge compile times, bug1248.
*** Support DPI open arrays, bug909, bug1245. [David Pierce, Victor Besyakov]
*** Add INFINITELOOP warning, bug1254. [Alex Solomatnikov]
**** Support > 64 bit decimal $display.
**** Support DPI time and svLogicVal. [Victor Besyakov]
Note older version incorrectly assumed svBitVal even for logicals.
**** Support string len() method. [Victor Besyakov]
**** Add error if always_comb has sensitivity list. [Arjen Roodselaar]
**** Fix SystemC 2.3.2 compile error, bug1251. [Tymoteusz Blazejczyk]
**** Fix modport outputs being treated as inputs, bug1246. [Jeff Bush]
**** Fix false ALWCOMBORDER on interface references, bug1247. [Josh Redford]
**** Fix constant propagation across DPI imports of inout strings. [Victor Besyakov]
**** Fix resolving inline nested interface names, bug1250. [Arjen Roodselaar]
* Verilator 3.916 2017-11-25
*** Support self-recursive modules, bug659. [Sean Moore, et al]
@@ -2106,7 +2213,7 @@ Bug fixes:
* Verilator 3.501 2005/11/16 Stable
*** Add --profile-cfuncs for correlating profiles back to Verilog.
*** Add --prof-cfuncs for correlating profiles back to Verilog.
**** Fixed functions where regs are declared before inputs. [Danny Ding]
@@ -2974,7 +3081,7 @@ of input ports exists for tracing.
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
Copyright 2001-2017 by Wilson Snyder. This program is free software; you
Copyright 2001-2018 by Wilson Snyder. This program is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+4
View File
@@ -16,6 +16,9 @@
/obj_dir/
/obj_dbg/
/obj_opt/
/obj_vlt/
/obj_vltmt/
/obj_dist/
/INCA_libs/
/cov_work/
/logs/
@@ -34,6 +37,7 @@ verilator.pc$
verilator_bin.*
verilator_coverage_bin.*
.vcsmx_rebuild$
ncverilog.history
autom4te\.cache/
nodist/
/simv$
+1 -1
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -11,7 +11,7 @@ This is the Verilator package README file.
http://www.veripool.org/verilator
This package is Copyright 2003-2017 by Wilson Snyder. (Report bugs to
This package is Copyright 2003-2018 by Wilson Snyder. (Report bugs to
L<http://www.veripool.org/>.)
Verilator is free software; you can redistribute it and/or modify it under
+3 -9
View File
@@ -1,6 +1,6 @@
// DESCRIPTION: Verilator: List of To Do issues.
//
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2018 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.
@@ -27,12 +27,10 @@ Long-term Features
* 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.
Testing:
* Move test_c/sp/v/verilated into test_regress format (4.000?)
* Capture all inputs into global "rerun it" file
* Code to make wrapper that sets signals, so can do comparison checks
* New random program generator
@@ -48,20 +46,17 @@ Usability:
* 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-2013.
Verilator 3.600 - The fast free open-sourced simulator. Copyright 2001-2013.
Verilated #### modules, #### instances, ##### sigs,
#### non-comment lines, ##### ops, ### KB model size
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
Lint:
* CDCRSTLOGIC should allow filtering with paths
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
Internal Code:
* Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
and removing it will speed up and simplify all the other code.
* A Visitor class that understands how to traverse data 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)
@@ -114,7 +109,6 @@ Performance:
* Usually blocks/values
Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out
* Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
* Allow Split of case statements without a $display/$stop
* I-cache packing improvements (what/how?)
* Data cache organization (order of vars in class)
First have clocks,
+164 -98
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
######################################################################
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you
# Copyright 2003-2018 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.
@@ -54,18 +54,6 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
# We sneak a look at the flags so we can do some pre-environment checks
# All flags will hit verilator...
foreach my $sw (@ARGV) {
# Some special treatment for parameters to allow verilog literals for numbers
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
# If there is a single quote in the parameter put it double quotes ,
# else just put it in double quotes
if ($sw =~ m![\']!) {
$sw = "\"$sw\"";
} else {
$sw = "'$sw'";
}
} else {
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
}
push @Opt_Verilator_Sw, $sw;
}
@@ -84,16 +72,30 @@ if (! GetOptions (
pod2usage(-exitstatus=>2, -verbose=>0);
}
# Determine runtime flags and run
if ($opt_gdbbt && !gdb_works()) {
warn "-Info: --gdbbt ignored: gdb doesn't seem to be working\n" if $Debug;
$opt_gdbbt = 0;
}
# Determine runtime flags and run
# Opt_Verilator_Sw is what we want verilator to see on its argc/argv.
# Starting with that, escape all special chars for the shell;
# The shell will undo the escapes and the verilator binary should
# then see exactly the contents of @Opt_Verilator_Sw.
my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw;
if ($opt_gdb) {
# Generic GDB interactive
run (("gdb"||$ENV{VERILATOR_GDB})
." ".verilator_bin()
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
# Note, uncomment to set breakpoints before running:
# ." -ex 'break main'"
# Note, we must use double-quotes ("run <switches>")
# and not single ('run <switches>') below. Bash swallows
# escapes as you would expect in a double-quoted string.
# That's not true for a single-quoted string, where \'
# actually terminates the string -- not what we want!
." -ex \"run ".join(' ', @quoted_sw)."\""
." -ex 'set width 0'"
." -ex 'bt'");
} elsif ($opt_gdbbt && $Debug) {
@@ -101,13 +103,12 @@ if ($opt_gdb) {
run ("gdb"
." ".verilator_bin()
." --batch --quiet --return-child-result"
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
." -ex \"run ".join(' ', @quoted_sw)."\""
." -ex 'set width 0'"
." -ex 'bt'");
} else {
# Normal, non gdb
run (verilator_bin()
." ".join(' ',@Opt_Verilator_Sw));
run (verilator_bin()." ".join(' ',@quoted_sw));
}
#----------------------------------------------------------------------
@@ -196,6 +197,16 @@ sub run {
}
}
sub sh_escape {
my ($arg) = @_;
# This is similar to quotemeta() but less aggressive.
# There's no need to escape hyphens, periods, or forward slashes
# for the shell as these have no special meaning to the shell.
$arg =~ s/([^0-9a-zA-Z_\-\.\/])/\\$1/g;
return $arg;
}
#######################################################################
#######################################################################
package main;
@@ -217,8 +228,8 @@ Verilator - Convert Verilog code to C++/SystemC
=head1 DESCRIPTION
Verilator converts synthesizable (not behavioral) Verilog code, plus some
Synthesis, SystemVerilog and a small subset of Verilog AMS assertions, into
Verilator converts synthesizable (generally not behavioral) Verilog code,
plus some Synthesis, SystemVerilog and a small subset of Verilog AMS into
C++ or SystemC code. It is not a complete simulator, but a compiler.
Verilator is invoked with parameters similar to GCC, Cadence
@@ -238,8 +249,8 @@ To get started, jump down to "EXAMPLE C++ EXECUTION".
=head1 ARGUMENT SUMMARY
This is a short summary of the arguments to Verilator. See the detailed
descriptions in the next sections for more information.
This is a short summary of the arguments to Verilator itself. See the
detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
{file.v} Verilog package, module and top module filenames
{file.c/cc/cpp} Optional C++ files to compile in
@@ -251,6 +262,7 @@ descriptions in the next sections for more information.
+1800-2005ext+<ext> Use SystemVerilog 2005 with file extension <ext>
+1800-2009ext+<ext> Use SystemVerilog 2009 with file extension <ext>
+1800-2012ext+<ext> Use SystemVerilog 2012 with file extension <ext>
+1800-2017ext+<ext> Use SystemVerilog 2017 with file extension <ext>
--assert Enable all assertions
--autoflush Flush streams after all $displays
--bbox-sys Blackbox unknown $system calls
@@ -270,6 +282,7 @@ descriptions in the next sections for more information.
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
--no-debug-leak Disable leaking memory in --debug mode
--debugi <level> Enable debugging at a specified level
--debugi-<srcfile> <level> Enable debugging a source file at a level
--default-language <lang> Default language to parse
@@ -289,6 +302,7 @@ descriptions in the next sections for more information.
--getenv <var> Get environment variable with defaults
--help Display this help
-I<dir> Directory to search for includes
--gate-stmts <value> Tune gate optimizer depth
--if-depth <value> Tune IFDEPTH warning
+incdir+<dir> Directory to search for includes
--inhibit-sim Create function to turn off sim
@@ -323,7 +337,7 @@ descriptions in the next sections for more information.
--pins-uint8 Specify types for top level ports
--pipe-filter <command> Filter all input through a script
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--prof-cfuncs Name functions for profiling
--private Debugging; see docs
--public Debugging; see docs
-pvalue+<name>=<value> Overwrite toplevel parameter
@@ -335,7 +349,7 @@ descriptions in the next sections for more information.
--stats Create statistics file
--stats-vars Provide statistics on variables
-sv Enable SystemVerilog parsing
+systemverilogext+<ext> Synonym for +1800-2012ext+<ext>
+systemverilogext+<ext> Synonym for +1800-2017ext+<ext>
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
@@ -352,6 +366,7 @@ descriptions in the next sections for more information.
-v <filename> Verilog library
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
--version Displays program version and exits
--vpi Enable VPI compiles
-Wall Enable all style warnings
-Werror-<message> Convert warnings to errors
@@ -366,7 +381,9 @@ descriptions in the next sections for more information.
-y <dir> Directory to search for modules
=head1 ARGUMENTS
=head1 VERILATION ARGUMENTS
The following are the arguments that may be passed to Verilator itself.
=over 4
@@ -402,6 +419,8 @@ with the --exe option.
=item +1800-2012ext+I<ext>
=item +1800-2017ext+I<ext>
Specifies the language standard to be used with a specific filename
extension, I<ext>.
@@ -433,7 +452,7 @@ Enable all assertions.
=item --autoflush
After every $display or $fdisplay, flush the output stream. This insures
After every $display or $fdisplay, flush the output stream. This ensures
that messages will appear immediately but may reduce performance; for best
performance call "fflush(stdout)" occasionally in the main C loop.
Defaults off, which will buffer output as provided by the normal C stdio
@@ -529,7 +548,7 @@ functions to avoid error C1061.
=back
=item --converge-limit <loops>
=item --converge-limit I<loops>
Rarely needed. Specifies the maximum number of runtime iterations before
creating a model failed to converge error. Defaults to 100.
@@ -626,9 +645,21 @@ to C<--dump-treei 3>).
Rarely needed. Enable internal debugging assertion checks, without
changing debug verbosity. Enabled automatically when --debug specified.
=item --debugi <level>
=item --no-debug-leak
=item --debugi-<srcfile> <level>
In --debug mode, by default Verilator intentionally leaks AstNode's
instead of freeing them, so that each node pointer is unique in the
resulting tree files and dot files.
This option disables the leak. This may avoid out-of-memory errors
when Verilating large models in --debug mode.
Outside of --debug mode, AstNode's should never be leaked and this option
has no effect.
=item --debugi I<level>
=item --debugi-I<srcfile> I<level>
Rarely needed - for developer use. Set internal debugging level globally
to the specified debug level (1-10) or set the specified Verilator source
@@ -639,7 +670,7 @@ produce more detailed messages.
Select the language to be used by default when first processing each
Verilog file. The language value must be "1364-1995", "1364-2001",
"1364-2005", "1800-2005", "1800-2009" or "1800-2012".
"1364-2005", "1800-2005", "1800-2009", "1800-2012" or "1800-2017".
Any language associated with a particular file extension (see the various
+I<lang>ext+ options) will be used in preference to the language specified
@@ -652,7 +683,7 @@ legacy mixed language designs, the various +I<lang>ext+ options should be
used.
If no language is specified, either by this flag or +I<lang>ext+ options,
then the latest SystemVerilog language (IEEE 1800-2012) is used.
then the latest SystemVerilog language (IEEE 1800-2017) is used.
=item +define+I<var>=I<value>
@@ -670,9 +701,9 @@ the Verilator Internals manual. --dump-tree is enabled automatically with
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
large and not desired.
=item --dump-treei <level>
=item --dump-treei I<level>
=item --dump-treei-<srcfile> <level>
=item --dump-treei-I<srcfile> I<level>
Rarely needed - for developer use. Set internal tree dumping level
globally to a specific dumping level or set the specified Verilator source
@@ -686,7 +717,7 @@ Preprocess the source code, but do not compile, as with 'gcc -E'. Output
is written to standard out. Beware of enabling debugging messages, as they
will also go to standard out.
=item --error-limit <value>
=item --error-limit I<value>
After this number of errors or warnings are encountered, exit. Defaults to
50.
@@ -713,7 +744,7 @@ The file may contain // comments which are ignored to the end of the line.
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
variable.
=item -FI <file>
=item -FI I<file>
Force include of the specified C++ header file. All generated C++ files
will insert a #include of the specified file before any other includes. The
@@ -745,11 +776,16 @@ Double literals must contain a dot (.) and/or an exponent (e).
=item Strings
String must in double quotes ("). On the command line it is required to escape
String must in double quotes (""). On the command line it is required to escape
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
=back
=item --gate-stmts I<value>
Rarely needed. Set the maximum number of statements that may be present in
an equation for the gate substitution optimization to inline that equation.
=item --gdb
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
@@ -866,7 +902,7 @@ otherwise manually create the Mdir before calling Verilator.
Specifies the name to prepend to all lower level classes. Defaults to
the same as --prefix.
=item --no-clk <signal-name>
=item --no-clk I<signal-name>
Prevent the specified signal from being marked as clock. See C<--clk>.
@@ -925,7 +961,7 @@ disables an optimization, an upper case letter enables it. This is
intended for debugging use only; see the source code for version-dependent
mappings of optimizations to -O letters.
=item -o <executable>
=item -o I<executable>
Specify the name for the final executable built if using --exe. Defaults
to the --prefix if not specified.
@@ -1024,7 +1060,7 @@ Specifies the name of the top level class and makefile. Defaults to V
prepended to the name of the --top-module switch, or V prepended to the
first Verilog filename passed on the command line.
=item --profile-cfuncs
=item --prof-cfuncs
Modify the created C++ functions to support profiling. The functions will
be minimized to contain one "basic" statement, generally a single always
@@ -1032,7 +1068,7 @@ block or wire statement. (Note this will slow down the executable by ~5%.)
Furthermore, the function name will be suffixed with the basename of the
Verilog module and line number the statement came from. This allows gprof
or oprofile reports to be correlated with the original Verilog source
statements.
statements. See also L<verilator_profcfunc>.
=item --private
@@ -1113,7 +1149,7 @@ Creates a dump file with statistics on the design in {prefix}__stats.txt.
=item --stats-vars
Creates more detailed statistics including a list of all the variables by
Creates more detailed statistics, including a list of all the variables by
size (plain --stats just gives a count). See --stats, which is implied by
this.
@@ -1125,7 +1161,7 @@ compatibility with other simulators.
=item +systemverilogext+I<ext>
A synonym for C<+1800-2012ext+>I<ext>.
A synonym for C<+1800-2017ext+>I<ext>.
=item --top-module I<topname>
@@ -1140,8 +1176,8 @@ Adds waveform tracing code to the model. Verilator will generate
additional {prefix}__Trace*.cpp files that will need to be compiled. In
addition verilated_vcd_sc.cpp (for SystemC traces) or verilated_vcd_c.cpp
(for both) must be compiled and linked in. If using the Verilator
generated Makefiles, these will be added as source targets for you. If
you're not using the Verilator makefiles, you will need to add these to
generated Makefiles, these files will be added as source targets for you.
If you're not using the Verilator makefiles, you will need to add these to
your Makefile manually.
Having tracing compiled in may result in some small performance losses,
@@ -1219,6 +1255,10 @@ Note -v is fairly standard across Verilog tools.
Synonyms for C<+1364-1995ext+>I<ext> and C<+1364-2001ext+>I<ext> respectively
=item --version
Displays program version and exits.
=item --vpi
Enable use of VPI and linking against the verilated_vpi.cpp files.
@@ -1245,8 +1285,9 @@ supports which the older version does not support.
=item -Wno-I<message>
Disable the specified warning message. This will override any lint_on
directives in the source, i.e. the warning will still not be printed.
Disable the specified warning message, or in some cases where noted here
disable an error. This will override any lint_on directives in the source,
i.e. the warning will still not be printed.
=item -Wno-lint
@@ -1337,7 +1378,7 @@ not otherwise initialized.
--x-initial=unique, the default, initializes variables using a function,
which determines the value to use each initialization. This gives greatest
flexibility and allows finding reset bugs. See L</"Unknown states">
flexibility and allows finding reset bugs. See L</"Unknown states">.
--x-initial=fast, is best for performance, and initializes all variables to
a state Verilator determines is optimal. This may allow further code
@@ -1569,7 +1610,7 @@ fast path, mostly code that is executed every cycle. OPT_SLOW specifies
optimizations for slow-path files (plus tracing), which execute only
rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
OPT_FAST and OPT_SLOW control. For best results, use OPT="-O2", and link
with "-static". Nearly the same results can be had with much better
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
such as "-O3" may help, but gcc compile times may be excessive under O3 on
@@ -1598,7 +1639,7 @@ code with -DVL_INLINE_OPT=inline. This will inline functions, however this
requires that all cpp files be compiled in a single compiler run.
You may uncover further tuning possibilities by profiling the Verilog code.
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
Use Verilator's --prof-cfuncs, then GCC's -g -pg. You can then run
either oprofile or gprof to see where in the C++ code the time is spent.
Run the gprof output through verilator_profcfunc and it will tell you what
Verilog line numbers on which most of the time is being spent.
@@ -1666,8 +1707,8 @@ needed at runtime.
Optionally specifies a caching or distribution program to place in front of
all runs of the C++ Compiler. For example, "objcache --read --write", or
"ccache". If using distcc, it would generally be run under either objcache
or ccache; see the documentation for those programs.
"ccache". If using distcc or icecc/icecream, they would generally be run
under either objcache or ccache; see the documentation for those programs.
=item SYSTEMC
@@ -2188,6 +2229,11 @@ Verilator currently has some support for SystemVerilog synthesis
constructs. As SystemVerilog features enter common usage they are added;
please file a bug if a feature you need is missing.
=head2 SystemVerilog 2017 (IEEE 1800-2017) Support
Verilator supports the 2017 "for" loop constructs, and several minor
cleanups made in 1800-2017.
=head2 Verilog AMS Support
Verilator implements a very small subset of Verilog AMS (Verilog Analog and
@@ -3041,13 +3087,15 @@ Simply use a different register for the flop:
always @* foo[0] = foo_flopped[0];
always @* foo[1] = ...
It is also possible to disable this error when one of the assignments is
inside a public task.
This is not illegal in SystemVerilog, but a violation of good coding
practice. Verilator reports this as an error, because ignoring this warning
may make Verilator simulations differ from other simulators.
It is generally safe to disable this error (with a "// verilator lint_off
BLKANDNBLK" metacomment or the -Wno-BLKANDNBLK option) when one of the
assignments is inside a public task, or when the blocked and non-blocking
assignments have non-overlapping bits and structure members.
=item BLKSEQ
This indicates that a blocking assignment (=) is used in a sequential
@@ -3275,6 +3323,18 @@ command line to specify the top include source directories.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item INFINITELOOP
Warns that a while or for statement has a condition that is always true.
and thus result in an infinite loop if the statement ever executes.
This might be unintended behavior if the loop body contains statements that
in other statements that would make time pass, which Verilator is ignoring
due to e.g. STMTDLY warnings being disabled.
Ignoring this warning will only suppress the lint check, it will simulate
correctly (i.e. hang due to the infinite loop).
=item INITIALDLY
Warns that you have a delayed assignment inside of an initial or final
@@ -3301,10 +3361,14 @@ correctly.
=item MODDUP
Error that a module has multiple definitions. Generally this indicates a
Warns that a module has multiple definitions. Generally this indicates a
coding error, or a mistake in a library file and it's good practice to have
one module per file to avoid these issues. For some gate level netlists
duplicates are unavoidable, and this error may be disabled.
one module per file (and only put each file once on the command line) to
avoid these issues. For some gate level netlists duplicates are sometimes
unavoidable, and MODDUP should be disabled.
Ignoring this warning will cause the more recent module definition to be
discarded.
=item MULTIDRIVEN
@@ -3651,7 +3715,7 @@ For example:
will toggle forever and thus the executable will give the didn't converge
error to prevent an infinite loop.
To debug this, run Verilator with --profile-cfuncs. Run make on the
To debug this, run Verilator with --prof-cfuncs. Run make on the
generated files with "OPT=-DVL_DEBUG". Then call Verilated::debug(1) in
your main.cpp.
@@ -4087,7 +4151,7 @@ When possible, please instead report bugs to L<http://www.veripool.org/>.
Wilson Snyder <[email protected]>
Major concepts by Paul Wasson, Duane Galbi and Jie Xu.
Major concepts by Paul Wasson, Duane Galbi, John Coiner and Jie Xu.
=head1 CONTRIBUTORS
@@ -4111,50 +4175,52 @@ Some of the people who have provided ideas and feedback for Verilator
include: Ahmed El-Mahmoudy, David Addison, Tariq B. Ahmad, Nikana
Anastasiadis, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad
Bagri, Andrew Bardsley, Matthew Barr, Geoff Barrett, Julius Baxter, Jeremy
Bennett, Michael Berman, David Binderman, Johan Bjork, David Black, Daniel
Bone, Gregg Bouchard, Christopher Boumenot, Nick Bowler, Byron Bradley,
Bryan Brady, Charlie Brej, J Briquet, Lane Brooks, John Brownlee, Jeff
Bush, Lawrence Butcher, Ted Campbell, Chris Candler, Lauren Carlson, Donal
Casey, Terry Chen, Enzo Chi, Robert A. Clark, Allan Cochrane, John Coiner,
Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, John Demme, Mike Denio,
John Deroo, Philip Derrick, John Dickol, Ruben Diez, Danny Ding, Ivan
Djordjevic, Jonathon Donaldson, Sebastian Dressler, Alex Duller, Jeff
Dutton, Usuario Eda, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert
Bennett, Michael Berman, Victor Besyakov, David Binderman, Johan Bjork,
David Black, Tymoteusz Blazejczyk, Daniel Bone, Gregg Bouchard, Christopher
Boumenot, Nick Bowler, Byron Bradley, Bryan Brady, Charlie Brej, J Briquet,
Lane Brooks, John Brownlee, Jeff Bush, Lawrence Butcher, Ted Campbell,
Chris Candler, Lauren Carlson, Donal Casey, Terry Chen, Enzo Chi, Robert
A. Clark, Allan Cochrane, John Coiner, Laurens van Dam, Gunter Dannoritzer,
Ashutosh Das, Bernard Deadman, John Demme, Mike Denio, John Deroo, Philip
Derrick, Joe DErrico, John Dickol, Ruben Diez, Danny Ding, Ivan Djordjevic,
Jonathon Donaldson, Sebastian Dressler, Alex Duller, Jeff Dutton, Usuario
Eda, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Trevor Elbourne, Robert
Farrell, Eugen Fekete, Fabrizio Ferrandi, Brian Flachs, Andrea Foletto, Bob
Fredieu, Christian Gelinek, Glen Gibb, Shankar Giri, Dan Gisselquist, Sam
Gladstone, Amir Gonnen, Chitlesh Goorah, Xuan Guo, Neil Hamilton, Jannis
Harder, Junji Hashimoto, Thomas Hawkins, Robert Henry, David Hewson, Jamey
Hicks, Hiroki Honda, Alex Hornung, David Horton, Jae Hossell, Alan Hunter,
Jamie Iles, Ben Jackson, Shareef Jalloq, Krzysztof Jankowski, HyungKi
Jeong, Iztok Jeras, James Johnson, Christophe Joly, Franck Jullien, Mike
Kagen, Arthur Kahlich, Kaalia Kahn, Guy-Armand Kamendje, Vasu Kandadi,
Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Olof
Kindgren, Sobhan Klnv, Gernot Koch, Soon Koh, Steve Kolecki, Brett Koonce,
Wojciech Koszek, Varun Koyyalagunta, David Kravitz, Roland Kruse, Sergey
Kvachonok, Ed Lander, Steve Lang, Stephane Laurent, Walter Lavino,
Christian Leber, Igor Lesik, John Li, Eivind Liland, Charlie Lind, Andrew
Ling, Paul Liu, Derek Lockhart, Arthur Low, Stefan Ludwig, Dan Lussier,
Fred Ma, Duraid Madina, Mark Marshall, Alfonso Martinez, Yves Mathieu,
Patrick Maupin, Jason McMullan, Elliot Mednick, Wim Michiels, Miodrag
Milanovic, Wai Sum Mong, Sean Moore, Dennis Muhlestein, John Murphy,
Richard Myers, Dimitris Nalbantis, Bob Newgard, Cong Van Nguyen, Paul
Nitza, Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, James
Pallister, Brad Parker, Maciej Piechotka, David Pierce, Dominic Plunkett,
David Poole, Mike Popoloski, Rich Porter, Niranjan Prabhu, Usha
Priyadharshini, Mark Jackson Pulver, Prateek Puri, Chris Randall, Anton
Rapp, Odd Magne Reitan, Frederic Requin, Alberto Del Rio, Oleg Rodionov,
Paul Rolfe, Jan Egil Ruud, John Sanguinetti, Galen Seitz, Salman Sheikh,
Hicks, Joel Holdsworth, Hiroki Honda, Alex Hornung, David Horton, Jae
Hossell, Alan Hunter, James Hutchinson, Jamie Iles, Ben Jackson, Shareef
Jalloq, Krzysztof Jankowski, HyungKi Jeong, Iztok Jeras, James Johnson,
Christophe Joly, Franck Jullien, James Jung, Mike Kagen, Arthur Kahlich,
Kaalia Kahn, Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf
Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Olof Kindgren, Dan Kirkham,
Sobhan Klnv, Gernot Koch, Soon Koh, Steve Kolecki, Brett Koonce, Wojciech
Koszek, Varun Koyyalagunta, David Kravitz, Roland Kruse, Sergey Kvachonok,
Ed Lander, Steve Lang, Stephane Laurent, Walter Lavino, Christian Leber,
Igor Lesik, John Li, Eivind Liland, Charlie Lind, Andrew Ling, Paul Liu,
Derek Lockhart, Arthur Low, Stefan Ludwig, Dan Lussier, Fred Ma, Duraid
Madina, Mark Marshall, Alfonso Martinez, Yves Mathieu, Patrick Maupin,
Jason McMullan, Elliot Mednick, Wim Michiels, Miodrag Milanovic, Wai Sum
Mong, Sean Moore, Dennis Muhlestein, John Murphy, Richard Myers, Dimitris
Nalbantis, Bob Newgard, Cong Van Nguyen, Paul Nitza, Pete Nixon, Lisa
Noack, Mark Nodine, Andreas Olofsson, James Pallister, Brad Parker, Maciej
Piechotka, David Pierce, Dominic Plunkett, David Poole, Mike Popoloski,
Rich Porter, Niranjan Prabhu, Usha Priyadharshini, Mark Jackson Pulver,
Prateek Puri, Chris Randall, Anton Rapp, Josh Redford, Odd Magne Reitan,
Frederic Requin, Alberto Del Rio, Oleg Rodionov, Paul Rolfe, Arjen
Roodselaar, Jan Egil Ruud, John Sanguinetti, Galen Seitz, Salman Sheikh,
Mike Shinkarovsky, Rafael Shirakawa, Jeffrey Short, Rodney Sinclair, Steven
Slatter, Brian Small, Alex Solomatnikov, Wei Song, Art Stamness, John
Stevenson, Rob Stoddard, Todd Strader, John Stroebel, Sven Stucki, Emerson
Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu Takatsukasa, Peter
Tengstrand, Wesley Terpstra, Stefan Thiede, Gary Thomas, Kevin Thompson,
Ian Thompson, Mike Thyer, Hans Tichelaar, Steve Tong, Michael Tresidder,
Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters, Thomas
Watts, Eugene Weber, David Welch, Thomas J Whatson, Leon Wildman, Gerald
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Clifford Wolf, Johan
Wouters, Ding Xiaoliang, Jie Xu, Mandy Xu, Luke Yang, and Amir
Yazdanbakhsh.
Stevenson, Patrick Stewart, Rob Stoddard, Todd Strader, John Stroebel, Sven
Stucki, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu
Takatsukasa, Peter Tengstrand, Wesley Terpstra, Rui Terra, Stefan Thiede,
Gary Thomas, Kevin Thompson, Ian Thompson, Mike Thyer, Hans Tichelaar,
Steve Tong, Michael Tresidder, Holger Waechtler, Stefan Wallentowitz, Shawn
Wang, Greg Waters, Thomas Watts, Eugene Weber, David Welch, Thomas J
Whatson, Leon Wildman, Gerald Williams, Trevor Williams, Jeff Winston,
Joshua Wise, Clifford Wolf, Johan Wouters, Junyi Xi, Ding Xiaoliang, Jie
Xu, Mandy Xu, Luke Yang, and Amir Yazdanbakhsh.
Thanks to them, and all those we've missed including above.
@@ -4163,7 +4229,7 @@ Thanks to them, and all those we've missed including above.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2003-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0.
+2 -2
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
######################################################################
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -271,7 +271,7 @@ Specifies a module search directory.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2003-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify the Verilator internals under the terms of
either the GNU Lesser General Public License Version 3 or the Perl Artistic
License Version 2.0.
+3 -2
View File
@@ -85,7 +85,8 @@ sub diff_dir {
diff_file($a,$b);
$any = 1;
}
$any or warn "%Warning: No .tree files found\n";
$any or warn ("%Warning: No .tree files found that have similar base names:\n "
.join("\n ", sort keys %files),"\n");
}
sub diff_file {
@@ -235,7 +236,7 @@ Do not show differences in line numbering.
The latest version is available from L<http://www.veripool.org/verilator>.
Copyright 2005-2017 by Wilson Snyder. This package is free software; you can
Copyright 2005-2018 by Wilson Snyder. This package is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
# DESCRIPTION: Print include statements for each ARGV
#
# Copyright 2003-2017 by Wilson Snyder. This package is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This package is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
######################################################################
+12 -4
View File
@@ -73,6 +73,14 @@ sub profcfunc {
$funcs{$func}{sec} += $sec;
$funcs{$func}{calls} += $calls;
}
# Older gprofs have no call column for single-call functions
# %time cumesec selfsec {stuff} name
elsif ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
my $pct=$1; my $sec=$2; my $calls=1; my $func=$3;
$funcs{$func}{pct} += $pct;
$funcs{$func}{sec} += $sec;
$funcs{$func}{calls} += $calls;
}
}
$fh->close;
@@ -191,11 +199,11 @@ __END__
=head1 NAME
verilator_profcfunc - Read gprof report created with --profile-cfuncs
verilator_profcfunc - Read gprof report created with --prof-cfuncs
=head1 SYNOPSIS
verilator --profile-cfuncs ....
verilator --prof-cfuncs ....
gcc --ggdb -pg ....
{run executable}
gprof
@@ -205,7 +213,7 @@ verilator_profcfunc - Read gprof report created with --profile-cfuncs
Verilator_profcfunc reads a profile report created by gprof. The names of
the functions are then transformed, assuming the user used verilator's
--profile-cfuncs, and a report printed showing the percentage of time, etc,
--prof-cfuncs, and a report printed showing the percentage of time, etc,
in each Verilog block.
=head1 ARGUMENTS
@@ -222,7 +230,7 @@ Displays this message and program version and exits.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2007-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2007-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+48 -2
View File
@@ -1,12 +1,13 @@
# DESCRIPTION: Process this file with autoconf to produce a configure script.
#
# Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
# Copyright 2003-2018 by Wilson Snyder. Verilator is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.916 2017-11-25])
AC_INIT([Verilator],[3.926 2018-08-22],[https://www.veripool.org/verilator],
[verilator],[https://www.veripool.org/verilator])
# When releasing, also update header of Changes file
# and commit using "devel release" or "Version bump" message
@@ -15,6 +16,14 @@ AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk incl
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
# Ignore automake flags passed by Ubuntu builds
AC_ARG_ENABLE([dependency-tracking],
[AS_HELP_STRING([--disable-dependency-tracking], [ignored])])
AC_ARG_ENABLE([maintainer-mode],
[AS_HELP_STRING([--enable-maintainer-mode], [ignored])])
AC_ARG_ENABLE([silent-rules],
[AS_HELP_STRING([--disable-silent-rules], [ignored])])
# Special Substitutions - CFG_WITH_DEFENV
AC_MSG_CHECKING(whether to use hardcoded paths)
AC_ARG_ENABLE([defenv],
@@ -65,6 +74,21 @@ AC_ARG_ENABLE([longtests],
AC_SUBST(CFG_WITH_LONGTESTS)
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
# CFG_WITH_PREC11
AC_MSG_CHECKING(whether allow pre-C++11)
AC_ARG_ENABLE([prec11],
[AS_HELP_STRING([--enable-prec11],
[enable pre-C++11 compilers])],
[case "${enableval}" in
yes) CFG_WITH_PREC11=yes ;;
no) CFG_WITH_PREC11=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-prec11]) ;;
esac],
[CFG_WITH_PREC11=no;]
)
AC_SUBST(CFG_WITH_PREC11)
AC_MSG_RESULT($CFG_WITH_PREC11)
# Compiler flags
CFLAGS=-I${includedir}
CPPFLAGS=-I${includedir}
@@ -77,6 +101,8 @@ AC_PROG_CXX
AC_PROG_INSTALL
AC_LANG_PUSH(C++)
cxx_version=$($CXX --version | head -1)
AC_MSG_RESULT([compiler is $CXX --version = $cxx_version])
AC_MSG_CHECKING([that C++ compiler can compile simple program])
AC_RUN_IFELSE(
[AC_LANG_SOURCE([int main() { return 0; }])],
@@ -167,9 +193,11 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
# Macros work such that first option that passes is the one we take
# gnu++14 is the newest that Verilator supports
# std++03 is the oldest that Verilator supports
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++17)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++14)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++11)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++03)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++17)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++14)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++11)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++03)
@@ -179,6 +207,7 @@ AC_SUBST(CFG_CXXFLAGS_STD_NEWEST)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++03)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++11)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++14)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++17)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++03)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++11)
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++14)
@@ -218,6 +247,7 @@ AC_SUBST(CFG_CXXFLAGS_PARSER)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-faligned-new)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-fbracket-depth=4096)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Qunused-arguments)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-bool-operation)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-parentheses-equality)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-sign-compare)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
@@ -244,6 +274,22 @@ CFG_WITH_THREADED=$_my_result
AC_SUBST(CFG_WITH_THREADED)
AC_MSG_RESULT($CFG_WITH_THREADED)
# Check compiler flag
if test "$CFG_WITH_THREADED" = "no" ; then
if test "$CFG_WITH_PREC11" = "no" ; then
AC_MSG_NOTICE([[]])
AC_MSG_ERROR([[the $CXX compiler appears to not support C++11.
Verilator plans to require a C++11 or newer compiler in a future release,
unless sufficient people report problems. Therefore, if you do not have a
C++11 compiler, please post a message to
https://www.veripool.org/boards/3/topics/2580-Verilator-Requiring-C-11-compiler
indicating your OS and when you think C++11 might be ok, and then rerun
configure with the --enable-prec11 argument. Thanks.]])
fi
fi
# Checks for library functions.
AC_CHECK_MEMBER([struct stat.st_mtim.tv_nsec],
[AC_DEFINE([HAVE_STAT_NSEC],[1],[Defined if struct stat has st_mtim.tv_nsec])],
+1 -5
View File
@@ -630,12 +630,8 @@ WARN_LOGFILE =
# with spaces.
INPUT = doxygen-mainpage \
include \
include \
src \
test_c \
test_regress \
test_sc \
test_v
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+2 -2
View File
@@ -5,7 +5,7 @@
# This calls the object directory makefile. That allows the objects to
# be placed in the "current directory" which simplifies the Makefile.
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -23,7 +23,7 @@ endif
# real project, it is better to start with a more complete example,
# e.g. examples/tracing_c.
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
# package inatall, and verilator is in your path. Otherwise find the
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
+2 -2
View File
@@ -5,7 +5,7 @@
# This calls the object directory makefile. That allows the objects to
# be placed in the "current directory" which simplifies the Makefile.
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -23,7 +23,7 @@ endif
# real project, it is better to start with a more complete example,
# e.g. examples/tracing_sc.
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
# package inatall, and verilator is in your path. Otherwise find the
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
+2 -2
View File
@@ -5,7 +5,7 @@
# This calls the object directory makefile. That allows the objects to
# be placed in the "current directory" which simplifies the Makefile.
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -20,7 +20,7 @@ endif
######################################################################
# Set up variables
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
# package inatall, and verilator is in your path. Otherwise find the
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
+4 -1
View File
@@ -5,7 +5,7 @@
#
# This is executed in the object directory, and called by ../Makefile
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -17,6 +17,9 @@ default: Vtop
# Include the rules made by Verilator
include Vtop.mk
# Use OBJCACHE (ccache) if using gmake and its installed
COMPILE.cc = $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
#######################################################################
# Compile flags
+6 -1
View File
@@ -90,6 +90,11 @@ int main(int argc, char** argv, char** env) {
// Evaluate model
top->eval();
#if VM_TRACE
// Dump trace data for this cycle
if (tfp) tfp->dump (main_time);
#endif
// Read outputs
VL_PRINTF ("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
@@ -102,7 +107,7 @@ int main(int argc, char** argv, char** env) {
// Close trace if opened
#if VM_TRACE
if (tfp) { tfp->close(); }
if (tfp) { tfp->close(); tfp = NULL; }
#endif
// Coverage analysis (since test passed)
+2 -2
View File
@@ -5,7 +5,7 @@
# This calls the object directory makefile. That allows the objects to
# be placed in the "current directory" which simplifies the Makefile.
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -20,7 +20,7 @@ endif
######################################################################
# Set up variables
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
# package inatall, and verilator is in your path. Otherwise find the
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
ifeq ($(VERILATOR_ROOT),)
+4 -1
View File
@@ -5,7 +5,7 @@
#
# This is executed in the object directory, and called by ../Makefile
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
@@ -17,6 +17,9 @@ default: Vtop
# Include the rules made by Verilator
include Vtop.mk
# Use OBJCACHE (ccache) if using gmake and its installed
COMPILE.cc = $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
#######################################################################
# Compile flags
+14 -9
View File
@@ -94,10 +94,10 @@ int sc_main(int argc, char* argv[]) {
const char* flag = Verilated::commandArgsPlusMatch("trace");
if (flag && 0==strcmp(flag, "+trace")) {
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
VerilatedVcdSc* tfp = new VerilatedVcdSc;
top->trace (tfp, 99);
tfp = new VerilatedVcdSc;
top->trace(tfp, 99);
mkdir("logs", 0777);
tfp->open ("logs/vlt_dump.vcd");
tfp->open("logs/vlt_dump.vcd");
}
#endif
@@ -107,13 +107,15 @@ int sc_main(int argc, char* argv[]) {
// Flush the wave files each cycle so we can immediately see the output
// Don't do this in "real" programs, do it in an abort() handler instead
if (tfp) tfp->flush();
#endif
// Apply inputs
if (VL_TIME_Q() > 1 && VL_TIME_Q() < 10) {
reset_l = !1; // Assert reset
} else if (VL_TIME_Q() > 1) {
reset_l = !0; // Deassert reset
}
#endif
// Simulate 1ns
#if (SYSTEMC_VERSION>=20070314)
sc_start(1,SC_NS);
@@ -122,20 +124,23 @@ int sc_main(int argc, char* argv[]) {
#endif
}
// Close Waves
#if VM_TRACE
if (tfp) tfp->close();
#endif
// Final model cleanup
top->final();
// Close trace if opened
#if VM_TRACE
if (tfp) { tfp->close(); tfp = NULL; }
#endif
// Coverage analysis (since test passed)
#if VM_COVERAGE
mkdir("logs", 0777);
VerilatedCov::write("logs/coverage.dat");
#endif
// Destroy model
delete top; top = NULL;
// Fin
return 0;
}
+323 -62
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -40,9 +40,9 @@ VerilatedVoidCb Verilated::s_flushCb = NULL;
Verilated::Serialized Verilated::s_s;
VL_THREAD_LOCAL Verilated::ThreadLocal Verilated::t_s;
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
Verilated::CommandArgValues Verilated::s_args;
VerilatedImp VerilatedImp::s_s;
VerilatedImp VerilatedImp::s_s;
//===========================================================================
// User definable functions
@@ -122,10 +122,16 @@ std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
va_list aq;
va_copy(aq, ap);
int len = VL_VSNPRINTF(NULL, 0, formatp, aq);
if (VL_UNLIKELY(len < 1)) return "";
va_end(aq);
if (VL_UNLIKELY(len < 1)) {
va_end(ap);
return "";
}
char* bufp = new char[len+1];
VL_VSNPRINTF(bufp, len+1, formatp, ap);
va_end(ap);
std::string out = std::string(bufp, len);
delete[] bufp;
return out;
@@ -159,7 +165,11 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
std::string out = _vl_string_vprintf(formatp, ap);
va_end(ap);
// printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
VL_PRINTF_MT("-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
// Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF
// from within the guts of the thread execution machinery (and it goes
// to the screen and not into the queues we're debugging)
VL_PRINTF("-V{t%d,%" VL_PRI64 "u}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
}
#ifdef VL_THREADED
@@ -198,7 +208,7 @@ IData VL_RAND32() VL_MT_SAFE {
t_seeded = true;
long seedval;
{
VerilatedLockGuard guard(s_mutex);
VerilatedLockGuard lock(s_mutex);
seedval = lrand48()<<16 ^ lrand48();
if (!seedval) seedval++;
}
@@ -430,7 +440,8 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE {
return out;
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
bool lsign, bool rsign) VL_MT_SAFE {
// obits==lbits, rbits can be different
if (rsign && VL_SIGN_W(rbits, rwp)) {
int words = VL_WORDS_I(obits);
@@ -450,7 +461,9 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
}
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
}
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, QData rhs,
bool lsign, bool rsign) VL_MT_SAFE {
WData rhsw[2]; VL_SET_WQ(rhsw, rhs);
return VL_POWSS_WWW(obits,lbits,rbits,owp,lwp,rhsw,lsign,rsign);
}
@@ -471,6 +484,45 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig
//===========================================================================
// Formatting
/// Output a string representation of a wide number
std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
int maxdecwidth = (width+3)*4/3;
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
WData bcd[VL_VALUE_STRING_MAX_WIDTH/4+2];
VL_ZERO_RESET_W(maxdecwidth, bcd);
WData tmp[VL_VALUE_STRING_MAX_WIDTH/4+2];
WData tmp2[VL_VALUE_STRING_MAX_WIDTH/4+2];
int from_bit = width-1;
// Skip all leading zeros
for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit);
// Double-dabble algorithm
for (; from_bit >= 0; --from_bit) {
// Any digits >= 5 need an add 3 (via tmp)
for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit+=4) {
if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
VL_ZERO_RESET_W(maxdecwidth, tmp2);
tmp2[VL_BITWORD_I(nibble_bit)] |= 0x3 << VL_BITBIT_I(nibble_bit);
VL_ASSIGN_W(maxdecwidth, tmp, bcd);
VL_ADD_W(VL_WORDS_I(maxdecwidth), bcd, tmp, tmp2);
}
}
// Shift; bcd = bcd << 1
VL_ASSIGN_W(maxdecwidth, tmp, bcd);
VL_SHIFTL_WWI(maxdecwidth, maxdecwidth, 32, bcd, tmp, 1);
// bcd[0] = lwp[from_bit]
if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
}
std::string output;
int lsb = (maxdecwidth-1) & ~3;
for (; lsb>0; lsb-=4) { // Skip leading zeros
if (VL_BITRSHIFT_W(bcd, lsb) & 0xf) break;
}
for (; lsb>=0; lsb-=4) {
output += ('0' + (VL_BITRSHIFT_W(bcd, lsb) & 0xf)); // 0..9
}
return output;
}
// Do a va_arg returning a quad, assuming input argument is anything less than wide
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
@@ -559,7 +611,6 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
} else {
lwp = va_arg(ap,WDataInP);
ld = lwp[0];
if (fmt == 'd' || fmt == '#') fmt = 'x'; // Not supported, but show something
}
int lsb=lbits-1;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) --lsb;
@@ -572,13 +623,27 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case 's':
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
output += (charval==0)?' ':charval;
}
break;
case 'd': { // Signed decimal
int digits = sprintf(tmp,"%" VL_PRI64 "d",
int digits;
std::string append;
if (lbits <= VL_QUADSIZE) {
digits = sprintf(tmp,"%" VL_PRI64 "d",
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits,lbits,ld)));
append = tmp;
} else {
if (VL_SIGN_I(lbits, lwp[VL_WORDS_I(lbits)-1])) {
WData neg[VL_VALUE_STRING_MAX_WIDTH/4+2];
VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp);
append = std::string("-") + VL_DECIMAL_NW(lbits, neg);
} else {
append = VL_DECIMAL_NW(lbits, lwp);
}
digits = append.length();
}
int needmore = width-digits;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
@@ -587,11 +652,19 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp;
output += append;
break;
}
case '#': { // Unsigned decimal
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
int digits;
std::string append;
if (lbits <= VL_QUADSIZE) {
digits = sprintf(tmp,"%" VL_PRI64 "u",ld);
append = tmp;
} else {
append = VL_DECIMAL_NW(lbits, lwp);
digits = append.length();
}
int needmore = width-digits;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
@@ -600,7 +673,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp;
output += append;
break;
}
case 't': { // Time
@@ -621,10 +694,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
case 'b':
for (; lsb>=0; --lsb) {
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
}
break;
break;
case 'o':
for (; lsb>=0; --lsb) {
lsb = (lsb / 3) * 3; // Next digit
@@ -658,14 +730,14 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
break;
case 'v': // Strength; assume always strong
for (lsb=lbits-1; lsb>=0; --lsb) {
if ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) output += "St1 ";
else output += "St0 ";
if (VL_BITRSHIFT_W(lwp, lsb) & 1) output += "St1 ";
else output += "St0 ";
}
break;
case 'x':
for (; lsb>=0; --lsb) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
output += "0123456789abcdef"[charval];
}
break;
@@ -701,7 +773,7 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const std:
if (fromp == NULL) {
return fstr[fstr.length()-1 - (floc>>3)];
} else {
return (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
return VL_BITRSHIFT_W(fromp, floc) & 0xff;
}
}
}
@@ -916,14 +988,15 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE
char* destp = destoutp;
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (sourcep[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
if (!start || charval) {
*destp++ = (charval==0)?' ':charval;
start = false; // Drop leading 0s
}
}
*destp = '\0'; // Terminate
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
// Drop trailing spaces
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0';
}
void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
@@ -1142,10 +1215,134 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
return got;
}
void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData ofilename, const void* memp, IData start,
IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
return VL_WRITEMEM_W(hex, width,depth,array_lsb,2,fnw,memp,start,end);
}
void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilenamep, const void* memp, IData start,
IData end) VL_MT_SAFE {
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
std::string ofilenames(ofilenamez);
return VL_WRITEMEM_N(hex, width,depth,array_lsb,ofilenames,memp,start,end);
}
const char* memhFormat(int nBits) {
assert((nBits >= 1) && (nBits <= 32));
static char buf[32];
switch ((nBits - 1) / 4) {
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
default: assert(false); break;
}
return buf;
}
void VL_WRITEMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& ofilenamep, // Output file name
const void* memp, // Array state
IData start, // First array row address to write
IData end // Last address to write
) VL_MT_SAFE {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
"VL_WRITEMEM_N only supports hex format for now, sorry!");
return;
}
FILE* fp = fopen(ofilenamep.c_str(), "w");
if (VL_UNLIKELY(!fp)) {
VL_FATAL_MT(ofilenamep.c_str(), 0, "", "$writemem file not found");
return;
}
for (int row_addr = start; row_addr <= end; ++row_addr) {
if ((row_addr < array_lsb)
|| (row_addr > array_lsb + depth - 1)) {
vluint32_t endmax = ~0;
if (end != endmax) {
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
"$writemem specified address out-of-bounds");
}
// else, it's not an error to overflow due to end == endmax,
// just return cleanly.
goto cleanup;
}
// Compute the offset into the memp array.
int row_offset = row_addr - array_lsb;
if (width <= 8) {
const CData* datap
= &(reinterpret_cast<const CData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 16) {
const SData* datap
= &(reinterpret_cast<const SData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 32) {
const IData* datap
= &(reinterpret_cast<const IData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 64) {
const QData* datap
= &(reinterpret_cast<const QData*>(memp))[row_offset];
vluint64_t value = VL_MASK_Q(width) & *datap;
vluint32_t lo = value & 0xffffffff;
vluint32_t hi = value >> 32;
fprintf(fp, memhFormat(width - 32), hi);
fprintf(fp, "%08x\n", lo);
} else {
WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)];
// output as a sequence of VL_WORDSIZE'd words
// from MSB to LSB. Mask off the MSB word which could
// contain junk above the top of valid data.
int word_idx = ((width - 1) / VL_WORDSIZE);
bool first = true;
while (word_idx >= 0) {
IData data = datap[word_idx];
if (first) {
data &= VL_MASK_I(width);
int top_word_nbits = ((width - 1) & 0x1f) + 1;
fprintf(fp, memhFormat(top_word_nbits), data);
} else {
fprintf(fp, "%08x", data);
}
word_idx--;
first = false;
}
fprintf(fp, "\n");
}
}
cleanup:
fclose(fp);
}
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
return VL_READMEM_W(hex,width,depth,array_lsb,2,fnw,memp,start,end);
}
void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
@@ -1153,12 +1350,20 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
std::string ofilenames(ofilenamez);
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
return VL_READMEM_N(hex,width,depth,array_lsb,ofilenames,memp,start,end);
}
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const std::string& ofilenamep, void* memp, IData start, IData end) VL_MT_SAFE {
if (fnwords) {}
void VL_READMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& ofilenamep, // Input file name
void* memp, // Array state
IData start, // First array row address to read
IData end // Last row address to read
) VL_MT_SAFE {
FILE* fp = fopen(ofilenamep.c_str(), "r");
if (VL_UNLIKELY(!fp)) {
// We don't report the Verilog source filename as it slow to have to pass it down
@@ -1180,7 +1385,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
while (1) {
int c = fgetc(fp);
if (VL_UNLIKELY(c==EOF)) break;
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n",
// linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
// Skip // comments and detect /* comments
@@ -1208,7 +1414,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
//printf(" Value width=%d @%x = %c\n", width, addr, c);
if (VL_UNLIKELY(addr >= static_cast<IData>(depth+array_lsb)
|| addr < static_cast<IData>(array_lsb))) {
VL_FATAL_MT (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array");
VL_FATAL_MT (ofilenamep.c_str(), linenum, "",
"$readmem file address beyond bounds of array");
} else {
int entry = addr - array_lsb;
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
@@ -1237,7 +1444,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
datap[0] |= value;
}
if (VL_UNLIKELY(value>=(1<<shift))) {
VL_FATAL_MT (ofilenamep.c_str(), linenum, "", "$readmemb (binary) file contains hex characters");
VL_FATAL_MT (ofilenamep.c_str(), linenum, "",
"$readmemb (binary) file contains hex characters");
}
}
}
@@ -1385,7 +1593,7 @@ std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
int len = 0;
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
if (!start || charval) {
*destp++ = (charval==0)?' ':charval;
len++;
@@ -1401,7 +1609,8 @@ std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
Verilated::ThreadLocal::ThreadLocal()
:
#ifdef VL_THREADED
t_trainId(0),
t_mtaskId(0),
t_endOfEvalReqd(0),
#endif
t_dpiScopep(NULL), t_dpiFilename(0), t_dpiLineno(0) {
}
@@ -1409,7 +1618,7 @@ Verilated::ThreadLocal::~ThreadLocal() {
}
void Verilated::debug(int val) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_debug = val;
if (val) {
#ifdef VL_DEBUG
@@ -1420,23 +1629,23 @@ void Verilated::debug(int val) VL_MT_SAFE {
}
}
void Verilated::randReset(int val) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_randReset = val;
}
void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_calcUnusedSigs = flag;
}
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_gotFinish = flag;
}
void Verilated::assertOn(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_assertOn = flag;
}
void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_s.s_fatalOnVpiError = flag;
}
@@ -1458,7 +1667,7 @@ const char* Verilated::catName(const char* n1, const char* n2) VL_MT_SAFE {
}
void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
if (s_flushCb == cb) {} // Ok - don't duplicate
else if (!s_flushCb) { s_flushCb=cb; }
else {
@@ -1468,12 +1677,14 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
}
void Verilated::flushCall() VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
if (s_flushCb) (*s_flushCb)();
fflush(stderr);
fflush(stdout);
}
void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
s_args.argc = argc;
s_args.argv = argv;
VerilatedImp::commandArgs(argc,argv);
@@ -1511,16 +1722,6 @@ void Verilated::scopesDump() VL_MT_SAFE {
VerilatedImp::scopesDump();
}
void Verilated::numThreads(unsigned threads) VL_MT_SAFE {
VerilatedImp::numThreads(threads);
}
unsigned Verilated::numThreads() VL_MT_SAFE {
return VerilatedImp::numThreads();
}
void Verilated::spawnThreads() VL_MT_SAFE {
VerilatedImp::spawnThreads();
}
const VerilatedScope* Verilated::scopeFind(const char* namep) VL_MT_SAFE {
return VerilatedImp::scopeFind(namep);
}
@@ -1534,8 +1735,8 @@ const VerilatedScopeNameMap* Verilated::scopeNameMap() VL_MT_SAFE {
}
#ifdef VL_THREADED
void Verilated::endOfThreadTrainGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
VL_DEBUG_IF(VL_DBG_MSGF("End of thread train\n"););
void Verilated::endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
VL_DEBUG_IF(VL_DBG_MSGF("End of thread mtask\n"););
VerilatedThreadMsgQueue::flush(evalMsgQp);
}
@@ -1545,6 +1746,44 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
}
#endif
//===========================================================================
// VerilatedImp:: Methods
void VerilatedImp::internalsDump() VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_argMutex);
VL_PRINTF_MT("internalsDump:\n");
versionDump();
VL_PRINTF_MT(" Argv:");
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
VL_PRINTF_MT(" %s",it->c_str());
}
VL_PRINTF_MT("\n");
scopesDump();
exportsDump();
userDump();
}
void VerilatedImp::versionDump() VL_MT_SAFE {
VL_PRINTF_MT(" Version: %s %s\n",
Verilated::productName(), Verilated::productVersion());
}
void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard lock(s_s.m_argMutex);
s_s.m_argVec.clear(); // Always clear
commandArgsAddGuts(argc, argv);
}
void VerilatedImp::commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard lock(s_s.m_argMutex);
commandArgsAddGuts(argc, argv);
}
void VerilatedImp::commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex) {
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
for (int i=0; i<argc; ++i) {
s_s.m_argVec.push_back(argv[i]);
}
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
}
//======================================================================
// VerilatedSyms:: Methods
@@ -1575,7 +1814,7 @@ VerilatedModule::~VerilatedModule() {
// VerilatedVar:: Methods
// cppcheck-suppress unusedFunction // Used by applications
vluint32_t VerilatedVar::entSize() const {
vluint32_t VerilatedVarProps::entSize() const {
vluint32_t size = 1;
switch (vltype()) {
case VLVT_PTR: size=sizeof(void*); break;
@@ -1583,12 +1822,32 @@ vluint32_t VerilatedVar::entSize() const {
case VLVT_UINT16: size=sizeof(SData); break;
case VLVT_UINT32: size=sizeof(IData); break;
case VLVT_UINT64: size=sizeof(QData); break;
case VLVT_WDATA: size=VL_WORDS_I(range().elements())*sizeof(IData); break;
case VLVT_WDATA: size=VL_WORDS_I(packed().elements())*sizeof(IData); break;
default: size=0; break;
}
return size;
}
size_t VerilatedVarProps::totalSize() const {
size_t size = entSize();
for (int dim=1; dim<=dims(); ++dim) {
size *= m_unpacked[dim].elements();
}
return size;
}
void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const {
if (VL_UNLIKELY(dim <=0 || dim > m_udims || dim > 3)) return NULL;
if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return NULL;
int indxAdj = indx - low(dim);
vluint8_t* bytep = reinterpret_cast<vluint8_t*>(datap);
// If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
size_t slicesz = entSize();
for (int d=dim+1; d<=m_udims; ++d) slicesz *= elements(d);
bytep += indxAdj*slicesz;
return bytep;
}
//======================================================================
// VerilatedScope:: Methods
@@ -1656,15 +1915,17 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
int msb = va_arg(ap,int);
int lsb = va_arg(ap,int);
if (i==0) {
var.m_range.m_left = msb;
var.m_range.m_right = lsb;
} else if (i==1) {
var.m_array.m_left = msb;
var.m_array.m_right = lsb;
var.m_packed.m_left = msb;
var.m_packed.m_right = lsb;
} else if (i>=1 && i<=3) {
var.m_unpacked[i-1].m_left = msb;
var.m_unpacked[i-1].m_right = lsb;
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
VL_FATAL_MT(__FILE__,__LINE__,"",(std::string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
VL_FATAL_MT(__FILE__,__LINE__,"",
(std::string("Unsupported multi-dimensional public varInsert: ")
+ namep).c_str());
}
}
va_end(ap);
@@ -1721,7 +1982,7 @@ void VerilatedScope::scopeDump() const {
//===========================================================================
// VerilatedOneThreaded:: Methods
#ifdef VL_THREADED
#if defined(VL_THREADED) && defined(VL_DEBUG)
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
VL_FATAL_MT(__FILE__, __LINE__, "", "Routine called that is single threaded, but called from"
" a different thread then the expected constructing thread");
+203 -107
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -99,7 +99,8 @@ enum VerilatedVarFlags {
VLVF_MASK_DIR=7, // Bit mask for above directions
// Flags
VLVF_PUB_RD=(1<<8), // Public readable
VLVF_PUB_RW=(1<<9) // Public writable
VLVF_PUB_RW=(1<<9), // Public writable
VLVF_DPI_CLAY=(1<<10) // DPI compatible C standard layout
};
//=========================================================================
@@ -110,6 +111,8 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
#if VL_THREADED
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
/// Mutex, wrapped to allow -fthread_safety checks
class VL_CAPABILITY("mutex") VerilatedMutex {
private:
@@ -118,9 +121,19 @@ class VL_CAPABILITY("mutex") VerilatedMutex {
VerilatedMutex() {}
~VerilatedMutex() {}
/// Acquire/lock mutex
void lock() VL_ACQUIRE() { m_mutex.lock(); }
void lock() VL_ACQUIRE() {
// Try to acquire the lock by spinning. If the wait is short,
// avoids a trap to the OS plus OS scheduler overhead.
if (VL_LIKELY(try_lock())) return; // Short circuit loop
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
if (VL_LIKELY(try_lock())) return;
VL_CPU_RELAX();
}
// Spinning hasn't worked, pay the cost of blocking.
m_mutex.lock();
}
/// Release/unlock mutex
void unlock() VL_RELEASE() { m_mutex.unlock(); }
void unlock() VL_RELEASE() { m_mutex.unlock(); }
/// Try to acquire mutex. Returns true on success, and false on failure.
bool try_lock() VL_TRY_ACQUIRE(true) { return m_mutex.try_lock(); }
};
@@ -142,14 +155,21 @@ class VL_SCOPED_CAPABILITY VerilatedLockGuard {
#else // !VL_THREADED
// Empty classes to avoid #ifdefs everywhere
class VerilatedMutex {};
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
class VerilatedMutex {
public:
void lock() {}
void unlock() {}
};
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
class VerilatedLockGuard {
VL_UNCOPYABLE(VerilatedLockGuard);
public:
explicit VerilatedLockGuard(VerilatedMutex&) {}
~VerilatedLockGuard() {}
};
#endif // VL_THREADED
/// Remember the calling thread at construction time, and make sure later calls use same thread
@@ -166,9 +186,7 @@ public:
// METHODS
/// Check that the current thread ID is the same as the construction thread ID
void check() VL_MT_UNSAFE_ONE {
// Memoize results in local thread, to prevent slow get_id() call
VL_THREAD_LOCAL bool t_okThread = (m_threadid == VL_THREAD_ID());
if (!VL_LIKELY(t_okThread)) {
if (!VL_LIKELY(m_threadid == VL_THREAD_ID())) {
fatal_different();
}
}
@@ -309,20 +327,21 @@ public: // But internals only - called from VerilatedModule's
class Verilated {
// MEMBERS
// Slow path variables
static VerilatedMutex m_mutex; ///< Mutex for all static members, when VL_THREADED
static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
static VerilatedVoidCb s_flushCb; ///< Flush callback function
static struct Serialized { // All these members serialized/deserialized
// Slow path
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
// Fast path
int s_debug; ///< See accessors... only when VL_DEBUG set
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
bool s_gotFinish; ///< A $finish statement executed
bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
Serialized();
// Slow path
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
Serialized();
~Serialized() {}
} s_s;
// no need to be save-restored (serialized) the
@@ -330,12 +349,14 @@ class Verilated {
static struct CommandArgValues {
int argc;
const char** argv;
CommandArgValues() : argc(0), argv(NULL) {}
~CommandArgValues() {}
} s_args;
// Not covered by mutex, as per-thread
static VL_THREAD_LOCAL struct ThreadLocal {
#ifdef VL_THREADED
vluint32_t t_trainId; ///< Current train# executing on this thread
vluint32_t t_mtaskId; ///< Current mtask# executing on this thread
vluint32_t t_endOfEvalReqd; ///< Messages may be pending, thread needs endOf-eval calls
#endif
const VerilatedScope* t_dpiScopep; ///< DPI context scope
@@ -372,7 +393,8 @@ public:
#endif
/// Enable calculation of unused signals
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
static bool calcUnusedSigs() VL_MT_SAFE { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
static bool calcUnusedSigs() VL_MT_SAFE { ///< Return calcUnusedSigs value
return s_s.s_calcUnusedSigs; }
/// Did the simulation $finish?
static void gotFinish(bool flag) VL_MT_SAFE;
static bool gotFinish() VL_MT_SAFE { return s_s.s_gotFinish; } ///< Return if got a $finish
@@ -392,7 +414,8 @@ public:
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
static void commandArgs(int argc, const char** argv) VL_MT_SAFE;
static void commandArgs(int argc, char** argv) VL_MT_SAFE { commandArgs(argc, const_cast<const char**>(argv)); }
static void commandArgs(int argc, char** argv) VL_MT_SAFE {
commandArgs(argc, const_cast<const char**>(argv)); }
static void commandArgsAdd(int argc, const char** argv);
static CommandArgValues* getCommandArgs() VL_MT_SAFE { return &s_args; }
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
@@ -416,17 +439,6 @@ public:
/// releases - contact the authors before production use.
static void scopesDump() VL_MT_SAFE;
/// Set the number of threads to execute on.
/// 0x0 = use all available CPU threads, or 1 if no support compiled in
/// Ignored after spawnThreads() has been called
static void numThreads(unsigned threads) VL_MT_SAFE;
static unsigned numThreads() VL_MT_SAFE;
/// Spawn child threads, using numThreads() as # of threads
/// Verilator calls this automatically on the first eval() call
/// User code may call it earlier if desired
/// Once called the first time, later calls are ignored
static void spawnThreads() VL_MT_SAFE;
public:
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
// Internal: Create a new module name by concatenating two strings
@@ -453,22 +465,29 @@ public:
static size_t serializedSize() VL_PURE { return sizeof(s_s); }
static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
#ifdef VL_THREADED
/// Set the trainId, called when a train starts
static void trainId(vluint32_t id) VL_MT_SAFE { t_s.t_trainId = id; }
static vluint32_t trainId() VL_MT_SAFE { return t_s.t_trainId; }
/// Set the mtaskId, called when an mtask starts
static void mtaskId(vluint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
static vluint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; }
static void endOfEvalReqdInc() VL_MT_SAFE { ++t_s.t_endOfEvalReqd; }
static void endOfEvalReqdDec() VL_MT_SAFE { --t_s.t_endOfEvalReqd; }
/// Called at end of each thread train, before finishing eval
static void endOfThreadTrain(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) { endOfThreadTrainGuts(evalMsgQp); } }
/// Called at end of each thread mtask, before finishing eval
static void endOfThreadMTask(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) { endOfThreadMTaskGuts(evalMsgQp); }
}
/// Called at end of eval loop
static void endOfEval(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) { endOfEvalGuts(evalMsgQp); } }
// It doesn't work to set endOfEvalReqd on the threadpool thread
// and then check it on the eval thread since it's thread local.
// It should be ok to call into endOfEvalGuts, it returns immediately
// if there are no transactions.
endOfEvalGuts(evalMsgQp);
}
#endif
private:
#ifdef VL_THREADED
static void endOfThreadTrainGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
static void endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
static void endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
#endif
};
@@ -525,6 +544,11 @@ extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal (slow - else use VL_ZERO_W)
#if VL_THREADED
/// Return high-precision counter for profiling, or 0x0 if not available
inline QData VL_RDTSC_Q() { vluint64_t val; VL_RDTSC(val); return val; }
#endif
/// Math
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
@@ -534,8 +558,8 @@ extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
inline IData VL_FOPEN_II(IData ofilename, IData mode) VL_MT_SAFE { return VL_FOPEN_QI(ofilename,mode); }
inline IData VL_FOPEN_II(IData ofilename, IData mode) VL_MT_SAFE {
return VL_FOPEN_QI(ofilename,mode); }
extern void VL_FCLOSE_I(IData fdi);
@@ -547,6 +571,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
IData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilename, const void* memp, IData start, IData end);
extern void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
QData ofilename, const void* memp, IData start, IData end);
inline void VL_WRITEMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
IData ofilename, const void* memp, IData start, IData end) VL_MT_SAFE {
VL_WRITEMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
@@ -575,13 +607,20 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSETLIMIT_W(data,width,bit) \
(((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
/// Shift appropriate word by bit. Does not account for wrapping between two words
#define VL_BITRSHIFT_W(data,bit) (data[VL_BITWORD_I(bit)] >> VL_BITBIT_I(bit))
/// Create two 32-bit words from quadword
/// WData is always at least 2 words; does not clean upper bits
#define VL_SET_WQ(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
#define VL_SET_WQ(owp,data) { owp[0]=static_cast<IData>(data); \
owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
#define VL_SET_WI(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=0; }
#define VL_SET_QW(lwp) ( (static_cast<QData>(lwp[0])) | (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
#define VL_SET_QW(lwp) \
( (static_cast<QData>(lwp[0])) \
| (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
#define _VL_SET_QII(ld,rd) ( (static_cast<QData>(ld)<<VL_ULL(32)) | static_cast<QData>(rd) )
/// Return FILE* from IData
@@ -589,19 +628,26 @@ extern FILE* VL_CVT_I_FP(IData lhs);
// Use a union to avoid cast-to-different-size warnings
/// Return void* from QData
static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return QData from void*
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
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) VL_PURE { union { double d; QData q; } u; u.q=lhs; return u.d; }
static inline double VL_CVT_D_Q(QData lhs) VL_PURE {
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) VL_PURE { union { double d; QData q; } u; u.d=lhs; return u.q; }
static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
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) VL_PURE { return static_cast<double>(static_cast<vlsint32_t>(lhs)); }
static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
return static_cast<double>(static_cast<vlsint32_t>(lhs)); }
/// Return QData from double (numeric)
static inline IData VL_RTOI_I_D(double lhs) VL_PURE { return static_cast<vlsint32_t>(VL_TRUNC(lhs)); }
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
return static_cast<vlsint32_t>(VL_TRUNC(lhs)); }
/// Return QData from double (numeric)
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE {
return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input)
@@ -612,8 +658,10 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast<v
// Sign bit extended up to MSB, doesn't include unsigned portion
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE {
return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE {
return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
// Debugging prints
extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
@@ -1223,7 +1271,7 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
static inline IData VL_NEGATE_I(IData data) VL_PURE { return -data; }
static inline QData VL_NEGATE_Q(QData data) VL_PURE { return -data; }
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp) VL_MT_SAFE {
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
QData carry = 0;
for (int i=0; i<words; ++i) {
carry = carry + static_cast<QData>(static_cast<IData>(~lwp[i]));
@@ -1396,13 +1444,19 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDa
WDataOutP VL_POW_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs);
QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp);
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) \
VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) \
VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
static inline IData VL_POWSS_III(int obits, int, int rbits,
IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
@@ -1415,7 +1469,8 @@ static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs
}
return VL_POW_III(obits, rbits, rbits, lhs, rhs);
}
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
static inline QData VL_POWSS_QQQ(int obits, int, int rbits,
QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
@@ -1428,9 +1483,12 @@ static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs
}
return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs);
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWW(int obits, int, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits,
WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
QData VL_POWSS_QQW(int obits, int, int rbits,
QData lhs, WDataInP rwp, bool lsign, bool rsign);
//===================================================================
// Concat/replication
@@ -1550,21 +1608,24 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) V
}
return (returndata);
}
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int,
WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
owp[0] = ld;
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WI(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int,
WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
VL_SET_WQ(owp,ld);
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WQ(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int,
WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WW(obits,owp,lwp,i*lbits+lbits-1,i*lbits);
@@ -1629,15 +1690,20 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_
}
switch (rd_log2) {
case 0:
ret = ((ret >> 1) & VL_ULL(0x5555555555555555)) | ((ret & VL_ULL(0x5555555555555555)) << 1); // FALLTHRU
ret = (((ret >> 1) & VL_ULL(0x5555555555555555))
| ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU
case 1:
ret = ((ret >> 2) & VL_ULL(0x3333333333333333)) | ((ret & VL_ULL(0x3333333333333333)) << 2); // FALLTHRU
ret = (((ret >> 2) & VL_ULL(0x3333333333333333))
| ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU
case 2:
ret = ((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4); // FALLTHRU
ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f))
| ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU
case 3:
ret = ((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8); // FALLTHRU
ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff))
| ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU
case 4:
ret = ((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16); // FALLTHRU
ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff))
| ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU
case 5:
ret = ((ret >> 32) | (ret << 32));
}
@@ -1679,7 +1745,7 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
for (int sbit=0; sbit<ssize && sbit<lbits-istart; ++sbit) {
// Extract a single bit from lwp and shift it to the correct
// location for owp.
WData bit= ((lwp[VL_BITWORD_I(istart+sbit)] >> VL_BITBIT_I(istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
WData bit= (VL_BITRSHIFT_W(lwp, (istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
owp[VL_BITWORD_I(ostart+sbit)] |= bit;
}
}
@@ -1690,61 +1756,75 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
// Thus we specify inputs must be clean, so we don't need to clean the output.
// Note the bit shifts are always constants, so the adds in these constify out.
// Casts required, as args may be 8 bit entities, and need to shift to appropriate output size
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) (static_cast<IData>(ld)<<(rbits) | static_cast<IData>(rd))
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) \
(static_cast<IData>(ld)<<(rbits) | static_cast<IData>(rd))
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) \
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
static inline WDataOutP VL_CONCAT_WII(int obits,int lbits,int rbits,WDataOutP owp,IData ld,IData rd) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits,
WDataOutP owp, IData ld,IData rd) VL_MT_SAFE {
owp[0] = rd;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWI(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
owp[0] = rd;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WIW(int obits,int lbits,int rbits,WDataOutP owp,IData ld, WDataInP rwp) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits,
WDataOutP owp, IData ld, WDataInP rwp) VL_MT_SAFE {
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WIQ(int obits,int lbits,int rbits,WDataOutP owp,IData ld,QData rd) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits,
WDataOutP owp, IData ld, QData rd) VL_MT_SAFE {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQI(int obits,int lbits,int rbits,WDataOutP owp,QData ld,IData rd) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits,
WDataOutP owp, QData ld, IData rd) VL_MT_SAFE {
owp[0] = rd;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQQ(int obits,int lbits,int rbits,WDataOutP owp,QData ld,QData rd) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits,
WDataOutP owp, QData ld, QData rd) VL_MT_SAFE {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWQ(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, QData rd) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQW(int obits,int lbits,int rbits,WDataOutP owp,QData ld, WDataInP rwp) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits,
WDataOutP owp, QData ld, WDataInP rwp) VL_MT_SAFE {
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
@@ -1783,7 +1863,8 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
}
return(owp);
}
static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
@@ -1803,7 +1884,8 @@ static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rw
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
// Important: Unlike most other funcs, the shift might well be a computed
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int,
WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_I(rd); // Maybe 0
int bit_shift = VL_BITBIT_I(rd);
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set
@@ -1828,7 +1910,8 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
}
return(owp);
}
static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
static inline WDataOutP VL_SHIFTR_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
@@ -1860,10 +1943,12 @@ static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData r
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
}
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) VL_PURE {
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits,
QData lhs, IData rhs) VL_PURE {
return static_cast<IData>(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
}
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
int word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_I(rd);
int lmsw = VL_WORDS_I(obits)-1;
@@ -1895,7 +1980,8 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
}
return(owp);
}
static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
int lmsw = VL_WORDS_I(obits)-1;
@@ -1907,7 +1993,8 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP o
}
return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) VL_MT_SAFE {
static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits,
IData lhs, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
@@ -1916,7 +2003,8 @@ static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDat
}
return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]);
}
static inline QData VL_SHIFTRS_QQW(int obits,int lbits,int rbits,QData lhs, WDataInP rwp) VL_MT_SAFE {
static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits,
QData lhs, WDataInP rwp) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
@@ -1959,42 +2047,45 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
#define VL_SEL_QQII(obits,lbits,rbits,tbits,lhs,lsb,width) ((lhs)>>(lsb))
#define VL_SEL_IQII(obits,lbits,rbits,tbits,lhs,lsb,width) (static_cast<IData>((lhs)>>(lsb)))
static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
static inline IData VL_SEL_IWII(int, int lbits, int, int,
WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
int msb = lsb+width-1;
if (VL_UNLIKELY(msb>lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
return (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
return VL_BITRSHIFT_W(lwp, lsb);
} else {
// 32 bit extraction may span two words
int nbitsfromlow = 32-VL_BITBIT_I(lsb); // bits that come from low word
return ((lwp[VL_BITWORD_I(msb)]<<nbitsfromlow)
|(lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)));
| VL_BITRSHIFT_W(lwp, lsb));
}
}
static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
static inline QData VL_SEL_QWII(int, int lbits, int, int,
WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
int msb = lsb+width-1;
if (VL_UNLIKELY(msb>lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
return (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
return VL_BITRSHIFT_W(lwp, lsb);
} else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I(static_cast<int>(lsb))) {
int nbitsfromlow = 32-VL_BITBIT_I(lsb);
QData hi = (lwp[VL_BITWORD_I(msb)]);
QData lo = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
QData lo = VL_BITRSHIFT_W(lwp, lsb);
return (hi<<nbitsfromlow) | lo;
} else {
// 64 bit extraction may span three words
int nbitsfromlow = 32-VL_BITBIT_I(lsb);
QData hi = (lwp[VL_BITWORD_I(msb)]);
QData mid= (lwp[VL_BITWORD_I(lsb)+1]);
QData lo = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
QData lo = VL_BITRSHIFT_W(lwp, lsb);
return (hi<<(nbitsfromlow+32)) | (mid<<nbitsfromlow) | lo;
}
}
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int,
WDataOutP owp, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
int msb = lsb+width-1;
int word_shift = VL_BITWORD_I(lsb);
if (VL_UNLIKELY(msb>lbits)) { // Outside bounds,
@@ -2117,37 +2208,41 @@ static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
o[0]=d0;
_END(obits,1); }
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
IData d1,IData d0) VL_MT_SAFE {
IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1;
_END(obits,2); }
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
IData d2,IData d1,IData d0) VL_MT_SAFE {
IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2;
_END(obits,3); }
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
_END(obits,4); }
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
IData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
_END(obits,5); }
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
IData d5, IData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
_END(obits,6); }
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
IData d6, IData d5, IData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
_END(obits,7); }
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
IData d7, IData d6, IData d5, IData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
_END(obits,8); }
@@ -2156,7 +2251,8 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
// Partial constant, lower words of vector wider than 8*32, starting at bit number lsb
static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
IData d7, IData d6, IData d5, IData d4, IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
IData d7, IData d6, IData d5, IData d4,
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; }
+4 -2
View File
@@ -2,7 +2,7 @@
######################################################################
# DESCRIPTION: Makefile commands for all verilated target files
#
# Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
# Copyright 2003-2018 by Wilson Snyder. Verilator is free software; you can
# redistribute it and/or modify it under the terms of either the GNU Lesser
# General Public License Version 3 or the Perl Artistic License Version 2.0.
######################################################################
@@ -186,14 +186,16 @@ endif
debug-make::
@echo
@echo CPPFLAGS: $(CPPFLAGS)
@echo VM_PREFIX: $(VM_PREFIX)
@echo VM_PARALLEL_BUILDS: $(VM_PARALLEL_BUILDS)
@echo VM_CLASSES_FAST: $(VM_CLASSES_FAST)
@echo VM_CLASSES_SLOW: $(VM_CLASSES_SLOW)
@echo VM_SUPPORT_FAST: $(VM_SUPPORT_FAST)
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
@echo CPPFLAGS: $(CPPFLAGS)
@echo VK_OBJS: $(VK_OBJS)
@echo
######################################################################
+1 -1
View File
@@ -4,7 +4,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
+8 -8
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 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.
//
@@ -233,12 +233,12 @@ public:
// PUBLIC METHODS
void clear() VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
clearGuts();
}
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
if (matchp && matchp[0]) {
ItemList newlist;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
@@ -254,7 +254,7 @@ public:
}
void zero() VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
(*it)->zero();
}
@@ -262,18 +262,18 @@ public:
// We assume there's always call to i/f/p in that order
void inserti (VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
assert(!m_insertp);
m_insertp = itemp;
}
void insertf (const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
m_insertFilenamep = filenamep;
m_insertLineno = lineno;
}
void insertp (const char* ckeyps[MAX_KEYS],
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
assert(m_insertp);
// First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
@@ -328,7 +328,7 @@ public:
void write(const char* filename) VL_EXCLUDES(m_mutex) {
Verilated::quiesce();
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
#ifndef VM_COVERAGE
VL_FATAL_MT("",0,"","%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
#endif
+1 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
+34 -34
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 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.
//
@@ -104,39 +104,39 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
class VerilatedCovKey {
public:
static std::string shortKey(const std::string& key) VL_PURE {
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
if (key == "col0") return VL_CIK_COL0;
if (key == "col0_name") return VL_CIK_COL0_NAME;
if (key == "col1") return VL_CIK_COL1;
if (key == "col1_name") return VL_CIK_COL1_NAME;
if (key == "col2") return VL_CIK_COL2;
if (key == "col2_name") return VL_CIK_COL2_NAME;
if (key == "col3") return VL_CIK_COL3;
if (key == "col3_name") return VL_CIK_COL3_NAME;
if (key == "column") return VL_CIK_COLUMN;
if (key == "comment") return VL_CIK_COMMENT;
if (key == "filename") return VL_CIK_FILENAME;
if (key == "groupcmt") return VL_CIK_GROUPCMT;
if (key == "groupdesc") return VL_CIK_GROUPDESC;
if (key == "groupname") return VL_CIK_GROUPNAME;
if (key == "hier") return VL_CIK_HIER;
if (key == "limit") return VL_CIK_LIMIT;
if (key == "lineno") return VL_CIK_LINENO;
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
if (key == "row0") return VL_CIK_ROW0;
if (key == "row0_name") return VL_CIK_ROW0_NAME;
if (key == "row1") return VL_CIK_ROW1;
if (key == "row1_name") return VL_CIK_ROW1_NAME;
if (key == "row2") return VL_CIK_ROW2;
if (key == "row2_name") return VL_CIK_ROW2_NAME;
if (key == "row3") return VL_CIK_ROW3;
if (key == "row3_name") return VL_CIK_ROW3_NAME;
if (key == "table") return VL_CIK_TABLE;
if (key == "thresh") return VL_CIK_THRESH;
if (key == "type") return VL_CIK_TYPE;
if (key == "weight") return VL_CIK_WEIGHT;
// VLCOVGEN_SHORT_AUTO_EDIT_END
return key;
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
if (key == "col0") return VL_CIK_COL0;
if (key == "col0_name") return VL_CIK_COL0_NAME;
if (key == "col1") return VL_CIK_COL1;
if (key == "col1_name") return VL_CIK_COL1_NAME;
if (key == "col2") return VL_CIK_COL2;
if (key == "col2_name") return VL_CIK_COL2_NAME;
if (key == "col3") return VL_CIK_COL3;
if (key == "col3_name") return VL_CIK_COL3_NAME;
if (key == "column") return VL_CIK_COLUMN;
if (key == "comment") return VL_CIK_COMMENT;
if (key == "filename") return VL_CIK_FILENAME;
if (key == "groupcmt") return VL_CIK_GROUPCMT;
if (key == "groupdesc") return VL_CIK_GROUPDESC;
if (key == "groupname") return VL_CIK_GROUPNAME;
if (key == "hier") return VL_CIK_HIER;
if (key == "limit") return VL_CIK_LIMIT;
if (key == "lineno") return VL_CIK_LINENO;
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
if (key == "row0") return VL_CIK_ROW0;
if (key == "row0_name") return VL_CIK_ROW0_NAME;
if (key == "row1") return VL_CIK_ROW1;
if (key == "row1_name") return VL_CIK_ROW1_NAME;
if (key == "row2") return VL_CIK_ROW2;
if (key == "row2_name") return VL_CIK_ROW2_NAME;
if (key == "row3") return VL_CIK_ROW3;
if (key == "row3_name") return VL_CIK_ROW3_NAME;
if (key == "table") return VL_CIK_TABLE;
if (key == "thresh") return VL_CIK_THRESH;
if (key == "type") return VL_CIK_TYPE;
if (key == "weight") return VL_CIK_WEIGHT;
// VLCOVGEN_SHORT_AUTO_EDIT_END
return key;
}
};
+562 -100
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -16,8 +16,8 @@
/// \file
/// \brief Verilator: DPI implementation code
///
/// This file must be compiled and linked against all objects
/// created from Verilator or called by Verilator that use the DPI.
/// This file must be compiled and linked against all objects
/// created from Verilator or called by Verilator that use the DPI.
///
/// Code available from: http://www.veripool.org/verilator
///
@@ -44,9 +44,12 @@
#define _VL_SVDPI_UNIMP() \
VL_FATAL_MT(__FILE__,__LINE__,"",(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
#define _VL_SVDPI_WARN(message...) \
VL_PRINTF_MT(message)
// Function requires a "context" in the import declaration
#define _VL_SVDPI_CONTEXT_WARN() \
VL_PRINTF_MT("%%Warning: DPI C Function called by Verilog DPI import with missing 'context' keyword.\n");
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing 'context' keyword.\n");
//======================================================================
//======================================================================
@@ -61,196 +64,655 @@ const char* svDpiVersion() {
// Bit-select utility functions.
svBit svGetBitselBit(const svBitVecVal* sp, int bit) {
return VL_BITISSET_W(sp,bit);
return VL_BITRSHIFT_W(sp,bit) & 1;
}
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
_VL_SVDPI_UNIMP(); return 0;
// Not VL_BITRSHIFT_W as sp is a different structure type
// Verilator doesn't support X/Z so only aval
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1)<<1));
}
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
VL_ASSIGNBIT_WI(32, bit, dp, s);
}
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
_VL_SVDPI_UNIMP();
// Verilator doesn't support X/Z so only aval
dp[VL_BITWORD_I(bit)].aval
= ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| ((s&1)<<VL_BITBIT_I(bit)));
dp[VL_BITWORD_I(bit)].bval
= ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| ((s&2)>>1<<VL_BITBIT_I(bit)));
}
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int i, int w) {
_VL_SVDPI_UNIMP();
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
// See also VL_SEL_WWI
int msb = lsb+width-1;
int word_shift = VL_BITWORD_I(lsb);
if (VL_BITBIT_I(lsb)==0) {
// Just a word extract
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
} else {
int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(msb-lsb+1);
for (int i=0; i<words; ++i) {
dp[i] = sp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
dp[i] |= sp[upperword] << nbitsfromlow;
}
}
}
// Clean result
dp[VL_WORDS_I(width)-1] &= VL_MASK_I(width);
}
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int i, int w) {
_VL_SVDPI_UNIMP();
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
int msb = lsb+width-1;
int word_shift = VL_BITWORD_I(lsb);
if (VL_BITBIT_I(lsb)==0) {
// Just a word extract
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
} else {
int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(msb-lsb+1);
for (int i=0; i<words; ++i) {
dp[i].aval = sp[i+word_shift].aval >> loffset;
dp[i].bval = sp[i+word_shift].bval >> loffset;
int upperword = i+word_shift+1;
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
dp[i].aval |= sp[upperword].aval << nbitsfromlow;
dp[i].bval |= sp[upperword].bval << nbitsfromlow;
}
}
}
// Clean result
dp[VL_WORDS_I(width)-1].aval &= VL_MASK_I(width);
dp[VL_WORDS_I(width)-1].bval &= VL_MASK_I(width);
}
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
// See also _VL_INSERT_WI
int hbit = lbit+width-1;
int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit);
if (hoffset==VL_SIZEBITS_I && loffset==0) {
// Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)] = s;
}
else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
} else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
int nbitsonright = 32-loffset; // bits that end up in lword
dp[lword] = (dp[lword] & ~linsmask) | ((s<<loffset) & linsmask);
dp[hword] = (dp[hword] & ~hinsmask) | ((s>>nbitsonright) & hinsmask);
}
}
}
// cppcheck-suppress passedByValue
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
int hbit = lbit+width-1;
int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit);
if (hoffset==VL_SIZEBITS_I && loffset==0) {
// Fast and common case, word based insertion
dp[VL_BITWORD_I(lbit)].aval = s.aval;
dp[VL_BITWORD_I(lbit)].bval = s.bval;
}
else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
} else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
int nbitsonright = 32-loffset; // bits that end up in lword
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval<<loffset) & linsmask);
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval<<loffset) & linsmask);
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval>>nbitsonright) & hinsmask);
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval>>nbitsonright) & hinsmask);
}
}
}
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int i, int w) {
_VL_SVDPI_UNIMP();
}
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int i, int w) {
_VL_SVDPI_UNIMP();
//======================================================================
// Open array internals
static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
if (VL_UNLIKELY(!h)) {
VL_FATAL_MT(__FILE__, __LINE__, "",
"%%Error: DPI svOpenArrayHandle function called with NULL handle");
}
const VerilatedDpiOpenVar* varp = reinterpret_cast<const VerilatedDpiOpenVar*>(h);
if (VL_UNLIKELY(!varp->magicOk())) {
VL_FATAL_MT(__FILE__, __LINE__, "",
"%%Error: DPI svOpenArrayHandle function called with non-Verilator handle");
}
return varp;
}
//======================================================================
// Open array querying functions
int svLeft(const svOpenArrayHandle h, int d) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_openhandle_varp(h)->left(d);
}
int svRight(const svOpenArrayHandle h, int d) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_openhandle_varp(h)->right(d);
}
int svLow(const svOpenArrayHandle h, int d) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_openhandle_varp(h)->low(d);
}
int svHigh(const svOpenArrayHandle h, int d) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_openhandle_varp(h)->high(d);
}
int svIncrement(const svOpenArrayHandle h, int d) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_openhandle_varp(h)->increment(d);
}
int svSize(const svOpenArrayHandle h, int d) {
return _vl_openhandle_varp(h)->elements(d);
}
int svDimensions(const svOpenArrayHandle h) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_openhandle_varp(h)->udims();
}
void *svGetArrayPtr(const svOpenArrayHandle) {
_VL_SVDPI_UNIMP(); return NULL;
/// Return pointer to open array data, or NULL if not in IEEE standard C layout
void* svGetArrayPtr(const svOpenArrayHandle h) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
return varp->datap();
}
int svSizeOfArray(const svOpenArrayHandle) {
_VL_SVDPI_UNIMP(); return 0;
}
void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...) {
_VL_SVDPI_UNIMP(); return NULL;
}
void *svGetArrElemPtr1(const svOpenArrayHandle, int indx1) {
_VL_SVDPI_UNIMP(); return NULL;
}
void *svGetArrElemPtr2(const svOpenArrayHandle, int indx1, int indx2) {
_VL_SVDPI_UNIMP(); return NULL;
}
void *svGetArrElemPtr3(const svOpenArrayHandle, int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP(); return NULL;
/// Return size of open array, or 0 if not in IEEE standard C layout
int svSizeOfArray(const svOpenArrayHandle h) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return 0;
// Truncate 64 bits to int; DPI is limited to 4GB
return static_cast<int>(varp->totalSize());
}
//======================================================================
// s=source, d=destination
// From user space into simulator storage
// Open array access internals
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
int nargs, int indx1, int indx2, int indx3) {
void* datap = varp->datap();
if (VL_UNLIKELY(nargs != varp->udims())) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
" %d dimensional array using %d dimensional function.\n",
varp->udims(), nargs);
return NULL;
}
if (nargs>=1) {
datap = varp->datapAdjustIndex(datap, 1, indx1);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 out of bounds; %d outside [%d:%d].\n",
indx1, varp->left(1), varp->right(1));
return NULL;
}
}
if (nargs>=2) {
datap = varp->datapAdjustIndex(datap, 2, indx2);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 out of bounds; %d outside [%d:%d].\n",
indx2, varp->left(2), varp->right(2));
return NULL;
}
}
if (nargs>=3) {
datap = varp->datapAdjustIndex(datap, 3, indx3);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 out of bounds; %d outside [%d:%d].\n",
indx1, varp->left(3), varp->right(3));
return NULL;
}
}
return datap;
}
static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d outside [%d:%d].\n",
indx, varp->left(0), varp->right(0));
return 0;
}
return indx - varp->low(0);
}
/// Return pointer to simulator open array element, or NULL if outside range
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
return datap;
}
/// Copy to user bit array from simulator open array
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
case VLVT_UINT64: {
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0] = lwp[0]; d[1] = lwp[1];
break;
}
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
return;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
return;
}
}
/// Copy to user logic array from simulator open array
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: d[0].aval = *(reinterpret_cast<CData*>(datap)); d[0].bval=0; return;
case VLVT_UINT16: d[0].aval = *(reinterpret_cast<SData*>(datap)); d[0].bval=0; return;
case VLVT_UINT32: d[0].aval = *(reinterpret_cast<IData*>(datap)); d[0].bval=0; return;
case VLVT_UINT64: {
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
d[0].aval = lwp[0]; d[0].bval=0;
d[1].aval = lwp[1]; d[0].bval=0;
break;
}
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) {
d[i].aval = wdatap[i]; d[i].bval = 0;
}
return;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
return;
}
}
/// Copy to simulator open array from from user bit array
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); break;
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
return;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
return;
}
}
/// Copy to simulator open array from from user logic array
static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval); break;
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
return;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
return;
}
}
/// Return bit from simulator open array
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s,
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
// One extra index supported, as need bit number
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
void* datap;
int lsb;
if (varp->packed().elements()) {
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
: (nargs==2) ? indx2
: (nargs==3) ? indx3
: indx4));
} else {
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
lsb = 0;
}
if (VL_UNLIKELY(!datap)) return 0;
switch (varp->vltype()) {
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(datap)) >> lsb) & 1;
case VLVT_UINT64: return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
return VL_BITRSHIFT_W(wdatap, lsb) & 1;
}
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
return 0;
}
}
/// Update simulator open array from bit
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value,
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
// One extra index supported, as need bit number
value &= 1; // Make sure clean
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
void* datap;
int lsb;
if (varp->packed().elements()) {
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
: (nargs==2) ? indx2
: (nargs==3) ? indx3
: indx4));
} else {
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
lsb = 0;
}
if (VL_UNLIKELY(!datap)) return;
switch (varp->vltype()) {
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
default:
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
return;
}
}
//======================================================================
// DPI accessors that simply call above functions
void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
void* datap;
va_list ap;
va_start(ap, indx1);
// va_arg is a macro, so need temporaries as used below
switch (varp->udims()) {
case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3); break; }
default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
return datap;
}
void* svGetArrElemPtr1(const svOpenArrayHandle h, int indx1) {
return _vl_svGetArrElemPtr(h, 1, indx1, 0, 0);
}
void* svGetArrElemPtr2(const svOpenArrayHandle h, int indx1, int indx2) {
return _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
}
void* svGetArrElemPtr3(const svOpenArrayHandle h, int indx1, int indx2, int indx3) {
return _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
}
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1, ...) {
_VL_SVDPI_UNIMP();
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1) {
_VL_SVDPI_UNIMP();
int indx1) {
_vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1, int indx2) {
_VL_SVDPI_UNIMP();
int indx1, int indx2) {
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP();
int indx1, int indx2, int indx3) {
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1, ...) {
_VL_SVDPI_UNIMP();
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1) {
_VL_SVDPI_UNIMP();
int indx1) {
_vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1, int indx2) {
_VL_SVDPI_UNIMP();
int indx1, int indx2) {
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP();
int indx1, int indx2, int indx3) {
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
//======================================================================
// From simulator storage into user space
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1, ...) {
_VL_SVDPI_UNIMP();
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1) {
_VL_SVDPI_UNIMP();
int indx1) {
_vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2) {
_VL_SVDPI_UNIMP();
int indx1, int indx2) {
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP();
int indx1, int indx2, int indx3) {
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, ...) {
_VL_SVDPI_UNIMP();
int indx1, ...) {
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1) {
_VL_SVDPI_UNIMP();
int indx1) {
_vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
}
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2) {
_VL_SVDPI_UNIMP();
int indx1, int indx2) {
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
}
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP();
int indx1, int indx2, int indx3) {
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
}
svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
_VL_SVDPI_UNIMP(); return 0;
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
svBit out;
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
return out;
}
svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0);
}
svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
}
svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP(); return 0;
return _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
}
svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
_VL_SVDPI_UNIMP(); return sv_x;
// Verilator doesn't support X/Z so can just call Bit version
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
svBit out;
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
return out;
}
svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1) {
_VL_SVDPI_UNIMP(); return sv_x;
// Verilator doesn't support X/Z so can just call Bit version
return svGetBitArrElem1(s, indx1);
}
svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2) {
_VL_SVDPI_UNIMP(); return sv_x;
// Verilator doesn't support X/Z so can just call Bit version
return svGetBitArrElem2(s, indx1, indx2);
}
svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP(); return sv_x;
}
void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) {
_VL_SVDPI_UNIMP();
}
void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
_VL_SVDPI_UNIMP();
}
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
_VL_SVDPI_UNIMP();
}
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP();
// Verilator doesn't support X/Z so can just call Bit version
return svGetBitArrElem3(s, indx1, indx2, indx3);
}
void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
_VL_SVDPI_UNIMP();
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1) {
_VL_SVDPI_UNIMP();
_vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0);
}
void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1, int indx2) {
_VL_SVDPI_UNIMP();
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
}
void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1, int indx2, int indx3) {
_VL_SVDPI_UNIMP();
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
}
void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) {
// Verilator doesn't support X/Z so can just call Bit version
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
va_list ap;
va_start(ap, indx1);
switch (varp->udims()) {
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
case 2: { int indx2=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
}
void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
// Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem1(d, value, indx1);
}
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
// Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem2(d, value, indx1, indx2);
}
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2, int indx3) {
// Verilator doesn't support X/Z so can just call Bit version
svPutBitArrElem3(d, value, indx1, indx2, indx3);
}
//======================================================================
@@ -277,7 +739,7 @@ svScope svGetScopeFromName(const char* scopeName) {
return (svScope)VerilatedImp::scopeFind(scopeName);
}
int svPutUserData(const svScope scope, void *userKey, void* userData) {
int svPutUserData(const svScope scope, void* userKey, void* userData) {
VerilatedImp::userInsert(scope,userKey,userData);
return 0;
}
+24 -7
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -28,36 +28,53 @@
#ifndef _VERILATED_DPI_H_
#define _VERILATED_DPI_H_ 1 ///< Header Guard
#include "verilated.h" // Presumed done by caller
#include "verilated.h" // Also presumably included by caller
#include "verilated_sym_props.h"
#include "svdpi.h"
//===================================================================
// SETTING OPERATORS
/// Return svBitVecVal from WData
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) VL_MT_SAFE {
/// Return WData from svBitVecVal
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
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);
}
/// Return svBitVecVal from WData
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE {
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) VL_MT_SAFE {
// Note we ignore X/Z in svLogicVecVal
/// Convert svLogicVecVal to/from WData
/// Note these functions ignore X/Z in svLogicVecVal
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
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 QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1].aval, lwp[0].aval);
}
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
return lwp[0].aval;
}
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE {
// 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);
}
static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, IData ld) VL_MT_SAFE {
owp[0].aval=ld; owp[0].bval=0;
}
static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, QData ld) VL_MT_SAFE {
WData lwp[2]; VL_SET_WQ(lwp,ld);
owp[0].aval=lwp[0]; owp[0].bval=0;
owp[1].aval=lwp[1]; owp[1].bval=0;
}
//======================================================================
+12 -5
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2010-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -56,15 +56,22 @@ inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData
for (unsigned times=0; times<rep; ++times) out += lhs;
return out;
}
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const std::string& lhs, IData rep) VL_PURE {
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits,
const std::string& lhs, IData rep) VL_PURE {
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
}
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const std::string& ofilename, void* memp, IData start, IData end) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
const std::string& ofilename,
void* memp, IData start, IData end) VL_MT_SAFE;
extern void VL_WRITEMEM_N(bool hex, int width, int depth, int array_lsb,
const std::string& ofilename,
const void* memp, IData start, IData end) VL_MT_SAFE;
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...) VL_MT_SAFE;
extern void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...) VL_MT_SAFE;
extern void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE;
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rdp) VL_MT_SAFE;
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE {
+45 -95
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2018 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.
@@ -49,25 +49,25 @@ class VerilatedScope;
// Threaded message passing
#ifdef VL_THREADED
/// Message, enqueued on a train, and consumed on the main eval thread
/// Message, enqueued on an mtask, and consumed on the main eval thread
class VerilatedMsg {
public:
// TYPES
struct Cmp {
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) {
return a.trainId() < b.trainId(); }
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) const {
return a.mtaskId() < b.mtaskId(); }
};
private:
// MEMBERS
vluint32_t m_trainId; ///< Train that did enqueue
vluint32_t m_mtaskId; ///< MTask that did enqueue
std::function<void()> m_cb; ///< Lambda to execute when message received
public:
// CONSTRUCTORS
VerilatedMsg(const std::function<void()>& cb)
: m_trainId(Verilated::trainId()), m_cb(cb) {}
: m_mtaskId(Verilated::mtaskId()), m_cb(cb) {}
~VerilatedMsg() {}
// METHODS
vluint32_t trainId() const { return m_trainId; }
vluint32_t mtaskId() const { return m_mtaskId; }
/// Execute the lambda function
void run() const { m_cb(); }
};
@@ -84,7 +84,9 @@ class VerilatedEvalMsgQueue {
VerilatedThreadQueue m_queue VL_GUARDED_BY(m_mutex); ///< Message queue
public:
// CONSTRUCTORS
VerilatedEvalMsgQueue() : m_depth(0) { }
VerilatedEvalMsgQueue() : m_depth(0) {
assert(atomic_is_lock_free(&m_depth));
}
~VerilatedEvalMsgQueue() { }
private:
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
@@ -92,8 +94,7 @@ public:
// METHODS
//// Add message to queue (called by producer)
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
Verilated::endOfEvalReqdInc(); // No mutex, threadsafe
VerilatedLockGuard guard(m_mutex);
VerilatedLockGuard lock(m_mutex);
m_queue.insert(msg); // Pass by value to copy the message into queue
++m_depth;
}
@@ -114,10 +115,9 @@ public:
m_queue.erase(it);
m_mutex.unlock();
m_depth--; // Ok if outside critical section as only this code checks the value
Verilated::endOfEvalReqdDec(); // No mutex, threadsafe
{
VL_DEBUG_IF(VL_DBG_MSGF("Executing callback from trainId=%d\n", msg.trainId()););
msg.run();
VL_DEBUG_IF(VL_DBG_MSGF("Executing callback from mtaskId=%d\n", msg.mtaskId()););
msg.run();
}
}
}
@@ -143,8 +143,15 @@ private:
public:
/// Add message to queue, called by producer
static void post(const VerilatedMsg& msg) VL_MT_SAFE {
Verilated::endOfEvalReqdInc();
threadton().m_queue.push(msg); // Pass by value to copy the message into queue
// Handle calls to threaded routines outside
// of any mtask -- if an initial block calls $finish, say.
if (Verilated::mtaskId() == 0) {
// No queueing, just do the action immediately
msg.run();
} else {
Verilated::endOfEvalReqdInc();
threadton().m_queue.push(msg); // Pass by value to copy the message into queue
}
}
/// Push all messages to the eval's queue
static void flush(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
@@ -192,15 +199,10 @@ class VerilatedImp {
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex); ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
// Threads
VerilatedMutex m_threadMutex; ///< Protect m_numThreads, etc
bool m_spawned VL_GUARDED_BY(m_threadMutex); ///< Already called spawnThreads()
unsigned m_numThreads VL_GUARDED_BY(m_threadMutex); ///< Number of threads user requested, 0x0=all cpus
public: // But only for verilated*.cpp
// CONSTRUCTORS
VerilatedImp()
: m_argVecLoaded(false), m_exportNext(0), m_spawned(false), m_numThreads(0) {
: m_argVecLoaded(false), m_exportNext(0) {
m_fdps.resize(3);
m_fdps[0] = stdin;
m_fdps[1] = stdout;
@@ -210,33 +212,16 @@ public: // But only for verilated*.cpp
private:
VL_UNCOPYABLE(VerilatedImp);
public:
static void internalsDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_argMutex);
VL_PRINTF_MT("internalsDump:\n");
VL_PRINTF_MT(" Argv:");
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
VL_PRINTF_MT(" %s",it->c_str());
}
VL_PRINTF_MT("\n");
VL_PRINTF_MT(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
scopesDump();
exportsDump();
userDump();
}
// METHODS - debug
static void internalsDump() VL_MT_SAFE;
static void versionDump() VL_MT_SAFE;
// METHODS - arguments
public:
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard guard(s_s.m_argMutex);
s_s.m_argVec.clear(); // Always clear
commandArgsAddGuts(argc, argv);
}
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard guard(s_s.m_argMutex);
commandArgsAddGuts(argc, argv);
}
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.m_argMutex) {
VerilatedLockGuard guard(s_s.m_argMutex);
VerilatedLockGuard lock(s_s.m_argMutex);
// Note prefixp does not include the leading "+"
size_t len = strlen(prefixp);
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
@@ -253,11 +238,7 @@ public:
return "";
}
private:
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex) {
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
for (int i=0; i<argc; ++i) s_s.m_argVec.push_back(argv[i]);
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
}
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
public:
// METHODS - user scope tracking
@@ -265,14 +246,14 @@ public:
// There's often many more scopes than userdata's and thus having a ~48byte
// per map overhead * N scopes would take much more space and cache thrashing.
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_userMapMutex);
VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
if (it != s_s.m_userMap.end()) it->second = userData;
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep,userKey),userData));
}
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_userMapMutex);
VerilatedLockGuard lock(s_s.m_userMapMutex);
UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
else return NULL;
@@ -281,7 +262,7 @@ private:
/// Symbol table destruction cleans up the entries for each scope.
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope on destruction, so we simply iterate.
VerilatedLockGuard guard(s_s.m_userMapMutex);
VerilatedLockGuard lock(s_s.m_userMapMutex);
for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ) {
if (it->first.first == scopep) {
s_s.m_userMap.erase(it++);
@@ -291,7 +272,7 @@ private:
}
}
static void userDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_userMapMutex); // Avoid it changing in middle of dump
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
bool first = true;
for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; }
@@ -304,27 +285,27 @@ public: // But only for verilated*.cpp
// METHODS - scope name
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at construction
VerilatedLockGuard guard(s_s.m_nameMutex);
VerilatedLockGuard lock(s_s.m_nameMutex);
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
if (it == s_s.m_nameMap.end()) {
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(),scopep));
}
}
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT
VerilatedLockGuard lock(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT
VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep);
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
else return NULL;
}
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at destruction
VerilatedLockGuard guard(s_s.m_nameMutex);
VerilatedLockGuard lock(s_s.m_nameMutex);
userEraseScope(scopep);
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
}
static void scopesDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_nameMutex);
VerilatedLockGuard lock(s_s.m_nameMutex);
VL_PRINTF_MT(" scopesDump:\n");
for (VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
const VerilatedScope* scopep = it->second;
@@ -348,7 +329,7 @@ public: // But only for verilated*.cpp
// miss at the cost of a multiply, and all lookups move to slowpath.
static int exportInsert(const char* namep) VL_MT_SAFE {
// Slow ok - called once/function at creation
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
if (it == s_s.m_exportMap.end()) {
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
@@ -358,7 +339,7 @@ public: // But only for verilated*.cpp
}
}
static int exportFind(const char* namep) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
ExportNameMap::const_iterator it=s_s.m_exportMap.find(namep);
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
std::string msg = (std::string("%Error: Testbench C called ")+namep
@@ -368,14 +349,14 @@ public: // But only for verilated*.cpp
}
static const char* exportName(int funcnum) VL_MT_SAFE {
// Slowpath; find name for given export; errors only so no map to reverse-map it
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
if (it->second == funcnum) return it->first;
}
return "*UNKNOWN*";
}
static void exportsDump() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_exportMutex);
VerilatedLockGuard lock(s_s.m_exportMutex);
bool first = true;
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; }
@@ -390,7 +371,7 @@ public: // But only for verilated*.cpp
static IData fdNew(FILE* fp) VL_MT_SAFE {
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
VerilatedLockGuard guard(s_s.m_fdMutex);
VerilatedLockGuard lock(s_s.m_fdMutex);
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();
@@ -403,7 +384,7 @@ public: // But only for verilated*.cpp
}
static void fdDelete(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;
VerilatedLockGuard guard(s_s.m_fdMutex);
VerilatedLockGuard lock(s_s.m_fdMutex);
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;
@@ -411,41 +392,10 @@ public: // But only for verilated*.cpp
}
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
IData idx = VL_MASK_I(31) & fdi;
VerilatedLockGuard guard(s_s.m_fdMutex); // This might get slow, if it does we can cache it
VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
return s_s.m_fdps[idx];
}
public: // But only for verilated*.cpp
// METHODS - Threading
static void numThreads(unsigned threads) VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_threadMutex);
if (!s_s.m_spawned) s_s.m_numThreads = threads;
}
static unsigned numThreads() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_threadMutex);
#ifdef VL_THREADED
unsigned threads = s_s.m_numThreads;
if (threads == 0x0) {
threads = std::thread::hardware_concurrency(); // Or 0=unknown, C++11
}
if (threads<1) threads = 1;
return threads;
#else
return 0;
#endif
}
static void spawnThreads() VL_MT_SAFE {
VerilatedLockGuard guard(s_s.m_threadMutex);
if (!s_s.m_spawned) {
// Convert numThreads from 0 to the spawned number
numThreads(numThreads());
s_s.m_spawned = true;
#ifdef VL_THREADED
// THREADED-TODO startup threads
#endif
}
}
};
//======================================================================
+1 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
+3 -2
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2012-2017 by Wilson Snyder. This program is free software;
// Copyright 2012-2018 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.
//
@@ -138,7 +138,8 @@ public:
}
// Read a datum and compare with expected value
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE { return readAssert(&data, sizeof(data)); }
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE {
return readAssert(&data, sizeof(data)); }
private:
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2018 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.
+224
View File
@@ -0,0 +1,224 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2018 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 provide information about symbol inspection
///
/// This file is for inclusion by internal files that need to inspect
/// specific symbols.
///
/// User routines wanting to inspect the symbol table should use
/// verilated_syms.h instead.
///
/// These classes are thread safe, and read only.
///
/// Code available from: http://www.veripool.org/verilator
///
//*************************************************************************
#ifndef _VERILATED_SYM_PROPS_H_
#define _VERILATED_SYM_PROPS_H_ 1 ///< Header Guard
//===========================================================================
/// Verilator range
/// Thread safety: Assume is constructed only with model, then any number of readers
// See also V3Ast::VNumRange
class VerilatedRange {
int m_left;
int m_right;
protected:
friend class VerilatedVarProps;
friend class VerilatedScope;
VerilatedRange() : m_left(0), m_right(0) {}
VerilatedRange(int left, int right) : m_left(left), m_right(right) {}
void init(int left, int right) { m_left=left; m_right=right; }
public:
~VerilatedRange() {}
int left() const { return m_left; }
int right() const { return m_right; }
int low() const { return (m_left < m_right) ? m_left : m_right; }
int high() const { return (m_left > m_right) ? m_left : m_right; }
int elements() const {
return (VL_LIKELY(m_left>=m_right) ? (m_left-m_right+1) : (m_right-m_left+1)); }
int increment() const { return (m_left >= m_right) ? 1 : -1; }
};
//===========================================================================
/// Verilator variable
/// Thread safety: Assume is constructed only with model, then any number of readers
class VerilatedVarProps {
// TYPES
enum { MAGIC = 0xddc4f829 };
// MEMBERS
const vluint32_t m_magic; // Magic number
const VerilatedVarType m_vltype; // Data type
const VerilatedVarFlags m_vlflags; // Direction
const int m_pdims; // Packed dimensions
const int m_udims; // Unpacked dimensions
VerilatedRange m_packed; // Packed array range
VerilatedRange m_unpacked[3]; // Unpacked array range
// CONSTRUCTORS
protected:
friend class VerilatedScope;
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags,
int pdims, int udims)
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(vlflags), m_pdims(pdims), m_udims(udims) {}
public:
class Unpacked {};
// Without packed
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) { }
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) {
m_unpacked[0].init(u0l, u0r); }
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); }
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); }
// With packed
class Packed {};
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) { }
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr,
Unpacked, int u0l, int u0r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) {
m_unpacked[0].init(u0l, u0r); }
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr,
Unpacked, int u0l, int u0r, int u1l, int u1r)
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)),
m_pdims(1), m_udims(2), m_packed(pl,pr) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); }
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
Packed, int pl, int pr,
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
: m_magic(MAGIC), m_vltype(vltype),
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) {
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); }
public:
~VerilatedVarProps() {}
// METHODS
bool magicOk() const { return m_magic==MAGIC; }
VerilatedVarType vltype() const { return m_vltype; }
VerilatedVarFlags vldir() const {
return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR); }
vluint32_t entSize() const;
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
/// DPI compatible C standard layout
bool isDpiCLayout() const { return ((m_vlflags & VLVF_DPI_CLAY) != 0); }
int udims() const { return m_udims; }
int dims() const { return m_pdims + m_udims; }
const VerilatedRange& packed() const { return m_packed; }
const VerilatedRange& unpacked() const { return m_unpacked[0]; }
// DPI accessors
int left(int dim) const {
return dim==0 ? m_packed.left() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].left() : 0;
}
int right(int dim) const {
return dim==0 ? m_packed.right() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].right() : 0;
}
int low(int dim) const {
return dim==0 ? m_packed.low() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].low() : 0;
}
int high(int dim) const {
return dim==0 ? m_packed.high() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].high() : 0;
}
int increment(int dim) const {
return dim==0 ? m_packed.increment() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].increment() : 0;
}
int elements(int dim) const {
return dim==0 ? m_packed.elements() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].elements() : 0;
}
/// Total size in bytes (note DPI limited to 4GB)
size_t totalSize() const;
/// Adjust a data pointer to access a given array element, NuLL if something goes bad
void* datapAdjustIndex(void* datap, int dim, int indx) const;
};
//===========================================================================
/// Verilator DPI open array variable
class VerilatedDpiOpenVar {
// MEMBERS
const VerilatedVarProps* m_propsp; // Variable properties
void* m_datap; // Location of data (local to thread always, so safe)
public:
// CONSTRUCTORS
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap)
: m_propsp(propsp), m_datap(datap) {}
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
: m_propsp(propsp), m_datap(const_cast<void*>(datap)) {}
~VerilatedDpiOpenVar() {}
// METHODS
void* datap() const { return m_datap; }
// METHODS - from VerilatedVarProps
bool magicOk() const { return m_propsp->magicOk(); }
VerilatedVarType vltype() const { return m_propsp->vltype(); }
bool isDpiStdLayout() const { return m_propsp->isDpiCLayout(); }
const VerilatedRange& packed() const { return m_propsp->packed(); }
const VerilatedRange& unpacked() const { return m_propsp->unpacked(); }
int udims() const { return m_propsp->udims(); }
int left(int dim) const { return m_propsp->left(dim); }
int right(int dim) const { return m_propsp->right(dim); }
int low(int dim) const { return m_propsp->low(dim); }
int high(int dim) const { return m_propsp->high(dim); }
int increment(int dim) const { return m_propsp->increment(dim); }
int elements(int dim) const { return m_propsp->elements(dim); }
size_t totalSize() const { return m_propsp->totalSize(); }
void* datapAdjustIndex(void* datap, int dim, int indx) const {
return m_propsp->datapAdjustIndex(datap, dim, indx); }
};
//===========================================================================
/// Verilator variable
/// Thread safety: Assume is constructed only with model, then any number of readers
class VerilatedVar : public VerilatedVarProps {
// MEMBERS
void* m_datap; // Location of data
const char* m_namep; // Name - slowpath
protected:
friend class VerilatedScope;
// CONSTRUCTORS
VerilatedVar(const char* namep, void* datap,
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
: VerilatedVarProps(vltype, vlflags, (dims>0?1:0), ((dims>1)?dims-1:0))
, m_datap(datap), m_namep(namep) {}
public:
~VerilatedVar() {}
// ACCESSORS
void* datap() const { return m_datap; }
const VerilatedRange& range() const { return packed(); } // Deprecated
const VerilatedRange& array() const { return unpacked(); } // Deprecated
const char* name() const { return m_namep; }
};
#endif // Guard
+12 -59
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
@@ -16,12 +16,12 @@
/// \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.
/// This file is for inclusion by files that need to inspect the symbol
/// table. It is not included in verilated.h (instead see
/// verilated_sym_props.h) as it requires some heavyweight C++ classes.
///
/// These classes are thread safe on read only. It is constructed
/// only when a model is built (from the main thread).
/// These classes are thread safe and read only. It is constructed only
/// when a model is built (from the main thread).
///
/// Code available from: http://www.veripool.org/verilator
///
@@ -31,70 +31,22 @@
#ifndef _VERILATED_SYMS_H_
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
#include "verilated_sym_props.h"
#include "verilated_heavy.h"
#include <map>
//===========================================================================
/// Verilator range
/// Thread safety: Assume is constructed only with model, then any number of readers
// See also V3Ast::VNumRange
class VerilatedRange {
int m_left;
int m_right;
protected:
friend class VerilatedVar;
friend class VerilatedScope;
VerilatedRange() : m_left(0), m_right(0) {}
void sets(int left, int right) { m_left=left; m_right=right; }
public:
~VerilatedRange() {}
int left() const { return m_left; }
int right() const { return m_right; }
int elements() const { return (VL_LIKELY(m_left>=m_right)?(m_left-m_right+1):(m_right-m_left+1)); }
};
//===========================================================================
/// Verilator variable
/// Thread safety: Assume is constructed only with model, then any number of readers
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 static_cast<VerilatedVarFlags>(static_cast<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
/// Class to sort maps keyed by const char*'s
struct VerilatedCStrCmp {
/// Ordering maps keyed by const char*'s
bool operator() (const char *a, const char *b) const {
return std::strcmp(a, b) < 0;
return std::strcmp(a, b) < 0;
}
};
/// Map of sorted scope names to find associated scope class
class VerilatedScopeNameMap
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
public:
@@ -102,6 +54,7 @@ public:
~VerilatedScopeNameMap() {}
};
/// Map of sorted variable names to find associated variable class
class VerilatedVarNameMap
: public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
public:
+10 -8
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 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.
//
@@ -61,18 +61,18 @@ private:
static Singleton& singleton() { static Singleton s; return s; }
public:
static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
VerilatedLockGuard guard(singleton().s_vcdMutex);
VerilatedLockGuard lock(singleton().s_vcdMutex);
singleton().s_vcdVecp.push_back(vcdp);
}
static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
VerilatedLockGuard guard(singleton().s_vcdMutex);
VerilatedLockGuard lock(singleton().s_vcdMutex);
VcdVec::iterator pos = find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), vcdp);
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
}
static void flush_all() VL_EXCLUDES(singleton().s_vcdMutex) VL_MT_UNSAFE_ONE {
// Thread safety: Although this function is protected by a mutex so perhaps
// in the future we can allow tracing in separate threads, vcdp->flush() assumes call from single thread
VerilatedLockGuard guard(singleton().s_vcdMutex);
VerilatedLockGuard lock(singleton().s_vcdMutex);
for (VcdVec::const_iterator it=singleton().s_vcdVecp.begin(); it!=singleton().s_vcdVecp.end(); ++it) {
VerilatedVcd* vcdp = *it;
vcdp->flush();
@@ -343,7 +343,7 @@ void VerilatedVcd::bufferResize(vluint64_t minsize) {
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
m_writep = m_wrBufp + (m_writep - oldbufp);
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
delete oldbufp; oldbufp=NULL;
delete [] oldbufp; oldbufp=NULL;
}
}
@@ -382,12 +382,14 @@ void VerilatedVcd::bufferFlush () VL_MT_UNSAFE_ONE {
// Simple methods
void VerilatedVcd::set_time_unit (const char* unitp) {
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeUnit = timescaleToDouble(unitp);
}
void VerilatedVcd::set_time_resolution (const char* unitp) {
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
m_timeRes = timescaleToDouble(unitp);
}
@@ -567,7 +569,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
sprintf(buf, " %2d ", bits);
decl += buf;
if (m_evcd) {
sprintf(buf, "<%d", code);
sprintf(buf, "<%u", code);
decl += buf;
} else {
decl += stringCode(code);
+1 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 by Wilson Snyder. This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
+6 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 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.
//
@@ -39,6 +39,11 @@ void VerilatedVcdSc::trace (const unsigned int &, const std::string &, const cha
# define DECL_TRACE_METHOD_B(tp) \
void VerilatedVcdSc::trace( const tp& object, const std::string& name, int width ) {}
#if (SYSTEMC_VERSION>=20171012)
DECL_TRACE_METHOD_A( sc_event )
DECL_TRACE_METHOD_A( sc_time )
#endif
DECL_TRACE_METHOD_A( bool )
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
DECL_TRACE_METHOD_A( sc_dt::sc_logic )
+6 -1
View File
@@ -3,7 +3,7 @@
//
// THIS MODULE IS PUBLICLY LICENSED
//
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
// Copyright 2001-2018 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.
//
@@ -96,6 +96,11 @@ private:
virtual void write_comment (const std::string &);
virtual void trace (const unsigned int &, const std::string &, const char **);
#if (SYSTEMC_VERSION>=20171012)
DECL_TRACE_METHOD_A( sc_event )
DECL_TRACE_METHOD_A( sc_time )
#endif
DECL_TRACE_METHOD_A( bool )
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
DECL_TRACE_METHOD_A( sc_dt::sc_logic )
+86 -52
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2018 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.
@@ -91,7 +91,8 @@ public:
t_freeHead = oldp;
}
// MEMBERS
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
static inline VerilatedVpio* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
inline vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
// ACCESSORS
virtual const char* name() const { return "<null>"; }
@@ -117,7 +118,8 @@ public:
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
static inline VerilatedVpioCb* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiCallback; }
vluint32_t reason() const { return m_cbData.reason; }
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
@@ -130,7 +132,8 @@ class VerilatedVpioConst : public VerilatedVpio {
public:
explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
virtual ~VerilatedVpioConst() {}
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
static inline VerilatedVpioConst* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiUndefined; }
vlsint32_t num() const { return m_num; }
};
@@ -141,7 +144,8 @@ class VerilatedVpioRange : public VerilatedVpio {
public:
explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
virtual ~VerilatedVpioRange() {}
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
static inline VerilatedVpioRange* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiRange; }
virtual vluint32_t size() const { return m_range->elements(); }
virtual const VerilatedRange* rangep() const { return m_range; }
@@ -164,7 +168,8 @@ public:
explicit VerilatedVpioScope(const VerilatedScope* scopep)
: m_scopep(scopep) {}
virtual ~VerilatedVpioScope() {}
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
static inline VerilatedVpioScope* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiScope; }
const VerilatedScope* scopep() const { return m_scopep; }
virtual const char* name() const { return m_scopep->name(); }
@@ -185,20 +190,21 @@ protected:
vlsint32_t m_index;
const VerilatedRange& get_range() const {
// Determine number of dimensions and return outermost
return (m_varp->dims()>1) ? m_varp->array() : m_varp->range();
return (m_varp->dims()>1) ? m_varp->unpacked() : m_varp->packed();
}
public:
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
: m_varp(varp), m_scopep(scopep), m_index(0) {
m_prevDatap = NULL;
m_mask.u32 = VL_MASK_I(varp->range().elements());
m_mask.u32 = VL_MASK_I(varp->packed().elements());
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); }
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.u32; }
@@ -236,10 +242,11 @@ public:
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
}
virtual ~VerilatedVpioMemoryWord() {}
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiMemoryWord; }
virtual vluint32_t size() const { return varp()->range().elements(); }
virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
virtual vluint32_t size() const { return varp()->packed().elements(); }
virtual const VerilatedRange* rangep() const { return &(varp()->packed()); }
virtual const char* fullname() const {
static VL_THREAD_LOCAL std::string out;
char num[20]; sprintf(num,"%d",m_index);
@@ -256,7 +263,8 @@ public:
explicit VerilatedVpioVarIter(const VerilatedScope* scopep)
: m_scopep(scopep), m_started(false) { }
virtual ~VerilatedVpioVarIter() {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
static inline VerilatedVpioVarIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiIterator; }
virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) {
@@ -281,12 +289,16 @@ class VerilatedVpioMemoryWordIter : public VerilatedVpio {
bool m_done;
public:
VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp)
: m_handle(handle), m_varp(varp), m_iteration(varp->array().right()), m_direction(VL_LIKELY(varp->array().left()>varp->array().right())?1:-1), m_done(false) { }
: m_handle(handle), m_varp(varp), m_iteration(varp->unpacked().right()),
m_direction(VL_LIKELY(varp->unpacked().left() > varp->unpacked().right())
? 1 : -1),
m_done(false) { }
virtual ~VerilatedVpioMemoryWordIter() {}
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
virtual vluint32_t type() const { return vpiIterator; }
void iterationInc() {
if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction;
if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration+=m_direction;
}
virtual vpiHandle dovpi_scan() {
vpiHandle result;
@@ -337,7 +349,9 @@ public:
varop->createPrevDatap();
}
}
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large");
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) {
VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large");
}
s_s.m_cbObjLists[vop->reason()].push_back(vop);
}
static void cbTimedAdd(VerilatedVpioCb* vop) {
@@ -459,11 +473,12 @@ public:
m_errorInfo.level = level;
return this;
}
void setMessage(std::string file, PLI_INT32 line, std::string message, ...) {
void setMessage(std::string file, PLI_INT32 line, const char* message, ...) {
// message cannot be a const string& as va_start cannot use a reference
static VL_THREAD_LOCAL std::string filehold;
va_list args;
va_start(args, message);
VL_VSNPRINTF(m_buff, sizeof(m_buff), message.c_str(), args);
VL_VSNPRINTF(m_buff, sizeof(m_buff), message, args);
va_end(args);
m_errorInfo.state = vpiPLI;
filehold = file;
@@ -921,7 +936,8 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
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_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n",cb_data_p->reason,vop,time););
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n",
cb_data_p->reason, vop, time););
VerilatedVpiImp::cbTimedAdd(vop);
return vop->castVpiHandle();
}
@@ -1015,15 +1031,17 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
_VL_VPI_ERROR_RESET(); // reset vpi error status
if (VL_LIKELY(varop)) {
if (varop->varp()->dims()<2) return 0;
if (VL_LIKELY(varop->varp()->array().left() >= varop->varp()->array().right())) {
if (VL_UNLIKELY(indx > varop->varp()->array().left() || indx < varop->varp()->array().right())) return 0;
if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) {
if (VL_UNLIKELY(indx > varop->varp()->unpacked().left()
|| indx < varop->varp()->unpacked().right())) return 0;
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().right()))
indx - varop->varp()->unpacked().right()))
->castVpiHandle();
} else {
if (VL_UNLIKELY(indx < varop->varp()->array().left() || indx > varop->varp()->array().right())) return 0;
if (VL_UNLIKELY(indx < varop->varp()->unpacked().left()
|| indx > varop->varp()->unpacked().right())) return 0;
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
indx - varop->varp()->array().left()))
indx - varop->varp()->unpacked().left()))
->castVpiHandle();
}
} else {
@@ -1206,7 +1224,8 @@ void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
// value processing
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination
// Maximum required size is for binary string, one byte per bit plus null termination
static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32];
// cppcheck-suppress variableScope
static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1;
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n",object););
@@ -1235,7 +1254,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
out[0].bval = 0;
return;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().elements());
int words = VL_WORDS_I(vop->varp()->packed().elements());
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
VL_FATAL_MT(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
}
@@ -1268,14 +1287,16 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bits = vop->varp()->range().elements();
int bits = vop->varp()->packed().elements();
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
int i;
if (bits > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
bits = outStrSz;
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
}
for (i=0; i<bits; ++i) {
char val = (datap[i>>3]>>(i&7))&1;
@@ -1286,7 +1307,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
}
default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname());
return;
}
} else if (value_p->format == vpiOctStrVal) {
@@ -1297,14 +1319,16 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().elements()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int chars = (vop->varp()->packed().elements()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
int i;
if (chars > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
}
for (i=0; i<chars; ++i) {
@@ -1320,7 +1344,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
if (i==(chars-1)) {
// most signifcant char, mask off non existant bits when vector
// size is not a multiple of 3
unsigned int rem = vop->varp()->range().elements() % 3;
unsigned int rem = vop->varp()->packed().elements() % 3;
if (rem) {
// generate bit mask & zero non existant bits
val &= (1<<rem)-1;
@@ -1363,13 +1387,15 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().elements()+3)>>2;
int chars = (vop->varp()->packed().elements()+3)>>2;
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
int i;
if (chars > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
}
for (i=0; i<chars; ++i) {
@@ -1377,7 +1403,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
if (i==(chars-1)) {
// most signifcant char, mask off non existant bits when vector
// size is not a multiple of 4
unsigned int rem = vop->varp()->range().elements() & 3;
unsigned int rem = vop->varp()->packed().elements() & 3;
if (rem) {
// generate bit mask & zero non existant bits
val &= (1<<rem)-1;
@@ -1401,12 +1427,13 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
int i;
if (bytes > outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes);
bytes = outStrSz;
@@ -1478,7 +1505,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n",
vop->varp()->datap(), vop->varDatap()););
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: ", vop->fullname());
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only,"
" use public_flat_rw instead: ",
vop->fullname());
return 0;
}
if (value_p->format == vpiVectorVal) {
@@ -1494,7 +1523,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
*(reinterpret_cast<IData*>(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
return object;
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().elements());
int words = VL_WORDS_I(vop->varp()->packed().elements());
WDataOutP datap = (reinterpret_cast<IData*>(vop->varDatap()));
for (int i=0; i<words; ++i) {
datap[i] = value_p->value.vector[i].aval;
@@ -1523,7 +1552,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bits = vop->varp()->range().elements();
int bits = vop->varp()->packed().elements();
int len = strlen(value_p->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
for (int i=0; i<bits; ++i) {
@@ -1550,8 +1579,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().elements()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int chars = (vop->varp()->packed().elements()+2)/3;
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
int len = strlen(value_p->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
div_t idx;
@@ -1615,7 +1644,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
}
if (success > 1) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s",
VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
VL_FUNC, remainder, value_p->value.str,
VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname());
}
switch (vop->varp()->vltype()) {
case VLVT_UINT8 : *(reinterpret_cast<CData*>(vop->varDatap())) = val & vop->mask(); break;
@@ -1637,7 +1668,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int chars = (vop->varp()->range().elements()+3)>>2;
int chars = (vop->varp()->packed().elements()+3)>>2;
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
char* val = value_p->value.str;
// skip hex ident if one is detected at the start of the string
@@ -1655,7 +1686,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10;
else {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non hex character '%c' in '%s' as value %s for %s",
VL_FUNC, digit, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
VL_FUNC, digit, value_p->value.str,
VerilatedVpiError::strFromVpiVal(value_p->format),
vop->fullname());
hex = 0;
}
} else {
@@ -1684,11 +1717,12 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
case VLVT_UINT64:
case VLVT_WDATA: {
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
int len = strlen(value_p->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
for (int i=0; i<bytes; ++i) {
datap[i] = (i < len)?value_p->value.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes
// prepend with 0 values before placing string the least signifcant bytes
datap[i] = (i < len)?value_p->value.str[len-i-1]:0;
}
return object;
}
+1 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2009-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
+38 -1
View File
@@ -1,7 +1,7 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -353,6 +353,43 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# define VL_ROUND(n) round(n)
#endif
//=========================================================================
// Performance counters
/// The vluint64_t argument is loaded with a high-performance counter for profiling
/// or 0x0 if not implemeted on this platform
#if defined(__i386__) || defined(__x86_64__)
# define VL_RDTSC(val) { \
vluint32_t hi, lo; \
asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); \
(val) = ((vluint64_t)lo) | (((vluint64_t)hi)<<32); \
}
#elif defined(__aarch64__)
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r" (val));
#else
// We just silently ignore unknown OSes, as only leads to missing statistics
# define VL_RDTSC(val) (val) = 0;
#endif
//=========================================================================
// Threading related OS-specific functions
#if VL_THREADED
# if defined(__i386__) || defined(__x86_64__)
/// For more efficient busy waiting on SMT CPUs, let the processor know
/// we're just waiting so it can let another thread run
# define VL_CPU_RELAX() asm volatile("rep; nop" ::: "memory")
# elif defined(__ia64__)
# define VL_CPU_RELAX() asm volatile("hint @pause" ::: "memory")
# elif defined(__aarch64__)
# define VL_CPU_RELAX() asm volatile("yield" ::: "memory")
# elif defined(__powerpc64__)
# define VL_CPU_RELAX() asm volatile("or 1, 1, 1; or 2, 2, 2;" ::: "memory")
# else
# error "Missing VL_CPU_RELAX() definition. Or, don't use VL_THREADED"
# endif
#endif
//=========================================================================
#endif /*guard*/
+22 -22
View File
@@ -7,7 +7,7 @@
* This file contains the constant definitions, structure definitions,
* and routine declarations used by SystemVerilog DPI.
*
* This file is from the SystemVerilog IEEE 1800-2012 Annex I.
* This file is from the SystemVerilog IEEE 1800-2017 Annex I.
*/
#ifndef INCLUDED_SVDPI
@@ -117,7 +117,7 @@ typedef uint32_t svBitVecVal;
/*
* Return implementation version information string ("1800-2005" or "SV3.1a").
*/
XXTERN const char* svDpiVersion();
XXTERN const char* svDpiVersion( void );
/* a handle to a scope (an instance of a module or interface) */
XXTERN typedef void* svScope;
@@ -155,7 +155,7 @@ XXTERN void svGetPartselBit(svBitVecVal* d, const svBitVecVal* s, int i, int w);
XXTERN void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
XXTERN void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w);
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal s, int i, int w);
/*
* Open array querying functions
@@ -241,28 +241,28 @@ XXTERN void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s
XXTERN void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
int indx1, int indx2, int indx3);
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
int indx3);
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
...);
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2);
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
int indx2, int indx3);
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
int indx2);
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
int indx2, int indx3);
/* Functions for working with DPI context */
@@ -273,7 +273,7 @@ XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1
* is the scope of the function's declaration site, not call site.
* Returns NULL if called from C code that is *not* an imported function.
*/
XXTERN svScope svGetScope();
XXTERN svScope svGetScope( void );
/*
* Set context for subsequent export function execution.
@@ -337,7 +337,7 @@ XXTERN int svGetCallerInfo(const char** fileName, int *lineNumber);
* Returns 1 if the current execution thread is in the disabled state.
* Disable protocol must be adhered to if in the disabled state.
*/
XXTERN int svIsDisabledState();
XXTERN int svIsDisabledState( void );
/*
* Imported functions call this API function during disable processing to
@@ -345,7 +345,7 @@ XXTERN int svIsDisabledState();
* This function must be called before returning from an imported function that is
* in the disabled state.
*/
XXTERN void svAckDisabledState();
XXTERN void svAckDisabledState( void );
/*
**********************************************************
+3 -3
View File
@@ -1,7 +1,7 @@
/*******************************************************************************
* vpi_user.h
*
* IEEE Std 1800-2012 Programming Language Interface (PLI)
* IEEE Std 1800-2017 Programming Language Interface (PLI)
*
* This file contains the constant definitions, structure definitions, and
* routine declarations used by the SystemVerilog Verification Procedural
@@ -251,7 +251,7 @@ typedef PLI_UINT32 *vpiHandle;
#define vpiModPathOut 96 /* output terminal of a module path */
#define vpiOperand 97 /* operand of expression */
#define vpiPortInst 98 /* connected port instance */
#define vpiProcess 99 /* process in module */
#define vpiProcess 99 /* process in module, program or interface */
#define vpiVariables 100 /* variables in module */
#define vpiUse 101 /* usage */
@@ -978,7 +978,7 @@ XXTERN vpiHandle vpi_handle_by_multi_index PROTO_PARAMS((vpiHandle obj,
/****************************** GLOBAL VARIABLES ******************************/
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])();
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])( void );
/* array of function pointers, last pointer should be null */
+2 -2
View File
@@ -749,7 +749,7 @@ File a bug (if there isn't already) so others know what you're working on.
=item 2.
Make a testcase in the test_regress/t/t_EXAMPLE format, see L<TESTING>.
Make a testcase in the test_regress/t/t_EXAMPLE format, see L</TESTING>.
=item 3.
@@ -785,7 +785,7 @@ in C<src/Makefile_obj.in> and reconfigure.
The latest version is available from L<http://www.veripool.org/>.
Copyright 2008-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2008-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
# Copyright 2007-2018 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
# Copyright 2007-2018 by Wilson Snyder. This package is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
# Copyright 2007-2018 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.
+177
View File
@@ -0,0 +1,177 @@
#!/usr/bin/perl -w
# See copyright, etc in below POD section.
######################################################################
use Getopt::Long;
#use Data::Dumper; $Data::Dumper::Indent=1; $Data::Dumper::Sortkeys=1; #Debug
use IO::File;
use IO::Dir;
use Pod::Usage;
use strict;
use vars qw ($Debug);
our $VERSION = '0.001';
#======================================================================
# main
autoflush STDOUT 1;
autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
if (! GetOptions (
"debug" => sub { $Debug = 1; },
"help" => sub { print "Version $VERSION\n";
pod2usage(-verbose=>2, -exitval => 2, output=>\*STDOUT, -noperldoc=>1); },
"version" => sub { print "Version $VERSION\n"; exit(0); },
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
)) {
die "%Error: Bad usage, try 'git_untabify --help'\n";
}
read_patch();
#######################################################################
sub read_patch {
my $filename = undef;
my $lineno = 0;
my $editlines = {};
while (defined(my $line = <STDIN>)) {
if ($line =~ m!^\+\+\+ b/(.*)!) {
edit_file($filename, $editlines);
$filename = $1;
$lineno = 0;
$editlines = {};
print "FILE $filename\n" if $Debug;
}
elsif ($line =~ m!^@@ -?[0-9]+,?[0-9]* \+?([0-9]+)!) {
$lineno = $1 - 1;
print " LINE $1 $line" if $Debug;
}
elsif ($line =~ m!^ !) {
++$lineno;
}
elsif ($line =~ m!^\+!) {
++$lineno;
if ($line =~ m!\t!) {
print " $lineno: $line" if $Debug;
$editlines->{$lineno} = 1;
}
}
}
edit_file($filename, $editlines);
}
sub edit_file {
my $filename = shift;
my $editlines = shift;
return if (scalar keys(%$editlines) < 1);
if (ignore($filename)) {
print "%Warning: Ignoring $filename\n";
return;
}
print "Edit $filename ",join(",",sort(keys %$editlines)),"\n";
my $lineno = 0;
my @out;
{
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
while (defined(my $line = $fh->getline)) {
++$lineno;
if ($editlines->{$lineno}) {
print $line;
push @out, untabify($line);
} else {
push @out, $line;
}
}
$fh->close;
}
{
my $fh = IO::File->new(">${filename}.untab") or die "%Error: $! ${filename}.untab,";
$fh->print(join('',@out));
$fh->close;
my ($dev,$ino,$mode) = stat($filename);
chmod $mode, "${filename}.untab";
}
rename("${filename}.untab", $filename) or die "%Error: $! ${filename}.untab,";
}
sub ignore {
my $filename = shift;
return 1 if ($filename =~ /(Makefile|\.mk)/);
return 1 if ($filename =~ /\.(y|l|out|vcd)$/);
#
return 0 if ($filename =~ /\.(sv|v|vh|svh|h|vc|cpp|pl)$/);
return 0;
}
sub untabify {
my $line = shift;
my $out = "";
my $col = 0;
foreach my $c (split //, $line) {
if ($c eq "\t") {
my $destcol = int(($col+8)/8)*8;
while ($col < $destcol) { ++$col; $out .= " "; }
} else {
$out .= $c;
$col++;
}
}
return $out;
}
#######################################################################
__END__
=pod
=head1 NAME
git_untabify - Pipe a git diff report and untabify differences
=head1 SYNOPSIS
git diff a..b | git_untabify
=head1 DESCRIPTION
Take a patch file, and edit the files in the destination patch list to
untabify the related patch lines.
=head1 ARGUMENTS
=over 4
=item --help
Displays this message and program version and exits.
=item --version
Displays program version and exits.
=back
=head1 DISTRIBUTION
Copyright 2005-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./git_untabify "
### End:
+4 -4
View File
@@ -100,14 +100,14 @@ sub write_verilog {
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('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(' top->eval();' ,"\n");
$fh->print(' main_time++;' ,"\n");
$fh->print(' }' ,"\n");
$fh->print(' top->final();' ,"\n");
$fh->print('}' ,"\n");
@@ -184,7 +184,7 @@ Runs a specific test stage (see the script).
=head1 DISTRIBUTION
Copyright 2009-2017 by Wilson Snyder. This package is free software; you
Copyright 2009-2018 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
Copyright 2005-2018 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1 -1
View File
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2007-2017 by Wilson Snyder. This package is free software; you
Copyright 2007-2018 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+2 -2
View File
@@ -8,7 +8,7 @@ use strict;
#======================================================================
# main
eval `modulecmd perl add cds-ius`;
eval `modulecmd perl add cds-ius/latest`;
exec('ncverilog',@ARGV);
#######################################################################
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
Copyright 2005-2018 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+2 -2
View File
@@ -8,7 +8,7 @@ use strict;
#======================================================================
# main
eval `modulecmd perl add synopsys-sim`;
eval `modulecmd perl add synopsys-sim/latest`;
exec('vcs',@ARGV);
#######################################################################
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
=head1 DISTRIBUTION
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
Copyright 2005-2018 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
+1 -1
View File
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
=head1 DISTRIBUTION
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
Copyright 2005-2018 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
+1 -1
View File
@@ -1,6 +1,6 @@
# DESCRIPTION: Verilator: GDB startup file with useful defines
#
# Copyright 2012-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2012-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
+1 -1
View File
@@ -7,7 +7,7 @@
#
#*****************************************************************************
#
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
# Copyright 2003-2018 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.
+8 -4
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -174,11 +174,13 @@ private:
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
nodep->v3warn(INITIALDLY, "Delayed assignments (<=) in initial"
" or final block; suggest blocking assignments (=).");
} else if (m_check == CT_LATCH) {
// Suppress. Shouldn't matter that the interior of the latch races
} else {
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked"
" (non flop or latch) block; suggest blocking assignments (=).");
}
AstNode* newp = new AstAssign (nodep->fileline(),
nodep->lhsp()->unlinkFrBack(),
@@ -437,6 +439,8 @@ public:
void V3Active::activeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveVisitor visitor (nodep);
{
ActiveVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+4 -2
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -159,6 +159,8 @@ public:
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveTopVisitor visitor (nodep);
{
ActiveTopVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+35 -10
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -88,11 +88,17 @@ private:
return newp;
}
AstNode* newFireAssert(AstNode* nodep, const string& message) {
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
// Like newFireAssert() but omits the asserts-on check
AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop (nodep->fileline()));
return bodysp;
}
AstNode* newFireAssert(AstNode* nodep, const string& message) {
AstNode* bodysp = newFireAssertUnchecked(nodep, message);
bodysp = newIfAssertOn(bodysp);
return bodysp;
}
@@ -105,7 +111,9 @@ private:
//
AstNode* bodysp = NULL;
bool selfDestruct = false;
AstIf* ifp = NULL;
if (AstPslCover* snodep = nodep->castPslCover()) {
++m_statAsCover;
if (!v3Global.opt.coverageUser()) {
selfDestruct = true;
} else {
@@ -116,14 +124,30 @@ private:
if (message!="") covincp->declp()->comment(message);
bodysp = covincp;
}
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
} else if (nodep->castPslAssert()) {
++m_statAsPsl;
// Insert an automatic error message and $stop after
// any user-supplied statements.
AstNode* autoMsgp = newFireAssertUnchecked(nodep, "'assert property' failed.");
if (stmtsp) {
stmtsp->addNext(autoMsgp);
} else {
stmtsp = autoMsgp;
}
ifp = new AstIf(nodep->fileline(), propp, NULL, stmtsp);
// It's more LIKELY that we'll take the NULL if clause
// than the sim-killing else clause:
ifp->branchPred(AstBranchPred::BP_LIKELY);
bodysp = newIfAssertOn(ifp);
} else {
nodep->v3fatalSrc("Unknown node type");
}
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
//
AstNode* newp = new AstAlways (nodep->fileline(),
VAlwaysKwd::ALWAYS,
sentreep,
@@ -294,12 +318,11 @@ private:
}
}
virtual void visit(AstPslCover* nodep) {
virtual void visit(AstNodePslCoverOrAssert* nodep) {
nodep->iterateChildren(*this);
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep);
++m_statAsCover;
}
virtual void visit(AstVAssert* nodep) {
nodep->iterateChildren(*this);
@@ -349,6 +372,8 @@ public:
void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertVisitor visitor (nodep);
{
AssertVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2018 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.
+5 -3
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2018 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.
@@ -86,7 +86,7 @@ private:
pushDeletep(nodep); VL_DANGLING(nodep);
}
virtual void visit(AstPslCover* nodep) {
virtual void visit(AstNodePslCoverOrAssert* nodep) {
if (nodep->sentreep()) return; // Already processed
clearAssertInfo();
nodep->iterateChildren(*this);
@@ -136,6 +136,8 @@ public:
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertPreVisitor visitor (nodep);
{
AssertPreVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2005-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+33 -22
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -229,7 +229,8 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
// Called on all major tree changers.
// Only for use for those really nasty bugs relating to internals
// Note this may be null.
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "
// <<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
//if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// // Commenting out the section below may crash, as the tree state
@@ -290,8 +291,8 @@ void AstNode::addNextHere(AstNode* newp) {
// This could be at head, tail, or both (single)
// New could be head of single node, or list
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
UASSERT(newp,"Null item passed to addNext");
UASSERT(newp->backp()==NULL,"New node (back) already assigned?");
UASSERT(newp, "Null item passed to addNext");
UASSERT(!newp->backp(), "New node (back) already assigned?");
this->debugTreeChange("-addHereThs: ", __LINE__, false);
newp->debugTreeChange("-addHereNew: ", __LINE__, true);
newp->editCountInc();
@@ -334,7 +335,7 @@ void AstNode::addNextHere(AstNode* newp) {
}
void AstNode::setOp1p(AstNode* newp) {
UASSERT(newp,"Null item passed to setOp1p\n");
UASSERT(newp, "Null item passed to setOp1p");
UDEBUGONLY(if (m_op1p) this->v3fatalSrc("Adding to non-empty, non-list op1"););
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1"););
@@ -347,7 +348,7 @@ void AstNode::setOp1p(AstNode* newp) {
}
void AstNode::setOp2p(AstNode* newp) {
UASSERT(newp,"Null item passed to setOp2p\n");
UASSERT(newp, "Null item passed to setOp2p");
UDEBUGONLY(if (m_op2p) this->v3fatalSrc("Adding to non-empty, non-list op2"););
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2"););
@@ -360,7 +361,7 @@ void AstNode::setOp2p(AstNode* newp) {
}
void AstNode::setOp3p(AstNode* newp) {
UASSERT(newp,"Null item passed to setOp3p\n");
UASSERT(newp, "Null item passed to setOp3p");
UDEBUGONLY(if (m_op3p) this->v3fatalSrc("Adding to non-empty, non-list op3"););
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3"););
@@ -373,7 +374,7 @@ void AstNode::setOp3p(AstNode* newp) {
}
void AstNode::setOp4p(AstNode* newp) {
UASSERT(newp,"Null item passed to setOp4p\n");
UASSERT(newp, "Null item passed to setOp4p");
UDEBUGONLY(if (m_op4p) this->v3fatalSrc("Adding to non-empty, non-list op4"););
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4"););
@@ -386,25 +387,25 @@ void AstNode::setOp4p(AstNode* newp) {
}
void AstNode::addOp1p(AstNode* newp) {
UASSERT(newp,"Null item passed to addOp1p\n");
UASSERT(newp, "Null item passed to addOp1p");
if (!m_op1p) { op1p(newp); }
else { m_op1p->addNext(newp); }
}
void AstNode::addOp2p(AstNode* newp) {
UASSERT(newp,"Null item passed to addOp2p\n");
UASSERT(newp, "Null item passed to addOp2p");
if (!m_op2p) { op2p(newp); }
else { m_op2p->addNext(newp); }
}
void AstNode::addOp3p(AstNode* newp) {
UASSERT(newp,"Null item passed to addOp3p\n");
UASSERT(newp, "Null item passed to addOp3p");
if (!m_op3p) { op3p(newp); }
else { m_op3p->addNext(newp); }
}
void AstNode::addOp4p(AstNode* newp) {
UASSERT(newp,"Null item passed to addOp4p\n");
UASSERT(newp, "Null item passed to addOp4p");
if (!m_op4p) { op4p(newp); }
else { m_op4p->addNext(newp); }
}
@@ -430,7 +431,7 @@ void AstNRelinker::dump(ostream& str) const {
AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) {
this->debugTreeChange("-unlinkWNextThs: ", __LINE__, true);
AstNode* oldp = this;
UASSERT(oldp->m_backp,"Node has no back, already unlinked?\n");
UASSERT(oldp->m_backp, "Node has no back, already unlinked?");
oldp->editCountInc();
AstNode* backp = oldp->m_backp;
if (linkerp) {
@@ -478,7 +479,7 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) {
AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) {
this->debugTreeChange("-unlinkFrBkThs: ", __LINE__, true);
AstNode* oldp = this;
UASSERT(oldp->m_backp,"Node has no back, already unlinked?\n");
UASSERT(oldp->m_backp, "Node has no back, already unlinked?");
oldp->editCountInc();
AstNode* backp = oldp->m_backp;
if (linkerp) {
@@ -530,8 +531,8 @@ AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) {
void AstNode::relink(AstNRelinker* linkerp) {
if (debug()>8) { UINFO(0," EDIT: relink: "); dumpPtrs(); }
AstNode* newp = this;
UASSERT(linkerp && linkerp->m_backp, "Need non-empty linker\n");
UASSERT(newp->backp()==NULL, "New node already linked?\n");
UASSERT(linkerp && linkerp->m_backp, "Need non-empty linker");
UASSERT(!newp->backp(), "New node already linked?");
newp->editCountInc();
if (debug()>8) { linkerp->dump(cout); cout<<endl; }
@@ -667,7 +668,7 @@ AstNode* AstNode::cloneTree(bool cloneNextLink) {
void AstNode::deleteNode() {
// private: Delete single node. Publicly call deleteTree() instead.
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
UASSERT(!m_backp, "Delete called on node with backlink still set");
editCountInc();
// Change links of old node so we coredump if used
this->m_nextp = (AstNode*)1;
@@ -677,9 +678,17 @@ void AstNode::deleteNode() {
this->m_op2p = (AstNode*)1;
this->m_op3p = (AstNode*)1;
this->m_op4p = (AstNode*)1;
if (
#if !defined(VL_DEBUG) || defined(VL_LEAK_CHECKS)
delete this; // Leak massively, so each pointer is unique and we can debug easier
1
#else
!v3Global.opt.debugLeak()
#endif
) {
delete this;
}
// Else leak massively, so each pointer is unique
// and we can debug easier.
}
AstNode::~AstNode() {
@@ -704,7 +713,7 @@ void AstNode::deleteTreeIter() {
void AstNode::deleteTree() {
// deleteTree always deletes the next link, because you must have called
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
UASSERT(!m_backp, "Delete called on node with backlink still set");
this->debugTreeChange("-delTree: ", __LINE__, true);
this->editCountInc();
// MUST be depth first!
@@ -779,7 +788,9 @@ void AstNode::iterateAndNext(AstNVisitor& v) {
niterp->m_iterpp = &niterp;
niterp->accept(v);
// accept may do a replaceNode and change niterp on us...
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
// niterp maybe NULL, so need cast if printing
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep
// <<" now into "<<(void*)niterp<<endl);
if (!niterp) return; // Perhaps node deleted inside accept
niterp->m_iterpp = NULL;
if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept
@@ -1037,8 +1048,8 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
if (doDump) {
{ // Write log & close
UINFO(2,"Dumping "<<filename<<endl);
const vl_unique_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
const vl_unique_ptr<std::ofstream> logsp (V3File::new_ofstream(filename, append));
if (logsp->fail()) v3fatal("Can't write "<<filename);
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
if (editCountGbl()==editCountLast()
+96 -43
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -167,7 +167,7 @@ class AstEdgeType {
public:
// REMEMBER to edit the strings below too
enum en {
// These must be in general -> most specific order, as we sort by it in V3Const::visit AstSenTre
// These must be in general -> most specific order, as we sort by it in V3Const::visit AstSenTree
ET_ILLEGAL,
// Involving a variable
ET_ANYEDGE, // Default for sensitivities; rip them out
@@ -364,8 +364,8 @@ public:
return names[m_e];
};
static void selfTest() {
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"),"Enum array mismatch");
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"), "SelfTest: Enum mismatch");
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"SelfTest: Enum mismatch");
}
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
// cppcheck-suppress noExplicitConstructor
@@ -418,11 +418,21 @@ public:
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
return (m_e==LOGIC || m_e==BIT);
}
bool isDpiUnsupported() const {
return (m_e==TIME);
bool isDpiBitVal() const { // DPI uses svBitVecVal
return m_e==BIT;
}
bool isDpiLogicVal() const { // DPI uses svLogicVecVal
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT || m_e==TIME;
}
bool isDpiUnreturnable() const { // Not legal as DPI function return
return isDpiLogicVal();
}
bool isDpiUnsignable() const { // Can add "unsigned" to DPI
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
}
bool isDpiCLayout() const { // Uses standard C layout, for DPI runtime access
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT
|| m_e==LONGINT || m_e==DOUBLE || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64);
}
bool isOpaque() const { // IE not a simple number we can bit optimize
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
@@ -881,14 +891,18 @@ public:
class AstNVisitor {
private:
vector<AstNode*> m_deleteps; // Nodes to delete when we are finished
vector<AstNode*> m_deleteps; // Nodes to delete when doDeletes() called
protected:
friend class AstNode;
public:
// Cleaning
/// At the end of the visitor (or doDeletes()), delete this pushed node
/// along with all children and next(s). This is often better to use
/// than an immediate deleteTree, as any pointers into this node will
/// persist for the lifetime of the visitor
void pushDeletep(AstNode* nodep) {
m_deleteps.push_back(nodep);
}
/// Call deleteTree on all previously pushDeletep()'ed nodes
void doDeletes();
public:
virtual ~AstNVisitor() {
@@ -1087,7 +1101,8 @@ public:
AstNode* op4p() const { return m_op4p; }
AstNodeDType* dtypep() const { return m_dtypep; }
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
AstNode* firstAbovep() const { // Returns NULL when second or later in list
return ((backp() && backp()->nextp()!=this) ? backp() : NULL); }
bool brokeExists() const;
bool brokeExistsAbove() const;
@@ -1273,12 +1288,13 @@ public:
static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
void addNextHere(AstNode* newp); // Adds after speced node
void addNextHere(AstNode* newp); // Insert newp at this->nextp
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
void replaceWith(AstNode* newp); // Replace current node in tree with new node
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
// Unlink this from whoever points to it, keep entire next list with unlinked node
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL);
void swapWith(AstNode* bp);
void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead
void cloneRelinkNode() { cloneRelink(); }
@@ -1307,17 +1323,20 @@ public:
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 isGateDedupable() const { return isGateOptimizable(); } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
virtual bool isGateDedupable() const { return isGateOptimizable(); }
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 isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed
virtual bool isUnlikely() const { return false; } // Else $stop or similar statement which means an above IF statement is unlikely to be taken
// isUnlikely handles $stop or similar statement which means an above IF statement is unlikely to be taken
virtual bool isUnlikely() const { return false; }
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
virtual bool same(const AstNode*) const { return true; }
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
// Another AstNode* may have a pointer into this node, other then normal front/back/etc.
virtual bool maybePointedTo() const { return false; }
virtual const char* broken() const { return NULL; }
// INVOKERS
@@ -1440,7 +1459,9 @@ public:
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
void thsp(AstNode* nodep) { return setOp3p(nodep); }
// METHODS
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) = 0; // Set out to evaluation of a AstConst'ed
// Set out to evaluation of a AstConst'ed
virtual void numberOperate(V3Number& out, const V3Number& lhs,
const V3Number& rhs, const V3Number& ths) = 0;
virtual bool cleanLhs() = 0; // True if LHS must have extra upper bits zero
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero
virtual bool cleanThs() = 0; // True if THS must have extra upper bits zero
@@ -1713,6 +1734,7 @@ public:
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
virtual AstNodeDType* subDTypep() const { return NULL; } // Iff has a non-null subDTypep(), as generic node function
virtual bool isFourstate() const;
//
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
@@ -1725,7 +1747,8 @@ public:
bool isNosign() const { return m_numeric.isNosign(); }
AstNumeric numeric() const { return m_numeric; }
int widthWords() const { return VL_WORDS_I(width()); }
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
int widthMin() const { // If sized, the size, if unsized the min digits to represent it
return m_widthMin?m_widthMin:m_width; }
int widthPow2() const;
void widthMinFromWidth() { m_widthMin = m_width; }
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
@@ -1735,6 +1758,7 @@ public:
pair<uint32_t,uint32_t> dimensions(bool includeBasic);
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
static int uniqueNumInc() { return ++s_uniqueNum; }
const char* charIQWN() const { return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); }
};
class AstNodeClassDType : public AstNodeDType {
@@ -1743,19 +1767,23 @@ private:
typedef map<string,AstMemberDType*> MemberNameMap;
// MEMBERS
bool m_packed;
bool m_isFourstate;
MemberNameMap m_members;
public:
AstNodeClassDType(FileLine* fl, AstNumeric numericUnpack)
: AstNodeDType(fl) {
// AstNumeric::NOSIGN overloaded to indicate not packed
m_packed = (numericUnpack != AstNumeric::NOSIGN);
m_isFourstate = false; // V3Width computes
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
}
ASTNODE_BASE_FUNCS(NodeClassDType)
virtual const char* broken() const;
virtual void dump(ostream& str);
// For basicp() we reuse the size to indicate a "fake" basic type of same size
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
virtual AstBasicDType* basicp() const {
return (isFourstate() ? findLogicDType(width(),width(),numeric())->castBasicDType()
: findBitDType(width(),width(),numeric())->castBasicDType()); }
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
@@ -1769,6 +1797,8 @@ public:
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
bool packed() const { return m_packed; }
bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs
void isFourstate(bool flag) { m_isFourstate = flag; }
virtual bool isFourstate() const { return m_isFourstate; }
void clearCache() { m_members.clear(); }
void repairMemberCache();
AstMemberDType* findMember(const string& name) const {
@@ -1867,21 +1897,24 @@ class AstNodeFTask : public AstNode {
private:
string m_name; // Name of task
string m_cname; // Name of task if DPI import
uint64_t m_dpiOpenParent; // DPI import open array, if !=0, how many callees
bool m_taskPublic:1; // Public task
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_prototype:1; // Just a prototype
bool m_dpiExport:1; // DPI exported
bool m_dpiImport:1; // DPI imported
bool m_dpiContext:1; // DPI import context
bool m_dpiOpenChild:1; // DPI import open array child wrapper
bool m_dpiTask:1; // DPI import task (vs. void function)
bool m_pure:1; // DPI import pure
public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline)
, m_name(name), m_taskPublic(false)
, m_name(name)
, m_dpiOpenParent(0), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false)
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
, m_dpiTask(false), m_pure(false) {
, m_dpiOpenChild(false), m_dpiTask(false), m_pure(false) {
addNOp3p(stmtsp);
cname(name); // Might be overridden by dpi import/export
}
@@ -1903,23 +1936,29 @@ public:
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
// op4 = scope name
AstScopeName* scopeNamep() const { return op4p()->castScopeName(); }
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; }
bool prototype() const { return m_prototype; }
void dpiExport(bool flag) { m_dpiExport = flag; }
bool dpiExport() const { return m_dpiExport; }
void dpiImport(bool flag) { m_dpiImport = flag; }
bool dpiImport() const { return m_dpiImport; }
void dpiContext(bool flag) { m_dpiContext = flag; }
bool dpiContext() const { return m_dpiContext; }
void dpiTask(bool flag) { m_dpiTask = flag; }
bool dpiTask() const { return m_dpiTask; }
void pure(bool flag) { m_pure = flag; }
bool pure() const { return m_pure; }
// MORE ACCESSORS
void dpiOpenParentInc() { ++m_dpiOpenParent; }
void dpiOpenParentClear() { m_dpiOpenParent=0; }
uint64_t dpiOpenParent() const { return m_dpiOpenParent; }
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; }
bool prototype() const { return m_prototype; }
void dpiExport(bool flag) { m_dpiExport = flag; }
bool dpiExport() const { return m_dpiExport; }
void dpiImport(bool flag) { m_dpiImport = flag; }
bool dpiImport() const { return m_dpiImport; }
void dpiContext(bool flag) { m_dpiContext = flag; }
bool dpiContext() const { return m_dpiContext; }
void dpiOpenChild(bool flag) { m_dpiOpenChild = flag; }
bool dpiOpenChild() const { return m_dpiOpenChild; }
void dpiTask(bool flag) { m_dpiTask = flag; }
bool dpiTask() const { return m_dpiTask; }
void pure(bool flag) { m_pure = flag; }
bool pure() const { return m_pure; }
};
class AstNodeFTaskRef : public AstNode {
@@ -1927,7 +1966,7 @@ class AstNodeFTaskRef : public AstNode {
private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
string m_name; // Name of variable
string m_dotted; // Dotted part of scope to task or ""
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
AstPackage* m_packagep; // Package hierarchy
public:
@@ -2027,6 +2066,13 @@ public:
bool recursiveClone() const { return m_recursiveClone; }
};
class AstNodeRange : public AstNode {
// A range, sized or unsized
public:
explicit AstNodeRange(FileLine* fl) : AstNode (fl) { }
ASTNODE_BASE_FUNCS(NodeRange)
};
//######################################################################
#include "V3AstNodes.h"
@@ -2040,11 +2086,16 @@ public:
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
inline bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
inline bool AstNode::width1() const { // V3Const uses to know it can optimize
return dtypep() && dtypep()->width()==1; }
inline int AstNode::widthInstrs() const {
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
inline bool AstNode::isDouble() const {
return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
inline bool AstNode::isString() const {
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
inline bool AstNode::isSigned() const {
return dtypep() && dtypep()->isSigned(); }
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
@@ -2056,6 +2107,8 @@ inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(this, n
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); }
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); }
inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); }
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+81 -15
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -64,7 +64,8 @@ int AstNodeSel::bitConst() const {
void AstNodeClassDType::repairMemberCache() {
clearCache();
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
if (m_members.find(itemp->name())!=m_members.end()) {
itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
else m_members.insert(make_pair(itemp->name(), itemp));
}
}
@@ -239,11 +240,20 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
} else if (isWide()) {
arg += "WData"; // []'s added later
}
if (isWide() && !strtype) {
arg += " (& "+name();
arg += ")["+cvtToStr(widthWords())+"]";
if (isDpiOpenArray() || (isWide() && !strtype)) {
arg += " (& "+name()+")";
for (AstNodeDType* dtp=dtypep(); dtp; ) {
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstUnpackArrayDType* adtypep = dtp->castUnpackArrayDType()) {
arg += "["+cvtToStr(adtypep->declRange().elements())+"]";
dtp = adtypep->subDTypep();
} else break;
}
if (isWide() && !strtype) {
arg += "["+cvtToStr(widthWords())+"]";
}
} else {
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
if (named) arg += " "+name();
}
return arg;
@@ -275,15 +285,48 @@ string AstVar::vlEnumType() const {
}
string AstVar::vlEnumDir() const {
string out;
if (isInout()) {
return "VLVD_INOUT";
out = "VLVD_INOUT";
} else if (isInOnly()) {
return "VLVD_IN";
out = "VLVD_IN";
} else if (isOutOnly()) {
return "VLVD_OUT";
out = "VLVD_OUT";
} else {
return "VLVD_NODIR";
out = "VLVD_NODIR";
}
//
if (isSigUserRWPublic()) out += "|VLVF_PUB_RW";
else if (isSigUserRdPublic()) out += "|VLVF_PUB_RD";
//
if (AstBasicDType* bdtypep = basicp()) {
if (bdtypep->keyword().isDpiCLayout()) out += "|VLVF_DPI_CLAY";
}
return out;
}
string AstVar::vlPropInit() const {
string out;
out = vlEnumType(); // VLVT_UINT32 etc
out += ", "+vlEnumDir(); // VLVD_IN etc
if (AstBasicDType* bdtypep = basicp()) {
out += ", VerilatedVarProps::Packed()";
out += ", "+cvtToStr(bdtypep->left())+", "+cvtToStr(bdtypep->right());
}
bool first = true;
for (AstNodeDType* dtp=dtypep(); dtp; ) {
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstNodeArrayDType* adtypep = dtp->castNodeArrayDType()) {
if (first) {
out += ", VerilatedVarProps::Unpacked()";
first = false;
}
out += ", "+cvtToStr(adtypep->declRange().left())+", "+cvtToStr(adtypep->declRange().right());
dtp = adtypep->subDTypep();
}
else break; // AstBasicDType - nothing below
}
return out;
}
string AstVar::cPubArgType(bool named, bool forReturn) const {
@@ -313,8 +356,11 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
string AstVar::dpiArgType(bool named, bool forReturn) const {
if (forReturn) named=false;
string arg;
if (!basicp()) arg = "UNKNOWN";
if (basicp()->isBitLogic()) {
if (isDpiOpenArray()) {
arg = "const svOpenArrayHandle";
} else if (!basicp()) {
arg = "UNKNOWN";
} else if (basicp()->keyword().isDpiBitVal()) {
if (widthMin() == 1) {
arg = "unsigned char";
if (!forReturn && isOutput()) arg += "*";
@@ -327,6 +373,19 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
arg = "svBitVecVal*";
}
}
} else if (basicp()->keyword().isDpiLogicVal()) {
if (widthMin() == 1) {
arg = "unsigned char";
if (!forReturn && isOutput()) arg += "*";
} else {
if (forReturn) {
arg = "svLogicVecVal";
} else if (isInOnly()) {
arg = "const svLogicVecVal*";
} else {
arg = "svLogicVecVal*";
}
}
} else {
arg = basicp()->keyword().dpiType();
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
@@ -851,6 +910,7 @@ void AstRefDType::dump(ostream& str) {
void AstNodeClassDType::dump(ostream& str) {
this->AstNode::dump(str);
if (packed()) str<<" [PACKED]";
if (isFourstate()) str<<" [4STATE]";
}
void AstNodeDType::dump(ostream& str) {
this->AstNode::dump(str);
@@ -949,7 +1009,10 @@ void AstTypeTable::dump(ostream& str) {
}
// Note get newline from caller too.
}
void AstUnsizedArrayDType::dumpSmall(ostream& str) {
this->AstNodeDType::dumpSmall(str);
str<<"[]";
}
void AstVarScope::dump(ostream& str) {
this->AstNode::dump(str);
if (isCircular()) str<<" [CIRC]";
@@ -961,7 +1024,7 @@ void AstVarXRef::dump(ostream& str) {
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- ";
str<<dotted()<<". - ";
str<<".="<<dotted()<<" ";
if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
if (varScopep()) { varScopep()->dump(str); }
else if (varp()) { varp()->dump(str); }
@@ -996,6 +1059,7 @@ void AstVar::dump(ostream& str) {
if (attrFileDescr()) str<<" [aFD]";
if (isFuncReturn()) str<<" [FUNCRTN]";
else if (isFuncLocal()) str<<" [FUNC]";
if (isDpiOpenArray()) str<<" [DPIOPENA]";
if (!attrClocker().unknown()) str<<" ["<<attrClocker().ascii()<<"] ";
str<<" "<<varType();
}
@@ -1031,7 +1095,7 @@ void AstNodeFTaskRef::dump(ostream& str) {
this->AstNode::dump(str);
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
str<<" -> ";
if (dotted()!="") { str<<dotted()<<". - "; }
if (dotted()!="") { str<<".="<<dotted()<<" "; }
if (taskp()) { taskp()->dump(str); }
else { str<<"UNLINKED"; }
}
@@ -1041,6 +1105,8 @@ void AstNodeFTask::dump(ostream& str) {
if (prototype()) str<<" [PROTOTYPE]";
if (dpiImport()) str<<" [DPII]";
if (dpiExport()) str<<" [DPIX]";
if (dpiOpenChild()) str<<" [DPIOPENCHILD]";
if (dpiOpenParent()) str<<" [DPIOPENPARENT]";
if ((dpiImport() || dpiExport()) && cname()!=name()) str<<" [c="<<cname()<<"]";
}
void AstBegin::dump(ostream& str) {
+383 -116
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -108,22 +108,22 @@ public:
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
};
class AstRange : public AstNode {
class AstRange : public AstNodeRange {
// Range specification, for use under variables and cells
private:
bool m_littleEndian:1; // Bit vector is little endian
public:
AstRange(FileLine* fl, AstNode* msbp, AstNode* lsbp)
:AstNode(fl) {
: AstNodeRange(fl) {
m_littleEndian = false;
setOp2p(msbp); setOp3p(lsbp); }
AstRange(FileLine* fl, int msb, int lsb)
:AstNode(fl) {
: AstNodeRange(fl) {
m_littleEndian = false;
setOp2p(new AstConst(fl,msb)); setOp3p(new AstConst(fl,lsb));
}
AstRange(FileLine* fl, const VNumRange& range)
:AstNode(fl) {
: AstNodeRange(fl) {
m_littleEndian = range.littleEndian();
setOp2p(new AstConst(fl,range.hi())); setOp3p(new AstConst(fl,range.lo()));
}
@@ -146,6 +146,17 @@ public:
virtual bool same(const AstNode* samep) const { return true; }
};
class AstUnsizedRange : public AstNodeRange {
// Unsized range specification, for open arrays
public:
explicit AstUnsizedRange(FileLine* fl) : AstNodeRange(fl) { }
ASTNODE_NODE_FUNCS(UnsizedRange)
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitVerilog() { return "[]"; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
};
class AstGatePin : public AstNodeMath {
// Possibly expand a gate primitive input pin value to match the range of the gate primitive
public:
@@ -334,6 +345,49 @@ public:
ASTNODE_NODE_FUNCS(UnpackArrayDType)
};
class AstUnsizedArrayDType : public AstNodeDType {
// Unsized/open-range Array data type, ie "some_dtype var_name []"
// Children: DTYPE (moved to refDTypep() in V3Width)
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
public:
AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
: AstNodeDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(NULL);
dtypep(NULL); // V3Width will resolve
}
ASTNODE_NODE_FUNCS(UnsizedArrayDType)
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep()))); return NULL; }
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
m_refDTypep = m_refDTypep->clonep();
}}
virtual bool same(const AstNode* samep) const {
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
return (subDTypep()==asamep->subDTypep()); }
virtual bool similarDType(AstNodeDType* samep) const {
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
}
virtual void dumpSmall(ostream& str);
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
// METHODS
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
};
class AstBasicDType : public AstNodeDType {
// Builtin atomic/vectored data type
// Children: RANGE (converted to constant in V3Width)
@@ -345,7 +399,7 @@ private:
return rhs.m_keyword == m_keyword
&& rhs.m_nrange == m_nrange; }
} m;
// See also in AstNodeDtype: m_width, m_widthMin, m_numeric(issigned)
// See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned)
public:
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSignedState signst=signedst_NOSIGN)
: AstNodeDType(fl) {
@@ -426,6 +480,7 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual bool isFourstate() const { return keyword().isFourstate(); }
AstBasicDTypeKwd keyword() const { return m.m_keyword; } // Avoid using - use isSomething accessors instead
bool isBitLogic() const { return keyword().isBitLogic(); }
bool isDouble() const { return keyword().isDouble(); }
@@ -615,7 +670,7 @@ public:
class AstMemberDType : public AstNodeDType {
// A member of a struct/union
// PARENT: AstClassDType
// PARENT: AstNodeClassDType
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
string m_name; // Name of variable
@@ -651,13 +706,17 @@ public:
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
//
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
// (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); }
// op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
// METHODS
virtual void name(const string& name) { m_name = name; }
virtual void tag(const string& text) { m_tag = text;}
@@ -1056,6 +1115,7 @@ private:
bool m_isPulldown:1; // Tri0
bool m_isPullup:1; // Tri1
bool m_isIfaceParent:1; // dtype is reference to interface present in this module
bool m_isDpiOpenArray:1; // DPI import open array
bool m_noSubst:1; // Do not substitute out references
bool m_trace:1; // Trace this variable
AstVarAttrClocker m_attrClocker;
@@ -1069,8 +1129,8 @@ private:
m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false; m_isPulldown=false; m_isPullup=false;
m_isIfaceParent=false; m_attrClocker=AstVarAttrClocker::CLOCKER_UNKNOWN; m_noSubst=false;
m_trace=false;
m_isIfaceParent=false; m_isDpiOpenArray=false; m_noSubst=false; m_trace=false;
m_attrClocker=AstVarAttrClocker::CLOCKER_UNKNOWN;
}
public:
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
@@ -1127,14 +1187,17 @@ public:
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
string vlArgType(bool named, bool forReturn, bool forFunc) const; // Return Verilator internal type for argument: CData, SData, IData, WData
// Return Verilator internal type for argument: CData, SData, IData, WData
string vlArgType(bool named, bool forReturn, bool forFunc) const;
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
string vlPropInit() const; // Return VerilatorVarProps initializer
void combineType(AstVarType type);
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
// (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
AstBasicDType* basicp() const { return subDTypep()->basicp(); }
AstNode* valuep() const { return op3p(); } // op3 = Initial value that never changes (static const)
void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than an AstConst
void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
@@ -1163,6 +1226,8 @@ public:
void isIfaceParent(bool flag) { m_isIfaceParent = flag; }
void funcLocal(bool flag) { m_funcLocal = flag; }
void funcReturn(bool flag) { m_funcReturn = flag; }
void isDpiOpenArray(bool flag) { m_isDpiOpenArray=flag; }
bool isDpiOpenArray() const { return m_isDpiOpenArray; }
void noSubst(bool flag) { m_noSubst=flag; }
bool noSubst() const { return m_noSubst; }
void trace(bool flag) { m_trace=flag; }
@@ -1384,11 +1449,14 @@ class AstVarRef : public AstNodeVarRef {
// A reference to a variable (lvalue or rvalue)
public:
AstVarRef(FileLine* fl, const string& name, bool lvalue)
:AstNodeVarRef(fl, name, NULL, lvalue) {}
AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) // This form only allowed post-link
:AstNodeVarRef(fl, varp->name(), varp, lvalue) {} // because output/wire compression may lead to deletion of AstVar's
AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue) // This form only allowed post-link
:AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) { // because output/wire compression may lead to deletion of AstVar's
: AstNodeVarRef(fl, name, NULL, lvalue) {}
// This form only allowed post-link because output/wire compression may
// lead to deletion of AstVar's
AstVarRef(FileLine* fl, AstVar* varp, bool lvalue)
: AstNodeVarRef(fl, varp->name(), varp, lvalue) {}
// This form only allowed post-link (see above)
AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue)
: AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) {
varScopep(varscp);
}
ASTNODE_NODE_FUNCS(VarRef)
@@ -1416,7 +1484,7 @@ class AstVarXRef : public AstNodeVarRef {
// A VarRef to something in another module before AstScope.
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
private:
string m_dotted; // Scope name to connected to
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
string m_inlinedDots; // Dotted hierarchy flattened out
public:
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
@@ -1881,7 +1949,7 @@ public:
};
class AstDot : public AstNode {
// A dot separating paths in an AstXRef, AstFuncRef or AstTaskRef
// A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
// These are eliminated in the link stage
public:
AstDot(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
@@ -2272,7 +2340,9 @@ public:
ASTNODE_NODE_FUNCS(CoverDecl)
virtual const char* broken() const {
BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists());
if (m_dataDeclp && m_dataDeclp->m_dataDeclp) v3fatalSrc("dataDeclp should point to real data, not be a list"); // Avoid O(n^2) accessing
if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing
v3fatalSrc("dataDeclp should point to real data, not be a list");
}
return NULL; }
virtual void cloneRelink() { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); }
virtual void dump(ostream& str);
@@ -2535,6 +2605,26 @@ public:
void lhsp(AstNode* nodep) { setOp3p(nodep); }
};
class AstSysFuncAsTask : public AstNodeStmt {
// Call what is normally a system function (with a return) in a non-return context
// Parents: stmtlist
// Children: a system function
public:
AstSysFuncAsTask(FileLine* fileline, AstNode* exprsp)
: AstNodeStmt (fileline) { addNOp1p(exprsp); }
ASTNODE_NODE_FUNCS(SysFuncAsTask)
virtual string verilogKwd() const { return ""; }
virtual bool isGateOptimizable() const { return true; }
virtual bool isPredictOptimizable() const { return true; }
virtual bool isPure() const { return true; }
virtual bool isOutputter() const { return false; }
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval
void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval
};
class AstSysIgnore : public AstNodeStmt {
// Parents: stmtlist
// Children: varrefs or exprs
@@ -2683,17 +2773,16 @@ public:
void fromp(AstNode* nodep) { setOp2p(nodep); }
};
class AstReadMem : public AstNodeStmt {
class AstNodeReadWriteMem : public AstNodeStmt {
private:
bool m_isHex; // readmemh, not readmemb
public:
AstReadMem(FileLine* fileline, bool hex,
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
AstNodeReadWriteMem(FileLine* fileline, bool hex,
AstNode* filenamep, AstNode* memp,
AstNode* lsbp, AstNode* msbp)
: AstNodeStmt (fileline), m_isHex(hex) {
setOp1p(filenamep); setOp2p(memp); setNOp3p(lsbp); setNOp4p(msbp);
}
ASTNODE_NODE_FUNCS(ReadMem)
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isPure() const { return false; }
@@ -2701,12 +2790,35 @@ public:
virtual bool isUnlikely() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const {
return isHex()==static_cast<const AstReadMem*>(samep)->isHex(); }
return isHex()==static_cast<const AstNodeReadWriteMem*>(samep)->isHex();
}
bool isHex() const { return m_isHex; }
AstNode* filenamep() const { return op1p(); }
AstNode* memp() const { return op2p(); }
AstNode* lsbp() const { return op3p(); }
AstNode* msbp() const { return op4p(); }
virtual const char* cFuncPrefixp() const = 0;
};
class AstReadMem : public AstNodeReadWriteMem {
public:
AstReadMem(FileLine* fileline, bool hex,
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
: AstNodeReadWriteMem(fileline, hex, filenamep, memp, lsbp, msbp)
{ }
ASTNODE_NODE_FUNCS(ReadMem);
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
virtual const char* cFuncPrefixp() const { return "VL_READMEM_"; }
};
class AstWriteMem : public AstNodeReadWriteMem {
public:
AstWriteMem(FileLine* fileline,
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
: AstNodeReadWriteMem(fileline, true, filenamep, memp, lsbp, msbp) { }
ASTNODE_NODE_FUNCS(WriteMem)
virtual string verilogKwd() const { return (isHex()?"$writememh":"$writememb"); }
virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; }
};
class AstSystemT : public AstNodeStmt {
@@ -3361,10 +3473,14 @@ public:
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
AstText* scopeEntrp() const { return op2p()->castText(); }
void scopeEntrp(AstNode* nodep) { addOp2p(nodep); }
string scopeSymName() const { return scopeNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
string scopeDpiName() const { return scopeNameFormatter(scopeEntrp()); } // Name for DPI import scope
string scopePrettySymName() const { return scopePrettyNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
string scopePrettyDpiName() const { return scopePrettyNameFormatter(scopeEntrp()); } // Name for __Vscope variable including children
string scopeSymName() const { // Name for __Vscope variable including children
return scopeNameFormatter(scopeAttrp()); }
string scopeDpiName() const { // Name for DPI import scope
return scopeNameFormatter(scopeEntrp()); }
string scopePrettySymName() const { // Name for __Vscope variable including children
return scopePrettyNameFormatter(scopeAttrp()); }
string scopePrettyDpiName() const { // Name for __Vscope variable including children
return scopePrettyNameFormatter(scopeEntrp()); }
bool dpiExport() const { return m_dpiExport; }
void dpiExport(bool flag) { m_dpiExport=flag; }
};
@@ -3545,6 +3661,18 @@ public:
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
};
class AstLenN : public AstNodeUniop {
// Length of a string
public:
AstLenN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetSigned32(); }
ASTNODE_NODE_FUNCS(LenN)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLenN(lhs); }
virtual string emitVerilog() { return "%f(%l)"; }
virtual string emitC() { return "VL_LEN_IN(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
};
class AstLogNot : public AstNodeUniop {
public:
AstLogNot(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
@@ -3876,94 +4004,176 @@ public:
AstNode* filep() const { return lhsp(); }
};
class AstCeilD : public AstNodeUniop {
class AstNodeSystemUniop : public AstNodeUniop {
public:
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_NODE_FUNCS(CeilD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(ceil(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ceil(%l)"; }
virtual string emitC() { return "ceil(%li)"; }
AstNodeSystemUniop(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_BASE_FUNCS(NodeSystemUniop)
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstExpD : public AstNodeUniop {
class AstLogD : public AstNodeSystemUniop {
public:
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_NODE_FUNCS(ExpD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(exp(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$exp(%l)"; }
virtual string emitC() { return "exp(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstFloorD : public AstNodeUniop {
public:
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
ASTNODE_NODE_FUNCS(FloorD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(floor(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$floor(%l)"; }
virtual string emitC() { return "floor(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstLogD : public AstNodeUniop {
public:
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(LogD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(log(lhs.toDouble())); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ln(%l)"; }
virtual string emitC() { return "log(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstLog10D : public AstNodeUniop {
class AstLog10D : public AstNodeSystemUniop {
public:
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(Log10D)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(log10(lhs.toDouble())); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log10(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$log10(%l)"; }
virtual string emitC() { return "log10(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstSqrtD : public AstNodeUniop {
class AstExpD : public AstNodeSystemUniop {
public:
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetDouble(); }
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(ExpD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(exp(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$exp(%l)"; }
virtual string emitC() { return "exp(%li)"; }
};
class AstSqrtD : public AstNodeSystemUniop {
public:
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SqrtD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(sqrt(lhs.toDouble())); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sqrt(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sqrt(%l)"; }
virtual string emitC() { return "sqrt(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstFloorD : public AstNodeSystemUniop {
public:
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(FloorD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(floor(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$floor(%l)"; }
virtual string emitC() { return "floor(%li)"; }
};
class AstCeilD : public AstNodeSystemUniop {
public:
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CeilD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(ceil(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ceil(%l)"; }
virtual string emitC() { return "ceil(%li)"; }
};
class AstSinD : public AstNodeSystemUniop {
public:
AstSinD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SinD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sin(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sin(%l)"; }
virtual string emitC() { return "sin(%li)"; }
};
class AstCosD : public AstNodeSystemUniop {
public:
AstCosD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CosD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cos(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$cos(%l)"; }
virtual string emitC() { return "cos(%li)"; }
};
class AstTanD : public AstNodeSystemUniop {
public:
AstTanD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TanD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tan(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$tan(%l)"; }
virtual string emitC() { return "tan(%li)"; }
};
class AstAsinD : public AstNodeSystemUniop {
public:
AstAsinD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AsinD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asin(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$asin(%l)"; }
virtual string emitC() { return "asin(%li)"; }
};
class AstAcosD : public AstNodeSystemUniop {
public:
AstAcosD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AcosD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acos(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$acos(%l)"; }
virtual string emitC() { return "acos(%li)"; }
};
class AstAtanD : public AstNodeSystemUniop {
public:
AstAtanD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AtanD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atan(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$atan(%l)"; }
virtual string emitC() { return "atan(%li)"; }
};
class AstSinhD : public AstNodeSystemUniop {
public:
AstSinhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SinhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sinh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sinh(%l)"; }
virtual string emitC() { return "sinh(%li)"; }
};
class AstCoshD : public AstNodeSystemUniop {
public:
AstCoshD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CoshD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cosh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$cosh(%l)"; }
virtual string emitC() { return "cosh(%li)"; }
};
class AstTanhD : public AstNodeSystemUniop {
public:
AstTanhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TanhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tanh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$tanh(%l)"; }
virtual string emitC() { return "tanh(%li)"; }
};
class AstAsinhD : public AstNodeSystemUniop {
public:
AstAsinhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AsinhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asinh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$asinh(%l)"; }
virtual string emitC() { return "asinh(%li)"; }
};
class AstAcoshD : public AstNodeSystemUniop {
public:
AstAcoshD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AcoshD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acosh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$acosh(%l)"; }
virtual string emitC() { return "acosh(%li)"; }
};
class AstAtanhD : public AstNodeSystemUniop {
public:
AstAtanhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AtanhD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atanh(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$atanh(%l)"; }
virtual string emitC() { return "atanh(%li)"; }
};
//======================================================================
@@ -4454,7 +4664,9 @@ public:
virtual string emitSimpleOperator() { return ">>"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} // LHS size might be > output size, so don't want to force size
// LHS size might be > output size, so don't want to force size
virtual bool sizeMattersLhs() {return false;}
virtual bool sizeMattersRhs() {return false;}
};
class AstShiftRS : public AstNodeBiop {
// Shift right with sign extension, >>> operator
@@ -4933,6 +5145,39 @@ public:
AstNode* filep() const { return rhsp(); }
};
class AstNodeSystemBiop : public AstNodeBiop {
public:
AstNodeSystemBiop(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
dtypeSetDouble(); }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
class AstAtan2D : public AstNodeSystemBiop {
public:
AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeSystemBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(Atan2D)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAtan2D(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
out.setDouble(atan2(lhs.toDouble(), rhs.toDouble())); }
virtual string emitVerilog() { return "%f$atan2(%l,%r)"; }
virtual string emitC() { return "atan2(%li,%ri)"; }
};
class AstHypotD : public AstNodeSystemBiop {
public:
AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeSystemBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(HypotD)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstHypotD(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
out.setDouble(hypot(lhs.toDouble(), rhs.toDouble())); }
virtual string emitVerilog() { return "%f$hypot(%l,%r)"; }
virtual string emitC() { return "hypot(%li,%ri)"; }
};
class AstPattern : public AstNodeMath {
// Verilog '{a,b,c,d...}
// Parents: AstNodeAssign, AstPattern, ...
@@ -5038,30 +5283,44 @@ public:
AstNode* propp() const { return op3p(); } // op3 = property
};
class AstPslCover : public AstNodeStmt {
class AstNodePslCoverOrAssert : public AstNodeStmt {
// Psl Cover
// Parents: {statement list}
// Children: expression, report string
private:
string m_name; // Name to report
public:
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
AstNodePslCoverOrAssert(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodeStmt(fl)
, m_name(name) {
addOp1p(propp);
addNOp4p(stmtsp);
}
ASTNODE_NODE_FUNCS(PslCover)
virtual string name() const { return m_name; } // * = Var name
ASTNODE_BASE_FUNCS(NodePslCoverOrAssert)
virtual string name() const { return m_name; } // * = Var name
virtual V3Hash sameHash() const { return V3Hash(name()); }
virtual bool same(const AstNode* samep) const { return samep->name() == name(); }
virtual void name(const string& name) { m_name = name; }
AstNode* propp() const { return op1p(); } // op1 = property
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
AstNode* stmtsp() const { return op4p(); } // op4 = statements
AstNode* propp() const { return op1p(); } // op1 = property
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
AstNode* stmtsp() const { return op4p(); } // op4 = statements
};
class AstPslCover : public AstNodePslCoverOrAssert {
public:
ASTNODE_NODE_FUNCS(PslCover)
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodePslCoverOrAssert(fl, propp, stmtsp, name) {}
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
};
class AstPslAssert : public AstNodePslCoverOrAssert {
public:
ASTNODE_NODE_FUNCS(PslAssert)
AstPslAssert(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodePslCoverOrAssert(fl, propp, stmtsp, name) {}
};
//======================================================================
@@ -5471,13 +5730,19 @@ class AstNetlist : public AstNode {
private:
AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup
AstPackage* m_dollarUnitPkgp;
AstCFunc* m_evalp; // The '_eval' function
public:
AstNetlist() : AstNode(new FileLine("AstRoot",0)) {
m_typeTablep = NULL;
m_dollarUnitPkgp = NULL;
}
AstNetlist()
: AstNode(new FileLine("AstRoot",0))
, m_typeTablep(NULL)
, m_dollarUnitPkgp(NULL)
, m_evalp(NULL) { }
ASTNODE_NODE_FUNCS(Netlist)
virtual const char* broken() const { BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); return NULL; }
virtual const char* broken() const {
BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists());
BROKEN_RTN(m_evalp && !m_evalp->brokeExists());
return NULL;
}
AstNodeModule* modulesp() const { return op1p()->castNodeModule();} // op1 = List of modules
AstNodeModule* topModulep() const { return op1p()->castNodeModule(); } // * = Top module in hierarchy (first one added, for now)
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
@@ -5497,6 +5762,8 @@ public:
addModulep(m_dollarUnitPkgp);
}
return m_dollarUnitPkgp; }
AstCFunc* evalp() const { return m_evalp; }
void evalp(AstCFunc* evalp) { m_evalp = evalp; }
};
//######################################################################
+8 -6
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -291,10 +291,12 @@ public:
void V3Begin::debeginAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
BeginState state;
{ BeginVisitor bvisitor (nodep,&state); }
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
{
BeginState state;
{ BeginVisitor bvisitor (nodep,&state); }
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
} // Destruct before checking
V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+6 -3
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -224,8 +224,11 @@ private:
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
}
if (nodep->dtypep()) {
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
else if (!nodep->dtypep()->castNodeDType()) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
if (!nodep->dtypep()->brokeExists()) {
nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep());
} else if (!nodep->dtypep()->castNodeDType()) {
nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep());
}
}
if (v3Global.assertDTypesResolved()) {
if (nodep->hasDType()) {
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+9 -5
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -77,7 +77,8 @@ public:
m_numStmts += 1;
}
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="",
V3CCtorsVisitor(AstNodeModule* nodep, const string& basename,
const string& argsp="", const string& callargsp="",
const string& stmt="") {
m_basename = basename;
m_argsp = argsp;
@@ -129,7 +130,8 @@ void V3CCtors::evalAsserts() {
newp = new AstAnd(varp->fileline(), newp,
new AstConst(varp->fileline(), num));
AstNodeIf* ifp = new AstIf(varp->fileline(), newp,
new AstCStmt(varp->fileline(), "Verilated::overWidthError(\""+varp->prettyName()+"\");"));
new AstCStmt(varp->fileline(),
"Verilated::overWidthError(\""+varp->prettyName()+"\");"));
ifp->branchPred(AstBranchPred::BP_UNLIKELY);
newp = ifp;
funcp->addStmtsp(newp);
@@ -149,14 +151,16 @@ void V3CCtors::cctorsAll() {
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
if (AstVar* varp = np->castVar()) {
var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
if (!varp->isIfaceParent() && !varp->isIfaceRef()) {
var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
}
}
}
}
if (v3Global.opt.coverage()) {
V3CCtorsVisitor configure_coverage
(modp, "_configure_coverage", EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first",
"if (0 && vlSymsp && first) {} // Prevent unused\n");
"if (0 && vlSymsp && first) {} // Prevent unused\n");
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
if (AstCoverDecl* coverp = np->castCoverDecl()) {
AstNode* backp = coverp->backp();
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+9 -7
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -166,7 +166,7 @@ private:
}
UINFO(8,"Simple case statement: "<<nodep<<endl);
// Zero list of items for each value
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) m_valueItem[i] = NULL;
// Now pick up the values for each assignment
// We can cheat and use uint32_t's because we only support narrow case's
bool bitched = false;
@@ -184,7 +184,7 @@ private:
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
uint32_t val = numval.toUInt();
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
if ((i & mask) == val) {
if (!m_valueItem[i]) {
m_valueItem[i] = itemp;
@@ -199,12 +199,12 @@ private:
}
// Defaults were moved to last in the caseitem list by V3LinkDot
if (itemp->isDefault()) { // Case statement's default... Fill the table
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
if (!m_valueItem[i]) m_valueItem[i] = itemp;
}
}
}
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
if (!m_valueItem[i]) {
nodep->v3warn(CASEINCOMPLETE,"Case values incompletely covered (example pattern 0x"<<hex<<i<<")");
m_caseNoOverlapsAllCovered = false;
@@ -278,7 +278,7 @@ private:
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
if (debug()>=9) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
if (AstNode* itemp = m_valueItem[i]) {
UINFO(9,"Value "<<hex<<i<<" "<<itemp<<endl);
}
@@ -488,7 +488,9 @@ public:
void V3Case::caseAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CaseVisitor visitor (nodep);
{
CaseVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Case::caseLint(AstNodeCase* nodep) {
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+4 -2
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2018 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.
@@ -187,6 +187,8 @@ public:
void V3Cast::castAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CastVisitor visitor (nodep);
{
CastVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2004-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+7 -7
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -76,7 +76,7 @@ public:
, m_srcDomainSet(false), m_dstDomainSet(false)
, m_asyncPath(false) {}
virtual ~CdcEitherVertex() {}
// Accessors
// ACCESSORS
AstScope* scopep() const { return m_scopep; }
AstNode* nodep() const { return m_nodep; }
AstSenTree* srcDomainp() const { return m_srcDomainp; }
@@ -99,7 +99,7 @@ public:
CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: CdcEitherVertex(graphp, scopep, varScp), m_varScp(varScp), m_cntAsyncRst(0), m_fromFlop(false) {}
virtual ~CdcVarVertex() {}
// Accessors
// ACCESSORS
AstVarScope* varScp() const { return m_varScp; }
virtual string name() const { return (cvtToStr((void*)m_varScp)+" "+varScp()->name()); }
virtual string dotColor() const { return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue"; }
@@ -118,7 +118,7 @@ public:
, m_hazard(false), m_isFlop(false)
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
virtual ~CdcLogicVertex() {}
// Accessors
// ACCESSORS
virtual string name() const { return (cvtToStr((void*)nodep())+"@"+scopep()->prettyName()); }
virtual string dotColor() const { return hazard() ? "black" : "yellow"; }
bool hazard() const { return m_hazard; }
@@ -496,8 +496,8 @@ private:
}
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc_edges.txt";
const vl_unique_ptr<ofstream> ofp (V3File::new_ofstream(filename));
if (ofp->fail()) v3fatalSrc("Can't write "<<filename);
const vl_unique_ptr<std::ofstream> ofp (V3File::new_ofstream(filename));
if (ofp->fail()) v3fatal("Can't write "<<filename);
*ofp<<"Edge Report for "<<v3Global.opt.prefix()<<endl;
deque<string> report; // Sort output by name
@@ -739,7 +739,7 @@ public:
// Make report of all signal names and what clock edges they have
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc.txt";
m_ofp = V3File::new_ofstream(filename);
if (m_ofp->fail()) v3fatalSrc("Can't write "<<filename);
if (m_ofp->fail()) v3fatal("Can't write "<<filename);
m_ofFilename = filename;
*m_ofp<<"CDC Report for "<<v3Global.opt.prefix()<<endl;
*m_ofp<<"Each dump below traces logic from inputs/source flops to destination flop(s).\n";
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+11 -5
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -175,13 +175,17 @@ private:
newChangeDet();
} else {
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-class-");
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
" (probably with UNOPTFLAT warning suppressed): "
<<m_vscp->varp()->prettyName());
}
}
virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this);
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-");
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
" (probably with UNOPTFLAT warning suppressed): "
<<m_vscp->varp()->prettyName());
}
public:
// CONSTUCTORS
@@ -300,7 +304,9 @@ public:
void V3Changed::changedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ChangedState state;
ChangedVisitor visitor (nodep, &state);
{
ChangedState state;
ChangedVisitor visitor (nodep, &state);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+6 -3
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -90,7 +90,8 @@ private:
}
void computeCppWidth (AstNode* nodep) {
if (!nodep->user2() && nodep->hasDType()) {
if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths!
if (nodep->castVar() || nodep->castNodeDType() // Don't want to change variable widths!
|| nodep->dtypep()->skipRefp()->castUnpackArrayDType()) { // Or arrays
} else {
setCppWidth(nodep);
}
@@ -296,6 +297,8 @@ public:
void V3Clean::cleanAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CleanVisitor visitor (nodep);
{
CleanVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+6 -4
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2008-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2008-2018 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.
@@ -373,7 +373,7 @@ class GaterVisitor : public GaterBaseVisitor {
}
void scoreboardPli(AstNode* nodep) {
// Order all PLI statements with other PLI statements
// This insures $display's and such remain in proper order
// This ensures $display's and such remain in proper order
// We don't prevent splitting out other non-pli statements, however,
// because it is common to have $uasserts sprinkled about.
if (!m_pliVertexp) {
@@ -912,8 +912,10 @@ public:
void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
// While the gater does well at some modules, it seems to slow down many others
UINFO(5,"ClkGater is disabled due to performance issues\n");
{
// While the gater does well at some modules, it seems to slow down many others
UINFO(5,"ClkGater is disabled due to performance issues\n");
} // Destruct before checking
//GaterVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clkgater", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
+16 -17
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
@@ -62,15 +62,12 @@ private:
AstNodeModule* m_modp; // Current module
AstTopScope* m_topScopep; // Current top scope
AstScope* m_scopep; // Current scope
AstActive* m_activep; // Current block
AstUntilStable* m_untilp; // Current until
AstCFunc* m_evalFuncp; // Top eval function we are creating
AstCFunc* m_initFuncp; // Top initial function we are creating
AstCFunc* m_finalFuncp; // Top final function we are creating
AstCFunc* m_settleFuncp; // Top settlement function we are creating
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
AstIf* m_lastIfp; // Last sensitivity if active to add more under
int m_stableNum; // Number of each untilstable
// METHODS
static int debug() {
@@ -252,7 +249,6 @@ private:
virtual void visit(AstNodeModule* nodep) {
//UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
m_stableNum = 0;
nodep->iterateChildren(*this);
m_modp= NULL;
}
@@ -330,16 +326,13 @@ private:
pushDeletep(nodep);
}
void addToEvalLoop(AstNode* stmtsp) {
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_evalFuncp->addStmtsp(stmtsp); // else add to top level function
m_evalFuncp->addStmtsp(stmtsp); // add to top level function
}
void addToSettleLoop(AstNode* stmtsp) {
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_settleFuncp->addStmtsp(stmtsp); // else add to top level function
m_settleFuncp->addStmtsp(stmtsp); // add to top level function
}
void addToInitial(AstNode* stmtsp) {
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
m_initFuncp->addStmtsp(stmtsp); // add to top level function
}
virtual void visit(AstActive* nodep) {
// Careful if adding variables here, ACTIVES can be under other ACTIVES
@@ -393,16 +386,20 @@ private:
public:
// CONSTUCTORS
explicit ClockVisitor(AstNetlist* nodep) {
m_modp=NULL; m_activep=NULL;
m_modp = NULL;
m_evalFuncp = NULL;
m_topScopep=NULL;
m_lastSenp=NULL;
m_initFuncp = NULL;
m_finalFuncp = NULL;
m_settleFuncp = NULL;
m_topScopep = NULL;
m_lastSenp = NULL;
m_lastIfp = NULL;
m_scopep = NULL;
m_stableNum = 0;
m_untilp = NULL;
//
nodep->accept(*this);
// Allow downstream modules to find _eval()
// easily without iterating through the tree.
nodep->evalp(m_evalFuncp);
}
virtual ~ClockVisitor() {}
};
@@ -412,6 +409,8 @@ public:
void V3Clock::clockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ClockVisitor visitor (nodep);
{
ClockVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
+5 -2
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 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.
@@ -402,6 +402,7 @@ private:
UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
m_modNFuncs = 0;
m_walkLast2p = NULL;
m_hashed.clear();
// Compute hash of all statement trees in the function
m_state = STATE_HASH;
@@ -473,6 +474,8 @@ public:
void V3Combine::combineAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CombineVisitor visitor (nodep);
{
CombineVisitor visitor (nodep);
} // Destruct before checking
V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -6,7 +6,7 @@
//
//*************************************************************************
//
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
// Copyright 2003-2018 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.

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