Compare commits

...
66 Commits
Author SHA1 Message Date
Wilson Snyder c4b1bc2506 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@950 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-08-01 13:44:45 +00:00
Wilson Snyder 551393d443 Fix SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
git-svn-id: file://localhost/svn/verilator/trunk/verilator@949 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-31 14:47:21 +00:00
Wilson Snyder 79d305f3e8 Match Verilog-Perl: Remove preprocessor adding newlines before `line.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@948 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-30 15:00:21 +00:00
Wilson Snyder 822956e769 Add SystemVerilog end labels
git-svn-id: file://localhost/svn/verilator/trunk/verilator@947 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-18 17:58:53 +00:00
Wilson Snyder a681a6a6d5 Make -> a token to match verilog-perl
git-svn-id: file://localhost/svn/verilator/trunk/verilator@946 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-18 17:26:12 +00:00
Wilson Snyder 5f6d69affd Support SystemVerilog ==? and !=? operators.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@945 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-18 15:01:39 +00:00
Wilson Snyder 4a9bea6980 Version bump; commentary
git-svn-id: file://localhost/svn/verilator/trunk/verilator@942 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-21 21:00:38 +00:00
Wilson Snyder bfddd80f43 Support V2K function/task argument lists.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@941 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-19 23:43:14 +00:00
Wilson Snyder 84a778719a Fix constification removing continuous always blocks
git-svn-id: file://localhost/svn/verilator/trunk/verilator@940 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-15 14:39:52 +00:00
Wilson Snyder 829d80d5b5 Fix display constanting of neg quads. Part of previous checkin
git-svn-id: file://localhost/svn/verilator/trunk/verilator@939 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 21:27:40 +00:00
Wilson Snyder d6a5c97f3a Fix last change: percents must be literalized
git-svn-id: file://localhost/svn/verilator/trunk/verilator@938 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 18:34:08 +00:00
Wilson Snyder 4ba00bd256 Propagate constants into displays
git-svn-id: file://localhost/svn/verilator/trunk/verilator@937 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 17:29:37 +00:00
Wilson Snyder c18f9da400 Put display scope tracking under special node type
git-svn-id: file://localhost/svn/verilator/trunk/verilator@936 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 16:41:32 +00:00
Wilson Snyder 5b620a8dc5 Add V3Number display function, unused as yet
git-svn-id: file://localhost/svn/verilator/trunk/verilator@935 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 14:24:21 +00:00
Wilson Snyder 9c968c590c Fix Preprocessor dropping some line directives
git-svn-id: file://localhost/svn/verilator/trunk/verilator@934 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-13 17:34:09 +00:00
Wilson Snyder dff5d5c4e4 Report as many warning types as possible before exiting.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@933 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-12 19:39:10 +00:00
Wilson Snyder 1265e8cce8 Support V2K portlists with input a,b,...
git-svn-id: file://localhost/svn/verilator/trunk/verilator@932 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-12 13:58:56 +00:00
Wilson Snyder 2b5d7eeb50 Lesser license for verilated files
git-svn-id: file://localhost/svn/verilator/trunk/verilator@931 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-11 17:07:11 +00:00
Wilson Snyder bb9ae89049 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@928 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-22 12:15:01 +00:00
Wilson Snyder 72832a2810 Support empty module declarations
git-svn-id: file://localhost/svn/verilator/trunk/verilator@927 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-18 18:48:22 +00:00
Wilson Snyder 18cb210eac Ignore protect, and allow empty case
git-svn-id: file://localhost/svn/verilator/trunk/verilator@926 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-18 14:03:50 +00:00
Wilson Snyder 2c5a183368 Ignore ctrl-Zs in preprocessor
git-svn-id: file://localhost/svn/verilator/trunk/verilator@925 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-17 16:15:24 +00:00
Wilson Snyder 386f0a75df Support automatic and additional v2k timing statements
git-svn-id: file://localhost/svn/verilator/trunk/verilator@924 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-16 19:27:29 +00:00
Wilson Snyder ea26482154 Support functions which return integers
git-svn-id: file://localhost/svn/verilator/trunk/verilator@923 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-16 18:19:23 +00:00
Wilson Snyder 3aee7f918a More cleanup to match VParse, and support celldefine properly
git-svn-id: file://localhost/svn/verilator/trunk/verilator@922 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-16 12:55:25 +00:00
Wilson Snyder b3dd18b215 More bison cleanup; no functional change
git-svn-id: file://localhost/svn/verilator/trunk/verilator@921 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-14 20:59:58 +00:00
Wilson Snyder a77e331e89 Standardize flex->bison token names. No functional change.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@920 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-12 16:29:25 +00:00
Wilson Snyder 6f414ee9e2 Add unsigned keyword
git-svn-id: file://localhost/svn/verilator/trunk/verilator@919 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-05-12 15:31:04 +00:00
Wilson Snyder 8d56b498d1 Warn if flex is not installed.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@918 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-24 17:03:52 +00:00
Wilson Snyder 871c1853bf Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@915 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-20 12:43:23 +00:00
Wilson Snyder f8cd3a785c Use LINK for the loader, and add USER_LDFLAGS and USER_CPPFLAGS
git-svn-id: file://localhost/svn/verilator/trunk/verilator@914 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-19 18:39:47 +00:00
Wilson Snyder 6a6995187e Add --compiler flags, and break up deep functions
git-svn-id: file://localhost/svn/verilator/trunk/verilator@913 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-19 18:20:16 +00:00
Wilson Snyder a216c1e7e4 Add verilator lint_save/lint_restore
git-svn-id: file://localhost/svn/verilator/trunk/verilator@912 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-19 14:21:37 +00:00
Wilson Snyder ea8445d187 Convert bad tests to --lint-only
git-svn-id: file://localhost/svn/verilator/trunk/verilator@911 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-18 18:45:41 +00:00
Wilson Snyder 77261cce5b Add -lint-only option
git-svn-id: file://localhost/svn/verilator/trunk/verilator@910 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-18 18:26:38 +00:00
Wilson Snyder 78db712438 Fix compile errors under Windows MINGW compiler. [Gerald Williams]
git-svn-id: file://localhost/svn/verilator/trunk/verilator@909 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-18 17:58:59 +00:00
Wilson Snyder 749302acb8 Fix MSVCC compile warning
git-svn-id: file://localhost/svn/verilator/trunk/verilator@908 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-04-18 17:41:31 +00:00
Wilson Snyder cbf52bb5d0 Fix 3.640 `verilog forcing IEEE 1364-1995 only.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@907 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-16 18:44:17 +00:00
Wilson Snyder d2ce499b59 Support SystemVerilog .name and .* interconnect.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@906 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-14 13:06:08 +00:00
Wilson Snyder 01e9bc4855 Support while and do-while loops.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@905 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-13 18:21:23 +00:00
Wilson Snyder 28d5e425a9 Fix dotted references under other dotteds
git-svn-id: file://localhost/svn/verilator/trunk/verilator@904 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-13 17:15:00 +00:00
Wilson Snyder eae1f380cd Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@901 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-12 12:58:08 +00:00
Wilson Snyder e7280d7237 Make V3Number::setMask to refactor some code
git-svn-id: file://localhost/svn/verilator/trunk/verilator@900 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-09 15:18:56 +00:00
Wilson Snyder 78997ee13c Another 64 bit fix
git-svn-id: file://localhost/svn/verilator/trunk/verilator@899 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-08 20:48:22 +00:00
Wilson Snyder 79ab50d84f Support trivial SV assertions
git-svn-id: file://localhost/svn/verilator/trunk/verilator@898 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-06 21:43:38 +00:00
Wilson Snyder 98282114c9 Fix display %m names inside named blocks.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@897 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-06 18:53:24 +00:00
Wilson Snyder d6cb175f96 More cleanup of verilog.l
git-svn-id: file://localhost/svn/verilator/trunk/verilator@896 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-06 17:07:13 +00:00
Wilson Snyder b4d9eb6ec4 Commentary
git-svn-id: file://localhost/svn/verilator/trunk/verilator@895 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-05 22:22:34 +00:00
Wilson Snyder fabbfbc46e Add `begin_keywords support
git-svn-id: file://localhost/svn/verilator/trunk/verilator@894 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-05 21:35:49 +00:00
Wilson Snyder c7d80f8cf8 Update keywords to indicate which language spec
git-svn-id: file://localhost/svn/verilator/trunk/verilator@893 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-05 20:29:05 +00:00
Wilson Snyder c70add7d0f Fix user() not zeroing all 64 bits in graphalg
git-svn-id: file://localhost/svn/verilator/trunk/verilator@892 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-05 13:52:21 +00:00
Wilson Snyder 44fe8741f3 Add /*verilator public_flat*/
git-svn-id: file://localhost/svn/verilator/trunk/verilator@891 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-02 22:24:51 +00:00
Wilson Snyder f8680cf5c2 Don't constant prop public signals
git-svn-id: file://localhost/svn/verilator/trunk/verilator@890 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-03-02 21:14:22 +00:00
Wilson Snyder 24c3424e51 Try all +libext's in the exact order given.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@889 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-02-27 20:00:29 +00:00
Wilson Snyder bd264006ef Fix empty for blocks
git-svn-id: file://localhost/svn/verilator/trunk/verilator@888 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-02-27 14:30:22 +00:00
Wilson Snyder bec3daa79f Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@885 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-02-07 14:27:37 +00:00
Wilson Snyder ead01ba0b9 Commentary and fix old SYSTEMPERL pointer
git-svn-id: file://localhost/svn/verilator/trunk/verilator@884 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-02-07 14:26:53 +00:00
Wilson Snyder 8e7267f0e2 With VL_DEBUG, show wires causing convergance errors.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@883 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-31 21:49:13 +00:00
Wilson Snyder 5dbae27f01 Fix 's with array select followed by wide AND. [David Hewson]
git-svn-id: file://localhost/svn/verilator/trunk/verilator@882 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-31 15:44:36 +00:00
Wilson Snyder ecb938f20e Add isolate_assignments to functions
git-svn-id: file://localhost/svn/verilator/trunk/verilator@881 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-30 15:51:16 +00:00
Wilson Snyder f1a2ee3273 Allow isolate_assignments on task input/outputs
git-svn-id: file://localhost/svn/verilator/trunk/verilator@880 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-26 21:53:03 +00:00
Wilson Snyder eb2eb14297 Make tests work on NCV
git-svn-id: file://localhost/svn/verilator/trunk/verilator@879 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-26 15:56:09 +00:00
Wilson Snyder da07cc6ed1 Testcases should use !== to avoid Xs matching
git-svn-id: file://localhost/svn/verilator/trunk/verilator@878 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-26 14:59:30 +00:00
Wilson Snyder 3ff10b40d6 Fix isolate_assignments when many signals per always.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@877 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-23 18:11:26 +00:00
Wilson Snyder 7f515e6033 Add --trace-depth option
git-svn-id: file://localhost/svn/verilator/trunk/verilator@876 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-18 18:31:49 +00:00
Wilson Snyder a583592cd4 Make error code for MULTITOP and document
git-svn-id: file://localhost/svn/verilator/trunk/verilator@875 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-01-18 14:30:45 +00:00
170 changed files with 5162 additions and 1214 deletions
+92 -5
View File
@@ -3,9 +3,96 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.653 8/1/2007
**** Support SystemVerilog ==? and !=? operators.
**** Fix SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
* Verilator 3.652 6/21/2007
**** Report as many warning types as possible before exiting.
**** Support V2K portlists with "input a,b,...". [Mark Nodine]
**** Support V2K function/task argument lists.
**** Optimize constant $display arguments.
**** Fix Preprocessor dropping some `line directives. [Mark Nodine]
* Verilator 3.651 5/22/2007
*** Added verilator_profcfunc utility. [Gene Weber]
*** Treat modules within `celldefine and `endcelldefine as if in library.
*** Support functions which return integers. [Mark Nodine]
**** Warn if flex is not installed. [Ralf Karge]
**** Ignore `protect and `endprotect.
**** Allow empty case/endcase blocks.
* Verilator 3.650 4/20/2007
** Add --compiler msvc option. This is now required when Verilated code
is to be run through MSVC++. This also enables fixing MSVC++ error
C1061, blocks nested too deeply. [Ralf Karge]
** Add --lint-only option, to lint without creating other output.
*** Add /*verilator lint_save*/ and /*verilator lint_restore*/ to allow
friendly control over re-enabling lint messages. [Gerald Williams]
*** Support SystemVerilog .name and .* interconnect.
*** Support while and do-while loops.
*** Use $(LINK) instead of $(CXX) for Makefile link rules. [Gerald Williams]
*** Add USER_CPPFLAGS and USER_LDFLAGS to Makefiles. [Gerald Williams]
**** Fix compile errors under Windows MINGW compiler. [Gerald Williams]
**** Fix dotted bit reference to local memory. [Eugene Weber]
**** Fix 3.640 `verilog forcing IEEE 1364-1995 only. [David Hewson]
* Verilator 3.640 3/12/2007
*** Support Verilog 2005 `begin_keywords and `end_keywords.
*** Updated list of SystemVerilog keywords to correspond to IEEE 1800-2005.
*** Add /*verilator public_flat*/. [Eugene Weber]
**** Try all +libext's in the exact order given. [Michael Shinkarovsky]
**** Fix elimination of public signals assigned to constants. [Eugene Weber]
**** Fix internal error when public for loop has empty body. [David Addison]
**** Fix "Loops detected" assertion when model exceeds 4GB. [David Hewson]
**** Fix display %m names inside named blocks.
* Verilator 3.633 2/7/2007
*** Add --trace-depth option for minimizing VCD file size. [Emerson Suguimoto]
*** With VL_DEBUG, show wires causing convergence errors. [Mike Shinkarovsky]
**** Fix isolate_assignments when many signals per always. [Mike Shinkarovsky]
**** Fix isolate_assignments across task/func temporaries. [Mike Shinkarovsky]
**** Fix $display's with array select followed by wide AND. [David Hewson]
* Verilator 3.632 1/17/2007 * Verilator 3.632 1/17/2007
*** Add /*verilator isolate_asignments*/ attribute. [Mike Shinkarovsky] *** Add /*verilator isolate_assignments*/ attribute. [Mike Shinkarovsky]
* Verilator 3.631 1/2/2007 * Verilator 3.631 1/2/2007
@@ -83,7 +170,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Removed coverage request variable; see Coverage limitations in docs. **** Removed coverage request variable; see Coverage limitations in docs.
**** Fix DOS carrage returns in multiline defines. [Ralf Karge] **** Fix DOS carriage returns in multiline defines. [Ralf Karge]
**** Fix printf format warnings on 64-bit linux. **** Fix printf format warnings on 64-bit linux.
@@ -95,7 +182,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Added --inhibit-sim flag for environments using old __Vm_inhibitSim. *** Added --inhibit-sim flag for environments using old __Vm_inhibitSim.
*** Added `systemc_dtor for destructor extentions. [Allan Cochrane] *** Added `systemc_dtor for destructor extensions. [Allan Cochrane]
*** Added -MP to make phony dependencies, ala GCC's. *** Added -MP to make phony dependencies, ala GCC's.
@@ -130,7 +217,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix extraneous UNSIGNED warning when comparing genvars. [David Hewson] **** Fix extraneous UNSIGNED warning when comparing genvars. [David Hewson]
**** Fix extra whitespace in $display %c. [by David Addison] **** Fix extra white space in $display %c. [by David Addison]
**** vl_finish and vl_fatal now print via VL_PRINTF rather then cerr/cout. **** vl_finish and vl_fatal now print via VL_PRINTF rather then cerr/cout.
@@ -233,7 +320,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix functions where regs are declared before inputs. [Danny Ding] **** Fix functions where regs are declared before inputs. [Danny Ding]
**** Fix bad deep expressions with bitselects and rotate. [Prabhat Gupta] **** Fix bad deep expressions with bit-selects and rotate. [Prabhat Gupta]
* Verilator 3.500 10/30/2005 Stable * Verilator 3.500 10/30/2005 Stable
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# This file is part of Verilator. # This file is part of Verilator.
# #
# Author: Wilson Snyder <[email protected]> or <[email protected]> # Author: Wilson Snyder <[email protected]>
# #
# Code available from: http://www.veripool.com/verilator # Code available from: http://www.veripool.com/verilator
# #
+11 -1
View File
@@ -26,11 +26,11 @@ Features:
Points should be per-scope like everything else rather then per-module Points should be per-scope like everything else rather then per-module
Expression coverage (see notes) Expression coverage (see notes)
More Verilog 2001 Support More Verilog 2001 Support
C-style function and task arguments. [Wim Michiels]
(* *) Attributes (just ignore -- preprocessor?) (* *) Attributes (just ignore -- preprocessor?)
Real numbers (NEVER) Real numbers (NEVER)
Recursive functions (NEVER) Recursive functions (NEVER)
Verilog configuration files (NEVER) Verilog configuration files (NEVER)
DPI to define C/C++ calls from Verilog
Long-term Features Long-term Features
Assertions Assertions
@@ -47,6 +47,10 @@ Testing:
Better graph viewer with search and zoom Better graph viewer with search and zoom
Port and test against opencores.org code Port and test against opencores.org code
Usability:
Better reporting of unopt problems, including what lines of code
Report more errors (all of them?) before exiting [Eugene Weber]
Performance: Performance:
Constant propagation Constant propagation
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF)) Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
@@ -99,6 +103,12 @@ Performance:
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b). If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal) Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
All of the temp vars that get set, exp pre_ vars and never feedback
(not flops) don't need to be stored in the structs, but instead can
be per-invocation, and even better register-colored-like to reuse
the space. This will greatly reduce the data footprint.
//********************************************************************** //**********************************************************************
//* Detailed notes on 'todo' features //* Detailed notes on 'todo' features
+390 -89
View File
@@ -104,10 +104,11 @@ if ($Opt_Sp) {
} }
if ($Opt_Sp eq 'sp' || $Opt_Trace) { if ($Opt_Sp eq 'sp' || $Opt_Trace) {
if (!defined $ENV{SYSTEMPERL}) { if (!defined $ENV{SYSTEMPERL}) {
my $try = "$ENV{W}/hw/utils/perltools/SystemC/src"; my $try = "$ENV{W}/hw/utils/perltools/SystemC";
$ENV{SYSTEMPERL} = $try if -d $try; $ENV{SYSTEMPERL} = $try if -d $try;
} }
(defined $ENV{SYSTEMPERL}) or die "%Error: verilator: Need \$SYSTEMPERL in environment for --sp or --trace\nProbably System-Perl isn't installed, see http://www.veripool.com/systemperl.html\n"; (defined $ENV{SYSTEMPERL}) or die "%Error: verilator: Need \$SYSTEMPERL in environment for --sp or --trace\nProbably System-Perl isn't installed, see http://www.veripool.com/systemperl.html\n";
(-d "$ENV{SYSTEMPERL}/src") or die "%Error: verilator: \$SYSTEMPERL environment var doesn't seem to point to System-Perl kit\n";
} }
# Determine runtime flags # Determine runtime flags
@@ -190,6 +191,7 @@ Verilator - Convert Verilog code to C++/SystemC
verilator --cc [options] [top_level.v] [opt_c_files.cpp/c/cc] verilator --cc [options] [top_level.v] [opt_c_files.cpp/c/cc]
verilator --sc [options] [top_level.v] [opt_c_files.cpp/c/cc] verilator --sc [options] [top_level.v] [opt_c_files.cpp/c/cc]
verilator --sp [options] [top_level.v] [opt_c_files.cpp/c/cc] verilator --sp [options] [top_level.v] [opt_c_files.cpp/c/cc]
verilator --lint-only ...
=head1 DESCRIPTION =head1 DESCRIPTION
@@ -212,6 +214,66 @@ C++, and linked with the Verilated files.
The resulting executable will perform the actual simulation. The resulting executable will perform the actual simulation.
=head1 ARGUMENT SUMMARY
This is a short summary of the arguments to Verilator. See the detailed
descriptions in the next sections for more information.
{file.v} Verilog top level filenames
{file.c/cc/cpp} Optional C++ files to link in
--assert Enable all assertions
--bin <filename> Override Verilator binary
--cc Create C++ output
--compiler <compiler-name> Tune for specified C++ compiler
--coverage Enable all coverage
--coverage-line Enable line coverage
--coverage-user Enable PSL/SVL user coverage
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
--dump-tree Enable dumping .tree files
-E Preprocess, but do not compile
--exe Link to create executable
-f <file> Parse options from a file
--help Display this help.
-I<dir> Directory to search for includes
--inhibit-sim Create function to turn off sim
--inline-mult <value> Tune module inlining
--lint-only Lint, but do not make output
--MMD Create .d dependency files
--MP Create phony dependency targets
--Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes
--no-skip-identical Disable skipping identical output
-O0 Disable optimizations
-O3 High performance optimizations
-O<optimization-letter> Selectable optimizations
--output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .ccp functions
--pins64 Use uint64_t's for 33-64 bit sigs
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--private Debugging; see docs
--psl Enable PSL parsing
--public Debugging; see docs
--sc Create SystemC output
--sp Create SystemPerl output
--stats Create statistics file
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
-U<var> Undefine preprocessor define
--underline-zero Zero signals with leading _'s
-v <filename> Verilog library
-Werror-<message> Convert warning to error
-Wno-<message> Disable warning
-x-assign <mode> Initially assign Xs to this value
-y <dir> Directory to search for modules
+define+<var>+<value> Set preprocessor define
+incdir+<dir> Directory to search for includes
+libext+<ext>+[ext]... Extensions for finding modules
=head1 ARGUMENTS =head1 ARGUMENTS
=over 4 =over 4
@@ -244,6 +306,27 @@ output files.
Specifies C++ without SystemC output mode; see also --sc and --sp. Specifies C++ without SystemC output mode; see also --sc and --sp.
=item --compiler I<compiler-name>
Enables tunings and work-arounds for the specified C++ compiler.
=over 4
=item gcc
Tune for Gnu C++, although generated code should work on almost any
compliant C++ compiler. Currently the default.
=item msvc
Tune for Microsoft Visual C++. This may reduce execution speed as it
enables several workarounds to avoid silly hardcoded limits in MSVC++.
This includes breaking deeply nested parenthesized expressions into
sub-expressions to avoid error C1009, and breaking deep blocks into
functions to avoid error C1061.
=back
=item --coverage =item --coverage
Enables all forms of coverage, alias for --coverage-line, --coverage-user Enables all forms of coverage, alias for --coverage-line, --coverage-user
@@ -297,6 +380,12 @@ internal assertions, debugging messages, and intermediate form dump files.
Rarely needed. Enable internal debugging assertion checks, without Rarely needed. Enable internal debugging assertion checks, without
changing debug verbosity. Enabled automatically when --debug specified. changing debug verbosity. Enabled automatically when --debug specified.
=item --dump-tree
Rarely needed. Enable writing .tree debug files. This is enabled with
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
large and not desired.
=item -E =item -E
Preprocess the source code, but do not compile, as with 'gcc -E'. Output Preprocess the source code, but do not compile, as with 'gcc -E'. Output
@@ -324,9 +413,13 @@ change the SystemC modules instantiated.
Tune the inlining of modules. The default value of 2000 specifies that up Tune the inlining of modules. The default value of 2000 specifies that up
to 2000 new operations may be added to the model by inlining, if more then to 2000 new operations may be added to the model by inlining, if more then
this number of operations would result, the module is not inlined. Larger this number of operations would result, the module is not inlined. Larger
values, or -1 to inline everything, will lead to longer compile times, but values, or a value <= 1 will inline everything, will lead to longer compile
potentially faster runtimes. This setting is ignored for very small times, but potentially faster runtimes. This setting is ignored for very
modules; they will always be inlined, if allowed. small modules; they will always be inlined, if allowed.
=item --lint-only
Check the files for lint violations only, do not create any other output.
=item --MMD =item --MMD
@@ -422,8 +515,8 @@ enable functional coverage.
=item --public =item --public
This is only for debug, and may result in mis-simulation of generated This is only for historical debug use. Using it may result in
clocks. mis-simulation of generated clocks.
Declares all signals and modules public. This will turn off signal Declares all signals and modules public. This will turn off signal
optimizations as if all signals had a /*verilator public*/ comments and optimizations as if all signals had a /*verilator public*/ comments and
@@ -449,6 +542,13 @@ Adds waveform tracing code to the model. Having tracing compiled in may
result in some small performance losses, even when waveforms are not turned result in some small performance losses, even when waveforms are not turned
on during model execution. on during model execution.
=item --trace-depth I<levels>
Specify the number of levels deep to enable tracing, for example
--trace-level 1 to only see the top level's signals. Defaults to the
entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size.
=item --underline-zero =item --underline-zero
Rarely needed. Signals starting with a underline should be initialized to Rarely needed. Signals starting with a underline should be initialized to
@@ -543,6 +643,7 @@ We'll compile this example into C++.
int main(int argc, char **argv, char **env) { int main(int argc, char **argv, char **env) {
Vour* top = new Vour; Vour* top = new Vour;
while (!Verilated::gotFinish()) { top->eval(); } while (!Verilated::gotFinish()) { top->eval(); }
exit(0);
} }
EOF EOF
@@ -596,13 +697,13 @@ This is an example similar to the above, but using SystemPerl.
cat <<EOF >sc_main.cpp cat <<EOF >sc_main.cpp
#include "Vour.h" #include "Vour.h"
#include "systemperl.h"
int sc_main(int argc, char **argv) { int sc_main(int argc, char **argv) {
sc_clock clk ("clk",10, 0.5, 3, true); sc_clock clk ("clk",10, 0.5, 3, true);
Vour* top; Vour* top;
SP_CELL (top, Vour); top = new Vour("top"); // SP_CELL (top, Vour);
SP_PIN (top, clk, clk); top->clk(clk); // SP_PIN (top, clk, clk);
while (!Verilated::gotFinish()) { sc_start(1); } while (!Verilated::gotFinish()) { sc_start(1); }
exit(0);
} }
EOF EOF
@@ -677,11 +778,13 @@ fast path, mostly code that is executed every cycle. OPT_SLOW specifies
optimizations for slow-path files (plus tracing), which execute only optimizations for slow-path files (plus tracing), which execute only
rarely, yet take a long time to compile with optimization on. OPT rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those specifies overall optimization and affects all compiles, including those
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2". Nearly the OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
same results can be had with much better compile times with OPT_FAST="-O1 with "-static". Nearly the same results can be had with much better
-fstrict-aliasing". Unfortunately, using the optimizer with SystemC files compile times with OPT_FAST="-O1 -fstrict-aliasing".
can result in compiles taking several minutes. (The SystemC libraries have
many little inlined functions that drive the compiler nuts.) Unfortunately, using the optimizer with SystemC files can result in
compiles taking several minutes. (The SystemC libraries have many little
inlined functions that drive the compiler nuts.)
For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have
optimization bugs around pointer aliasing detection, which can result in 2x optimization bugs around pointer aliasing detection, which can result in 2x
@@ -693,16 +796,19 @@ feedback driven compilation. With GCC, using -fprofile-arcs, then
You may uncover further tuning possibilities by profiling the Verilog code. You may uncover further tuning possibilities by profiling the Verilog code.
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
either oprofile or gprof to see where in the C++ code, and by looking at either oprofile or gprof to see where in the C++ code the time is spent.
the mangled function name where in the Verilog code most of the time is Run the gprof output through verilator_profcfunc and it will tell you what
being spent. Verilog line numbers on which most of the time is being spent.
When done, please let the author know the results. I like to keep tabs on When done, please let the author know the results. I like to keep tabs on
how Verilator compares, and may be able to suggest additional improvements. how Verilator compares, and may be able to suggest additional improvements.
=head1 FILES =head1 FILES
Verilator creates the following files: All output files are placed in the output directory name specified with the
-Mdir option, or "obj_dir" if not specified.
Verilator creates the following files in the output directory:
{prefix}.mk // Make include file for compiling {prefix}.mk // Make include file for compiling
{prefix}_classes.mk // Make include file with class names {prefix}_classes.mk // Make include file with class names
@@ -714,7 +820,7 @@ For -cc and -sc mode, it also creates:
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files {prefix}{each_verilog_module}.cpp // Lower level internal C++ files
{prefix}{each_verilog_module}.h // Lower level internal header files {prefix}{each_verilog_module}.h // Lower level internal header files
For -sp mode, it also creates: For -sp mode, instead of .cpp and .h it creates:
{prefix}.sp // Top level SystemC file {prefix}.sp // Top level SystemC file
{prefix}{each_verilog_module}.sp // Lower level internal SC files {prefix}{each_verilog_module}.sp // Lower level internal SC files
@@ -736,7 +842,8 @@ It also creates internal files that can be mostly ignored:
{prefix}{misc}.dot // Debugging graph files (--debug) {prefix}{misc}.dot // Debugging graph files (--debug)
{prefix}{misc}.tree // Debugging files (--debug) {prefix}{misc}.tree // Debugging files (--debug)
After running Make, the compiler will produce the following: After running Make, the C++ compiler should produce the following:
{prefix} // Final executable (w/--exe argument) {prefix} // Final executable (w/--exe argument)
{prefix}__ALL.a // Library of all Verilated objects {prefix}__ALL.a // Library of all Verilated objects
{prefix}{misc}.o // Intermediate objects {prefix}{misc}.o // Intermediate objects
@@ -883,30 +990,48 @@ The target system may also require edits to the Makefiles, the simple
Makefiles produced by Verilator presume the target system is the same type Makefiles produced by Verilator presume the target system is the same type
as the build system. as the build system.
=head1 VERILOG 2001 SUPPORT =head1 VERILOG 2001 (IEEE 1364-2001) SUPPORT
Verilator supports the more common Verilog 2001 language features. This Verilator supports almost all Verilog 2001 language features. This
includes signed numbers, "always @*", comma separated sensitivity lists, includes signed numbers, "always @*", comma separated sensitivity lists,
generate statements, multidimensional arrays, localparam, and C-style generate statements, multidimensional arrays, localparam, and C-style
declarations inside port lists. declarations inside port lists.
=head1 SYSTEMVERILOG 3.1 SUPPORT =head1 VERILOG 2005 (IEEE 1364-2005) SUPPORT
Verilator currently has very minimal support for SystemVerilog. Verilator supports the `begin_keywords and `end_keywords compiler
directives.
Verilator implement the full SystemVerilog 3.1 preprocessor subset, Verilator partially supports the uwire keyword.
including function call-like preprocessor defines. Verilator also
implements $bits, $countones, $isunknown, $onehot, and $onehot0, =head1 SYSTEMVERILOG (IEEE 1800-2005) SUPPORT
always_comb, always_ff, always_latch, and final.
Verilator currently has very minimal support for SystemVerilog. As
SystemVerilog features enter common usage they will be added. Contact the
author if a feature you need is missing.
Verilator implements the full SystemVerilog 1800-2005 preprocessor,
including function call-like preprocessor defines.
Verilator supports ==? and !=? operators, $bits, $countones, $error,
$fatal, $info, $isunknown, $onehot, $onehot0, $warning, always_comb,
always_ff, always_latch, do-while, and final.
It also supports .name and .* interconnection.
Verilator partially supports assert.
=head1 SUGAR/PSL SUPPORT =head1 SUGAR/PSL SUPPORT
With the --assert switch, Verilator is just beginning to support the Most future work is being directed towards improving SystemVerilog
Property Specification Language (PSL), specifically the simple subset assertions instead of PSL. If you are using these PSL features, please
without time-branching primitives. Verilator currently only converts PSL contact the author as they may be depreciated in future versions.
With the --assert switch, Verilator enables support of the Property
Specification Language (PSL), specifically the simple PSL subset without
time-branching primitives. Verilator currently only converts PSL
assertions to simple "if (...) error" statements, and coverage statements assertions to simple "if (...) error" statements, and coverage statements
to increment the line counters described in the coverage section. If you to increment the line counters described in the coverage section.
need additional features please contact the author.
Verilator implements these keywords: assert, assume (same as assert), Verilator implements these keywords: assert, assume (same as assert),
default (for clocking), countones, cover, isunknown, onehot, onehot0, default (for clocking), countones, cover, isunknown, onehot, onehot0,
@@ -915,18 +1040,16 @@ report, true.
Verilator implements these operators: -> (logical if). Verilator implements these operators: -> (logical if).
Verilator does not support SEREs yet. All assertion and coverage Verilator does not support SEREs yet. All assertion and coverage
statements must be simple expressions that complete in one cycle. statements must be simple expressions that complete in one cycle. PSL
(Arguably SEREs are the whole point of PSL, but one must start somewhere.) vmode/vprop/vunits are not supported. PSL statements must be in the module
they reference, at the module level where you would put an
PSL vmode/vprop/vunits are not supported. PSL statements must be in the
module they reference, at the module level where you would put an
initial... statement. initial... statement.
Verilator only supports (posedge CLK) or (negedge CLK), where CLK is the Verilator only supports (posedge CLK) or (negedge CLK), where CLK is the
name of a one bit signal. You may not use arbitrary expressions as name of a one bit signal. You may not use arbitrary expressions as
assertion clocks. assertion clocks.
=head1 SYNTHESIS DIRECTIVE ASSERTIONS =head1 SYNTHESIS DIRECTIVE ASSERTION SUPPORT
With the --assert switch, Verilator reads any "//synopsys full_case" or "// With the --assert switch, Verilator reads any "//synopsys full_case" or "//
synopsys parallel_case" directives. The same applies to any "//cadence" or synopsys parallel_case" directives. The same applies to any "//cadence" or
@@ -1052,7 +1175,9 @@ around compiler specific constructs.
=item `verilog =item `verilog
Switch back to processing Verilog code, after a `systemc_... mode switch. Switch back to processing Verilog code after a `systemc_... mode switch.
The Verilog code returns to the last language mode specified with
`begin_keywords, or SystemVerilog if none were specified.
=item /*verilator clock_enable*/ =item /*verilator clock_enable*/
@@ -1075,28 +1200,7 @@ submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not
allow "." in signal names. SystemPerl when tracing such signals will allow "." in signal names. SystemPerl when tracing such signals will
replace the __DOT__ with the period. replace the __DOT__ with the period.
=item /*verilator lint_off I<msg>*/ =item /*verilator isolate_assignments*/
Disable the specified warning message for any warnings following the comment.
=item /*verilator lint_on I<msg>*/
Re-enable the specified warning message for any warnings following the comment.
=item /*verilator no_inline_task*/
Used in a function or task variable definition section to specify the
function or task should not be inlined into where it is used. This may
reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself.
=item /*verilator sc_clock*/
Used after a input declaration to indicate the signal should be declared in
SystemC as a sc_clock instead of a bool.
=item /*verilator isolate_asignments*/
Used after a signal declaration to indicate the assignments to this signal Used after a signal declaration to indicate the assignments to this signal
in any blocks should be isolated into new blocks. When there is a large in any blocks should be isolated into new blocks. When there is a large
@@ -1105,7 +1209,7 @@ this to the signal causing a false loop may clear up the problem.
IE, with the following IE, with the following
reg splitme /* verilator isolate_asignments*/; reg splitme /* verilator isolate_assignments*/;
always @* begin always @* begin
if (....) begin if (....) begin
splitme = ....; splitme = ....;
@@ -1131,21 +1235,48 @@ It would then internally break it into (sort of):
end end
end end
=item /*verilator tracing_off*/ =item /*verilator lint_off I<msg>*/
Disable waveform tracing for all future signals that are declared in this Disable the specified warning message for any warnings following the comment.
module. Often this is placed just after a primitive's module statement, so
that the entire module is not traced.
=item /*verilator tracing_on*/ =item /*verilator lint_on I<msg>*/
Re-enable waveform tracing for all future signals that are declared. Re-enable the specified warning message for any warnings following the comment.
=item /*verilator lint_restore*/
After a /*verilator lint_save*/, pop the stack containing lint message
state. Often this is useful at the bottom of include files.
=item /*verilator lint_save*/
Push the current state of what lint messages are turned on or turned off to
a stack. Later meta-comments may then lint_on or lint_off specific
messages, then return to the earlier message state by using /*verilator
lint_restore*/. For example:
// verilator lint_save
// verilator lint_off SOME_WARNING
... // code needing SOME_WARNING turned off
// verilator lint_restore
If SOME_WARNING was on before the lint_off, it will now be restored to on,
and if it was off before the lint_off it will remain off.
=item /*verilator no_inline_task*/
Used in a function or task variable definition section to specify the
function or task should not be inlined into where it is used. This may
reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself.
=item /*verilator public*/ (variable) =item /*verilator public*/ (variable)
Used after a input, output, register, or wire declaration to indicate the Used after a input, output, register, or wire declaration to indicate the
signal should be declared so that C code may read or write the value signal should be declared so that C code may read or write the value
of the signal. of the signal. This will also declare this module public, otherwise use
/*verilator public_flat*/.
=item /*verilator public*/ (task/function) =item /*verilator public*/ (task/function)
@@ -1167,6 +1298,14 @@ stored state (flops) should be written, as the model will NOT notice
changes made to variables in these functions. (Same as when a signal is changes made to variables in these functions. (Same as when a signal is
declared public.) declared public.)
=item /*verilator public_flat*/ (variable)
Used after a input, output, register, or wire declaration to indicate the
signal should be declared so that C code may read or write the value of the
signal. This will not declare this module public, which means the name of
the signal or path to it may change based upon the module inlining which
takes place.
=item /*verilator public_module*/ =item /*verilator public_module*/
Used after a module statement to indicate the module should not be inlined Used after a module statement to indicate the module should not be inlined
@@ -1175,6 +1314,21 @@ Verilator automatically sets this attribute when the module contains any
public signals or `systemc_ directives. Also set for all modules when public signals or `systemc_ directives. Also set for all modules when
using the --public switch. using the --public switch.
=item /*verilator sc_clock*/
Used after a input declaration to indicate the signal should be declared in
SystemC as a sc_clock instead of a bool.
=item /*verilator tracing_off*/
Disable waveform tracing for all future signals that are declared in this
module. Often this is placed just after a primitive's module statement, so
that the entire module is not traced.
=item /*verilator tracing_on*/
Re-enable waveform tracing for all future signals that are declared.
=back =back
=head1 LANGUAGE LIMITATIONS =head1 LANGUAGE LIMITATIONS
@@ -1220,6 +1374,10 @@ users to use these names, so it should not matter.
If you are having trouble determining where a dotted path goes wrong, note If you are having trouble determining where a dotted path goes wrong, note
that Verilator will print a list of known scopes to help your debugging. that Verilator will print a list of known scopes to help your debugging.
=head2 Floating Point
Floating Point numbers are not synthesizable, and so not supported.
=head2 Latches =head2 Latches
Verilator is optimized for edge sensitive (flop based) designs. It will Verilator is optimized for edge sensitive (flop based) designs. It will
@@ -1272,17 +1430,12 @@ prepended. (If you don't know what this means, Verilator will do what you
probably expect -- what C does. The default behavior of Verilog is probably expect -- what C does. The default behavior of Verilog is
different.) different.)
=head2 Generate Statements
All instantiations and variables in generate blocks will be placed under
hierarchy that has a name different from that required in the language
specification.
=head2 Generated Clocks =head2 Generated Clocks
Verilator attempts to deal with generated clocks correctly, however new Verilator attempts to deal with generated clocks correctly, however new
cases may turn up bugs in the scheduling algorithm. The safest option is cases may turn up bugs in the scheduling algorithm. The safest option is
to have all clocks as primary inputs to the model. to have all clocks as primary inputs to the model, or wires directly
attached to primary inputs.
=head2 Ranges must be big-bit-endian =head2 Ranges must be big-bit-endian
@@ -1332,6 +1485,56 @@ will give a width warning and wrap around the power-of-2 size. For
non-power-of-2 sizes, it will return a unspecified constant of the non-power-of-2 sizes, it will return a unspecified constant of the
appropriate width. appropriate width.
=head2 Assertions
Verilator is beginning to add support for assertions. Verilator currently
only converts assertions to simple "if (...) error" statements, and
coverage statements to increment the line counters described in the
coverage section.
Verilator does not support SEREs yet. All assertion and coverage
statements must be simple expressions that complete in one cycle.
(Arguably SEREs are much of the point, but one must start somewhere.)
=head1 LANGUAGE KEYWORD LIMITATIONS
This section describes specific limitations for each language keyword.
=over 4
=item `__FILE__, `__LINE__, `begin_keywords, `begin_keywords, `begin_keywords,
`begin_keywords, `begin_keywords, `define, `else, `elsif, `end_keywords,
`endif, `error, `ifdef, `ifndef, `include, `line, `systemc_ctor,
`systemc_dtor, `systemc_header, `systemc_imp_header,
`systemc_implementation, `systemc_interface, `timescale, `undef, `verilog
Fully supported.
=item always, always_comb, always_ff, always_latch, and, assign, begin,
buf, case, casex, casez, default, defparam, do-while, else, end, endcase,
endfunction, endgenerate, endmodule, endspecify, endtask, final, for,
function, generate, genvar, if, initial, inout, input, integer, localparam,
macromodule, module, nand, negedge, nor, not, or, output, parameter,
posedge, reg, scalared, signed, supply0, supply1, task, tri, vectored,
while, wire, xnor, xor
Generally supported.
=item specify specparam
All specify blocks and timing checks are ignored.
=item uwire
Verilator does not perform warning checking on uwires, it treats the uwire
keyword as if it were the normal wire keyword.
=item $bits, $countones, $error, $fatal, $finish, $info, $isunknown,
$onehot, $onehot0, $readmemb, $readmemh, $signed, $stop, $time, $unsigned,
$warning.
Generally supported.
=item $display, $write, $fdisplay, $fwrite =item $display, $write, $fdisplay, $fwrite
$display and friends must have a constant format string as the first $display and friends must have a constant format string as the first
@@ -1352,12 +1555,23 @@ are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a
reg [63:0] rather then an integer. The define `verilator_file_descriptor in reg [63:0] rather then an integer. The define `verilator_file_descriptor in
verilated.v can be used to hide this difference. verilated.v can be used to hide this difference.
=item $fullskew, $hold, $nochange, $period, $recovery, $recrem, $removal,
$setup, $setuphold, $skew, $timeskew, $width
All specify blocks and timing checks are ignored.
=item $readmemb, $readmemh =item $readmemb, $readmemh
Read memory commands should work properly. Note Verilator and the Verilog Read memory commands should work properly. Note Verilator and the Verilog
specification does not include support for readmem to multi-dimensional specification does not include support for readmem to multi-dimensional
arrays. arrays.
=item $realtime
Treated as $time.
=back
=head1 ERRORS AND WARNINGS =head1 ERRORS AND WARNINGS
Warnings may be disabled in two ways. First, when the warning is Warnings may be disabled in two ways. First, when the warning is
@@ -1380,9 +1594,9 @@ List of all warnings:
=item BLKANDNBLK =item BLKANDNBLK
Error that a variable comes from a mix of blocked and non-blocking BLKANDNBLK is an error that a variable comes from a mix of blocked and
assignments. Generally, this is caused by a register driven by both combo non-blocking assignments. Generally, this is caused by a register driven
logic and a flop: by both combo logic and a flop:
always @ (posedge clk) foo[0] <= ... always @ (posedge clk) foo[0] <= ...
always @* foo[1] = ... always @* foo[1] = ...
@@ -1398,6 +1612,9 @@ This is good coding practice anyways.
It is also possible to disable this error when one of the assignments is It is also possible to disable this error when one of the assignments is
inside a public task. inside a public task.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item CASEINCOMPLETE =item CASEINCOMPLETE
Warns that inside a case statement there is a stimulus pattern for which Warns that inside a case statement there is a stimulus pattern for which
@@ -1405,6 +1622,9 @@ there is no case item specified. This is bad style, if a case is
impossible, it's better to have a "default: $stop;" or just "default: ;" so impossible, it's better to have a "default: $stop;" or just "default: ;" so
that any design assumption violations will be discovered in simulation. that any design assumption violations will be discovered in simulation.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item CASEOVERLAP =item CASEOVERLAP
Warns that inside a case statement you have case values which are detected Warns that inside a case statement you have case values which are detected
@@ -1412,17 +1632,26 @@ to be overlapping. This is bad style, as moving the order of case values
will cause different behavior. Generally the values can be respecified to will cause different behavior. Generally the values can be respecified to
not overlap. not overlap.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item CASEX =item CASEX
Warns that it is simply better style to use casez, and C<?> in place of Warns that it is simply better style to use casez, and C<?> in place of
C<x>'s. See C<x>'s. See
L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf> L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf>
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item CMPCONST =item CMPCONST
Warns that you are comparing a value in a way that will always be constant. Warns that you are comparing a value in a way that will always be constant.
For example "X > 1" will always be true when X is a single bit wide. For example "X > 1" will always be true when X is a single bit wide.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item COMBDLY =item COMBDLY
Warns that you have a delayed assignment inside of a combinatorial block. Warns that you have a delayed assignment inside of a combinatorial block.
@@ -1432,6 +1661,9 @@ Verilator, like synthesis, will convert this to a non-delayed assignment,
which may result in logic races or other nasties. See which may result in logic races or other nasties. See
L<http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf> L<http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf>
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item GENCLK =item GENCLK
Warns that the specified signal is generated, but is also being used as a Warns that the specified signal is generated, but is also being used as a
@@ -1442,6 +1674,9 @@ generate ALL clocks outside in C++/SystemC and make them primary inputs to
your Verilog model. (However once need to you have even one, don't sweat your Verilog model. (However once need to you have even one, don't sweat
additional ones.) additional ones.)
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item IMPLICIT =item IMPLICIT
Warns that a wire is being implicitly declared (it is a single bit wide Warns that a wire is being implicitly declared (it is a single bit wide
@@ -1451,18 +1686,38 @@ signal before it is implicitly declared by a cell, and can lead to dangling
nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode for nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode for
Emacs, available from L<http://www.veripool.com/> Emacs, available from L<http://www.veripool.com/>
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item IMPURE =item IMPURE
Warns that a task or function that has been marked with /*verilator Warns that a task or function that has been marked with /*verilator
no_inline_task*/ references variables that are not local to the task. no_inline_task*/ references variables that are not local to the task.
Verilator cannot schedule these variables correctly. Verilator cannot schedule these variables correctly.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item MULTIDRIVEN =item MULTIDRIVEN
Warns that the specified signal comes from multiple always blocks. This is Warns that the specified signal comes from multiple always blocks. This is
often unsupported by synthesis tools, and is considered bad style. It will often unsupported by synthesis tools, and is considered bad style. It will
also cause longer runtimes due to reduced optimizations. also cause longer runtimes due to reduced optimizations.
Ignoring this warning will only slow simulations, it will simulate
correctly.
=item MULTITOP
Error that there are multiple top level modules, that is modules not
instantiated by any other module. Verilator only supports a single top
level, if you need more, create a module that wraps all of the top modules.
Often this error is because some low level cell is being read in, but is
not really needed. The best solution is to insure that each module is in a
unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y.
=item TASKNSVAR =item TASKNSVAR
Error when a call to a task or function has a output from that task tied to Error when a call to a task or function has a output from that task tied to
@@ -1490,6 +1745,9 @@ cases would result in simulator mismatches.
Warns that the specified signal is never sourced. Warns that the specified signal is never sourced.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item UNOPT =item UNOPT
Warns that due to some construct, optimization of the specified signal or Warns that due to some construct, optimization of the specified signal or
@@ -1503,6 +1761,9 @@ blocks in both submodules, even if they are unrelated always blocks. This
affects performance because Verilator would have to evaluate each submodule affects performance because Verilator would have to evaluate each submodule
multiple times to stabilize the signals crossing between the modules. multiple times to stabilize the signals crossing between the modules.
Ignoring this warning will only slow simulations, it will simulate
correctly.
=item UNOPTFLAT =item UNOPTFLAT
Warns that due to some construct, optimization of the specified signal is Warns that due to some construct, optimization of the specified signal is
@@ -1552,18 +1813,27 @@ clock_enable meta comment described above.
The UNOPTFLAT warning may also occur where outputs from a block of logic The UNOPTFLAT warning may also occur where outputs from a block of logic
are independent, but occur in the same always block. To fix this, use the are independent, but occur in the same always block. To fix this, use the
isolate_asignments meta comment described above. isolate_assignments meta comment described above.
Ignoring this warning will only slow simulations, it will simulate
correctly.
=item UNSIGNED =item UNSIGNED
Warns that you are comparing a unsigned value in a way that implies it is Warns that you are comparing a unsigned value in a way that implies it is
signed, for example "X < 0" will always be true when X is unsigned. signed, for example "X < 0" will always be true when X is unsigned.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item UNUSED =item UNUSED
Warns that the specified signal is never sinked. This is a future message, Warns that the specified signal is never sinked. This is a future message,
currently Verilator will not produce this warning. currently Verilator will not produce this warning.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item VARHIDDEN =item VARHIDDEN
Warns that a task, function, or begin/end block is declaring a variable by Warns that a task, function, or begin/end block is declaring a variable by
@@ -1571,6 +1841,9 @@ the same name as a variable in the upper level module or begin/end block
(thus hiding the upper variable from being able to be used.) Rename the (thus hiding the upper variable from being able to be used.) Rename the
variable to avoid confusion when reading the code. variable to avoid confusion when reading the code.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item WIDTH =item WIDTH
Warns that based on width rules of Verilog, two operands have different Warns that based on width rules of Verilog, two operands have different
@@ -1589,6 +1862,9 @@ The best fix, which clarifies intent and will also make all tools happy is:
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]}; wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=back =back
The following describes the less obvious errors: The following describes the less obvious errors:
@@ -1616,12 +1892,18 @@ For example:
always @ (b) a=b always @ (b) a=b
will toggle forever and thus the executable will give the didn't converge will toggle forever and thus the executable will give the didn't converge
error to prevent an infinite loop. To debug this, compile the Verilated error to prevent an infinite loop.
.cpp files with -DVL_DEBUG, then call Verilated::debug(1) in your main.cpp.
This will cause each module to print a message when it's invoked. From To debug this, run Verilator with --profile-cfuncs. Run make on the
that it should be obvious what routine(s) are part of the infinite loop. generated files with "OPT=-DVL_DEBUG". Then call Verilated::debug(1) in
Then in Gdb, add a break point at the routine entry point and "print *this" your main.cpp.
on each loop so you can see what variables are changing each invocation.
This will cause each change in a variable to print a message. Near the
bottom you'll see the code and variable that causes the problem. For the
program above:
CHANGE: filename.v:1: b
CHANGE: filename.v:2: a
=back =back
@@ -1656,6 +1938,25 @@ so your simulator shouldn't have to be -- and Verilator is closer to the
synthesis interpretation, so this is a good thing for getting working synthesis interpretation, so this is a good thing for getting working
silicon. silicon.
=item May programs I create with Verilator remain under my own copyright?
Yes, it's just like using GCC on your programs. If you change Verilator
itself, you must make the source code available under the GNU Public
License. However, the include and generated files use the GNU Lesser
Public License, which means that files using them are NOT required to be released.
You also have the option of using the Perl Artistic License, which again
does not require you release your Verilog or generated code.
=item Why is running Verilator so slow?
Verilator needs more memory then the resulting simulator will require, as
Verilator creates internally all of the state of the resulting simulator in
order to optimize it. If it takes more then a minute or so (and you're not
using --debug), see if your machine is paging; most likely you need to run
it on a machine with more memory. Verilator is a full 64 bit application
and may use more then 4GB, but about 1GB is the maximum typically needed.
=item How do I generate waveforms (traces) in C++? =item How do I generate waveforms (traces) in C++?
See the next question for SystemC mode. See the next question for SystemC mode.
@@ -1864,7 +2165,7 @@ Communications, Sun Microsystems, Nauticus Networks, and SiCortex.
The people who have contributed code or other major functionality are Paul The people who have contributed code or other major functionality are Paul
Wasson, Duane Galbi, and Wilson Snyder. Major testers include Jeff Dutton, Wasson, Duane Galbi, and Wilson Snyder. Major testers include Jeff Dutton,
Ralf Karge and Wim Michiels. Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
Some of the people who have provided ideas and feedback for Verilator Some of the people who have provided ideas and feedback for Verilator
include Hans Van Antwerpen, Jens Arm, David Black, Gregg Bouchard, Chris include Hans Van Antwerpen, Jens Arm, David Black, Gregg Bouchard, Chris
@@ -1891,7 +2192,7 @@ Major concepts by Paul Wasson and Duane Galbi.
=head1 SEE ALSO =head1 SEE ALSO
L<systemperl>, L<vcoverage>, L<make> L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>
=cut =cut
+2 -1
View File
@@ -35,12 +35,13 @@ my $Opt_A;
my $Opt_B; my $Opt_B;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions (
"help" => \&usage, "help" => \&usage,
"debug" => \&debug, "debug" => \&debug,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
usage(); die "%Error: Bad usage, try 'verilator_difftree --help'\n";
} }
defined $Opt_A or die "%Error: No old diff filename\n"; defined $Opt_A or die "%Error: No old diff filename\n";
+211
View File
@@ -0,0 +1,211 @@
: # -*-Mode: perl;-*- use perl, wherever it is
eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
# $Id$
######################################################################
#
# Copyright 2007-2007 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
######################################################################
require 5.006_001;
use warnings;
use Getopt::Long;
use IO::File;
use Pod::Usage;
use strict;
use vars qw ($Debug);
#======================================================================
#======================================================================
# main
$Debug = 0;
my $Opt_File;
autoflush STDOUT 1;
autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
if (! GetOptions (
"help" => \&usage,
"debug" => \&debug,
"<>" => \&parameter,
)) {
die "%Error: Bad usage, try 'verilator_profcfunc --help'\n";
}
defined $Opt_File or die "%Error: No filename given\n";
profcfunc($Opt_File);
#----------------------------------------------------------------------
sub usage {
print '$Id$ ', "\n";
pod2usage(-verbose=>2, -exitval => 2);
exit (1);
}
sub debug {
$Debug = 1;
}
sub parameter {
my $param = shift;
if (!defined $Opt_File) {
$Opt_File = $param;
} else {
die "%Error: Unknown parameter: $param\n";
}
}
#######################################################################
sub profcfunc {
my $filename = shift;
# Remove hex numbers before diffing
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
my %funcs;
while (defined (my $line=$fh->getline())) {
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+.*\s+(\S+)\s*$/) {
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
$funcs{$func}{pct} += $pct;
$funcs{$func}{sec} += $sec;
$funcs{$func}{calls} += $calls;
}
}
$fh->close;
# Find modules
my %verilated_mods;
foreach my $func (keys %funcs) {
if ($func =~ /(.*)::_eval\(.*__Syms.*\)$/) {
$verilated_mods{$1} = qr/^$1/;
}
}
# Resort by Verilog name
my %vfuncs;
my %groups;
foreach my $func (keys %funcs) {
my $vfunc = $func;
my $design;
foreach my $vde (keys %verilated_mods) {
if ($func =~ /$verilated_mods{$vde}/) {
$design=$vde;
last;
}
}
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) {
$vfunc = sprintf("VBlock %s:%d", $1, $2);
$groups{"Verilog Blocks under $design"} += $funcs{$func}{pct};
} else {
if ($design) {
$vfunc = sprintf("VCommon %s", $func);
$groups{"Common code under $design"} += $funcs{$func}{pct};
} else {
$vfunc = sprintf("C++ %s", $func);
$groups{'C++'} += $funcs{$func}{pct};
}
}
$vfuncs{$vfunc} = $funcs{$func};
}
print("Overall summary:\n");
print(" % time\n");
foreach (sort (keys %groups)) {
printf(" %6.2f In all %s\n", $groups{$_}, $_);
}
print("\n");
print("Verilog code profile:\n");
print(" These are split into three categories:\n");
print(" C++: Time in non-Verilated C++ code\n");
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
print("\n");
print(" % cumulative self \n");
print(" time seconds seconds calls type filename and line number\n");
my $cume = 0;
foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec}
|| $a cmp $b}
(keys %vfuncs)) {
$cume += $vfuncs{$func}{sec};
printf +("%6.2f %9.2f %8.2f %8d %s\n",
$vfuncs{$func}{pct},
$cume, $vfuncs{$func}{sec},
$vfuncs{$func}{calls},
$func);
}
}
#######################################################################
__END__
=pod
=head1 NAME
verilator_profcfunc - Read gprof report created with --profile-cfuncs
=head1 SYNOPSIS
verilator --profile-cfuncs ....
gcc --ggdb -pg ....
{run executable}
gprof
verilator_profcfuncs gprof.out
=head1 DESCRIPTION
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,
in each Verilog block.
=head1 ARGUMENTS
=over 4
=item --help
Displays this message and program version and exits.
=back
=head1 DISTRIBUTION
The latest version is available from L<http://www.veripool.com/>.
Copyright 2007-2007 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 or the Perl Artistic License.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
C<verilator>
=cut
######################################################################
### Local Variables:
### compile-command: "$V4/bin/verilator_profcfunc $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
### End:
+10 -1
View File
@@ -16,8 +16,17 @@ AC_PROG_CC
AC_PROG_CXX AC_PROG_CXX
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PATH_PROG(PERL,perl) AC_PATH_PROG(PERL,perl)
AC_PATH_PROG(YACC,bison) if test "x$PERL" = "x" ; then
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
fi
AC_PATH_PROG(LEX,flex) AC_PATH_PROG(LEX,flex)
if test "x$LEX" = "x" ; then
AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it])
fi
AC_PATH_PROG(YACC,bison)
if test "x$YACC" = "x" ; then
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
fi
dnl Checks for libraries. dnl Checks for libraries.
+4 -3
View File
@@ -3,7 +3,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// Verilator is distributed in the hope that it will be useful, // Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -31,7 +31,7 @@
//=========================================================================== //===========================================================================
// Global variables // Global variables
int Verilated::s_randReset = false; int Verilated::s_randReset = 0;
int Verilated::s_debug = 1; int Verilated::s_debug = 1;
bool Verilated::s_calcUnusedSigs = false; bool Verilated::s_calcUnusedSigs = false;
bool Verilated::s_gotFinish = false; bool Verilated::s_gotFinish = false;
@@ -72,7 +72,8 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
// Random reset -- Only called at init time, so don't inline. // Random reset -- Only called at init time, so don't inline.
IData VL_RAND32() { IData VL_RAND32() {
#ifdef _MSC_VER #if defined(_WIN32) && !defined(__CYGWIN__)
// Windows doesn't have lrand48(), although Cygwin does.
return (rand()<<16) | rand(); return (rand()<<16) | rand();
#else #else
return (lrand48()<<16) | lrand48(); return (lrand48()<<16) | lrand48();
+3 -3
View File
@@ -3,7 +3,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// Verilator is distributed in the hope that it will be useful, // Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -513,10 +513,10 @@ static inline IData VL_COUNTONES_W(int words, WDataInP lwp) {
} }
static inline IData VL_ONEHOT_I(IData lhs) { static inline IData VL_ONEHOT_I(IData lhs) {
return ((lhs & (lhs-1))==0 & lhs!=0); return (((lhs & (lhs-1))==0) & (lhs!=0));
} }
static inline IData VL_ONEHOT_Q(QData lhs) { static inline IData VL_ONEHOT_Q(QData lhs) {
return ((lhs & (lhs-1))==0 & lhs!=0); return (((lhs & (lhs-1))==0) & (lhs!=0));
} }
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) { static inline IData VL_ONEHOT_W(int words, WDataInP lwp) {
IData one=0; IData one=0;
+11 -6
View File
@@ -4,7 +4,7 @@
# #
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can # Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License. # Lesser General Public License or the Perl Artistic License.
###################################################################### ######################################################################
PERL = @PERL@ PERL = @PERL@
@@ -49,7 +49,12 @@ VPATH += $(VERILATOR_ROOT)/include
CPPFLAGS += $(OPT) CPPFLAGS += $(OPT)
CPPFLAGS += $(M32) CPPFLAGS += $(M32)
LDFLAGS += $(M32) LDFLAGS += $(M32)
# Allow upper level user makefiles to specify flags they want.
# These aren't ever set by Verilator, so users are free to override them.
CPPFLAGS += $(USER_CPPFLAGS)
LDFLAGS += $(USER_LDFLAGS)
# See the benchmarking section of bin/verilator. # See the benchmarking section of bin/verilator.
# Support class optimizations. This includes the tracing and symbol table. # Support class optimizations. This includes the tracing and symbol table.
@@ -84,8 +89,8 @@ endif
##### SystemPerl builds ##### SystemPerl builds
ifeq ($(VM_SP),1) ifeq ($(VM_SP),1)
CPPFLAGS += -I$(SYSTEMPERL) -I$(SYSTEMPERL)/src -DSYSTEMPERL CPPFLAGS += -I$(SYSTEMPERL)/src -DSYSTEMPERL
VPATH += $(SYSTEMPERL) $(SYSTEMPERL)/src VPATH += $(SYSTEMPERL)/src
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES)) VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
@@ -104,8 +109,8 @@ endif
ifeq ($(VM_PCLI),1) ifeq ($(VM_PCLI),1)
LIBS += -lm -lstdc++ LIBS += -lm -lstdc++
ifeq ($(VM_TRACE),1) ifeq ($(VM_TRACE),1)
CPPFLAGS += -I$(SYSTEMPERL) -I$(SYSTEMPERL)/src CPPFLAGS += -I$(SYSTEMPERL)/src
VPATH += $(SYSTEMPERL) $(SYSTEMPERL)/src VPATH += $(SYSTEMPERL)/src
endif endif
endif endif
+1 -1
View File
@@ -7,7 +7,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// This is distributed in the hope that it will be useful, // This is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
+6 -2
View File
@@ -3,7 +3,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// Verilator is distributed in the hope that it will be useful, // Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -39,6 +39,8 @@
# define VL_ATTR_UNUSED __attribute__ ((unused)) # define VL_ATTR_UNUSED __attribute__ ((unused))
# define VL_LIKELY(x) __builtin_expect(!!(x), 1) # define VL_LIKELY(x) __builtin_expect(!!(x), 1)
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0) # define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
#else #else
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking # define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment # define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
@@ -46,6 +48,8 @@
# define VL_ATTR_UNUSED ///< Function that may be never used # define VL_ATTR_UNUSED ///< Function that may be never used
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true then false # define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true then false
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false then true # define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false then true
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
#endif #endif
#ifdef VL_THREADED #ifdef VL_THREADED
@@ -79,7 +83,7 @@ typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type typedef unsigned long vluint32_t; ///< 32-bit unsigned type
typedef long long vlsint64_t; ///< 64-bit signed type typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#elif defined(_WIN32) #elif defined(_WIN32) && !defined(__MINGW32__)
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility) typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility) typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility) typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/perl -w
#$Id$
######################################################################
#
# Copyright 2007-2007 by Wilson Snyder.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of either the GNU General Public License or the
# Perl Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the Perl Artistic License
# along with this module; see the file COPYING. If not, see
# www.cpan.org
#
######################################################################
# DESCRIPTION: Debugging of bison output
use strict;
my $Debug;
my %declared;
my %used;
my $body = 0;
my $rule = "";
my $lineno = 0;
foreach my $line (<STDIN>) {
$lineno++;
chomp $line;
$line =~ s!//.*$!!g;
$line =~ s!\s+! !g;
next if $line eq '';
if ($line =~ m!^\%\%!) {
$body++;
} elsif ($body == 1) {
$rule .= $line;
if ($line =~ m!^\s*;\s*$!) {
#print "Rule: $rule\n";
($rule =~ /^([a-zA-Z0-9_]+):(.*)$/) or die "%Error: No rule name: $1\n";
my $rulename = $1; my $preaction = $2;
$declared{$rulename} = $lineno;
$preaction =~ s/\{[^\}]*\}/ /g;
#print "RULEN $rulename PA $preaction\n" if $Debug;
$rule = '';
foreach my $ref (split /\s+/, $preaction) {
next if $ref !~ /^[a-zA-Z]/;
next if $ref eq $rulename;
if (!$used{$ref} && $declared{$ref}) {
print " %Warning: $lineno: $ref used by $rulename after declaration\n";
}
$used{$ref} = $lineno;
print " ref $ref\n" if $Debug;
}
}
}
}
# Local Variables:
# compile-command: "./bisonreader < verilog.y"
# End:
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/perl -w
# $Id$
######################################################################
#
# Copyright 2005-2007 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
######################################################################
require 5.006_001;
use Getopt::Long;
use IO::File;
use Pod::Usage;
use Data::Dumper; $Data::Dumper::Indent=1;
use strict;
use vars qw ($Debug);
#======================================================================
our @Header;
our %Vertexes;
our @Edges;
our %Edges;
#======================================================================
# main
$Debug = 0;
my $opt_filename;
autoflush STDOUT 1;
autoflush STDERR 1;
if (! GetOptions (
"help" => \&usage,
"debug" => \&debug,
"<>" => \&parameter,
)) {
usage();
}
dotread ($opt_filename);
cwrite ("graph_export.cpp");
#----------------------------------------------------------------------
sub usage {
print '$Id$ ', "\n";
pod2usage(-verbose=>2, -exitval => 2);
exit (1);
}
sub debug {
$Debug = 1;
}
sub parameter {
my $param = shift;
if (!$opt_filename) {
$opt_filename = $param;
} else {
die "%Error: Unknown parameter: $param\n";
}
}
#######################################################################
sub dotread {
my $filename = shift;
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
my $header = 1;
my $vnum = 0;
while (defined (my $line = $fh->getline)) {
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
next if $1 eq 'nTITLE';
$header = 0;
$Vertexes{$1} = {num => $vnum++,
line => $line,
name => $1,};
}
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
my $from=$1; my $to=$2;
my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/;
my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/;
my $edge = {num => $vnum++,
line => $line,
weight => $weight,
cutable => $cutable,
from => $from,
to => $to,};
push @Edges, $edge;
$Edges{$from}{$to} = $edge;
}
elsif ($header) {
push @Header, $line;
print "IGNORE: $line";
}
}
}
#######################################################################
sub cwrite {
my $filename = shift;
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
$fh->print("void V3GraphTestImport::dotImport() {\n");
$fh->print(" DfaGraph* gp = &m_graph;\n");
foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) {
$fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n",
$ver->{name}, $ver->{name}, $ver->{name});
}
$fh->print("\n");
foreach my $edge (@Edges) {
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
$edge->{from}, $edge->{to},
$edge->{weight}, $edge->{cutable}?"true":"false");
}
$fh->print("}\n");
}
#######################################################################
__END__
=pod
=head1 NAME
dot_importer - Take graph .dot file and convert into .cpp file
=head1 SYNOPSIS
dot_importer a.dot
=head1 DESCRIPTION
Dot_importer takes a graphvis .dot file and converts into .cpp file. This
.cpp file is then manually included in V3GraphTest.cpp to verify various
sub-algorithms.
=head1 ARGUMENTS
=over 4
=item --help
Displays this message and program version and exits.
=back
=head1 DISTRIBUTION
Copyright 2005-2007 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 or the Perl Artistic License.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./dot_importer | tee ~/d/a.dot"
### End:
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/perl -w
# $Id$
######################################################################
#
# Copyright 2007-2007 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
######################################################################
require 5.006_001;
use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','cadence_verif');
exec('ncverilog',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "/sicortex/$ENV{DIRPROJECT_ARCH}/lib/Modules/default/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
=pod
=head1 NAME
invoke_ncverilog - Invoke tool under "modules" command
=head1 SYNOPSIS
invoke_ncverilog {ncv arguments}
=head1 DESCRIPTION
=head1 DISTRIBUTION
Copyright 2007-2007 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 or the Perl Artistic License.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./invoke_ncverilog -help"
### End:
+1
View File
@@ -118,6 +118,7 @@ RAW_OBJS = \
V3Dead.o \ V3Dead.o \
V3Delayed.o \ V3Delayed.o \
V3Depth.o \ V3Depth.o \
V3DepthBlock.o \
V3Descope.o \ V3Descope.o \
V3EmitC.o \ V3EmitC.o \
V3EmitCSyms.o \ V3EmitCSyms.o \
+91 -17
View File
@@ -47,28 +47,61 @@ private:
V3Double0 m_statAsCover; // Statistic tracking V3Double0 m_statAsCover; // Statistic tracking
V3Double0 m_statAsPsl; // Statistic tracking V3Double0 m_statAsPsl; // Statistic tracking
V3Double0 m_statAsFull; // Statistic tracking V3Double0 m_statAsFull; // Statistic tracking
V3Double0 m_statAsSV; // Statistic tracking
// METHODS // METHODS
AstNode* newFireAssert(AstNode* nodep, const string& message) { string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) {
AstNode* bodysp = new AstDisplay return (string("[%0t] "+prefix+": ")+nodep->fileline()->filebasename()
(nodep->fileline(), '\0', +":"+cvtToStr(nodep->fileline()->lineno())
(string("[%0t] %%Error: ")+nodep->fileline()->filebasename() +": Assertion failed in %m"
+":"+cvtToStr(nodep->fileline()->lineno()) +((message != "")?": ":"")+message
+": Assertion failed in %m" +"\\n");
+((message != "")?": ":"")+message }
+"\\n"), void replaceDisplay(AstDisplay* nodep, const string& prefix) {
NULL, nodep->displayType(AstDisplayType::WRITE);
new AstTime(nodep->fileline())); nodep->text(assertDisplayMessage(nodep, prefix, nodep->text()));
bodysp->addNext(new AstStop (nodep->fileline())); AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack();
timesp = timesp->addNext(new AstTime(nodep->fileline()));
nodep->exprsp(timesp);
if (!nodep->scopeNamep() && nodep->name().find("%m") != string::npos) {
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
}
}
AstNode* newIfAssertOn(AstNode* nodep) {
// Add a internal if to check assertions are on. // Add a internal if to check assertions are on.
// Don't make this a AND term, as it's unlikely to need to test this. // Don't make this a AND term, as it's unlikely to need to test this.
bodysp = new AstIf (nodep->fileline(), return new AstIf (nodep->fileline(),
new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1), // If assertions are off, have constant propagation rip them out later
bodysp, NULL); // This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
: (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 0)))),
nodep, NULL);
}
AstNode* newIfCoverageOn(AstNode* nodep) {
// Add a internal if to check coverage is on
// Don't make this a AND term, as it's unlikely to need to test this.
return new AstIf (nodep->fileline(),
// If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.coverage()
? (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 1)))
: (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 0)))),
nodep, NULL);
}
AstNode* newFireAssert(AstNode* nodep, const string& message) {
AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::ERROR, message, NULL, NULL);
AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop (nodep->fileline()));
bodysp = newIfAssertOn(bodysp);
return bodysp; return bodysp;
} }
void newAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) { void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) {
propp->unlinkFrBack(); propp->unlinkFrBack();
sentreep->unlinkFrBack(); sentreep->unlinkFrBack();
// //
@@ -114,6 +147,28 @@ private:
pushDeletep(nodep); nodep=NULL; pushDeletep(nodep); nodep=NULL;
} }
void newVAssertion(AstVAssert* nodep, AstNode* propp) {
propp->unlinkFrBackWithNext();
AstNode* passsp = nodep->passsp(); if (passsp) passsp->unlinkFrBackWithNext();
AstNode* failsp = nodep->failsp(); if (failsp) failsp->unlinkFrBackWithNext();
//
if (nodep->castVAssert()) {
if (passsp) passsp = newIfAssertOn(passsp);
if (failsp) failsp = newIfAssertOn(failsp);
} else {
nodep->v3fatalSrc("Unknown node type");
}
AstIf* ifp = new AstIf (nodep->fileline(), propp, passsp, failsp);
AstNode* newp = ifp;
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
//
// Install it
nodep->replaceWith(newp);
// Bye
pushDeletep(nodep); nodep=NULL;
}
// VISITORS //========== Case assertions // VISITORS //========== Case assertions
virtual void visit(AstCase* nodep, AstNUser*) { virtual void visit(AstCase* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -163,16 +218,34 @@ private:
} }
// VISITORS //========== Statements // VISITORS //========== Statements
virtual void visit(AstDisplay* nodep, AstNUser*) {
nodep->iterateChildren(*this);
// Replace the special types with standard text
if (nodep->displayType()==AstDisplayType::INFO) {
replaceDisplay(nodep, "-Info");
} else if (nodep->displayType()==AstDisplayType::WARNING) {
replaceDisplay(nodep, "%%Warning");
} else if (nodep->displayType()==AstDisplayType::ERROR
|| nodep->displayType()==AstDisplayType::FATAL) {
replaceDisplay(nodep, "%%Error");
}
}
virtual void visit(AstPslCover* nodep, AstNUser*) { virtual void visit(AstPslCover* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL; newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
m_statAsCover++; m_statAsCover++;
} }
virtual void visit(AstPslAssert* nodep, AstNUser*) { virtual void visit(AstPslAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL; newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
m_statAsPsl++; m_statAsPsl++;
} }
virtual void visit(AstVAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this);
newVAssertion(nodep, nodep->propp()); nodep=NULL;
m_statAsSV++;
}
virtual void visit(AstModule* nodep, AstNUser*) { virtual void visit(AstModule* nodep, AstNUser*) {
m_modp = nodep; m_modp = nodep;
@@ -203,6 +276,7 @@ public:
} }
virtual ~AssertVisitor() { virtual ~AssertVisitor() {
V3Stats::addStat("Assertions, PSL asserts", m_statAsPsl); V3Stats::addStat("Assertions, PSL asserts", m_statAsPsl);
V3Stats::addStat("Assertions, SystemVerilog asserts", m_statAsSV);
V3Stats::addStat("Assertions, cover statements", m_statAsCover); V3Stats::addStat("Assertions, cover statements", m_statAsCover);
V3Stats::addStat("Assertions, full/parallel case", m_statAsFull); V3Stats::addStat("Assertions, full/parallel case", m_statAsFull);
} }
+1 -1
View File
@@ -789,7 +789,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append) {
if (logsp->fail()) v3fatalSrc("Can't write "<<filename); if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">"; *logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl; *logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
if (editCountGbl()==editCountLast() && 0) { // Off, as messes up tree diffing if (editCountGbl()==editCountLast() && 1) { // Off, as messes up tree diffing
*logsp<<endl; *logsp<<endl;
*logsp<<"No changes since last dump!\n"; *logsp<<"No changes since last dump!\n";
} else { } else {
+31 -1
View File
@@ -250,6 +250,34 @@ public:
//###################################################################### //######################################################################
class AstDisplayType {
public:
enum en {
DISPLAY,
WRITE,
INFO,
ERROR,
WARNING,
FATAL
};
enum en m_e;
inline AstDisplayType () {};
inline AstDisplayType (en _e) : m_e(_e) {};
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {};
operator en () const { return m_e; };
bool addNewline() const { return m_e!=WRITE; }
bool needScopeTracking() const { return m_e!=DISPLAY && m_e!=WRITE; }
const char* ascii() const {
static const char* names[] = {
"display","write","info","error","warning","fatal"};
return names[m_e];};
};
inline bool operator== (AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstDisplayType::en lhs, AstDisplayType rhs) { return (lhs == rhs.m_e); }
//######################################################################
class AstParseRefExp { class AstParseRefExp {
public: public:
enum en { enum en {
@@ -505,6 +533,7 @@ public:
AstNode* op3p() const { return m_op3p; } AstNode* op3p() const { return m_op3p; }
AstNode* op4p() const { return m_op4p; } AstNode* op4p() const { return m_op4p; }
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); } AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
bool brokeExists() const; bool brokeExists() const;
// CONSTRUCTORS // CONSTRUCTORS
@@ -905,6 +934,7 @@ public:
virtual ~AstNodePli() {} virtual ~AstNodePli() {}
virtual string name() const { return m_text; } virtual string name() const { return m_text; }
virtual int instrCount() const { return instrCountPli(); } virtual int instrCount() const { return instrCountPli(); }
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
string text() const { return m_text; } // * = Text to display string text() const { return m_text; } // * = Text to display
void text(const string& text) { m_text=text; } void text(const string& text) { m_text=text; }
@@ -969,7 +999,7 @@ private:
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
string m_name; // Name of variable string m_name; // Name of variable
string m_dotted; // Dotted part of scope to task or "" string m_dotted; // Dotted part of scope to task or ""
string m_inlinedDots; // Dotted hiearchy flattened out string m_inlinedDots; // Dotted hierarchy flattened out
public: public:
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp) AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
:AstNode(fl) :AstNode(fl)
+2
View File
@@ -298,6 +298,7 @@ void AstCell::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (modp()) { str<<" -> "; modp()->dump(str); } if (modp()) { str<<" -> "; modp()->dump(str); }
else { str<<" ->UNLINKED:"<<modName(); } else { str<<" ->UNLINKED:"<<modName(); }
if (pinStar()) str<<" [.*]";
} }
void AstCellInline::dump(ostream& str) { void AstCellInline::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
@@ -307,6 +308,7 @@ void AstPin::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
if (modVarp()) { str<<" -> "; modVarp()->dump(str); } if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
else { str<<" ->UNLINKED"; } else { str<<" ->UNLINKED"; }
if (svImplicit()) str<<" [.SV]";
} }
void AstVarXRef::dump(ostream& str) { void AstVarXRef::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
+107 -16
View File
@@ -236,12 +236,13 @@ private:
bool m_scClocked:1; // SystemC sc_clk<> needed bool m_scClocked:1; // SystemC sc_clk<> needed
bool m_scSensitive:1;// SystemC sensitive() needed bool m_scSensitive:1;// SystemC sensitive() needed
bool m_sigPublic:1; // User C code accesses this signal bool m_sigPublic:1; // User C code accesses this signal
bool m_sigModPublic:1;// User C code accesses this signal and module
bool m_usedClock:1; // Signal used as a clock bool m_usedClock:1; // Signal used as a clock
bool m_usedParam:1; // Parameter is referenced (on link; later signals not setup) bool m_usedParam:1; // Parameter is referenced (on link; later signals not setup)
bool m_funcLocal:1; // Local variable for a function bool m_funcLocal:1; // Local variable for a function
bool m_funcReturn:1; // Return variable for a function bool m_funcReturn:1; // Return variable for a function
bool m_attrClockEn:1;// User clock enable attribute bool m_attrClockEn:1;// User clock enable attribute
bool m_attrIsolateAssign:1;// User isolate_asignments attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_fileDescr:1; // File descriptor bool m_fileDescr:1; // File descriptor
bool m_isConst:1; // Table contains constant data bool m_isConst:1; // Table contains constant data
bool m_isStatic:1; // Static variable bool m_isStatic:1; // Static variable
@@ -252,7 +253,8 @@ private:
m_primaryIO=false; m_primaryIO=false;
m_sc=false; m_scClocked=false; m_scSensitive=false; m_sc=false; m_scClocked=false; m_scSensitive=false;
m_usedClock=false; m_usedParam=false; m_usedClock=false; m_usedParam=false;
m_sigPublic=false; m_funcLocal=false; m_funcReturn=false; m_sigPublic=false; m_sigModPublic=false;
m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrClockEn=false; m_attrIsolateAssign=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false; m_fileDescr=false; m_isConst=false; m_isStatic=false;
m_trace=false; m_trace=false;
@@ -307,6 +309,7 @@ public:
void usedClock(bool flag) { m_usedClock = flag; } void usedClock(bool flag) { m_usedClock = flag; }
void usedParam(bool flag) { m_usedParam = flag; } void usedParam(bool flag) { m_usedParam = flag; }
void sigPublic(bool flag) { m_sigPublic = flag; } void sigPublic(bool flag) { m_sigPublic = flag; }
void sigModPublic(bool flag) { m_sigModPublic = flag; }
void sc(bool flag) { m_sc = flag; } void sc(bool flag) { m_sc = flag; }
void scSensitive(bool flag) { m_scSensitive = flag; } void scSensitive(bool flag) { m_scSensitive = flag; }
void primaryIO(bool flag) { m_primaryIO = flag; } void primaryIO(bool flag) { m_primaryIO = flag; }
@@ -343,6 +346,7 @@ public:
bool isScWide() const; bool isScWide() const;
bool isScSensitive() const { return m_scSensitive; } bool isScSensitive() const { return m_scSensitive; }
bool isSigPublic() const; bool isSigPublic() const;
bool isSigModPublic() const { return m_sigModPublic; }
bool isTrace() const { return m_trace; } bool isTrace() const { return m_trace; }
bool isConst() const { return m_isConst; } bool isConst() const { return m_isConst; }
bool isStatic() const { return m_isStatic; } bool isStatic() const { return m_isStatic; }
@@ -374,6 +378,7 @@ public:
propagateAttrFrom(typevarp); propagateAttrFrom(typevarp);
combineType(typevarp->varType()); combineType(typevarp->varType());
if (typevarp->isSigPublic()) sigPublic(true); if (typevarp->isSigPublic()) sigPublic(true);
if (typevarp->isSigModPublic()) sigModPublic(true);
if (typevarp->attrScClocked()) attrScClocked(true); if (typevarp->attrScClocked()) attrScClocked(true);
} }
void inlineAttrReset(const string& name) { void inlineAttrReset(const string& name) {
@@ -416,7 +421,7 @@ struct AstScope : public AstNode {
private: private:
string m_name; // Name string m_name; // Name
AstScope* m_aboveScopep; // Scope above this one in the hierarchy (NULL if top) AstScope* m_aboveScopep; // Scope above this one in the hierarchy (NULL if top)
AstCell* m_aboveCellp; // Cell above this in the hiearchy (NULL if top) AstCell* m_aboveCellp; // Cell above this in the hierarchy (NULL if top)
AstModule* m_modp; // Module scope corresponds to AstModule* m_modp; // Module scope corresponds to
public: public:
AstScope(FileLine* fl, AstModule* modp, const string& name, AstScope(FileLine* fl, AstModule* modp, const string& name,
@@ -535,7 +540,7 @@ struct AstVarXRef : public AstNodeVarRef {
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
private: private:
string m_dotted; // Scope name to connected to string m_dotted; // Scope name to connected to
string m_inlinedDots; // Dotted hiearchy flattened out string m_inlinedDots; // Dotted hierarchy flattened out
public: public:
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue) AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
:AstNodeVarRef(fl, name, NULL, lvalue) :AstNodeVarRef(fl, name, NULL, lvalue)
@@ -571,10 +576,11 @@ private:
int m_pinNum; // Pin number int m_pinNum; // Pin number
string m_name; // Pin name, or "" for number based interconnect string m_name; // Pin name, or "" for number based interconnect
AstVar* m_modVarp; // Input/output this pin connects to on submodule. AstVar* m_modVarp; // Input/output this pin connects to on submodule.
bool m_svImplicit; // Pin is SystemVerilog .name'ed
public: public:
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
:AstNode(fl) :AstNode(fl)
,m_name(name) { ,m_name(name), m_svImplicit(false) {
m_pinNum = pinNum; m_pinNum = pinNum;
m_modVarp = NULL; m_modVarp = NULL;
setNOp1p(exprp); } setNOp1p(exprp); }
@@ -591,6 +597,8 @@ public:
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
void modVarp(AstVar* varp) { m_modVarp=varp; } void modVarp(AstVar* varp) { m_modVarp=varp; }
bool svImplicit() const { return m_svImplicit; }
void svImplicit(bool flag) { m_svImplicit=flag; }
}; };
struct AstModule : public AstNode { struct AstModule : public AstNode {
@@ -647,12 +655,14 @@ private:
string m_name; // Cell name string m_name; // Cell name
string m_origName; // Original name before dot addition string m_origName; // Original name before dot addition
string m_modName; // Module the cell instances string m_modName; // Module the cell instances
bool m_pinStar; // Pin list has .*
AstModule* m_modp; // [AfterLink] Pointer to module instanced AstModule* m_modp; // [AfterLink] Pointer to module instanced
public: public:
AstCell(FileLine* fl, const string& instName, const string& modName, AstCell(FileLine* fl, const string& instName, const string& modName,
AstPin* pinsp, AstPin* paramsp, AstRange* rangep) AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
: AstNode(fl) : AstNode(fl)
, m_name(instName), m_origName(instName), m_modName(modName), m_modp(NULL) { , m_name(instName), m_origName(instName), m_modName(modName)
, m_pinStar(false), m_modp(NULL) {
addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); } addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); }
virtual ~AstCell() {} virtual ~AstCell() {}
virtual AstType type() const { return AstType::CELL;} virtual AstType type() const { return AstType::CELL;}
@@ -669,6 +679,8 @@ public:
void origName(const string& name) { m_origName = name; } void origName(const string& name) { m_origName = name; }
string modName() const { return m_modName; } // * = Instance name string modName() const { return m_modName; } // * = Instance name
void modName(const string& name) { m_modName = name; } void modName(const string& name) { m_modName = name; }
bool pinStar() const { return m_pinStar; }
void pinStar(bool flag) { m_pinStar = flag; }
AstPin* pinsp() const { return op1p()->castPin(); } // op1 = List of cell ports AstPin* pinsp() const { return op1p()->castPin(); } // op1 = List of cell ports
AstPin* paramsp() const { return op2p()->castPin(); } // op2 = List of parameter #(##) values AstPin* paramsp() const { return op2p()->castPin(); } // op2 = List of parameter #(##) values
AstRange* rangep() const { return op3p()->castRange(); } // op3 = Range of arrayed instants (NULL=not ranged) AstRange* rangep() const { return op3p()->castRange(); } // op3 = Range of arrayed instants (NULL=not ranged)
@@ -814,10 +826,13 @@ struct AstTask : public AstNodeFTask {
}; };
struct AstFunc : public AstNodeFTask { struct AstFunc : public AstNodeFTask {
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
public:
// A function inside a module // A function inside a module
AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp) AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp)
:AstNodeFTask(fl, name, stmtp) { :AstNodeFTask(fl, name, stmtp) {
addNOp1p(fvarsp); addNOp1p(fvarsp);
m_attrIsolateAssign = false;
} }
virtual ~AstFunc() {} virtual ~AstFunc() {}
virtual AstType type() const { return AstType::FUNC;} virtual AstType type() const { return AstType::FUNC;}
@@ -826,6 +841,8 @@ struct AstFunc : public AstNodeFTask {
// op1 = Range output variable (functions only) // op1 = Range output variable (functions only)
AstNode* fvarp() const { return op1p()->castNode(); } AstNode* fvarp() const { return op1p()->castNode(); }
void addFvarp(AstNode* nodep) { addOp1p(nodep); } void addFvarp(AstNode* nodep) { addOp1p(nodep); }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
}; };
struct AstTaskRef : public AstNodeFTaskRef { struct AstTaskRef : public AstNodeFTaskRef {
@@ -1226,19 +1243,19 @@ struct AstDisplay : public AstNodePli {
// Parents: stmtlist // Parents: stmtlist
// Children: file which must be a varref, MATH to print // Children: file which must be a varref, MATH to print
private: private:
char m_newline; AstDisplayType m_displayType;
public: public:
AstDisplay(FileLine* fileline, char newln, const string& text, AstNode* filep, AstNode* exprsp) AstDisplay(FileLine* fileline, AstDisplayType dispType, const string& text, AstNode* filep, AstNode* exprsp)
: AstNodePli (fileline, text, exprsp) { : AstNodePli (fileline, text, exprsp) {
setNOp2p(filep); setNOp2p(filep);
m_newline = newln; m_displayType = dispType;
} }
virtual ~AstDisplay() {} virtual ~AstDisplay() {}
virtual AstType type() const { return AstType::DISPLAY;} virtual AstType type() const { return AstType::DISPLAY;}
virtual AstNode* clone() { return new AstDisplay(*this); } virtual AstNode* clone() { return new AstDisplay(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); } virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string verilogKwd() const { return (filep() ? ((newline() == '\n')?"$fdisplay":"$fwrite") virtual string verilogKwd() const { return (filep() ? (string)"$f"+(string)displayType().ascii()
: ((newline() == '\n')?"$display":"$write")); }; : (string)"$"+(string)displayType().ascii()); }
virtual bool isGateOptimizable() const { return false; } virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; }
virtual bool isSplittable() const { return false; } // SPECIAL: $display has 'visual' ordering virtual bool isSplittable() const { return false; } // SPECIAL: $display has 'visual' ordering
@@ -1246,15 +1263,16 @@ public:
virtual bool isUnlikely() const { return true; } virtual bool isUnlikely() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(text()); } virtual V3Hash sameHash() const { return V3Hash(text()); }
virtual bool same(AstNode* samep) const { virtual bool same(AstNode* samep) const {
return newline()==samep->castDisplay()->newline() return displayType()==samep->castDisplay()->displayType()
&& text()==samep->castDisplay()->text(); } && text()==samep->castDisplay()->text(); }
// op1 used by AstNodePli // op1 used by AstNodePli
char newline() const { return m_newline; } // * = Add a newline for $display AstDisplayType displayType() const { return m_displayType; }
void displayType(AstDisplayType type) { m_displayType = type; }
bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display
AstNode* filep() const { return op2p(); } AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
AstNode* scopeAttrp() const { return op3p(); } AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
AstText* scopeTextp() const { return op3p()->castText(); } void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
void scopeAttrp(AstNode* nodep) { addOp3p(nodep); }
}; };
struct AstFClose : public AstNodeStmt { struct AstFClose : public AstNodeStmt {
@@ -1705,6 +1723,22 @@ public:
int dimension() const { return m_dimension; } int dimension() const { return m_dimension; }
}; };
struct AstScopeName : public AstNode {
// For display %m
// Parents: DISPLAY
// Children: TEXT
AstScopeName(FileLine* fl)
: AstNode(fl) {}
virtual ~AstScopeName() {}
virtual AstType type() const { return AstType::SCOPENAME;}
virtual AstNode* clone() { return new AstScopeName(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstText* scopeAttrp() const { return op1p()->castText(); }
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
};
//====================================================================== //======================================================================
// non-ary ops // non-ary ops
@@ -2572,6 +2606,39 @@ struct AstNeqCase : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstEqWild : public AstNodeBiop {
// Note wildcard operator rhs differs from lhs
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
virtual ~AstEqWild() {}
virtual AstType type() const { return AstType::EQWILD;}
virtual AstNode* clone() { return new AstEqWild(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k==? %r)"; }
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
virtual string emitSimpleOperator() { return "=="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstNeqWild : public AstNodeBiop {
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
virtual ~AstNeqWild() {}
virtual AstType type() const { return AstType::NEQWILD;}
virtual AstNode* clone() { return new AstNeqWild(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k!=? %r)"; }
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
virtual string emitSimpleOperator() { return "!="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstConcat : public AstNodeBiop { struct AstConcat : public AstNodeBiop {
// If you're looking for {#{}}, see AstReplicate // If you're looking for {#{}}, see AstReplicate
AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
@@ -2606,6 +2673,30 @@ struct AstReplicate : public AstNodeBiop {
virtual int instrCount() const { return widthInstrs()*2; } virtual int instrCount() const { return widthInstrs()*2; }
}; };
//======================================================================
// SysVerilog assertions
struct AstVAssert : public AstNodeStmt {
// Verilog Assertion
// Parents: {statement list}
// Children: expression, if pass statements, if fail statements
AstVAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp)
: AstNodeStmt(fl) {
addOp1p(propp);
addNOp2p(passsp);
addNOp3p(failsp);
}
virtual ~AstVAssert() {}
virtual AstType type() const { return AstType::VASSERT;}
virtual AstNode* clone() { return new AstVAssert(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstNode* propp() const { return op1p(); } // op1 = property
AstNode* passsp() const { return op2p(); } // op2 = if passes
AstNode* failsp() const { return op3p(); } // op3 = if fails
};
//====================================================================== //======================================================================
// PSL // PSL
+12
View File
@@ -131,6 +131,18 @@ private:
nodep->replaceWith(newp); nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
} }
virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline
if (m_beginScope != "") {
// To keep correct visual order, must add before other Text's
AstNode* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeAttrp(new AstText(nodep->fileline(), (string)"."+AstNode::prettyName(m_beginScope)));
if (afterp) nodep->scopeAttrp(afterp);
}
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
-3
View File
@@ -62,9 +62,6 @@ private:
//int debug() { return 9; } //int debug() { return 9; }
virtual void visit(AstNodeCase* nodep, AstNUser*) { virtual void visit(AstNodeCase* nodep, AstNUser*) {
// We report a syntax error on empty "case (x) endcase" blocks, so never no items at all
if (!nodep->itemsp()) nodep->v3fatalSrc("No items (not even default) under case statement?\n");
// Detect multiple defaults // Detect multiple defaults
bool hitDefault = false; bool hitDefault = false;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
+4 -4
View File
@@ -104,11 +104,8 @@ private:
nodep->unlinkFrBack(&relinkHandle); nodep->unlinkFrBack(&relinkHandle);
// //
computeCppWidth(nodep); computeCppWidth(nodep);
V3Number zero (nodep->fileline(), nodep->widthMin(),0);
V3Number masksmall (nodep->fileline(), nodep->widthMin());
masksmall.opNot(zero);
V3Number mask (nodep->fileline(), cppWidth(nodep)); V3Number mask (nodep->fileline(), cppWidth(nodep));
mask.opAssign(masksmall); mask.setMask(nodep->widthMin());
AstNode* cleanp = new AstAnd (nodep->fileline(), AstNode* cleanp = new AstAnd (nodep->fileline(),
new AstConst (nodep->fileline(), mask), new AstConst (nodep->fileline(), mask),
nodep); nodep);
@@ -199,6 +196,9 @@ private:
virtual void visit(AstText* nodep, AstNUser*) { virtual void visit(AstText* nodep, AstNUser*) {
setClean (nodep, true); setClean (nodep, true);
} }
virtual void visit(AstScopeName* nodep, AstNUser*) {
setClean (nodep, true);
}
virtual void visit(AstSel* nodep, AstNUser*) { virtual void visit(AstSel* nodep, AstNUser*) {
operandTriop(nodep); operandTriop(nodep);
setClean (nodep, nodep->cleanOut()); setClean (nodep, nodep->cleanOut());
+2 -1
View File
@@ -472,7 +472,8 @@ private:
ifstmtp->addNext(new AstIf(fl, ifstmtp->addNext(new AstIf(fl,
new AstLt (fl, new AstConst(fl, 100), new AstLt (fl, new AstConst(fl, 100),
new AstVarRef(fl, countVarp, false)), new AstVarRef(fl, countVarp, false)),
(new AstDisplay (fl, '\n', "%%Error: Verilated model didn't converge", NULL, NULL)) (new AstDisplay (fl, AstDisplayType::DISPLAY,
"%%Error: Verilated model didn't converge", NULL, NULL))
->addNext(new AstStop (fl)), ->addNext(new AstStop (fl)),
NULL)); NULL));
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0), untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
+74 -6
View File
@@ -246,9 +246,8 @@ private:
replaceNum(nodep, 0); nodep=NULL; replaceNum(nodep, 0); nodep=NULL;
} }
void replaceAllOnes (AstNode* nodep) { void replaceAllOnes (AstNode* nodep) {
V3Number num (nodep->fileline(), nodep->width(), 0); V3Number ones (nodep->fileline(), nodep->width(), 0);
V3Number ones (nodep->fileline(), nodep->width()); ones.setMask(nodep->width());
ones.opNot(num);
replaceNum(nodep, ones); nodep=NULL; replaceNum(nodep, ones); nodep=NULL;
} }
void replaceConst(AstNodeUniop* nodep) { void replaceConst(AstNodeUniop* nodep) {
@@ -388,7 +387,7 @@ private:
AstNode* newp; AstNode* newp;
V3Number mask1 (nodep->fileline(), nodep->width()); V3Number mask1 (nodep->fileline(), nodep->width());
V3Number ones (nodep->fileline(), nodep->width()); V3Number ones (nodep->fileline(), nodep->width());
ones.opNot(mask1); ones.setMask(nodep->width());
if (shift1<0) { if (shift1<0) {
mask1.opShiftR(ones,V3Number(nodep->fileline(),VL_WORDSIZE,-shift1)); mask1.opShiftR(ones,V3Number(nodep->fileline(),VL_WORDSIZE,-shift1));
} else { } else {
@@ -757,7 +756,8 @@ private:
nodep->varp()->initp()->iterateAndNext(*this); nodep->varp()->initp()->iterateAndNext(*this);
if (operandConst(nodep->varp()->initp()) if (operandConst(nodep->varp()->initp())
&& !nodep->lvalue() && !nodep->lvalue()
&& ((v3Global.opt.oConst() && !m_params) // Can reduce constant wires into equations && ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations
&& !nodep->varp()->isSigPublic())
|| nodep->varp()->isParam())) { || nodep->varp()->isParam())) {
AstConst* constp = nodep->varp()->initp()->castConst(); AstConst* constp = nodep->varp()->initp()->castConst();
const V3Number& num = constp->num(); const V3Number& num = constp->num();
@@ -802,7 +802,12 @@ private:
if (nodep->sensp()->castConst() if (nodep->sensp()->castConst()
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) { || (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
// Constants in sensitivity lists may be removed (we'll simplify later) // Constants in sensitivity lists may be removed (we'll simplify later)
AstSenItem* newp = new AstSenItem(nodep->fileline(), AstSenItem::Never()); AstSenItem* newp;
if (nodep->isClocked()) { // A constant can never get a pos/negexge
newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
} else { // Otherwise it may compute a result that needs to settle out
newp = new AstSenItem(nodep->fileline(), AstSenItem::Combo());
}
nodep->replaceWith(newp); nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
} else if (nodep->sensp()->castNot()) { } else if (nodep->sensp()->castNot()) {
@@ -938,6 +943,63 @@ private:
} }
} }
virtual void visit(AstDisplay* nodep, AstNUser*) {
// Substitute constants into displays. The main point of this is to
// simplify assertion methodologies which call functions with display's.
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
nodep->iterateChildren(*this);
bool anyconst = false;
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
if (argp->castConst()) { anyconst=true; break; }
}
if (anyconst) {
//UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
string fmt = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && isdigit(ch)) {
fmt += ch;
} else if (inPct) {
inPct = false;
fmt += ch;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
default: // Most operators, just move to next argument
if (argp) {
AstNode* nextp=argp->nextp();
if (argp && argp->castConst()) { // Convert it
string out = argp->castConst()->num().displayed(fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
{ // fmt = out w/ replace % with %% as it must be literal.
fmt = "";
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
if (*pos == '%') fmt += '%';
fmt += *pos;
}
}
argp->unlinkFrBack()->deleteTree();
}
argp=nextp;
}
break;
} // switch
dispout += fmt;
} else {
dispout += ch;
}
}
nodep->text(dispout);
//UINFO(9," Display out "<<nodep->text()<<endl);
}
}
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->condp()->isZero()) { if (nodep->condp()->isZero()) {
@@ -1048,6 +1110,10 @@ private:
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}"); TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castEqWild, $lhsp.width1}","AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEqWild}", "AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqWild, $lhsp.width1}","AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeqWild}", "AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}"); TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}"); TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
@@ -1089,6 +1155,7 @@ private:
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
@@ -1099,6 +1166,7 @@ private:
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
///=== Verilog operators ///=== Verilog operators
+6 -14
View File
@@ -40,7 +40,6 @@
#include "V3Ast.h" #include "V3Ast.h"
//###################################################################### //######################################################################
// Depth state, as a visitor of each AstNode
class DepthVisitor : public AstNVisitor { class DepthVisitor : public AstNVisitor {
private: private:
@@ -55,11 +54,6 @@ private:
//int debug() { return 9; } //int debug() { return 9; }
// MSVC++ has a limit of 100 parenthesis. We have some operator
// defines that use 2 parens. Thus we can't have a expression deeper
// then 50 operators. We'll add some margin though.
enum en { MAX_EXPR_DEPTH = 40 }; // Expressions deeper then this need temp
// METHODS // METHODS
void createDeepTemp(AstNode* nodep) { void createDeepTemp(AstNode* nodep) {
UINFO(6," Deep "<<nodep<<endl); UINFO(6," Deep "<<nodep<<endl);
@@ -114,13 +108,15 @@ private:
virtual void visit(AstNodeTermop* nodep, AstNUser*) { virtual void visit(AstNodeTermop* nodep, AstNUser*) {
} }
virtual void visit(AstNodeMath* nodep, AstNUser*) { virtual void visit(AstNodeMath* nodep, AstNUser*) {
m_depth++; // We have some operator defines that use 2 parens, so += 2.
m_depth += 2;
if (m_depth>m_maxdepth) m_maxdepth=m_depth; if (m_depth>m_maxdepth) m_maxdepth=m_depth;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_depth--; m_depth -= 2;
if ((m_maxdepth-m_depth) > MAX_EXPR_DEPTH if (m_stmtp
&& m_stmtp && (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
&& (m_maxdepth-m_depth) > v3Global.opt.compLimitParens()
&& !nodep->backp()->castNodeStmt() // Not much point if we're about to use it && !nodep->backp()->castNodeStmt() // Not much point if we're about to use it
) { ) {
m_maxdepth = m_depth; m_maxdepth = m_depth;
@@ -173,14 +169,10 @@ public:
virtual ~DepthVisitor() {} virtual ~DepthVisitor() {}
}; };
//----------------------------------------------------------------------
// Top loop
//###################################################################### //######################################################################
// Depth class functions // Depth class functions
void V3Depth::depthAll(AstNetlist* nodep) { void V3Depth::depthAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(2,__FUNCTION__<<": "<<endl);
// We must do it in bottom-up module
DepthVisitor visitor (nodep); DepthVisitor visitor (nodep);
} }
+139
View File
@@ -0,0 +1,139 @@
// $Id$
//*************************************************************************
// DESCRIPTION: Verilator: Prevent very deep expressions
//
// Code available from: http://www.veripool.com/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License.
//
// 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.
//
//*************************************************************************
// V3DepthBlock's Transformations:
//
// Each module:
// For each deep block, create cfunc including that block.
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <algorithm>
#include "V3Global.h"
#include "V3DepthBlock.h"
#include "V3Ast.h"
#include "V3EmitCBase.h"
//######################################################################
class DepthBlockVisitor : public AstNVisitor {
private:
// NODE STATE
// STATE
AstModule* m_modp; // Current module
AstCFunc* m_funcp; // Current function
int m_depth; // How deep in an expression
int m_deepNum; // How many functions made
//int debug() { return 9; }
// METHODS
AstCFunc* createDeepFunc(AstNode* nodep) {
AstNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
// Create function
string name = m_funcp->name()+"__deep"+cvtToStr(++m_deepNum);
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->symProlog(true);
funcp->slow(m_funcp->slow());
funcp->addStmtsp(nodep);
m_modp->addStmtp(funcp);
// Call it at the point where the body was removed from
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
callp->argTypes("vlSymsp");
UINFO(6," New "<<callp<<endl);
//
relinkHandle.relink(callp);
return funcp;
}
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
m_deepNum = 0;
nodep->iterateChildren(*this);
}
virtual void visit(AstCFunc* nodep, AstNUser*) {
// We recurse into this.
int lastDepth = m_depth;
AstCFunc* lastFuncp = m_funcp;
{
m_depth = 0;
m_funcp = nodep;
nodep->iterateChildren(*this);
}
m_depth = lastDepth;
m_funcp = lastFuncp;
}
void visitStmt(AstNodeStmt* nodep) {
m_depth++;
if (m_depth > v3Global.opt.compLimitBlocks()
&& !nodep->castCCall()) { // Already done
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
AstNode* backp = nodep->backp(); // Only for debug
if (debug()>=9) backp->dumpTree(cout,"- pre : ");
AstCFunc* funcp = createDeepFunc(nodep);
funcp->accept(*this);
if (debug()>=9) backp->dumpTree(cout,"- post: ");
if (debug()>=9) funcp->dumpTree(cout,"- func: ");
} else {
nodep->iterateChildren(*this);
}
m_depth--;
}
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
visitStmt(nodep);
}
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
//--------------------
// Default: Just iterate
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
DepthBlockVisitor(AstNode* nodep) {
m_modp=NULL;
m_depth=0;
//
nodep->accept(*this);
}
virtual ~DepthBlockVisitor() {}
};
//######################################################################
// DepthBlock class functions
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DepthBlockVisitor visitor (nodep);
}
+36
View File
@@ -0,0 +1,36 @@
// $Id$ //-*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Prevent very deep expressions
//
// Code available from: http://www.veripool.com/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3DEPTHBLOCK_H_
#define _V3DEPTHBLOCK_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3DepthBlock {
public:
static void depthBlockAll(AstNetlist* nodep);
};
#endif // Guard
+2 -2
View File
@@ -160,8 +160,8 @@ private:
} }
} }
// Not really any way the user could do this, and we'd need to come up with some return value // Not really any way the user could do this, and we'd need to come up with some return value
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), //newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DISPLAY,
// '\n', string("%%Error: ")+name+"() called with bad scope", NULL)); // string("%%Error: ")+name+"() called with bad scope", NULL));
//newfuncp->addStmtsp(new AstStop (newfuncp->fileline())); //newfuncp->addStmtsp(new AstStop (newfuncp->fileline()));
if (debug()>=9) newfuncp->dumpTree(cout," newfunc: "); if (debug()>=9) newfuncp->dumpTree(cout," newfunc: ");
} else { } else {
+28 -6
View File
@@ -388,7 +388,7 @@ public:
} }
virtual void visit(AstMulS* nodep, AstNUser* vup) { virtual void visit(AstMulS* nodep, AstNUser* vup) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n"); nodep->v3error("Unsupported: Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n");
} }
visit(nodep->castNodeBiop(), vup); visit(nodep->castNodeBiop(), vup);
} }
@@ -594,7 +594,14 @@ class EmitCImp : EmitCStmts {
if (filenum) filenameNoExt += "__"+cvtToStr(filenum); if (filenum) filenameNoExt += "__"+cvtToStr(filenum);
filenameNoExt += (slow ? "__Slow":""); filenameNoExt += (slow ? "__Slow":"");
V3OutCFile* ofp = NULL; V3OutCFile* ofp = NULL;
if (optSystemPerl()) { if (v3Global.opt.lintOnly()) {
// Unfortunately we have some lint checks here, so we can't just skip processing.
// We should move them to a different stage.
string filename = "/dev/null";
newCFile(filename, slow, source);
ofp = new V3OutSpFile (filename);
}
else if (optSystemPerl()) {
string filename = filenameNoExt+".sp"; string filename = filenameNoExt+".sp";
newCFile(filename, slow, source); newCFile(filename, slow, source);
ofp = new V3OutSpFile (filename); ofp = new V3OutSpFile (filename);
@@ -687,6 +694,21 @@ class EmitCImp : EmitCStmts {
if (gotOne) { if (gotOne) {
puts(");\n"); puts(");\n");
//puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );"); //puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );");
for (vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
it != m_blkChangeDetVec.end(); ++it) {
AstChangeDet* nodep = *it;
if (nodep->lhsp()) {
puts("VL_DEBUG_IF( if(__req && (");
bool gotOneIgnore = false;
doubleOrDetect(nodep, gotOneIgnore);
string varname;
if (nodep->lhsp()->castVarRef()) {
varname = ": "+nodep->lhsp()->castVarRef()->varp()->prettyName();
}
puts(")) cout<<\"\tCHANGE: "+nodep->fileline()->ascii()
+varname+"\"<<endl; );");
}
}
} }
} }
@@ -998,7 +1020,6 @@ void EmitCStmts::displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, cha
void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) { void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
string vformat = nodep->text(); string vformat = nodep->text();
bool addNewline = (nodep->newline() == '\n');
AstNode* elistp = nodep->exprsp(); AstNode* elistp = nodep->exprsp();
// Convert Verilog display to C printf formats // Convert Verilog display to C printf formats
@@ -1031,16 +1052,17 @@ void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
// Spec: h d o b c l // Spec: h d o b c l
case 'b': displayArg(nodep,&elistp,fmt,'b'); break; case 'b': displayArg(nodep,&elistp,fmt,'b'); break;
case 'c': displayArg(nodep,&elistp,fmt,'c'); break; case 'c': displayArg(nodep,&elistp,fmt,'c'); break;
case 't':
case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal
case 'o': displayArg(nodep,&elistp,fmt,'o'); break; case 'o': displayArg(nodep,&elistp,fmt,'o'); break;
case 'h': case 'h':
case 'x': displayArg(nodep,&elistp,fmt,'x'); break; case 'x': displayArg(nodep,&elistp,fmt,'x'); break;
case 's': displayArg(nodep,&elistp,fmt,'s'); break; case 's': displayArg(nodep,&elistp,fmt,'s'); break;
case 't': displayArg(nodep,&elistp,fmt,'u'); break;
case 'm': { case 'm': {
emitDispState.pushFormat("%s"); emitDispState.pushFormat("%s");
emitDispState.pushArg(NULL, "vlSymsp->name("); emitDispState.pushArg(NULL, "vlSymsp->name(");
for (AstText* textp=nodep->scopeTextp(); textp; textp=textp->nextp()->castText()) { if (!nodep->scopeNamep()) nodep->v3fatalSrc("Display with %m but no AstScopeName");
for (AstText* textp=nodep->scopeNamep()->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
emitDispState.pushFormat(textp->text()); emitDispState.pushFormat(textp->text());
} }
break; break;
@@ -1061,7 +1083,7 @@ void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
if (elistp != NULL) { if (elistp != NULL) {
nodep->v3error("Extra arguments for $display format\n"); nodep->v3error("Extra arguments for $display format\n");
} }
if (addNewline) emitDispState.pushFormat("\\n"); if (nodep->addNewline()) emitDispState.pushFormat("\\n");
displayEmit(nodep); displayEmit(nodep);
} }
+1 -1
View File
@@ -138,7 +138,7 @@ public:
of.puts("\n# Link rules...\n"); of.puts("\n# Link rules...\n");
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n"); of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n");
of.puts("\t$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt\n"); of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS) 2>&1 | c++filt\n");
of.puts("\n"); of.puts("\n");
} }
+2
View File
@@ -246,6 +246,8 @@ public:
virtual void visit(AstText* nodep, AstNUser*) { virtual void visit(AstText* nodep, AstNUser*) {
ofp()->putsNoTracking(nodep->text()); ofp()->putsNoTracking(nodep->text());
} }
virtual void visit(AstScopeName* nodep, AstNUser*) {
}
virtual void visit(AstCStmt* nodep, AstNUser*) { virtual void visit(AstCStmt* nodep, AstNUser*) {
putbs("$_CSTMT("); putbs("$_CSTMT(");
nodep->bodysp()->iterateAndNext(*this); nodep->bodysp()->iterateAndNext(*this);
+30 -7
View File
@@ -34,7 +34,8 @@
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret()); FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
int V3Error::s_errcnt = 0; int V3Error::s_errCount = 0;
int V3Error::s_warnCount = 0;
int V3Error::s_debugDefault = 0; int V3Error::s_debugDefault = 0;
ostringstream V3Error::s_errorStr; // Error string being formed ostringstream V3Error::s_errorStr; // Error string being formed
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL; V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
@@ -187,25 +188,46 @@ string V3Error::lineStr (const char* filename, int lineno) {
return out.str(); return out.str();
} }
void V3Error::incWarnings() {
s_warnCount++;
if (errorOrWarnCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
v3fatal ("Exiting due to too many errors encountered\n");
}
}
void V3Error::incErrors() { void V3Error::incErrors() {
s_errcnt++; s_errCount++;
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse if (errorOrWarnCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
v3fatal ("Exiting due to too many errors encountered\n"); v3fatal ("Exiting due to too many errors encountered\n");
} }
} }
void V3Error::abortIfErrors() { void V3Error::abortIfErrors() {
if (errorCount()) { if (errorCount()) {
v3fatal ("Exiting due to "<<dec<<errorCount()<<" warning(s)\n"); v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
} }
} }
void V3Error::abortIfWarnings() {
if (errorOrWarnCount()) {
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
}
}
bool V3Error::isError(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return false;
else if (code==V3ErrorCode::FATAL) return true;
else if (code==V3ErrorCode::ERROR) return true;
else if (code<V3ErrorCode::FIRST_WARN
|| s_pretendError[code]) return true;
else return false;
}
string V3Error::msgPrefix(V3ErrorCode code) { string V3Error::msgPrefix(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: "; if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
else if (code==V3ErrorCode::FATAL) return "%Error: "; else if (code==V3ErrorCode::FATAL) return "%Error: ";
else if (code==V3ErrorCode::ERROR) return "%Error: "; else if (code==V3ErrorCode::ERROR) return "%Error: ";
else if (code<V3ErrorCode::FIRST_WARN else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|| s_pretendError[code]) return "%Error-"+(string)code.ascii()+": ";
else return "%Warning-"+(string)code.ascii()+": "; else return "%Warning-"+(string)code.ascii()+": ";
} }
@@ -258,7 +280,8 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl; cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
} }
} }
incErrors(); if (isError(s_errorCode)) incErrors();
else incWarnings();
if (s_errorCode==V3ErrorCode::FATAL) { if (s_errorCode==V3ErrorCode::FATAL) {
static bool inFatal = false; static bool inFatal = false;
if (!inFatal) { if (!inFatal) {
+12 -4
View File
@@ -37,6 +37,7 @@ public:
FATAL, // Kill the program FATAL, // Kill the program
ERROR, // General error out, can't suppress ERROR, // General error out, can't suppress
// Error codes: // Error codes:
MULTITOP, // Error: Multiple top level modules
TASKNSVAR, // Error: Task I/O not simple TASKNSVAR, // Error: Task I/O not simple
// Warning codes: // Warning codes:
FIRST_WARN, // Just a code so the program knows where to start warnings FIRST_WARN, // Just a code so the program knows where to start warnings
@@ -71,7 +72,7 @@ public:
const char* names[] = { const char* names[] = {
// Leading spaces indicate it can't be disabled. // Leading spaces indicate it can't be disabled.
" SUPPRESS", " FATAL", " ERROR", " SUPPRESS", " FATAL", " ERROR",
"TASKNSVAR", "MULTITOP", "TASKNSVAR",
" FIRST_WARN", " FIRST_WARN",
"BLKANDNBLK", "BLKANDNBLK",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST", "CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
@@ -103,11 +104,13 @@ class V3Error {
static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning
static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error
static int s_debugDefault; // Default debugging level static int s_debugDefault; // Default debugging level
static int s_errcnt; // Error count static int s_errCount; // Error count
static int s_warnCount; // Error count
static ostringstream s_errorStr; // Error string being formed static ostringstream s_errorStr; // Error string being formed
static V3ErrorCode s_errorCode; // Error string being formed will abort static V3ErrorCode s_errorCode; // Error string being formed will abort
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
static void incErrors(); static void incErrors();
static void incWarnings();
V3Error() { cerr<<("Static class"); abort(); } V3Error() { cerr<<("Static class"); abort(); }
@@ -117,12 +120,16 @@ class V3Error {
static void debugDefault(int level) { s_debugDefault = level; } static void debugDefault(int level) { s_debugDefault = level; }
static int debugDefault() { return s_debugDefault; } static int debugDefault() { return s_debugDefault; }
static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn
static int errorCount() { return s_errcnt; } static int errorCount() { return s_errCount; }
static int warnCount() { return s_warnCount; }
static int errorOrWarnCount() { return errorCount()+warnCount(); }
// METHODS // METHODS
static void init(); static void init();
static void abortIfErrors(); static void abortIfErrors();
static void abortIfWarnings();
static void suppressThisWarning(); // Suppress next %Warn if user has it off static void suppressThisWarning(); // Suppress next %Warn if user has it off
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; } static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
static bool isError(V3ErrorCode code);
static string v3sform (const char* format, ...); static string v3sform (const char* format, ...);
static string lineStr (const char* filename, int lineno); static string lineStr (const char* filename, int lineno);
static V3ErrorCode errorCode() { return s_errorCode; } static V3ErrorCode errorCode() { return s_errorCode; }
@@ -197,7 +204,8 @@ public:
void warnOff(V3ErrorCode code, bool flag) { m_warnOff.set(code,flag); } // Turn on/off warning messages on this line. void warnOff(V3ErrorCode code, bool flag) { m_warnOff.set(code,flag); } // Turn on/off warning messages on this line.
bool warnOff(const string& code, bool flag); // Returns 1 if ok bool warnOff(const string& code, bool flag); // Returns 1 if ok
bool warnIsOff(V3ErrorCode code); bool warnIsOff(V3ErrorCode code);
void warnResetDefault() { m_warnOff=s_defaultFileLine.m_warnOff; } void warnStateFrom(const FileLine& from) { m_warnOff=from.m_warnOff; }
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
void v3errorEnd(ostringstream& str); void v3errorEnd(ostringstream& str);
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); } inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
+1 -4
View File
@@ -65,11 +65,8 @@ private:
if (nodep->isWide()) { if (nodep->isWide()) {
return V3Number (nodep->fileline(), VL_WORDSIZE, VL_MASK_I(nodep->widthMin())); return V3Number (nodep->fileline(), VL_WORDSIZE, VL_MASK_I(nodep->widthMin()));
} else { } else {
V3Number zero (nodep->fileline(), nodep->widthMin(),0);
V3Number masksmall (nodep->fileline(), nodep->widthMin());
masksmall.opNot(zero);
V3Number mask (nodep->fileline(), longOrQuadWidth(nodep)); V3Number mask (nodep->fileline(), longOrQuadWidth(nodep));
mask.opAssign(masksmall); mask.setMask(nodep->widthMin());
return mask; return mask;
} }
} }
+10
View File
@@ -198,10 +198,18 @@ public:
m_substTreep = NULL; m_substTreep = NULL;
m_buffersOnly = buffersOnly; m_buffersOnly = buffersOnly;
m_lhsVarRef = NULL; m_lhsVarRef = NULL;
// Iterate
nodep->accept(*this); nodep->accept(*this);
// Check results
if (!m_substTreep) { if (!m_substTreep) {
clearSimple("No assignment found\n"); clearSimple("No assignment found\n");
} }
for (GateVarRefList::const_iterator it = rhsVarRefs().begin();
it != rhsVarRefs().end(); ++it) {
if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) {
clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later.
}
}
if (debug()>=9 && !m_isSimple) { if (debug()>=9 && !m_isSimple) {
nodep->dumpTree(cout,"\tgate!Ok: "); nodep->dumpTree(cout,"\tgate!Ok: ");
} }
@@ -224,6 +232,7 @@ private:
//Entire netlist: //Entire netlist:
// AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet // AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet
// {statement}Node::userp -> GateLogicVertex* for this statement // {statement}Node::userp -> GateLogicVertex* for this statement
// STATE // STATE
V3Graph m_graph; // Scoreboard of var usages/dependencies V3Graph m_graph; // Scoreboard of var usages/dependencies
GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
@@ -458,6 +467,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
} }
} }
} }
// Process it
if (!doit) { if (!doit) {
if (allowMultiIn && (debug()>=9)) { if (allowMultiIn && (debug()>=9)) {
UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
+5 -1
View File
@@ -180,6 +180,7 @@ void V3Graph::userClearVertices() {
// the extra code on each read of user() would probably slow things down more then help. // the extra code on each read of user() would probably slow things down more then help.
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
vertexp->user(0); vertexp->user(0);
vertexp->userp(NULL); // Its a union, but might be different size then user()
} }
} }
@@ -187,7 +188,8 @@ void V3Graph::userClearEdges() {
// Clear user() in all of tree // Clear user() in all of tree
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
edgep->userp(NULL); edgep->user(0);
edgep->userp(NULL); // Its a union, but might be different size then user()
} }
} }
} }
@@ -253,6 +255,8 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
*logp<<"digraph v3graph {\n"; *logp<<"digraph v3graph {\n";
*logp<<"\trankdir="<<dotRankDir()<<"\n"; *logp<<"\trankdir="<<dotRankDir()<<"\n";
*logp<<"\tsize="<<"\"7.5,10\""<<"\n"; *logp<<"\tsize="<<"\"7.5,10\""<<"\n";
*logp<<"\tnTITLE\t[fontsize=20 label=\""<<filename<<"\", shape=box, style=bold, color=black];\n";
*logp<<"\n";
// List of all possible subgraphs // List of all possible subgraphs
typedef multimap<string,V3GraphVertex*> SubgraphMmap; typedef multimap<string,V3GraphVertex*> SubgraphMmap;
+8 -4
View File
@@ -37,6 +37,7 @@
// Break the minimal number of backward edges to make the graph acyclic // Break the minimal number of backward edges to make the graph acyclic
class GraphAcycVertex : public V3GraphVertex { class GraphAcycVertex : public V3GraphVertex {
// user() is used for various sub-algorithm pieces
V3GraphVertex* m_origVertexp; // Pointer to first vertex this represents V3GraphVertex* m_origVertexp; // Pointer to first vertex this represents
protected: protected:
friend class GraphAcyc; friend class GraphAcyc;
@@ -308,6 +309,9 @@ void GraphAcyc::simplifyOne (GraphAcycVertex* avertexp) {
avertexp->setDelete(); // Mark so we won't delete it twice avertexp->setDelete(); // Mark so we won't delete it twice
// Make a new edge connecting the two vertices directly // Make a new edge connecting the two vertices directly
// If both are breakable, we pick the one with less weight, else it's arbitrary // If both are breakable, we pick the one with less weight, else it's arbitrary
// We can forget about the origEdge list for the "non-selected" set of edges,
// as we need to break only one set or the other set of edges, not both.
// (This is why we must give preference to the cutable set.)
V3GraphEdge* templateEdgep = ( (inEdgep->cutable() V3GraphEdge* templateEdgep = ( (inEdgep->cutable()
&& (!outEdgep->cutable() && (!outEdgep->cutable()
|| inEdgep->weight()<outEdgep->weight() )) || inEdgep->weight()<outEdgep->weight() ))
@@ -353,7 +357,7 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
if (avertexp->isDelete()) return; if (avertexp->isDelete()) return;
// Clear marks // Clear marks
for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
edgep->top()->user(false); edgep->top()->userp(NULL);
} }
// Mark edges and detect duplications // Mark edges and detect duplications
for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) { for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) {
@@ -364,16 +368,16 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
if (!prevEdgep->cutable()) { if (!prevEdgep->cutable()) {
// !cutable duplicates prev !cutable: we can ignore it, redundant // !cutable duplicates prev !cutable: we can ignore it, redundant
// cutable duplicates prev !cutable: know it's not a relevant loop, ignore it // cutable duplicates prev !cutable: know it's not a relevant loop, ignore it
UINFO(8," DelDupEdge "<<avertexp<<endl); UINFO(8," DelDupEdge "<<avertexp<<" -> "<<edgep->top()<<endl);
edgep->unlinkDelete(); edgep = NULL; edgep->unlinkDelete(); edgep = NULL;
} else if (!edgep->cutable()) { } else if (!edgep->cutable()) {
// !cutable duplicates prev cutable: delete the earlier cutable // !cutable duplicates prev cutable: delete the earlier cutable
UINFO(8," DelDupPrev "<<avertexp<<endl); UINFO(8," DelDupPrev "<<avertexp<<" -> "<<prevEdgep->top()<<endl);
prevEdgep->unlinkDelete(); prevEdgep = NULL; prevEdgep->unlinkDelete(); prevEdgep = NULL;
outVertexp->userp(edgep); outVertexp->userp(edgep);
} else { } else {
// cutable duplicates prev cutable: combine weights // cutable duplicates prev cutable: combine weights
UINFO(8," DelDupComb "<<avertexp<<endl); UINFO(8," DelDupComb "<<avertexp<<" -> "<<edgep->top()<<endl);
prevEdgep->weight (prevEdgep->weight() + edgep->weight()); prevEdgep->weight (prevEdgep->weight() + edgep->weight());
addOrigEdgep (prevEdgep, edgep); addOrigEdgep (prevEdgep, edgep);
edgep->unlinkDelete(); edgep = NULL; edgep->unlinkDelete(); edgep = NULL;
+1 -1
View File
@@ -86,7 +86,7 @@ private:
void vertexIterate(V3GraphVertex* vertexp) { void vertexIterate(V3GraphVertex* vertexp) {
// Clear marks // Clear marks
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
edgep->top()->user(false); edgep->top()->userp(NULL);
} }
// Mark edges and detect duplications // Mark edges and detect duplications
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) { for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
+29
View File
@@ -311,6 +311,34 @@ public:
gp->dfaReduce(); gp->dfaReduce();
} }
}; };
//======================================================================
class V3GraphTestImport : public V3GraphTest {
void dotImport();
public:
virtual string name() { return "import"; }
virtual void runTest() {
DfaGraph* gp = &m_graph;
if (V3GraphTest::debug()) gp->debug(9);
dotImport();
dump();
gp->acyclic(&V3GraphEdge::followAlwaysTrue);
dump();
gp->rank(&V3GraphEdge::followAlwaysTrue);
dump();
}
};
#if 0
# include "graph_export.cpp"
#else
void V3GraphTestImport::dotImport() {
}
#endif
//====================================================================== //======================================================================
void V3Graph::test() { void V3Graph::test() {
@@ -320,5 +348,6 @@ void V3Graph::test() {
{ V3GraphTestAcyc test; test.run(); } { V3GraphTestAcyc test; test.run(); }
{ V3GraphTestVars test; test.run(); } { V3GraphTestVars test; test.run(); }
{ V3GraphTestDfa test; test.run(); } { V3GraphTestDfa test; test.run(); }
{ V3GraphTestImport test; test.run(); }
if (V3GraphTest::debug()) v3fatalSrc("Exiting due to graph testing enabled"); if (V3GraphTest::debug()) v3fatalSrc("Exiting due to graph testing enabled");
} }
+3 -3
View File
@@ -233,10 +233,10 @@ private:
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
if (m_cellp // Similar code in V3Begin
&& nodep->name().find("%m") != string::npos) { if (m_cellp) {
// To keep correct visual order, must add before other Text's // To keep correct visual order, must add before other Text's
AstNode* afterp = nodep->scopeAttrp(); AstNode* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext(); if (afterp) afterp->unlinkFrBackWithNext();
+12 -1
View File
@@ -143,6 +143,13 @@ private:
if (!m_curVarsp) nodep->v3fatalSrc("Var not under module??\n"); if (!m_curVarsp) nodep->v3fatalSrc("Var not under module??\n");
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_idState==ID_FIND) { if (m_idState==ID_FIND) {
// We used modTrace before leveling, and we may now
// want to turn it off now that we know the levelizations
if (v3Global.opt.traceDepth()
&& (m_modp->level()-1) > v3Global.opt.traceDepth()) {
m_modp->modTrace(false);
nodep->trace(false);
}
// Find under either a task or the module's vars // Find under either a task or the module's vars
AstNode* findidp = m_curVarsp->findIdName(nodep->name()); AstNode* findidp = m_curVarsp->findIdName(nodep->name());
AstVar* findvarp = findidp->castVar(); AstVar* findvarp = findidp->castVar();
@@ -213,6 +220,8 @@ private:
nodep->userp(m_curVarsp); nodep->userp(m_curVarsp);
} }
// Convert the func's range to the output variable // Convert the func's range to the output variable
// This should probably be done in the Parser instead, as then we could
// just attact normal signal attributes to it.
if (AstFunc* funcp = nodep->castFunc()) { if (AstFunc* funcp = nodep->castFunc()) {
if (!funcp->fvarp()->castVar()) { if (!funcp->fvarp()->castVar()) {
AstRange* rangep = funcp->fvarp()->castRange(); AstRange* rangep = funcp->fvarp()->castRange();
@@ -221,6 +230,7 @@ private:
newvarp->isSigned(funcp->isSigned()); newvarp->isSigned(funcp->isSigned());
newvarp->funcReturn(true); newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(funcp->attrIsolateAssign());
funcp->addFvarp(newvarp); funcp->addFvarp(newvarp);
// Explicit insert required, as the var name shadows the upper level's task name // Explicit insert required, as the var name shadows the upper level's task name
m_curVarsp->insert(newvarp->name(), newvarp); m_curVarsp->insert(newvarp->name(), newvarp);
@@ -362,7 +372,8 @@ private:
} }
} }
// Deal with implicit definitions // Deal with implicit definitions
if (m_idState==ID_RESOLVE && nodep->modVarp()) { if (m_idState==ID_RESOLVE && nodep->modVarp()
&& !nodep->svImplicit()) { // SV 19.11.3: .name pins don't allow implicit decls
pinImplicitExprRecurse(nodep->exprp()); pinImplicitExprRecurse(nodep->exprp());
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
+26
View File
@@ -163,6 +163,32 @@ private:
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false); new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false);
} }
} }
// Convert .* to list of pins
if (nodep->modp() && nodep->pinStar()) {
// Note what pins exist
UINFO(9," CELL .* connect "<<nodep<<endl);
V3SymTable ports; // Symbol table of all connected port names
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells");
if (!ports.findIdName(pinp->name())) {
ports.insert(pinp->name(), pinp);
}
}
// We search ports, rather then in/out declarations as they aren't resolved yet,
// and it's easier to do it now then in V3Link when we'd need to repeat steps.
for (AstNode* portnodep = nodep->modp()->stmtsp(); portnodep; portnodep=portnodep->nextp()) {
if (AstPort* portp = portnodep->castPort()) {
if (!ports.findIdName(portp->name())) {
UINFO(9," need PORT "<<portp<<endl);
// Create any not already connected
AstPin* newp = new AstPin(nodep->fileline(),0,portp->name(),
new AstVarRef(nodep->fileline(),portp->name(),false));
newp->svImplicit(true);
nodep->addPinsp(newp);
}
}
}
}
// Convert unnamed pins to pin number based assignments // Convert unnamed pins to pin number based assignments
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) { for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (pinp->name()=="") pinp->name("__pinNumber"+cvtToStr(pinp->pinNum())); if (pinp->name()=="") pinp->name("__pinNumber"+cvtToStr(pinp->pinNum()));
+7 -7
View File
@@ -21,7 +21,7 @@
// LinkDot TRANSFORMATIONS: // LinkDot TRANSFORMATIONS:
// Top-down traversal // Top-down traversal
// Cells: // Cells:
// Make graph of cell hiearchy // Make graph of cell hierarchy
// Var/Funcs's: // Var/Funcs's:
// Collect all names into symtable under appropriate cell // Collect all names into symtable under appropriate cell
// Top-down traversal // Top-down traversal
@@ -180,7 +180,7 @@ private:
// TYPES // TYPES
typedef std::multimap<string,LinkDotCellVertex*> NameScopeMap; typedef std::multimap<string,LinkDotCellVertex*> NameScopeMap;
// MEMBERS // MEMBERS
LinkDotGraph m_graph; // Graph of hiearchy LinkDotGraph m_graph; // Graph of hierarchy
NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name
bool m_forPrearray; // Compress cell__[array] refs bool m_forPrearray; // Compress cell__[array] refs
bool m_forScopeCreation; // Remove VarXRefs for V3Scope bool m_forScopeCreation; // Remove VarXRefs for V3Scope
@@ -277,7 +277,7 @@ private:
public: public:
LinkDotBaseVertex* findDotted(LinkDotBaseVertex* cellVxp, const string& dotname, LinkDotBaseVertex* findDotted(LinkDotBaseVertex* cellVxp, const string& dotname,
string& baddot, LinkDotBaseVertex*& okVxp) { string& baddot, LinkDotBaseVertex*& okVxp) {
// Given a dotted hiearchy name, return where in scope it is // Given a dotted hierarchy name, return where in scope it is
// Note when dotname=="" we just fall through and return cellVxp // Note when dotname=="" we just fall through and return cellVxp
UINFO(8," dottedFind "<<dotname<<endl); UINFO(8," dottedFind "<<dotname<<endl);
bool firstId = true; bool firstId = true;
@@ -520,8 +520,8 @@ private:
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep, AstNUser*) {
UINFO(8," SCOPE "<<nodep<<endl); UINFO(8," SCOPE "<<nodep<<endl);
if (!m_statep->forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope"); if (!m_statep->forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope");
// Using the CELL names, we created all hiearchy. We now need to match this Scope // Using the CELL names, we created all hierarchy. We now need to match this Scope
// up with the hiearchy created by the CELL names. // up with the hierarchy created by the CELL names.
m_cellVxp = m_statep->findScope(nodep); m_cellVxp = m_statep->findScope(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_cellVxp = NULL; m_cellVxp = NULL;
@@ -610,7 +610,7 @@ private:
UINFO(8," "<<nodep<<endl); UINFO(8," "<<nodep<<endl);
if (!m_cellVxp) { if (!m_cellVxp) {
UINFO(9,"Dead module for "<<nodep<<endl); UINFO(9,"Dead module for "<<nodep<<endl);
nodep->varp(NULL); // Module that is not in hiearchy. We'll be dead code eliminating it later. nodep->varp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
} else { } else {
string baddot; string baddot;
LinkDotBaseVertex* okVxp; LinkDotBaseVertex* okVxp;
@@ -657,7 +657,7 @@ private:
UINFO(8," "<<nodep<<endl); UINFO(8," "<<nodep<<endl);
if (!m_cellVxp) { if (!m_cellVxp) {
UINFO(9,"Dead module for "<<nodep<<endl); UINFO(9,"Dead module for "<<nodep<<endl);
nodep->taskp(NULL); // Module that is not in hiearchy. We'll be dead code eliminating it later. nodep->taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
} else { } else {
string baddot; string baddot;
LinkDotBaseVertex* okVxp; LinkDotBaseVertex* okVxp;
+2 -2
View File
@@ -92,8 +92,8 @@ void V3LinkLevel::modSortByLevel() {
AstModule* topp = NULL; AstModule* topp = NULL;
for (AstModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castModule()) { for (AstModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castModule()) {
if (nodep->level()<=2) { if (nodep->level()<=2) {
if (topp) nodep->v3error("Unsupported: Multiple top level modules: " if (topp) nodep->v3warn(MULTITOP, "Unsupported: Multiple top level modules: "
<<nodep->prettyName()<<" and "<<topp->prettyName()); <<nodep->prettyName()<<" and "<<topp->prettyName());
topp = nodep; topp = nodep;
} }
vec.push_back(nodep); vec.push_back(nodep);
+11 -1
View File
@@ -89,6 +89,10 @@ private:
// VarRef: Parse its reference // VarRef: Parse its reference
UINFO(5," "<<nodep<<endl); UINFO(5," "<<nodep<<endl);
// May be a varref inside a select, etc, so save state and recurse // May be a varref inside a select, etc, so save state and recurse
string oldText = m_dotText;
bool oldDot = m_inModDot;
AstParseRefExp oldExp = m_exp;
AstText* oldBasep = m_baseTextp;
{ {
// Replace the parsed item with its child IE the selection tree down to the varref itself // Replace the parsed item with its child IE the selection tree down to the varref itself
// Do this before iterating, so we don't have to process the edited tree twice // Do this before iterating, so we don't have to process the edited tree twice
@@ -117,8 +121,14 @@ private:
} else { } else {
nodep->v3fatalSrc("Unknown ParseRefExp type\n"); nodep->v3fatalSrc("Unknown ParseRefExp type\n");
} }
nodep->deleteTree(); nodep=NULL;
}
if (m_exp != AstParseRefExp::FUNC) { // Fuctions need to look at the name themself
m_dotText = oldText;
m_inModDot = oldDot;
m_exp = oldExp;
m_baseTextp = oldBasep;
} }
nodep->deleteTree(); nodep=NULL;
} }
virtual void visit(AstDot* nodep, AstNUser*) { virtual void visit(AstDot* nodep, AstNUser*) {
UINFO(5," "<<nodep<<endl); UINFO(5," "<<nodep<<endl);
+24 -1
View File
@@ -54,6 +54,7 @@ private:
// Below state needs to be preserved between each module call. // Below state needs to be preserved between each module call.
AstModule* m_modp; // Current module AstModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Function or task we're inside AstNodeFTask* m_ftaskp; // Function or task we're inside
AstVAssert* m_assertp; // Current assertion
//int debug() { return 9; } //int debug() { return 9; }
@@ -72,13 +73,23 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstVAssert* nodep, AstNUser*) {
if (m_assertp) nodep->v3error("Assert not allowed under another assert");
m_assertp = nodep;
nodep->iterateChildren(*this);
m_assertp = NULL;
}
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->arraysp() && nodep->isIO()) { if (nodep->arraysp() && nodep->isIO()) {
nodep->v3error("Arrayed variables may not be inputs nor outputs"); nodep->v3error("Arrayed variables may not be inputs nor outputs");
} }
if (m_ftaskp) nodep->funcLocal(true); if (m_ftaskp) nodep->funcLocal(true);
if (nodep->isSigPublic()) m_modp->modPublic(true); // Avoid flattening if signals are exposed if (nodep->isSigModPublic()) {
nodep->sigModPublic(false); // We're done with this attribute
m_modp->modPublic(true); // Avoid flattening if signals are exposed
}
} }
virtual void visit(AstNodeVarRef* nodep, AstNUser*) { virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
@@ -317,6 +328,17 @@ private:
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstDisplay* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
if (!m_assertp
&& (nodep->displayType() == AstDisplayType::INFO
|| nodep->displayType() == AstDisplayType::WARNING
|| nodep->displayType() == AstDisplayType::ERROR
|| nodep->displayType() == AstDisplayType::FATAL)) {
nodep->v3error(nodep->verilogKwd()+" only allowed under a assertion.");
}
if (nodep->displayType().needScopeTracking()
|| nodep->name().find("%m") != string::npos) {
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
}
} }
virtual void visit(AstScCtor* nodep, AstNUser*) { virtual void visit(AstScCtor* nodep, AstNUser*) {
@@ -345,6 +367,7 @@ public:
LinkResolveVisitor(AstNetlist* rootp) { LinkResolveVisitor(AstNetlist* rootp) {
m_ftaskp = NULL; m_ftaskp = NULL;
m_modp = NULL; m_modp = NULL;
m_assertp = NULL;
// //
rootp->accept(*this); rootp->accept(*this);
} }
+141 -27
View File
@@ -296,9 +296,14 @@ V3Number& V3Number::setAllBitsZ() {
for (int i=0; i<words(); i++) { m_value[i]=0; m_valueX[i] = ~0; } for (int i=0; i<words(); i++) { m_value[i]=0; m_valueX[i] = ~0; }
return *this; return *this;
} }
V3Number& V3Number::setMask(int nbits) {
setZero();
for (int bit=0; bit<nbits; bit++) { setBit(bit,1); }
return *this;
}
//====================================================================== //======================================================================
// ACCESSORS // ACCESSORS - as strings
string V3Number::ascii(bool prefixed, bool cleanVerilog) const { string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
ostringstream out; ostringstream out;
@@ -329,34 +334,115 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
if (binary) { if (binary) {
out<<"b"; out<<"b";
int bit=width()-1; out<<displayed("%0b");
while (bit && bitIs0(bit)) bit--;
for(; bit>=0; --bit) {
if (bitIs0(bit)) out<<'0';
else if (bitIs1(bit)) out<<'1';
else if (bitIsZ(bit)) out<<'z';
else out<<'x';
}
} }
else { else {
if (prefixed) out<<"h"; if (prefixed) out<<"h";
// Always deal with 4 bits at once. Note no 4-state, it's above. // Always deal with 4 bits at once. Note no 4-state, it's above.
int hexStart = width()-1; out<<displayed("%0h");
while (hexStart && bitIs0(hexStart)) hexStart--;
while ((hexStart&3)!=3) hexStart++;
for(int bit=hexStart; bit>0; ) {
int v = 0;
if (bitIs1(bit)) v |= 8; bit--;
if (bitIs1(bit)) v |= 4; bit--;
if (bitIs1(bit)) v |= 2; bit--;
if (bitIs1(bit)) v |= 1; bit--;
if (v>=10) out<<(char)('a'+v-10);
else out<<(char)('0'+v);
}
} }
return out.str(); return out.str();
} }
string V3Number::displayed(const string& vformat) const {
string::const_iterator pos = vformat.begin();
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
pos++;
string fmtsize;
for (; pos != vformat.end() && isdigit(pos[0]); pos++) {
fmtsize += pos[0];
}
string str;
char code = tolower(pos[0]);
switch (code) {
case 'b': {
int bit = width()-1;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
for (; bit>=0; bit--) {
if (bitIs0(bit)) str+='0';
else if (bitIs1(bit)) str+='1';
else if (bitIsZ(bit)) str+='z';
else str+='x';
}
return str;
}
case 'o': {
int bit = width()-1;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
while ((bit%3)!=2) bit++;
for (; bit>0; bit -= 3) {
int v = bitsValue(bit-2, 3);
str += (char)('0'+v);
}
return str;
}
case 'h':
case 'x': {
int bit = width()-1;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
while ((bit%4)!=3) bit++;
for (; bit>0; bit -= 4) {
int v = bitsValue(bit-3, 4);
if (v>=10) str += (char)('a'+v-10);
else str += (char)('0'+v);
}
return str;
}
case 'c': {
if (this->width()>8) m_fileline->v3error("$display of char format of > 8 bit value");
int v = bitsValue(0, 8);
str += (char)(v);
return str;
}
case 's': {
// Spec says always drop leading zeros, this isn't quite right, we space pad.
int bit=this->width()-1;
bool start=true;
while ((bit%8)!=7) bit++;
for (; bit>=0; bit -= 8) {
int v = bitsValue(bit-7, 8);
if (!start || v) {
str += (char)((v==0)?' ':v);
start = false; // Drop leading 0s
} else {
if (fmtsize != "0") str += ' ';
}
}
return str;
}
case '~': // Signed decimal
case 't':
case 'd': { // Unsigned decimal
bool issigned = (code == '~');
if (fmtsize == "") {
double mantissabits = this->width() - (issigned?1:0);
double maxval = pow(2.0, mantissabits);
double dchars = log10(maxval)+1.0;
if (issigned) dchars++; // space for sign
fmtsize = cvtToStr(int(dchars));
}
if (width() > 64) {
m_fileline->v3error("Unsupported: $display of dec format of > 64 bit results (use hex format instead)");
return "ERR";
}
if (issigned) {
str = cvtToStr(asSQuad());
} else {
str = cvtToStr(asQuad());
}
int intfmtsize = atoi(fmtsize.c_str());
while ((int)(str.length()) < intfmtsize) str = " "+str;
return str;
}
default:
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
return "ERR";
}
}
//======================================================================
// ACCESSORS - as numbers
uint32_t V3Number::asInt() const { uint32_t V3Number::asInt() const {
UASSERT(!isFourState(),"asInt with 4-state "<<*this); UASSERT(!isFourState(),"asInt with 4-state "<<*this);
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this); UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this);
@@ -364,18 +450,24 @@ uint32_t V3Number::asInt() const {
} }
vlsint32_t V3Number::asSInt() const { vlsint32_t V3Number::asSInt() const {
UASSERT(!isFourState(),"asSInt with 4-state "<<*this); uint32_t v = asInt();
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this); uint32_t signExtend = (-(v & (1UL<<(width()-1))));
uint32_t signExtend = (-((m_value[0]) & (1UL<<(width()-1)))); uint32_t extended = v | signExtend;
uint32_t extended = m_value[0] | signExtend;
return (vlsint32_t)(extended); return (vlsint32_t)(extended);
} }
vluint64_t V3Number::asQuad() const { vluint64_t V3Number::asQuad() const {
UASSERT(!isFourState(),"asQuad with 4-state "<<*this); UASSERT(!isFourState(),"asQuad with 4-state "<<*this);
UASSERT(width()<65, "Value too wide "<<*this); UASSERT(width()<65, "Value too wide "<<*this);
if (width()<=32) return ((vluint64_t)m_value[0]); if (width()<=32) return ((vluint64_t)(asInt()));
else return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]); return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]);
}
vlsint64_t V3Number::asSQuad() const {
vluint64_t v = asQuad();
vluint64_t signExtend = (-(v & (VL_ULL(1)<<(width()-1))));
vluint64_t extended = v | signExtend;
return (vlsint64_t)(extended);
} }
uint32_t V3Number::asHash() const { uint32_t V3Number::asHash() const {
@@ -722,6 +814,28 @@ last:
return setSingleBits(outc); return setSingleBits(outc);
} }
V3Number& V3Number::opWildEq (const V3Number& lhs, const V3Number& rhs) {
char outc = 1;
for (int bit=0; bit<max(lhs.width(),rhs.width()); bit++) {
if (!rhs.bitIsXZ(bit)
&& lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=0; goto last; }
if (lhs.bitIsXZ(bit)) outc='x';
}
last:
return setSingleBits(outc);
}
V3Number& V3Number::opWildNeq (const V3Number& lhs, const V3Number& rhs) {
char outc = 0;
for (int bit=0; bit<max(lhs.width(),rhs.width()); bit++) {
if (!rhs.bitIsXZ(bit)
&& lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=1; goto last; }
if (lhs.bitIsXZ(bit)) outc='x';
}
last:
return setSingleBits(outc);
}
V3Number& V3Number::opGt (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opGt (const V3Number& lhs, const V3Number& rhs) {
// i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend. // i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend.
char outc = 0; char outc = 0;
+11
View File
@@ -94,6 +94,12 @@ private:
bool bitIsZ (int bit) const { bool bitIsZ (int bit) const {
if (bit>=m_width) return bitIsZ(m_width-1); if (bit>=m_width) return bitIsZ(m_width-1);
return ( (~m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); } return ( (~m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); }
uint32_t bitsValue(int lsb, int nbits) const {
uint32_t v=0;
for (int bitn=0; bitn<nbits; bitn++) { v |= (bitIs1(lsb+bitn)<<bitn); }
return v;
}
int words() const { return ((width()+31)/32); } int words() const { return ((width()+31)/32); }
public: public:
@@ -108,9 +114,11 @@ public:
// SETTERS // SETTERS
V3Number& setAllBitsX(); V3Number& setAllBitsX();
V3Number& setAllBitsZ(); V3Number& setAllBitsZ();
V3Number& setMask(int nbits); // IE if nbits=1, then 0b1, if 2->0b11, if 3->0b111 etc
// ACCESSORS // ACCESSORS
string ascii(bool prefixed=true, bool cleanVerilog=false) const; string ascii(bool prefixed=true, bool cleanVerilog=false) const;
string displayed(const string& format) const;
int width() const { return m_width; } int width() const { return m_width; }
int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1) int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1)
bool sized() const { return m_sized; } bool sized() const { return m_sized; }
@@ -128,6 +136,7 @@ public:
uint32_t asInt() const; uint32_t asInt() const;
vlsint32_t asSInt() const; vlsint32_t asSInt() const;
vluint64_t asQuad() const; vluint64_t asQuad() const;
vlsint64_t asSQuad() const;
uint32_t asHash() const; uint32_t asHash() const;
uint32_t dataWord(int word) const; uint32_t dataWord(int word) const;
uint32_t countOnes() const; uint32_t countOnes() const;
@@ -165,6 +174,8 @@ public:
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths); V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs); V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs); V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
// "standard" math // "standard" math
V3Number& opNot (const V3Number& lhs); V3Number& opNot (const V3Number& lhs);
V3Number& opLogNot (const V3Number& lhs); V3Number& opLogNot (const V3Number& lhs);
+3
View File
@@ -65,7 +65,10 @@ void test(string lhss, string op, string rhss, string exps) {
else if (op=="<<") gotnum.opShiftL (lhnum,rhnum); else if (op=="<<") gotnum.opShiftL (lhnum,rhnum);
else if (op=="==") gotnum.opEq (lhnum,rhnum); else if (op=="==") gotnum.opEq (lhnum,rhnum);
else if (op=="===") gotnum.opCaseEq (lhnum,rhnum); else if (op=="===") gotnum.opCaseEq (lhnum,rhnum);
else if (op=="==?") gotnum.opWildEq (lhnum,rhnum);
else if (op=="!=") gotnum.opNeq (lhnum,rhnum); else if (op=="!=") gotnum.opNeq (lhnum,rhnum);
else if (op=="!==") gotnum.opCaseNeq (lhnum,rhnum);
else if (op=="!=?") gotnum.opWildNeq (lhnum,rhnum);
else if (op=="<=") gotnum.opLte (lhnum,rhnum); else if (op=="<=") gotnum.opLte (lhnum,rhnum);
else if (op==">=") gotnum.opGte (lhnum,rhnum); else if (op==">=") gotnum.opGte (lhnum,rhnum);
else if (op=="&&") gotnum.opLogAnd (lhnum,rhnum); else if (op=="&&") gotnum.opLogAnd (lhnum,rhnum);
+37 -14
View File
@@ -48,7 +48,8 @@ struct V3OptionsImp {
list<string> m_allArgs; // List of every argument encountered list<string> m_allArgs; // List of every argument encountered
list<string> m_incDirs; // Include directories (ordered) list<string> m_incDirs; // Include directories (ordered)
set<string> m_incDirSet; // Include directories (for removing duplicates) set<string> m_incDirSet; // Include directories (for removing duplicates)
set<string> m_libExts; // Library extensions list<string> m_libExts; // Library extensions (ordered)
set<string> m_libExtSet; // Library extensions (for removing duplicates)
DirMap m_dirMap; // Directory listing DirMap m_dirMap; // Directory listing
// ACCESSOR METHODS // ACCESSOR METHODS
@@ -59,8 +60,9 @@ struct V3OptionsImp {
} }
} }
void addLibExt(const string& libext) { void addLibExt(const string& libext) {
if (m_libExts.find(libext) == m_libExts.end()) { if (m_libExtSet.find(libext) == m_libExtSet.end()) {
m_libExts.insert(libext); m_libExtSet.insert(libext);
m_libExts.push_back(libext);
} }
} }
V3OptionsImp() {} V3OptionsImp() {}
@@ -193,7 +195,7 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
// using the incdir and libext's. // using the incdir and libext's.
// Return "" if not found. // Return "" if not found.
for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) { for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) {
for (set<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) { for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter); string fn = filenameFromDirBase(*dirIter,modname+*extIter);
string exists = fileExists(fn); string exists = fileExists(fn);
if (exists!="") { if (exists!="") {
@@ -214,7 +216,7 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
} else { } else {
fl->v3error("Looked in:"<<endl); fl->v3error("Looked in:"<<endl);
for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) { for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) {
for (set<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) { for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter); string fn = filenameFromDirBase(*dirIter,modname+*extIter);
fl->v3error(" "<<fn<<endl); fl->v3error(" "<<fn<<endl);
} }
@@ -353,6 +355,10 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
shift; shift;
m_outputSplitCFuncs = atoi(argv[i]); m_outputSplitCFuncs = atoi(argv[i]);
} }
else if ( !strcmp (sw, "-trace-depth") ) {
shift;
m_traceDepth = atoi(argv[i]);
}
else if ( !strcmp (sw, "-unroll-count") ) { // Undocumented optimization tweak else if ( !strcmp (sw, "-unroll-count") ) { // Undocumented optimization tweak
shift; shift;
m_unrollCount = atoi(argv[i]); m_unrollCount = atoi(argv[i]);
@@ -377,6 +383,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; } else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; }
else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)){ m_inhibitSim = flag; } else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)){ m_inhibitSim = flag; }
else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; } else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; }
else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; }
else if ( onoff (sw, "-pins64", flag/*ref*/) ) { m_pins64 = flag; } else if ( onoff (sw, "-pins64", flag/*ref*/) ) { m_pins64 = flag; }
else if ( !strcmp (sw, "-private") ) { m_public = false; } else if ( !strcmp (sw, "-private") ) { m_public = false; }
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; } else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
@@ -447,18 +454,20 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
V3Error::pretendError(code, true); V3Error::pretendError(code, true);
} }
} }
else if ( !strcmp (sw, "-x-assign") && (i+1)<argc) {
shift;
if (!strcmp (argv[i], "0")) { m_xAssign="0"; }
else if (!strcmp (argv[i], "1")) { m_xAssign="1"; }
else if (!strcmp (argv[i], "unique")) { m_xAssign="unique"; }
else {
fl->v3fatal("Unknown setting for -x-assign: "<<sw);
}
}
else if ( !strcmp (sw, "-bin") && (i+1)<argc ) { else if ( !strcmp (sw, "-bin") && (i+1)<argc ) {
shift; m_bin = argv[i]; shift; m_bin = argv[i];
} }
else if ( !strcmp (sw, "-compiler") && (i+1)<argc) {
shift;
if (!strcmp (argv[i], "gcc")) {
m_compLimitParens = 0;
} else if (!strcmp (argv[i], "msvc")) {
m_compLimitParens = 80; // 128, but allow some room
m_compLimitBlocks = 80; // 128, but allow some room
} else {
fl->v3fatal("Unknown setting for --compiler: "<<argv[i]);
}
}
else if ( !strcmp (sw, "-f") && (i+1)<argc ) { else if ( !strcmp (sw, "-f") && (i+1)<argc ) {
shift; shift;
parseOptsFile(fl, argv[i]); parseOptsFile(fl, argv[i]);
@@ -473,6 +482,15 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
shift; m_prefix = argv[i]; shift; m_prefix = argv[i];
if (m_modPrefix=="") m_modPrefix = m_prefix; if (m_modPrefix=="") m_modPrefix = m_prefix;
} }
else if ( !strcmp (sw, "-x-assign") && (i+1)<argc) {
shift;
if (!strcmp (argv[i], "0")) { m_xAssign="0"; }
else if (!strcmp (argv[i], "1")) { m_xAssign="1"; }
else if (!strcmp (argv[i], "unique")) { m_xAssign="unique"; }
else {
fl->v3fatal("Unknown setting for --x-assign: "<<argv[i]);
}
}
else if ( !strcmp (sw, "-y")) { else if ( !strcmp (sw, "-y")) {
shift; addIncDir (string (argv[i])); shift; addIncDir (string (argv[i]));
} }
@@ -568,6 +586,7 @@ V3Options::V3Options() {
m_exe = false; m_exe = false;
m_ignc = false; m_ignc = false;
m_l2Name = true; m_l2Name = true;
m_lintOnly = false;
m_makeDepend = true; m_makeDepend = true;
m_makePhony = false; m_makePhony = false;
m_outFormatOk = false; m_outFormatOk = false;
@@ -587,9 +606,13 @@ V3Options::V3Options() {
m_inlineMult = 2000; m_inlineMult = 2000;
m_outputSplit = 0; m_outputSplit = 0;
m_outputSplitCFuncs = 0; m_outputSplitCFuncs = 0;
m_traceDepth = 0;
m_unrollCount = 64; m_unrollCount = 64;
m_unrollStmts = 20; m_unrollStmts = 20;
m_compLimitParens = 0;
m_compLimitBlocks = 0;
m_makeDir = "obj_dir"; m_makeDir = "obj_dir";
m_bin = ""; m_bin = "";
m_flags = ""; m_flags = "";
+11
View File
@@ -56,6 +56,7 @@ class V3Options {
bool m_ignc; // main switch: --ignc bool m_ignc; // main switch: --ignc
bool m_inhibitSim; // main switch: --inhibit-sim bool m_inhibitSim; // main switch: --inhibit-sim
bool m_l2Name; // main switch: --l2name bool m_l2Name; // main switch: --l2name
bool m_lintOnly; // main switch: --lint-only
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
bool m_pins64; // main switch: --pins64 bool m_pins64; // main switch: --pins64
bool m_profileCFuncs;// main switch: --profile-cfuncs bool m_profileCFuncs;// main switch: --profile-cfuncs
@@ -72,9 +73,13 @@ class V3Options {
int m_inlineMult; // main switch: --inline-mult int m_inlineMult; // main switch: --inline-mult
int m_outputSplit; // main switch: --output-split int m_outputSplit; // main switch: --output-split
int m_outputSplitCFuncs;// main switch: --output-split-cfuncs int m_outputSplitCFuncs;// main switch: --output-split-cfuncs
int m_traceDepth; // main switch: --trace-depth
int m_unrollCount; // main switch: --unroll-count int m_unrollCount; // main switch: --unroll-count
int m_unrollStmts; // main switch: --unroll-stmts int m_unrollStmts; // main switch: --unroll-stmts
int m_compLimitBlocks; // compiler selection options
int m_compLimitParens; // compiler selection options
string m_bin; // main switch: --bin {binary} string m_bin; // main switch: --bin {binary}
string m_flags; // main switch: -f {name} string m_flags; // main switch: -f {name}
string m_top; // main switch: Top .v file name string m_top; // main switch: Top .v file name
@@ -149,15 +154,20 @@ class V3Options {
bool psl() const { return m_psl; } bool psl() const { return m_psl; }
bool allPublic() const { return m_public; } bool allPublic() const { return m_public; }
bool l2Name() const { return m_l2Name; } bool l2Name() const { return m_l2Name; }
bool lintOnly() const { return m_lintOnly; }
bool ignc() const { return m_ignc; } bool ignc() const { return m_ignc; }
bool inhibitSim() const { return m_inhibitSim; } bool inhibitSim() const { return m_inhibitSim; }
int inlineMult() const { return m_inlineMult; } int inlineMult() const { return m_inlineMult; }
int outputSplit() const { return m_outputSplit; } int outputSplit() const { return m_outputSplit; }
int outputSplitCFuncs() const { return m_outputSplitCFuncs; } int outputSplitCFuncs() const { return m_outputSplitCFuncs; }
int traceDepth() const { return m_traceDepth; }
int unrollCount() const { return m_unrollCount; } int unrollCount() const { return m_unrollCount; }
int unrollStmts() const { return m_unrollStmts; } int unrollStmts() const { return m_unrollStmts; }
int compLimitBlocks() const { return m_compLimitBlocks; }
int compLimitParens() const { return m_compLimitParens; }
string makeDir() const { return m_makeDir; } string makeDir() const { return m_makeDir; }
string prefix() const { return m_prefix; } string prefix() const { return m_prefix; }
string modPrefix() const { return m_modPrefix; } string modPrefix() const { return m_modPrefix; }
@@ -165,6 +175,7 @@ class V3Options {
const V3StringSet& cppFiles() const { return m_cppFiles; } const V3StringSet& cppFiles() const { return m_cppFiles; }
const V3StringSet& libraryFiles() const { return m_libraryFiles; } const V3StringSet& libraryFiles() const { return m_libraryFiles; }
// ACCESSORS (optimization options) // ACCESSORS (optimization options)
bool oAcycSimp() const { return m_oAcycSimp; } bool oAcycSimp() const { return m_oAcycSimp; }
bool oCase() const { return m_oCase; } bool oCase() const { return m_oCase; }
+8
View File
@@ -382,6 +382,14 @@ private:
//nodep->v3warn(GENCLK,"Signal unoptimizable: Generated clock: "<<nodep->prettyName()); //nodep->v3warn(GENCLK,"Signal unoptimizable: Generated clock: "<<nodep->prettyName());
} else if (nodep->varp()->isSigPublic()) { } else if (nodep->varp()->isSigPublic()) {
nodep->v3warn(UNOPT,"Signal unoptimizable: Feedback to public clock or circular logic: "<<nodep->prettyName()); nodep->v3warn(UNOPT,"Signal unoptimizable: Feedback to public clock or circular logic: "<<nodep->prettyName());
if (!nodep->fileline()->warnIsOff(V3ErrorCode::UNOPT)) {
nodep->fileline()->warnOff(V3ErrorCode::UNOPT, true); // Complain just once
// Give the user an example.
bool tempWeight = (edgep && edgep->weight()==0);
if (tempWeight) edgep->weight(1); // Else the below loop detect can't see the loop
m_graph.reportLoops(&OrderEdge::followComboConnected, vertexp); // calls OrderGraph::loopsVertexCb
if (tempWeight) edgep->weight(0);
}
} else { } else {
// We don't use UNOPT, as there are lots of V2 places where it was needed, that aren't any more // We don't use UNOPT, as there are lots of V2 places where it was needed, that aren't any more
// First v3warn not inside warnIsOff so we can see the suppressions with --debug // First v3warn not inside warnIsOff so we can see the suppressions with --debug
+1
View File
@@ -40,6 +40,7 @@
#define VP_DEFINE 261 #define VP_DEFINE 261
#define VP_ELSE 262 #define VP_ELSE 262
#define VP_ELSIF 263 #define VP_ELSIF 263
#define VP_LINE 264
#define VP_SYMBOL 300 #define VP_SYMBOL 300
#define VP_STRING 301 #define VP_STRING 301
+17 -2
View File
@@ -57,6 +57,9 @@ static void pslMoreNeeded(bool flag) { V3PreLex::s_currentLexp->m_pslMoreNeeded
%x DEFMODE %x DEFMODE
%x ARGMODE %x ARGMODE
%x INCMODE %x INCMODE
%x PRTMODE
/* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */
ws [ \t\f\r] ws [ \t\f\r]
wsn [ \t\f] wsn [ \t\f]
@@ -64,12 +67,14 @@ crnl [\r]*[\n]
quote [\"] quote [\"]
backslash [\\] backslash [\\]
symb [a-zA-Z_][a-zA-Z0-9_$]* symb [a-zA-Z_][a-zA-Z0-9_$]*
drop [\032]
psl [p]sl psl [p]sl
/**************************************************************/ /**************************************************************/
%% %%
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext); } <INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext);
return(VP_LINE); }
/* Special directives we recognise */ /* Special directives we recognise */
<INITIAL>"`include" { return(VP_INCLUDE); } <INITIAL>"`include" { return(VP_INCLUDE); }
@@ -103,6 +108,13 @@ psl [p]sl
if (V3PreLex::s_currentLexp->m_parenLevel) appendDefValue(yytext,yyleng); if (V3PreLex::s_currentLexp->m_parenLevel) appendDefValue(yytext,yyleng);
else return (VP_STRING); } else return (VP_STRING); }
/* Protected blocks */
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
<PRTMODE><<EOF>> { linenoInc(); yyerror("EOF in `protected"); yyleng=0; yyterminate(); }
<PRTMODE>{crnl} { linenoInc(); yymore(); }
<PRTMODE>. { yymore(); }
<PRTMODE>"`endprotected" { yy_pop_state(); return (VP_TEXT); }
/* Pass-through include <> filenames */ /* Pass-through include <> filenames */
<INCMODE><<EOF>> { linenoInc(); yyerror("EOF in unterminated include filename"); yyleng=0; yyterminate(); } <INCMODE><<EOF>> { linenoInc(); yyerror("EOF in unterminated include filename"); yyleng=0; yyterminate(); }
<INCMODE>{crnl} { linenoInc(); yyerror("Unterminated include filename"); BEGIN(INITIAL); } <INCMODE>{crnl} { linenoInc(); yyerror("Unterminated include filename"); BEGIN(INITIAL); }
@@ -113,6 +125,7 @@ psl [p]sl
/* Reading definition */ /* Reading definition */
<DEFMODE>"/*" { yy_push_state(CMTMODE); yymore(); } <DEFMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
<DEFMODE>"//"[^\n\r]* { return (VP_COMMENT);} <DEFMODE>"//"[^\n\r]* { return (VP_COMMENT);}
<DEFMODE>{drop} { }
<DEFMODE><<EOF>> { linenoInc(); yyerror("EOF (missing return?) in define value"); yyleng=0; yyterminate(); } <DEFMODE><<EOF>> { linenoInc(); yyerror("EOF (missing return?) in define value"); yyleng=0; yyterminate(); }
<DEFMODE>{crnl} { linenoInc(); yy_pop_state(); yytext="\n"; yyleng=1; return (VP_DEFVALUE); } <DEFMODE>{crnl} { linenoInc(); yy_pop_state(); yytext="\n"; yyleng=1; return (VP_DEFVALUE); }
<DEFMODE>[\\]{crnl} { linenoInc(); appendDefValue("\n",1); } /* Include return so can maintain output line count */ <DEFMODE>[\\]{crnl} { linenoInc(); appendDefValue("\n",1); } /* Include return so can maintain output line count */
@@ -123,6 +136,7 @@ psl [p]sl
/* Define arguments */ /* Define arguments */
<ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); } <ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
<ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);} <ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);}
<ARGMODE>{drop} { }
<ARGMODE><<EOF>> { yyerror("EOF in define argument list\n"); yyleng = 0; yyterminate(); } <ARGMODE><<EOF>> { yyerror("EOF in define argument list\n"); yyleng = 0; yyterminate(); }
<ARGMODE>{crnl} { linenoInc(); yytext="\n"; yyleng=1; return(VP_WHITE); } <ARGMODE>{crnl} { linenoInc(); yytext="\n"; yyleng=1; return(VP_WHITE); }
<ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); } <ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); }
@@ -179,8 +193,9 @@ psl [p]sl
/* Generics */ /* Generics */
<INITIAL,PSLMULM>{crnl} { linenoInc(); yytext="\n"; yyleng=1; return(VP_WHITE); } <INITIAL,PSLMULM>{crnl} { linenoInc(); yytext="\n"; yyleng=1; return(VP_WHITE); }
<INITIAL,PSLMULM,PSLONEM>{symb} { return (VP_SYMBOL); } <INITIAL,PSLMULM,PSLONEM>{symb} { return (VP_SYMBOL); }
<INITIAL,PSLMULM,PSLONEM>[\r] { }
<INITIAL,PSLMULM,PSLONEM>{wsn}+ { return (VP_WHITE); } <INITIAL,PSLMULM,PSLONEM>{wsn}+ { return (VP_WHITE); }
<INITIAL,PSLMULM,PSLONEM>{drop} { }
<INITIAL,PSLMULM,PSLONEM>[\r] { }
<INITIAL,PSLMULM,PSLONEM>. { return (VP_TEXT); } <INITIAL,PSLMULM,PSLONEM>. { return (VP_TEXT); }
%% %%
+45 -12
View File
@@ -83,7 +83,9 @@ struct V3PreProcImp : public V3PreProc {
// For getRawToken/ `line insertion // For getRawToken/ `line insertion
string m_lineCmt; // Line comment(s) to be returned string m_lineCmt; // Line comment(s) to be returned
int m_lineAdd; // Empty lines to return to maintain line count bool m_lineCmtNl; ///< Newline needed before inserting lineCmt
int m_lineAdd; ///< Empty lines to return to maintain line count
bool m_rawAtBol; ///< Last rawToken left us at beginning of line
// For defines // For defines
string m_defName; // Define last name being defined string m_defName; // Define last name being defined
@@ -134,6 +136,7 @@ public:
virtual bool isEof() const { return (m_lexp==NULL); } virtual bool isEof() const { return (m_lexp==NULL); }
virtual string getline(); virtual string getline();
virtual void insertUnreadback(const string& text) { m_lineCmt += text; } virtual void insertUnreadback(const string& text) { m_lineCmt += text; }
void insertUnreadbackAtBol(const string& text);
// METHODS, callbacks // METHODS, callbacks
virtual void comment(const string& cmt); // Comment detected (if keepComments==2) virtual void comment(const string& cmt); // Comment detected (if keepComments==2)
@@ -151,6 +154,8 @@ public:
m_lineChars = ""; m_lineChars = "";
m_lastSym = ""; m_lastSym = "";
m_lineAdd = 0; m_lineAdd = 0;
m_lineCmtNl = false;
m_rawAtBol = true;
m_defDepth = 0; m_defDepth = 0;
} }
}; };
@@ -301,12 +306,12 @@ void V3PreProcImp::comment(const string& text) {
if (commentTokenMatch(cmd/*ref*/, "parallel_case")) { if (commentTokenMatch(cmd/*ref*/, "parallel_case")) {
insertUnreadback ("/*verilator parallel_case*/"); insertUnreadback ("/*verilator parallel_case*/");
} }
if (commentTokenMatch(cmd/*ref*/, "one_hot")) { //if (commentTokenMatch(cmd/*ref*/, "one_hot")) {
insertUnreadback ("/*verilator one_hot*/ "+cmd+";"); // insertUnreadback ("/*verilator one_hot*/ "+cmd+";");
} //}
if (commentTokenMatch(cmd/*ref*/, "one_cold")) { //if (commentTokenMatch(cmd/*ref*/, "one_cold")) {
insertUnreadback ("/*verilator one_cold*/ "+cmd+";"); // insertUnreadback ("/*verilator one_cold*/ "+cmd+";");
} //}
// else ignore the comment we don't recognize // else ignore the comment we don't recognize
} // else no assertions } // else no assertions
} else { } else {
@@ -328,6 +333,7 @@ const char* V3PreProcImp::tokenName(int tok) {
case VP_DEFINE : return("DEFINE"); case VP_DEFINE : return("DEFINE");
case VP_ELSE : return("ELSE"); case VP_ELSE : return("ELSE");
case VP_ELSIF : return("ELSIF"); case VP_ELSIF : return("ELSIF");
case VP_LINE : return("LINE");
case VP_SYMBOL : return("SYMBOL"); case VP_SYMBOL : return("SYMBOL");
case VP_STRING : return("STRING"); case VP_STRING : return("STRING");
case VP_DEFVALUE : return("DEFVALUE"); case VP_DEFVALUE : return("DEFVALUE");
@@ -485,14 +491,24 @@ void V3PreProcImp::openFile(FileLine* fl, const string& filename) {
yy_switch_to_buffer(m_lexp->m_yyState); yy_switch_to_buffer(m_lexp->m_yyState);
} }
void V3PreProcImp::insertUnreadbackAtBol(const string& text) {
// Insert insuring we're at the beginning of line, for `line
// We don't always add a leading newline, as it may result in extra unreadback(newlines).
if (m_lineCmt == "") { m_lineCmtNl = true; }
else if (m_lineCmt[m_lineCmt.length()-1]!='\n') {
insertUnreadback("\n");
}
insertUnreadback(text);
}
void V3PreProcImp::addLineComment(int enter_exit_level) { void V3PreProcImp::addLineComment(int enter_exit_level) {
if (lineDirectives()) { if (lineDirectives()) {
char numbuf[20]; sprintf(numbuf, "%d", m_lexp->m_curFilelinep->lineno()); char numbuf[20]; sprintf(numbuf, "%d", m_lexp->m_curFilelinep->lineno());
char levelbuf[20]; sprintf(levelbuf, "%d", enter_exit_level); char levelbuf[20]; sprintf(levelbuf, "%d", enter_exit_level);
string cmt = ((string)"\n`line "+numbuf string cmt = ((string)"`line "+numbuf
+" \""+m_lexp->m_curFilelinep->filename()+"\" " +" \""+m_lexp->m_curFilelinep->filename()+"\" "
+levelbuf+"\n"); +levelbuf+"\n");
insertUnreadback(cmt); insertUnreadbackAtBol(cmt);
} }
} }
@@ -516,6 +532,7 @@ int V3PreProcImp::getRawToken() {
next_tok: next_tok:
if (m_lineAdd) { if (m_lineAdd) {
m_lineAdd--; m_lineAdd--;
m_rawAtBol = true;
yytext="\n"; yyleng=1; yytext="\n"; yyleng=1;
return (VP_TEXT); return (VP_TEXT);
} }
@@ -523,8 +540,13 @@ int V3PreProcImp::getRawToken() {
// We have some `line directive to return to the user. Do it. // We have some `line directive to return to the user. Do it.
static string rtncmt; // Keep the c string till next call static string rtncmt; // Keep the c string till next call
rtncmt = m_lineCmt; rtncmt = m_lineCmt;
if (m_lineCmtNl) {
if (!m_rawAtBol) rtncmt = "\n"+rtncmt;
m_lineCmtNl = false;
}
yytext=(char*)rtncmt.c_str(); yyleng=rtncmt.length(); yytext=(char*)rtncmt.c_str(); yyleng=rtncmt.length();
m_lineCmt = ""; m_lineCmt = "";
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
if (m_state!=ps_DEFVALUE) return (VP_TEXT); if (m_state!=ps_DEFVALUE) return (VP_TEXT);
else { else {
V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng); V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng);
@@ -532,6 +554,7 @@ int V3PreProcImp::getRawToken() {
} }
} }
if (isEof()) return (VP_EOF); if (isEof()) return (VP_EOF);
// Snarf next token from the file // Snarf next token from the file
m_fileline = m_lexp->m_curFilelinep; // Remember token start location m_fileline = m_lexp->m_curFilelinep; // Remember token start location
V3PreLex::s_currentLexp = m_lexp; // Tell parser where to get/put data V3PreLex::s_currentLexp = m_lexp; // Tell parser where to get/put data
@@ -552,6 +575,7 @@ int V3PreProcImp::getRawToken() {
goto next_tok; // Parse parent, or find the EOF. goto next_tok; // Parse parent, or find the EOF.
} }
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
return tok; return tok;
} }
} }
@@ -583,6 +607,10 @@ int V3PreProcImp::getToken() {
for (int len=0; len<yyleng; len++) { if (yytext[len]=='\n') m_lineAdd++; } for (int len=0; len<yyleng; len++) { if (yytext[len]=='\n') m_lineAdd++; }
goto next_tok; goto next_tok;
} }
if (tok==VP_LINE) {
addLineComment(0);
goto next_tok;
}
// Deal with some special parser states // Deal with some special parser states
switch (m_state) { switch (m_state) {
case ps_TOP: { case ps_TOP: {
@@ -867,7 +895,8 @@ string V3PreProcImp::getline() {
// Get a single line from the parse stream. Buffer unreturned text until the newline. // Get a single line from the parse stream. Buffer unreturned text until the newline.
if (isEof()) return ""; if (isEof()) return "";
char* rtnp; char* rtnp;
while (NULL==(rtnp=strchr(m_lineChars.c_str(),'\n'))) { bool gotEof = false;
while (NULL==(rtnp=strchr(m_lineChars.c_str(),'\n')) && !gotEof) {
int tok = getToken(); int tok = getToken();
if (debug()>4) { if (debug()>4) {
string buf = string (yytext, yyleng); string buf = string (yytext, yyleng);
@@ -878,8 +907,12 @@ string V3PreProcImp::getline() {
fileline()->lineno(), tokenName(tok), buf.c_str()); fileline()->lineno(), tokenName(tok), buf.c_str());
} }
if (tok==VP_EOF) { if (tok==VP_EOF) {
// Add a final newline, in case the user forgot the final \n. // Add a final newline, if the user forgot the final \n.
m_lineChars.append("\n"); // Note tok==VP_EOF isn't always seen by us, as isEof() may be set earlier
if (m_lineChars != "" && m_lineChars[m_lineChars.length()-1] != '\n') {
m_lineChars.append("\n");
}
gotEof = true;
} }
else if (tok==VP_PSL) { else if (tok==VP_PSL) {
m_lineChars.append(" psl "); m_lineChars.append(" psl ");
-6
View File
@@ -61,12 +61,6 @@ protected:
s_preprocp->define(prefl,"verilator3", "1"); s_preprocp->define(prefl,"verilator3", "1");
s_preprocp->define(prefl,"systemc_clock", "/*verilator systemc_clock*/"); s_preprocp->define(prefl,"systemc_clock", "/*verilator systemc_clock*/");
s_preprocp->define(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); s_preprocp->define(prefl,"coverage_block_off", "/*verilator coverage_block_off*/");
// Standards - We ignore
s_preprocp->define(prefl,"endcelldefine", "");
s_preprocp->define(prefl,"celldefine", "");
s_preprocp->define(prefl,"resetall", "");
s_preprocp->define(prefl,"portcoerce", "");
s_preprocp->define(prefl,"inline", "");
} }
} }
+8 -3
View File
@@ -71,14 +71,18 @@ private:
// ASSIGN(CONST*here*, VARREF(!sc)) // ASSIGN(CONST*here*, VARREF(!sc))
// ARRAYSEL(*here*, ...) (No wides can be in any argument but first, so we don't check which arg is wide) // ARRAYSEL(*here*, ...) (No wides can be in any argument but first, so we don't check which arg is wide)
// ASSIGN(x, SEL*HERE*(ARRAYSEL()...) (m_assignLhs==true handles this.) // ASSIGN(x, SEL*HERE*(ARRAYSEL()...) (m_assignLhs==true handles this.)
//UINFO(9, " Check: "<<nodep<<endl);
//UINFO(9, " Detail stmtp="<<(m_stmtp?"Y":"N")<<" U="<<(nodep->user()?"Y":"N")<<" IW "<<(nodep->isWide()?"Y":"N")<<endl);
if (m_stmtp if (m_stmtp
&& !nodep->user()) { // Not already done && !nodep->user()) { // Not already done
if (nodep->isWide()) { // Else might be cell interconnect or something if (nodep->isWide()) { // Else might be cell interconnect or something
if (m_assignLhs) { if (m_assignLhs) {
} else if (nodep->backp()->castNodeAssign() } else if (nodep->firstAbovep()
&& assignNoTemp(nodep->backp()->castNodeAssign())) { && nodep->firstAbovep()->castNodeAssign()
&& assignNoTemp(nodep->firstAbovep()->castNodeAssign())) {
// Not much point if it's just a direct assignment to a constant // Not much point if it's just a direct assignment to a constant
} else if (nodep->backp()->castArraySel()) { // ArraySel's are pointer refs, ignore } else if (nodep->firstAbovep()
&& nodep->firstAbovep()->castArraySel()) { // ArraySel's are pointer refs, ignore
} else { } else {
UINFO(4,"Cre Temp: "<<nodep<<endl); UINFO(4,"Cre Temp: "<<nodep<<endl);
createDeepTemp(nodep); createDeepTemp(nodep);
@@ -140,6 +144,7 @@ private:
virtual void visit(AstCFunc* nodep, AstNUser*) { virtual void visit(AstCFunc* nodep, AstNUser*) {
m_funcp = nodep; m_funcp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_funcp = NULL;
} }
void startStatement(AstNode* nodep) { void startStatement(AstNode* nodep) {
m_assignLhs = false; m_assignLhs = false;
+2 -2
View File
@@ -62,10 +62,10 @@ public:
// METHODS // METHODS
void stateExitPsl() { void stateExitPsl() {
if (YY_START != PSL) yyerror("Internal error: Exiting PSL state when not in PSL state"); if (YY_START != PSL) yyerror("Internal error: Exiting PSL state when not in PSL state");
BEGIN VLG; yy_pop_state();
} }
void statePushVlg() { void statePushVlg() {
yy_push_state(VLG); yy_push_state(STATE_VERILOG_RECENT);
} }
void statePop() { void statePop() {
yy_pop_state(); yy_pop_state();
+16 -1
View File
@@ -38,9 +38,13 @@ class V3Read {
V3Lexer* m_lexerp; // Current FlexLexer V3Lexer* m_lexerp; // Current FlexLexer
static V3Read* s_readp; // Current THIS, bison() isn't class based static V3Read* s_readp; // Current THIS, bison() isn't class based
FileLine* m_fileline; // Filename/linenumber currently active FileLine* m_fileline; // Filename/linenumber currently active
bool m_inLibrary; // Currently reading a library vs. regular file bool m_inCellDefine; // Inside a `celldefine
bool m_inLibrary; // Currently reading a library vs. regular file
int m_inBeginKwd; // Inside a `begin_keywords
int m_lastVerilogState; // Last LEX state in `begin_keywords
deque<string*> m_stringps; // Created strings for later cleanup deque<string*> m_stringps; // Created strings for later cleanup
deque<V3Number*> m_numberps; // Created numbers for later cleanup deque<V3Number*> m_numberps; // Created numbers for later cleanup
deque<FileLine> m_lintState; // Current lint state for save/restore
//int debug() { return 9; } //int debug() { return 9; }
protected: protected:
@@ -53,7 +57,12 @@ protected:
static void ppline (const char* text); static void ppline (const char* text);
static void incLineno() { s_readp->fileline()->incLineno(); } static void incLineno() { s_readp->fileline()->incLineno(); }
static void verilatorCmtLint(const char* text, bool on); static void verilatorCmtLint(const char* text, bool on);
static void verilatorCmtLintSave();
static void verilatorCmtLintRestore();
static void verilatorCmtBad(const char* text); static void verilatorCmtBad(const char* text);
static void pushBeginKeywords(int state) { s_readp->m_inBeginKwd++; s_readp->m_lastVerilogState=state; }
static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; }
static int lastVerilogState() { return s_readp->m_lastVerilogState; }
public: // But for internal use only public: // But for internal use only
static string* newString(const string& text) { static string* newString(const string& text) {
@@ -84,16 +93,22 @@ public: // But for internal use only
static FileLine* fileline() { return s_readp->m_fileline; } static FileLine* fileline() { return s_readp->m_fileline; }
static AstNetlist* rootp() { return s_readp->m_rootp; } static AstNetlist* rootp() { return s_readp->m_rootp; }
static FileLine* copyOrSameFileLine() { return s_readp->fileline()->copyOrSameFileLine(); } static FileLine* copyOrSameFileLine() { return s_readp->fileline()->copyOrSameFileLine(); }
static bool inCellDefine() { return s_readp->m_inCellDefine; }
static void inCellDefine(bool flag) { s_readp->m_inCellDefine = flag; }
static bool inLibrary() { return s_readp->m_inLibrary; } static bool inLibrary() { return s_readp->m_inLibrary; }
static void stateExitPsl(); // Parser -> lexer communication static void stateExitPsl(); // Parser -> lexer communication
static void statePushVlg(); // Parser -> lexer communication static void statePushVlg(); // Parser -> lexer communication
static void statePop(); // Parser -> lexer communication static void statePop(); // Parser -> lexer communication
static int stateVerilogRecent(); // Parser -> lexer communication
public: public:
// CREATORS // CREATORS
V3Read(AstNetlist* rootp) { V3Read(AstNetlist* rootp) {
m_rootp = rootp; m_lexerp = NULL; m_rootp = rootp; m_lexerp = NULL;
m_inCellDefine = false;
m_inLibrary = false; m_inLibrary = false;
m_inBeginKwd = 0;
m_lastVerilogState = stateVerilogRecent();
} }
~V3Read() { ~V3Read() {
for (deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) { for (deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) {
+10 -12
View File
@@ -198,19 +198,17 @@ private:
nodep->taskp(NULL); nodep->taskp(NULL);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
if (nodep->name().find("%m") != string::npos) { string prefix = (string)(".")+m_scopep->prettyName();
string prefix = (string)(".")+m_scopep->prettyName(); // TOP and above will be the user's name().
// TOP and above will be the user's name(). // Note 'TOP.'is stripped by prettyName, but not 'TOP'.
// Note 'TOP.'is stripped by prettyName, but not 'TOP'. if (prefix != ".TOP") {
if (prefix != ".TOP") { // To keep correct visual order, must add before other Text's
// To keep correct visual order, must add before other Text's AstNode* afterp = nodep->scopeAttrp();
AstNode* afterp = nodep->scopeAttrp(); if (afterp) afterp->unlinkFrBackWithNext();
if (afterp) afterp->unlinkFrBackWithNext(); nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix)); if (afterp) nodep->scopeAttrp(afterp);
if (afterp) nodep->scopeAttrp(afterp);
}
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+2
View File
@@ -98,8 +98,10 @@ private:
// ... (Though they should match. We don't check.) // ... (Though they should match. We don't check.)
virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); } virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); } virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqWild* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); } virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); } virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//======= //=======
// Signed: Output signed iff LHS signed; unary operator // Signed: Output signed iff LHS signed; unary operator
+1 -1
View File
@@ -428,7 +428,7 @@ private:
AstNode* firstp = nodep; // We may reorder, and nodep is no longer first. AstNode* firstp = nodep; // We may reorder, and nodep is no longer first.
void* oldBlockUser3 = nodep->user3p(); // May be overloaded in below loop, save it void* oldBlockUser3 = nodep->user3p(); // May be overloaded in below loop, save it
nodep->user3p(NULL); nodep->user3p(NULL);
if (nodep->backp()->nextp()==nodep) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at oncen"); if (!nodep->firstAbovep()) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at once");
// Process it // Process it
if (!nodep->nextp()) { if (!nodep->nextp()) {
// Just one, so can't reorder. Just look for more blocks/statements. // Just one, so can't reorder. Just look for more blocks/statements.
+13 -2
View File
@@ -20,7 +20,7 @@
//************************************************************************* //*************************************************************************
// V3SplitAs's Transformations: // V3SplitAs's Transformations:
// //
// Search each ALWAYS for a VARREF lvalue with a /*isolate_asignments*/ attribute // Search each ALWAYS for a VARREF lvalue with a /*isolate_assignments*/ attribute
// If found, color statements with both, assignment to that varref, or other assignments. // If found, color statements with both, assignment to that varref, or other assignments.
// Replicate the Always, and remove mis-colored duplicate code. // Replicate the Always, and remove mis-colored duplicate code.
// //
@@ -166,12 +166,23 @@ private:
virtual void visit(AstAlways* nodep, AstNUser*) { virtual void visit(AstAlways* nodep, AstNUser*) {
// Are there any lvalue references below this? // Are there any lvalue references below this?
// There could be more then one. So, we process the first one found first. // There could be more then one. So, we process the first one found first.
if (!nodep->user()) { AstVarScope* lastSplitVscp = NULL;
while (!nodep->user()) {
// Find any splittable variables
SplitAsFindVisitor visitor (nodep); SplitAsFindVisitor visitor (nodep);
m_splitVscp = visitor.splitVscp(); m_splitVscp = visitor.splitVscp();
if (m_splitVscp && m_splitVscp == lastSplitVscp) {
// We did this last time! Something's stuck!
nodep->v3fatalSrc("Infinite loop in isolate_assignments removal for: "<<m_splitVscp->prettyName())
m_splitVscp = NULL;
}
lastSplitVscp = m_splitVscp;
// Now isolate the always
if (m_splitVscp) { if (m_splitVscp) {
splitAlways(nodep); splitAlways(nodep);
m_statSplits++; m_statSplits++;
} else {
nodep->user(true);
} }
} }
} }
+2 -3
View File
@@ -63,9 +63,8 @@ private:
m_instrs += nodep->instrCount(); m_instrs += nodep->instrCount();
if (m_counting) { if (m_counting) {
++m_statTypeCount[nodep->type()]; ++m_statTypeCount[nodep->type()];
if (nodep->backp() && nodep->backp()->nextp()!=nodep) { if (nodep->firstAbovep()) { // Grab only those above, not those "back"
// Grab only those above, not those "back" ++m_statAbove[nodep->firstAbovep()->type()][nodep->type()];
++m_statAbove[nodep->backp()->type()][nodep->type()];
} }
m_statInstr += nodep->instrCount(); m_statInstr += nodep->instrCount();
if (m_cfuncp && !m_cfuncp->slow()) m_statInstrFast += nodep->instrCount(); if (m_cfuncp && !m_cfuncp->slow()) m_statInstrFast += nodep->instrCount();
+2 -1
View File
@@ -306,6 +306,7 @@ private:
AstVar* newvarp = new AstVar (invarp->fileline(), AstVarType::BLOCKTEMP, AstVar* newvarp = new AstVar (invarp->fileline(), AstVarType::BLOCKTEMP,
name, invarp); name, invarp);
newvarp->funcLocal(false); newvarp->funcLocal(false);
newvarp->propagateAttrFrom(invarp);
m_modp->addStmtp(newvarp); m_modp->addStmtp(newvarp);
AstVarScope* newvscp = new AstVarScope (newvarp->fileline(), m_scopep, newvarp); AstVarScope* newvscp = new AstVarScope (newvarp->fileline(), m_scopep, newvarp);
m_scopep->addVarp(newvscp); m_scopep->addVarp(newvscp);
@@ -628,7 +629,7 @@ private:
if (!funcp) nodep->v3fatalSrc("unlinked"); if (!funcp) nodep->v3fatalSrc("unlinked");
// Inline func refs in the function // Inline func refs in the function
iterateIntoFTask(funcp); iterateIntoFTask(funcp);
// Create output variabls // Create output variable
string namePrefix = "__Vfunc_"+funcp->shortName()+"__"+cvtToStr(m_modNCalls++); string namePrefix = "__Vfunc_"+funcp->shortName()+"__"+cvtToStr(m_modNCalls++);
AstVarScope* outvscp = createVarScope (funcp->fvarp()->castVar(), AstVarScope* outvscp = createVarScope (funcp->fvarp()->castVar(),
namePrefix+"__out"); namePrefix+"__out");
+42
View File
@@ -106,6 +106,42 @@ private:
newp->iterateChildren(*this); newp->iterateChildren(*this);
} }
} }
void visitEqNeqWild(AstNodeBiop* nodep) {
UINFO(4," N/EQWILD->EQ "<<nodep<<endl);
V3Const::constifyTree(nodep->lhsp());
V3Const::constifyTree(nodep->rhsp());
if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) {
// Both sides are constant, node can be constant
V3Const::constifyTree(nodep); nodep=NULL;
return;
} else {
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp;
if (!rhsp->castConst()) {
nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec.
// Replace with anything that won't cause more errors
newp = new AstEq (nodep->fileline(), lhsp, rhsp);
} else {
// X or Z's become mask, ala case statements.
V3Number nummask (rhsp->fileline(), rhsp->width());
nummask.opBitsNonX(rhsp->castConst()->num());
V3Number numval (rhsp->fileline(), rhsp->width());
numval.opBitsOne (rhsp->castConst()->num());
AstNode* and1p = new AstAnd(nodep->fileline(), lhsp,
new AstConst(nodep->fileline(), nummask));
AstNode* and2p = new AstConst(nodep->fileline(), numval);
if (nodep->castEqWild())
newp = new AstEq (nodep->fileline(), and1p, and2p);
else newp = new AstNeq (nodep->fileline(), and1p, and2p);
rhsp->deleteTree(); rhsp=NULL;
}
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
// Iterate tree now that we may have gotten rid of the compare
newp->iterateChildren(*this);
}
}
virtual void visit(AstEqCase* nodep, AstNUser*) { virtual void visit(AstEqCase* nodep, AstNUser*) {
visitEqNeqCase(nodep); visitEqNeqCase(nodep);
@@ -113,6 +149,12 @@ private:
virtual void visit(AstNeqCase* nodep, AstNUser*) { virtual void visit(AstNeqCase* nodep, AstNUser*) {
visitEqNeqCase(nodep); visitEqNeqCase(nodep);
} }
virtual void visit(AstEqWild* nodep, AstNUser*) {
visitEqNeqWild(nodep);
}
virtual void visit(AstNeqWild* nodep, AstNUser*) {
visitEqNeqWild(nodep);
}
virtual void visit(AstIsUnknown* nodep, AstNUser*) { virtual void visit(AstIsUnknown* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Ahh, we're two state, so this is easy // Ahh, we're two state, so this is easy
+6 -1
View File
@@ -252,7 +252,12 @@ private:
if (clonedIncsp) { if (clonedIncsp) {
// Previous iteration of loop set the variable. // Previous iteration of loop set the variable.
// This set is redundant with this next iteration and can be removed. // This set is redundant with this next iteration and can be removed.
clonedIncsp->unlinkFrBack()->deleteTree(); if (clonedIncsp == newbodysp) { // Increment was only thing in list
newbodysp = NULL;
} else {
clonedIncsp->unlinkFrBack();
}
clonedIncsp->deleteTree();
} }
clonedIncsp = incp->clonep(); if (!clonedIncsp) nodep->v3fatalSrc("inc failed"); clonedIncsp = incp->clonep(); if (!clonedIncsp) nodep->v3fatalSrc("inc failed");
} }
+12
View File
@@ -117,6 +117,7 @@ private:
void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup); void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup);
virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstEqWild* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstGt* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstGt* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstGtS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstGtS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstGte* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstGte* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
@@ -127,6 +128,7 @@ private:
virtual void visit(AstLteS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstLteS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstNeq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstNeq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstNeqCase* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstNeqCase* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstNeqWild* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
// Widths: out width = lhs width = rhs width // Widths: out width = lhs width = rhs width
void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup); void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup);
@@ -385,6 +387,9 @@ private:
virtual void visit(AstText* nodep, AstNUser* vup) { virtual void visit(AstText* nodep, AstNUser* vup) {
// Only used in CStmts which don't care.... // Only used in CStmts which don't care....
} }
virtual void visit(AstScopeName* nodep, AstNUser* vup) {
// Only used in Displays which don't care....
}
virtual void visit(AstVar* nodep, AstNUser* vup) { virtual void visit(AstVar* nodep, AstNUser* vup) {
//if (debug()) nodep->dumpTree(cout," InitPre: "); //if (debug()) nodep->dumpTree(cout," InitPre: ");
// Must have deterministic constant width // Must have deterministic constant width
@@ -575,6 +580,13 @@ private:
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p()); nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition. widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
} }
virtual void visit(AstVAssert* nodep, AstNUser*) {
// TOP LEVEL NODE
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
nodep->passsp()->iterateAndNext(*this);
nodep->failsp()->iterateAndNext(*this);
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
}
virtual void visit(AstPin* nodep, AstNUser*) { virtual void visit(AstPin* nodep, AstNUser*) {
//if (debug()) nodep->dumpTree(cout,"- PinPre: "); //if (debug()) nodep->dumpTree(cout,"- PinPre: ");
// TOP LEVEL NODE // TOP LEVEL NODE
+40 -27
View File
@@ -41,6 +41,7 @@
#include "V3Dead.h" #include "V3Dead.h"
#include "V3Delayed.h" #include "V3Delayed.h"
#include "V3Depth.h" #include "V3Depth.h"
#include "V3DepthBlock.h"
#include "V3Descope.h" #include "V3Descope.h"
#include "V3EmitC.h" #include "V3EmitC.h"
#include "V3EmitMk.h" #include "V3EmitMk.h"
@@ -159,13 +160,11 @@ void process () {
// Assertion insertion // Assertion insertion
// After we've added block coverage, but before other nasty transforms // After we've added block coverage, but before other nasty transforms
if (v3Global.opt.assertOn() || v3Global.opt.psl()) { V3AssertPre::assertPreAll(v3Global.rootp());
V3AssertPre::assertPreAll(v3Global.rootp()); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assertpre.tree"));
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assertpre.tree")); //
// V3Assert::assertAll(v3Global.rootp());
V3Assert::assertAll(v3Global.rootp()); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assert.tree"));
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assert.tree"));
}
// Add top level wrapper with instance pointing to old top // Add top level wrapper with instance pointing to old top
// Must do this after we know the width of any parameters // Must do this after we know the width of any parameters
@@ -381,6 +380,12 @@ void process () {
//--MODULE OPTIMIZATIONS-------------- //--MODULE OPTIMIZATIONS--------------
// Split deep blocks to appease MSVC++. Must be before Localize.
if (!v3Global.opt.lintOnly() && v3Global.opt.compLimitBlocks()) {
V3DepthBlock::depthBlockAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("deepblock.tree"));
}
// Move BLOCKTEMPS from class to local variables // Move BLOCKTEMPS from class to local variables
if (v3Global.opt.oLocalize()) { if (v3Global.opt.oLocalize()) {
V3Localize::localizeAll(v3Global.rootp()); V3Localize::localizeAll(v3Global.rootp());
@@ -435,24 +440,28 @@ void process () {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("dead.tree")); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("dead.tree"));
} }
// Fix very deep expressions if (!v3Global.opt.lintOnly()) {
// Mark evaluation functions as member functions, if needed. // Fix very deep expressions
V3Depth::depthAll(v3Global.rootp()); // Mark evaluation functions as member functions, if needed.
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("depth.tree")); V3Depth::depthAll(v3Global.rootp());
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("depth.tree"));
// Branch prediction // Branch prediction
V3Branch::branchAll(v3Global.rootp()); V3Branch::branchAll(v3Global.rootp());
// Add C casts when longs need to become long-long and vice-versa // Add C casts when longs need to become long-long and vice-versa
// Note depth may insert something needing a cast, so this must be last. // Note depth may insert something needing a cast, so this must be last.
V3Cast::castAll(v3Global.rootp()); V3Cast::castAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("cast.tree")); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("cast.tree"));
}
V3Error::abortIfErrors(); V3Error::abortIfErrors();
// Output the text // Output the text
V3EmitC::emitcSyms(); if (!v3Global.opt.lintOnly()) {
V3EmitC::emitcTrace(); V3EmitC::emitcSyms();
V3EmitC::emitcTrace();
}
V3EmitC::emitc(); V3EmitC::emitc();
// Statistics // Statistics
@@ -461,8 +470,10 @@ void process () {
V3Stats::statsReport(); V3Stats::statsReport();
} }
// Makefile must be after all other emitters if (!v3Global.opt.lintOnly()) {
V3EmitMk::emitmk(v3Global.rootp()); // Makefile must be after all other emitters
V3EmitMk::emitmk(v3Global.rootp());
}
} }
//###################################################################### //######################################################################
@@ -483,11 +494,11 @@ int main(int argc, char** argv, char** env) {
v3Global.opt.bin(argv[0]); v3Global.opt.bin(argv[0]);
string argString = V3Options::argString(argc-1, argv+1); string argString = V3Options::argString(argc-1, argv+1);
v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1); v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1);
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl()) { if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) {
v3fatal("Unsupported: Coverage analysis requires --sp output."); v3fatal("Unsupported: Coverage analysis requires --sp output.");
} }
if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly()) { if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly() && !v3Global.opt.lintOnly()) {
v3fatal("verilator: Need --cc, --sc, --sp or --E option"); v3fatal("verilator: Need --cc, --sc, --sp, --lint-only or --E option");
} }
V3Error::abortIfErrors(); V3Error::abortIfErrors();
@@ -496,6 +507,7 @@ int main(int argc, char** argv, char** env) {
V3File::addSrcDepend(v3Global.opt.bin()); V3File::addSrcDepend(v3Global.opt.bin());
if (v3Global.opt.skipIdentical() if (v3Global.opt.skipIdentical()
&& !v3Global.opt.preprocOnly() && !v3Global.opt.preprocOnly()
&& !v3Global.opt.lintOnly()
&& V3File::checkTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString)) { && V3File::checkTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString)) {
UINFO(1,"--skip-identical: No change to any source files, exiting\n"); UINFO(1,"--skip-identical: No change to any source files, exiting\n");
exit(0); exit(0);
@@ -526,12 +538,13 @@ int main(int argc, char** argv, char** env) {
// Final steps // Final steps
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99)); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
V3Error::abortIfErrors(); V3Error::abortIfWarnings();
if (v3Global.opt.makeDepend()) { if (!v3Global.opt.lintOnly() && v3Global.opt.makeDepend()) {
V3File::writeDepend(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__ver.d"); V3File::writeDepend(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__ver.d");
} }
if (v3Global.opt.skipIdentical() || v3Global.opt.makeDepend()) { if (!v3Global.opt.lintOnly()
&& (v3Global.opt.skipIdentical() || v3Global.opt.makeDepend())) {
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString); V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString);
} }
+2 -2
View File
@@ -4,7 +4,7 @@
// //
// This file is part of Verilator. // This file is part of Verilator.
// //
// Author: Wilson Snyder <[email protected]> or <[email protected]> // Author: Wilson Snyder <[email protected]>
// //
// Code available from: http://www.veripool.com/verilator // Code available from: http://www.veripool.com/verilator
// //
@@ -24,7 +24,7 @@
//********************************************************************** //**********************************************************************
//**** Version and host name //**** Version and host name
#define DTVERSION "Verilator 3.632 1/17/2007" #define DTVERSION "Verilator 3.653 8/1/2007"
//********************************************************************** //**********************************************************************
//**** Functions //**** Functions
+5 -1
View File
@@ -19,7 +19,7 @@
# #
###################################################################### ######################################################################
# DESCRIPTION: Edits flex output to get around Redhat 8.0 broken flex. # DESCRIPTION: Edits flex output to get around various broken flex issues.
foreach my $line (<STDIN>) { foreach my $line (<STDIN>) {
# Fix flex 2.5.4 namespace omission # Fix flex 2.5.4 namespace omission
@@ -28,5 +28,9 @@ foreach my $line (<STDIN>) {
$line =~ s!(\#define\s+yyFlexLexer\s+yyFlexLexer)!//flexfix: $1!g; $line =~ s!(\#define\s+yyFlexLexer\s+yyFlexLexer)!//flexfix: $1!g;
# Fix flex 2.5.1 yytext_ptr undef # Fix flex 2.5.1 yytext_ptr undef
$line =~ s!(\#undef\s+yytext_ptr)!//flexfix: $1!g; $line =~ s!(\#undef\s+yytext_ptr)!//flexfix: $1!g;
# Fix flex 2.5.4 and GCC 4.1.0 warn_unused_result
$line =~ s!\(void\) *fwrite\((.*)\)!if (fwrite($1)) {}!g;
# Fix flex 2.5.33 and GCC 4.1.2 "warning: comparison between signed and unsigned integer expressions" in YY_INPUT
$line =~ s!for \( n = 0; n < max_size && !for ( n = 0; ((size_t)n < (size_t)max_size) && !g;
print "$line"; print "$line";
} }
+577 -433
View File
File diff suppressed because it is too large Load Diff
+496 -309
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -34,6 +34,6 @@ ifeq ($(VM_TRACE),1)
endif endif
simx: sim_main.o $(SP_SRCS) $(VM_PREFIX)__ALL.a simx: sim_main.o $(SP_SRCS) $(VM_PREFIX)__ALL.a
$(CXX) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
sim_main.o: sim_main.cpp $(VM_PREFIX).h sim_main.o: sim_main.cpp $(VM_PREFIX).h
+2 -2
View File
@@ -43,7 +43,7 @@ endif
#Default compile, using normal make rules #Default compile, using normal make rules
#$(VM_PREFIX): $(SP_SRCS) $(VK_OBJS) #$(VM_PREFIX): $(SP_SRCS) $(VK_OBJS)
# $(CXX) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt # $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
#Our own compile rules; Faster compile, all in one file #Our own compile rules; Faster compile, all in one file
$(VM_PREFIX)__ALLboth.cpp: $(VK_CLASSES_CPP) $(VK_SUPPORT_CPP) $(VM_PREFIX)__ALLboth.cpp: $(VK_CLASSES_CPP) $(VK_SUPPORT_CPP)
@@ -54,5 +54,5 @@ $(VM_PREFIX)__ALLboth.o: $(VM_PREFIX)__ALLboth.cpp
ifneq ($(MAKE_MAIN),0) ifneq ($(MAKE_MAIN),0)
$(VM_PREFIX): $(VM_PREFIX)__ALLboth.o $(VM_PREFIX): $(VM_PREFIX)__ALLboth.o
$(CXX) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
endif endif
+32 -6
View File
@@ -32,8 +32,8 @@ use vars qw ($Debug %Vars $Driver $Fork);
$::Driver = 1; $::Driver = 1;
eval "use Parallel::Forker; \$Fork=Parallel::Forker->new();"; eval "use Parallel::Forker; \$Fork=Parallel::Forker->new(use_sig_child=>1);";
$Fork = Forker->new() if !$Fork; $Fork = Forker->new(use_sig_child=>1) if !$Fork;
$SIG{CHLD} = sub { $Fork->sig_child() if $Fork; }; $SIG{CHLD} = sub { $Fork->sig_child() if $Fork; };
$SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork; die "Quitting...\n"; }; $SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork; die "Quitting...\n"; };
@@ -197,13 +197,17 @@ sub new {
# VCS # VCS
vcs => 0, vcs => 0,
vcs_flags => [split(/\s+/,"+cli -I +define+vcs+1 -q +v2k")], vcs_flags => [split(/\s+/,"+cli -I +define+vcs+1 -q +v2k")],
vcs_flags2 => [], # Overridden in some sim files
# NC # NC
nc => 0, nc => 0,
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+nc=1 -q +assert +sv31a")], nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+nc=1 -q +assert +sv")],
nc_flags2 => [], # Overridden in some sim files
# Verilator # Verilator
'v3' => 0, 'v3' => 0,
verilator_flags => [split(/\s+/,"-cc")], verilator_flags => [split(/\s+/,"-cc")],
verilator_flags2 => [],
verilator_make_gcc => 1, verilator_make_gcc => 1,
verilated_debug => $Opt_Verilated_Debug,
stdout_filename => undef, # Redirect stdout stdout_filename => undef, # Redirect stdout
@_}; @_};
bless $self, $class; bless $self, $class;
@@ -289,8 +293,9 @@ sub compile {
$self->_make_top(); $self->_make_top();
$self->_run(logfile=>"obj_dir/".$self->{name}."_vcs_compile.log", $self->_run(logfile=>"obj_dir/".$self->{name}."_vcs_compile.log",
fails=>$param{fails}, fails=>$param{fails},
cmd=>["vcs", cmd=>[($ENV{VERILATOR_VCS}||"vcs"),
@{$param{vcs_flags}}, @{$param{vcs_flags}},
@{$param{vcs_flags2}},
@{$param{v_flags}}, @{$param{v_flags}},
@{$param{v_flags2}}, @{$param{v_flags2}},
$param{top_filename}, $param{top_filename},
@@ -302,8 +307,9 @@ sub compile {
$self->_make_top(); $self->_make_top();
$self->_run(logfile=>"obj_dir/".$self->{name}."_nc_compile.log", $self->_run(logfile=>"obj_dir/".$self->{name}."_nc_compile.log",
fails=>$param{fails}, fails=>$param{fails},
cmd=>["ncverilog", cmd=>[($ENV{VERILATOR_NCVERILOG}||"ncverilog"),
@{$param{nc_flags}}, @{$param{nc_flags}},
@{$param{nc_flags2}},
@{$param{v_flags}}, @{$param{v_flags}},
@{$param{v_flags2}}, @{$param{v_flags2}},
$param{top_filename}, $param{top_filename},
@@ -333,6 +339,7 @@ sub compile {
my @v3args = ("perl","../bin/verilator", my @v3args = ("perl","../bin/verilator",
"--prefix ".$self->{VM_PREFIX}, "--prefix ".$self->{VM_PREFIX},
@{$param{verilator_flags}}, @{$param{verilator_flags}},
@{$param{verilator_flags2}},
@{$param{v_flags}}, @{$param{v_flags}},
@{$param{v_flags2}}, @{$param{v_flags2}},
$param{top_filename}, $param{top_filename},
@@ -541,7 +548,8 @@ sub _make_main {
print $fh "int main(int argc, char **argv, char **env) {\n"; print $fh "int main(int argc, char **argv, char **env) {\n";
print $fh " double sim_time = 1000;\n"; print $fh " double sim_time = 1000;\n";
} }
print $fh " Verilated::debug(".($Opt_Verilated_Debug?1:0).");\n"; print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n";
print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset};
print $fh " topp = new $VM_PREFIX (\"TOP\");\n"; print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
my $set; my $set;
if ($self->sp) { if ($self->sp) {
@@ -841,6 +849,24 @@ Run using Verilator.
=back =back
=head1 ENVIRONMENT
=over 4
=item SYSTEMC
Root directory name of SystemC kit.
=item VERILATOR_NCVERILOG
Command to use to invoke ncverilog.
=item VERILATOR_VCS
Command to use to invoke VCS.
=back
=head1 SEE ALSO =head1 SEE ALSO
=head1 AUTHORS =head1 AUTHORS
+80 -41
View File
@@ -1,4 +1,4 @@
// $Id:$ // $Id$
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// Use this file as a template for submitting bugs, etc. // Use this file as a template for submitting bugs, etc.
@@ -7,57 +7,96 @@
// $finish // $finish
// on success, or $stop. // on success, or $stop.
// //
// The code as shown applies a random vector to the Test
// module, then calculates a CRC on the Test module's outputs.
//
// **If you do not wish for your code to be released to the public // **If you do not wish for your code to be released to the public
// please note it here** // please note it here, otherwise:**
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/ module t (/*AUTOARG*/
// Inputs // Inputs
clk clk
); );
input clk; input clk;
// Some inputs we'll set to random values integer cyc=0;
reg [31:0] in_a; reg [63:0] crc;
reg [31:0] in_b; reg [63:0] sum;
// Some arbitrary function for testing // Take CRC data and apply to testblock inputs
// We'll test below that for each random in_a and in_b, we get a good out_a. wire [31:0] in = crc[31:0];
wire [31:0] out_x = (in_a ^ in_b);
integer cyc; initial cyc=1; /*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [31:0] out; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.out (out[31:0]),
// Inputs
.clk (clk),
.in (in[31:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {32'h0, out};
// What checksum will we end up with
`define EXPECTED_SUM 64'h4afe43fb79d7b71e
// Test loop
always @ (posedge clk) begin always @ (posedge clk) begin
if (cyc!=0) begin `ifdef TEST_VERBOSE
cyc <= cyc + 1; $write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
$write("%d %x %x %x\n", cyc, in_a, in_b, out_x); `endif
if (cyc==1) begin cyc <= cyc + 1;
// Assign inputs randomly crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
in_a <= 32'h89a14fab; sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
in_b <= 32'h7ab512fa; if (cyc==0) begin
end // Setup
if (cyc==2) begin crc <= 64'h5aef0c8d_d70a4497;
in_a <= 32'hf4c11a42; end
in_b <= 32'h359967c6; else if (cyc<10) begin
// Verify output is correct sum <= 64'h0;
if (out_x != 32'hf3145d51) $stop; end
end else if (cyc<90) begin
if (cyc==3) begin end
in_a <= 32'h58dca151; else if (cyc==99) begin
in_b <= 32'hdc687b27; $write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (out_x != 32'hc1587d84) $stop; if (crc !== 64'hc77bb9b3784ea091) $stop;
end if (sum !== `EXPECTED_SUM) $stop;
if (cyc==4) begin $write("*-* All Finished *-*\n");
in_a <= 32'h09df0bbb; $finish;
in_b <= 32'h0d0e7231;
if (out_x != 32'h84b4da76) $stop;
end
if (cyc==5) begin
if (out_x != 32'h04d1798a) $stop;
end
if (cyc==9) begin
$write("*-* All Finished *-*\n");
$finish;
end
end end
end end
endmodule
module Test (/*AUTOARG*/
// Outputs
out,
// Inputs
clk, in
);
// Replace this module with the device under test.
//
// Change the code in the t module to apply values to the inputs and
// merge the output values into the result vector.
input clk;
input [31:0] in;
output [31:0] out;
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [31:0] out;
// End of automatics
always @(posedge clk) begin
out <= in;
end
endmodule endmodule
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
compile (
v_flags2 => [$Last_Self->{v3}?'--assert':($Last_Self->{nc}?'+assert':'')],
);
execute (
check_finished=>1,
);
ok(1);
1;
+48
View File
@@ -0,0 +1,48 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
reg toggle;
integer cyc; initial cyc=1;
wire [7:0] cyc_copy = cyc[7:0];
always @ (negedge clk) begin
AssertionFalse1: assert (cyc<100);
assert (!(cyc==5) || toggle);
// FIX cover {cyc==3 || cyc==4};
// FIX cover {cyc==9} report "DefaultClock,expect=1";
// FIX cover {(cyc==5)->toggle} report "ToggleLogIf,expect=1";
end
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
toggle <= !cyc[0];
if (cyc==9) begin
`ifdef FAILING_ASSERTIONS
assert (0) else $info;
assert (0) else $info("Info message");
assert (0) else $info("Info message, cyc=%d", cyc);
InWarningBlock: assert (0) else $warning("Warning....");
InErrorBlock: assert (0) else $error("Error....");
assert (0) else $fatal(1,"Fatal....");
`endif
end
if (cyc==10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_assert_basic.v");
compile (
v_flags2 => [$Last_Self->{v3}?'--assert --sp --coverage-user':''],
);
execute (
check_finished=>1,
);
#Needs work
print "-Info: NOT checking for coverage\n";
#file_grep ($Last_Self->{coverage_filename}, qr/t=>'psl_cover',o=>'cover',c=>2\);/);
#file_grep ($Last_Self->{coverage_filename}, qr/DefaultClock.*,c=>1\);/);
#file_grep ($Last_Self->{coverage_filename}, qr/ToggleLogIf.*,c=>9\);/);
ok(1);
1;
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_assert_basic.v");
compile (
v_flags2 => ['+define+FAILING_ASSERTIONS',
$Last_Self->{v3}?'--assert':($Last_Self->{nc}?'+assert':'')],
fails => $Last_Self->{nc},
);
execute (
fails => 1,
);
ok(1);
1;
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_assert_basic.v");
compile (
v_flags2 => [],
);
execute (
check_finished=>1,
);
ok(1);
1;
+3 -1
View File
@@ -1,4 +1,4 @@
// $Id:$ // $Id$
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
@@ -31,7 +31,9 @@ module t (/*AUTOARG*/
always @ (posedge clk) begin always @ (posedge clk) begin
if (cyc!=0) begin if (cyc!=0) begin
cyc <= cyc + 1; cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$write("%x/%x %x\n", q, qq, a); $write("%x/%x %x\n", q, qq, a);
`endif
if (cyc==1) begin if (cyc==1) begin
a = 256'hed388e646c843d35de489bab2413d77045e0eb7642b148537491f3da147e7f26; a = 256'hed388e646c843d35de489bab2413d77045e0eb7642b148537491f3da147e7f26;
end end
-1
View File
@@ -65,7 +65,6 @@ module t (/*AUTOARG*/
end end
else if (_mode==4) begin else if (_mode==4) begin
if (mode_d3r != 8'd1) $stop; if (mode_d3r != 8'd1) $stop;
$write("[%0t] t_blocking: Passed\n", $time);
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
compile (
verilator_flags2 => ["--compiler msvc"], # We have deep expressions we want to test
);
execute (
check_finished=>1,
);
ok(1);
1;
+342
View File
@@ -0,0 +1,342 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// Take CRC data and apply to testblock inputs
wire [33:0] in = crc[33:0];
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [31:0] code; // From test of Test.v
wire [4:0] len; // From test of Test.v
wire next; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.next (next),
.code (code[31:0]),
.len (len[4:0]),
// Inputs
.clk (clk),
.in (in[33:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {26'h0, next, len, code};
// What checksum will we end up with
`define EXPECTED_SUM 64'h5537fa30d49bf865
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
end
else if (cyc<10) begin
sum <= 64'h0;
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (/*AUTOARG*/
// Outputs
next, code, len,
// Inputs
clk, in
);
input clk;
input [33:0] in;
output next;
output [31:0] code;
output [4:0] len;
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [31:0] code;
reg [4:0] len;
reg next;
// End of automatics
/*
#!/usr/bin/perl -w
srand(5);
my @used;
pat:
for (my $pat=0; 1; ) {
last if $pat > 196;
my $len = int($pat / (6 + $pat/50)) + 4; $len=20 if $len>20;
my ($try, $val, $mask);
try:
for ($try=0; ; $try++) {
next pat if $try>50;
$val = 0;
for (my $bit=23; $bit>(23-$len); $bit--) {
my $b = int(rand()*2);
$val |= (1<<$bit) if $b;
}
$mask = (1<<(23-$len+1))-1;
for (my $testval = $val; $testval <= ($val + $mask); $testval ++) {
next try if $used[$testval];
}
last;
}
my $bits = "";
my $val2 = 0;
for (my $bit=23; $bit>(23-$len); $bit--) {
my $b = ($val & (1<<$bit));
$bits .= $b?'1':'0';
}
for (my $testval = $val; $testval <= ($val + $mask); $testval++) {
$used[$testval]= 1; #printf "U%08x\n", $testval;
}
if ($try<90) {
printf +(" 24'b%s: {next, len, code} = {in[%02d], 5'd%02d, 32'd%03d};\n"
,$bits.("?"x(24-$len)), 31-$len, $len, $pat);
$pat++;
}
}
*/
always @* begin
next = 1'b0;
code = 32'd0;
len = 5'b11111;
casez (in[31:8])
24'b1010????????????????????: {next, len, code} = {in[27], 5'd04, 32'd000};
24'b1100????????????????????: {next, len, code} = {in[27], 5'd04, 32'd001};
24'b0110????????????????????: {next, len, code} = {in[27], 5'd04, 32'd002};
24'b1001????????????????????: {next, len, code} = {in[27], 5'd04, 32'd003};
24'b1101????????????????????: {next, len, code} = {in[27], 5'd04, 32'd004};
24'b0011????????????????????: {next, len, code} = {in[27], 5'd04, 32'd005};
24'b0001????????????????????: {next, len, code} = {in[27], 5'd04, 32'd006};
24'b10001???????????????????: {next, len, code} = {in[26], 5'd05, 32'd007};
24'b01110???????????????????: {next, len, code} = {in[26], 5'd05, 32'd008};
24'b01000???????????????????: {next, len, code} = {in[26], 5'd05, 32'd009};
24'b00001???????????????????: {next, len, code} = {in[26], 5'd05, 32'd010};
24'b11100???????????????????: {next, len, code} = {in[26], 5'd05, 32'd011};
24'b01011???????????????????: {next, len, code} = {in[26], 5'd05, 32'd012};
24'b100001??????????????????: {next, len, code} = {in[25], 5'd06, 32'd013};
24'b111110??????????????????: {next, len, code} = {in[25], 5'd06, 32'd014};
24'b010010??????????????????: {next, len, code} = {in[25], 5'd06, 32'd015};
24'b001011??????????????????: {next, len, code} = {in[25], 5'd06, 32'd016};
24'b101110??????????????????: {next, len, code} = {in[25], 5'd06, 32'd017};
24'b111011??????????????????: {next, len, code} = {in[25], 5'd06, 32'd018};
24'b0111101?????????????????: {next, len, code} = {in[24], 5'd07, 32'd020};
24'b0010100?????????????????: {next, len, code} = {in[24], 5'd07, 32'd021};
24'b0111111?????????????????: {next, len, code} = {in[24], 5'd07, 32'd022};
24'b1011010?????????????????: {next, len, code} = {in[24], 5'd07, 32'd023};
24'b1000000?????????????????: {next, len, code} = {in[24], 5'd07, 32'd024};
24'b1011111?????????????????: {next, len, code} = {in[24], 5'd07, 32'd025};
24'b1110100?????????????????: {next, len, code} = {in[24], 5'd07, 32'd026};
24'b01111100????????????????: {next, len, code} = {in[23], 5'd08, 32'd027};
24'b00000110????????????????: {next, len, code} = {in[23], 5'd08, 32'd028};
24'b00000101????????????????: {next, len, code} = {in[23], 5'd08, 32'd029};
24'b01001100????????????????: {next, len, code} = {in[23], 5'd08, 32'd030};
24'b10110110????????????????: {next, len, code} = {in[23], 5'd08, 32'd031};
24'b00100110????????????????: {next, len, code} = {in[23], 5'd08, 32'd032};
24'b11110010????????????????: {next, len, code} = {in[23], 5'd08, 32'd033};
24'b010011101???????????????: {next, len, code} = {in[22], 5'd09, 32'd034};
24'b001000000???????????????: {next, len, code} = {in[22], 5'd09, 32'd035};
24'b010101111???????????????: {next, len, code} = {in[22], 5'd09, 32'd036};
24'b010101010???????????????: {next, len, code} = {in[22], 5'd09, 32'd037};
24'b010011011???????????????: {next, len, code} = {in[22], 5'd09, 32'd038};
24'b010100011???????????????: {next, len, code} = {in[22], 5'd09, 32'd039};
24'b010101000???????????????: {next, len, code} = {in[22], 5'd09, 32'd040};
24'b1111010101??????????????: {next, len, code} = {in[21], 5'd10, 32'd041};
24'b0010001000??????????????: {next, len, code} = {in[21], 5'd10, 32'd042};
24'b0101001101??????????????: {next, len, code} = {in[21], 5'd10, 32'd043};
24'b0010010100??????????????: {next, len, code} = {in[21], 5'd10, 32'd044};
24'b1011001110??????????????: {next, len, code} = {in[21], 5'd10, 32'd045};
24'b1111000011??????????????: {next, len, code} = {in[21], 5'd10, 32'd046};
24'b0101000000??????????????: {next, len, code} = {in[21], 5'd10, 32'd047};
24'b1111110000??????????????: {next, len, code} = {in[21], 5'd10, 32'd048};
24'b10110111010?????????????: {next, len, code} = {in[20], 5'd11, 32'd049};
24'b11110000011?????????????: {next, len, code} = {in[20], 5'd11, 32'd050};
24'b01001111011?????????????: {next, len, code} = {in[20], 5'd11, 32'd051};
24'b00101011011?????????????: {next, len, code} = {in[20], 5'd11, 32'd052};
24'b01010010100?????????????: {next, len, code} = {in[20], 5'd11, 32'd053};
24'b11110111100?????????????: {next, len, code} = {in[20], 5'd11, 32'd054};
24'b00100111001?????????????: {next, len, code} = {in[20], 5'd11, 32'd055};
24'b10110001010?????????????: {next, len, code} = {in[20], 5'd11, 32'd056};
24'b10000010000?????????????: {next, len, code} = {in[20], 5'd11, 32'd057};
24'b111111101100????????????: {next, len, code} = {in[19], 5'd12, 32'd058};
24'b100000111110????????????: {next, len, code} = {in[19], 5'd12, 32'd059};
24'b100000110010????????????: {next, len, code} = {in[19], 5'd12, 32'd060};
24'b100000111001????????????: {next, len, code} = {in[19], 5'd12, 32'd061};
24'b010100101111????????????: {next, len, code} = {in[19], 5'd12, 32'd062};
24'b001000001100????????????: {next, len, code} = {in[19], 5'd12, 32'd063};
24'b000001111111????????????: {next, len, code} = {in[19], 5'd12, 32'd064};
24'b011111010100????????????: {next, len, code} = {in[19], 5'd12, 32'd065};
24'b1110101111101???????????: {next, len, code} = {in[18], 5'd13, 32'd066};
24'b0100110101110???????????: {next, len, code} = {in[18], 5'd13, 32'd067};
24'b1111111011011???????????: {next, len, code} = {in[18], 5'd13, 32'd068};
24'b0101011011001???????????: {next, len, code} = {in[18], 5'd13, 32'd069};
24'b0010000101100???????????: {next, len, code} = {in[18], 5'd13, 32'd070};
24'b1111111101101???????????: {next, len, code} = {in[18], 5'd13, 32'd071};
24'b1011110010110???????????: {next, len, code} = {in[18], 5'd13, 32'd072};
24'b0101010111010???????????: {next, len, code} = {in[18], 5'd13, 32'd073};
24'b1111011010010???????????: {next, len, code} = {in[18], 5'd13, 32'd074};
24'b01010100100011??????????: {next, len, code} = {in[17], 5'd14, 32'd075};
24'b10110000110010??????????: {next, len, code} = {in[17], 5'd14, 32'd076};
24'b10111101001111??????????: {next, len, code} = {in[17], 5'd14, 32'd077};
24'b10110000010101??????????: {next, len, code} = {in[17], 5'd14, 32'd078};
24'b00101011001111??????????: {next, len, code} = {in[17], 5'd14, 32'd079};
24'b00100000101100??????????: {next, len, code} = {in[17], 5'd14, 32'd080};
24'b11111110010111??????????: {next, len, code} = {in[17], 5'd14, 32'd081};
24'b10110010100000??????????: {next, len, code} = {in[17], 5'd14, 32'd082};
24'b11101011101000??????????: {next, len, code} = {in[17], 5'd14, 32'd083};
24'b01010000011111??????????: {next, len, code} = {in[17], 5'd14, 32'd084};
24'b101111011001011?????????: {next, len, code} = {in[16], 5'd15, 32'd085};
24'b101111010001100?????????: {next, len, code} = {in[16], 5'd15, 32'd086};
24'b100000111100111?????????: {next, len, code} = {in[16], 5'd15, 32'd087};
24'b001010101011000?????????: {next, len, code} = {in[16], 5'd15, 32'd088};
24'b111111100100001?????????: {next, len, code} = {in[16], 5'd15, 32'd089};
24'b001001011000010?????????: {next, len, code} = {in[16], 5'd15, 32'd090};
24'b011110011001011?????????: {next, len, code} = {in[16], 5'd15, 32'd091};
24'b111111111111010?????????: {next, len, code} = {in[16], 5'd15, 32'd092};
24'b101111001010011?????????: {next, len, code} = {in[16], 5'd15, 32'd093};
24'b100000110000111?????????: {next, len, code} = {in[16], 5'd15, 32'd094};
24'b0010010000000101????????: {next, len, code} = {in[15], 5'd16, 32'd095};
24'b0010010010101001????????: {next, len, code} = {in[15], 5'd16, 32'd096};
24'b1111011010110010????????: {next, len, code} = {in[15], 5'd16, 32'd097};
24'b0010010001100100????????: {next, len, code} = {in[15], 5'd16, 32'd098};
24'b0101011101110100????????: {next, len, code} = {in[15], 5'd16, 32'd099};
24'b0101011010001111????????: {next, len, code} = {in[15], 5'd16, 32'd100};
24'b0010000110011111????????: {next, len, code} = {in[15], 5'd16, 32'd101};
24'b0101010010000101????????: {next, len, code} = {in[15], 5'd16, 32'd102};
24'b1110101011000000????????: {next, len, code} = {in[15], 5'd16, 32'd103};
24'b1111000000110010????????: {next, len, code} = {in[15], 5'd16, 32'd104};
24'b0111100010001101????????: {next, len, code} = {in[15], 5'd16, 32'd105};
24'b00100010110001100???????: {next, len, code} = {in[14], 5'd17, 32'd106};
24'b00100010101101010???????: {next, len, code} = {in[14], 5'd17, 32'd107};
24'b11111110111100000???????: {next, len, code} = {in[14], 5'd17, 32'd108};
24'b00100000111010000???????: {next, len, code} = {in[14], 5'd17, 32'd109};
24'b00100111011101001???????: {next, len, code} = {in[14], 5'd17, 32'd110};
24'b11111110111000011???????: {next, len, code} = {in[14], 5'd17, 32'd111};
24'b11110001101000100???????: {next, len, code} = {in[14], 5'd17, 32'd112};
24'b11101011101011101???????: {next, len, code} = {in[14], 5'd17, 32'd113};
24'b01010000100101011???????: {next, len, code} = {in[14], 5'd17, 32'd114};
24'b00100100110011001???????: {next, len, code} = {in[14], 5'd17, 32'd115};
24'b01001110010101000???????: {next, len, code} = {in[14], 5'd17, 32'd116};
24'b010011110101001000??????: {next, len, code} = {in[13], 5'd18, 32'd117};
24'b111010101110010010??????: {next, len, code} = {in[13], 5'd18, 32'd118};
24'b001001001001111000??????: {next, len, code} = {in[13], 5'd18, 32'd119};
24'b101111000110111101??????: {next, len, code} = {in[13], 5'd18, 32'd120};
24'b101101111010101001??????: {next, len, code} = {in[13], 5'd18, 32'd121};
24'b111101110010111110??????: {next, len, code} = {in[13], 5'd18, 32'd122};
24'b010100100011010000??????: {next, len, code} = {in[13], 5'd18, 32'd123};
24'b001001001111011001??????: {next, len, code} = {in[13], 5'd18, 32'd124};
24'b010100110010001001??????: {next, len, code} = {in[13], 5'd18, 32'd125};
24'b111010110000111000??????: {next, len, code} = {in[13], 5'd18, 32'd126};
24'b111010110011000101??????: {next, len, code} = {in[13], 5'd18, 32'd127};
24'b010100001000111001??????: {next, len, code} = {in[13], 5'd18, 32'd128};
24'b1000001011000110100?????: {next, len, code} = {in[12], 5'd19, 32'd129};
24'b0010010111001110110?????: {next, len, code} = {in[12], 5'd19, 32'd130};
24'b0101011001000001101?????: {next, len, code} = {in[12], 5'd19, 32'd131};
24'b0101000010010101011?????: {next, len, code} = {in[12], 5'd19, 32'd132};
24'b1111011111101001101?????: {next, len, code} = {in[12], 5'd19, 32'd133};
24'b1011001000101010110?????: {next, len, code} = {in[12], 5'd19, 32'd134};
24'b1011000001000100001?????: {next, len, code} = {in[12], 5'd19, 32'd135};
24'b1110101100010011001?????: {next, len, code} = {in[12], 5'd19, 32'd136};
24'b0010010111010111110?????: {next, len, code} = {in[12], 5'd19, 32'd137};
24'b0010010001100111100?????: {next, len, code} = {in[12], 5'd19, 32'd138};
24'b1011001011100000101?????: {next, len, code} = {in[12], 5'd19, 32'd139};
24'b1011000100010100101?????: {next, len, code} = {in[12], 5'd19, 32'd140};
24'b1111111001000111011?????: {next, len, code} = {in[12], 5'd19, 32'd141};
24'b00100010111101101101????: {next, len, code} = {in[11], 5'd20, 32'd142};
24'b10000010101010101101????: {next, len, code} = {in[11], 5'd20, 32'd143};
24'b10110010100101001101????: {next, len, code} = {in[11], 5'd20, 32'd144};
24'b01010110111100010000????: {next, len, code} = {in[11], 5'd20, 32'd145};
24'b10110111110011001001????: {next, len, code} = {in[11], 5'd20, 32'd146};
24'b11111101101100100101????: {next, len, code} = {in[11], 5'd20, 32'd147};
24'b10110000010100100001????: {next, len, code} = {in[11], 5'd20, 32'd148};
24'b10110010011010110110????: {next, len, code} = {in[11], 5'd20, 32'd149};
24'b01111001010000011000????: {next, len, code} = {in[11], 5'd20, 32'd150};
24'b11110110001011011011????: {next, len, code} = {in[11], 5'd20, 32'd151};
24'b01010000100100001011????: {next, len, code} = {in[11], 5'd20, 32'd152};
24'b10110001100101110111????: {next, len, code} = {in[11], 5'd20, 32'd153};
24'b10111100110111101000????: {next, len, code} = {in[11], 5'd20, 32'd154};
24'b01010001010111010000????: {next, len, code} = {in[11], 5'd20, 32'd155};
24'b01010100111110001110????: {next, len, code} = {in[11], 5'd20, 32'd156};
24'b11111110011001100111????: {next, len, code} = {in[11], 5'd20, 32'd157};
24'b11110111111101010001????: {next, len, code} = {in[11], 5'd20, 32'd158};
24'b10110000010111100000????: {next, len, code} = {in[11], 5'd20, 32'd159};
24'b01001111100001000101????: {next, len, code} = {in[11], 5'd20, 32'd160};
24'b01010010000111010110????: {next, len, code} = {in[11], 5'd20, 32'd161};
24'b11101010101011101111????: {next, len, code} = {in[11], 5'd20, 32'd162};
24'b11111110010011100011????: {next, len, code} = {in[11], 5'd20, 32'd163};
24'b01010111001111101111????: {next, len, code} = {in[11], 5'd20, 32'd164};
24'b10110001111111111101????: {next, len, code} = {in[11], 5'd20, 32'd165};
24'b10110001001100110000????: {next, len, code} = {in[11], 5'd20, 32'd166};
24'b11110100011000111101????: {next, len, code} = {in[11], 5'd20, 32'd167};
24'b00101011101110100011????: {next, len, code} = {in[11], 5'd20, 32'd168};
24'b01010000011011111110????: {next, len, code} = {in[11], 5'd20, 32'd169};
24'b00000111000010000010????: {next, len, code} = {in[11], 5'd20, 32'd170};
24'b00101010000011001000????: {next, len, code} = {in[11], 5'd20, 32'd171};
24'b01001110010100101110????: {next, len, code} = {in[11], 5'd20, 32'd172};
24'b11110000000010000000????: {next, len, code} = {in[11], 5'd20, 32'd173};
24'b01001101011001111001????: {next, len, code} = {in[11], 5'd20, 32'd174};
24'b11110111000111010101????: {next, len, code} = {in[11], 5'd20, 32'd175};
24'b01111001101001110110????: {next, len, code} = {in[11], 5'd20, 32'd176};
24'b11110000101011101111????: {next, len, code} = {in[11], 5'd20, 32'd177};
24'b00100100100110101010????: {next, len, code} = {in[11], 5'd20, 32'd178};
24'b11110001011011000011????: {next, len, code} = {in[11], 5'd20, 32'd179};
24'b01010111001000110011????: {next, len, code} = {in[11], 5'd20, 32'd180};
24'b01111000000100010101????: {next, len, code} = {in[11], 5'd20, 32'd181};
24'b00100101101011001101????: {next, len, code} = {in[11], 5'd20, 32'd182};
24'b10110010110000111001????: {next, len, code} = {in[11], 5'd20, 32'd183};
24'b10110000101010000011????: {next, len, code} = {in[11], 5'd20, 32'd184};
24'b00100100111110001101????: {next, len, code} = {in[11], 5'd20, 32'd185};
24'b01111001101001101011????: {next, len, code} = {in[11], 5'd20, 32'd186};
24'b01010001000000010001????: {next, len, code} = {in[11], 5'd20, 32'd187};
24'b11110101111111101110????: {next, len, code} = {in[11], 5'd20, 32'd188};
24'b10000010111110110011????: {next, len, code} = {in[11], 5'd20, 32'd189};
24'b00000100011110100111????: {next, len, code} = {in[11], 5'd20, 32'd190};
24'b11111101001111101100????: {next, len, code} = {in[11], 5'd20, 32'd191};
24'b00101011100011110000????: {next, len, code} = {in[11], 5'd20, 32'd192};
24'b00100100111001011001????: {next, len, code} = {in[11], 5'd20, 32'd193};
24'b10000010101000000100????: {next, len, code} = {in[11], 5'd20, 32'd194};
24'b11110001001000111100????: {next, len, code} = {in[11], 5'd20, 32'd195};
24'b10111100011010011001????: {next, len, code} = {in[11], 5'd20, 32'd196};
24'b000000??????????????????: begin
casez (in[33:32])
2'b1?: {next, len, code} = {1'b0, 5'd18, 32'd197};
2'b01: {next, len, code} = {1'b0, 5'd19, 32'd198};
2'b00: {next, len, code} = {1'b0, 5'd19, 32'd199};
default: ;
endcase
end
default: ;
endcase
end
endmodule
+2 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/perl #!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id:$ # $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition # DESCRIPTION: Verilator: Verilog Test driver/expect definition
# #
# Copyright 2003 by Wilson Snyder. This program is free software; you can # Copyright 2003 by Wilson Snyder. This program is free software; you can
@@ -8,6 +8,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# General Public License or the Perl Artistic License. # General Public License or the Perl Artistic License.
compile ( compile (
v_flags2 => ["--lint-only"],
fails=>1, fails=>1,
expect=> expect=>
'%Error: t/t_case_default_bad.v:\d+: Multiple default statements in case statement. '%Error: t/t_case_default_bad.v:\d+: Multiple default statements in case statement.
+1
View File
@@ -8,6 +8,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# General Public License or the Perl Artistic License. # General Public License or the Perl Artistic License.
compile ( compile (
v_flags2 => ["--lint-only"],
fails=>1, fails=>1,
expect=> expect=>
'%Error: t/t_case_genx_bad.v:\d+: Use of x/\? constant in generate case statement, \(no such thing as \'generate casez\'\) '%Error: t/t_case_genx_bad.v:\d+: Use of x/\? constant in generate case statement, \(no such thing as \'generate casez\'\)
+3 -1
View File
@@ -19,7 +19,9 @@ module t (/*AUTOARG*/
sub sub (.in(crc[23:0]), .out1(out1)); sub sub (.in(crc[23:0]), .out1(out1));
always @ (posedge clk) begin always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x sum=%x out=%x\n",$time, cyc, crc, sum, out1); $write("[%0t] cyc==%0d crc=%x sum=%x out=%x\n",$time, cyc, crc, sum, out1);
`endif
cyc <= cyc + 1; cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {63'h0,out1}; sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {63'h0,out1};
@@ -29,7 +31,7 @@ module t (/*AUTOARG*/
sum <= 64'h0; sum <= 64'h0;
end end
else if (cyc==90) begin else if (cyc==90) begin
if (sum != 64'h2e5cb972eb02b8a0) $stop; if (sum !== 64'h2e5cb972eb02b8a0) $stop;
end end
else if (cyc==91) begin else if (cyc==91) begin
end end
+4 -1
View File
@@ -30,7 +30,7 @@ module t (/*AUTOARG*/
sum <= 64'h0; sum <= 64'h0;
end end
else if (cyc==90) begin else if (cyc==90) begin
if (sum != 64'hf0afc2bfa78277c5) $stop; if (sum !== 64'hf0afc2bfa78277c5) $stop;
end end
else if (cyc==91) begin else if (cyc==91) begin
end end
@@ -60,6 +60,9 @@ module sub (/*AUTOARG*/
output reg [4:0] out2; output reg [4:0] out2;
always @* begin always @* begin
// Test empty cases
casez (in[0])
endcase
casez (in) casez (in)
24'b0000_0000_0000_0000_0000_0000 : {out1,out2} = {1'b0,5'h00}; 24'b0000_0000_0000_0000_0000_0000 : {out1,out2} = {1'b0,5'h00};
24'b????_????_????_????_????_???1 : {out1,out2} = {1'b1,5'h00}; 24'b????_????_????_????_????_???1 : {out1,out2} = {1'b1,5'h00};
+1
View File
@@ -8,6 +8,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# General Public License or the Perl Artistic License. # General Public License or the Perl Artistic License.
compile ( compile (
v_flags2 => ["--lint-only"],
fails=>1, fails=>1,
expect=> expect=>
'%Error: t/t_case_x_bad.v:\d+: Use of x/. constant in case statement, \(perhaps intended casex/casez\) '%Error: t/t_case_x_bad.v:\d+: Use of x/. constant in case statement, \(perhaps intended casex/casez\)
+4
View File
@@ -15,13 +15,17 @@ execute (
expect=>quotemeta( expect=>quotemeta(
'[0] In TOP.v: Hi '[0] In TOP.v: Hi
[0] In TOP.v.sub [0] In TOP.v.sub
[0] In TOP.v.sub.subblock
[0] In TOP.v.sub2 [0] In TOP.v.sub2
[0] In TOP.v.sub2.subblock2
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100 [0] %X=0c %D=12 %0X=c %0O=14 %B=001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100 [0] %x=0c %d=12 %0x=c %0o=14 %b=001100
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100 [0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 [0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %s=! %s= what! %s= hmmm!1234 [0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
*-* All Finished *-*
'), '),
); );
+15 -2
View File
@@ -33,6 +33,9 @@ module t;
$display("[%0t] %%s=%s %%s=%s %%s=%s", $time, $display("[%0t] %%s=%s %%s=%s %%s=%s", $time,
str2[7:0], str2, str3); str2[7:0], str2, str3);
$display("[%0t] %s%s%s", $time,
"hel", "lo, fr", "om a very long string. Percent %s are literally substituted in.");
// Str check // Str check
`ifndef nc // NC-Verilog 5.3 chokes on this test `ifndef nc // NC-Verilog 5.3 chokes on this test
if (str !== 32'h00_bf_11_0a) $stop; if (str !== 32'h00_bf_11_0a) $stop;
@@ -44,13 +47,23 @@ endmodule
module sub; module sub;
task write_m; task write_m;
$write("[%0t] In %m\n", $time); begin
$write("[%0t] In %m\n", $time);
begin : subblock
$write("[%0t] In %m\n", $time);
end
end
endtask endtask
endmodule endmodule
module sub2; module sub2;
// verilator no_inline_module // verilator no_inline_module
task write_m; task write_m;
$write("[%0t] In %m\n", $time); begin
$write("[%0t] In %m\n", $time);
begin : subblock2
$write("[%0t] In %m\n", $time);
end
end
endtask endtask
endmodule endmodule
+2 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/perl #!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id:$ # $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition # DESCRIPTION: Verilator: Verilog Test driver/expect definition
# #
# Copyright 2003 by Wilson Snyder. This program is free software; you can # Copyright 2003 by Wilson Snyder. This program is free software; you can
@@ -8,6 +8,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# General Public License or the Perl Artistic License. # General Public License or the Perl Artistic License.
compile ( compile (
v_flags2 => ["--lint-only"],
fails=>1, fails=>1,
expect=> expect=>
'%Error: t/t_display_bad.v:\d+: Missing arguments for \$display format '%Error: t/t_display_bad.v:\d+: Missing arguments for \$display format
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_display.v");
compile (
v_flags2 => [$Last_Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=>quotemeta(
'[0] In TOP.v: Hi
[0] In TOP.v.sub
[0] In TOP.v.sub.subblock
[0] In TOP.v.sub2
[0] In TOP.v.sub2.subblock2
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
*-* All Finished *-*
'),
);
ok(1);
1;
+6 -6
View File
@@ -13,12 +13,12 @@ compile (
execute ( execute (
check_finished=>1, check_finished=>1,
expect=> quotemeta( expect=> quotemeta(
'[0] %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228 '[0] lp %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228
[0] %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348 [0] ln %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348
[0] %x=000bbbbcccc %x=000bbbbcccc %o=00027356746314 %b=00000000010111011101110111100110011001100 %0d=3149647052 %d= 3149647052 [0] qp %x=001bbbbcccc %x=001bbbbcccc %o=00067356746314 %b=00000000110111011101110111100110011001100 %0d=7444614348 %d= 7444614348
[0] %x=100bbbbcccc %x=100bbbbcccc %o=20027356746314 %b=10000000010111011101110111100110011001100 %0d=-1096361980724 %d=-1096361980724 [0] qn %x=101bbbbcccc %x=101bbbbcccc %o=20067356746314 %b=10000000110111011101110111100110011001100 %0d=-1092067013428 %d=-1092067013428
[0] %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000 [0] wp %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000
[0] %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000 [0] wn %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000
'), '),
); );
+8 -8
View File
@@ -7,24 +7,24 @@
module t; module t;
reg signed [20:0] longp; initial longp = 21'shbbccc; reg signed [20:0] longp; initial longp = 21'shbbccc;
reg signed [20:0] longn; initial longn = 21'shbbccc; initial longn[20]=1'b1; reg signed [20:0] longn; initial longn = 21'shbbccc; initial longn[20]=1'b1;
reg signed [40:0] quadp; initial quadp = 41'shbbbb_cccc; reg signed [40:0] quadp; initial quadp = 41'sh1_bbbb_cccc;
reg signed [40:0] quadn; initial quadn = 41'shbbbb_cccc; initial quadn[40]=1'b1; reg signed [40:0] quadn; initial quadn = 41'sh1_bbbb_cccc; initial quadn[40]=1'b1;
reg signed [80:0] widep; initial widep = 81'shbc_1234_5678_1234_5678; reg signed [80:0] widep; initial widep = 81'shbc_1234_5678_1234_5678;
reg signed [80:0] widen; initial widen = 81'shbc_1234_5678_1234_5678; initial widen[40]=1'b1; reg signed [80:0] widen; initial widen = 81'shbc_1234_5678_1234_5678; initial widen[40]=1'b1;
initial begin initial begin
// Display formatting // Display formatting
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] lp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
longp, longp, longp, longp, longp, longp); longp, longp, longp, longp, longp, longp);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] ln %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
longn, longn, longn, longn, longn, longn); longn, longn, longn, longn, longn, longn);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] qp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
quadp, quadp, quadp, quadp, quadp, quadp); quadp, quadp, quadp, quadp, quadp, quadp);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] qn %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
quadn, quadn, quadn, quadn, quadn, quadn); quadn, quadn, quadn, quadn, quadn, quadn);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b", $time, $display("[%0t] wp %%x=%x %%x=%x %%o=%o %%b=%b", $time,
widep, widep, widep, widep); widep, widep, widep, widep);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b", $time, $display("[%0t] wn %%x=%x %%x=%x %%o=%o %%b=%b", $time,
widen, widen, widen, widen); widen, widen, widen, widen);
$display; $display;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_display_signed.v");
compile (
v_flags2 => [$Last_Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] lp %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228
[0] ln %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348
[0] qp %x=001bbbbcccc %x=001bbbbcccc %o=00067356746314 %b=00000000110111011101110111100110011001100 %0d=7444614348 %d= 7444614348
[0] qn %x=101bbbbcccc %x=101bbbbcccc %o=20067356746314 %b=10000000110111011101110111100110011001100 %0d=-1092067013428 %d=-1092067013428
[0] wp %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000
[0] wn %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000
'),
);
ok(1);
1;

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