Compare commits

...
24 Commits
Author SHA1 Message Date
Wilson Snyder f23203dc96 Make __Inlines.h file so we can build VL_CONST_W_#X funcs automatically
git-svn-id: file://localhost/svn/verilator/trunk/verilator@974 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-11-30 22:38:21 +00:00
Wilson Snyder a94f1c779b Spelling fixes
git-svn-id: file://localhost/svn/verilator/trunk/verilator@973 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-11-30 22:12:53 +00:00
Wilson Snyder 6412aff82d Version bump, commentary
git-svn-id: file://localhost/svn/verilator/trunk/verilator@970 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-11-27 16:52:19 +00:00
Wilson Snyder 99bc1f92c9 Declare lex %tokens so user doesn't see yP_UGLYNAMES.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@969 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-11-05 21:38:20 +00:00
Wilson Snyder 891edad53a Fixed generate for loops with constant zero conditions.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@968 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-11-05 14:09:22 +00:00
Wilson Snyder 98e35b02ad Leak repairs and node leak detection
git-svn-id: file://localhost/svn/verilator/trunk/verilator@967 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-11-02 11:23:03 +00:00
Wilson Snyder 8075372675 Add -Wno-lint
git-svn-id: file://localhost/svn/verilator/trunk/verilator@966 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-31 21:17:23 +00:00
Wilson Snyder 10e34ca48e Support "#delay <statement>;" with associated STMTDLY warning.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@965 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-31 20:29:07 +00:00
Wilson Snyder 329808afff Misc updates to match Verilog-Perl
git-svn-id: file://localhost/svn/verilator/trunk/verilator@964 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-31 20:11:59 +00:00
Wilson Snyder 7fc3e6c168 Fix missing CAST required above some CONSTs
git-svn-id: file://localhost/svn/verilator/trunk/verilator@963 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-31 19:22:26 +00:00
Wilson Snyder 199b32709c Fix div by zero in constant propagation
git-svn-id: file://localhost/svn/verilator/trunk/verilator@962 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-30 22:58:47 +00:00
Wilson Snyder 1775da5f43 Track verilog-perl: Add static keyword; track IEEE BNF
git-svn-id: file://localhost/svn/verilator/trunk/verilator@961 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-26 14:58:26 +00:00
Wilson Snyder 45c202f78f Match Verilog-Perl operator names
git-svn-id: file://localhost/svn/verilator/trunk/verilator@960 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-23 20:54:29 +00:00
Wilson Snyder a77b58dba9 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@957 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-18 16:32:16 +00:00
Wilson Snyder c300ab6dd9 Match up with Verilog-Perl: add specify operators
git-svn-id: file://localhost/svn/verilator/trunk/verilator@956 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-10-18 16:29:19 +00:00
Wilson Snyder 9ac0f1accb Fix parsing system functions with empty parens
git-svn-id: file://localhost/svn/verilator/trunk/verilator@955 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-09-17 17:54:02 +00:00
Wilson Snyder 7990e5d4b1 Fix parsing module #(parameter x,y) declarations.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@954 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-09-11 13:35:02 +00:00
Wilson Snyder fb2cb3c49d Don't exit early if many warnings but no errors are found. [Stan Mayer]
git-svn-id: file://localhost/svn/verilator/trunk/verilator@953 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-08-23 13:21:58 +00:00
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
79 changed files with 1481 additions and 453 deletions
+107 -76
View File
@@ -3,6 +3,37 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.655 ***
**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman]
In such cases, a new {prefix}__Inlines.h file will be built and included.
* Verilator 3.655 11/27/2007
*** Support "#delay <statement>;" with associated STMTDLY warning.
**** Fixed generate for loops with constant zero conditions. [Rodney Sinclair]
**** Fixed divide-by-zero errors in constant propagator. [Rodney Sinclair]
**** Fixed wrong result with obscure signed-shift underneath a "? :".
**** Fixed many internal memory leaks, and added leak detector.
* Verilator 3.654 10/18/2007
**** Don't exit early if many warnings but no errors are found. [Stan Mayer]
**** Fixed parsing module #(parameter x,y) declarations. [Oleg Rodionov]
**** Fixed parsing system functions with empty parens. [Oleg Rodionov]
* Verilator 3.653 8/1/2007
**** Support SystemVerilog ==? and !=? operators.
**** Fixed SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
* Verilator 3.652 6/21/2007
**** Report as many warning types as possible before exiting.
@@ -13,7 +44,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Optimize constant $display arguments.
**** Fix Preprocessor dropping some `line directives. [Mark Nodine]
**** Fixed Preprocessor dropping some `line directives. [Mark Nodine]
* Verilator 3.651 5/22/2007
@@ -48,11 +79,11 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add USER_CPPFLAGS and USER_LDFLAGS to Makefiles. [Gerald Williams]
**** Fix compile errors under Windows MINGW compiler. [Gerald Williams]
**** Fixed compile errors under Windows MINGW compiler. [Gerald Williams]
**** Fix dotted bit reference to local memory. [Eugene Weber]
**** Fixed dotted bit reference to local memory. [Eugene Weber]
**** Fix 3.640 `verilog forcing IEEE 1364-1995 only. [David Hewson]
**** Fixed 3.640 `verilog forcing IEEE 1364-1995 only. [David Hewson]
* Verilator 3.640 3/12/2007
@@ -64,13 +95,13 @@ indicates the contributor was also the author of the fix; Thanks!
**** Try all +libext's in the exact order given. [Michael Shinkarovsky]
**** Fix elimination of public signals assigned to constants. [Eugene Weber]
**** Fixed elimination of public signals assigned to constants. [Eugene Weber]
**** Fix internal error when public for loop has empty body. [David Addison]
**** Fixed internal error when public for loop has empty body. [David Addison]
**** Fix "Loops detected" assertion when model exceeds 4GB. [David Hewson]
**** Fixed "Loops detected" assertion when model exceeds 4GB. [David Hewson]
**** Fix display %m names inside named blocks.
**** Fixed display %m names inside named blocks.
* Verilator 3.633 2/7/2007
@@ -78,11 +109,11 @@ indicates the contributor was also the author of the fix; Thanks!
*** With VL_DEBUG, show wires causing convergence errors. [Mike Shinkarovsky]
**** Fix isolate_assignments when many signals per always. [Mike Shinkarovsky]
**** Fixed isolate_assignments when many signals per always. [Mike Shinkarovsky]
**** Fix isolate_assignments across task/func temporaries. [Mike Shinkarovsky]
**** Fixed isolate_assignments across task/func temporaries. [Mike Shinkarovsky]
**** Fix $display's with array select followed by wide AND. [David Hewson]
**** Fixed $display's with array select followed by wide AND. [David Hewson]
* Verilator 3.632 1/17/2007
@@ -93,11 +124,11 @@ indicates the contributor was also the author of the fix; Thanks!
** Support standard NAME[#] for cells created by arraying or generate for.
This replaces the non-standard name__# syntax used in earlier versions.
**** Fix again dotted references into generate cells. [David Hewson]
**** Fixed again dotted references into generate cells. [David Hewson]
Verilator no longer accepts duplicated variables inside unique
generate blocks as this is illegal according to the specification.
**** Fix $readmem* with filenames < 8 characters. [Emerson Suguimoto]
**** Fixed $readmem* with filenames < 8 characters. [Emerson Suguimoto]
* Verilator 3.630 12/19/2006
@@ -109,21 +140,21 @@ indicates the contributor was also the author of the fix; Thanks!
*** Reduce depth of priority encoded case statements. [Eugene Weber]
**** Fix dotted references inside generated cells. [David Hewson]
**** Fixed dotted references inside generated cells. [David Hewson]
**** Fix missed split optimization points underneath other re-split blocks.
**** Fixed missed split optimization points underneath other re-split blocks.
* Verilator 3.623 12/05/2006
*** Add --output-split-cfuncs for accelerating GCC compile. [Eugene Weber]
**** Fix $signed mis-extending when input has a WIDTH violation. [Eugene Weber]
**** Fixed $signed mis-extending when input has a WIDTH violation. [Eugene Weber]
**** Add M32 make variable to support -m32 compiles. [Eugene Weber]
* Verilator 3.622 10/17/2006 Stable
**** Fix --skip-identical without --debug, broken in 3.621. [Andy Meier]
**** Fixed --skip-identical without --debug, broken in 3.621. [Andy Meier]
* Verilator 3.621 10/11/2006 Beta
@@ -133,11 +164,11 @@ indicates the contributor was also the author of the fix; Thanks!
**** Remove .vpp intermediate files when not under --debug.
**** Fix link error when using --exe with --trace. [Eugene Weber]
**** Fixed link error when using --exe with --trace. [Eugene Weber]
**** Fix mis-optimization of wide concats with constants.
**** Fixed mis-optimization of wide concats with constants.
**** Fix core dump on printing error when not under --debug. [Allan Cochrane]
**** Fixed core dump on printing error when not under --debug. [Allan Cochrane]
* Verilator 3.620 10/04/2006 Stable
@@ -152,9 +183,9 @@ indicates the contributor was also the author of the fix; Thanks!
**** Optimize additional boolean identities (a|a = a, etc.)
**** Fix coredump when dotted cross-ref inside task call. [Eugene Weber]
**** Fixed coredump when dotted cross-ref inside task call. [Eugene Weber]
**** Fix dotted variables in always sensitivity lists. [Allan Cochrane]
**** Fixed dotted variables in always sensitivity lists. [Allan Cochrane]
* Verilator 3.610 09/20/2006 Stable
@@ -164,13 +195,13 @@ indicates the contributor was also the author of the fix; Thanks!
**** Removed coverage request variable; see Coverage limitations in docs.
**** Fix DOS carriage returns in multiline defines. [Ralf Karge]
**** Fixed DOS carriage returns in multiline defines. [Ralf Karge]
**** Fix printf format warnings on 64-bit linux.
**** Fixed printf format warnings on 64-bit linux.
* Verilator 3.602 09/11/2006 Stable
**** Fix function references under top inlined module. [David Hewson]
**** Fixed function references under top inlined module. [David Hewson]
* Verilator 3.601 09/06/2006 Beta
@@ -183,15 +214,15 @@ indicates the contributor was also the author of the fix; Thanks!
*** Changed how internal functions are invoked to reduce aliasing.
Useful when using GCC's -O2 or -fstrict-aliasing, to gain another ~4%.
**** Fix memory leak when destroying modules. [John Stroebel]
**** Fixed memory leak when destroying modules. [John Stroebel]
**** Fix coredump when unused modules have unused cells. [David Hewson]
**** Fixed coredump when unused modules have unused cells. [David Hewson]
**** Fix 3.600 internal error with arrayed instances. [David Hewson]
**** Fixed 3.600 internal error with arrayed instances. [David Hewson]
**** Fix 3.600 internal error with non-unrolled function loops. [David Hewson]
**** Fixed 3.600 internal error with non-unrolled function loops. [David Hewson]
**** Fix $display %m name not matching Verilog name inside SystemC modules.
**** Fixed $display %m name not matching Verilog name inside SystemC modules.
**** Declare optimized lookup tables as 'static', to reduce D-Cache miss rate.
@@ -201,17 +232,17 @@ indicates the contributor was also the author of the fix; Thanks!
**** Lint for x's in generate case statements.
**** Fix line numbers being off by one when first file starts with newline.
**** Fixed line numbers being off by one when first file starts with newline.
**** Fix naming of generate for blocks to prevent non-inline name conflict.
**** Fixed naming of generate for blocks to prevent non-inline name conflict.
**** Fix redundant statements remaining after table optimization.
**** Fixed redundant statements remaining after table optimization.
* Verilator 3.542 08/11/2006 Stable
**** Fix extraneous UNSIGNED warning when comparing genvars. [David Hewson]
**** Fixed extraneous UNSIGNED warning when comparing genvars. [David Hewson]
**** Fix extra white space in $display %c. [by David Addison]
**** Fixed extra white space in $display %c. [by David Addison]
**** vl_finish and vl_fatal now print via VL_PRINTF rather then cerr/cout.
@@ -219,15 +250,15 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.541 07/05/2006 Beta
*** Fix "// verilator lint_on" not re-enabling warnings. [David Hewson]
*** Fixed "// verilator lint_on" not re-enabling warnings. [David Hewson]
*** Fix 3.540's multiple memory assignments to same block. [David Hewson]
*** Fixed 3.540's multiple memory assignments to same block. [David Hewson]
**** Add warning on changeDetect to arrayed structures. [David Hewson]
**** Fix non-zero start number for arrayed instantiations. [Jae Hossell]
**** Fixed non-zero start number for arrayed instantiations. [Jae Hossell]
**** Fix GCC 4.0 header file warnings.
**** Fixed GCC 4.0 header file warnings.
* Verilator 3.540 06/27/2006 Beta
@@ -235,27 +266,27 @@ indicates the contributor was also the author of the fix; Thanks!
**** Optimize delayed assignments to memories inside loops, ~0-5% faster.
**** Fix mis-width warning on bit selects of memories. [David Hewson]
**** Fixed mis-width warning on bit selects of memories. [David Hewson]
**** Fix mis-width warning on dead generate-if branches. [Jae Hossell]
**** Fixed mis-width warning on dead generate-if branches. [Jae Hossell]
* Verilator 3.533 06/05/2006 Stable
*** Add PDF user manual, verilator.pdf.
**** Fix delayed bit-selected arrayed assignments. [David Hewson]
**** Fixed delayed bit-selected arrayed assignments. [David Hewson]
**** Fix execution path to Perl. [Shanshan Xu]
**** Fixed execution path to Perl. [Shanshan Xu]
**** Fix Bison compile errors in verilog.y. [by Ben Jackson]
**** Fixed Bison compile errors in verilog.y. [by Ben Jackson]
* Verilator 3.531 05/10/2006 Stable
*** Support $c routines which return 64 bit values.
**** Fix `include `DEFINE.
**** Fixed `include `DEFINE.
**** Fix Verilator core dump when have empty public function. [David.Hewson]
**** Fixed Verilator core dump when have empty public function. [David.Hewson]
* Verilator 3.530 04/24/2006 Stable
@@ -264,11 +295,11 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.523 03/06/2006 Stable
**** Fix error line numbers being off due to multi-line defines. [Mat Zeno]
**** Fixed error line numbers being off due to multi-line defines. [Mat Zeno]
**** Fix GCC sign extending (uint64_t)(a<b). [David Hewson]
**** Fixed GCC sign extending (uint64_t)(a<b). [David Hewson]
**** Fix `systemc_imp_header "undefined macro" error.
**** Fixed `systemc_imp_header "undefined macro" error.
* Verilator 3.522 02/23/2006 Beta
@@ -280,7 +311,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Added SystemVerilog 'x,'z,'0,'1, and new string literals.
**** Fix public module's parent still getting inlined.
**** Fixed public module's parent still getting inlined.
* Verilator 3.520 01/14/2006 Stable
@@ -293,28 +324,28 @@ indicates the contributor was also the author of the fix; Thanks!
This adds a small ~2% performance penalty if traces are compiled in,
but not turned on. For best non-tracing performance, do not use --trace.
**** Fix $'s in specify delays causing bad PLI errors. [Mat Zeno]
**** Fixed $'s in specify delays causing bad PLI errors. [Mat Zeno]
**** Fix public functions not setting up proper symbol table. [Mat Zeno]
**** Fixed public functions not setting up proper symbol table. [Mat Zeno]
**** Fix genvars generating trace compile errors. [Mat Zeno]
**** Fixed genvars generating trace compile errors. [Mat Zeno]
**** Fix VL_MULS_WWW compile error with MSVC++. [Wim Michiels]
**** Fixed VL_MULS_WWW compile error with MSVC++. [Wim Michiels]
* Verilator 3.502 11/30/2005 Stable
**** Fix local non-IO variables in public functions and tasks.
**** Fixed local non-IO variables in public functions and tasks.
**** Fix bad lifetime optimization when same signal is assigned multiple
**** Fixed bad lifetime optimization when same signal is assigned multiple
times in both branch of a if. [Danny Ding]
* Verilator 3.501 11/16/2005 Stable
*** Add --profile-cfuncs for correlating profiles back to Verilog.
**** Fix functions where regs are declared before inputs. [Danny Ding]
**** Fixed functions where regs are declared before inputs. [Danny Ding]
**** Fix bad deep expressions with bit-selects and rotate. [Prabhat Gupta]
**** Fixed bad deep expressions with bit-selects and rotate. [Prabhat Gupta]
* Verilator 3.500 10/30/2005 Stable
@@ -328,15 +359,15 @@ indicates the contributor was also the author of the fix; Thanks!
** With --assert, generate assertions for synthesis parallel_case and full_case.
**** Fix generate if's with empty if/else blocks. [Mat Zeno]
**** Fixed generate if's with empty if/else blocks. [Mat Zeno]
**** Fix generate for cell instantiations with same name. [Mat Zeno]
**** Fixed generate for cell instantiations with same name. [Mat Zeno]
* Verilator 3.481 10/12/2005 Stable
*** Add /*verilator tracing_on/off*/ for waveform control.
**** Fix split optimization reordering $display statements.
**** Fixed split optimization reordering $display statements.
* Verilator 3.480 9/27/2005 Beta
@@ -361,9 +392,9 @@ indicates the contributor was also the author of the fix; Thanks!
**** Add GCC branch prediction hints on generated if statements.
**** Fix bad simulation when same function called twice in same expression.
**** Fixed bad simulation when same function called twice in same expression.
**** Fix preprocessor substitution of quoted parameterized defines.
**** Fixed preprocessor substitution of quoted parameterized defines.
* Verilator 3.464 8/24/2005 Stable
@@ -371,7 +402,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add --stats option to dump design statistics.
**** Fix core dump with clock inversion optimizations.
**** Fixed core dump with clock inversion optimizations.
* Verilator 3.463 8/5/2005 Stable
@@ -379,15 +410,15 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.462 8/3/2005 Stable
*** Fix reordering of delayed assignments to same memory index. [Wim Michiels]
*** Fixed reordering of delayed assignments to same memory index. [Wim Michiels]
**** Fix compile error with Flex 2.5.1. [Jens Arm]
**** Fixed compile error with Flex 2.5.1. [Jens Arm]
**** Fix multiply-instantiated public tasks generating non-compilable code.
**** Fixed multiply-instantiated public tasks generating non-compilable code.
* Verilator 3.461 7/28/2005 Beta
**** Fix compile error with older versions of bison. [Jeff Dutton]
**** Fixed compile error with older versions of bison. [Jeff Dutton]
* Verilator 3.460 7/27/2005 Beta
@@ -400,13 +431,13 @@ indicates the contributor was also the author of the fix; Thanks!
*** When issuing unoptimizable warning, show an example path.
**** Fix false warning when a clock is constant.
**** Fixed false warning when a clock is constant.
**** Fix X/Z in decimal numbers. [Wim Michiels]
**** Fixed X/Z in decimal numbers. [Wim Michiels]
**** Fix genvar statements in non-named generate blocks.
**** Fixed genvar statements in non-named generate blocks.
**** Fix core dump when missing newline in `define. [David van der bokke]
**** Fixed core dump when missing newline in `define. [David van der bokke]
**** Internal tree dumps now indicate edit number that changed the node.
@@ -423,7 +454,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add support for SystemVerilog keywords $bits, $countones, $isunknown,
$onehot, $onehot0, always_comb, always_ff, always_latch, finish.
**** Fix "=== 1'bx" to always be false, instead of random.
**** Fixed "=== 1'bx" to always be false, instead of random.
* Verilator 3.440 6/28/2005 Stable
@@ -431,7 +462,7 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.431 6/24/2005 Stable
*** Fix selection bugs introduced in 3.430 beta.
*** Fixed selection bugs introduced in 3.430 beta.
* Verilator 3.430 6/22/2005 Beta
@@ -1063,7 +1094,7 @@ of input ports exists for tracing.
** [Versions 0 to 1.8 were by Paul Wasson]
**** Fix single bit in concat from instance output incorrect offset bug.
**** Fixed single bit in concat from instance output incorrect offset bug.
* Verilator 1.7 5/20/1996
@@ -1078,7 +1109,7 @@ of input ports exists for tracing.
*** Pass structure pointer into translated code,
so multiple instances can use same functions.
**** Fix static value concat on casex items.
**** Fixed static value concat on casex items.
* Verilator 1.1 3/30/1995
+1 -1
View File
@@ -4,7 +4,7 @@
#
# 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
#
+7
View File
@@ -25,6 +25,7 @@ Features:
Coverage
Points should be per-scope like everything else rather then per-module
Expression coverage (see notes)
Constant functions for widths, etc, IE "input [log2(PARAM):0] xx;"
More Verilog 2001 Support
(* *) Attributes (just ignore -- preprocessor?)
Real numbers (NEVER)
@@ -103,6 +104,12 @@ Performance:
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)
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
+58 -21
View File
@@ -411,7 +411,7 @@ change the SystemC modules instantiated.
=item --inline-mult I<value>
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 than
this number of operations would result, the module is not inlined. Larger
values, or a value <= 1 will inline everything, will lead to longer compile
times, but potentially faster runtimes. This setting is ignored for very
@@ -566,6 +566,17 @@ example C<-Werror-NOUNOPTFLAT>.
Disable the specified warning message.
=item -Wno-lint
Disable all lint related warning messages. This is equivelent to
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CMPCONST
-Wno-IMPLICIT -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-VARHIDDEN
-Wno-WIDTH".
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
received from third parties.
=item -x-assign 0
=item -x-assign 1
@@ -827,6 +838,7 @@ For -sp mode, instead of .cpp and .h it creates:
In certain optimization modes, it also creates:
{prefix}__Inlines.h // Inline support functions
{prefix}__Slow.cpp // Constructors and infrequent routines
{prefix}__Syms.cpp // Global symbol table C++
{prefix}__Syms.h // Global symbol table header
@@ -983,7 +995,7 @@ To support this, none of the files that Verilator produces will reference
any configure generated build-system specific files, such as config.h
(which is renamed in Verilator to config_build.h to reduce confusion.) The
disadvantage of this approach is that include/verilatedos.h must
self-detect the requirements of the target system, rather then using
self-detect the requirements of the target system, rather than using
configure.
The target system may also require edits to the Makefiles, the simple
@@ -1010,12 +1022,14 @@ 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 subset,
Verilator implements the full SystemVerilog 1800-2005 preprocessor,
including function call-like preprocessor defines.
Verilator supports $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 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.
@@ -1096,7 +1110,7 @@ call C++ functions from your Verilog code.
String arguments will be put directly into the output C++ code. Expression
arguments will have the code to evaluate the expression inserted. Thus to
call a C++ function, $c("func(",a,")") will result in 'func(a)' in the
output C++ code. For input arguments, rather then hard-coding variable
output C++ code. For input arguments, rather than hard-coding variable
names in the string $c("func(a)"), instead pass the variable as an
expression $c("func(",a,")"). This will allow the call to work inside
Verilog functions where the variable is flattened out, and also enable
@@ -1463,7 +1477,7 @@ When initializing an array, you need to use non-delayed assignments. This
is done in the interest of speed; if delayed assignments were used, the
simulator would have to copy large arrays every cycle. (In smaller loops,
loop unrolling allows the delayed assignment to work, though it's a bit
slower then a non-delayed assignment.) Here's an example
slower than a non-delayed assignment.) Here's an example
always @ (posedge clk)
if (~reset_l) begin
@@ -1550,7 +1564,7 @@ MCDs, which includes the mode parameter to $fopen being mandatory.
Verilator will convert the integer used to hold the file descriptor into a
internal FILE*. To prevent core dumps due to mis-use, and because integers
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 than an integer. The define `verilator_file_descriptor in
verilated.v can be used to hide this difference.
=item $fullskew, $hold, $nochange, $period, $recovery, $recrem, $removal,
@@ -1716,6 +1730,16 @@ 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 STMTDLY
Warns that you have a statement with a delayed time in front of it, for
example:
#100 $finish;
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item TASKNSVAR
Error when a call to a task or function has a output from that task tied to
@@ -1847,7 +1871,7 @@ correctly.
Warns that based on width rules of Verilog, two operands have different
widths. Verilator generally can intuit the common usages of widths, and
you shouldn't need to disable this message like you do with most lint
programs. Generally other then simple mistakes, you have two solutions:
programs. Generally other than simple mistakes, you have two solutions:
If it's a constant 0 that's 32 bits or less, simply leave it
unwidthed. Verilator considers zero to be any width needed.
@@ -1916,13 +1940,13 @@ Visual C++ Version 7 or newer, but this is not tested by the author.
=item Can you provide binaries?
At this time I'd prefer to get patches out quickly then have to generate
At this time I'd prefer to get patches out quickly than have to generate
myriad binaries for many different OS flavors. People have generally
requested binaries when they are having problems with their C++
compiler. Alas, binaries won't help this, as in the end a fully working C++
compiler is required to compile the output of Verilator.
=item How can it be faster then (name-the-simulator)?
=item How can it be faster than (name-the-simulator)?
Generally, the implied part of the question is "... with all of their
manpower they can put into it."
@@ -1948,16 +1972,16 @@ 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 needs more memory than 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
order to optimize it. If it takes more than 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.
and may use more than 4GB, but about 1GB is the maximum typically needed.
=item How do I generate waveforms (traces) in C++?
See the next question for SystemC mode.
See the next question for tracing in SystemC mode.
Add the --trace switch to Verilator, and make sure the SystemPerl package
is installed. SystemC itself does not need to be installed for C++ only
@@ -1966,8 +1990,10 @@ the SystemPerl kit and point the SYSTEMPERL environment variable to the
untarred directory.
In your top level C code, call Verilated::traceEverOn(true). Then create a
SpTraceVcdC object. For an example, see the call to SpTraceVcdC in the
test_c/sc_main.cpp file of the distribution.
SpTraceVcdC object, and in your main loop call "trace_object->dump(time)"
every time step, and finally call "trace_object->close()". For an example,
see the call to SpTraceVcdC in the test_c/sim_main.cpp file of the
distribution.
You also need to compile SpTraceVcdC.cpp and add it to your link. This is
done for you if using the Verilator --exe flag.
@@ -1999,6 +2025,17 @@ the "verilator" define for you, so just wrap the code in a ifndef region:
Something_Verilator_Dislikes;
`endif
=item Why do I get "unexpected `do'" or "unexpected `bit'" errors?
Do, bit, ref, and other words are now SystemVerilog keywords. You should
change your code to not use them to insure it works with newer tools.
Alternatively, surround them by the Verilog 2005/SystemVerilog
begin_keywords pragma to indicate Verilog 2001 code.
`begin_keywords "1364-2001"
integer bit; initial bit = 1;
`end_keywords
=item How do I prevent my assertions from firing during reset?
Call Verilated::assertOn(false) before you first call the model, then turn
@@ -2059,7 +2096,7 @@ bit long longs that fits the width of the signal. Generally, you can use
just uint32_t's for 1 to 32 bits, or uint64_t for 1 to 64 bits, and the
compiler will properly up-convert smaller entities.
Signals wider then 64 bits are stored as an array of 32-bit uint32_t's.
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
Thus to read bits 31:0, access signal[0], and for bits 63:32, access
signal[1]. Unused bits (for example bit numbers 65-96 of a 65 bit vector)
will always be zero. if you change the value you must make sure to pack
@@ -2150,8 +2187,8 @@ scratch in C++. This added many optimizations, yielding about a 2-5x
performance gain.
Currently, various language features and performance enhancements are added
as the need arises. Verilator is now about 2x faster then in 2002, and is
faster then many popular commercial simulators.
as the need arises. Verilator is now about 2x faster than in 2002, and is
faster than many popular commercial simulators.
=head1 CONTRIBUTORS
+24 -87
View File
@@ -210,9 +210,9 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
// Base macros
/// Return true if data[bit] set
#define VL_BITISSET_I(data,bit) (data & (1UL<<VL_BITBIT_I(bit)))
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (1UL<<VL_BITBIT_I(bit)))
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
/// Create two 32-bit words from quadword
#define VL_SET_WQ(decl,data) { decl[0]=(data); decl[1]=((data)>>VL_WORDSIZE); }
@@ -225,13 +225,13 @@ static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input)
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - 1UL))
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1)))
#define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1)))
#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits,lhs)))
// Sign bit extended up to MSB, doesn't include unsigned portion
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) { return (-((lhs)&(1UL<<(lbits-1)))); }
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
// Debugging prints
@@ -304,15 +304,15 @@ static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp,WDataInP lwp){
// EMIT_RULE: VL_ASSIGNBIT: rclean=clean;
static inline void VL_ASSIGNBIT_II(int, int bit, CData& lhsr, IData rhs) {
lhsr = ((lhsr & ~(1UL<<VL_BITBIT_I(bit)))
lhsr = ((lhsr & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| (rhs<<VL_BITBIT_I(bit)));
}
static inline void VL_ASSIGNBIT_II(int, int bit, SData& lhsr, IData rhs) {
lhsr = ((lhsr & ~(1UL<<VL_BITBIT_I(bit)))
lhsr = ((lhsr & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| (rhs<<VL_BITBIT_I(bit)));
}
static inline void VL_ASSIGNBIT_II(int, int bit, IData& lhsr, IData rhs) {
lhsr = ((lhsr & ~(1UL<<VL_BITBIT_I(bit)))
lhsr = ((lhsr & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
| (rhs<<VL_BITBIT_I(bit)));
}
static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) {
@@ -321,25 +321,25 @@ static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) {
}
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) {
IData orig = owp[VL_BITWORD_I(bit)];
owp[VL_BITWORD_I(bit)] = (orig & ~(1UL<<VL_BITBIT_I(bit))
owp[VL_BITWORD_I(bit)] = (orig & ~(VL_UL(1)<<VL_BITBIT_I(bit))
| (rhs<<VL_BITBIT_I(bit)));
}
// Alternative form that is an instruction faster when rhs is constant one.
static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) {
lhsr = (lhsr | (1UL<<VL_BITBIT_I(bit)));
lhsr = (lhsr | (VL_UL(1)<<VL_BITBIT_I(bit)));
}
static inline void VL_ASSIGNBIT_IO(int, int bit, SData& lhsr, IData) {
lhsr = (lhsr | (1UL<<VL_BITBIT_I(bit)));
lhsr = (lhsr | (VL_UL(1)<<VL_BITBIT_I(bit)));
}
static inline void VL_ASSIGNBIT_IO(int, int bit, IData& lhsr, IData) {
lhsr = (lhsr | (1UL<<VL_BITBIT_I(bit)));
lhsr = (lhsr | (VL_UL(1)<<VL_BITBIT_I(bit)));
}
static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) {
lhsr = (lhsr | (VL_ULL(1)<<VL_BITBIT_Q(bit)));
}
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
IData orig = owp[VL_BITWORD_I(bit)];
owp[VL_BITWORD_I(bit)] = (orig | (1UL<<VL_BITBIT_I(bit)));
owp[VL_BITWORD_I(bit)] = (orig | (VL_UL(1)<<VL_BITBIT_I(bit)));
}
//===================================================================
@@ -1164,7 +1164,7 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
int word = VL_BITWORD_I(rd);
if ((int)rd>lbits) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
// We return all 1's as that's more likely to find bugs (?) then 0's.
// We return all 1's as that's more likely to find bugs (?) than 0's.
} else {
return (lwp[word]>>VL_BITBIT_I(rd));
}
@@ -1288,123 +1288,60 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
// VL_CONST_W_#X(int obits, WDataOutP owp, IData data0, .... IData data(#-1))
// Sets wide vector words to specified constant words, zeros upper data.
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
#define I IData
#define _END(obits,wordsSet) \
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
return o
#define VL_HAVE_CONST_W_1X
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
I d0) {
o[0]=d0;
_END(obits,1); }
#define VL_HAVE_CONST_W_2X
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
I d1,I d0) {
o[0]=d0; o[1]=d1;
_END(obits,2); }
#define VL_HAVE_CONST_W_3X
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2;
_END(obits,3); }
#define VL_HAVE_CONST_W_4X
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
_END(obits,4); }
#define VL_HAVE_CONST_W_5X
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
_END(obits,5); }
#define VL_HAVE_CONST_W_6X
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
_END(obits,6); }
#define VL_HAVE_CONST_W_7X
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
_END(obits,7); }
#define VL_HAVE_CONST_W_8X
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
_END(obits,8); }
#define VL_HAVE_CONST_W_9X
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8;
_END(obits,9); }
static inline WDataOutP VL_CONST_W_10X(int obits, WDataOutP o,
I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9;
_END(obits,10); }
static inline WDataOutP VL_CONST_W_11X(int obits, WDataOutP o,
I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10;
_END(obits,11); }
static inline WDataOutP VL_CONST_W_12X(int obits, WDataOutP o,
I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11;
_END(obits,12); }
static inline WDataOutP VL_CONST_W_16X(int obits, WDataOutP o,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
_END(obits,16); }
static inline WDataOutP VL_CONST_W_17X(int obits, WDataOutP o,
I d16,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
o[16]=d16;
_END(obits,17); }
static inline WDataOutP VL_CONST_W_18X(int obits, WDataOutP o,
I d17,I d16,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
o[16]=d16; o[17]=d17;
_END(obits,18); }
static inline WDataOutP VL_CONST_W_19X(int obits, WDataOutP o,
I d18,I d17,I d16,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
o[16]=d16; o[17]=d17; o[18]=d18;
_END(obits,19); }
static inline WDataOutP VL_CONST_W_20X(int obits, WDataOutP o,
I d19,I d18,I d17,I d16,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
o[16]=d16; o[17]=d17; o[18]=d18; o[19]=d19;
_END(obits,20); }
static inline WDataOutP VL_CONST_W_24X(int obits, WDataOutP o,
I d23,I d22,I d21,I d20,I d19,I d18,I d17,I d16,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
o[16]=d16; o[17]=d17; o[18]=d18; o[19]=d19; o[20]=d20; o[21]=d21; o[22]=d22; o[23]=d23;
_END(obits,24); }
static inline WDataOutP VL_CONST_W_28X(int obits, WDataOutP o,
I d27,I d26,I d25,I d24,
I d23,I d22,I d21,I d20,I d19,I d18,I d17,I d16,
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
o[16]=d16; o[17]=d17; o[18]=d18; o[19]=d19; o[20]=d20; o[21]=d21; o[22]=d22; o[23]=d23;
o[24]=d24; o[25]=d25; o[26]=d26; o[27]=d27;
_END(obits,28); }
#undef _END
#undef I
+5 -2
View File
@@ -46,8 +46,8 @@
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
# define VL_ATTR_NORETURN ///< Function does not ever return
# define VL_ATTR_UNUSED ///< Function that may be never used
# 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_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
#endif
@@ -68,6 +68,9 @@
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
#endif
// This is not necessarily the same as #UL, depending on what the IData typedef is.
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
//=========================================================================
// Basic integer types
+1
View File
@@ -121,6 +121,7 @@ RAW_OBJS = \
V3DepthBlock.o \
V3Descope.o \
V3EmitC.o \
V3EmitCInlines.o \
V3EmitCSyms.o \
V3EmitMk.o \
V3EmitV.o \
+21 -2
View File
@@ -134,6 +134,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
// Called on all major tree changers.
// Only for use for those really nasty bugs relating to internals
// Note this may be null.
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<endl;
//if (debug()) {
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
@@ -458,7 +459,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
if (linkerp->m_iterpp) {
// If we're iterating over a next() link, we need to follow links off the
// NEW node. Thus we pass iteration information via a pointer in the node.
// This adds a unfortunate 4 bytes to every AstNode, but is faster then passing
// This adds a unfortunate 4 bytes to every AstNode, but is faster than passing
// across every function.
// If anyone has a cleaner way, I'd be grateful.
*(linkerp->m_iterpp) = newp;
@@ -586,11 +587,29 @@ void AstNode::deleteTree() {
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
if (!this) return;
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
this->debugTreeChange("-delete: ", __LINE__, true);
this->debugTreeChange("-delTree: ", __LINE__, true);
// MUST be depth first!
deleteTreeIter();
}
//======================================================================
// Memory checks
#ifdef VL_LEAK_CHECKS
void* AstNode::operator new(size_t size) {
AstNode* objp = static_cast<AstNode*>(::operator new(size));
V3Broken::addNewed(objp);
return objp;
}
void AstNode::operator delete(void* objp, size_t size) {
if (!objp) return;
AstNode* nodep = static_cast<AstNode*>(objp);
V3Broken::deleted(nodep);
::operator delete(objp);
}
#endif
//======================================================================
// Iterators
+4
View File
@@ -538,6 +538,10 @@ public:
// CONSTRUCTORS
virtual ~AstNode();
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
static void operator delete(void* obj, size_t size);
#endif
// CONSTANT ACCESSORS
static int instrCountBranch() { return 4; } ///< Instruction cycles to branch
+33
View File
@@ -2606,6 +2606,39 @@ struct AstNeqCase : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
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 {
// If you're looking for {#{}}, see AstReplicate
AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
+1 -1
View File
@@ -21,7 +21,7 @@
// BRANCH TRANSFORMATIONS:
// At each IF/(IF else).
// Count underneath $display/$stop statements.
// If more on if then else, this branch is unlikely, or vice-versa.
// If more on if than else, this branch is unlikely, or vice-versa.
//
//*************************************************************************
+102 -16
View File
@@ -32,7 +32,7 @@
#include <stdarg.h>
#include <unistd.h>
#include <algorithm>
#include <set>
#include <map>
#include "V3Global.h"
#include "V3Broken.h"
@@ -45,19 +45,100 @@ class BrokenTable : public AstNVisitor {
private:
// MEMBERS
// For each node, we keep if it exists or not.
typedef set<const AstNode*> NodeSet;
static NodeSet s_nodes; // Set of all nodes that exist
typedef map<const AstNode*,int> NodeMap;
static NodeMap s_nodes; // Set of all nodes that exist
// BITMASK
static const int FLAG_ALLOCATED = 0x01; // new() and not delete()ed
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
static const int FLAG_LEAKED = 0x08; // Known to have been leaked
public:
// METHODS
static void add(const AstNode* nodep) {
s_nodes.insert(nodep);
static void deleted(const AstNode* nodep) {
// Called by operator delete on any node - only if VL_LEAK_CHECKS
if (debug()) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
}
if (iter!=s_nodes.end()) s_nodes.erase(iter);
}
static bool exists(const AstNode* nodep) {
NodeSet::iterator iter = s_nodes.find(nodep);
return (iter != s_nodes.end());
static void addNewed(const AstNode* nodep) {
// Called by operator new on any node - only if VL_LEAK_CHECKS
if (debug()) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
}
if (iter == s_nodes.end()) {
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
}
}
static void clear() {
static void addInTree(AstNode* nodep, bool linkable) {
#ifndef VL_LEAK_CHECKS
if (!linkable) return; // save some time, else the map will get huge!
#endif
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) {
#ifdef VL_LEAK_CHECKS
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
#endif
} else {
if (!(iter->second & FLAG_ALLOCATED)) {
#ifdef VL_LEAK_CHECKS
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
#endif
}
if (iter->second & FLAG_IN_TREE) {
nodep->v3fatalSrc("AstNode is already in tree at another location\n");
}
}
int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0);
if (iter == s_nodes.end()) {
s_nodes.insert(make_pair(nodep,or_flags));
} else {
iter->second |= or_flags;
}
}
static bool okIfLinkedTo(const AstNode* nodep) {
// Someone has a pointer to this node. Is it kosher?
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) return false;
#ifdef VL_LEAK_CHECKS
if (!(iter->second & FLAG_ALLOCATED)) return false;
#endif
if (!(iter->second & FLAG_IN_TREE)) return false;
if (!(iter->second & FLAG_LINKABLE)) return false;
return true;
}
static void prepForTree() {
#ifndef VL_LEAK_CHECKS
s_nodes.clear();
#endif
for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) {
it->second &= ~FLAG_IN_TREE;
it->second &= ~FLAG_LINKABLE;
}
}
static void doneWithTree() {
for (int backs=0; backs<2; backs++) { // Those with backp() are probably under one leaking without
for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) {
if ((it->second & FLAG_ALLOCATED)
&& !(it->second & FLAG_IN_TREE)
&& !(it->second & FLAG_LEAKED)
&& (it->first->backp() ? backs==1 : backs==0)) {
// Use only AstNode::dump instead of the virtual one, as there
// may be varp() and other cross links that are bad.
if (debug()) {
cout<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
((AstNode*)(it->first))->AstNode::dump(cout);
cout<<endl;
V3Error::incErrors();
}
it->second |= FLAG_LEAKED;
}
}
}
}
public:
// CONSTUCTORS
@@ -65,11 +146,11 @@ public:
virtual ~BrokenTable() {}
};
BrokenTable::NodeSet BrokenTable::s_nodes;
BrokenTable::NodeMap BrokenTable::s_nodes;
bool AstNode::brokeExists() const {
// Called by node->broken() routines to do table lookup
return BrokenTable::exists(this);
return BrokenTable::okIfLinkedTo(this);
}
//######################################################################
@@ -82,9 +163,7 @@ private:
// // so userp and friends may not be used
// VISITORS
virtual void visit(AstNode* nodep, AstNUser*) {
if (nodep->maybePointedTo()) {
BrokenTable::add(nodep);
}
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
nodep->iterateChildren(*this);
}
public:
@@ -127,8 +206,15 @@ public:
void V3Broken::brokenAll(AstNetlist* nodep) {
//UINFO(9,__FUNCTION__<<": "<<endl);
BrokenTable::clear();
BrokenTable::prepForTree();
BrokenMarkVisitor mvisitor (nodep);
BrokenCheckVisitor cvisitor (nodep);
BrokenTable::clear();
BrokenTable::doneWithTree();
}
void V3Broken::addNewed(AstNode* nodep) {
BrokenTable::addNewed(nodep);
}
void V3Broken::deleted(AstNode* nodep) {
BrokenTable::deleted(nodep);
}
+2
View File
@@ -31,6 +31,8 @@
class V3Broken {
public:
static void brokenAll(AstNetlist* nodep);
static void addNewed(AstNode* nodep);
static void deleted(AstNode* nodep);
};
#endif // Guard
+9 -3
View File
@@ -218,7 +218,10 @@ private:
a++, b++) {
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
}
if (same) return tree0p;
if (same) {
tree1p->deleteTree(); tree1p=NULL;
return tree0p;
}
// Must have differing logic, so make a selection
@@ -245,8 +248,7 @@ private:
// CASEx(cexpr,....
// -> tree of IF(msb, IF(msb-1, 11, 10)
// IF(msb-1, 01, 00))
AstNode* cexprp = nodep->exprp();
cexprp->unlinkFrBack();
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
if (debug()>=9) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
@@ -264,6 +266,8 @@ private:
if (ifrootp) nodep->replaceWith(ifrootp);
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
cexprp->deleteTree(); cexprp=NULL;
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
}
@@ -304,6 +308,7 @@ private:
and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
} else {
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
and1p = cexprp->cloneTree(false);
@@ -320,6 +325,7 @@ private:
itemp->condsp(ifexprp);
}
}
cexprp->deleteTree(); cexprp=NULL;
if (!hadDefault) {
// If there was no default, add a empty one, this greatly simplifies below code
// and constant propagation will just eliminate it for us later.
+20 -1
View File
@@ -60,6 +60,7 @@ class CastVisitor : public AstNVisitor {
private:
// NODE STATE
// Entire netlist:
// AstNode::user() // bool. Indicates node is of known size
// STATE
//int debug() { return 9; }
@@ -76,6 +77,7 @@ private:
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
//
insureLower32Cast(castp);
nodep->user(1); // Now must be of known size
}
int castSize (AstNode* nodep) {
if (nodep->isQuad()) return VL_QUADSIZE;
@@ -84,7 +86,8 @@ private:
else return VL_WORDSIZE;
}
void insureCast(AstNode* nodep) {
if (castSize(nodep->backp()) != castSize(nodep)) {
if (castSize(nodep->backp()) != castSize(nodep)
|| !nodep->user()) {
insertCast(nodep, castSize(nodep->backp()));
}
}
@@ -102,15 +105,21 @@ private:
// VISITORS
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->user(nodep->lhsp()->user());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
}
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->user(nodep->lhsp()->user()
| nodep->rhsp()->user());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
}
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->user(nodep->lhsp()->user()
| nodep->rhsp()->user()
| nodep->thsp()->user());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
@@ -118,9 +127,11 @@ private:
virtual void visit(AstCast* nodep, AstNUser*) {
nodep->iterateChildren(*this);
insureLower32Cast(nodep);
nodep->user(1);
}
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->user(nodep->lhsp()->user());
if (nodep->lhsp()->widthMin()==1) {
// We want to avoid a GCC "converting of negative value" warning
// from our expansion of
@@ -140,6 +151,13 @@ private:
// CData x=3; out = (QData)(x<<30);
insertCast (nodep, castSize(nodep));
}
nodep->user(1);
}
virtual void visit(AstConst* nodep, AstNUser*) {
// Constants are of unknown size if smaller than 33 bits, becase
// we're too lazy to wrap every constant in the universe in
// ((IData)#).
nodep->user(nodep->isQuad() || nodep->isWide());
}
// NOPs
@@ -154,6 +172,7 @@ private:
public:
// CONSTUCTORS
CastVisitor(AstNetlist* nodep) {
AstNode::userClearTree();
nodep->accept(*this);
}
virtual ~CastVisitor() {}
+17 -4
View File
@@ -384,6 +384,8 @@ private:
int shift1 = shift1p->castConst()->asInt(); if (lhsp->castShiftR()) shift1=-shift1;
int shift2 = shift2p->castConst()->asInt(); if (nodep->castShiftR()) shift2=-shift2;
int newshift = shift1+shift2;
shift1p->deleteTree(); shift1p=NULL;
shift2p->deleteTree(); shift1p=NULL;
AstNode* newp;
V3Number mask1 (nodep->fileline(), nodep->width());
V3Number ones (nodep->fileline(), nodep->width());
@@ -524,7 +526,8 @@ private:
if (debug()>=9) asn1p->dumpTree(cout," _new: ");
if (debug()>=9) asn2p->dumpTree(cout," _new: ");
// Cleanup
nodep->unlinkFrBack()->deleteTree();
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
conp->deleteTree(); conp=NULL;
// Further reduce, either node may have more reductions.
return true;
}
@@ -637,6 +640,7 @@ private:
// If bp was a concat, then we have this exact same form again!
// Recurse rather then calling node->iterate to prevent 2^n recursion!
if (operandConcatMove(abConcp)) moveConcat(abConcp);
bcConcp->deleteTree(); bcConcp=NULL;
} else {
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
@@ -647,6 +651,7 @@ private:
nodep->lhsp(ap);
nodep->rhsp(bcConcp);
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
abConcp->deleteTree(); abConcp=NULL;
}
}
@@ -677,6 +682,8 @@ private:
if (lsb1p->castConst() && lsb2p->castConst()) {
newlsbp = new AstConst(lsb1p->fileline(),
lsb1p->castConst()->asInt() + lsb2p->castConst()->asInt());
lsb1p->deleteTree(); lsb1p=NULL;
lsb2p->deleteTree(); lsb2p=NULL;
} else {
// Width is important, we need the width of the fromp's
// expression, not the potentially smaller lsb1p's width
@@ -860,7 +867,7 @@ private:
new AstAssign(nodep->fileline(),
varrefp, exprp));
m_modp->addStmtp(newinitp);
nodep->unlinkFrBack(); nodep=NULL;
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
// Set the initial value right in the variable so we can constant propagate
AstNode* initvaluep = exprp->cloneTree(false);
varrefp->varp()->initp(initvaluep);
@@ -1016,7 +1023,7 @@ private:
// Below lines are magic expressions processed by astgen
// "AstNODETYPE { # bracket not paren
// $accessor_name, ...
// # ,, gets replaced with a , rather then &&
// # ,, gets replaced with a , rather than &&
// }" # bracket not paren
// ,"function to call"
// or ,"AstREPLACEMENT_TYPE{ $accessor }"
@@ -1110,6 +1117,10 @@ private:
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","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()}");
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
@@ -1151,6 +1162,7 @@ private:
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
@@ -1161,6 +1173,7 @@ private:
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
///=== Verilog operators
@@ -1191,7 +1204,7 @@ private:
TREEOPV("AstRedXor{$lhsp->castExtend()}", "AstRedXor{$lhsp->castExtend()->lhsp()}");
TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)");
TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)");
// Binary AND/OR is faster then logical and/or (usually)
// Binary AND/OR is faster than logical and/or (usually)
TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1}", "AstAnd{$lhsp,$rhsp}");
TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1}", "AstOr{$lhsp,$rhsp}");
TREEOPV("AstLogNot{$lhsp.width1}", "AstNot{$lhsp}");
+12 -13
View File
@@ -110,18 +110,6 @@ private:
}
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) {
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
AstRange* rangep = NULL;
if (width==0) {
rangep = new AstRange(oldvarscp->fileline(),
oldvarscp->varp()->msb(),
oldvarscp->varp()->lsb());
} else if (width==1) {
rangep = NULL;
} else {
rangep = new AstRange(oldvarscp->fileline(),
width-1, 0);
}
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
AstVar* varp;
AstModule* addmodp = oldvarscp->scopep()->modp();
@@ -131,6 +119,17 @@ private:
// Created module's AstVar earlier under some other scope
varp = iter->second;
} else {
AstRange* rangep = NULL;
if (width==0) {
rangep = new AstRange(oldvarscp->fileline(),
oldvarscp->varp()->msb(),
oldvarscp->varp()->lsb());
} else if (width==1) {
rangep = NULL;
} else {
rangep = new AstRange(oldvarscp->fileline(),
width-1, 0);
}
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, rangep);
if (width==0) varp->widthSignedFrom(oldvarscp);
addmodp->addStmtp(varp);
@@ -226,7 +225,7 @@ private:
if (nodep->user5p()) {
// Simplistic optimization. If the previous statement in same scope was also a =>,
// then we told this nodep->user5 we can use its Vdlyvset rather then making a new one.
// then we told this nodep->user5 we can use its Vdlyvset rather than making a new one.
// This is good for code like:
// for (i=0; i<5; i++) vector[i] <= something;
sharedVset = true;
+5 -2
View File
@@ -254,7 +254,7 @@ public:
virtual void visit(AstReadMem* nodep, AstNUser*) {
puts("VL_READMEM_");
emitIQW(nodep->filenamep());
puts(" ("); // We take a void* rather then emitIQW(nodep->memp());
puts(" ("); // We take a void* rather than emitIQW(nodep->memp());
puts(nodep->isHex()?"true":"false");
putbs(",");
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
@@ -1214,7 +1214,7 @@ void EmitCImp::emitConfigureImp(AstModule* modp) {
void EmitCImp::emitCoverageImp(AstModule* modp) {
if (m_coverIds.size()) {
puts("\n// Coverage\n");
// Rather then putting out SP_COVER_INSERT calls directly, we do it via this function
// Rather than putting out SP_COVER_INSERT calls directly, we do it via this function
// This gets around gcc slowness constructing all of the template arguments
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(SpZeroed<uint32_t>* countp, const char* filename, int lineno, int column,\n");
puts( "const char* hier, const char* type, const char* comment) {\n");
@@ -1428,6 +1428,9 @@ void EmitCImp::emitInt(AstModule* modp) {
if (v3Global.opt.coverage()) {
puts("#include \"SpCoverage.h\"\n");
}
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
puts("#include \""+topClassName()+"__Inlines.h\"\n");
}
// Declare foreign instances up front to make C++ happy
puts("class "+symClassName()+";\n");
+1
View File
@@ -31,6 +31,7 @@
class V3EmitC {
public:
static void emitc();
static void emitcInlines();
static void emitcSyms();
static void emitcTrace();
};
+126
View File
@@ -0,0 +1,126 @@
// $Id$
//*************************************************************************
// DESCRIPTION: Verilator: Emit C++ for tree
//
// 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.
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <math.h>
#include <map>
#include <vector>
#include "V3Global.h"
#include "V3EmitC.h"
#include "V3EmitCBase.h"
#include "V3Stats.h"
#define EMITCINLINES_NUM_CONSTW 10 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_9X is last)
//######################################################################
class EmitCInlines : EmitCBaseVisitor {
// STATE
vector<V3Double0> m_wordWidths; // What sizes are used?
// METHODS
void emitInt();
// VISITORS
virtual void visit(AstVar* nodep, AstNUser*) {
// All wide constants load into variables, so we can just hunt for them
if (nodep->widthWords() >= EMITCINLINES_NUM_CONSTW ) {
if (int(m_wordWidths.size()) <= nodep->widthWords()) {
m_wordWidths.resize(nodep->widthWords()+5);
}
++ m_wordWidths.at(nodep->widthWords());
v3Global.needHInlines(true);
}
}
// NOPs
virtual void visit(AstNodeStmt*, AstNUser*) {}
// Default
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
//---------------------------------------
// ACCESSORS
public:
EmitCInlines(AstNetlist* nodep) {
nodep->accept(*this);
if (v3Global.needHInlines()) {
emitInt();
}
}
};
void EmitCInlines::emitInt() {
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Inlines.h";
newCFile(filename, false/*slow*/, false/*source*/);
V3OutCFile hf (filename);
m_ofp = &hf;
ofp()->putsHeader();
puts("#ifndef _"+topClassName()+"__Inlines_H_\n");
puts("#define _"+topClassName()+"__Inlines_H_\n");
puts("\n");
puts("#include \"verilated.h\"\n");
puts("\n//======================\n\n");
for (unsigned words=0; words<m_wordWidths.size(); words++) {
if (m_wordWidths.at(words)) {
puts("#ifndef VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
puts("# define VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
puts("static inline WDataOutP VL_CONST_W_"+cvtToStr(words)+"X(int obits, WDataOutP o\n");
puts("\t");
for (int i=words-1; i>=0; --i) {
puts(",IData d"+cvtToStr(i));
if (i && (i % 8 == 0)) puts("\n\t");
}
puts(") {\n");
puts(" ");
for (int i=words-1; i>=0; --i) {
puts(" o["+cvtToStr(i)+"]=d"+cvtToStr(i)+";");
if (i && (i % 8 == 0)) puts("\n ");
}
puts("\n");
puts(" for(int i="+cvtToStr(words)+";i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0;\n");
puts(" return o;\n");
puts("}\n");
puts("#endif\n");
puts("\n");
}
}
puts("//======================\n\n");
puts("#endif /*guard*/\n");
}
//######################################################################
// EmitC class functions
void V3EmitC::emitcInlines() {
UINFO(2,__FUNCTION__<<": "<<endl);
EmitCInlines syms (v3Global.rootp());
}
+1 -1
View File
@@ -138,7 +138,7 @@ public:
of.puts("\n# Link rules...\n");
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n");
of.puts("\t$(LINK) $(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");
}
+51 -5
View File
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <set>
#include "V3Error.h"
#ifndef _V3ERROR_NO_GLOBAL_
# include "V3Ast.h"
@@ -101,9 +102,16 @@ bool FileLine::warnOff(const string& msg, bool flag) {
}
}
void FileLine::warnLintOff(bool flag) {
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
V3ErrorCode code = (V3ErrorCode)codei;
if (code.lintError()) warnOff(code, flag);
}
}
FileLine* FileLine::copyOrSameFileLine() {
// Return this, or a copy of this
// There are often more then one token per line, thus we use the
// There are often more than one token per line, thus we use the
// same pointer as long as we're on the same line.
static FileLine* lastNewp = NULL;
if (lastNewp && *lastNewp == *this) {
@@ -163,6 +171,46 @@ void FileLine::v3errorEnd(ostringstream& str) {
V3Error::v3errorEnd(str);
}
}
#ifdef VL_LEAK_CHECKS
typedef set<FileLine*> FileLineCheckSet;
FileLineCheckSet fileLineLeakChecks;
void* FileLine::operator new(size_t size) {
FileLine* objp = static_cast<FileLine*>(::operator new(size));
fileLineLeakChecks.insert(objp);
return objp;
}
void FileLine::operator delete(void* objp, size_t size) {
if (!objp) return;
FileLine* flp = static_cast<FileLine*>(objp);
FileLineCheckSet::iterator it = fileLineLeakChecks.find(flp);
if (it != fileLineLeakChecks.end()) {
fileLineLeakChecks.erase(it);
} else {
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
}
::operator delete(objp);
}
#endif
void FileLine::deleteAllRemaining() {
#ifdef VL_LEAK_CHECKS
// FileLines are allocated, but never nicely freed, as it's much faster
// that way. Unfortunately this makes our leak checking a big mess, so
// only when leak checking we'll track them all and cleanup.
while (1) {
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
if (it==fileLineLeakChecks.end()) break;
delete *it;
// Operator delete will remove the iterated object from the list.
// Eventually the list will be empty and terminate the loop.
}
fileLineLeakChecks.clear();
#endif
}
//######################################################################
// V3Error class functions
@@ -190,14 +238,12 @@ string V3Error::lineStr (const char* filename, int lineno) {
void V3Error::incWarnings() {
s_warnCount++;
if (errorOrWarnCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
v3fatal ("Exiting due to too many errors encountered\n");
}
// We don't exit on a lot of warnings.
}
void V3Error::incErrors() {
s_errCount++;
if (errorOrWarnCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
v3fatal ("Exiting due to too many errors encountered\n");
}
}
+22 -6
View File
@@ -48,6 +48,7 @@ public:
CASEX, // Casex
CMPCONST, // Comparison is constant due to limited range
COMBDLY, // Combinatorial delayed assignment
STMTDLY, // Delayed statement
GENCLK, // Generated Clock
IMPLICIT, // Implicit wire
IMPURE, // Impure function not being inlined
@@ -76,7 +77,7 @@ public:
" FIRST_WARN",
"BLKANDNBLK",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
"COMBDLY", "GENCLK", "IMPLICIT", "IMPURE",
"COMBDLY", "STMTDLY", "GENCLK", "IMPLICIT", "IMPURE",
"MULTIDRIVEN",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH",
@@ -89,6 +90,13 @@ public:
// Warnings we'll present to the user as errors
// Later -Werror- options may make more of these.
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE); };
// Warnings that are lint only
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|| m_e==CASEX || m_e==CMPCONST
|| m_e==IMPLICIT
|| m_e==UNDRIVEN || m_e==UNSIGNED
|| m_e==UNUSED || m_e==VARHIDDEN
|| m_e==WIDTH); };
};
inline bool operator== (V3ErrorCode lhs, V3ErrorCode rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (V3ErrorCode lhs, V3ErrorCode::en rhs) { return (lhs.m_e == rhs); }
@@ -109,8 +117,6 @@ class V3Error {
static ostringstream s_errorStr; // Error string being formed
static V3ErrorCode s_errorCode; // Error string being formed will abort
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
static void incErrors();
static void incWarnings();
V3Error() { cerr<<("Static class"); abort(); }
@@ -124,6 +130,8 @@ class V3Error {
static int warnCount() { return s_warnCount; }
static int errorOrWarnCount() { return errorCount()+warnCount(); }
// METHODS
static void incErrors();
static void incWarnings();
static void init();
static void abortIfErrors();
static void abortIfWarnings();
@@ -191,9 +199,14 @@ protected:
void incLineno() { m_lineno++; }
FileLine* copyOrSameFileLine();
public:
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff;}
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff;};
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; } // Only for static constructor
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff; }
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff; }
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; }
~FileLine() { }
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
static void operator delete(void* obj, size_t size);
#endif
static FileLine& defaultFileLine() { return s_defaultFileLine; }
int lineno () const { return m_lineno; }
string ascii() const;
@@ -204,11 +217,14 @@ public:
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 warnIsOff(V3ErrorCode code);
void warnLintOff(bool flag);
void warnStateFrom(const FileLine& from) { m_warnOff=from.m_warnOff; }
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
void v3errorEnd(ostringstream& str);
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
static void deleteAllRemaining();
};
ostream& operator<<(ostream& os, FileLine* fileline);
+3 -1
View File
@@ -531,6 +531,8 @@ private:
rhsp, lsb)));
}
}
rhsp->deleteTree(); rhsp=NULL;
destp->deleteTree(); destp=NULL;
} else {
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
@@ -803,7 +805,7 @@ private:
for (int w=0; w<nodep->lhsp()->widthWords(); w++) {
AstNode* eqp = newAstWordSelClone (nodep->lhsp(), w);
if (w==nodep->lhsp()->widthWords()-1) {
// Rather then doing a (slowish) ==##, we OR in the bits that aren't part of the mask
// Rather than doing a (slowish) ==##, we OR in the bits that aren't part of the mask
eqp = new AstOr (nodep->fileline(),
new AstConst (nodep->fileline(), notWideMask(nodep->lhsp())),
eqp);
+2 -2
View File
@@ -341,7 +341,7 @@ private:
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
GateVarVertex* varvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
// We use weight of one; if we ref the var more then once, when we simplify,
// We use weight of one; if we ref the var more than once, when we simplify,
// the weight will increase
if (nodep->lvalue()) {
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
@@ -433,7 +433,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
}
}
else if (!vvertexp->inSize1()) {
vvertexp->clearReducible("size!1"); // Can't deal with more then one src
vvertexp->clearReducible("size!1"); // Can't deal with more than one src
}
// Reduce it?
if (!vvertexp->reducible()) {
+6 -1
View File
@@ -42,8 +42,10 @@ class V3Global {
AstNetlist* m_rootp; // Root of entire netlist
int m_debugFileNumber; // Number to append to debug files created
bool m_assertWidthsSame; // Tree should have width()==widthMin()
// Options
bool m_needHInlines; // Need a __Inlines file
public:
// Options
V3Options opt; // All options; let user see them directly
public:
@@ -52,6 +54,7 @@ public:
m_rootp = new AstNetlist;
m_debugFileNumber = 0;
m_assertWidthsSame = false;
m_needHInlines = false;
}
void clear() {
if (m_rootp) m_rootp->deleteTree(); m_rootp=NULL;
@@ -70,6 +73,8 @@ public:
char digits[100]; sprintf(digits, "%02d", m_debugFileNumber);
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
}
bool needHInlines() const { return m_needHInlines; }
void needHInlines(bool flag) { m_needHInlines=flag; }
};
extern V3Global v3Global;
+3 -3
View File
@@ -177,10 +177,10 @@ void V3Graph::clear() {
void V3Graph::userClearVertices() {
// Clear user() in all of tree
// We may use the userCnt trick in V3Ast later... For now we don't call this often, and
// 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 than help.
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
vertexp->user(0);
vertexp->userp(NULL); // Its a union, but might be different size then user()
vertexp->userp(NULL); // Its a union, but might be different size than user()
}
}
@@ -189,7 +189,7 @@ void V3Graph::userClearEdges() {
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
edgep->user(0);
edgep->userp(NULL); // Its a union, but might be different size then user()
edgep->userp(NULL); // Its a union, but might be different size than user()
}
}
}
+1 -1
View File
@@ -440,7 +440,7 @@ void GraphAcyc::place() {
UINFO(4, " Cutable edges = "<<numEdges<<endl);
vector<V3GraphEdge*> edges; // List of all edges to be processed
edges.reserve(numEdges+1); // Make the vector properly sized right off the bat -- faster then reallocating
edges.reserve(numEdges+1); // Make the vector properly sized right off the bat -- faster than reallocating
for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
vertexp->user(0); // Clear in prep of next step
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
+3 -3
View File
@@ -58,7 +58,7 @@ void V3Graph::deleteCutableOnlyEdges() {
}
// Pass 2, delete those marked
// Rather then doing a delete() we set the weight to 0 which disconnects the edge.
// Rather than doing a delete() we set the weight to 0 which disconnects the edge.
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
if (vertexp->user()) {
//UINFO(7,"Disconnect "<<vertexp->name()<<endl);
@@ -99,9 +99,9 @@ private:
} else { // Duplicate
bool saveOld = true;
if (prevEdgep->cutable() && !edgep->cutable()) {
saveOld = false; // new !cutable more important then old
saveOld = false; // new !cutable more important than old
} else if (!prevEdgep->cutable() && edgep->cutable()) {
saveOld = true; // old !cutable more important then new
saveOld = true; // old !cutable more important than new
} else {
saveOld = true;
if (!m_sumWeights && (prevEdgep->weight() < edgep->weight())) { // Keep max weight
+1 -1
View File
@@ -83,7 +83,7 @@ public:
class DfaVertex : public V3GraphVertex {
// Each DFA state is captured in this vertex.
// Start and accepting are members, rather then the more intuitive
// Start and accepting are members, rather than the more intuitive
// subclasses, as subclassing them would make it harder to inherit from here.
bool m_start; // Start state
bool m_accepting; // Accepting state?
+3 -3
View File
@@ -151,7 +151,7 @@ private:
// Remove the cell
newmodp->deleteTree(); newmodp=NULL; // Clear any leftover ports, etc
nodep->unlinkFrBack();
nodep = NULL;
pushDeletep(nodep); nodep = NULL;
if (debug()>=9) { m_modp->dumpTree(cout,"donemod:"); }
}
}
@@ -332,14 +332,14 @@ private:
} else {
m_modp->user(1);
}
nodep->unlinkFrBack(); nodep=NULL; // Remove so don't propagate to upper cell...
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
} else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) {
if (!m_modp) {
nodep->v3error("Inline pragma not under a module");
} else {
cantInline("Pragma NO_INLINE_MODULE");
}
nodep->unlinkFrBack(); nodep=NULL; // Remove so don't propagate to upper cell...
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
} else {
nodep->iterateChildren(*this);
}
+1 -1
View File
@@ -134,7 +134,7 @@ public:
AstVar* varp = it->first->varp();
LifeVarEntry* entp = &(it->second);
if (!varp->isSigPublic()) {
// Rather then track what sigs AstUCFunc/AstUCStmt may change,
// Rather than track what sigs AstUCFunc/AstUCStmt may change,
// we just don't optimize any public sigs
// Check the var entry, and remove if appropriate
if (AstNode* oldassp = entp->assignp()) {
+1 -1
View File
@@ -165,7 +165,7 @@ private:
if ((findvarp->isIO() && nodep->isSignal())
|| (findvarp->isSignal() && nodep->isIO())) {
findvarp->combineType(nodep);
nodep->unlinkFrBack(); nodep=NULL;
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} else {
nodep->v3error("Duplicate declaration of signal: "<<nodep->prettyName());
findvarp->v3error("... Location of original declaration");
+2 -2
View File
@@ -174,8 +174,8 @@ private:
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.
// We search ports, rather than in/out declarations as they aren't resolved yet,
// and it's easier to do it now than 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())) {
+1 -1
View File
@@ -72,7 +72,7 @@ private:
UINFO(5," "<<nodep<<endl);
checkExpected(nodep);
// Due to a need to get the arguments, the ParseRefs are under here,
// rather then the NodeFTaskRef under the ParseRef.
// rather than the NodeFTaskRef under the ParseRef.
if (nodep->namep()) {
m_exp = AstParseRefExp::FUNC;
nodep->namep()->accept(*this); // No next, we don't want to do the edit
+27 -1
View File
@@ -721,7 +721,7 @@ V3Number& V3Number::opRepl (const V3Number& lhs, const V3Number& rhs) { // rhs i
V3Number& V3Number::opRepl (const V3Number& lhs, uint32_t rhsval) { // rhs is # of times to replicate
// i op repl, L(i)*value(rhs) bit return
setZero();
if (rhsval>8192) m_fileline->v3fatal("More then a 8k bit replication is probably wrong: "<<rhsval);
if (rhsval>8192) m_fileline->v3fatal("More than a 8k bit replication is probably wrong: "<<rhsval);
int obit = 0;
for (unsigned times=0; times<rhsval; times++) {
for(int bit=0; bit<lhs.width(); bit++) {
@@ -814,6 +814,28 @@ last:
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) {
// i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend.
char outc = 0;
@@ -985,6 +1007,7 @@ V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opDiv (const V3Number& lhs, const V3Number& rhs) {
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX();
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large / math not implemented yet: "<<*this);
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large / math not implemented yet: "<<*this);
setQuad(lhs.asQuad() / rhs.asQuad());
@@ -993,6 +1016,7 @@ V3Number& V3Number::opDiv (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
// Signed divide
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
@@ -1007,6 +1031,7 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX();
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large % math not implemented yet: "<<*this);
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large % math not implemented yet: "<<*this);
setQuad(lhs.asQuad() % rhs.asQuad());
@@ -1015,6 +1040,7 @@ V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
// Signed moddiv
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
+2
View File
@@ -174,6 +174,8 @@ public:
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
V3Number& opCaseEq (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
V3Number& opNot (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.opEq (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.opCaseNeq (lhnum,rhnum);
else if (op=="!=?") gotnum.opWildNeq (lhnum,rhnum);
else if (op=="<=") gotnum.opLte (lhnum,rhnum);
else if (op==">=") gotnum.opGte (lhnum,rhnum);
else if (op=="&&") gotnum.opLogAnd (lhnum,rhnum);
+9 -4
View File
@@ -440,9 +440,14 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
V3PreShell::undef (string (sw+strlen("-U")));
}
else if ( !strncmp (sw, "-Wno-",5) ) {
string msg = sw+strlen("-Wno-");
if (!(FileLine::defaultFileLine().warnOff(msg, true))) {
fl->v3fatal("Unknown warning disabled: "<<sw);
if (!strcmp (sw, "-Wno-lint")) {
FileLine::defaultFileLine().warnLintOff(true);
}
else {
string msg = sw+strlen("-Wno-");
if (!(FileLine::defaultFileLine().warnOff(msg, true))) {
fl->v3fatal("Unknown warning disabled: "<<sw);
}
}
}
else if ( !strncmp (sw, "-Werror-",strlen("-Werror-")) ) {
@@ -623,7 +628,7 @@ V3Options::V3Options() {
addLibExt(""); // So include "filename.v" will find the same file
addLibExt(".v");
// Default -I
addIncDir("."); // Looks better then {long_cwd_path}/...
addIncDir("."); // Looks better than {long_cwd_path}/...
}
V3Options::~V3Options() {
+12 -6
View File
@@ -155,6 +155,9 @@ public:
void movedVertex(OrderVisitor* ovp, OrderMoveVertex* vertexp); // Mark one vertex as finished, remove from ready list if done
// STATIC MEMBERS (for lookup)
static void clear() {
for (DomScopeMap::iterator it=s_dsMap.begin(); it!=s_dsMap.end(); ++it) {
delete it->second;
}
s_dsMap.clear();
}
V3List<OrderMoveVertex*>& readyVertices() { return m_readyVertices; }
@@ -426,15 +429,18 @@ private:
m_finder.main(m_topScopep);
// ProcessDomainsIterate will use these when it needs to move
// something to a combodomain. This saves a ton of find() operations.
AstSenTree comb (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
m_comboDomainp = m_finder.getSenTree(nodep->fileline(), &comb);
AstSenTree settle (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
m_settleDomainp = m_finder.getSenTree(nodep->fileline(), &settle);
AstSenTree* combp = new AstSenTree (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
m_comboDomainp = m_finder.getSenTree(nodep->fileline(), combp);
pushDeletep(combp); // Cleanup when done
AstSenTree* settlep = new AstSenTree (nodep->fileline(), // Gets cloned() so ok if goes out of scope
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
m_settleDomainp = m_finder.getSenTree(nodep->fileline(), settlep);
pushDeletep(settlep); // Cleanup when done
// Fake AstSenTree we set domainp to indicate needs deletion
m_deleteDomainp = new AstSenTree (nodep->fileline(),
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
pushDeletep(m_deleteDomainp); // Cleanup when done
UINFO(5," DeleteDomain = "<<m_deleteDomainp<<endl);
// Base vertices
m_activeSenVxp = NULL;
+34 -6
View File
@@ -83,7 +83,9 @@ struct V3PreProcImp : public V3PreProc {
// For getRawToken/ `line insertion
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
string m_defName; // Define last name being defined
@@ -134,6 +136,7 @@ public:
virtual bool isEof() const { return (m_lexp==NULL); }
virtual string getline();
virtual void insertUnreadback(const string& text) { m_lineCmt += text; }
void insertUnreadbackAtBol(const string& text);
// METHODS, callbacks
virtual void comment(const string& cmt); // Comment detected (if keepComments==2)
@@ -151,6 +154,8 @@ public:
m_lineChars = "";
m_lastSym = "";
m_lineAdd = 0;
m_lineCmtNl = false;
m_rawAtBol = true;
m_defDepth = 0;
}
};
@@ -486,14 +491,24 @@ void V3PreProcImp::openFile(FileLine* fl, const string& filename) {
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) {
if (lineDirectives()) {
char numbuf[20]; sprintf(numbuf, "%d", m_lexp->m_curFilelinep->lineno());
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()+"\" "
+levelbuf+"\n");
insertUnreadback(cmt);
insertUnreadbackAtBol(cmt);
}
}
@@ -517,6 +532,7 @@ int V3PreProcImp::getRawToken() {
next_tok:
if (m_lineAdd) {
m_lineAdd--;
m_rawAtBol = true;
yytext="\n"; yyleng=1;
return (VP_TEXT);
}
@@ -524,8 +540,13 @@ int V3PreProcImp::getRawToken() {
// We have some `line directive to return to the user. Do it.
static string rtncmt; // Keep the c string till next call
rtncmt = m_lineCmt;
if (m_lineCmtNl) {
if (!m_rawAtBol) rtncmt = "\n"+rtncmt;
m_lineCmtNl = false;
}
yytext=(char*)rtncmt.c_str(); yyleng=rtncmt.length();
m_lineCmt = "";
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
if (m_state!=ps_DEFVALUE) return (VP_TEXT);
else {
V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng);
@@ -533,6 +554,7 @@ int V3PreProcImp::getRawToken() {
}
}
if (isEof()) return (VP_EOF);
// Snarf next token from the file
m_fileline = m_lexp->m_curFilelinep; // Remember token start location
V3PreLex::s_currentLexp = m_lexp; // Tell parser where to get/put data
@@ -553,6 +575,7 @@ int V3PreProcImp::getRawToken() {
goto next_tok; // Parse parent, or find the EOF.
}
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
return tok;
}
}
@@ -872,7 +895,8 @@ string V3PreProcImp::getline() {
// Get a single line from the parse stream. Buffer unreturned text until the newline.
if (isEof()) return "";
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();
if (debug()>4) {
string buf = string (yytext, yyleng);
@@ -883,8 +907,12 @@ string V3PreProcImp::getline() {
fileline()->lineno(), tokenName(tok), buf.c_str());
}
if (tok==VP_EOF) {
// Add a final newline, in case the user forgot the final \n.
m_lineChars.append("\n");
// Add a final newline, if the user forgot the final \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) {
m_lineChars.append(" psl ");
+4 -4
View File
@@ -57,10 +57,10 @@ protected:
s_preprocp->debug(debug());
// Default defines
FileLine* prefl = new FileLine("INTERNAL_VERILATOR_DEFINE",0);
s_preprocp->define(prefl,"verilator", "1");
s_preprocp->define(prefl,"verilator3", "1");
s_preprocp->define(prefl,"systemc_clock", "/*verilator systemc_clock*/");
s_preprocp->define(prefl,"coverage_block_off", "/*verilator coverage_block_off*/");
s_preprocp->define(prefl,"verilator", "1"); // LEAK_OK
s_preprocp->define(prefl,"verilator3", "1"); // LEAK_OK
s_preprocp->define(prefl,"systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK
s_preprocp->define(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK
}
}
+13
View File
@@ -78,6 +78,19 @@ void V3Read::statePop() { s_readp->m_lexerp->statePop(); }
//######################################################################
// Read class functions
V3Read::~V3Read() {
for (deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) {
delete (*it);
}
m_stringps.clear();
for (deque<V3Number*>::iterator it = m_numberps.begin(); it != m_numberps.end(); ++it) {
delete (*it);
}
m_numberps.clear();
if (m_lexerp) { delete m_lexerp; m_lexerp = NULL; }
parserClear();
}
void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) {
string modname = V3Options::filenameNonExt(modfilename);
+2 -10
View File
@@ -110,16 +110,8 @@ public:
m_inBeginKwd = 0;
m_lastVerilogState = stateVerilogRecent();
}
~V3Read() {
for (deque<string*>::iterator it = m_stringps.begin(); it != m_stringps.end(); ++it) {
delete (*it);
}
m_stringps.clear();
for (deque<V3Number*>::iterator it = m_numberps.begin(); it != m_numberps.end(); ++it) {
delete (*it);
}
m_numberps.clear();
}
~V3Read();
void parserClear();
// METHODS
// Preprocess and read the Verilog file specified into the netlist database
+2
View File
@@ -98,8 +98,10 @@ private:
// ... (Though they should match. We don't check.)
virtual void visit(AstEq* 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(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
+1 -1
View File
@@ -337,7 +337,7 @@ private:
SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
vvertexp->splitColor(vvertexp->color());
uint32_t color = vvertexp->splitColor();
if (color >= numVertexes) nextp->v3fatalSrc("More colors then vertexes!\n");
if (color >= numVertexes) nextp->v3fatalSrc("More colors than vertexes!\n");
if (!color) nextp->v3fatalSrc("No node color assigned\n");
if (lastOfColor[color]) {
new SplitStrictEdge(&m_graph, lastOfColor[color], vvertexp);
+1 -1
View File
@@ -165,7 +165,7 @@ private:
virtual void visit(AstAlways* nodep, AstNUser*) {
// 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 than one. So, we process the first one found first.
AstVarScope* lastSplitVscp = NULL;
while (!nodep->user()) {
// Find any splittable variables
+2 -2
View File
@@ -120,14 +120,14 @@ public:
if (!nodep->user3p()) {
// Save time - kept a list of allocated but unused V3Numbers
// It would be more efficient to do this by size, but the extra accounting
// slows things down more then we gain.
// slows things down more than we gain.
V3Number* nump;
if (!m_numFreeps.empty()) {
//UINFO(7,"Num Reuse "<<nodep->width()<<endl);
nump = m_numFreeps.back(); m_numFreeps.pop_back();
nump->width(nodep->width());
nump->fileline(nodep->fileline());
nump->setLong(value); // We do support more then 32 bit numbers, just valuep=0 in that case
nump->setLong(value); // We do support more than 32 bit numbers, just valuep=0 in that case
} else {
//UINFO(7,"Num New "<<nodep->width()<<endl);
nump = new V3Number (nodep->fileline(), nodep->width(), value);
+1
View File
@@ -349,6 +349,7 @@ private:
// Connect to this exact variable
AstVarScope* localVscp = varrefp->varScopep(); if (!localVscp) varrefp->v3fatalSrc("Null var scope");
portp->user2p(localVscp);
pushDeletep(pinp);
} else {
pinp->v3warn(TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
}
+1 -1
View File
@@ -37,7 +37,7 @@
// For each CFUNC in graph
// Add ASSIGN(SEL(__Vm_funcActivity,activityNumber++),1)
// Create __Vm_funcActivity vector
// Sort TRACEs by activityNumber(s) they come from (may be more then one)
// Sort TRACEs by activityNumber(s) they come from (may be more than one)
// Each set of activityNumbers
// Add IF (SEL(__Vm_funcActivity,activityNumber),1)
// Add traces under that activity number.
+45
View File
@@ -95,6 +95,8 @@ private:
|| (rhsp->castConst() && rhsp->castConst()->num().isFourState()))) {
V3Number num (nodep->fileline(), 1, (nodep->castEqCase()?0:1));
newp = new AstConst (nodep->fileline(), num);
lhsp->deleteTree(); lhsp=NULL;
rhsp->deleteTree(); rhsp=NULL;
} else {
if (nodep->castEqCase())
newp = new AstEq (nodep->fileline(), lhsp, rhsp);
@@ -106,6 +108,42 @@ private:
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*) {
visitEqNeqCase(nodep);
@@ -113,6 +151,12 @@ private:
virtual void visit(AstNeqCase* nodep, AstNUser*) {
visitEqNeqCase(nodep);
}
virtual void visit(AstEqWild* nodep, AstNUser*) {
visitEqNeqWild(nodep);
}
virtual void visit(AstNeqWild* nodep, AstNUser*) {
visitEqNeqWild(nodep);
}
virtual void visit(AstIsUnknown* nodep, AstNUser*) {
nodep->iterateChildren(*this);
// Ahh, we're two state, so this is easy
@@ -179,6 +223,7 @@ private:
if (debug()>=9) newref1p->dumpTree(cout," _new: ");
if (debug()>=9) newvarp->dumpTree(cout," _new: ");
if (debug()>=9) newinitp->dumpTree(cout," _new: ");
nodep->deleteTree(); nodep=NULL;
}
}
}
+23 -25
View File
@@ -171,7 +171,7 @@ private:
if (((valStop - valInit)/valInc) > v3Global.opt.unrollCount())
return cantUnroll(nodep, "too many iterations");
// Less then 10 statements in the body?
// Less than 10 statements in the body?
int bodySize = 0;
for (AstNode* bodp = precondsp; bodp; bodp=bodp->nextp()) {
bodySize++;
@@ -198,6 +198,7 @@ private:
constInitp->num(),
condBip, constStopp->num(),
incInstrp, constIncp->num()); nodep = NULL;
// Cleanup
return true;
}
@@ -229,7 +230,6 @@ private:
loopValue.opAssign(numInit);
AstNode* newbodysp = NULL;
AstNode* clonedIncsp = NULL; // Last cloned incp() statements
m_statLoops++;
if (stmtsp) {
int times = 0;
@@ -244,25 +244,8 @@ private:
// Replace iterator values with constant.
AstNode* oneloopp = stmtsp->cloneTree(true);
// A nicer way to propage the loop constant would be to set the variable to the value
// and call a constant-propagator like V3Table, so temp values
// that are calculated propagate down.
// If we do this, we can remove the below
if (nodep->castWhile() && incp) {
if (clonedIncsp) {
// Previous iteration of loop set the variable.
// This set is redundant with this next iteration and can be removed.
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");
}
m_varValuep = new AstConst(nodep->fileline(), loopValue);
m_varModeReplace = true;
oneloopp->iterateAndNext(*this);
m_varModeReplace = false;
@@ -280,6 +263,8 @@ private:
V3Number newnum(nodep->fileline(), m_forVarp->width()); // Can't increment in-place
incInstrp->numberOperate(newnum, loopValue, numInc);
loopValue.opAssign(newnum);
pushDeletep(m_varValuep); m_varValuep=NULL;
}
}
}
@@ -287,6 +272,9 @@ private:
// Replace the FOR()
if (newbodysp) nodep->replaceWith(newbodysp);
else nodep->unlinkFrBack();
if (bodysp) { pushDeletep(bodysp); bodysp=NULL; }
if (precondsp) { pushDeletep(precondsp); precondsp=NULL; }
if (initp) { pushDeletep(initp); initp=NULL; }
if (debug()>=9) newbodysp->dumpTree(cout,"- _new: ");
}
@@ -311,7 +299,7 @@ private:
if (forUnrollCheck(nodep, initp,
nodep->precondsp(), nodep->condp(),
incp, nodep->bodysp())) {
nodep=NULL; // Did replacement
pushDeletep(nodep); nodep=NULL; // Did replacement
}
}
}
@@ -325,10 +313,19 @@ private:
if (nodep->initsp()) V3Const::constifyTree(nodep->initsp());
if (nodep->condp()) V3Const::constifyTree(nodep->condp());
if (nodep->incsp()) V3Const::constifyTree(nodep->incsp());
if (forUnrollCheck(nodep, nodep->initsp(),
NULL, nodep->condp(),
nodep->incsp(), nodep->bodysp())) {
nodep=NULL; // Did replacement
if (nodep->condp()->isZero()) {
// We don't need to do any loops. Remove the GenFor,
// Genvar's don't care about any initial assignments.
//
// Note normal For's can't do exactly this deletion, as
// we'd need to initialize the variable to the initial
// condition, but they'll become while's which can be
// deleted by V3Const.
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} else if (forUnrollCheck(nodep, nodep->initsp(),
NULL, nodep->condp(),
nodep->incsp(), nodep->bodysp())) {
pushDeletep(nodep); nodep=NULL; // Did replacement
} else {
nodep->v3error("For loop doesn't have genvar index, or is misformed");
}
@@ -373,6 +370,7 @@ private:
&& !nodep->lvalue()) {
AstNode* newconstp = m_varValuep->cloneTree(false);
nodep->replaceWith(newconstp);
pushDeletep(nodep);
}
}
+5 -2
View File
@@ -117,6 +117,7 @@ private:
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(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(AstGtS* 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(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(AstNeqWild* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
// Widths: out width = lhs width = rhs width
void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup);
@@ -365,7 +367,7 @@ private:
}
if (vup->c()->final()) {
nodep->width(vup->c()->width(),vup->c()->widthMin()); // We don't care
if (nodep->width()>64) nodep->v3error("Unsupported: $c can't generate wider then 64 bits");
if (nodep->width()>64) nodep->v3error("Unsupported: $c can't generate wider than 64 bits");
}
// Just let all arguments seek their natural sizes
nodep->iterateChildren(*this,WidthVP(ANYSIZE,0,BOTH).p());
@@ -533,7 +535,7 @@ private:
nodep->rhsp()->iterateAndNext(*this,WidthVP(awidth,awidth,FINAL).p());
nodep->width(awidth,awidth); // We know the assign will truncate, so rather
//UINFO(0,"aw "<<awidth<<" w"<<nodep->rhsp()->width()<<" m"<<nodep->rhsp()->widthMin()<<endl);
// then using "width" and have the optimizer truncate the result, we do
// than using "width" and have the optimizer truncate the result, we do
// it using the normal width reduction checks.
widthCheck(nodep,"Assign RHS",nodep->rhsp(),awidth,awidth);
//if (debug()) nodep->dumpTree(cout," AssignPos: ");
@@ -758,6 +760,7 @@ void WidthVisitor::fixWidthExtend (AstNode* nodep, int expWidth) {
AstNode* newp = new AstConst(nodep->fileline(), num);
newp->signedFrom(constp);
constp->replaceWith(newp);
pushDeletep(constp); constp=NULL;
nodep=newp;
} else if (expWidth<nodep->width()) {
// Trunc - Extract
+3
View File
@@ -459,6 +459,8 @@ void process () {
// Output the text
if (!v3Global.opt.lintOnly()) {
// emitcInlines is first, as it may set needHInlines which other emitters read
V3EmitC::emitcInlines();
V3EmitC::emitcSyms();
V3EmitC::emitcTrace();
}
@@ -552,6 +554,7 @@ int main(int argc, char** argv, char** env) {
// Cleanup memory for valgrind leak analysis
v3Global.clear();
#endif
FileLine::deleteAllRemaining();
UINFO(1,"Done, Exiting...\n");
}
+2 -2
View File
@@ -4,7 +4,7 @@
//
// 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
//
@@ -24,7 +24,7 @@
//**********************************************************************
//**** Version and host name
#define DTVERSION "Verilator 3.652 6/21/2007"
#define DTVERSION "Verilator 3.655 11/27/2007"
//**********************************************************************
//**** Functions
+40 -6
View File
@@ -324,6 +324,7 @@ escid \\[^ \t\f\r\n]+
"always_latch" {yylval.fileline = CRELINE(); return yALWAYS;}
"do" {yylval.fileline = CRELINE(); return yDO;}
"final" {yylval.fileline = CRELINE(); return yFINAL;}
"static" {yylval.fileline = CRELINE(); return ySTATIC;}
/* Generic unsupported warnings */
/* Note assert_strobe was in SystemVerilog 3.1, but removed for SystemVerilog 2005 */
"alias" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
@@ -391,7 +392,6 @@ escid \\[^ \t\f\r\n]+
"shortint" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
"shortreal" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
"solve" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
"static" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
"string" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
"struct" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
"super" {yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext);}
@@ -567,6 +567,10 @@ escid \\[^ \t\f\r\n]+
"~^" {yylval.fileline = CRELINE(); return yP_XNOR;}
"~&" {yylval.fileline = CRELINE(); return yP_NAND;}
"~|" {yylval.fileline = CRELINE(); return yP_NOR;}
"->" {yylval.fileline = CRELINE(); return yP_MINUSGT;}
"=>" {yylval.fileline = CRELINE(); return yP_EQGT; }
"*>" {yylval.fileline = CRELINE(); return yP_ASTGT; }
"&&&" {yylval.fileline = CRELINE(); return yP_ANDANDAND; }
}
/* Verilog 2001 Operators */
@@ -576,13 +580,39 @@ escid \\[^ \t\f\r\n]+
"**" {yylval.fileline = CRELINE(); return yP_POW;}
"+:" {yylval.fileline = CRELINE(); return yP_PLUSCOLON;}
"-:" {yylval.fileline = CRELINE(); return yP_MINUSCOLON;}
".*" {yylval.fileline = CRELINE(); return yP_DOTSTAR;}
}
/* SystemVerilog Operators */
<S05>{
"==?" {yylval.fileline = CRELINE(); return yP_WILDEQUAL;}
"!=?" {yylval.fileline = CRELINE(); return yP_WILDNOTEQUAL;}
"+=" {yylval.fileline = CRELINE(); return yP_PLUSEQ; }
"-=" {yylval.fileline = CRELINE(); return yP_MINUSEQ; }
"*=" {yylval.fileline = CRELINE(); return yP_TIMESEQ; }
"/=" {yylval.fileline = CRELINE(); return yP_DIVEQ; }
"%=" {yylval.fileline = CRELINE(); return yP_MODEQ; }
"&=" {yylval.fileline = CRELINE(); return yP_ANDEQ; }
"|=" {yylval.fileline = CRELINE(); return yP_OREQ; }
"^=" {yylval.fileline = CRELINE(); return yP_XOREQ; }
"<<=" {yylval.fileline = CRELINE(); return yP_SLEFTEQ; }
">>=" {yylval.fileline = CRELINE(); return yP_SRIGHTEQ; }
"<<<=" {yylval.fileline = CRELINE(); return yP_SLEFTEQ; }
">>>=" {yylval.fileline = CRELINE(); return yP_SSRIGHTEQ; }
"->>" {yylval.fileline = CRELINE(); return yP_MINUSGTGT; }
"##" {yylval.fileline = CRELINE(); return yP_POUNDPOUND; }
"@@" {yylval.fileline = CRELINE(); return yP_ATAT; }
"::" {yylval.fileline = CRELINE(); return yP_COLONCOLON; }
":=" {yylval.fileline = CRELINE(); return yP_COLONEQ; }
":/" {yylval.fileline = CRELINE(); return yP_COLONDIV; }
"|->" {yylval.fileline = CRELINE(); return yP_ORMINUSGT; }
"|=>" {yylval.fileline = CRELINE(); return yP_OREQGT; }
}
/* PSL Operators */
<PSL>{
"{" {yylval.fileline = CRELINE(); return yPSL_BRA;} // Avoid parser hitting concatenate.
"}" {yylval.fileline = CRELINE(); return yPSL_KET;} // Avoid parser hitting concatenate.
"->" {yylval.fileline = CRELINE(); return yP_LOGIF;}
"<->" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} //Unsup in other tools
"[*" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_STAR
"[*]" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_STAR_KET
@@ -590,8 +620,8 @@ escid \\[^ \t\f\r\n]+
"[->" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_MINUS_GT
"[->]" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_MINUS_GT_KET
"[=" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_EQ
"|->" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_OR_MINUS_GT
"|=>" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_OR_EQ_GT
"|->" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_ORMINUSGT
"|=>" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_OREQGT
}
/* Identifiers and numbers */
@@ -641,6 +671,10 @@ escid \\[^ \t\f\r\n]+
yylval.cdouble = 0; /* Only for delays, not used yet */
return yaFLOATNUM;
}
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
yylval.cdouble = 0; /* Only for times, not used yet */
return yaFLOATNUM;
}
}
/************************************************************************/
@@ -659,7 +693,7 @@ escid \\[^ \t\f\r\n]+
<ATTRMODE>"*)" { yy_pop_state(); }
<ATTRMODE>. { yymore(); }
<ATTRMODE><<EOF>> { yyerror("EOF in (*");
yyleng = 0; }
yyleng = 0; yy_pop_state(); }
/************************************************************************/
/* Attributes */
@@ -695,7 +729,7 @@ escid \\[^ \t\f\r\n]+
"`begin_keywords"[ \t]*\"1364-2001-noconfig\" { yy_push_state(V01); V3Read::pushBeginKeywords(YY_START);}
"`begin_keywords"[ \t]*\"1364-2005\" { yy_push_state(V05); V3Read::pushBeginKeywords(YY_START);}
"`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); V3Read::pushBeginKeywords(YY_START);}
"`end_keywords" { yy_pop_state(); if (!V3Read::popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
"`end_keywords" { yy_pop_state(); if (!V3Read::popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
}
<SYSCHDR>[ \t]*[^` \t\n][^\n]*\n { NEXTLINE(); yylval.strp = V3Read::newString(yytext); return yaSCHDR;}
+240 -89
View File
@@ -66,6 +66,10 @@ public:
nodep->addNext(new AstStop(fileline));
return nodep;
}
static void setRange(AstRange* rangep) {
if (s_varRangep) { s_varRangep->deleteTree(); s_varRangep=NULL; } // It was cloned, so this is safe.
s_varRangep = rangep;
}
static string deQuote(FileLine* fileline, string text);
};
@@ -88,7 +92,7 @@ AstCase* V3Parse::s_caseAttrp = NULL;
#define VARDECL(type) { V3Parse::s_varDecl = AstVarType::type; }
#define VARIO(type) { V3Parse::s_varIO = AstVarType::type; }
#define VARSIGNED(value) { V3Parse::s_varSigned = value; }
#define VARRANGE(range) { V3Parse::s_varRangep=(range); }
#define VARRANGE(rangep) { V3Parse::setRange(rangep); }
#define INSTPREP(modname,paramsp) { V3Parse::s_impliedDecl = true; V3Parse::s_instModule = modname; V3Parse::s_instParamp = paramsp; }
@@ -127,11 +131,19 @@ class AstSenTree;
}
// Generic lexer tokens, for example a number
// IEEE: real_number
%token<cdouble> yaFLOATNUM "FLOATING-POINT NUMBER"
%token<fileline> yaTIMINGSPEC "TIMING SPEC ELEMENT"
%token<nump> yaINTNUM "INTEGER NUMBER"
// IEEE: identifier, class_identifier, class_variable_identifier,
// covergroup_variable_identifier, dynamic_array_variable_identifier,
// enum_identifier, interface_identifier, interface_instance_identifier,
// package_identifier, type_identifier, variable_identifier,
%token<strp> yaID "IDENTIFIER"
// IEEE: integral_number
%token<nump> yaINTNUM "INTEGER NUMBER"
// IEEE: string_literal
%token<strp> yaSTRING "STRING"
%token<fileline> yaTIMINGSPEC "TIMING SPEC ELEMENT"
%token<strp> yaSCHDR "`systemc_header BLOCK"
%token<strp> yaSCINT "`systemc_ctor BLOCK"
@@ -193,6 +205,7 @@ class AstSenTree;
%token<fileline> ySCALARED "scalared"
%token<fileline> ySIGNED "signed"
%token<fileline> ySPECIFY "specify"
%token<fileline> ySTATIC "static"
%token<fileline> ySUPPLY0 "supply0"
%token<fileline> ySUPPLY1 "supply1"
%token<fileline> yTASK "task"
@@ -246,39 +259,114 @@ class AstSenTree;
%token<fileline> yVL_TRACING_OFF "/*verilator tracing_off*/"
%token<fileline> yVL_TRACING_ON "/*verilator tracing_on*/"
%token<fileline> yP_OROR "||"
%token<fileline> yP_ANDAND "&&"
%token<fileline> yP_NOR "~|"
%token<fileline> yP_XNOR "^~"
%token<fileline> yP_NAND "~&"
%token<fileline> yP_EQUAL "=="
%token<fileline> yP_NOTEQUAL "!="
%token<fileline> yP_CASEEQUAL "==="
%token<fileline> yP_CASENOTEQUAL "!=="
%token<fileline> yP_WILDEQUAL "==?"
%token<fileline> yP_WILDNOTEQUAL "!=?"
%token<fileline> yP_GTE ">="
%token<fileline> yP_LTE "<="
%token<fileline> yP_SLEFT "<<"
%token<fileline> yP_SRIGHT ">>"
%token<fileline> yP_SSRIGHT ">>>"
%token<fileline> yP_POW "**"
%token<fileline> yP_PLUSCOLON "+:"
%token<fileline> yP_MINUSCOLON "-:"
%token<fileline> yP_MINUSGT "->"
%token<fileline> yP_MINUSGTGT "->>"
%token<fileline> yP_EQGT "=>"
%token<fileline> yP_ASTGT "*>"
%token<fileline> yP_ANDANDAND "&&&"
%token<fileline> yP_POUNDPOUND "##"
%token<fileline> yP_DOTSTAR ".*"
%token<fileline> yP_ATAT "@@"
%token<fileline> yP_COLONCOLON "::"
%token<fileline> yP_COLONEQ ":="
%token<fileline> yP_COLONDIV ":/"
%token<fileline> yP_ORMINUSGT "|->"
%token<fileline> yP_OREQGT "|=>"
%token<fileline> yP_PLUSEQ "+="
%token<fileline> yP_MINUSEQ "-="
%token<fileline> yP_TIMESEQ "*="
%token<fileline> yP_DIVEQ "/="
%token<fileline> yP_MODEQ "%="
%token<fileline> yP_ANDEQ "&="
%token<fileline> yP_OREQ "|="
%token<fileline> yP_XOREQ "^="
%token<fileline> yP_SLEFTEQ "<<="
%token<fileline> yP_SRIGHTEQ ">>="
%token<fileline> yP_SSRIGHTEQ ">>>="
%token<fileline> yPSL_BRA "{"
%token<fileline> yPSL_KET "}"
%token<fileline> yP_LOGIFF
%token<fileline> ';' '=' ',' '(' '.' '!' '~' '[' '@'
%token<fileline> '!'
%token<fileline> '#'
%token<fileline> '%'
%token<fileline> '&'
%token<fileline> '('
%token<fileline> ')'
%token<fileline> '*'
%token<fileline> '+'
%token<fileline> ','
%token<fileline> '-'
%token<fileline> '.'
%token<fileline> '/'
%token<fileline> ':'
%token<fileline> ';'
%token<fileline> '<'
%token<fileline> '='
%token<fileline> '>'
%token<fileline> '?'
%token<fileline> '@'
%token<fileline> '['
%token<fileline> ']'
%token<fileline> '^'
%token<fileline> '{'
%token<fileline> '|'
%token<fileline> '}'
%token<fileline> '~'
// [* is not a operator, as "[ * ]" is legal
// [= and [-> could be repitition operators, but to match [* we don't add them.
// '( is not a operator, as "' (" is legal
// '{ could be an operator. More research needed.
//********************
// PSL op precedence
%right<fileline> yP_LOGIF yP_LOGIFF
%right<fileline> yP_OR_MINUS_GT yP_OR_EQ_GT
%left<fileline> prPSLCLK
%right yP_MINUSGT yP_LOGIFF
%right yP_ORMINUSGT yP_OREQGT
%left<fileline> prPSLCLK
// Verilog op precedence
%left<fileline> ':'
%left<fileline> '?'
%left<fileline> yP_OROR
%left<fileline> yP_ANDAND
%left<fileline> '|' yP_NOR
%left<fileline> '^'
%left<fileline> yP_XNOR
%left<fileline> '&' yP_NAND
%left<fileline> yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL
%left<fileline> '>' '<' yP_GTE yP_LTE
%left<fileline> yP_SLEFT yP_SRIGHT yP_SSRIGHT
%left<fileline> '+' '-'
%left<fileline> '*' '/' '%'
%left<fileline> yP_POW
%left<fileline> '{' '}'
%left<fileline> prUNARYARITH
%left<fileline> prREDUCTION
%left<fileline> prNEGATION
%left ':'
%left '?'
%left yP_OROR
%left yP_ANDAND
%left '|' yP_NOR
%left '^'
%left yP_XNOR
%left '&' yP_NAND
%left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
%left '>' '<' yP_GTE yP_LTE
%left yP_SLEFT yP_SRIGHT yP_SSRIGHT
%left '+' '-'
%left '*' '/' '%'
%left yP_POW
%left '{' '}'
%left<fileline> prUNARYARITH
%left<fileline> prREDUCTION
%left<fileline> prNEGATION
%nonassoc prLOWER_THAN_ELSE
%nonassoc yELSE
@@ -289,11 +377,13 @@ class AstSenTree;
%type<modulep> modHdr
%type<nodep> modPortsE portList port
%type<nodep> portV2kArgs portV2kList portV2kSecond portV2kSig
%type<nodep> portV2kDecl ioDecl varDecl
%type<nodep> modParDecl modParList modParE
%type<nodep> portV2kDecl portDecl varDecl
%type<nodep> modParArgs modParSecond modParDecl modParList modParE
%type<nodep> modItem modItemList modItemListE modOrGenItem
%type<nodep> generateRegion
%type<nodep> genItem genItemList genItemBegin genItemBlock genTopBlock genCaseListE genCaseList
%type<nodep> dlyTerm
%type<fileline> delay
%type<varp> sigAndAttr sigId sigIdRange sigList regsig regsigList regSigId
%type<varp> netSig netSigList
%type<rangep> rangeListE regrangeE anyrange rangeList delayrange portRangeE
@@ -303,8 +393,8 @@ class AstSenTree;
%type<cellp> instnameParen
%type<pinp> cellpinList cellpinItList cellpinItemE instparamListE
%type<nodep> defpList defpOne
%type<sentreep> sensitivity
%type<sentreep> sensitivityE
%type<sentreep> eventControl
%type<sentreep> eventControlE
%type<senitemp> senList senitem senitemEdge senitemVar
%type<nodep> stmtBlock stmtList stmt labeledStmt stateCaseForIf
%type<nodep> assertStmt
@@ -355,14 +445,19 @@ statePop: /* empty */ { V3Read::statePop(); }
//**********************************************************************
// Files
file: mod { }
| file mod { }
file: description { }
| file description { }
;
// IEEE: description
description: moduleDecl { }
;
//**********************************************************************
// Module headers
mod: modHdr modParE modPortsE ';' modItemListE yENDMODULE
// IEEE: module_declaration:
moduleDecl: modHdr modParE modPortsE ';' modItemListE yENDMODULE endLabelE
{ $1->modTrace(V3Parse::s_trace); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); }
;
@@ -375,12 +470,20 @@ modHdr: yMODULE { V3Parse::s_trace=v3Global.opt.trace();}
modParE: /* empty */ { $$ = NULL; }
| '#' '(' ')' { $$ = NULL; }
| '#' '(' modParList ')' { $$ = $3; }
| '#' '(' modParList ';' ')' { $$ = $3; }
| '#' '(' modParArgs ')' { $$ = $3; }
;
modParList: modParDecl { $$ = $1; }
| modParList ';' modParDecl { $$ = $1->addNext($3); }
modParArgs: modParDecl { $$ = $1; }
| modParDecl ',' modParList { $$ = $1->addNext($3); }
;
modParList: modParSecond { $$ = $1; }
| modParList ',' modParSecond { $$ = $1->addNext($3); }
;
// Called only after a comma in a v2k list, to allow parsing "parameter a,b, parameter x"
modParSecond: modParDecl { $$ = $1; }
| param { $$ = $1; }
;
modPortsE: /* empty */ { $$ = NULL; }
@@ -423,24 +526,25 @@ regsigList: regsig { $$ = $1; }
| regsigList ',' regsig { $$ = $1;$1->addNext($3); }
;
portV2kDecl: varRESET varInput varSignedE v2kNetDeclE regrangeE portV2kSig { $$ = $6; }
| varRESET varInout varSignedE v2kNetDeclE regrangeE portV2kSig { $$ = $6; }
| varRESET varOutput varSignedE v2kVarDeclE regrangeE portV2kSig { $$ = $6; }
portV2kDecl: varRESET varInput signingE v2kNetDeclE regrangeE portV2kSig { $$ = $6; }
| varRESET varInout signingE v2kNetDeclE regrangeE portV2kSig { $$ = $6; }
| varRESET varOutput signingE v2kVarDeclE regrangeE portV2kSig { $$ = $6; }
;
ioDecl: varRESET varInput varSignedE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
| varRESET varInout varSignedE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
| varRESET varOutput varSignedE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
// IEEE: port_declaration - plus ';'
portDecl: varRESET varInput signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
| varRESET varInout signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
| varRESET varOutput signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; }
;
varDecl: varRESET varReg varSignedE regrangeE regsigList ';' { $$ = $5; }
| varRESET varGParam varSignedE regrangeE paramList ';' { $$ = $5; }
| varRESET varLParam varSignedE regrangeE paramList ';' { $$ = $5; }
| varRESET varNet varSignedE delayrange netSigList ';' { $$ = $5; }
| varRESET varGenVar varSignedE regsigList ';' { $$ = $4; }
varDecl: varRESET varReg signingE regrangeE regsigList ';' { $$ = $5; }
| varRESET varGParam signingE regrangeE paramList ';' { $$ = $5; }
| varRESET varLParam signingE regrangeE paramList ';' { $$ = $5; }
| varRESET varNet signingE delayrange netSigList ';' { $$ = $5; }
| varRESET varGenVar signingE regsigList ';' { $$ = $4; }
;
modParDecl: varRESET varGParam varSignedE regrangeE paramList { $$ = $5; } /* No semicolon*/
modParDecl: varRESET varGParam signingE regrangeE param { $$ = $5; }
;
varRESET: /* empty */ { VARRESET(); }
@@ -467,7 +571,8 @@ varOutput: yOUTPUT { VARIO(OUTPUT); }
varInout: yINOUT { VARIO(INOUT); }
;
varSignedE: /*empty*/ { }
// IEEE: signing - plus empty
signingE: /*empty*/ { }
| ySIGNED { VARSIGNED(true); }
| yUNSIGNED { VARSIGNED(false); }
;
@@ -492,7 +597,7 @@ modItemList: modItem { $$ = $1; }
;
modItem: modOrGenItem { $$ = $1; }
| yGENERATE genTopBlock yENDGENERATE { $$ = new AstGenerate($1, $2); }
| generateRegion { $$ = $1; }
| yaSCHDR { $$ = new AstScHdr(CRELINE(),*$1); }
| yaSCINT { $$ = new AstScInt(CRELINE(),*$1); }
| yaSCIMP { $$ = new AstScImp(CRELINE(),*$1); }
@@ -508,7 +613,11 @@ modItem: modOrGenItem { $$ = $1; }
| ySPECIFY yENDSPECIFY { $$ = NULL; }
;
modOrGenItem: yALWAYS sensitivityE stmtBlock { $$ = new AstAlways($1,$2,$3); }
// IEEE: generate_region
generateRegion: yGENERATE genTopBlock yENDGENERATE { $$ = new AstGenerate($1, $2); }
;
modOrGenItem: yALWAYS eventControlE stmtBlock { $$ = new AstAlways($1,$2,$3); }
| yFINAL stmtBlock { $$ = new AstFinal($1,$2); }
| yINITIAL stmtBlock { $$ = new AstInitial($1,$2); }
| yASSIGN delayE assignList ';' { $$ = $3; }
@@ -517,7 +626,7 @@ modOrGenItem: yALWAYS sensitivityE stmtBlock { $$ = new AstAlways($1,$2,$3); }
| taskDecl { $$ = $1; }
| funcDecl { $$ = $1; }
| gateDecl { $$ = $1; }
| ioDecl { $$ = $1; }
| portDecl { $$ = $1; }
| varDecl { $$ = $1; }
//No: | tableDecl // Unsupported
| pslStmt { $$ = $1; }
@@ -537,8 +646,8 @@ genTopBlock: genItemList { $$ = $1; }
genItemBegin: yBEGIN genItemList yEND { $$ = new AstBegin($1,"genblk",$2); }
| yBEGIN yEND { $$ = NULL; }
| yBEGIN ':' yaID genItemList yEND { $$ = new AstBegin($2,*$3,$4); }
| yBEGIN ':' yaID yEND { $$ = NULL; }
| yBEGIN ':' yaID genItemList yEND endLabelE { $$ = new AstBegin($2,*$3,$4); }
| yBEGIN ':' yaID yEND endLabelE { $$ = NULL; }
;
genItemList: genItem { $$ = $1; }
@@ -582,10 +691,10 @@ delayE: /* empty */ { }
| delay { } /* ignored */
;
delay: '#' dlyTerm { } /* ignored */
| '#' '(' dlyInParen ')' { } /* ignored */
| '#' '(' dlyInParen ',' dlyInParen ')' { } /* ignored */
| '#' '(' dlyInParen ',' dlyInParen ',' dlyInParen ')' { } /* ignored */
delay: '#' dlyTerm { $$ = $1; } /* ignored */
| '#' '(' dlyInParen ')' { $$ = $1; } /* ignored */
| '#' '(' dlyInParen ',' dlyInParen ')' { $$ = $1; } /* ignored */
| '#' '(' dlyInParen ',' dlyInParen ',' dlyInParen ')' { $$ = $1; } /* ignored */
;
dlyTerm: yaID { $$ = NULL; }
@@ -676,6 +785,7 @@ paramList: param { $$ = $1; }
| paramList ',' param { $$ = $1; $1->addNext($3); }
;
// IEEE: list_of_defparam_assignments
defpList: defpOne { $$ = $1; }
| defpList ',' defpOne { $$ = $1->addNext($3); }
;
@@ -712,7 +822,7 @@ cellpinItList: cellpinItemE { $$ = $1; }
;
cellpinItemE: /* empty: ',,' is legal */ { $$ = NULL; V3Parse::s_pinNum++; }
| '.' '*' { $$ = NULL; if (V3Parse::s_pinStar) $1->v3error("Duplicate .* in a cell"); V3Parse::s_pinStar=true; }
| yP_DOTSTAR { $$ = NULL; if (V3Parse::s_pinStar) $1->v3error("Duplicate .* in a cell"); V3Parse::s_pinStar=true; }
| '.' yaID { $$ = new AstPin($1,V3Parse::s_pinNum++,*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
| '.' yaID '(' ')' { $$ = NULL; V3Parse::s_pinNum++; }
| '.' yaID '(' expr ')' { $$ = new AstPin($1,V3Parse::s_pinNum++,*$2,$4); }
@@ -720,19 +830,19 @@ cellpinItemE: /* empty: ',,' is legal */ { $$ = NULL; V3Parse::s_pinNum++; }
;
//************************************************
// Sensitivity lists
// EventControl lists
sensitivityE: /* empty */ { $$ = NULL; }
| sensitivity { $$ = $1; }
eventControlE: /* empty */ { $$ = NULL; }
| eventControl { $$ = $1; }
//IEEE: event_control
sensitivity: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); }
// IEEE: event_control
eventControl: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); }
| '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */
| '@' '(' '*' ')' { $$ = NULL; $2->v3error("Use @*. always @ (*) to be depreciated in Verilog 2005.\n"); }
| '@' '*' { $$ = NULL; } /* Verilog 2001 */
;
//IEEE: event_expression - split over several
// IEEE: event_expression - split over several
senList: senitem { $$ = $1; }
| senList yOR senitem { $$ = $1;$1->addNext($3); }
| senList ',' senitem { $$ = $1;$1->addNext($3); } /* Verilog 2001 */
@@ -755,8 +865,8 @@ senitemEdge: yPOSEDGE varRefDotBit { $$ = new AstSenItem($1,AstEdgeType::POSED
stmtBlock: stmt { $$ = $1; }
| yBEGIN stmtList yEND { $$ = $2; }
| yBEGIN yEND { $$ = NULL; }
| beginNamed stmtList yEND { $$ = $1; $1->addStmtp($2); }
| beginNamed yEND { $$ = $1; }
| beginNamed stmtList yEND endLabelE { $$ = $1; $1->addStmtp($2); }
| beginNamed yEND endLabelE { $$ = $1; }
;
beginNamed: yBEGIN ':' yaID varDeclList { $$ = new AstBegin($2,*$3,$4); }
@@ -771,6 +881,8 @@ stmt: ';' { $$ = NULL; }
| labeledStmt { $$ = $1; }
| yaID ':' labeledStmt { $$ = new AstBegin($2, *$1, $3); } /*S05 block creation rule*/
| delay stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Ignoring delay on this delayed statement.\n"); }
| varRefDotBit yP_LTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); }
| varRefDotBit '=' delayE expr ';' { $$ = new AstAssign($2,$1,$4); }
| varRefDotBit '=' yD_FOPEN '(' expr ',' expr ')' ';' { $$ = new AstFOpen($3,$1,$5,$7); }
@@ -779,26 +891,26 @@ stmt: ';' { $$ = NULL; }
| '{' concIdList '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); }
| yD_C '(' cStrList ')' ';' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
| yD_FCLOSE '(' varRefDotBit ')' ';' { $$ = new AstFClose($1, $3); }
| yD_FINISH ';' { $$ = new AstFinish($1); }
| yD_STOP ';' { $$ = new AstStop($1); }
| yD_FINISH parenE ';' { $$ = new AstFinish($1); }
| yD_STOP parenE ';' { $$ = new AstStop($1); }
| yVL_COVER_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
| stateCaseForIf { $$ = $1; }
| taskRef ';' { $$ = $1; }
| yD_DISPLAY ';' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,"", NULL,NULL); }
| yD_DISPLAY parenE ';' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,"", NULL,NULL); }
| yD_DISPLAY '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$3,NULL,$4); }
| yD_WRITE '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$3,NULL,$4); }
| yD_FDISPLAY '(' varRefDotBit ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$5,$3,$6); }
| yD_FWRITE '(' varRefDotBit ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$5,$3,$6); }
| yD_INFO ';' { $$ = new AstDisplay($1,AstDisplayType::INFO, "", NULL,NULL); }
| yD_INFO parenE ';' { $$ = new AstDisplay($1,AstDisplayType::INFO, "", NULL,NULL); }
| yD_INFO '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::INFO, *$3,NULL,$4); }
| yD_WARNING ';' { $$ = new AstDisplay($1,AstDisplayType::WARNING,"", NULL,NULL); }
| yD_WARNING parenE ';' { $$ = new AstDisplay($1,AstDisplayType::WARNING,"", NULL,NULL); }
| yD_WARNING '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::WARNING,*$3,NULL,$4); }
| yD_ERROR ';' { $$ = V3Parse::createDisplayError($1); }
| yD_ERROR parenE ';' { $$ = V3Parse::createDisplayError($1); }
| yD_ERROR '(' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::ERROR, *$3,NULL,$4); $$->addNext(new AstStop($1)); }
| yD_FATAL ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); }
| yD_FATAL parenE ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
| yD_FATAL '(' expr ',' yaSTRING commaEListE ')' ';' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
| yD_READMEMB '(' expr ',' varRefMem ')' ';' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' varRefMem ',' expr ')' ';' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
@@ -858,16 +970,19 @@ taskRef: idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileli
funcRef: idDotted '(' exprList ')' { $$ = new AstFuncRef($2,new AstParseRef($1->fileline(), AstParseRefExp::FUNC, $1), $3); }
;
taskDecl: yTASK taskAutoE yaID funcGuts yENDTASK { $$ = new AstTask ($1,*$3,$4);}
taskDecl: yTASK lifetimeE yaID funcGuts yENDTASK endLabelE
{ $$ = new AstTask ($1,*$3,$4);}
;
funcDecl: yFUNCTION taskAutoE funcTypeE yaID funcGuts yENDFUNCTION { $$ = new AstFunc ($1,*$4,$5,$3); }
| yFUNCTION taskAutoE ySIGNED funcTypeE yaID funcGuts yENDFUNCTION { $$ = new AstFunc ($1,*$5,$6,$4); $$->isSigned(true); }
| yFUNCTION taskAutoE funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION { $$ = new AstFunc ($1,*$4,$6,$3); $$->attrIsolateAssign(true);}
| yFUNCTION taskAutoE ySIGNED funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION { $$ = new AstFunc ($1,*$5,$7,$4); $$->attrIsolateAssign(true); $$->isSigned(true); }
funcDecl: yFUNCTION lifetimeE funcTypeE yaID funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$5,$3); }
| yFUNCTION lifetimeE ySIGNED funcTypeE yaID funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$6,$4); $$->isSigned(true); }
| yFUNCTION lifetimeE funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$6,$3); $$->attrIsolateAssign(true);}
| yFUNCTION lifetimeE ySIGNED funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$7,$4); $$->attrIsolateAssign(true); $$->isSigned(true); }
;
taskAutoE: /* empty */ { }
// IEEE: lifetime - plus empty
lifetimeE: /* empty */ { }
| ySTATIC { $1->v3error("Unsupported: Static in this context\n"); }
| yAUTOMATIC { }
;
@@ -888,12 +1003,16 @@ funcVarList: funcVar { $$ = $1; }
| funcVarList funcVar { $$ = $1;$1->addNext($2); }
;
funcVar: ioDecl { $$ = $1; }
funcVar: portDecl { $$ = $1; }
| varDecl { $$ = $1; }
| yVL_PUBLIC { $$ = new AstPragma($1,AstPragmaType::PUBLIC_TASK); }
| yVL_NO_INLINE_TASK { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_TASK); }
;
parenE: /* empty */ { }
| '(' ')' { }
;
//************************************************
// Expressions
@@ -912,6 +1031,8 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$1,$3); }
| expr yP_NOTEQUAL expr { $$ = new AstNeq ($2,$1,$3); }
| expr yP_CASEEQUAL expr { $$ = new AstEqCase ($2,$1,$3); }
| expr yP_CASENOTEQUAL expr { $$ = new AstNeqCase ($2,$1,$3); }
| expr yP_WILDEQUAL expr { $$ = new AstEqWild ($2,$1,$3); }
| expr yP_WILDNOTEQUAL expr { $$ = new AstNeqWild ($2,$1,$3); }
| expr '>' expr { $$ = new AstGt ($2,$1,$3); }
| expr '<' expr { $$ = new AstLt ($2,$1,$3); }
| expr yP_GTE expr { $$ = new AstGte ($2,$1,$3); }
@@ -925,7 +1046,7 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$1,$3); }
| expr '/' expr { $$ = new AstDiv ($2,$1,$3); }
| expr '%' expr { $$ = new AstModDiv ($2,$1,$3); }
| expr yP_POW expr { $$ = new AstPow ($2,$1,$3); }
| expr yP_LOGIF expr { $$ = new AstLogIf ($2,$1,$3); }
| expr yP_MINUSGT expr { $$ = new AstLogIf ($2,$1,$3); }
| expr yP_LOGIFF expr { $$ = new AstLogIff ($2,$1,$3); }
| '-' expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); }
@@ -1093,6 +1214,7 @@ specifyJunk: dlyTerm {} /* ignored */
| '[' {} | ']' {}
| '|' {}
| '~' {}
| '@' {}
| yIF {}
| yNEGEDGE {}
@@ -1104,18 +1226,35 @@ specifyJunk: dlyTerm {} /* ignored */
| yP_ANDAND {} | yP_GTE {} | yP_LTE {}
| yP_EQUAL {} | yP_NOTEQUAL {}
| yP_CASEEQUAL {} | yP_CASENOTEQUAL {}
| yP_WILDEQUAL {} | yP_WILDNOTEQUAL {}
| yP_XNOR {} | yP_NOR {} | yP_NAND {}
| yP_OROR {}
| yP_SLEFT {} | yP_SRIGHT {} | yP_SSRIGHT {}
| yP_PLUSCOLON {} | yP_MINUSCOLON {}
| yP_POW {}
| yP_LOGIF {}
| yP_MINUSGT {}
| yP_LOGIFF {}
| yPSL_BRA {}
| yPSL_KET {}
| yP_OR_MINUS_GT {}
| yP_OR_EQ_GT {}
| yP_ORMINUSGT {}
| yP_OREQGT {}
| yP_EQGT {} | yP_ASTGT {}
| yP_ANDANDAND {}
| yP_MINUSGTGT {}
| yP_POUNDPOUND {}
| yP_DOTSTAR {}
| yP_ATAT {}
| yP_COLONCOLON {}
| yP_COLONEQ {}
| yP_COLONDIV {}
| yP_PLUSEQ {} | yP_MINUSEQ {}
| yP_TIMESEQ {}
| yP_DIVEQ {} | yP_MODEQ {}
| yP_ANDEQ {} | yP_OREQ {}
| yP_XOREQ {}
| yP_SLEFTEQ {} | yP_SRIGHTEQ {} | yP_SSRIGHTEQ {}
| error {}
;
@@ -1159,6 +1298,10 @@ concIdList: varRefDotBit { $$ = $1; }
| concIdList ',' varRefDotBit { $$ = new AstConcat($2,$1,$3); }
;
endLabelE: /* empty */ { }
| ':' yaID { }
;
//************************************************
// Asserts
@@ -1223,11 +1366,16 @@ pslExpr: exprPsl { $$ = new AstPslBool($1->fileline(), $1); }
//**********************************************************************
%%
void V3Read::parserClear() {
// Clear up any dynamic memory V3Parser required
V3Parse::setRange(NULL);
}
AstNode* V3Parse::createSupplyExpr(FileLine* fileline, string name, int value) {
FileLine* newfl = new FileLine (fileline);
newfl->warnOff(V3ErrorCode::WIDTH, true);
AstNode* nodep = new AstConst(newfl, V3Number(fileline));
// Adding a NOT is less work then figuring out how wide to make it
// Adding a NOT is less work than figuring out how wide to make it
if (value) nodep = new AstNot(newfl, nodep);
nodep = new AstAssignW(newfl, new AstVarRef(fileline, name, true),
nodep);
@@ -1237,6 +1385,7 @@ AstNode* V3Parse::createSupplyExpr(FileLine* fileline, string name, int value) {
AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* arrayp) {
AstVarType type = V3Parse::s_varIO;
AstRange* rangep = V3Parse::s_varRangep;
AstRange* cleanup_rangep = NULL;
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<V3Parse::s_varDecl.ascii()<<" io="<<V3Parse::s_varIO.ascii()<<endl);
if (type == AstVarType::UNKNOWN) type = V3Parse::s_varDecl;
if (type == AstVarType::UNKNOWN) fileline->v3fatalSrc("Unknown signal type declared");
@@ -1244,7 +1393,8 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array
if (type == AstVarType::INTEGER || V3Parse::s_varDecl == AstVarType::INTEGER
|| type == AstVarType::GENVAR) {
if (rangep) fileline->v3error("Integers may not be ranged: "<<name);
rangep = new AstRange(fileline, 31, 0); // Integer == REG[31:0]
cleanup_rangep = new AstRange(fileline, 31, 0); // Integer == REG[31:0]
rangep = cleanup_rangep;
}
if (type == AstVarType::GENVAR) {
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
@@ -1272,6 +1422,7 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array
// Remember the last variable created, so we can attach attributes to it in later parsing
V3Parse::s_varAttrp = nodep;
if (cleanup_rangep) { cleanup_rangep->deleteTree(); cleanup_rangep=NULL; }
return nodep;
}
+25
View File
@@ -560,6 +560,18 @@ sub _make_main {
print $fh " topp->eval();\n";
$set = "topp->";
}
my $traceit = ($self->{trace} && !$self->{sp} && !$self->{sc});
if ($traceit) {
$fh->print("\n");
$fh->print("#if VM_TRACE\n");
$fh->print(" Verilated::traceEverOn(true);\n");
$fh->print(" SpTraceVcdCFile* tfp = new SpTraceVcdCFile;\n");
$fh->print(" topp->trace (tfp, 99);\n");
$fh->print(" tfp->open (\"obj_dir/".$self->{name}."_simx.vcd\");\n");
$fh->print("#endif\n");
}
print $fh " ${set}fastclk = true;\n" if $self->{inputs}{fastclk};
print $fh " ${set}clk = true;\n" if $self->{inputs}{clk};
print $fh " while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {\n";
@@ -578,6 +590,11 @@ sub _make_main {
} else {
print $fh " main_time+=1;\n";
print $fh " ${set}eval();\n" if $action;
if ($traceit) {
$fh->print("#if VM_TRACE\n");
$fh->print(" tfp->dump (main_time);\n");
$fh->print("#endif //VM_TRACE\n");
}
}
}
print $fh " }\n";
@@ -586,6 +603,14 @@ sub _make_main {
print $fh " }\n";
print $fh " topp->final();\n";
print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage};
if ($traceit) {
$fh->print("#if VM_TRACE\n");
$fh->print(" tfp->close();\n");
$fh->print("#endif //VM_TRACE\n");
}
$fh->print("\n");
print $fh " delete topp; topp=NULL;\n";
print $fh " exit(0L);\n";
print $fh "}\n";
+2 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id:$
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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.
compile (
v_flags2 => [$Last_Self->{v3}?'-Wno-STMTDLY':''],
);
execute (
+2 -2
View File
@@ -1,4 +1,4 @@
// $Id:$
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
@@ -30,7 +30,7 @@ module t (/*AUTOARG*/
else if (cyc==3) begin
if (dly0 !== 32'h23) $stop;
$write("*-* All Finished *-*\n");
$finish;
#100 $finish;
end
end
+20
View File
@@ -0,0 +1,20 @@
#!/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_delay.v");
compile (
fails=>1,
expect=>
'%Warning-STMTDLY: t/t_delay.v:\d+: Ignoring delay on this delayed statement.
.*%Error: Exiting due to.*',
) if $Last_Self->{v3};
ok(1);
1;
+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 (
v_flags2 => [$Last_Self->{v3}?'--Ox':''],
);
execute (
check_finished=>1,
);
ok(1);
1;
+70
View File
@@ -0,0 +1,70 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
reg [2*32-1:0] w2; initial w2 = {2 {32'h12345678}};
reg [9*32-1:0] w9; initial w9 = {9 {32'h12345678}};
reg [10*32-1:0] w10; initial w10 = {10{32'h12345678}};
reg [11*32-1:0] w11; initial w11 = {11{32'h12345678}};
reg [15*32-1:0] w15; initial w15 = {15{32'h12345678}};
reg [31*32-1:0] w31; initial w31 = {31{32'h12345678}};
reg [47*32-1:0] w47; initial w47 = {47{32'h12345678}};
reg [63*32-1:0] w63; initial w63 = {63{32'h12345678}};
// Aggregate outputs into a single result vector
wire [63:0] result = (w2[63:0]
^ w9[64:1]
^ w10[65:2]
^ w11[66:3]
^ w15[67:4]
^ w31[68:5]
^ w47[69:6]
^ w63[70:7]);
// What checksum will we end up with
`define EXPECTED_SUM 64'h184cb39122d8c6e3
// 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
w2 <= w2 >> 1;
w9 <= w9 >> 1;
w10 <= w10 >> 1;
w11 <= w11 >> 1;
w15 <= w15 >> 1;
w31 <= w31 >> 1;
w47 <= w47 >> 1;
w63 <= w63 >> 1;
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
+21 -1
View File
@@ -13,9 +13,9 @@ module t (/*AUTOARG*/
integer cyc; initial cyc=1;
integer j;
integer hit_count;
reg [63:0] cam_lookup_hit_vector;
integer hit_count;
always @(/*AUTOSENSE*/cam_lookup_hit_vector) begin
hit_count = 0;
for (j=0; j < 64; j=j+1) begin
@@ -23,6 +23,22 @@ module t (/*AUTOARG*/
end
end
integer hit_count2;
always @(/*AUTOSENSE*/cam_lookup_hit_vector) begin
hit_count2 = 0;
for (j=63; j >= 0; j=j-1) begin
hit_count2 = hit_count2 + {31'h0, cam_lookup_hit_vector[j]};
end
end
integer hit_count3;
always @(/*AUTOSENSE*/cam_lookup_hit_vector) begin
hit_count3 = 0;
for (j=63; j > 0; j=j-1) begin
if (cam_lookup_hit_vector[j]) hit_count3 = hit_count3 + 32'd1;
end
end
reg [127:0] wide_for_index;
reg [31:0] wide_for_count;
always @(/*AUTOSENSE*/cam_lookup_hit_vector) begin
@@ -64,10 +80,14 @@ module t (/*AUTOARG*/
end
if (cyc==2) begin
if (hit_count != 32'd2) $stop;
if (hit_count2 != 32'd2) $stop;
if (hit_count3 != 32'd2) $stop;
cam_lookup_hit_vector <= 64'h01010010_00010001;
end
if (cyc==3) begin
if (hit_count != 32'd5) $stop;
if (hit_count2 != 32'd5) $stop;
if (hit_count3 != 32'd4) $stop;
if (wide_for_count != 32'h80) $stop;
end
if (cyc==9) begin
+1 -1
View File
@@ -44,7 +44,7 @@ module t;
reg [31:0] flocal;
flocal = 1;
global = global + flocal;
end
end : named // SystemVerilog end labels
end
endfunction
+18
View File
@@ -0,0 +1,18 @@
#!/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 (
);
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;
integer cyc=0;
Testit testit (/*AUTOINST*/
// Inputs
.clk (clk));
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc==0) begin
end
else if (cyc<10) begin
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Testit (clk);
input clk;
genvar igen;
generate
for (igen=0; igen<0; igen=igen+1) begin : test_gen
always @ (posedge clk) begin
$display("igen1 = %d", igen);
$stop;
end
end
endgenerate
endmodule
+2
View File
@@ -85,6 +85,8 @@ module t (/*AUTOARG*/
if (qq !== {61{1'bx}}) $stop;
if (rq !== {61{1'bx}}) $stop;
`endif
if ({16{1'bx}} !== 16'd1/16'd0) $stop; // No div by zero errors
if ({16{1'bx}} !== 16'd1%16'd0) $stop; // No div by zero errors
end
if (cyc==19) begin
$write("*-* All Finished *-*\n");
+18
View File
@@ -0,0 +1,18 @@
#!/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 (
);
execute (
check_finished=>1,
);
ok(1);
1;
+81
View File
@@ -0,0 +1,81 @@
// $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 [31:0] in = crc[31:0];
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [3:0] out; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.out (out[3:0]),
// Inputs
.clk (clk),
.in (in[31:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0, out};
// What checksum will we end up with
`define EXPECTED_SUM 64'h1a0d07009b6a30d2
// 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
out,
// Inputs
clk, in
);
input clk;
input [31:0] in;
output [3:0] out;
assign out[0] = in[3:0] ==? 4'b1001;
assign out[1] = in[3:0] !=? 4'b1001;
assign out[2] = in[3:0] ==? 4'bx01x;
assign out[3] = in[3:0] !=? 4'bx01x;
endmodule
+11
View File
@@ -263,6 +263,17 @@ module t (/*AUTOARG*/
//============================================================
reg signed [ 5:0] W123_is_3f ; //=3F
always @(posedge clk) begin
W123_is_3f <= 6'sh3f;
end
always @(posedge clk) begin
if (((~ ((32'sh088d1bcb) <<< W123_is_3f)) >>> 6'sh3f) != 32'shffffffff) if (check) $stop;
end
//============================================================
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
+9 -13
View File
@@ -1,4 +1,4 @@
// $Id:$
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
@@ -11,7 +11,10 @@ module t (/*AUTOARG*/
parameter PAR = 3;
input clk;
`ifdef verilator
// Else it becomes a localparam, per IEEE 4.10.1, but we don't check it
defparam m3.FROMDEFP = 19;
`endif
m3 #(.P3(PAR),
.P2(2))
@@ -29,14 +32,12 @@ module t (/*AUTOARG*/
endmodule
module m3
`ifdef verilator
#(
parameter UNCH = 99;
parameter P1 = 10;
parameter UNCH = 99,
parameter P1 = 10,
parameter P2 = 20,
P3 = 30;
P3 = 30
)
`endif
(/*AUTOARG*/
// Inputs
clk
@@ -44,13 +45,6 @@ module m3
input clk;
localparam LOC = 13;
`ifndef verilator // Vcs not compliant yet
parameter UNCH = 99;
parameter P1 = 10;
parameter P2 = 20;
parameter P3 = 30;
`endif
parameter FROMDEFP = 11;
initial begin
@@ -61,6 +55,8 @@ module m3
if (P1 !== 10) $stop;
if (P2 !== 2) $stop;
if (P3 !== 3) $stop;
`ifdef verilator
if (FROMDEFP !== 19) $stop;
`endif
end
endmodule
+1 -9
View File
@@ -1,4 +1,3 @@
`line 1 "t/t_preproc.v" 1
@@ -10,7 +9,6 @@
`line 9 "t/t_preproc.v" 0
`line 1 "t/t_preproc_inc2.v" 1
@@ -19,9 +17,7 @@ At file t/t_preproc_inc2.v line 4
`line 6 "t/t_preproc_inc2.v" 0
`line 1 "t/t_preproc_inc3.v" 1
`line 2 "inc3_a_filename_from_line_directive" 0
@@ -43,14 +39,10 @@ At file t/t_preproc_inc2.v line 4
`line 17 "inc3_a_filename_from_line_directive" 0
`line 18 "inc3_a_filename_from_line_directive" 2
`line 6 "t/t_preproc_inc2.v" 0
`line 7 "t/t_preproc_inc2.v" 2
`line 9 "t/t_preproc.v" 0
@@ -150,4 +142,4 @@ $display( "left side: \" right side\"" )
`line 95 "t/t_preproc.v" 0
Line_Preproc_Check 96
`line 97 "t/t_preproc.v" 2
+1 -2
View File
@@ -1,4 +1,3 @@
`line 1 "t/t_preproc_psl.v" 1
@@ -74,4 +73,4 @@ psl assert always sig!=90;
72
`line 73 "t/t_preproc_psl.v" 2
+1 -2
View File
@@ -1,4 +1,3 @@
`line 1 "t/t_preproc_psl.v" 1
@@ -74,4 +73,4 @@ psl assert always sig!=90;
72
`line 73 "t/t_preproc_psl.v" 2
+1
View File
@@ -18,6 +18,7 @@ execute (
if ($Last_Self->{v3}) {
file_grep ("obj_dir/Vt_trace_ena__Trace__Slow.cpp", qr/c_trace_on\"/x);
file_grep_not ("obj_dir/Vt_trace_ena__Trace__Slow.cpp", qr/_trace_off\"/x);
file_grep ("obj_dir/t_trace_ena_simx.vcd", qr/\$enddefinitions/x);
}
ok(1);
+1 -1
View File
@@ -58,7 +58,7 @@ module t_arith(/*AUTOARG*/
if (( 1'b0 ? 3'h3 : 1'b0 ? 3'h2 : 1'b1 ? 3'h1 : 3'h0) !== 3'h1) $stop;
// verilator lint_off WIDTH
// surefire lint_off CNDWID
if (( 8'h10 + 1'b0 ? 8'he : 8'hf) !== 8'he) $stop; // + is higher then ?
if (( 8'h10 + 1'b0 ? 8'he : 8'hf) !== 8'he) $stop; // + is higher than ?
// surefire lint_on CNDWID
// verilator lint_on WIDTH