mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 00:23:35 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f23203dc96 | ||
|
|
a94f1c779b | ||
|
|
6412aff82d | ||
|
|
99bc1f92c9 | ||
|
|
891edad53a | ||
|
|
98e35b02ad | ||
|
|
8075372675 | ||
|
|
10e34ca48e | ||
|
|
329808afff | ||
|
|
7fc3e6c168 | ||
|
|
199b32709c | ||
|
|
1775da5f43 | ||
|
|
45c202f78f | ||
|
|
a77b58dba9 | ||
|
|
c300ab6dd9 | ||
|
|
9ac0f1accb | ||
|
|
7990e5d4b1 | ||
|
|
fb2cb3c49d | ||
|
|
c4b1bc2506 | ||
|
|
551393d443 | ||
|
|
79d305f3e8 | ||
|
|
822956e769 | ||
|
|
a681a6a6d5 | ||
|
|
5f6d69affd |
@@ -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
@@ -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
|
||||
#
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ RAW_OBJS = \
|
||||
V3DepthBlock.o \
|
||||
V3Descope.o \
|
||||
V3EmitC.o \
|
||||
V3EmitCInlines.o \
|
||||
V3EmitCSyms.o \
|
||||
V3EmitMk.o \
|
||||
V3EmitV.o \
|
||||
|
||||
+21
-2
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
class V3EmitC {
|
||||
public:
|
||||
static void emitc();
|
||||
static void emitcInlines();
|
||||
static void emitcSyms();
|
||||
static void emitcTrace();
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Executable
+20
@@ -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;
|
||||
Executable
+19
@@ -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;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -44,7 +44,7 @@ module t;
|
||||
reg [31:0] flocal;
|
||||
flocal = 1;
|
||||
global = global + flocal;
|
||||
end
|
||||
end : named // SystemVerilog end labels
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
Executable
+18
@@ -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;
|
||||
@@ -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
|
||||
@@ -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");
|
||||
|
||||
Executable
+18
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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,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,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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user