mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +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 | ||
|
|
4a9bea6980 | ||
|
|
bfddd80f43 | ||
|
|
84a778719a | ||
|
|
829d80d5b5 | ||
|
|
d6a5c97f3a | ||
|
|
4ba00bd256 | ||
|
|
c18f9da400 | ||
|
|
5b620a8dc5 | ||
|
|
9c968c590c | ||
|
|
dff5d5c4e4 | ||
|
|
1265e8cce8 | ||
|
|
2b5d7eeb50 | ||
|
|
bb9ae89049 | ||
|
|
72832a2810 | ||
|
|
18cb210eac | ||
|
|
2c5a183368 | ||
|
|
386f0a75df | ||
|
|
ea26482154 | ||
|
|
3aee7f918a | ||
|
|
b3dd18b215 | ||
|
|
a77e331e89 | ||
|
|
6f414ee9e2 | ||
|
|
8d56b498d1 | ||
|
|
871c1853bf | ||
|
|
f8cd3a785c | ||
|
|
6a6995187e | ||
|
|
a216c1e7e4 | ||
|
|
ea8445d187 | ||
|
|
77261cce5b | ||
|
|
78db712438 | ||
|
|
749302acb8 | ||
|
|
cbf52bb5d0 | ||
|
|
d2ce499b59 | ||
|
|
01e9bc4855 | ||
|
|
28d5e425a9 | ||
|
|
eae1f380cd | ||
|
|
e7280d7237 | ||
|
|
78997ee13c | ||
|
|
79ab50d84f | ||
|
|
98282114c9 | ||
|
|
d6cb175f96 | ||
|
|
b4d9eb6ec4 | ||
|
|
fabbfbc46e | ||
|
|
c7d80f8cf8 | ||
|
|
c70add7d0f | ||
|
|
44fe8741f3 | ||
|
|
f8680cf5c2 | ||
|
|
24c3424e51 | ||
|
|
bd264006ef |
@@ -3,17 +3,117 @@ 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.
|
||||
|
||||
**** Support V2K portlists with "input a,b,...". [Mark Nodine]
|
||||
|
||||
**** Support V2K function/task argument lists.
|
||||
|
||||
**** Optimize constant $display arguments.
|
||||
|
||||
**** Fixed Preprocessor dropping some `line directives. [Mark Nodine]
|
||||
|
||||
* Verilator 3.651 5/22/2007
|
||||
|
||||
*** Added verilator_profcfunc utility. [Gene Weber]
|
||||
|
||||
*** Treat modules within `celldefine and `endcelldefine as if in library.
|
||||
|
||||
*** Support functions which return integers. [Mark Nodine]
|
||||
|
||||
**** Warn if flex is not installed. [Ralf Karge]
|
||||
|
||||
**** Ignore `protect and `endprotect.
|
||||
|
||||
**** Allow empty case/endcase blocks.
|
||||
|
||||
* Verilator 3.650 4/20/2007
|
||||
|
||||
** Add --compiler msvc option. This is now required when Verilated code
|
||||
is to be run through MSVC++. This also enables fixing MSVC++ error
|
||||
C1061, blocks nested too deeply. [Ralf Karge]
|
||||
|
||||
** Add --lint-only option, to lint without creating other output.
|
||||
|
||||
*** Add /*verilator lint_save*/ and /*verilator lint_restore*/ to allow
|
||||
friendly control over re-enabling lint messages. [Gerald Williams]
|
||||
|
||||
*** Support SystemVerilog .name and .* interconnect.
|
||||
|
||||
*** Support while and do-while loops.
|
||||
|
||||
*** Use $(LINK) instead of $(CXX) for Makefile link rules. [Gerald Williams]
|
||||
|
||||
*** Add USER_CPPFLAGS and USER_LDFLAGS to Makefiles. [Gerald Williams]
|
||||
|
||||
**** Fixed compile errors under Windows MINGW compiler. [Gerald Williams]
|
||||
|
||||
**** Fixed dotted bit reference to local memory. [Eugene Weber]
|
||||
|
||||
**** Fixed 3.640 `verilog forcing IEEE 1364-1995 only. [David Hewson]
|
||||
|
||||
* Verilator 3.640 3/12/2007
|
||||
|
||||
*** Support Verilog 2005 `begin_keywords and `end_keywords.
|
||||
|
||||
*** Updated list of SystemVerilog keywords to correspond to IEEE 1800-2005.
|
||||
|
||||
*** Add /*verilator public_flat*/. [Eugene Weber]
|
||||
|
||||
**** Try all +libext's in the exact order given. [Michael Shinkarovsky]
|
||||
|
||||
**** Fixed elimination of public signals assigned to constants. [Eugene Weber]
|
||||
|
||||
**** Fixed internal error when public for loop has empty body. [David Addison]
|
||||
|
||||
**** Fixed "Loops detected" assertion when model exceeds 4GB. [David Hewson]
|
||||
|
||||
**** Fixed display %m names inside named blocks.
|
||||
|
||||
* Verilator 3.633 2/7/2007
|
||||
|
||||
*** Add --trace-depth option for minimizing VCD file size. [Emerson Suguimoto]
|
||||
|
||||
*** With VL_DEBUG, show wires causing convergance errors. [Mike Shinkarovsky]
|
||||
*** 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
|
||||
|
||||
@@ -24,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
|
||||
|
||||
@@ -40,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
|
||||
|
||||
@@ -64,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
|
||||
|
||||
@@ -83,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
|
||||
|
||||
@@ -95,34 +195,34 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
**** Removed coverage request variable; see Coverage limitations in docs.
|
||||
|
||||
**** Fix DOS carrage 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
|
||||
|
||||
*** Added --inhibit-sim flag for environments using old __Vm_inhibitSim.
|
||||
|
||||
*** Added `systemc_dtor for destructor extentions. [Allan Cochrane]
|
||||
*** Added `systemc_dtor for destructor extensions. [Allan Cochrane]
|
||||
|
||||
*** Added -MP to make phony dependencies, ala GCC's.
|
||||
|
||||
*** 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.
|
||||
|
||||
@@ -132,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 whitespace 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.
|
||||
|
||||
@@ -150,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
|
||||
|
||||
@@ -166,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
|
||||
|
||||
@@ -195,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
|
||||
|
||||
@@ -211,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
|
||||
|
||||
@@ -224,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 bitselects and rotate. [Prabhat Gupta]
|
||||
**** Fixed bad deep expressions with bit-selects and rotate. [Prabhat Gupta]
|
||||
|
||||
* Verilator 3.500 10/30/2005 Stable
|
||||
|
||||
@@ -259,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
|
||||
|
||||
@@ -292,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
|
||||
|
||||
@@ -302,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
|
||||
|
||||
@@ -310,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
|
||||
|
||||
@@ -331,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.
|
||||
|
||||
@@ -354,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
|
||||
|
||||
@@ -362,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
|
||||
|
||||
@@ -994,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
|
||||
|
||||
@@ -1009,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,12 +25,13 @@ 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
|
||||
C-style function and task arguments. [Wim Michiels]
|
||||
(* *) Attributes (just ignore -- preprocessor?)
|
||||
Real numbers (NEVER)
|
||||
Recursive functions (NEVER)
|
||||
Verilog configuration files (NEVER)
|
||||
DPI to define C/C++ calls from Verilog
|
||||
|
||||
Long-term Features
|
||||
Assertions
|
||||
@@ -47,6 +48,10 @@ Testing:
|
||||
Better graph viewer with search and zoom
|
||||
Port and test against opencores.org code
|
||||
|
||||
Usability:
|
||||
Better reporting of unopt problems, including what lines of code
|
||||
Report more errors (all of them?) before exiting [Eugene Weber]
|
||||
|
||||
Performance:
|
||||
Constant propagation
|
||||
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
||||
@@ -99,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
|
||||
|
||||
|
||||
+378
-67
@@ -191,6 +191,7 @@ Verilator - Convert Verilog code to C++/SystemC
|
||||
verilator --cc [options] [top_level.v] [opt_c_files.cpp/c/cc]
|
||||
verilator --sc [options] [top_level.v] [opt_c_files.cpp/c/cc]
|
||||
verilator --sp [options] [top_level.v] [opt_c_files.cpp/c/cc]
|
||||
verilator --lint-only ...
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@@ -213,6 +214,66 @@ C++, and linked with the Verilated files.
|
||||
|
||||
The resulting executable will perform the actual simulation.
|
||||
|
||||
=head1 ARGUMENT SUMMARY
|
||||
|
||||
This is a short summary of the arguments to Verilator. See the detailed
|
||||
descriptions in the next sections for more information.
|
||||
|
||||
{file.v} Verilog top level filenames
|
||||
{file.c/cc/cpp} Optional C++ files to link in
|
||||
|
||||
--assert Enable all assertions
|
||||
--bin <filename> Override Verilator binary
|
||||
--cc Create C++ output
|
||||
--compiler <compiler-name> Tune for specified C++ compiler
|
||||
--coverage Enable all coverage
|
||||
--coverage-line Enable line coverage
|
||||
--coverage-user Enable PSL/SVL user coverage
|
||||
-D<var>[=<value>] Set preprocessor define
|
||||
--debug Enable debugging
|
||||
--debug-check Enable debugging assertions
|
||||
--dump-tree Enable dumping .tree files
|
||||
-E Preprocess, but do not compile
|
||||
--exe Link to create executable
|
||||
-f <file> Parse options from a file
|
||||
--help Display this help.
|
||||
-I<dir> Directory to search for includes
|
||||
--inhibit-sim Create function to turn off sim
|
||||
--inline-mult <value> Tune module inlining
|
||||
--lint-only Lint, but do not make output
|
||||
--MMD Create .d dependency files
|
||||
--MP Create phony dependency targets
|
||||
--Mdir <directory> Name of output object directory
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--no-skip-identical Disable skipping identical output
|
||||
-O0 Disable optimizations
|
||||
-O3 High performance optimizations
|
||||
-O<optimization-letter> Selectable optimizations
|
||||
--output-split <bytes> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split .ccp functions
|
||||
--pins64 Use uint64_t's for 33-64 bit sigs
|
||||
--prefix <topname> Name of top level class
|
||||
--profile-cfuncs Name functions for profiling
|
||||
--private Debugging; see docs
|
||||
--psl Enable PSL parsing
|
||||
--public Debugging; see docs
|
||||
--sc Create SystemC output
|
||||
--sp Create SystemPerl output
|
||||
--stats Create statistics file
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
-U<var> Undefine preprocessor define
|
||||
--underline-zero Zero signals with leading _'s
|
||||
-v <filename> Verilog library
|
||||
-Werror-<message> Convert warning to error
|
||||
-Wno-<message> Disable warning
|
||||
-x-assign <mode> Initially assign Xs to this value
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
+define+<var>+<value> Set preprocessor define
|
||||
+incdir+<dir> Directory to search for includes
|
||||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
@@ -245,6 +306,27 @@ output files.
|
||||
|
||||
Specifies C++ without SystemC output mode; see also --sc and --sp.
|
||||
|
||||
=item --compiler I<compiler-name>
|
||||
|
||||
Enables tunings and work-arounds for the specified C++ compiler.
|
||||
|
||||
=over 4
|
||||
|
||||
=item gcc
|
||||
|
||||
Tune for Gnu C++, although generated code should work on almost any
|
||||
compliant C++ compiler. Currently the default.
|
||||
|
||||
=item msvc
|
||||
|
||||
Tune for Microsoft Visual C++. This may reduce execution speed as it
|
||||
enables several workarounds to avoid silly hardcoded limits in MSVC++.
|
||||
This includes breaking deeply nested parenthesized expressions into
|
||||
sub-expressions to avoid error C1009, and breaking deep blocks into
|
||||
functions to avoid error C1061.
|
||||
|
||||
=back
|
||||
|
||||
=item --coverage
|
||||
|
||||
Enables all forms of coverage, alias for --coverage-line, --coverage-user
|
||||
@@ -298,6 +380,12 @@ internal assertions, debugging messages, and intermediate form dump files.
|
||||
Rarely needed. Enable internal debugging assertion checks, without
|
||||
changing debug verbosity. Enabled automatically when --debug specified.
|
||||
|
||||
=item --dump-tree
|
||||
|
||||
Rarely needed. Enable writing .tree debug files. This is enabled with
|
||||
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
|
||||
large and not desired.
|
||||
|
||||
=item -E
|
||||
|
||||
Preprocess the source code, but do not compile, as with 'gcc -E'. Output
|
||||
@@ -323,11 +411,15 @@ 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 -1 to inline everything, will lead to longer compile times, but
|
||||
potentially faster runtimes. This setting is ignored for very small
|
||||
modules; they will always be inlined, if allowed.
|
||||
values, or a value <= 1 will inline everything, will lead to longer compile
|
||||
times, but potentially faster runtimes. This setting is ignored for very
|
||||
small modules; they will always be inlined, if allowed.
|
||||
|
||||
=item --lint-only
|
||||
|
||||
Check the files for lint violations only, do not create any other output.
|
||||
|
||||
=item --MMD
|
||||
|
||||
@@ -423,8 +515,8 @@ enable functional coverage.
|
||||
|
||||
=item --public
|
||||
|
||||
This is only for debug, and may result in mis-simulation of generated
|
||||
clocks.
|
||||
This is only for historical debug use. Using it may result in
|
||||
mis-simulation of generated clocks.
|
||||
|
||||
Declares all signals and modules public. This will turn off signal
|
||||
optimizations as if all signals had a /*verilator public*/ comments and
|
||||
@@ -474,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
|
||||
@@ -551,6 +654,7 @@ We'll compile this example into C++.
|
||||
int main(int argc, char **argv, char **env) {
|
||||
Vour* top = new Vour;
|
||||
while (!Verilated::gotFinish()) { top->eval(); }
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
|
||||
@@ -604,13 +708,13 @@ This is an example similar to the above, but using SystemPerl.
|
||||
|
||||
cat <<EOF >sc_main.cpp
|
||||
#include "Vour.h"
|
||||
#include "systemperl.h"
|
||||
int sc_main(int argc, char **argv) {
|
||||
sc_clock clk ("clk",10, 0.5, 3, true);
|
||||
Vour* top;
|
||||
SP_CELL (top, Vour);
|
||||
SP_PIN (top, clk, clk);
|
||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||
while (!Verilated::gotFinish()) { sc_start(1); }
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
|
||||
@@ -685,11 +789,13 @@ fast path, mostly code that is executed every cycle. OPT_SLOW specifies
|
||||
optimizations for slow-path files (plus tracing), which execute only
|
||||
rarely, yet take a long time to compile with optimization on. OPT
|
||||
specifies overall optimization and affects all compiles, including those
|
||||
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2". Nearly the
|
||||
same results can be had with much better compile times with OPT_FAST="-O1
|
||||
-fstrict-aliasing". Unfortunately, using the optimizer with SystemC files
|
||||
can result in compiles taking several minutes. (The SystemC libraries have
|
||||
many little inlined functions that drive the compiler nuts.)
|
||||
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
|
||||
with "-static". Nearly the same results can be had with much better
|
||||
compile times with OPT_FAST="-O1 -fstrict-aliasing".
|
||||
|
||||
Unfortunately, using the optimizer with SystemC files can result in
|
||||
compiles taking several minutes. (The SystemC libraries have many little
|
||||
inlined functions that drive the compiler nuts.)
|
||||
|
||||
For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have
|
||||
optimization bugs around pointer aliasing detection, which can result in 2x
|
||||
@@ -701,16 +807,19 @@ feedback driven compilation. With GCC, using -fprofile-arcs, then
|
||||
|
||||
You may uncover further tuning possibilities by profiling the Verilog code.
|
||||
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
|
||||
either oprofile or gprof to see where in the C++ code, and by looking at
|
||||
the mangled function name where in the Verilog code most of the time is
|
||||
being spent.
|
||||
either oprofile or gprof to see where in the C++ code the time is spent.
|
||||
Run the gprof output through verilator_profcfunc and it will tell you what
|
||||
Verilog line numbers on which most of the time is being spent.
|
||||
|
||||
When done, please let the author know the results. I like to keep tabs on
|
||||
how Verilator compares, and may be able to suggest additional improvements.
|
||||
|
||||
=head1 FILES
|
||||
|
||||
Verilator creates the following files:
|
||||
All output files are placed in the output directory name specified with the
|
||||
-Mdir option, or "obj_dir" if not specified.
|
||||
|
||||
Verilator creates the following files in the output directory:
|
||||
|
||||
{prefix}.mk // Make include file for compiling
|
||||
{prefix}_classes.mk // Make include file with class names
|
||||
@@ -722,13 +831,14 @@ For -cc and -sc mode, it also creates:
|
||||
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files
|
||||
{prefix}{each_verilog_module}.h // Lower level internal header files
|
||||
|
||||
For -sp mode, it also creates:
|
||||
For -sp mode, instead of .cpp and .h it creates:
|
||||
|
||||
{prefix}.sp // Top level SystemC file
|
||||
{prefix}{each_verilog_module}.sp // Lower level internal SC files
|
||||
|
||||
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
|
||||
@@ -744,7 +854,8 @@ It also creates internal files that can be mostly ignored:
|
||||
{prefix}{misc}.dot // Debugging graph files (--debug)
|
||||
{prefix}{misc}.tree // Debugging files (--debug)
|
||||
|
||||
After running Make, the compiler will produce the following:
|
||||
After running Make, the C++ compiler should produce the following:
|
||||
|
||||
{prefix} // Final executable (w/--exe argument)
|
||||
{prefix}__ALL.a // Library of all Verilated objects
|
||||
{prefix}{misc}.o // Intermediate objects
|
||||
@@ -884,37 +995,55 @@ 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
|
||||
Makefiles produced by Verilator presume the target system is the same type
|
||||
as the build system.
|
||||
|
||||
=head1 VERILOG 2001 SUPPORT
|
||||
=head1 VERILOG 2001 (IEEE 1364-2001) SUPPORT
|
||||
|
||||
Verilator supports the more common Verilog 2001 language features. This
|
||||
Verilator supports almost all Verilog 2001 language features. This
|
||||
includes signed numbers, "always @*", comma separated sensitivity lists,
|
||||
generate statements, multidimensional arrays, localparam, and C-style
|
||||
declarations inside port lists.
|
||||
|
||||
=head1 SYSTEMVERILOG 3.1 SUPPORT
|
||||
=head1 VERILOG 2005 (IEEE 1364-2005) SUPPORT
|
||||
|
||||
Verilator currently has very minimal support for SystemVerilog.
|
||||
Verilator supports the `begin_keywords and `end_keywords compiler
|
||||
directives.
|
||||
|
||||
Verilator implement the full SystemVerilog 3.1 preprocessor subset,
|
||||
including function call-like preprocessor defines. Verilator also
|
||||
implements $bits, $countones, $isunknown, $onehot, and $onehot0,
|
||||
always_comb, always_ff, always_latch, and final.
|
||||
Verilator partially supports the uwire keyword.
|
||||
|
||||
=head1 SYSTEMVERILOG (IEEE 1800-2005) SUPPORT
|
||||
|
||||
Verilator currently has very minimal support for SystemVerilog. As
|
||||
SystemVerilog features enter common usage they will be added. Contact the
|
||||
author if a feature you need is missing.
|
||||
|
||||
Verilator implements the full SystemVerilog 1800-2005 preprocessor,
|
||||
including function call-like preprocessor defines.
|
||||
|
||||
Verilator supports ==? and !=? operators, $bits, $countones, $error,
|
||||
$fatal, $info, $isunknown, $onehot, $onehot0, $warning, always_comb,
|
||||
always_ff, always_latch, do-while, and final.
|
||||
|
||||
It also supports .name and .* interconnection.
|
||||
|
||||
Verilator partially supports assert.
|
||||
|
||||
=head1 SUGAR/PSL SUPPORT
|
||||
|
||||
With the --assert switch, Verilator is just beginning to support the
|
||||
Property Specification Language (PSL), specifically the simple subset
|
||||
without time-branching primitives. Verilator currently only converts PSL
|
||||
Most future work is being directed towards improving SystemVerilog
|
||||
assertions instead of PSL. If you are using these PSL features, please
|
||||
contact the author as they may be depreciated in future versions.
|
||||
|
||||
With the --assert switch, Verilator enables support of the Property
|
||||
Specification Language (PSL), specifically the simple PSL subset without
|
||||
time-branching primitives. Verilator currently only converts PSL
|
||||
assertions to simple "if (...) error" statements, and coverage statements
|
||||
to increment the line counters described in the coverage section. If you
|
||||
need additional features please contact the author.
|
||||
to increment the line counters described in the coverage section.
|
||||
|
||||
Verilator implements these keywords: assert, assume (same as assert),
|
||||
default (for clocking), countones, cover, isunknown, onehot, onehot0,
|
||||
@@ -923,18 +1052,16 @@ report, true.
|
||||
Verilator implements these operators: -> (logical if).
|
||||
|
||||
Verilator does not support SEREs yet. All assertion and coverage
|
||||
statements must be simple expressions that complete in one cycle.
|
||||
(Arguably SEREs are the whole point of PSL, but one must start somewhere.)
|
||||
|
||||
PSL vmode/vprop/vunits are not supported. PSL statements must be in the
|
||||
module they reference, at the module level where you would put an
|
||||
statements must be simple expressions that complete in one cycle. PSL
|
||||
vmode/vprop/vunits are not supported. PSL statements must be in the module
|
||||
they reference, at the module level where you would put an
|
||||
initial... statement.
|
||||
|
||||
Verilator only supports (posedge CLK) or (negedge CLK), where CLK is the
|
||||
name of a one bit signal. You may not use arbitrary expressions as
|
||||
assertion clocks.
|
||||
|
||||
=head1 SYNTHESIS DIRECTIVE ASSERTIONS
|
||||
=head1 SYNTHESIS DIRECTIVE ASSERTION SUPPORT
|
||||
|
||||
With the --assert switch, Verilator reads any "//synopsys full_case" or "//
|
||||
synopsys parallel_case" directives. The same applies to any "//cadence" or
|
||||
@@ -983,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
|
||||
@@ -1060,7 +1187,9 @@ around compiler specific constructs.
|
||||
|
||||
=item `verilog
|
||||
|
||||
Switch back to processing Verilog code, after a `systemc_... mode switch.
|
||||
Switch back to processing Verilog code after a `systemc_... mode switch.
|
||||
The Verilog code returns to the last language mode specified with
|
||||
`begin_keywords, or SystemVerilog if none were specified.
|
||||
|
||||
=item /*verilator clock_enable*/
|
||||
|
||||
@@ -1126,7 +1255,27 @@ Disable the specified warning message for any warnings following the comment.
|
||||
|
||||
Re-enable the specified warning message for any warnings following the comment.
|
||||
|
||||
=item /*verilator no_inline_task*/
|
||||
=item /*verilator lint_restore*/
|
||||
|
||||
After a /*verilator lint_save*/, pop the stack containing lint message
|
||||
state. Often this is useful at the bottom of include files.
|
||||
|
||||
=item /*verilator lint_save*/
|
||||
|
||||
Push the current state of what lint messages are turned on or turned off to
|
||||
a stack. Later meta-comments may then lint_on or lint_off specific
|
||||
messages, then return to the earlier message state by using /*verilator
|
||||
lint_restore*/. For example:
|
||||
|
||||
// verilator lint_save
|
||||
// verilator lint_off SOME_WARNING
|
||||
... // code needing SOME_WARNING turned off
|
||||
// verilator lint_restore
|
||||
|
||||
If SOME_WARNING was on before the lint_off, it will now be restored to on,
|
||||
and if it was off before the lint_off it will remain off.
|
||||
|
||||
=item /*verilator no_inline_task*/
|
||||
|
||||
Used in a function or task variable definition section to specify the
|
||||
function or task should not be inlined into where it is used. This may
|
||||
@@ -1138,7 +1287,8 @@ be pure; they cannot reference any variables outside the task itself.
|
||||
|
||||
Used after a input, output, register, or wire declaration to indicate the
|
||||
signal should be declared so that C code may read or write the value
|
||||
of the signal.
|
||||
of the signal. This will also declare this module public, otherwise use
|
||||
/*verilator public_flat*/.
|
||||
|
||||
=item /*verilator public*/ (task/function)
|
||||
|
||||
@@ -1160,6 +1310,14 @@ stored state (flops) should be written, as the model will NOT notice
|
||||
changes made to variables in these functions. (Same as when a signal is
|
||||
declared public.)
|
||||
|
||||
=item /*verilator public_flat*/ (variable)
|
||||
|
||||
Used after a input, output, register, or wire declaration to indicate the
|
||||
signal should be declared so that C code may read or write the value of the
|
||||
signal. This will not declare this module public, which means the name of
|
||||
the signal or path to it may change based upon the module inlining which
|
||||
takes place.
|
||||
|
||||
=item /*verilator public_module*/
|
||||
|
||||
Used after a module statement to indicate the module should not be inlined
|
||||
@@ -1228,6 +1386,10 @@ users to use these names, so it should not matter.
|
||||
If you are having trouble determining where a dotted path goes wrong, note
|
||||
that Verilator will print a list of known scopes to help your debugging.
|
||||
|
||||
=head2 Floating Point
|
||||
|
||||
Floating Point numbers are not synthesizable, and so not supported.
|
||||
|
||||
=head2 Latches
|
||||
|
||||
Verilator is optimized for edge sensitive (flop based) designs. It will
|
||||
@@ -1280,17 +1442,12 @@ prepended. (If you don't know what this means, Verilator will do what you
|
||||
probably expect -- what C does. The default behavior of Verilog is
|
||||
different.)
|
||||
|
||||
=head2 Generate Statements
|
||||
|
||||
All instantiations and variables in generate blocks will be placed under
|
||||
hierarchy that has a name different from that required in the language
|
||||
specification.
|
||||
|
||||
=head2 Generated Clocks
|
||||
|
||||
Verilator attempts to deal with generated clocks correctly, however new
|
||||
cases may turn up bugs in the scheduling algorithm. The safest option is
|
||||
to have all clocks as primary inputs to the model.
|
||||
to have all clocks as primary inputs to the model, or wires directly
|
||||
attached to primary inputs.
|
||||
|
||||
=head2 Ranges must be big-bit-endian
|
||||
|
||||
@@ -1320,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
|
||||
@@ -1340,6 +1497,56 @@ will give a width warning and wrap around the power-of-2 size. For
|
||||
non-power-of-2 sizes, it will return a unspecified constant of the
|
||||
appropriate width.
|
||||
|
||||
=head2 Assertions
|
||||
|
||||
Verilator is beginning to add support for assertions. Verilator currently
|
||||
only converts assertions to simple "if (...) error" statements, and
|
||||
coverage statements to increment the line counters described in the
|
||||
coverage section.
|
||||
|
||||
Verilator does not support SEREs yet. All assertion and coverage
|
||||
statements must be simple expressions that complete in one cycle.
|
||||
(Arguably SEREs are much of the point, but one must start somewhere.)
|
||||
|
||||
=head1 LANGUAGE KEYWORD LIMITATIONS
|
||||
|
||||
This section describes specific limitations for each language keyword.
|
||||
|
||||
=over 4
|
||||
|
||||
=item `__FILE__, `__LINE__, `begin_keywords, `begin_keywords, `begin_keywords,
|
||||
`begin_keywords, `begin_keywords, `define, `else, `elsif, `end_keywords,
|
||||
`endif, `error, `ifdef, `ifndef, `include, `line, `systemc_ctor,
|
||||
`systemc_dtor, `systemc_header, `systemc_imp_header,
|
||||
`systemc_implementation, `systemc_interface, `timescale, `undef, `verilog
|
||||
|
||||
Fully supported.
|
||||
|
||||
=item always, always_comb, always_ff, always_latch, and, assign, begin,
|
||||
buf, case, casex, casez, default, defparam, do-while, else, end, endcase,
|
||||
endfunction, endgenerate, endmodule, endspecify, endtask, final, for,
|
||||
function, generate, genvar, if, initial, inout, input, integer, localparam,
|
||||
macromodule, module, nand, negedge, nor, not, or, output, parameter,
|
||||
posedge, reg, scalared, signed, supply0, supply1, task, tri, vectored,
|
||||
while, wire, xnor, xor
|
||||
|
||||
Generally supported.
|
||||
|
||||
=item specify specparam
|
||||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item uwire
|
||||
|
||||
Verilator does not perform warning checking on uwires, it treats the uwire
|
||||
keyword as if it were the normal wire keyword.
|
||||
|
||||
=item $bits, $countones, $error, $fatal, $finish, $info, $isunknown,
|
||||
$onehot, $onehot0, $readmemb, $readmemh, $signed, $stop, $time, $unsigned,
|
||||
$warning.
|
||||
|
||||
Generally supported.
|
||||
|
||||
=item $display, $write, $fdisplay, $fwrite
|
||||
|
||||
$display and friends must have a constant format string as the first
|
||||
@@ -1357,15 +1564,26 @@ 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,
|
||||
$setup, $setuphold, $skew, $timeskew, $width
|
||||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item $readmemb, $readmemh
|
||||
|
||||
Read memory commands should work properly. Note Verilator and the Verilog
|
||||
specification does not include support for readmem to multi-dimensional
|
||||
arrays.
|
||||
|
||||
=item $realtime
|
||||
|
||||
Treated as $time.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ERRORS AND WARNINGS
|
||||
|
||||
Warnings may be disabled in two ways. First, when the warning is
|
||||
@@ -1388,9 +1606,9 @@ List of all warnings:
|
||||
|
||||
=item BLKANDNBLK
|
||||
|
||||
Error that a variable comes from a mix of blocked and non-blocking
|
||||
assignments. Generally, this is caused by a register driven by both combo
|
||||
logic and a flop:
|
||||
BLKANDNBLK is an error that a variable comes from a mix of blocked and
|
||||
non-blocking assignments. Generally, this is caused by a register driven
|
||||
by both combo logic and a flop:
|
||||
|
||||
always @ (posedge clk) foo[0] <= ...
|
||||
always @* foo[1] = ...
|
||||
@@ -1406,6 +1624,9 @@ This is good coding practice anyways.
|
||||
It is also possible to disable this error when one of the assignments is
|
||||
inside a public task.
|
||||
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item CASEINCOMPLETE
|
||||
|
||||
Warns that inside a case statement there is a stimulus pattern for which
|
||||
@@ -1413,6 +1634,9 @@ there is no case item specified. This is bad style, if a case is
|
||||
impossible, it's better to have a "default: $stop;" or just "default: ;" so
|
||||
that any design assumption violations will be discovered in simulation.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEOVERLAP
|
||||
|
||||
Warns that inside a case statement you have case values which are detected
|
||||
@@ -1420,17 +1644,26 @@ to be overlapping. This is bad style, as moving the order of case values
|
||||
will cause different behavior. Generally the values can be respecified to
|
||||
not overlap.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEX
|
||||
|
||||
Warns that it is simply better style to use casez, and C<?> in place of
|
||||
C<x>'s. See
|
||||
L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf>
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CMPCONST
|
||||
|
||||
Warns that you are comparing a value in a way that will always be constant.
|
||||
For example "X > 1" will always be true when X is a single bit wide.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item COMBDLY
|
||||
|
||||
Warns that you have a delayed assignment inside of a combinatorial block.
|
||||
@@ -1440,6 +1673,9 @@ Verilator, like synthesis, will convert this to a non-delayed assignment,
|
||||
which may result in logic races or other nasties. See
|
||||
L<http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf>
|
||||
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item GENCLK
|
||||
|
||||
Warns that the specified signal is generated, but is also being used as a
|
||||
@@ -1450,6 +1686,9 @@ generate ALL clocks outside in C++/SystemC and make them primary inputs to
|
||||
your Verilog model. (However once need to you have even one, don't sweat
|
||||
additional ones.)
|
||||
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item IMPLICIT
|
||||
|
||||
Warns that a wire is being implicitly declared (it is a single bit wide
|
||||
@@ -1459,18 +1698,27 @@ signal before it is implicitly declared by a cell, and can lead to dangling
|
||||
nets. A better option is the /*AUTOWIRE*/ feature of Verilog-Mode for
|
||||
Emacs, available from L<http://www.veripool.com/>
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item IMPURE
|
||||
|
||||
Warns that a task or function that has been marked with /*verilator
|
||||
no_inline_task*/ references variables that are not local to the task.
|
||||
Verilator cannot schedule these variables correctly.
|
||||
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item MULTIDRIVEN
|
||||
|
||||
Warns that the specified signal comes from multiple always blocks. This is
|
||||
often unsupported by synthesis tools, and is considered bad style. It will
|
||||
also cause longer runtimes due to reduced optimizations.
|
||||
|
||||
Ignoring this warning will only slow simulations, it will simulate
|
||||
correctly.
|
||||
|
||||
=item MULTITOP
|
||||
|
||||
Error that there are multiple top level modules, that is modules not
|
||||
@@ -1482,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
|
||||
@@ -1509,6 +1767,9 @@ cases would result in simulator mismatches.
|
||||
|
||||
Warns that the specified signal is never sourced.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item UNOPT
|
||||
|
||||
Warns that due to some construct, optimization of the specified signal or
|
||||
@@ -1522,6 +1783,9 @@ blocks in both submodules, even if they are unrelated always blocks. This
|
||||
affects performance because Verilator would have to evaluate each submodule
|
||||
multiple times to stabilize the signals crossing between the modules.
|
||||
|
||||
Ignoring this warning will only slow simulations, it will simulate
|
||||
correctly.
|
||||
|
||||
=item UNOPTFLAT
|
||||
|
||||
Warns that due to some construct, optimization of the specified signal is
|
||||
@@ -1573,16 +1837,25 @@ The UNOPTFLAT warning may also occur where outputs from a block of logic
|
||||
are independent, but occur in the same always block. To fix this, use the
|
||||
isolate_assignments meta comment described above.
|
||||
|
||||
Ignoring this warning will only slow simulations, it will simulate
|
||||
correctly.
|
||||
|
||||
=item UNSIGNED
|
||||
|
||||
Warns that you are comparing a unsigned value in a way that implies it is
|
||||
signed, for example "X < 0" will always be true when X is unsigned.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item UNUSED
|
||||
|
||||
Warns that the specified signal is never sinked. This is a future message,
|
||||
currently Verilator will not produce this warning.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item VARHIDDEN
|
||||
|
||||
Warns that a task, function, or begin/end block is declaring a variable by
|
||||
@@ -1590,12 +1863,15 @@ the same name as a variable in the upper level module or begin/end block
|
||||
(thus hiding the upper variable from being able to be used.) Rename the
|
||||
variable to avoid confusion when reading the code.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item WIDTH
|
||||
|
||||
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.
|
||||
@@ -1608,6 +1884,9 @@ The best fix, which clarifies intent and will also make all tools happy is:
|
||||
|
||||
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=back
|
||||
|
||||
The following describes the less obvious errors:
|
||||
@@ -1661,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."
|
||||
@@ -1681,9 +1960,28 @@ so your simulator shouldn't have to be -- and Verilator is closer to the
|
||||
synthesis interpretation, so this is a good thing for getting working
|
||||
silicon.
|
||||
|
||||
=item May programs I create with Verilator remain under my own copyright?
|
||||
|
||||
Yes, it's just like using GCC on your programs. If you change Verilator
|
||||
itself, you must make the source code available under the GNU Public
|
||||
License. However, the include and generated files use the GNU Lesser
|
||||
Public License, which means that files using them are NOT required to be released.
|
||||
|
||||
You also have the option of using the Perl Artistic License, which again
|
||||
does not require you release your Verilog or generated code.
|
||||
|
||||
=item Why is running Verilator so slow?
|
||||
|
||||
Verilator needs more memory 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 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 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
|
||||
@@ -1692,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.
|
||||
@@ -1725,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
|
||||
@@ -1785,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
|
||||
@@ -1876,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
|
||||
|
||||
@@ -1889,7 +2200,7 @@ Communications, Sun Microsystems, Nauticus Networks, and SiCortex.
|
||||
|
||||
The people who have contributed code or other major functionality are Paul
|
||||
Wasson, Duane Galbi, and Wilson Snyder. Major testers include Jeff Dutton,
|
||||
Ralf Karge and Wim Michiels.
|
||||
Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
|
||||
|
||||
Some of the people who have provided ideas and feedback for Verilator
|
||||
include Hans Van Antwerpen, Jens Arm, David Black, Gregg Bouchard, Chris
|
||||
@@ -1916,7 +2227,7 @@ Major concepts by Paul Wasson and Duane Galbi.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<systemperl>, L<vcoverage>, L<make>
|
||||
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -35,12 +35,13 @@ my $Opt_A;
|
||||
my $Opt_B;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config ("no_auto_abbrev");
|
||||
if (! GetOptions (
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
usage();
|
||||
die "%Error: Bad usage, try 'verilator_difftree --help'\n";
|
||||
}
|
||||
|
||||
defined $Opt_A or die "%Error: No old diff filename\n";
|
||||
|
||||
Executable
+211
@@ -0,0 +1,211 @@
|
||||
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
# $Id$
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2007 by Wilson Snyder <[email protected]>. This
|
||||
# program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of either the GNU Lesser General Public License or the Perl
|
||||
# Artistic License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
######################################################################
|
||||
|
||||
require 5.006_001;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw ($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $Opt_File;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config ("no_auto_abbrev");
|
||||
if (! GetOptions (
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'verilator_profcfunc --help'\n";
|
||||
}
|
||||
|
||||
defined $Opt_File or die "%Error: No filename given\n";
|
||||
|
||||
profcfunc($Opt_File);
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
print '$Id$ ', "\n";
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!defined $Opt_File) {
|
||||
$Opt_File = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub profcfunc {
|
||||
my $filename = shift;
|
||||
# Remove hex numbers before diffing
|
||||
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
|
||||
|
||||
my %funcs;
|
||||
|
||||
while (defined (my $line=$fh->getline())) {
|
||||
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+.*\s+(\S+)\s*$/) {
|
||||
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
|
||||
$funcs{$func}{pct} += $pct;
|
||||
$funcs{$func}{sec} += $sec;
|
||||
$funcs{$func}{calls} += $calls;
|
||||
}
|
||||
}
|
||||
$fh->close;
|
||||
|
||||
# Find modules
|
||||
my %verilated_mods;
|
||||
foreach my $func (keys %funcs) {
|
||||
if ($func =~ /(.*)::_eval\(.*__Syms.*\)$/) {
|
||||
$verilated_mods{$1} = qr/^$1/;
|
||||
}
|
||||
}
|
||||
|
||||
# Resort by Verilog name
|
||||
my %vfuncs;
|
||||
my %groups;
|
||||
foreach my $func (keys %funcs) {
|
||||
my $vfunc = $func;
|
||||
my $design;
|
||||
foreach my $vde (keys %verilated_mods) {
|
||||
if ($func =~ /$verilated_mods{$vde}/) {
|
||||
$design=$vde;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) {
|
||||
$vfunc = sprintf("VBlock %s:%d", $1, $2);
|
||||
$groups{"Verilog Blocks under $design"} += $funcs{$func}{pct};
|
||||
} else {
|
||||
if ($design) {
|
||||
$vfunc = sprintf("VCommon %s", $func);
|
||||
$groups{"Common code under $design"} += $funcs{$func}{pct};
|
||||
} else {
|
||||
$vfunc = sprintf("C++ %s", $func);
|
||||
$groups{'C++'} += $funcs{$func}{pct};
|
||||
}
|
||||
}
|
||||
$vfuncs{$vfunc} = $funcs{$func};
|
||||
}
|
||||
|
||||
print("Overall summary:\n");
|
||||
print(" % time\n");
|
||||
foreach (sort (keys %groups)) {
|
||||
printf(" %6.2f In all %s\n", $groups{$_}, $_);
|
||||
}
|
||||
print("\n");
|
||||
|
||||
|
||||
print("Verilog code profile:\n");
|
||||
print(" These are split into three categories:\n");
|
||||
print(" C++: Time in non-Verilated C++ code\n");
|
||||
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
|
||||
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
|
||||
print("\n");
|
||||
|
||||
print(" % cumulative self \n");
|
||||
print(" time seconds seconds calls type filename and line number\n");
|
||||
|
||||
my $cume = 0;
|
||||
foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec}
|
||||
|| $a cmp $b}
|
||||
(keys %vfuncs)) {
|
||||
$cume += $vfuncs{$func}{sec};
|
||||
printf +("%6.2f %9.2f %8.2f %8d %s\n",
|
||||
$vfuncs{$func}{pct},
|
||||
$cume, $vfuncs{$func}{sec},
|
||||
$vfuncs{$func}{calls},
|
||||
$func);
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
verilator_profcfunc - Read gprof report created with --profile-cfuncs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
verilator --profile-cfuncs ....
|
||||
gcc --ggdb -pg ....
|
||||
{run executable}
|
||||
gprof
|
||||
verilator_profcfuncs gprof.out
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Verilator_profcfunc reads a profile report created by gprof. The names of
|
||||
the functions are then transformed, assuming the user used verilator's
|
||||
--profile-cfuncs, and a report printed showing the percentage of time, etc,
|
||||
in each Verilog block.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<http://www.veripool.com/>.
|
||||
|
||||
Copyright 2007-2007 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License or the Perl Artistic License.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
C<verilator>
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "$V4/bin/verilator_profcfunc $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
|
||||
### End:
|
||||
+10
-1
@@ -16,8 +16,17 @@ AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
AC_PATH_PROG(PERL,perl)
|
||||
AC_PATH_PROG(YACC,bison)
|
||||
if test "x$PERL" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
||||
fi
|
||||
AC_PATH_PROG(LEX,flex)
|
||||
if test "x$LEX" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it])
|
||||
fi
|
||||
AC_PATH_PROG(YACC,bison)
|
||||
if test "x$YACC" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
|
||||
fi
|
||||
|
||||
dnl Checks for libraries.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// 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.
|
||||
// Lesser 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
|
||||
@@ -31,7 +31,7 @@
|
||||
//===========================================================================
|
||||
// Global variables
|
||||
|
||||
int Verilated::s_randReset = false;
|
||||
int Verilated::s_randReset = 0;
|
||||
int Verilated::s_debug = 1;
|
||||
bool Verilated::s_calcUnusedSigs = false;
|
||||
bool Verilated::s_gotFinish = false;
|
||||
@@ -72,7 +72,8 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
||||
// Random reset -- Only called at init time, so don't inline.
|
||||
|
||||
IData VL_RAND32() {
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Windows doesn't have lrand48(), although Cygwin does.
|
||||
return (rand()<<16) | rand();
|
||||
#else
|
||||
return (lrand48()<<16) | lrand48();
|
||||
|
||||
+27
-90
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// 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.
|
||||
// Lesser 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
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
@@ -513,10 +513,10 @@ static inline IData VL_COUNTONES_W(int words, WDataInP lwp) {
|
||||
}
|
||||
|
||||
static inline IData VL_ONEHOT_I(IData lhs) {
|
||||
return ((lhs & (lhs-1))==0 & lhs!=0);
|
||||
return (((lhs & (lhs-1))==0) & (lhs!=0));
|
||||
}
|
||||
static inline IData VL_ONEHOT_Q(QData lhs) {
|
||||
return ((lhs & (lhs-1))==0 & lhs!=0);
|
||||
return (((lhs & (lhs-1))==0) & (lhs!=0));
|
||||
}
|
||||
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) {
|
||||
IData one=0;
|
||||
@@ -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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Lesser General Public License or the Perl Artistic License.
|
||||
######################################################################
|
||||
|
||||
PERL = @PERL@
|
||||
@@ -49,7 +49,12 @@ VPATH += $(VERILATOR_ROOT)/include
|
||||
CPPFLAGS += $(OPT)
|
||||
|
||||
CPPFLAGS += $(M32)
|
||||
LDFLAGS += $(M32)
|
||||
LDFLAGS += $(M32)
|
||||
|
||||
# Allow upper level user makefiles to specify flags they want.
|
||||
# These aren't ever set by Verilator, so users are free to override them.
|
||||
CPPFLAGS += $(USER_CPPFLAGS)
|
||||
LDFLAGS += $(USER_LDFLAGS)
|
||||
|
||||
# See the benchmarking section of bin/verilator.
|
||||
# Support class optimizations. This includes the tracing and symbol table.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
// 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.
|
||||
// Lesser General Public License or the Perl Artistic License.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// 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.
|
||||
// Lesser 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
|
||||
@@ -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
|
||||
|
||||
@@ -83,7 +86,7 @@ typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
#elif defined(_WIN32)
|
||||
#elif defined(_WIN32) && !defined(__MINGW32__)
|
||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/perl -w
|
||||
#$Id$
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2007 by Wilson Snyder.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of either the GNU General Public License or the
|
||||
# Perl Artistic License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the Perl Artistic License
|
||||
# along with this module; see the file COPYING. If not, see
|
||||
# www.cpan.org
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# DESCRIPTION: Debugging of bison output
|
||||
|
||||
use strict;
|
||||
|
||||
my $Debug;
|
||||
|
||||
my %declared;
|
||||
my %used;
|
||||
|
||||
my $body = 0;
|
||||
my $rule = "";
|
||||
my $lineno = 0;
|
||||
foreach my $line (<STDIN>) {
|
||||
$lineno++;
|
||||
chomp $line;
|
||||
$line =~ s!//.*$!!g;
|
||||
$line =~ s!\s+! !g;
|
||||
next if $line eq '';
|
||||
if ($line =~ m!^\%\%!) {
|
||||
$body++;
|
||||
} elsif ($body == 1) {
|
||||
$rule .= $line;
|
||||
if ($line =~ m!^\s*;\s*$!) {
|
||||
#print "Rule: $rule\n";
|
||||
($rule =~ /^([a-zA-Z0-9_]+):(.*)$/) or die "%Error: No rule name: $1\n";
|
||||
my $rulename = $1; my $preaction = $2;
|
||||
$declared{$rulename} = $lineno;
|
||||
$preaction =~ s/\{[^\}]*\}/ /g;
|
||||
#print "RULEN $rulename PA $preaction\n" if $Debug;
|
||||
$rule = '';
|
||||
foreach my $ref (split /\s+/, $preaction) {
|
||||
next if $ref !~ /^[a-zA-Z]/;
|
||||
next if $ref eq $rulename;
|
||||
if (!$used{$ref} && $declared{$ref}) {
|
||||
print " %Warning: $lineno: $ref used by $rulename after declaration\n";
|
||||
}
|
||||
$used{$ref} = $lineno;
|
||||
print " ref $ref\n" if $Debug;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# compile-command: "./bisonreader < verilog.y"
|
||||
# End:
|
||||
Executable
+174
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/perl -w
|
||||
# $Id$
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2005-2007 by Wilson Snyder <[email protected]>. This
|
||||
# program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of either the GNU Lesser General Public License or the Perl
|
||||
# Artistic License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
######################################################################
|
||||
|
||||
require 5.006_001;
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use Data::Dumper; $Data::Dumper::Indent=1;
|
||||
use strict;
|
||||
use vars qw ($Debug);
|
||||
|
||||
#======================================================================
|
||||
|
||||
our @Header;
|
||||
our %Vertexes;
|
||||
our @Edges;
|
||||
our %Edges;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $opt_filename;
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
if (! GetOptions (
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
dotread ($opt_filename);
|
||||
cwrite ("graph_export.cpp");
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
print '$Id$ ', "\n";
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
sub debug {
|
||||
$Debug = 1;
|
||||
}
|
||||
|
||||
sub parameter {
|
||||
my $param = shift;
|
||||
if (!$opt_filename) {
|
||||
$opt_filename = $param;
|
||||
} else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub dotread {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||
my $header = 1;
|
||||
my $vnum = 0;
|
||||
while (defined (my $line = $fh->getline)) {
|
||||
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
|
||||
next if $1 eq 'nTITLE';
|
||||
$header = 0;
|
||||
$Vertexes{$1} = {num => $vnum++,
|
||||
line => $line,
|
||||
name => $1,};
|
||||
}
|
||||
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
|
||||
my $from=$1; my $to=$2;
|
||||
my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/;
|
||||
my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/;
|
||||
my $edge = {num => $vnum++,
|
||||
line => $line,
|
||||
weight => $weight,
|
||||
cutable => $cutable,
|
||||
from => $from,
|
||||
to => $to,};
|
||||
push @Edges, $edge;
|
||||
$Edges{$from}{$to} = $edge;
|
||||
}
|
||||
elsif ($header) {
|
||||
push @Header, $line;
|
||||
print "IGNORE: $line";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub cwrite {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
|
||||
$fh->print("void V3GraphTestImport::dotImport() {\n");
|
||||
$fh->print(" DfaGraph* gp = &m_graph;\n");
|
||||
foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) {
|
||||
$fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n",
|
||||
$ver->{name}, $ver->{name}, $ver->{name});
|
||||
}
|
||||
$fh->print("\n");
|
||||
foreach my $edge (@Edges) {
|
||||
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
|
||||
$edge->{from}, $edge->{to},
|
||||
$edge->{weight}, $edge->{cutable}?"true":"false");
|
||||
}
|
||||
$fh->print("}\n");
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
dot_importer - Take graph .dot file and convert into .cpp file
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
dot_importer a.dot
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Dot_importer takes a graphvis .dot file and converts into .cpp file. This
|
||||
.cpp file is then manually included in V3GraphTest.cpp to verify various
|
||||
sub-algorithms.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2007 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License or the Perl Artistic License.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./dot_importer | tee ~/d/a.dot"
|
||||
### End:
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/perl -w
|
||||
# $Id$
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2007 by Wilson Snyder <[email protected]>. This
|
||||
# program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of either the GNU Lesser General Public License or the Perl
|
||||
# Artistic License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
######################################################################
|
||||
|
||||
require 5.006_001;
|
||||
use strict;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence_verif');
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "/sicortex/$ENV{DIRPROJECT_ARCH}/lib/Modules/default/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
invoke_ncverilog - Invoke tool under "modules" command
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invoke_ncverilog {ncv arguments}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2007-2007 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License or the Perl Artistic License.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./invoke_ncverilog -help"
|
||||
### End:
|
||||
@@ -118,8 +118,10 @@ RAW_OBJS = \
|
||||
V3Dead.o \
|
||||
V3Delayed.o \
|
||||
V3Depth.o \
|
||||
V3DepthBlock.o \
|
||||
V3Descope.o \
|
||||
V3EmitC.o \
|
||||
V3EmitCInlines.o \
|
||||
V3EmitCSyms.o \
|
||||
V3EmitMk.o \
|
||||
V3EmitV.o \
|
||||
|
||||
+91
-17
@@ -47,28 +47,61 @@ private:
|
||||
V3Double0 m_statAsCover; // Statistic tracking
|
||||
V3Double0 m_statAsPsl; // Statistic tracking
|
||||
V3Double0 m_statAsFull; // Statistic tracking
|
||||
V3Double0 m_statAsSV; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||
AstNode* bodysp = new AstDisplay
|
||||
(nodep->fileline(), '\0',
|
||||
(string("[%0t] %%Error: ")+nodep->fileline()->filebasename()
|
||||
+":"+cvtToStr(nodep->fileline()->lineno())
|
||||
+": Assertion failed in %m"
|
||||
+((message != "")?": ":"")+message
|
||||
+"\\n"),
|
||||
NULL,
|
||||
new AstTime(nodep->fileline()));
|
||||
bodysp->addNext(new AstStop (nodep->fileline()));
|
||||
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) {
|
||||
return (string("[%0t] "+prefix+": ")+nodep->fileline()->filebasename()
|
||||
+":"+cvtToStr(nodep->fileline()->lineno())
|
||||
+": Assertion failed in %m"
|
||||
+((message != "")?": ":"")+message
|
||||
+"\\n");
|
||||
}
|
||||
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
|
||||
nodep->displayType(AstDisplayType::WRITE);
|
||||
nodep->text(assertDisplayMessage(nodep, prefix, nodep->text()));
|
||||
AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack();
|
||||
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
||||
nodep->exprsp(timesp);
|
||||
if (!nodep->scopeNamep() && nodep->name().find("%m") != string::npos) {
|
||||
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
}
|
||||
}
|
||||
|
||||
AstNode* newIfAssertOn(AstNode* nodep) {
|
||||
// Add a internal if to check assertions are on.
|
||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||
bodysp = new AstIf (nodep->fileline(),
|
||||
new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1),
|
||||
bodysp, NULL);
|
||||
return new AstIf (nodep->fileline(),
|
||||
// If assertions are off, have constant propagation rip them out later
|
||||
// This allows syntax errors and such to be detected normally.
|
||||
(v3Global.opt.assertOn()
|
||||
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
|
||||
: (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 0)))),
|
||||
nodep, NULL);
|
||||
}
|
||||
|
||||
AstNode* newIfCoverageOn(AstNode* nodep) {
|
||||
// Add a internal if to check coverage is on
|
||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||
return new AstIf (nodep->fileline(),
|
||||
// If assertions are off, have constant propagation rip them out later
|
||||
// This allows syntax errors and such to be detected normally.
|
||||
(v3Global.opt.coverage()
|
||||
? (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 1)))
|
||||
: (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 0)))),
|
||||
nodep, NULL);
|
||||
}
|
||||
|
||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||
AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::ERROR, message, NULL, NULL);
|
||||
AstNode* bodysp = dispp;
|
||||
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
|
||||
bodysp->addNext(new AstStop (nodep->fileline()));
|
||||
bodysp = newIfAssertOn(bodysp);
|
||||
return bodysp;
|
||||
}
|
||||
|
||||
void newAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) {
|
||||
void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) {
|
||||
propp->unlinkFrBack();
|
||||
sentreep->unlinkFrBack();
|
||||
//
|
||||
@@ -114,6 +147,28 @@ private:
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
|
||||
void newVAssertion(AstVAssert* nodep, AstNode* propp) {
|
||||
propp->unlinkFrBackWithNext();
|
||||
AstNode* passsp = nodep->passsp(); if (passsp) passsp->unlinkFrBackWithNext();
|
||||
AstNode* failsp = nodep->failsp(); if (failsp) failsp->unlinkFrBackWithNext();
|
||||
//
|
||||
if (nodep->castVAssert()) {
|
||||
if (passsp) passsp = newIfAssertOn(passsp);
|
||||
if (failsp) failsp = newIfAssertOn(failsp);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unknown node type");
|
||||
}
|
||||
|
||||
AstIf* ifp = new AstIf (nodep->fileline(), propp, passsp, failsp);
|
||||
AstNode* newp = ifp;
|
||||
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
|
||||
//
|
||||
// Install it
|
||||
nodep->replaceWith(newp);
|
||||
// Bye
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
|
||||
// VISITORS //========== Case assertions
|
||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -163,16 +218,34 @@ private:
|
||||
}
|
||||
|
||||
// VISITORS //========== Statements
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
// Replace the special types with standard text
|
||||
if (nodep->displayType()==AstDisplayType::INFO) {
|
||||
replaceDisplay(nodep, "-Info");
|
||||
} else if (nodep->displayType()==AstDisplayType::WARNING) {
|
||||
replaceDisplay(nodep, "%%Warning");
|
||||
} else if (nodep->displayType()==AstDisplayType::ERROR
|
||||
|| nodep->displayType()==AstDisplayType::FATAL) {
|
||||
replaceDisplay(nodep, "%%Error");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
newAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
||||
m_statAsCover++;
|
||||
}
|
||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
newAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
||||
m_statAsPsl++;
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
||||
m_statAsSV++;
|
||||
}
|
||||
|
||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
@@ -203,6 +276,7 @@ public:
|
||||
}
|
||||
virtual ~AssertVisitor() {
|
||||
V3Stats::addStat("Assertions, PSL asserts", m_statAsPsl);
|
||||
V3Stats::addStat("Assertions, SystemVerilog asserts", m_statAsSV);
|
||||
V3Stats::addStat("Assertions, cover statements", m_statAsCover);
|
||||
V3Stats::addStat("Assertions, full/parallel case", m_statAsFull);
|
||||
}
|
||||
|
||||
+22
-3
@@ -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
|
||||
|
||||
@@ -789,7 +808,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append) {
|
||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||
if (editCountGbl()==editCountLast() && 0) { // Off, as messes up tree diffing
|
||||
if (editCountGbl()==editCountLast() && 1) { // Off, as messes up tree diffing
|
||||
*logsp<<endl;
|
||||
*logsp<<"No changes since last dump!\n";
|
||||
} else {
|
||||
|
||||
+34
-1
@@ -250,6 +250,34 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstDisplayType {
|
||||
public:
|
||||
enum en {
|
||||
DISPLAY,
|
||||
WRITE,
|
||||
INFO,
|
||||
ERROR,
|
||||
WARNING,
|
||||
FATAL
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstDisplayType () {};
|
||||
inline AstDisplayType (en _e) : m_e(_e) {};
|
||||
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {};
|
||||
operator en () const { return m_e; };
|
||||
bool addNewline() const { return m_e!=WRITE; }
|
||||
bool needScopeTracking() const { return m_e!=DISPLAY && m_e!=WRITE; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"display","write","info","error","warning","fatal"};
|
||||
return names[m_e];};
|
||||
};
|
||||
inline bool operator== (AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstDisplayType::en lhs, AstDisplayType rhs) { return (lhs == rhs.m_e); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstParseRefExp {
|
||||
public:
|
||||
enum en {
|
||||
@@ -510,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
|
||||
@@ -906,6 +938,7 @@ public:
|
||||
virtual ~AstNodePli() {}
|
||||
virtual string name() const { return m_text; }
|
||||
virtual int instrCount() const { return instrCountPli(); }
|
||||
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
|
||||
string text() const { return m_text; } // * = Text to display
|
||||
void text(const string& text) { m_text=text; }
|
||||
@@ -970,7 +1003,7 @@ private:
|
||||
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
||||
string m_name; // Name of variable
|
||||
string m_dotted; // Dotted part of scope to task or ""
|
||||
string m_inlinedDots; // Dotted hiearchy flattened out
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
public:
|
||||
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
|
||||
:AstNode(fl)
|
||||
|
||||
@@ -298,6 +298,7 @@ void AstCell::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (modp()) { str<<" -> "; modp()->dump(str); }
|
||||
else { str<<" ->UNLINKED:"<<modName(); }
|
||||
if (pinStar()) str<<" [.*]";
|
||||
}
|
||||
void AstCellInline::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -307,6 +308,7 @@ void AstPin::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
||||
else { str<<" ->UNLINKED"; }
|
||||
if (svImplicit()) str<<" [.SV]";
|
||||
}
|
||||
void AstVarXRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
|
||||
+101
-15
@@ -236,6 +236,7 @@ private:
|
||||
bool m_scClocked:1; // SystemC sc_clk<> needed
|
||||
bool m_scSensitive:1;// SystemC sensitive() needed
|
||||
bool m_sigPublic:1; // User C code accesses this signal
|
||||
bool m_sigModPublic:1;// User C code accesses this signal and module
|
||||
bool m_usedClock:1; // Signal used as a clock
|
||||
bool m_usedParam:1; // Parameter is referenced (on link; later signals not setup)
|
||||
bool m_funcLocal:1; // Local variable for a function
|
||||
@@ -252,7 +253,8 @@ private:
|
||||
m_primaryIO=false;
|
||||
m_sc=false; m_scClocked=false; m_scSensitive=false;
|
||||
m_usedClock=false; m_usedParam=false;
|
||||
m_sigPublic=false; m_funcLocal=false; m_funcReturn=false;
|
||||
m_sigPublic=false; m_sigModPublic=false;
|
||||
m_funcLocal=false; m_funcReturn=false;
|
||||
m_attrClockEn=false; m_attrIsolateAssign=false;
|
||||
m_fileDescr=false; m_isConst=false; m_isStatic=false;
|
||||
m_trace=false;
|
||||
@@ -307,6 +309,7 @@ public:
|
||||
void usedClock(bool flag) { m_usedClock = flag; }
|
||||
void usedParam(bool flag) { m_usedParam = flag; }
|
||||
void sigPublic(bool flag) { m_sigPublic = flag; }
|
||||
void sigModPublic(bool flag) { m_sigModPublic = flag; }
|
||||
void sc(bool flag) { m_sc = flag; }
|
||||
void scSensitive(bool flag) { m_scSensitive = flag; }
|
||||
void primaryIO(bool flag) { m_primaryIO = flag; }
|
||||
@@ -343,6 +346,7 @@ public:
|
||||
bool isScWide() const;
|
||||
bool isScSensitive() const { return m_scSensitive; }
|
||||
bool isSigPublic() const;
|
||||
bool isSigModPublic() const { return m_sigModPublic; }
|
||||
bool isTrace() const { return m_trace; }
|
||||
bool isConst() const { return m_isConst; }
|
||||
bool isStatic() const { return m_isStatic; }
|
||||
@@ -374,6 +378,7 @@ public:
|
||||
propagateAttrFrom(typevarp);
|
||||
combineType(typevarp->varType());
|
||||
if (typevarp->isSigPublic()) sigPublic(true);
|
||||
if (typevarp->isSigModPublic()) sigModPublic(true);
|
||||
if (typevarp->attrScClocked()) attrScClocked(true);
|
||||
}
|
||||
void inlineAttrReset(const string& name) {
|
||||
@@ -416,7 +421,7 @@ struct AstScope : public AstNode {
|
||||
private:
|
||||
string m_name; // Name
|
||||
AstScope* m_aboveScopep; // Scope above this one in the hierarchy (NULL if top)
|
||||
AstCell* m_aboveCellp; // Cell above this in the hiearchy (NULL if top)
|
||||
AstCell* m_aboveCellp; // Cell above this in the hierarchy (NULL if top)
|
||||
AstModule* m_modp; // Module scope corresponds to
|
||||
public:
|
||||
AstScope(FileLine* fl, AstModule* modp, const string& name,
|
||||
@@ -535,7 +540,7 @@ struct AstVarXRef : public AstNodeVarRef {
|
||||
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
|
||||
private:
|
||||
string m_dotted; // Scope name to connected to
|
||||
string m_inlinedDots; // Dotted hiearchy flattened out
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
public:
|
||||
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
|
||||
:AstNodeVarRef(fl, name, NULL, lvalue)
|
||||
@@ -571,10 +576,11 @@ private:
|
||||
int m_pinNum; // Pin number
|
||||
string m_name; // Pin name, or "" for number based interconnect
|
||||
AstVar* m_modVarp; // Input/output this pin connects to on submodule.
|
||||
bool m_svImplicit; // Pin is SystemVerilog .name'ed
|
||||
public:
|
||||
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
|
||||
:AstNode(fl)
|
||||
,m_name(name) {
|
||||
,m_name(name), m_svImplicit(false) {
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
setNOp1p(exprp); }
|
||||
@@ -591,6 +597,8 @@ public:
|
||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin
|
||||
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
|
||||
void modVarp(AstVar* varp) { m_modVarp=varp; }
|
||||
bool svImplicit() const { return m_svImplicit; }
|
||||
void svImplicit(bool flag) { m_svImplicit=flag; }
|
||||
};
|
||||
|
||||
struct AstModule : public AstNode {
|
||||
@@ -647,12 +655,14 @@ private:
|
||||
string m_name; // Cell name
|
||||
string m_origName; // Original name before dot addition
|
||||
string m_modName; // Module the cell instances
|
||||
bool m_pinStar; // Pin list has .*
|
||||
AstModule* m_modp; // [AfterLink] Pointer to module instanced
|
||||
public:
|
||||
AstCell(FileLine* fl, const string& instName, const string& modName,
|
||||
AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
|
||||
: AstNode(fl)
|
||||
, m_name(instName), m_origName(instName), m_modName(modName), m_modp(NULL) {
|
||||
, m_name(instName), m_origName(instName), m_modName(modName)
|
||||
, m_pinStar(false), m_modp(NULL) {
|
||||
addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); }
|
||||
virtual ~AstCell() {}
|
||||
virtual AstType type() const { return AstType::CELL;}
|
||||
@@ -669,6 +679,8 @@ public:
|
||||
void origName(const string& name) { m_origName = name; }
|
||||
string modName() const { return m_modName; } // * = Instance name
|
||||
void modName(const string& name) { m_modName = name; }
|
||||
bool pinStar() const { return m_pinStar; }
|
||||
void pinStar(bool flag) { m_pinStar = flag; }
|
||||
AstPin* pinsp() const { return op1p()->castPin(); } // op1 = List of cell ports
|
||||
AstPin* paramsp() const { return op2p()->castPin(); } // op2 = List of parameter #(##) values
|
||||
AstRange* rangep() const { return op3p()->castRange(); } // op3 = Range of arrayed instants (NULL=not ranged)
|
||||
@@ -1231,19 +1243,19 @@ struct AstDisplay : public AstNodePli {
|
||||
// Parents: stmtlist
|
||||
// Children: file which must be a varref, MATH to print
|
||||
private:
|
||||
char m_newline;
|
||||
AstDisplayType m_displayType;
|
||||
public:
|
||||
AstDisplay(FileLine* fileline, char newln, const string& text, AstNode* filep, AstNode* exprsp)
|
||||
AstDisplay(FileLine* fileline, AstDisplayType dispType, const string& text, AstNode* filep, AstNode* exprsp)
|
||||
: AstNodePli (fileline, text, exprsp) {
|
||||
setNOp2p(filep);
|
||||
m_newline = newln;
|
||||
m_displayType = dispType;
|
||||
}
|
||||
virtual ~AstDisplay() {}
|
||||
virtual AstType type() const { return AstType::DISPLAY;}
|
||||
virtual AstNode* clone() { return new AstDisplay(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string verilogKwd() const { return (filep() ? ((newline() == '\n')?"$fdisplay":"$fwrite")
|
||||
: ((newline() == '\n')?"$display":"$write")); };
|
||||
virtual string verilogKwd() const { return (filep() ? (string)"$f"+(string)displayType().ascii()
|
||||
: (string)"$"+(string)displayType().ascii()); }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: $display has 'visual' ordering
|
||||
@@ -1251,15 +1263,16 @@ public:
|
||||
virtual bool isUnlikely() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return newline()==samep->castDisplay()->newline()
|
||||
return displayType()==samep->castDisplay()->displayType()
|
||||
&& text()==samep->castDisplay()->text(); }
|
||||
// op1 used by AstNodePli
|
||||
char newline() const { return m_newline; } // * = Add a newline for $display
|
||||
AstDisplayType displayType() const { return m_displayType; }
|
||||
void displayType(AstDisplayType type) { m_displayType = type; }
|
||||
bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display
|
||||
AstNode* filep() const { return op2p(); }
|
||||
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
|
||||
AstNode* scopeAttrp() const { return op3p(); }
|
||||
AstText* scopeTextp() const { return op3p()->castText(); }
|
||||
void scopeAttrp(AstNode* nodep) { addOp3p(nodep); }
|
||||
AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
|
||||
void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
|
||||
};
|
||||
|
||||
struct AstFClose : public AstNodeStmt {
|
||||
@@ -1710,6 +1723,22 @@ public:
|
||||
int dimension() const { return m_dimension; }
|
||||
};
|
||||
|
||||
struct AstScopeName : public AstNode {
|
||||
// For display %m
|
||||
// Parents: DISPLAY
|
||||
// Children: TEXT
|
||||
AstScopeName(FileLine* fl)
|
||||
: AstNode(fl) {}
|
||||
virtual ~AstScopeName() {}
|
||||
virtual AstType type() const { return AstType::SCOPENAME;}
|
||||
virtual AstNode* clone() { return new AstScopeName(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
AstText* scopeAttrp() const { return op1p()->castText(); }
|
||||
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// non-ary ops
|
||||
|
||||
@@ -2577,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) {
|
||||
@@ -2611,6 +2673,30 @@ struct AstReplicate : public AstNodeBiop {
|
||||
virtual int instrCount() const { return widthInstrs()*2; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// SysVerilog assertions
|
||||
|
||||
struct AstVAssert : public AstNodeStmt {
|
||||
// Verilog Assertion
|
||||
// Parents: {statement list}
|
||||
// Children: expression, if pass statements, if fail statements
|
||||
AstVAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp)
|
||||
: AstNodeStmt(fl) {
|
||||
addOp1p(propp);
|
||||
addNOp2p(passsp);
|
||||
addNOp3p(failsp);
|
||||
}
|
||||
virtual ~AstVAssert() {}
|
||||
virtual AstType type() const { return AstType::VASSERT;}
|
||||
virtual AstNode* clone() { return new AstVAssert(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
AstNode* propp() const { return op1p(); } // op1 = property
|
||||
AstNode* passsp() const { return op2p(); } // op2 = if passes
|
||||
AstNode* failsp() const { return op3p(); } // op3 = if fails
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// PSL
|
||||
|
||||
|
||||
@@ -131,6 +131,18 @@ private:
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
// Similar code in V3Inline
|
||||
if (m_beginScope != "") {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
nodep->scopeAttrp(new AstText(nodep->fileline(), (string)"."+AstNode::prettyName(m_beginScope)));
|
||||
if (afterp) nodep->scopeAttrp(afterp);
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
+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
-6
@@ -62,9 +62,6 @@ private:
|
||||
//int debug() { return 9; }
|
||||
|
||||
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
||||
// We report a syntax error on empty "case (x) endcase" blocks, so never no items at all
|
||||
if (!nodep->itemsp()) nodep->v3fatalSrc("No items (not even default) under case statement?\n");
|
||||
|
||||
// Detect multiple defaults
|
||||
bool hitDefault = false;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
@@ -221,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
|
||||
|
||||
@@ -248,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++) {
|
||||
@@ -267,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: ");
|
||||
}
|
||||
|
||||
@@ -307,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);
|
||||
@@ -323,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() {}
|
||||
|
||||
+4
-4
@@ -104,11 +104,8 @@ private:
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
//
|
||||
computeCppWidth(nodep);
|
||||
V3Number zero (nodep->fileline(), nodep->widthMin(),0);
|
||||
V3Number masksmall (nodep->fileline(), nodep->widthMin());
|
||||
masksmall.opNot(zero);
|
||||
V3Number mask (nodep->fileline(), cppWidth(nodep));
|
||||
mask.opAssign(masksmall);
|
||||
mask.setMask(nodep->widthMin());
|
||||
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), mask),
|
||||
nodep);
|
||||
@@ -199,6 +196,9 @@ private:
|
||||
virtual void visit(AstText* nodep, AstNUser*) {
|
||||
setClean (nodep, true);
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
setClean (nodep, true);
|
||||
}
|
||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||
operandTriop(nodep);
|
||||
setClean (nodep, nodep->cleanOut());
|
||||
|
||||
+2
-1
@@ -472,7 +472,8 @@ private:
|
||||
ifstmtp->addNext(new AstIf(fl,
|
||||
new AstLt (fl, new AstConst(fl, 100),
|
||||
new AstVarRef(fl, countVarp, false)),
|
||||
(new AstDisplay (fl, '\n', "%%Error: Verilated model didn't converge", NULL, NULL))
|
||||
(new AstDisplay (fl, AstDisplayType::DISPLAY,
|
||||
"%%Error: Verilated model didn't converge", NULL, NULL))
|
||||
->addNext(new AstStop (fl)),
|
||||
NULL));
|
||||
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
|
||||
|
||||
+85
-10
@@ -246,9 +246,8 @@ private:
|
||||
replaceNum(nodep, 0); nodep=NULL;
|
||||
}
|
||||
void replaceAllOnes (AstNode* nodep) {
|
||||
V3Number num (nodep->fileline(), nodep->width(), 0);
|
||||
V3Number ones (nodep->fileline(), nodep->width());
|
||||
ones.opNot(num);
|
||||
V3Number ones (nodep->fileline(), nodep->width(), 0);
|
||||
ones.setMask(nodep->width());
|
||||
replaceNum(nodep, ones); nodep=NULL;
|
||||
}
|
||||
void replaceConst(AstNodeUniop* nodep) {
|
||||
@@ -385,10 +384,12 @@ 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());
|
||||
ones.opNot(mask1);
|
||||
ones.setMask(nodep->width());
|
||||
if (shift1<0) {
|
||||
mask1.opShiftR(ones,V3Number(nodep->fileline(),VL_WORDSIZE,-shift1));
|
||||
} else {
|
||||
@@ -525,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;
|
||||
}
|
||||
@@ -638,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();
|
||||
@@ -648,6 +651,7 @@ private:
|
||||
nodep->lhsp(ap);
|
||||
nodep->rhsp(bcConcp);
|
||||
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
|
||||
abConcp->deleteTree(); abConcp=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,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
|
||||
@@ -757,7 +763,8 @@ private:
|
||||
nodep->varp()->initp()->iterateAndNext(*this);
|
||||
if (operandConst(nodep->varp()->initp())
|
||||
&& !nodep->lvalue()
|
||||
&& ((v3Global.opt.oConst() && !m_params) // Can reduce constant wires into equations
|
||||
&& ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations
|
||||
&& !nodep->varp()->isSigPublic())
|
||||
|| nodep->varp()->isParam())) {
|
||||
AstConst* constp = nodep->varp()->initp()->castConst();
|
||||
const V3Number& num = constp->num();
|
||||
@@ -802,7 +809,12 @@ private:
|
||||
if (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||
AstSenItem* newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
|
||||
AstSenItem* newp;
|
||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||
newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
|
||||
} else { // Otherwise it may compute a result that needs to settle out
|
||||
newp = new AstSenItem(nodep->fileline(), AstSenItem::Combo());
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
} else if (nodep->sensp()->castNot()) {
|
||||
@@ -855,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);
|
||||
@@ -938,6 +950,63 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
// Substitute constants into displays. The main point of this is to
|
||||
// simplify assertion methodologies which call functions with display's.
|
||||
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
|
||||
nodep->iterateChildren(*this);
|
||||
bool anyconst = false;
|
||||
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
|
||||
if (argp->castConst()) { anyconst=true; break; }
|
||||
}
|
||||
if (anyconst) {
|
||||
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||
string dispout = "";
|
||||
string fmt = "";
|
||||
bool inPct = false;
|
||||
AstNode* argp = nodep->exprsp();
|
||||
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
|
||||
char ch = *inp; // Breaks with iterators...
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
} else if (inPct && isdigit(ch)) {
|
||||
fmt += ch;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
fmt += ch;
|
||||
switch (tolower(ch)) {
|
||||
case '%': break; // %% - just output a %
|
||||
case 'm': break; // %m - auto insert "name"
|
||||
default: // Most operators, just move to next argument
|
||||
if (argp) {
|
||||
AstNode* nextp=argp->nextp();
|
||||
if (argp && argp->castConst()) { // Convert it
|
||||
string out = argp->castConst()->num().displayed(fmt);
|
||||
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
||||
{ // fmt = out w/ replace % with %% as it must be literal.
|
||||
fmt = "";
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
|
||||
if (*pos == '%') fmt += '%';
|
||||
fmt += *pos;
|
||||
}
|
||||
}
|
||||
argp->unlinkFrBack()->deleteTree();
|
||||
}
|
||||
argp=nextp;
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
dispout += fmt;
|
||||
} else {
|
||||
dispout += ch;
|
||||
}
|
||||
}
|
||||
nodep->text(dispout);
|
||||
//UINFO(9," Display out "<<nodep->text()<<endl);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->condp()->isZero()) {
|
||||
@@ -954,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 }"
|
||||
@@ -1048,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()}");
|
||||
@@ -1089,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)");
|
||||
@@ -1099,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
|
||||
@@ -1129,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;
|
||||
|
||||
+6
-14
@@ -40,7 +40,6 @@
|
||||
#include "V3Ast.h"
|
||||
|
||||
//######################################################################
|
||||
// Depth state, as a visitor of each AstNode
|
||||
|
||||
class DepthVisitor : public AstNVisitor {
|
||||
private:
|
||||
@@ -55,11 +54,6 @@ private:
|
||||
|
||||
//int debug() { return 9; }
|
||||
|
||||
// MSVC++ has a limit of 100 parenthesis. We have some operator
|
||||
// defines that use 2 parens. Thus we can't have a expression deeper
|
||||
// then 50 operators. We'll add some margin though.
|
||||
enum en { MAX_EXPR_DEPTH = 40 }; // Expressions deeper then this need temp
|
||||
|
||||
// METHODS
|
||||
void createDeepTemp(AstNode* nodep) {
|
||||
UINFO(6," Deep "<<nodep<<endl);
|
||||
@@ -114,13 +108,15 @@ private:
|
||||
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
||||
}
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
||||
m_depth++;
|
||||
// We have some operator defines that use 2 parens, so += 2.
|
||||
m_depth += 2;
|
||||
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
||||
nodep->iterateChildren(*this);
|
||||
m_depth--;
|
||||
m_depth -= 2;
|
||||
|
||||
if ((m_maxdepth-m_depth) > MAX_EXPR_DEPTH
|
||||
&& m_stmtp
|
||||
if (m_stmtp
|
||||
&& (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
|
||||
&& (m_maxdepth-m_depth) > v3Global.opt.compLimitParens()
|
||||
&& !nodep->backp()->castNodeStmt() // Not much point if we're about to use it
|
||||
) {
|
||||
m_maxdepth = m_depth;
|
||||
@@ -173,14 +169,10 @@ public:
|
||||
virtual ~DepthVisitor() {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Top loop
|
||||
|
||||
//######################################################################
|
||||
// Depth class functions
|
||||
|
||||
void V3Depth::depthAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
// We must do it in bottom-up module
|
||||
DepthVisitor visitor (nodep);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
// $Id$
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||
//
|
||||
// Code available from: http://www.veripool.com/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// General Public License or the Perl Artistic License.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
// V3DepthBlock's Transformations:
|
||||
//
|
||||
// Each module:
|
||||
// For each deep block, create cfunc including that block.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3DepthBlock.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
class DepthBlockVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current function
|
||||
int m_depth; // How deep in an expression
|
||||
int m_deepNum; // How many functions made
|
||||
|
||||
//int debug() { return 9; }
|
||||
|
||||
// METHODS
|
||||
AstCFunc* createDeepFunc(AstNode* nodep) {
|
||||
AstNRelinker relinkHandle;
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
// Create function
|
||||
string name = m_funcp->name()+"__deep"+cvtToStr(++m_deepNum);
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->symProlog(true);
|
||||
funcp->slow(m_funcp->slow());
|
||||
funcp->addStmtsp(nodep);
|
||||
m_modp->addStmtp(funcp);
|
||||
// Call it at the point where the body was removed from
|
||||
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
|
||||
callp->argTypes("vlSymsp");
|
||||
UINFO(6," New "<<callp<<endl);
|
||||
//
|
||||
relinkHandle.relink(callp);
|
||||
return funcp;
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||
UINFO(4," MOD "<<nodep<<endl);
|
||||
m_modp = nodep;
|
||||
m_deepNum = 0;
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
// We recurse into this.
|
||||
int lastDepth = m_depth;
|
||||
AstCFunc* lastFuncp = m_funcp;
|
||||
{
|
||||
m_depth = 0;
|
||||
m_funcp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
m_depth = lastDepth;
|
||||
m_funcp = lastFuncp;
|
||||
}
|
||||
void visitStmt(AstNodeStmt* nodep) {
|
||||
m_depth++;
|
||||
if (m_depth > v3Global.opt.compLimitBlocks()
|
||||
&& !nodep->castCCall()) { // Already done
|
||||
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
|
||||
AstNode* backp = nodep->backp(); // Only for debug
|
||||
if (debug()>=9) backp->dumpTree(cout,"- pre : ");
|
||||
AstCFunc* funcp = createDeepFunc(nodep);
|
||||
funcp->accept(*this);
|
||||
if (debug()>=9) backp->dumpTree(cout,"- post: ");
|
||||
if (debug()>=9) funcp->dumpTree(cout,"- func: ");
|
||||
} else {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
m_depth--;
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
||||
visitStmt(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
DepthBlockVisitor(AstNode* nodep) {
|
||||
m_modp=NULL;
|
||||
m_depth=0;
|
||||
//
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~DepthBlockVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// DepthBlock class functions
|
||||
|
||||
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DepthBlockVisitor visitor (nodep);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// $Id$ //-*- C++ -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||
//
|
||||
// Code available from: http://www.veripool.com/verilator
|
||||
//
|
||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// General Public License or the Perl Artistic License.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3DEPTHBLOCK_H_
|
||||
#define _V3DEPTHBLOCK_H_ 1
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3DepthBlock {
|
||||
public:
|
||||
static void depthBlockAll(AstNetlist* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
+2
-2
@@ -160,8 +160,8 @@ private:
|
||||
}
|
||||
}
|
||||
// Not really any way the user could do this, and we'd need to come up with some return value
|
||||
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(),
|
||||
// '\n', string("%%Error: ")+name+"() called with bad scope", NULL));
|
||||
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DISPLAY,
|
||||
// string("%%Error: ")+name+"() called with bad scope", NULL));
|
||||
//newfuncp->addStmtsp(new AstStop (newfuncp->fileline()));
|
||||
if (debug()>=9) newfuncp->dumpTree(cout," newfunc: ");
|
||||
} else {
|
||||
|
||||
+18
-8
@@ -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
|
||||
@@ -388,7 +388,7 @@ public:
|
||||
}
|
||||
virtual void visit(AstMulS* nodep, AstNUser* vup) {
|
||||
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
|
||||
nodep->v3error("Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n");
|
||||
nodep->v3error("Unsupported: Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n");
|
||||
}
|
||||
visit(nodep->castNodeBiop(), vup);
|
||||
}
|
||||
@@ -594,7 +594,14 @@ class EmitCImp : EmitCStmts {
|
||||
if (filenum) filenameNoExt += "__"+cvtToStr(filenum);
|
||||
filenameNoExt += (slow ? "__Slow":"");
|
||||
V3OutCFile* ofp = NULL;
|
||||
if (optSystemPerl()) {
|
||||
if (v3Global.opt.lintOnly()) {
|
||||
// Unfortunately we have some lint checks here, so we can't just skip processing.
|
||||
// We should move them to a different stage.
|
||||
string filename = "/dev/null";
|
||||
newCFile(filename, slow, source);
|
||||
ofp = new V3OutSpFile (filename);
|
||||
}
|
||||
else if (optSystemPerl()) {
|
||||
string filename = filenameNoExt+".sp";
|
||||
newCFile(filename, slow, source);
|
||||
ofp = new V3OutSpFile (filename);
|
||||
@@ -1013,7 +1020,6 @@ void EmitCStmts::displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, cha
|
||||
|
||||
void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
|
||||
string vformat = nodep->text();
|
||||
bool addNewline = (nodep->newline() == '\n');
|
||||
AstNode* elistp = nodep->exprsp();
|
||||
|
||||
// Convert Verilog display to C printf formats
|
||||
@@ -1046,16 +1052,17 @@ void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
|
||||
// Spec: h d o b c l
|
||||
case 'b': displayArg(nodep,&elistp,fmt,'b'); break;
|
||||
case 'c': displayArg(nodep,&elistp,fmt,'c'); break;
|
||||
case 't':
|
||||
case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal
|
||||
case 'o': displayArg(nodep,&elistp,fmt,'o'); break;
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,fmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,fmt,'s'); break;
|
||||
case 't': displayArg(nodep,&elistp,fmt,'u'); break;
|
||||
case 'm': {
|
||||
emitDispState.pushFormat("%s");
|
||||
emitDispState.pushArg(NULL, "vlSymsp->name(");
|
||||
for (AstText* textp=nodep->scopeTextp(); textp; textp=textp->nextp()->castText()) {
|
||||
if (!nodep->scopeNamep()) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
for (AstText* textp=nodep->scopeNamep()->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
|
||||
emitDispState.pushFormat(textp->text());
|
||||
}
|
||||
break;
|
||||
@@ -1076,7 +1083,7 @@ void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
|
||||
if (elistp != NULL) {
|
||||
nodep->v3error("Extra arguments for $display format\n");
|
||||
}
|
||||
if (addNewline) emitDispState.pushFormat("\\n");
|
||||
if (nodep->addNewline()) emitDispState.pushFormat("\\n");
|
||||
displayEmit(nodep);
|
||||
}
|
||||
|
||||
@@ -1207,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");
|
||||
@@ -1421,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$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt\n");
|
||||
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS) 2>&1 | c++filt\n");
|
||||
of.puts("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -246,6 +246,8 @@ public:
|
||||
virtual void visit(AstText* nodep, AstNUser*) {
|
||||
ofp()->putsNoTracking(nodep->text());
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
}
|
||||
virtual void visit(AstCStmt* nodep, AstNUser*) {
|
||||
putbs("$_CSTMT(");
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
|
||||
+76
-7
@@ -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"
|
||||
@@ -34,7 +35,8 @@
|
||||
|
||||
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
|
||||
|
||||
int V3Error::s_errcnt = 0;
|
||||
int V3Error::s_errCount = 0;
|
||||
int V3Error::s_warnCount = 0;
|
||||
int V3Error::s_debugDefault = 0;
|
||||
ostringstream V3Error::s_errorStr; // Error string being formed
|
||||
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
|
||||
@@ -100,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) {
|
||||
@@ -162,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
|
||||
|
||||
@@ -187,8 +236,13 @@ string V3Error::lineStr (const char* filename, int lineno) {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
void V3Error::incWarnings() {
|
||||
s_warnCount++;
|
||||
// We don't exit on a lot of warnings.
|
||||
}
|
||||
|
||||
void V3Error::incErrors() {
|
||||
s_errcnt++;
|
||||
s_errCount++;
|
||||
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
|
||||
v3fatal ("Exiting due to too many errors encountered\n");
|
||||
}
|
||||
@@ -196,16 +250,30 @@ void V3Error::incErrors() {
|
||||
|
||||
void V3Error::abortIfErrors() {
|
||||
if (errorCount()) {
|
||||
v3fatal ("Exiting due to "<<dec<<errorCount()<<" warning(s)\n");
|
||||
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||
}
|
||||
}
|
||||
|
||||
void V3Error::abortIfWarnings() {
|
||||
if (errorOrWarnCount()) {
|
||||
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool V3Error::isError(V3ErrorCode code) {
|
||||
if (code==V3ErrorCode::SUPPRESS) return false;
|
||||
else if (code==V3ErrorCode::FATAL) return true;
|
||||
else if (code==V3ErrorCode::ERROR) return true;
|
||||
else if (code<V3ErrorCode::FIRST_WARN
|
||||
|| s_pretendError[code]) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
string V3Error::msgPrefix(V3ErrorCode code) {
|
||||
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
|
||||
else if (code==V3ErrorCode::FATAL) return "%Error: ";
|
||||
else if (code==V3ErrorCode::ERROR) return "%Error: ";
|
||||
else if (code<V3ErrorCode::FIRST_WARN
|
||||
|| s_pretendError[code]) return "%Error-"+(string)code.ascii()+": ";
|
||||
else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|
||||
else return "%Warning-"+(string)code.ascii()+": ";
|
||||
}
|
||||
|
||||
@@ -258,7 +326,8 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
|
||||
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
||||
}
|
||||
}
|
||||
incErrors();
|
||||
if (isError(s_errorCode)) incErrors();
|
||||
else incWarnings();
|
||||
if (s_errorCode==V3ErrorCode::FATAL) {
|
||||
static bool inFatal = false;
|
||||
if (!inFatal) {
|
||||
|
||||
+31
-8
@@ -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); }
|
||||
@@ -104,11 +112,11 @@ class V3Error {
|
||||
static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning
|
||||
static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error
|
||||
static int s_debugDefault; // Default debugging level
|
||||
static int s_errcnt; // Error count
|
||||
static int s_errCount; // Error count
|
||||
static int s_warnCount; // Error count
|
||||
static ostringstream s_errorStr; // Error string being formed
|
||||
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
||||
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
||||
static void incErrors();
|
||||
|
||||
V3Error() { cerr<<("Static class"); abort(); }
|
||||
|
||||
@@ -118,12 +126,18 @@ class V3Error {
|
||||
static void debugDefault(int level) { s_debugDefault = level; }
|
||||
static int debugDefault() { return s_debugDefault; }
|
||||
static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn
|
||||
static int errorCount() { return s_errcnt; }
|
||||
static int errorCount() { return s_errCount; }
|
||||
static int warnCount() { return s_warnCount; }
|
||||
static int errorOrWarnCount() { return errorCount()+warnCount(); }
|
||||
// METHODS
|
||||
static void incErrors();
|
||||
static void incWarnings();
|
||||
static void init();
|
||||
static void abortIfErrors();
|
||||
static void abortIfWarnings();
|
||||
static void suppressThisWarning(); // Suppress next %Warn if user has it off
|
||||
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
|
||||
static bool isError(V3ErrorCode code);
|
||||
static string v3sform (const char* format, ...);
|
||||
static string lineStr (const char* filename, int lineno);
|
||||
static V3ErrorCode errorCode() { return s_errorCode; }
|
||||
@@ -185,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;
|
||||
@@ -198,10 +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 warnResetDefault() { m_warnOff=s_defaultFileLine.m_warnOff; }
|
||||
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);
|
||||
|
||||
|
||||
+4
-5
@@ -65,11 +65,8 @@ private:
|
||||
if (nodep->isWide()) {
|
||||
return V3Number (nodep->fileline(), VL_WORDSIZE, VL_MASK_I(nodep->widthMin()));
|
||||
} else {
|
||||
V3Number zero (nodep->fileline(), nodep->widthMin(),0);
|
||||
V3Number masksmall (nodep->fileline(), nodep->widthMin());
|
||||
masksmall.opNot(zero);
|
||||
V3Number mask (nodep->fileline(), longOrQuadWidth(nodep));
|
||||
mask.opAssign(masksmall);
|
||||
mask.setMask(nodep->widthMin());
|
||||
return mask;
|
||||
}
|
||||
}
|
||||
@@ -534,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);
|
||||
@@ -806,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;
|
||||
|
||||
+6
-2
@@ -177,9 +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 than user()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +188,8 @@ void V3Graph::userClearEdges() {
|
||||
// Clear user() in all of tree
|
||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
edgep->userp(NULL);
|
||||
edgep->user(0);
|
||||
edgep->userp(NULL); // Its a union, but might be different size than user()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,6 +255,8 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
||||
*logp<<"digraph v3graph {\n";
|
||||
*logp<<"\trankdir="<<dotRankDir()<<"\n";
|
||||
*logp<<"\tsize="<<"\"7.5,10\""<<"\n";
|
||||
*logp<<"\tnTITLE\t[fontsize=20 label=\""<<filename<<"\", shape=box, style=bold, color=black];\n";
|
||||
*logp<<"\n";
|
||||
|
||||
// List of all possible subgraphs
|
||||
typedef multimap<string,V3GraphVertex*> SubgraphMmap;
|
||||
|
||||
+9
-5
@@ -37,6 +37,7 @@
|
||||
// Break the minimal number of backward edges to make the graph acyclic
|
||||
|
||||
class GraphAcycVertex : public V3GraphVertex {
|
||||
// user() is used for various sub-algorithm pieces
|
||||
V3GraphVertex* m_origVertexp; // Pointer to first vertex this represents
|
||||
protected:
|
||||
friend class GraphAcyc;
|
||||
@@ -308,6 +309,9 @@ void GraphAcyc::simplifyOne (GraphAcycVertex* avertexp) {
|
||||
avertexp->setDelete(); // Mark so we won't delete it twice
|
||||
// Make a new edge connecting the two vertices directly
|
||||
// If both are breakable, we pick the one with less weight, else it's arbitrary
|
||||
// We can forget about the origEdge list for the "non-selected" set of edges,
|
||||
// as we need to break only one set or the other set of edges, not both.
|
||||
// (This is why we must give preference to the cutable set.)
|
||||
V3GraphEdge* templateEdgep = ( (inEdgep->cutable()
|
||||
&& (!outEdgep->cutable()
|
||||
|| inEdgep->weight()<outEdgep->weight() ))
|
||||
@@ -353,7 +357,7 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
|
||||
if (avertexp->isDelete()) return;
|
||||
// Clear marks
|
||||
for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
edgep->top()->user(false);
|
||||
edgep->top()->userp(NULL);
|
||||
}
|
||||
// Mark edges and detect duplications
|
||||
for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) {
|
||||
@@ -364,16 +368,16 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
|
||||
if (!prevEdgep->cutable()) {
|
||||
// !cutable duplicates prev !cutable: we can ignore it, redundant
|
||||
// cutable duplicates prev !cutable: know it's not a relevant loop, ignore it
|
||||
UINFO(8," DelDupEdge "<<avertexp<<endl);
|
||||
UINFO(8," DelDupEdge "<<avertexp<<" -> "<<edgep->top()<<endl);
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
} else if (!edgep->cutable()) {
|
||||
// !cutable duplicates prev cutable: delete the earlier cutable
|
||||
UINFO(8," DelDupPrev "<<avertexp<<endl);
|
||||
UINFO(8," DelDupPrev "<<avertexp<<" -> "<<prevEdgep->top()<<endl);
|
||||
prevEdgep->unlinkDelete(); prevEdgep = NULL;
|
||||
outVertexp->userp(edgep);
|
||||
} else {
|
||||
// cutable duplicates prev cutable: combine weights
|
||||
UINFO(8," DelDupComb "<<avertexp<<endl);
|
||||
UINFO(8," DelDupComb "<<avertexp<<" -> "<<edgep->top()<<endl);
|
||||
prevEdgep->weight (prevEdgep->weight() + edgep->weight());
|
||||
addOrigEdgep (prevEdgep, edgep);
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
@@ -436,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()) {
|
||||
|
||||
+4
-4
@@ -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);
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
void vertexIterate(V3GraphVertex* vertexp) {
|
||||
// Clear marks
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
edgep->top()->user(false);
|
||||
edgep->top()->userp(NULL);
|
||||
}
|
||||
// Mark edges and detect duplications
|
||||
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||
@@ -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?
|
||||
|
||||
@@ -311,6 +311,34 @@ public:
|
||||
gp->dfaReduce();
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
class V3GraphTestImport : public V3GraphTest {
|
||||
|
||||
void dotImport();
|
||||
|
||||
public:
|
||||
virtual string name() { return "import"; }
|
||||
virtual void runTest() {
|
||||
DfaGraph* gp = &m_graph;
|
||||
if (V3GraphTest::debug()) gp->debug(9);
|
||||
dotImport();
|
||||
dump();
|
||||
gp->acyclic(&V3GraphEdge::followAlwaysTrue);
|
||||
dump();
|
||||
gp->rank(&V3GraphEdge::followAlwaysTrue);
|
||||
dump();
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
# include "graph_export.cpp"
|
||||
#else
|
||||
void V3GraphTestImport::dotImport() {
|
||||
}
|
||||
#endif
|
||||
|
||||
//======================================================================
|
||||
|
||||
void V3Graph::test() {
|
||||
@@ -320,5 +348,6 @@ void V3Graph::test() {
|
||||
{ V3GraphTestAcyc test; test.run(); }
|
||||
{ V3GraphTestVars test; test.run(); }
|
||||
{ V3GraphTestDfa test; test.run(); }
|
||||
{ V3GraphTestImport test; test.run(); }
|
||||
if (V3GraphTest::debug()) v3fatalSrc("Exiting due to graph testing enabled");
|
||||
}
|
||||
|
||||
+6
-6
@@ -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:"); }
|
||||
}
|
||||
}
|
||||
@@ -233,10 +233,10 @@ private:
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
if (m_cellp
|
||||
&& nodep->name().find("%m") != string::npos) {
|
||||
// Similar code in V3Begin
|
||||
if (m_cellp) {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
@@ -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()) {
|
||||
|
||||
+3
-2
@@ -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");
|
||||
@@ -372,7 +372,8 @@ private:
|
||||
}
|
||||
}
|
||||
// Deal with implicit definitions
|
||||
if (m_idState==ID_RESOLVE && nodep->modVarp()) {
|
||||
if (m_idState==ID_RESOLVE && nodep->modVarp()
|
||||
&& !nodep->svImplicit()) { // SV 19.11.3: .name pins don't allow implicit decls
|
||||
pinImplicitExprRecurse(nodep->exprp());
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
@@ -163,6 +163,32 @@ private:
|
||||
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false);
|
||||
}
|
||||
}
|
||||
// Convert .* to list of pins
|
||||
if (nodep->modp() && nodep->pinStar()) {
|
||||
// Note what pins exist
|
||||
UINFO(9," CELL .* connect "<<nodep<<endl);
|
||||
V3SymTable ports; // Symbol table of all connected port names
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells");
|
||||
if (!ports.findIdName(pinp->name())) {
|
||||
ports.insert(pinp->name(), pinp);
|
||||
}
|
||||
}
|
||||
// We search ports, rather 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())) {
|
||||
UINFO(9," need PORT "<<portp<<endl);
|
||||
// Create any not already connected
|
||||
AstPin* newp = new AstPin(nodep->fileline(),0,portp->name(),
|
||||
new AstVarRef(nodep->fileline(),portp->name(),false));
|
||||
newp->svImplicit(true);
|
||||
nodep->addPinsp(newp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert unnamed pins to pin number based assignments
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
|
||||
if (pinp->name()=="") pinp->name("__pinNumber"+cvtToStr(pinp->pinNum()));
|
||||
|
||||
+7
-7
@@ -21,7 +21,7 @@
|
||||
// LinkDot TRANSFORMATIONS:
|
||||
// Top-down traversal
|
||||
// Cells:
|
||||
// Make graph of cell hiearchy
|
||||
// Make graph of cell hierarchy
|
||||
// Var/Funcs's:
|
||||
// Collect all names into symtable under appropriate cell
|
||||
// Top-down traversal
|
||||
@@ -180,7 +180,7 @@ private:
|
||||
// TYPES
|
||||
typedef std::multimap<string,LinkDotCellVertex*> NameScopeMap;
|
||||
// MEMBERS
|
||||
LinkDotGraph m_graph; // Graph of hiearchy
|
||||
LinkDotGraph m_graph; // Graph of hierarchy
|
||||
NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name
|
||||
bool m_forPrearray; // Compress cell__[array] refs
|
||||
bool m_forScopeCreation; // Remove VarXRefs for V3Scope
|
||||
@@ -277,7 +277,7 @@ private:
|
||||
public:
|
||||
LinkDotBaseVertex* findDotted(LinkDotBaseVertex* cellVxp, const string& dotname,
|
||||
string& baddot, LinkDotBaseVertex*& okVxp) {
|
||||
// Given a dotted hiearchy name, return where in scope it is
|
||||
// Given a dotted hierarchy name, return where in scope it is
|
||||
// Note when dotname=="" we just fall through and return cellVxp
|
||||
UINFO(8," dottedFind "<<dotname<<endl);
|
||||
bool firstId = true;
|
||||
@@ -520,8 +520,8 @@ private:
|
||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||
UINFO(8," SCOPE "<<nodep<<endl);
|
||||
if (!m_statep->forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope");
|
||||
// Using the CELL names, we created all hiearchy. We now need to match this Scope
|
||||
// up with the hiearchy created by the CELL names.
|
||||
// Using the CELL names, we created all hierarchy. We now need to match this Scope
|
||||
// up with the hierarchy created by the CELL names.
|
||||
m_cellVxp = m_statep->findScope(nodep);
|
||||
nodep->iterateChildren(*this);
|
||||
m_cellVxp = NULL;
|
||||
@@ -610,7 +610,7 @@ private:
|
||||
UINFO(8," "<<nodep<<endl);
|
||||
if (!m_cellVxp) {
|
||||
UINFO(9,"Dead module for "<<nodep<<endl);
|
||||
nodep->varp(NULL); // Module that is not in hiearchy. We'll be dead code eliminating it later.
|
||||
nodep->varp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
|
||||
} else {
|
||||
string baddot;
|
||||
LinkDotBaseVertex* okVxp;
|
||||
@@ -657,7 +657,7 @@ private:
|
||||
UINFO(8," "<<nodep<<endl);
|
||||
if (!m_cellVxp) {
|
||||
UINFO(9,"Dead module for "<<nodep<<endl);
|
||||
nodep->taskp(NULL); // Module that is not in hiearchy. We'll be dead code eliminating it later.
|
||||
nodep->taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
|
||||
} else {
|
||||
string baddot;
|
||||
LinkDotBaseVertex* okVxp;
|
||||
|
||||
+12
-2
@@ -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
|
||||
@@ -89,6 +89,10 @@ private:
|
||||
// VarRef: Parse its reference
|
||||
UINFO(5," "<<nodep<<endl);
|
||||
// May be a varref inside a select, etc, so save state and recurse
|
||||
string oldText = m_dotText;
|
||||
bool oldDot = m_inModDot;
|
||||
AstParseRefExp oldExp = m_exp;
|
||||
AstText* oldBasep = m_baseTextp;
|
||||
{
|
||||
// Replace the parsed item with its child IE the selection tree down to the varref itself
|
||||
// Do this before iterating, so we don't have to process the edited tree twice
|
||||
@@ -117,8 +121,14 @@ private:
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unknown ParseRefExp type\n");
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
if (m_exp != AstParseRefExp::FUNC) { // Fuctions need to look at the name themself
|
||||
m_dotText = oldText;
|
||||
m_inModDot = oldDot;
|
||||
m_exp = oldExp;
|
||||
m_baseTextp = oldBasep;
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
virtual void visit(AstDot* nodep, AstNUser*) {
|
||||
UINFO(5," "<<nodep<<endl);
|
||||
|
||||
+24
-1
@@ -54,6 +54,7 @@ private:
|
||||
// Below state needs to be preserved between each module call.
|
||||
AstModule* m_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
||||
AstVAssert* m_assertp; // Current assertion
|
||||
|
||||
//int debug() { return 9; }
|
||||
|
||||
@@ -72,13 +73,23 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||
if (m_assertp) nodep->v3error("Assert not allowed under another assert");
|
||||
m_assertp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_assertp = NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->arraysp() && nodep->isIO()) {
|
||||
nodep->v3error("Arrayed variables may not be inputs nor outputs");
|
||||
}
|
||||
if (m_ftaskp) nodep->funcLocal(true);
|
||||
if (nodep->isSigPublic()) m_modp->modPublic(true); // Avoid flattening if signals are exposed
|
||||
if (nodep->isSigModPublic()) {
|
||||
nodep->sigModPublic(false); // We're done with this attribute
|
||||
m_modp->modPublic(true); // Avoid flattening if signals are exposed
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||
@@ -317,6 +328,17 @@ private:
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
if (!m_assertp
|
||||
&& (nodep->displayType() == AstDisplayType::INFO
|
||||
|| nodep->displayType() == AstDisplayType::WARNING
|
||||
|| nodep->displayType() == AstDisplayType::ERROR
|
||||
|| nodep->displayType() == AstDisplayType::FATAL)) {
|
||||
nodep->v3error(nodep->verilogKwd()+" only allowed under a assertion.");
|
||||
}
|
||||
if (nodep->displayType().needScopeTracking()
|
||||
|| nodep->name().find("%m") != string::npos) {
|
||||
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstScCtor* nodep, AstNUser*) {
|
||||
@@ -345,6 +367,7 @@ public:
|
||||
LinkResolveVisitor(AstNetlist* rootp) {
|
||||
m_ftaskp = NULL;
|
||||
m_modp = NULL;
|
||||
m_assertp = NULL;
|
||||
//
|
||||
rootp->accept(*this);
|
||||
}
|
||||
|
||||
+146
-28
@@ -296,9 +296,14 @@ V3Number& V3Number::setAllBitsZ() {
|
||||
for (int i=0; i<words(); i++) { m_value[i]=0; m_valueX[i] = ~0; }
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setMask(int nbits) {
|
||||
setZero();
|
||||
for (int bit=0; bit<nbits; bit++) { setBit(bit,1); }
|
||||
return *this;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// ACCESSORS
|
||||
// ACCESSORS - as strings
|
||||
|
||||
string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
ostringstream out;
|
||||
@@ -329,34 +334,115 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
|
||||
if (binary) {
|
||||
out<<"b";
|
||||
int bit=width()-1;
|
||||
while (bit && bitIs0(bit)) bit--;
|
||||
for(; bit>=0; --bit) {
|
||||
if (bitIs0(bit)) out<<'0';
|
||||
else if (bitIs1(bit)) out<<'1';
|
||||
else if (bitIsZ(bit)) out<<'z';
|
||||
else out<<'x';
|
||||
}
|
||||
out<<displayed("%0b");
|
||||
}
|
||||
else {
|
||||
if (prefixed) out<<"h";
|
||||
// Always deal with 4 bits at once. Note no 4-state, it's above.
|
||||
int hexStart = width()-1;
|
||||
while (hexStart && bitIs0(hexStart)) hexStart--;
|
||||
while ((hexStart&3)!=3) hexStart++;
|
||||
for(int bit=hexStart; bit>0; ) {
|
||||
int v = 0;
|
||||
if (bitIs1(bit)) v |= 8; bit--;
|
||||
if (bitIs1(bit)) v |= 4; bit--;
|
||||
if (bitIs1(bit)) v |= 2; bit--;
|
||||
if (bitIs1(bit)) v |= 1; bit--;
|
||||
if (v>=10) out<<(char)('a'+v-10);
|
||||
else out<<(char)('0'+v);
|
||||
}
|
||||
out<<displayed("%0h");
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
string V3Number::displayed(const string& vformat) const {
|
||||
string::const_iterator pos = vformat.begin();
|
||||
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
|
||||
pos++;
|
||||
string fmtsize;
|
||||
for (; pos != vformat.end() && isdigit(pos[0]); pos++) {
|
||||
fmtsize += pos[0];
|
||||
}
|
||||
string str;
|
||||
char code = tolower(pos[0]);
|
||||
switch (code) {
|
||||
case 'b': {
|
||||
int bit = width()-1;
|
||||
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
|
||||
for (; bit>=0; bit--) {
|
||||
if (bitIs0(bit)) str+='0';
|
||||
else if (bitIs1(bit)) str+='1';
|
||||
else if (bitIsZ(bit)) str+='z';
|
||||
else str+='x';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case 'o': {
|
||||
int bit = width()-1;
|
||||
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
|
||||
while ((bit%3)!=2) bit++;
|
||||
for (; bit>0; bit -= 3) {
|
||||
int v = bitsValue(bit-2, 3);
|
||||
str += (char)('0'+v);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case 'h':
|
||||
case 'x': {
|
||||
int bit = width()-1;
|
||||
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
|
||||
while ((bit%4)!=3) bit++;
|
||||
for (; bit>0; bit -= 4) {
|
||||
int v = bitsValue(bit-3, 4);
|
||||
if (v>=10) str += (char)('a'+v-10);
|
||||
else str += (char)('0'+v);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case 'c': {
|
||||
if (this->width()>8) m_fileline->v3error("$display of char format of > 8 bit value");
|
||||
int v = bitsValue(0, 8);
|
||||
str += (char)(v);
|
||||
return str;
|
||||
}
|
||||
case 's': {
|
||||
// Spec says always drop leading zeros, this isn't quite right, we space pad.
|
||||
int bit=this->width()-1;
|
||||
bool start=true;
|
||||
while ((bit%8)!=7) bit++;
|
||||
for (; bit>=0; bit -= 8) {
|
||||
int v = bitsValue(bit-7, 8);
|
||||
if (!start || v) {
|
||||
str += (char)((v==0)?' ':v);
|
||||
start = false; // Drop leading 0s
|
||||
} else {
|
||||
if (fmtsize != "0") str += ' ';
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case '~': // Signed decimal
|
||||
case 't':
|
||||
case 'd': { // Unsigned decimal
|
||||
bool issigned = (code == '~');
|
||||
if (fmtsize == "") {
|
||||
double mantissabits = this->width() - (issigned?1:0);
|
||||
double maxval = pow(2.0, mantissabits);
|
||||
double dchars = log10(maxval)+1.0;
|
||||
if (issigned) dchars++; // space for sign
|
||||
fmtsize = cvtToStr(int(dchars));
|
||||
}
|
||||
if (width() > 64) {
|
||||
m_fileline->v3error("Unsupported: $display of dec format of > 64 bit results (use hex format instead)");
|
||||
return "ERR";
|
||||
}
|
||||
if (issigned) {
|
||||
str = cvtToStr(asSQuad());
|
||||
} else {
|
||||
str = cvtToStr(asQuad());
|
||||
}
|
||||
int intfmtsize = atoi(fmtsize.c_str());
|
||||
while ((int)(str.length()) < intfmtsize) str = " "+str;
|
||||
return str;
|
||||
}
|
||||
default:
|
||||
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
|
||||
return "ERR";
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// ACCESSORS - as numbers
|
||||
|
||||
uint32_t V3Number::asInt() const {
|
||||
UASSERT(!isFourState(),"asInt with 4-state "<<*this);
|
||||
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this);
|
||||
@@ -364,18 +450,24 @@ uint32_t V3Number::asInt() const {
|
||||
}
|
||||
|
||||
vlsint32_t V3Number::asSInt() const {
|
||||
UASSERT(!isFourState(),"asSInt with 4-state "<<*this);
|
||||
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this);
|
||||
uint32_t signExtend = (-((m_value[0]) & (1UL<<(width()-1))));
|
||||
uint32_t extended = m_value[0] | signExtend;
|
||||
uint32_t v = asInt();
|
||||
uint32_t signExtend = (-(v & (1UL<<(width()-1))));
|
||||
uint32_t extended = v | signExtend;
|
||||
return (vlsint32_t)(extended);
|
||||
}
|
||||
|
||||
vluint64_t V3Number::asQuad() const {
|
||||
UASSERT(!isFourState(),"asQuad with 4-state "<<*this);
|
||||
UASSERT(width()<65, "Value too wide "<<*this);
|
||||
if (width()<=32) return ((vluint64_t)m_value[0]);
|
||||
else return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]);
|
||||
if (width()<=32) return ((vluint64_t)(asInt()));
|
||||
return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]);
|
||||
}
|
||||
|
||||
vlsint64_t V3Number::asSQuad() const {
|
||||
vluint64_t v = asQuad();
|
||||
vluint64_t signExtend = (-(v & (VL_ULL(1)<<(width()-1))));
|
||||
vluint64_t extended = v | signExtend;
|
||||
return (vlsint64_t)(extended);
|
||||
}
|
||||
|
||||
uint32_t V3Number::asHash() const {
|
||||
@@ -629,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++) {
|
||||
@@ -722,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;
|
||||
@@ -893,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());
|
||||
@@ -901,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);
|
||||
@@ -915,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());
|
||||
@@ -923,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);
|
||||
|
||||
@@ -94,6 +94,12 @@ private:
|
||||
bool bitIsZ (int bit) const {
|
||||
if (bit>=m_width) return bitIsZ(m_width-1);
|
||||
return ( (~m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); }
|
||||
uint32_t bitsValue(int lsb, int nbits) const {
|
||||
uint32_t v=0;
|
||||
for (int bitn=0; bitn<nbits; bitn++) { v |= (bitIs1(lsb+bitn)<<bitn); }
|
||||
return v;
|
||||
}
|
||||
|
||||
int words() const { return ((width()+31)/32); }
|
||||
|
||||
public:
|
||||
@@ -108,9 +114,11 @@ public:
|
||||
// SETTERS
|
||||
V3Number& setAllBitsX();
|
||||
V3Number& setAllBitsZ();
|
||||
V3Number& setMask(int nbits); // IE if nbits=1, then 0b1, if 2->0b11, if 3->0b111 etc
|
||||
|
||||
// ACCESSORS
|
||||
string ascii(bool prefixed=true, bool cleanVerilog=false) const;
|
||||
string displayed(const string& format) const;
|
||||
int width() const { return m_width; }
|
||||
int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1)
|
||||
bool sized() const { return m_sized; }
|
||||
@@ -128,6 +136,7 @@ public:
|
||||
uint32_t asInt() const;
|
||||
vlsint32_t asSInt() const;
|
||||
vluint64_t asQuad() const;
|
||||
vlsint64_t asSQuad() const;
|
||||
uint32_t asHash() const;
|
||||
uint32_t dataWord(int word) const;
|
||||
uint32_t countOnes() const;
|
||||
@@ -165,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);
|
||||
|
||||
+41
-18
@@ -48,7 +48,8 @@ struct V3OptionsImp {
|
||||
list<string> m_allArgs; // List of every argument encountered
|
||||
list<string> m_incDirs; // Include directories (ordered)
|
||||
set<string> m_incDirSet; // Include directories (for removing duplicates)
|
||||
set<string> m_libExts; // Library extensions
|
||||
list<string> m_libExts; // Library extensions (ordered)
|
||||
set<string> m_libExtSet; // Library extensions (for removing duplicates)
|
||||
DirMap m_dirMap; // Directory listing
|
||||
|
||||
// ACCESSOR METHODS
|
||||
@@ -59,8 +60,9 @@ struct V3OptionsImp {
|
||||
}
|
||||
}
|
||||
void addLibExt(const string& libext) {
|
||||
if (m_libExts.find(libext) == m_libExts.end()) {
|
||||
m_libExts.insert(libext);
|
||||
if (m_libExtSet.find(libext) == m_libExtSet.end()) {
|
||||
m_libExtSet.insert(libext);
|
||||
m_libExts.push_back(libext);
|
||||
}
|
||||
}
|
||||
V3OptionsImp() {}
|
||||
@@ -193,7 +195,7 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
|
||||
// using the incdir and libext's.
|
||||
// Return "" if not found.
|
||||
for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) {
|
||||
for (set<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
|
||||
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
|
||||
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
|
||||
string exists = fileExists(fn);
|
||||
if (exists!="") {
|
||||
@@ -214,7 +216,7 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
|
||||
} else {
|
||||
fl->v3error("Looked in:"<<endl);
|
||||
for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) {
|
||||
for (set<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
|
||||
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
|
||||
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
|
||||
fl->v3error(" "<<fn<<endl);
|
||||
}
|
||||
@@ -381,6 +383,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
else if ( onoff (sw, "-ignc", flag/*ref*/) ) { m_ignc = flag; }
|
||||
else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)){ m_inhibitSim = flag; }
|
||||
else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; }
|
||||
else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; }
|
||||
else if ( onoff (sw, "-pins64", flag/*ref*/) ) { m_pins64 = flag; }
|
||||
else if ( !strcmp (sw, "-private") ) { m_public = false; }
|
||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
|
||||
@@ -437,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-")) ) {
|
||||
@@ -451,18 +459,20 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
V3Error::pretendError(code, true);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (sw, "-x-assign") && (i+1)<argc) {
|
||||
shift;
|
||||
if (!strcmp (argv[i], "0")) { m_xAssign="0"; }
|
||||
else if (!strcmp (argv[i], "1")) { m_xAssign="1"; }
|
||||
else if (!strcmp (argv[i], "unique")) { m_xAssign="unique"; }
|
||||
else {
|
||||
fl->v3fatal("Unknown setting for -x-assign: "<<sw);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (sw, "-bin") && (i+1)<argc ) {
|
||||
shift; m_bin = argv[i];
|
||||
}
|
||||
else if ( !strcmp (sw, "-compiler") && (i+1)<argc) {
|
||||
shift;
|
||||
if (!strcmp (argv[i], "gcc")) {
|
||||
m_compLimitParens = 0;
|
||||
} else if (!strcmp (argv[i], "msvc")) {
|
||||
m_compLimitParens = 80; // 128, but allow some room
|
||||
m_compLimitBlocks = 80; // 128, but allow some room
|
||||
} else {
|
||||
fl->v3fatal("Unknown setting for --compiler: "<<argv[i]);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (sw, "-f") && (i+1)<argc ) {
|
||||
shift;
|
||||
parseOptsFile(fl, argv[i]);
|
||||
@@ -477,6 +487,15 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
shift; m_prefix = argv[i];
|
||||
if (m_modPrefix=="") m_modPrefix = m_prefix;
|
||||
}
|
||||
else if ( !strcmp (sw, "-x-assign") && (i+1)<argc) {
|
||||
shift;
|
||||
if (!strcmp (argv[i], "0")) { m_xAssign="0"; }
|
||||
else if (!strcmp (argv[i], "1")) { m_xAssign="1"; }
|
||||
else if (!strcmp (argv[i], "unique")) { m_xAssign="unique"; }
|
||||
else {
|
||||
fl->v3fatal("Unknown setting for --x-assign: "<<argv[i]);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp (sw, "-y")) {
|
||||
shift; addIncDir (string (argv[i]));
|
||||
}
|
||||
@@ -572,6 +591,7 @@ V3Options::V3Options() {
|
||||
m_exe = false;
|
||||
m_ignc = false;
|
||||
m_l2Name = true;
|
||||
m_lintOnly = false;
|
||||
m_makeDepend = true;
|
||||
m_makePhony = false;
|
||||
m_outFormatOk = false;
|
||||
@@ -595,6 +615,9 @@ V3Options::V3Options() {
|
||||
m_unrollCount = 64;
|
||||
m_unrollStmts = 20;
|
||||
|
||||
m_compLimitParens = 0;
|
||||
m_compLimitBlocks = 0;
|
||||
|
||||
m_makeDir = "obj_dir";
|
||||
m_bin = "";
|
||||
m_flags = "";
|
||||
@@ -605,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() {
|
||||
|
||||
@@ -56,6 +56,7 @@ class V3Options {
|
||||
bool m_ignc; // main switch: --ignc
|
||||
bool m_inhibitSim; // main switch: --inhibit-sim
|
||||
bool m_l2Name; // main switch: --l2name
|
||||
bool m_lintOnly; // main switch: --lint-only
|
||||
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
|
||||
bool m_pins64; // main switch: --pins64
|
||||
bool m_profileCFuncs;// main switch: --profile-cfuncs
|
||||
@@ -76,6 +77,9 @@ class V3Options {
|
||||
int m_unrollCount; // main switch: --unroll-count
|
||||
int m_unrollStmts; // main switch: --unroll-stmts
|
||||
|
||||
int m_compLimitBlocks; // compiler selection options
|
||||
int m_compLimitParens; // compiler selection options
|
||||
|
||||
string m_bin; // main switch: --bin {binary}
|
||||
string m_flags; // main switch: -f {name}
|
||||
string m_top; // main switch: Top .v file name
|
||||
@@ -150,6 +154,7 @@ class V3Options {
|
||||
bool psl() const { return m_psl; }
|
||||
bool allPublic() const { return m_public; }
|
||||
bool l2Name() const { return m_l2Name; }
|
||||
bool lintOnly() const { return m_lintOnly; }
|
||||
bool ignc() const { return m_ignc; }
|
||||
bool inhibitSim() const { return m_inhibitSim; }
|
||||
|
||||
@@ -160,6 +165,9 @@ class V3Options {
|
||||
int unrollCount() const { return m_unrollCount; }
|
||||
int unrollStmts() const { return m_unrollStmts; }
|
||||
|
||||
int compLimitBlocks() const { return m_compLimitBlocks; }
|
||||
int compLimitParens() const { return m_compLimitParens; }
|
||||
|
||||
string makeDir() const { return m_makeDir; }
|
||||
string prefix() const { return m_prefix; }
|
||||
string modPrefix() const { return m_modPrefix; }
|
||||
@@ -167,6 +175,7 @@ class V3Options {
|
||||
const V3StringSet& cppFiles() const { return m_cppFiles; }
|
||||
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
|
||||
|
||||
|
||||
// ACCESSORS (optimization options)
|
||||
bool oAcycSimp() const { return m_oAcycSimp; }
|
||||
bool oCase() const { return m_oCase; }
|
||||
|
||||
+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;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define VP_DEFINE 261
|
||||
#define VP_ELSE 262
|
||||
#define VP_ELSIF 263
|
||||
#define VP_LINE 264
|
||||
|
||||
#define VP_SYMBOL 300
|
||||
#define VP_STRING 301
|
||||
|
||||
+17
-2
@@ -57,6 +57,9 @@ static void pslMoreNeeded(bool flag) { V3PreLex::s_currentLexp->m_pslMoreNeeded
|
||||
%x DEFMODE
|
||||
%x ARGMODE
|
||||
%x INCMODE
|
||||
%x PRTMODE
|
||||
|
||||
/* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */
|
||||
|
||||
ws [ \t\f\r]
|
||||
wsn [ \t\f]
|
||||
@@ -64,12 +67,14 @@ crnl [\r]*[\n]
|
||||
quote [\"]
|
||||
backslash [\\]
|
||||
symb [a-zA-Z_][a-zA-Z0-9_$]*
|
||||
drop [\032]
|
||||
psl [p]sl
|
||||
|
||||
/**************************************************************/
|
||||
%%
|
||||
|
||||
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext); }
|
||||
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext);
|
||||
return(VP_LINE); }
|
||||
|
||||
/* Special directives we recognise */
|
||||
<INITIAL>"`include" { return(VP_INCLUDE); }
|
||||
@@ -103,6 +108,13 @@ psl [p]sl
|
||||
if (V3PreLex::s_currentLexp->m_parenLevel) appendDefValue(yytext,yyleng);
|
||||
else return (VP_STRING); }
|
||||
|
||||
/* Protected blocks */
|
||||
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
|
||||
<PRTMODE><<EOF>> { linenoInc(); yyerror("EOF in `protected"); yyleng=0; yyterminate(); }
|
||||
<PRTMODE>{crnl} { linenoInc(); yymore(); }
|
||||
<PRTMODE>. { yymore(); }
|
||||
<PRTMODE>"`endprotected" { yy_pop_state(); return (VP_TEXT); }
|
||||
|
||||
/* Pass-through include <> filenames */
|
||||
<INCMODE><<EOF>> { linenoInc(); yyerror("EOF in unterminated include filename"); yyleng=0; yyterminate(); }
|
||||
<INCMODE>{crnl} { linenoInc(); yyerror("Unterminated include filename"); BEGIN(INITIAL); }
|
||||
@@ -113,6 +125,7 @@ psl [p]sl
|
||||
/* Reading definition */
|
||||
<DEFMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
|
||||
<DEFMODE>"//"[^\n\r]* { return (VP_COMMENT);}
|
||||
<DEFMODE>{drop} { }
|
||||
<DEFMODE><<EOF>> { linenoInc(); yyerror("EOF (missing return?) in define value"); yyleng=0; yyterminate(); }
|
||||
<DEFMODE>{crnl} { linenoInc(); yy_pop_state(); yytext="\n"; yyleng=1; return (VP_DEFVALUE); }
|
||||
<DEFMODE>[\\]{crnl} { linenoInc(); appendDefValue("\n",1); } /* Include return so can maintain output line count */
|
||||
@@ -123,6 +136,7 @@ psl [p]sl
|
||||
/* Define arguments */
|
||||
<ARGMODE>"/*" { yy_push_state(CMTMODE); yymore(); }
|
||||
<ARGMODE>"//"[^\n\r]* { return (VP_COMMENT);}
|
||||
<ARGMODE>{drop} { }
|
||||
<ARGMODE><<EOF>> { yyerror("EOF in define argument list\n"); yyleng = 0; yyterminate(); }
|
||||
<ARGMODE>{crnl} { linenoInc(); yytext="\n"; yyleng=1; return(VP_WHITE); }
|
||||
<ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
@@ -179,8 +193,9 @@ psl [p]sl
|
||||
/* Generics */
|
||||
<INITIAL,PSLMULM>{crnl} { linenoInc(); yytext="\n"; yyleng=1; return(VP_WHITE); }
|
||||
<INITIAL,PSLMULM,PSLONEM>{symb} { return (VP_SYMBOL); }
|
||||
<INITIAL,PSLMULM,PSLONEM>[\r] { }
|
||||
<INITIAL,PSLMULM,PSLONEM>{wsn}+ { return (VP_WHITE); }
|
||||
<INITIAL,PSLMULM,PSLONEM>{drop} { }
|
||||
<INITIAL,PSLMULM,PSLONEM>[\r] { }
|
||||
<INITIAL,PSLMULM,PSLONEM>. { return (VP_TEXT); }
|
||||
%%
|
||||
|
||||
|
||||
+45
-12
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -301,12 +306,12 @@ void V3PreProcImp::comment(const string& text) {
|
||||
if (commentTokenMatch(cmd/*ref*/, "parallel_case")) {
|
||||
insertUnreadback ("/*verilator parallel_case*/");
|
||||
}
|
||||
if (commentTokenMatch(cmd/*ref*/, "one_hot")) {
|
||||
insertUnreadback ("/*verilator one_hot*/ "+cmd+";");
|
||||
}
|
||||
if (commentTokenMatch(cmd/*ref*/, "one_cold")) {
|
||||
insertUnreadback ("/*verilator one_cold*/ "+cmd+";");
|
||||
}
|
||||
//if (commentTokenMatch(cmd/*ref*/, "one_hot")) {
|
||||
// insertUnreadback ("/*verilator one_hot*/ "+cmd+";");
|
||||
//}
|
||||
//if (commentTokenMatch(cmd/*ref*/, "one_cold")) {
|
||||
// insertUnreadback ("/*verilator one_cold*/ "+cmd+";");
|
||||
//}
|
||||
// else ignore the comment we don't recognize
|
||||
} // else no assertions
|
||||
} else {
|
||||
@@ -328,6 +333,7 @@ const char* V3PreProcImp::tokenName(int tok) {
|
||||
case VP_DEFINE : return("DEFINE");
|
||||
case VP_ELSE : return("ELSE");
|
||||
case VP_ELSIF : return("ELSIF");
|
||||
case VP_LINE : return("LINE");
|
||||
case VP_SYMBOL : return("SYMBOL");
|
||||
case VP_STRING : return("STRING");
|
||||
case VP_DEFVALUE : return("DEFVALUE");
|
||||
@@ -485,14 +491,24 @@ void V3PreProcImp::openFile(FileLine* fl, const string& filename) {
|
||||
yy_switch_to_buffer(m_lexp->m_yyState);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,6 +532,7 @@ int V3PreProcImp::getRawToken() {
|
||||
next_tok:
|
||||
if (m_lineAdd) {
|
||||
m_lineAdd--;
|
||||
m_rawAtBol = true;
|
||||
yytext="\n"; yyleng=1;
|
||||
return (VP_TEXT);
|
||||
}
|
||||
@@ -523,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);
|
||||
@@ -532,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
|
||||
@@ -552,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;
|
||||
}
|
||||
}
|
||||
@@ -583,6 +607,10 @@ int V3PreProcImp::getToken() {
|
||||
for (int len=0; len<yyleng; len++) { if (yytext[len]=='\n') m_lineAdd++; }
|
||||
goto next_tok;
|
||||
}
|
||||
if (tok==VP_LINE) {
|
||||
addLineComment(0);
|
||||
goto next_tok;
|
||||
}
|
||||
// Deal with some special parser states
|
||||
switch (m_state) {
|
||||
case ps_TOP: {
|
||||
@@ -867,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);
|
||||
@@ -878,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
-10
@@ -57,16 +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*/");
|
||||
// Standards - We ignore
|
||||
s_preprocp->define(prefl,"endcelldefine", "");
|
||||
s_preprocp->define(prefl,"celldefine", "");
|
||||
s_preprocp->define(prefl,"resetall", "");
|
||||
s_preprocp->define(prefl,"portcoerce", "");
|
||||
s_preprocp->define(prefl,"inline", "");
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-2
@@ -62,10 +62,10 @@ public:
|
||||
// METHODS
|
||||
void stateExitPsl() {
|
||||
if (YY_START != PSL) yyerror("Internal error: Exiting PSL state when not in PSL state");
|
||||
BEGIN VLG;
|
||||
yy_pop_state();
|
||||
}
|
||||
void statePushVlg() {
|
||||
yy_push_state(VLG);
|
||||
yy_push_state(STATE_VERILOG_RECENT);
|
||||
}
|
||||
void statePop() {
|
||||
yy_pop_state();
|
||||
@@ -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);
|
||||
|
||||
|
||||
+18
-11
@@ -38,9 +38,13 @@ class V3Read {
|
||||
V3Lexer* m_lexerp; // Current FlexLexer
|
||||
static V3Read* s_readp; // Current THIS, bison() isn't class based
|
||||
FileLine* m_fileline; // Filename/linenumber currently active
|
||||
bool m_inLibrary; // Currently reading a library vs. regular file
|
||||
bool m_inCellDefine; // Inside a `celldefine
|
||||
bool m_inLibrary; // Currently reading a library vs. regular file
|
||||
int m_inBeginKwd; // Inside a `begin_keywords
|
||||
int m_lastVerilogState; // Last LEX state in `begin_keywords
|
||||
deque<string*> m_stringps; // Created strings for later cleanup
|
||||
deque<V3Number*> m_numberps; // Created numbers for later cleanup
|
||||
deque<FileLine> m_lintState; // Current lint state for save/restore
|
||||
//int debug() { return 9; }
|
||||
|
||||
protected:
|
||||
@@ -53,7 +57,12 @@ protected:
|
||||
static void ppline (const char* text);
|
||||
static void incLineno() { s_readp->fileline()->incLineno(); }
|
||||
static void verilatorCmtLint(const char* text, bool on);
|
||||
static void verilatorCmtLintSave();
|
||||
static void verilatorCmtLintRestore();
|
||||
static void verilatorCmtBad(const char* text);
|
||||
static void pushBeginKeywords(int state) { s_readp->m_inBeginKwd++; s_readp->m_lastVerilogState=state; }
|
||||
static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; }
|
||||
static int lastVerilogState() { return s_readp->m_lastVerilogState; }
|
||||
|
||||
public: // But for internal use only
|
||||
static string* newString(const string& text) {
|
||||
@@ -84,27 +93,25 @@ public: // But for internal use only
|
||||
static FileLine* fileline() { return s_readp->m_fileline; }
|
||||
static AstNetlist* rootp() { return s_readp->m_rootp; }
|
||||
static FileLine* copyOrSameFileLine() { return s_readp->fileline()->copyOrSameFileLine(); }
|
||||
static bool inCellDefine() { return s_readp->m_inCellDefine; }
|
||||
static void inCellDefine(bool flag) { s_readp->m_inCellDefine = flag; }
|
||||
static bool inLibrary() { return s_readp->m_inLibrary; }
|
||||
static void stateExitPsl(); // Parser -> lexer communication
|
||||
static void statePushVlg(); // Parser -> lexer communication
|
||||
static void statePop(); // Parser -> lexer communication
|
||||
static int stateVerilogRecent(); // Parser -> lexer communication
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
V3Read(AstNetlist* rootp) {
|
||||
m_rootp = rootp; m_lexerp = NULL;
|
||||
m_inCellDefine = false;
|
||||
m_inLibrary = false;
|
||||
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
|
||||
|
||||
+10
-12
@@ -198,19 +198,17 @@ private:
|
||||
nodep->taskp(NULL);
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
if (nodep->name().find("%m") != string::npos) {
|
||||
string prefix = (string)(".")+m_scopep->prettyName();
|
||||
// TOP and above will be the user's name().
|
||||
// Note 'TOP.'is stripped by prettyName, but not 'TOP'.
|
||||
if (prefix != ".TOP") {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
|
||||
if (afterp) nodep->scopeAttrp(afterp);
|
||||
}
|
||||
string prefix = (string)(".")+m_scopep->prettyName();
|
||||
// TOP and above will be the user's name().
|
||||
// Note 'TOP.'is stripped by prettyName, but not 'TOP'.
|
||||
if (prefix != ".TOP") {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
|
||||
if (afterp) nodep->scopeAttrp(afterp);
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
@@ -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
-20
@@ -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,20 +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.
|
||||
clonedIncsp->unlinkFrBack()->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;
|
||||
@@ -275,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,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: ");
|
||||
}
|
||||
|
||||
@@ -306,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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,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");
|
||||
}
|
||||
@@ -368,6 +370,7 @@ private:
|
||||
&& !nodep->lvalue()) {
|
||||
AstNode* newconstp = m_varValuep->cloneTree(false);
|
||||
nodep->replaceWith(newconstp);
|
||||
pushDeletep(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-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());
|
||||
@@ -385,6 +387,9 @@ private:
|
||||
virtual void visit(AstText* nodep, AstNUser* vup) {
|
||||
// Only used in CStmts which don't care....
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep, AstNUser* vup) {
|
||||
// Only used in Displays which don't care....
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser* vup) {
|
||||
//if (debug()) nodep->dumpTree(cout," InitPre: ");
|
||||
// Must have deterministic constant width
|
||||
@@ -530,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: ");
|
||||
@@ -575,6 +580,13 @@ private:
|
||||
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
|
||||
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||
// TOP LEVEL NODE
|
||||
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
|
||||
nodep->passsp()->iterateAndNext(*this);
|
||||
nodep->failsp()->iterateAndNext(*this);
|
||||
widthCheckReduce(nodep,"Property",nodep->propp(),1,1); // it's like a if() condition.
|
||||
}
|
||||
virtual void visit(AstPin* nodep, AstNUser*) {
|
||||
//if (debug()) nodep->dumpTree(cout,"- PinPre: ");
|
||||
// TOP LEVEL NODE
|
||||
@@ -748,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
|
||||
|
||||
+43
-27
@@ -41,6 +41,7 @@
|
||||
#include "V3Dead.h"
|
||||
#include "V3Delayed.h"
|
||||
#include "V3Depth.h"
|
||||
#include "V3DepthBlock.h"
|
||||
#include "V3Descope.h"
|
||||
#include "V3EmitC.h"
|
||||
#include "V3EmitMk.h"
|
||||
@@ -159,13 +160,11 @@ void process () {
|
||||
|
||||
// Assertion insertion
|
||||
// After we've added block coverage, but before other nasty transforms
|
||||
if (v3Global.opt.assertOn() || v3Global.opt.psl()) {
|
||||
V3AssertPre::assertPreAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assertpre.tree"));
|
||||
//
|
||||
V3Assert::assertAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assert.tree"));
|
||||
}
|
||||
V3AssertPre::assertPreAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assertpre.tree"));
|
||||
//
|
||||
V3Assert::assertAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("assert.tree"));
|
||||
|
||||
// Add top level wrapper with instance pointing to old top
|
||||
// Must do this after we know the width of any parameters
|
||||
@@ -381,6 +380,12 @@ void process () {
|
||||
|
||||
//--MODULE OPTIMIZATIONS--------------
|
||||
|
||||
// Split deep blocks to appease MSVC++. Must be before Localize.
|
||||
if (!v3Global.opt.lintOnly() && v3Global.opt.compLimitBlocks()) {
|
||||
V3DepthBlock::depthBlockAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("deepblock.tree"));
|
||||
}
|
||||
|
||||
// Move BLOCKTEMPS from class to local variables
|
||||
if (v3Global.opt.oLocalize()) {
|
||||
V3Localize::localizeAll(v3Global.rootp());
|
||||
@@ -435,24 +440,30 @@ void process () {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("dead.tree"));
|
||||
}
|
||||
|
||||
// Fix very deep expressions
|
||||
// Mark evaluation functions as member functions, if needed.
|
||||
V3Depth::depthAll(v3Global.rootp());
|
||||
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("depth.tree"));
|
||||
if (!v3Global.opt.lintOnly()) {
|
||||
// Fix very deep expressions
|
||||
// Mark evaluation functions as member functions, if needed.
|
||||
V3Depth::depthAll(v3Global.rootp());
|
||||
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("depth.tree"));
|
||||
|
||||
// Branch prediction
|
||||
V3Branch::branchAll(v3Global.rootp());
|
||||
// Branch prediction
|
||||
V3Branch::branchAll(v3Global.rootp());
|
||||
|
||||
// Add C casts when longs need to become long-long and vice-versa
|
||||
// Note depth may insert something needing a cast, so this must be last.
|
||||
V3Cast::castAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("cast.tree"));
|
||||
// Add C casts when longs need to become long-long and vice-versa
|
||||
// Note depth may insert something needing a cast, so this must be last.
|
||||
V3Cast::castAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("cast.tree"));
|
||||
}
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
// Output the text
|
||||
V3EmitC::emitcSyms();
|
||||
V3EmitC::emitcTrace();
|
||||
if (!v3Global.opt.lintOnly()) {
|
||||
// emitcInlines is first, as it may set needHInlines which other emitters read
|
||||
V3EmitC::emitcInlines();
|
||||
V3EmitC::emitcSyms();
|
||||
V3EmitC::emitcTrace();
|
||||
}
|
||||
V3EmitC::emitc();
|
||||
|
||||
// Statistics
|
||||
@@ -461,8 +472,10 @@ void process () {
|
||||
V3Stats::statsReport();
|
||||
}
|
||||
|
||||
// Makefile must be after all other emitters
|
||||
V3EmitMk::emitmk(v3Global.rootp());
|
||||
if (!v3Global.opt.lintOnly()) {
|
||||
// Makefile must be after all other emitters
|
||||
V3EmitMk::emitmk(v3Global.rootp());
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
@@ -483,11 +496,11 @@ int main(int argc, char** argv, char** env) {
|
||||
v3Global.opt.bin(argv[0]);
|
||||
string argString = V3Options::argString(argc-1, argv+1);
|
||||
v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1);
|
||||
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl()) {
|
||||
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) {
|
||||
v3fatal("Unsupported: Coverage analysis requires --sp output.");
|
||||
}
|
||||
if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly()) {
|
||||
v3fatal("verilator: Need --cc, --sc, --sp or --E option");
|
||||
if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly() && !v3Global.opt.lintOnly()) {
|
||||
v3fatal("verilator: Need --cc, --sc, --sp, --lint-only or --E option");
|
||||
}
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
@@ -496,6 +509,7 @@ int main(int argc, char** argv, char** env) {
|
||||
V3File::addSrcDepend(v3Global.opt.bin());
|
||||
if (v3Global.opt.skipIdentical()
|
||||
&& !v3Global.opt.preprocOnly()
|
||||
&& !v3Global.opt.lintOnly()
|
||||
&& V3File::checkTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString)) {
|
||||
UINFO(1,"--skip-identical: No change to any source files, exiting\n");
|
||||
exit(0);
|
||||
@@ -526,12 +540,13 @@ int main(int argc, char** argv, char** env) {
|
||||
|
||||
// Final steps
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
|
||||
V3Error::abortIfErrors();
|
||||
V3Error::abortIfWarnings();
|
||||
|
||||
if (v3Global.opt.makeDepend()) {
|
||||
if (!v3Global.opt.lintOnly() && v3Global.opt.makeDepend()) {
|
||||
V3File::writeDepend(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__ver.d");
|
||||
}
|
||||
if (v3Global.opt.skipIdentical() || v3Global.opt.makeDepend()) {
|
||||
if (!v3Global.opt.lintOnly()
|
||||
&& (v3Global.opt.skipIdentical() || v3Global.opt.makeDepend())) {
|
||||
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString);
|
||||
}
|
||||
|
||||
@@ -539,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.633 2/7/2007"
|
||||
#define DTVERSION "Verilator 3.655 11/27/2007"
|
||||
|
||||
//**********************************************************************
|
||||
//**** Functions
|
||||
|
||||
+5
-1
@@ -19,7 +19,7 @@
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# DESCRIPTION: Edits flex output to get around Redhat 8.0 broken flex.
|
||||
# DESCRIPTION: Edits flex output to get around various broken flex issues.
|
||||
|
||||
foreach my $line (<STDIN>) {
|
||||
# Fix flex 2.5.4 namespace omission
|
||||
@@ -28,5 +28,9 @@ foreach my $line (<STDIN>) {
|
||||
$line =~ s!(\#define\s+yyFlexLexer\s+yyFlexLexer)!//flexfix: $1!g;
|
||||
# Fix flex 2.5.1 yytext_ptr undef
|
||||
$line =~ s!(\#undef\s+yytext_ptr)!//flexfix: $1!g;
|
||||
# Fix flex 2.5.4 and GCC 4.1.0 warn_unused_result
|
||||
$line =~ s!\(void\) *fwrite\((.*)\)!if (fwrite($1)) {}!g;
|
||||
# Fix flex 2.5.33 and GCC 4.1.2 "warning: comparison between signed and unsigned integer expressions" in YY_INPUT
|
||||
$line =~ s!for \( n = 0; n < max_size && !for ( n = 0; ((size_t)n < (size_t)max_size) && !g;
|
||||
print "$line";
|
||||
}
|
||||
|
||||
+605
-433
File diff suppressed because it is too large
Load Diff
+654
-332
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -34,6 +34,6 @@ ifeq ($(VM_TRACE),1)
|
||||
endif
|
||||
|
||||
simx: sim_main.o $(SP_SRCS) $(VM_PREFIX)__ALL.a
|
||||
$(CXX) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||
|
||||
sim_main.o: sim_main.cpp $(VM_PREFIX).h
|
||||
|
||||
@@ -43,7 +43,7 @@ endif
|
||||
|
||||
#Default compile, using normal make rules
|
||||
#$(VM_PREFIX): $(SP_SRCS) $(VK_OBJS)
|
||||
# $(CXX) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||
# $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||
|
||||
#Our own compile rules; Faster compile, all in one file
|
||||
$(VM_PREFIX)__ALLboth.cpp: $(VK_CLASSES_CPP) $(VK_SUPPORT_CPP)
|
||||
@@ -54,5 +54,5 @@ $(VM_PREFIX)__ALLboth.o: $(VM_PREFIX)__ALLboth.cpp
|
||||
|
||||
ifneq ($(MAKE_MAIN),0)
|
||||
$(VM_PREFIX): $(VM_PREFIX)__ALLboth.o
|
||||
$(CXX) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||
endif
|
||||
|
||||
+51
-5
@@ -32,8 +32,8 @@ use vars qw ($Debug %Vars $Driver $Fork);
|
||||
|
||||
$::Driver = 1;
|
||||
|
||||
eval "use Parallel::Forker; \$Fork=Parallel::Forker->new();";
|
||||
$Fork = Forker->new() if !$Fork;
|
||||
eval "use Parallel::Forker; \$Fork=Parallel::Forker->new(use_sig_child=>1);";
|
||||
$Fork = Forker->new(use_sig_child=>1) if !$Fork;
|
||||
$SIG{CHLD} = sub { $Fork->sig_child() if $Fork; };
|
||||
$SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork; die "Quitting...\n"; };
|
||||
|
||||
@@ -200,11 +200,12 @@ sub new {
|
||||
vcs_flags2 => [], # Overridden in some sim files
|
||||
# NC
|
||||
nc => 0,
|
||||
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+nc=1 -q +assert +sv31a")],
|
||||
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+nc=1 -q +assert +sv")],
|
||||
nc_flags2 => [], # Overridden in some sim files
|
||||
# Verilator
|
||||
'v3' => 0,
|
||||
verilator_flags => [split(/\s+/,"-cc")],
|
||||
verilator_flags2 => [],
|
||||
verilator_make_gcc => 1,
|
||||
verilated_debug => $Opt_Verilated_Debug,
|
||||
stdout_filename => undef, # Redirect stdout
|
||||
@@ -292,7 +293,7 @@ sub compile {
|
||||
$self->_make_top();
|
||||
$self->_run(logfile=>"obj_dir/".$self->{name}."_vcs_compile.log",
|
||||
fails=>$param{fails},
|
||||
cmd=>["vcs",
|
||||
cmd=>[($ENV{VERILATOR_VCS}||"vcs"),
|
||||
@{$param{vcs_flags}},
|
||||
@{$param{vcs_flags2}},
|
||||
@{$param{v_flags}},
|
||||
@@ -306,7 +307,7 @@ sub compile {
|
||||
$self->_make_top();
|
||||
$self->_run(logfile=>"obj_dir/".$self->{name}."_nc_compile.log",
|
||||
fails=>$param{fails},
|
||||
cmd=>["ncverilog",
|
||||
cmd=>[($ENV{VERILATOR_NCVERILOG}||"ncverilog"),
|
||||
@{$param{nc_flags}},
|
||||
@{$param{nc_flags2}},
|
||||
@{$param{v_flags}},
|
||||
@@ -338,6 +339,7 @@ sub compile {
|
||||
my @v3args = ("perl","../bin/verilator",
|
||||
"--prefix ".$self->{VM_PREFIX},
|
||||
@{$param{verilator_flags}},
|
||||
@{$param{verilator_flags2}},
|
||||
@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
$param{top_filename},
|
||||
@@ -547,6 +549,7 @@ sub _make_main {
|
||||
print $fh " double sim_time = 1000;\n";
|
||||
}
|
||||
print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n";
|
||||
print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset};
|
||||
print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
|
||||
my $set;
|
||||
if ($self->sp) {
|
||||
@@ -557,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";
|
||||
@@ -575,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";
|
||||
@@ -583,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";
|
||||
@@ -846,6 +874,24 @@ Run using Verilator.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
=over 4
|
||||
|
||||
=item SYSTEMC
|
||||
|
||||
Root directory name of SystemC kit.
|
||||
|
||||
=item VERILATOR_NCVERILOG
|
||||
|
||||
Command to use to invoke ncverilog.
|
||||
|
||||
=item VERILATOR_VCS
|
||||
|
||||
Command to use to invoke VCS.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
+77
-40
@@ -7,59 +7,96 @@
|
||||
// $finish
|
||||
// on success, or $stop.
|
||||
//
|
||||
// The code as shown applies a random vector to the Test
|
||||
// module, then calculates a CRC on the Test module's outputs.
|
||||
//
|
||||
// **If you do not wish for your code to be released to the public
|
||||
// please note it here**
|
||||
// please note it here, otherwise:**
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
// Some inputs we'll set to random values
|
||||
reg [31:0] in_a;
|
||||
reg [31:0] in_b;
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Some arbitrary function for testing
|
||||
// We'll test below that for each random in_a and in_b, we get a good out_a.
|
||||
wire [31:0] out_x = (in_a ^ in_b);
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [31:0] in = crc[31:0];
|
||||
|
||||
integer cyc; initial cyc=1;
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [31:0] out; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.out (out[31:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[31:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {32'h0, out};
|
||||
|
||||
// What checksum will we end up with
|
||||
`define EXPECTED_SUM 64'h4afe43fb79d7b71e
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("%d %x %x %x\n", cyc, in_a, in_b, out_x);
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
if (cyc==1) begin
|
||||
// Assign inputs randomly
|
||||
in_a <= 32'h89a14fab;
|
||||
in_b <= 32'h7ab512fa;
|
||||
end
|
||||
if (cyc==2) begin
|
||||
in_a <= 32'hf4c11a42;
|
||||
in_b <= 32'h359967c6;
|
||||
// Verify output is correct
|
||||
if (out_x != 32'hf3145d51) $stop;
|
||||
end
|
||||
if (cyc==3) begin
|
||||
in_a <= 32'h58dca151;
|
||||
in_b <= 32'hdc687b27;
|
||||
if (out_x != 32'hc1587d84) $stop;
|
||||
end
|
||||
if (cyc==4) begin
|
||||
in_a <= 32'h09df0bbb;
|
||||
in_b <= 32'h0d0e7231;
|
||||
if (out_x != 32'h84b4da76) $stop;
|
||||
end
|
||||
if (cyc==5) begin
|
||||
if (out_x != 32'h04d1798a) $stop;
|
||||
end
|
||||
if (cyc==9) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
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
|
||||
);
|
||||
|
||||
// Replace this module with the device under test.
|
||||
//
|
||||
// Change the code in the t module to apply values to the inputs and
|
||||
// merge the output values into the result vector.
|
||||
|
||||
input clk;
|
||||
input [31:0] in;
|
||||
output [31:0] out;
|
||||
|
||||
/*AUTOREG*/
|
||||
// Beginning of automatic regs (for this module's undeclared outputs)
|
||||
reg [31:0] out;
|
||||
// End of automatics
|
||||
|
||||
always @(posedge clk) begin
|
||||
out <= in;
|
||||
end
|
||||
endmodule
|
||||
|
||||
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-2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Last_Self->{v3}?'--assert':($Last_Self->{nc}?'+assert':'')],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,48 @@
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
reg toggle;
|
||||
|
||||
integer cyc; initial cyc=1;
|
||||
wire [7:0] cyc_copy = cyc[7:0];
|
||||
|
||||
always @ (negedge clk) begin
|
||||
AssertionFalse1: assert (cyc<100);
|
||||
assert (!(cyc==5) || toggle);
|
||||
// FIX cover {cyc==3 || cyc==4};
|
||||
// FIX cover {cyc==9} report "DefaultClock,expect=1";
|
||||
// FIX cover {(cyc==5)->toggle} report "ToggleLogIf,expect=1";
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc <= cyc + 1;
|
||||
toggle <= !cyc[0];
|
||||
if (cyc==9) begin
|
||||
`ifdef FAILING_ASSERTIONS
|
||||
assert (0) else $info;
|
||||
assert (0) else $info("Info message");
|
||||
assert (0) else $info("Info message, cyc=%d", cyc);
|
||||
InWarningBlock: assert (0) else $warning("Warning....");
|
||||
InErrorBlock: assert (0) else $error("Error....");
|
||||
assert (0) else $fatal(1,"Fatal....");
|
||||
`endif
|
||||
end
|
||||
if (cyc==10) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_assert_basic.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Last_Self->{v3}?'--assert --sp --coverage-user':''],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
#Needs work
|
||||
print "-Info: NOT checking for coverage\n";
|
||||
#file_grep ($Last_Self->{coverage_filename}, qr/t=>'psl_cover',o=>'cover',c=>2\);/);
|
||||
#file_grep ($Last_Self->{coverage_filename}, qr/DefaultClock.*,c=>1\);/);
|
||||
#file_grep ($Last_Self->{coverage_filename}, qr/ToggleLogIf.*,c=>9\);/);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_assert_basic.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+FAILING_ASSERTIONS',
|
||||
$Last_Self->{v3}?'--assert':($Last_Self->{nc}?'+assert':'')],
|
||||
fails => $Last_Self->{nc},
|
||||
);
|
||||
|
||||
execute (
|
||||
fails => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# $Id$
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
top_filename("t/t_assert_basic.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => [],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
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 (
|
||||
verilator_flags2 => ["--compiler msvc"], # We have deep expressions we want to test
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,342 @@
|
||||
// $Id$
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [33:0] in = crc[33:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [31:0] code; // From test of Test.v
|
||||
wire [4:0] len; // From test of Test.v
|
||||
wire next; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.next (next),
|
||||
.code (code[31:0]),
|
||||
.len (len[4:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (in[33:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {26'h0, next, len, code};
|
||||
|
||||
// What checksum will we end up with
|
||||
`define EXPECTED_SUM 64'h5537fa30d49bf865
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Outputs
|
||||
next, code, len,
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [33:0] in;
|
||||
output next;
|
||||
output [31:0] code;
|
||||
output [4:0] len;
|
||||
|
||||
/*AUTOREG*/
|
||||
// Beginning of automatic regs (for this module's undeclared outputs)
|
||||
reg [31:0] code;
|
||||
reg [4:0] len;
|
||||
reg next;
|
||||
// End of automatics
|
||||
|
||||
/*
|
||||
#!/usr/bin/perl -w
|
||||
srand(5);
|
||||
my @used;
|
||||
pat:
|
||||
for (my $pat=0; 1; ) {
|
||||
last if $pat > 196;
|
||||
my $len = int($pat / (6 + $pat/50)) + 4; $len=20 if $len>20;
|
||||
my ($try, $val, $mask);
|
||||
try:
|
||||
for ($try=0; ; $try++) {
|
||||
next pat if $try>50;
|
||||
$val = 0;
|
||||
for (my $bit=23; $bit>(23-$len); $bit--) {
|
||||
my $b = int(rand()*2);
|
||||
$val |= (1<<$bit) if $b;
|
||||
}
|
||||
$mask = (1<<(23-$len+1))-1;
|
||||
for (my $testval = $val; $testval <= ($val + $mask); $testval ++) {
|
||||
next try if $used[$testval];
|
||||
}
|
||||
last;
|
||||
}
|
||||
my $bits = "";
|
||||
my $val2 = 0;
|
||||
for (my $bit=23; $bit>(23-$len); $bit--) {
|
||||
my $b = ($val & (1<<$bit));
|
||||
$bits .= $b?'1':'0';
|
||||
}
|
||||
for (my $testval = $val; $testval <= ($val + $mask); $testval++) {
|
||||
$used[$testval]= 1; #printf "U%08x\n", $testval;
|
||||
}
|
||||
if ($try<90) {
|
||||
printf +(" 24'b%s: {next, len, code} = {in[%02d], 5'd%02d, 32'd%03d};\n"
|
||||
,$bits.("?"x(24-$len)), 31-$len, $len, $pat);
|
||||
$pat++;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
always @* begin
|
||||
next = 1'b0;
|
||||
code = 32'd0;
|
||||
len = 5'b11111;
|
||||
casez (in[31:8])
|
||||
24'b1010????????????????????: {next, len, code} = {in[27], 5'd04, 32'd000};
|
||||
24'b1100????????????????????: {next, len, code} = {in[27], 5'd04, 32'd001};
|
||||
24'b0110????????????????????: {next, len, code} = {in[27], 5'd04, 32'd002};
|
||||
24'b1001????????????????????: {next, len, code} = {in[27], 5'd04, 32'd003};
|
||||
24'b1101????????????????????: {next, len, code} = {in[27], 5'd04, 32'd004};
|
||||
24'b0011????????????????????: {next, len, code} = {in[27], 5'd04, 32'd005};
|
||||
24'b0001????????????????????: {next, len, code} = {in[27], 5'd04, 32'd006};
|
||||
24'b10001???????????????????: {next, len, code} = {in[26], 5'd05, 32'd007};
|
||||
24'b01110???????????????????: {next, len, code} = {in[26], 5'd05, 32'd008};
|
||||
24'b01000???????????????????: {next, len, code} = {in[26], 5'd05, 32'd009};
|
||||
24'b00001???????????????????: {next, len, code} = {in[26], 5'd05, 32'd010};
|
||||
24'b11100???????????????????: {next, len, code} = {in[26], 5'd05, 32'd011};
|
||||
24'b01011???????????????????: {next, len, code} = {in[26], 5'd05, 32'd012};
|
||||
24'b100001??????????????????: {next, len, code} = {in[25], 5'd06, 32'd013};
|
||||
24'b111110??????????????????: {next, len, code} = {in[25], 5'd06, 32'd014};
|
||||
24'b010010??????????????????: {next, len, code} = {in[25], 5'd06, 32'd015};
|
||||
24'b001011??????????????????: {next, len, code} = {in[25], 5'd06, 32'd016};
|
||||
24'b101110??????????????????: {next, len, code} = {in[25], 5'd06, 32'd017};
|
||||
24'b111011??????????????????: {next, len, code} = {in[25], 5'd06, 32'd018};
|
||||
24'b0111101?????????????????: {next, len, code} = {in[24], 5'd07, 32'd020};
|
||||
24'b0010100?????????????????: {next, len, code} = {in[24], 5'd07, 32'd021};
|
||||
24'b0111111?????????????????: {next, len, code} = {in[24], 5'd07, 32'd022};
|
||||
24'b1011010?????????????????: {next, len, code} = {in[24], 5'd07, 32'd023};
|
||||
24'b1000000?????????????????: {next, len, code} = {in[24], 5'd07, 32'd024};
|
||||
24'b1011111?????????????????: {next, len, code} = {in[24], 5'd07, 32'd025};
|
||||
24'b1110100?????????????????: {next, len, code} = {in[24], 5'd07, 32'd026};
|
||||
24'b01111100????????????????: {next, len, code} = {in[23], 5'd08, 32'd027};
|
||||
24'b00000110????????????????: {next, len, code} = {in[23], 5'd08, 32'd028};
|
||||
24'b00000101????????????????: {next, len, code} = {in[23], 5'd08, 32'd029};
|
||||
24'b01001100????????????????: {next, len, code} = {in[23], 5'd08, 32'd030};
|
||||
24'b10110110????????????????: {next, len, code} = {in[23], 5'd08, 32'd031};
|
||||
24'b00100110????????????????: {next, len, code} = {in[23], 5'd08, 32'd032};
|
||||
24'b11110010????????????????: {next, len, code} = {in[23], 5'd08, 32'd033};
|
||||
24'b010011101???????????????: {next, len, code} = {in[22], 5'd09, 32'd034};
|
||||
24'b001000000???????????????: {next, len, code} = {in[22], 5'd09, 32'd035};
|
||||
24'b010101111???????????????: {next, len, code} = {in[22], 5'd09, 32'd036};
|
||||
24'b010101010???????????????: {next, len, code} = {in[22], 5'd09, 32'd037};
|
||||
24'b010011011???????????????: {next, len, code} = {in[22], 5'd09, 32'd038};
|
||||
24'b010100011???????????????: {next, len, code} = {in[22], 5'd09, 32'd039};
|
||||
24'b010101000???????????????: {next, len, code} = {in[22], 5'd09, 32'd040};
|
||||
24'b1111010101??????????????: {next, len, code} = {in[21], 5'd10, 32'd041};
|
||||
24'b0010001000??????????????: {next, len, code} = {in[21], 5'd10, 32'd042};
|
||||
24'b0101001101??????????????: {next, len, code} = {in[21], 5'd10, 32'd043};
|
||||
24'b0010010100??????????????: {next, len, code} = {in[21], 5'd10, 32'd044};
|
||||
24'b1011001110??????????????: {next, len, code} = {in[21], 5'd10, 32'd045};
|
||||
24'b1111000011??????????????: {next, len, code} = {in[21], 5'd10, 32'd046};
|
||||
24'b0101000000??????????????: {next, len, code} = {in[21], 5'd10, 32'd047};
|
||||
24'b1111110000??????????????: {next, len, code} = {in[21], 5'd10, 32'd048};
|
||||
24'b10110111010?????????????: {next, len, code} = {in[20], 5'd11, 32'd049};
|
||||
24'b11110000011?????????????: {next, len, code} = {in[20], 5'd11, 32'd050};
|
||||
24'b01001111011?????????????: {next, len, code} = {in[20], 5'd11, 32'd051};
|
||||
24'b00101011011?????????????: {next, len, code} = {in[20], 5'd11, 32'd052};
|
||||
24'b01010010100?????????????: {next, len, code} = {in[20], 5'd11, 32'd053};
|
||||
24'b11110111100?????????????: {next, len, code} = {in[20], 5'd11, 32'd054};
|
||||
24'b00100111001?????????????: {next, len, code} = {in[20], 5'd11, 32'd055};
|
||||
24'b10110001010?????????????: {next, len, code} = {in[20], 5'd11, 32'd056};
|
||||
24'b10000010000?????????????: {next, len, code} = {in[20], 5'd11, 32'd057};
|
||||
24'b111111101100????????????: {next, len, code} = {in[19], 5'd12, 32'd058};
|
||||
24'b100000111110????????????: {next, len, code} = {in[19], 5'd12, 32'd059};
|
||||
24'b100000110010????????????: {next, len, code} = {in[19], 5'd12, 32'd060};
|
||||
24'b100000111001????????????: {next, len, code} = {in[19], 5'd12, 32'd061};
|
||||
24'b010100101111????????????: {next, len, code} = {in[19], 5'd12, 32'd062};
|
||||
24'b001000001100????????????: {next, len, code} = {in[19], 5'd12, 32'd063};
|
||||
24'b000001111111????????????: {next, len, code} = {in[19], 5'd12, 32'd064};
|
||||
24'b011111010100????????????: {next, len, code} = {in[19], 5'd12, 32'd065};
|
||||
24'b1110101111101???????????: {next, len, code} = {in[18], 5'd13, 32'd066};
|
||||
24'b0100110101110???????????: {next, len, code} = {in[18], 5'd13, 32'd067};
|
||||
24'b1111111011011???????????: {next, len, code} = {in[18], 5'd13, 32'd068};
|
||||
24'b0101011011001???????????: {next, len, code} = {in[18], 5'd13, 32'd069};
|
||||
24'b0010000101100???????????: {next, len, code} = {in[18], 5'd13, 32'd070};
|
||||
24'b1111111101101???????????: {next, len, code} = {in[18], 5'd13, 32'd071};
|
||||
24'b1011110010110???????????: {next, len, code} = {in[18], 5'd13, 32'd072};
|
||||
24'b0101010111010???????????: {next, len, code} = {in[18], 5'd13, 32'd073};
|
||||
24'b1111011010010???????????: {next, len, code} = {in[18], 5'd13, 32'd074};
|
||||
24'b01010100100011??????????: {next, len, code} = {in[17], 5'd14, 32'd075};
|
||||
24'b10110000110010??????????: {next, len, code} = {in[17], 5'd14, 32'd076};
|
||||
24'b10111101001111??????????: {next, len, code} = {in[17], 5'd14, 32'd077};
|
||||
24'b10110000010101??????????: {next, len, code} = {in[17], 5'd14, 32'd078};
|
||||
24'b00101011001111??????????: {next, len, code} = {in[17], 5'd14, 32'd079};
|
||||
24'b00100000101100??????????: {next, len, code} = {in[17], 5'd14, 32'd080};
|
||||
24'b11111110010111??????????: {next, len, code} = {in[17], 5'd14, 32'd081};
|
||||
24'b10110010100000??????????: {next, len, code} = {in[17], 5'd14, 32'd082};
|
||||
24'b11101011101000??????????: {next, len, code} = {in[17], 5'd14, 32'd083};
|
||||
24'b01010000011111??????????: {next, len, code} = {in[17], 5'd14, 32'd084};
|
||||
24'b101111011001011?????????: {next, len, code} = {in[16], 5'd15, 32'd085};
|
||||
24'b101111010001100?????????: {next, len, code} = {in[16], 5'd15, 32'd086};
|
||||
24'b100000111100111?????????: {next, len, code} = {in[16], 5'd15, 32'd087};
|
||||
24'b001010101011000?????????: {next, len, code} = {in[16], 5'd15, 32'd088};
|
||||
24'b111111100100001?????????: {next, len, code} = {in[16], 5'd15, 32'd089};
|
||||
24'b001001011000010?????????: {next, len, code} = {in[16], 5'd15, 32'd090};
|
||||
24'b011110011001011?????????: {next, len, code} = {in[16], 5'd15, 32'd091};
|
||||
24'b111111111111010?????????: {next, len, code} = {in[16], 5'd15, 32'd092};
|
||||
24'b101111001010011?????????: {next, len, code} = {in[16], 5'd15, 32'd093};
|
||||
24'b100000110000111?????????: {next, len, code} = {in[16], 5'd15, 32'd094};
|
||||
24'b0010010000000101????????: {next, len, code} = {in[15], 5'd16, 32'd095};
|
||||
24'b0010010010101001????????: {next, len, code} = {in[15], 5'd16, 32'd096};
|
||||
24'b1111011010110010????????: {next, len, code} = {in[15], 5'd16, 32'd097};
|
||||
24'b0010010001100100????????: {next, len, code} = {in[15], 5'd16, 32'd098};
|
||||
24'b0101011101110100????????: {next, len, code} = {in[15], 5'd16, 32'd099};
|
||||
24'b0101011010001111????????: {next, len, code} = {in[15], 5'd16, 32'd100};
|
||||
24'b0010000110011111????????: {next, len, code} = {in[15], 5'd16, 32'd101};
|
||||
24'b0101010010000101????????: {next, len, code} = {in[15], 5'd16, 32'd102};
|
||||
24'b1110101011000000????????: {next, len, code} = {in[15], 5'd16, 32'd103};
|
||||
24'b1111000000110010????????: {next, len, code} = {in[15], 5'd16, 32'd104};
|
||||
24'b0111100010001101????????: {next, len, code} = {in[15], 5'd16, 32'd105};
|
||||
24'b00100010110001100???????: {next, len, code} = {in[14], 5'd17, 32'd106};
|
||||
24'b00100010101101010???????: {next, len, code} = {in[14], 5'd17, 32'd107};
|
||||
24'b11111110111100000???????: {next, len, code} = {in[14], 5'd17, 32'd108};
|
||||
24'b00100000111010000???????: {next, len, code} = {in[14], 5'd17, 32'd109};
|
||||
24'b00100111011101001???????: {next, len, code} = {in[14], 5'd17, 32'd110};
|
||||
24'b11111110111000011???????: {next, len, code} = {in[14], 5'd17, 32'd111};
|
||||
24'b11110001101000100???????: {next, len, code} = {in[14], 5'd17, 32'd112};
|
||||
24'b11101011101011101???????: {next, len, code} = {in[14], 5'd17, 32'd113};
|
||||
24'b01010000100101011???????: {next, len, code} = {in[14], 5'd17, 32'd114};
|
||||
24'b00100100110011001???????: {next, len, code} = {in[14], 5'd17, 32'd115};
|
||||
24'b01001110010101000???????: {next, len, code} = {in[14], 5'd17, 32'd116};
|
||||
24'b010011110101001000??????: {next, len, code} = {in[13], 5'd18, 32'd117};
|
||||
24'b111010101110010010??????: {next, len, code} = {in[13], 5'd18, 32'd118};
|
||||
24'b001001001001111000??????: {next, len, code} = {in[13], 5'd18, 32'd119};
|
||||
24'b101111000110111101??????: {next, len, code} = {in[13], 5'd18, 32'd120};
|
||||
24'b101101111010101001??????: {next, len, code} = {in[13], 5'd18, 32'd121};
|
||||
24'b111101110010111110??????: {next, len, code} = {in[13], 5'd18, 32'd122};
|
||||
24'b010100100011010000??????: {next, len, code} = {in[13], 5'd18, 32'd123};
|
||||
24'b001001001111011001??????: {next, len, code} = {in[13], 5'd18, 32'd124};
|
||||
24'b010100110010001001??????: {next, len, code} = {in[13], 5'd18, 32'd125};
|
||||
24'b111010110000111000??????: {next, len, code} = {in[13], 5'd18, 32'd126};
|
||||
24'b111010110011000101??????: {next, len, code} = {in[13], 5'd18, 32'd127};
|
||||
24'b010100001000111001??????: {next, len, code} = {in[13], 5'd18, 32'd128};
|
||||
24'b1000001011000110100?????: {next, len, code} = {in[12], 5'd19, 32'd129};
|
||||
24'b0010010111001110110?????: {next, len, code} = {in[12], 5'd19, 32'd130};
|
||||
24'b0101011001000001101?????: {next, len, code} = {in[12], 5'd19, 32'd131};
|
||||
24'b0101000010010101011?????: {next, len, code} = {in[12], 5'd19, 32'd132};
|
||||
24'b1111011111101001101?????: {next, len, code} = {in[12], 5'd19, 32'd133};
|
||||
24'b1011001000101010110?????: {next, len, code} = {in[12], 5'd19, 32'd134};
|
||||
24'b1011000001000100001?????: {next, len, code} = {in[12], 5'd19, 32'd135};
|
||||
24'b1110101100010011001?????: {next, len, code} = {in[12], 5'd19, 32'd136};
|
||||
24'b0010010111010111110?????: {next, len, code} = {in[12], 5'd19, 32'd137};
|
||||
24'b0010010001100111100?????: {next, len, code} = {in[12], 5'd19, 32'd138};
|
||||
24'b1011001011100000101?????: {next, len, code} = {in[12], 5'd19, 32'd139};
|
||||
24'b1011000100010100101?????: {next, len, code} = {in[12], 5'd19, 32'd140};
|
||||
24'b1111111001000111011?????: {next, len, code} = {in[12], 5'd19, 32'd141};
|
||||
24'b00100010111101101101????: {next, len, code} = {in[11], 5'd20, 32'd142};
|
||||
24'b10000010101010101101????: {next, len, code} = {in[11], 5'd20, 32'd143};
|
||||
24'b10110010100101001101????: {next, len, code} = {in[11], 5'd20, 32'd144};
|
||||
24'b01010110111100010000????: {next, len, code} = {in[11], 5'd20, 32'd145};
|
||||
24'b10110111110011001001????: {next, len, code} = {in[11], 5'd20, 32'd146};
|
||||
24'b11111101101100100101????: {next, len, code} = {in[11], 5'd20, 32'd147};
|
||||
24'b10110000010100100001????: {next, len, code} = {in[11], 5'd20, 32'd148};
|
||||
24'b10110010011010110110????: {next, len, code} = {in[11], 5'd20, 32'd149};
|
||||
24'b01111001010000011000????: {next, len, code} = {in[11], 5'd20, 32'd150};
|
||||
24'b11110110001011011011????: {next, len, code} = {in[11], 5'd20, 32'd151};
|
||||
24'b01010000100100001011????: {next, len, code} = {in[11], 5'd20, 32'd152};
|
||||
24'b10110001100101110111????: {next, len, code} = {in[11], 5'd20, 32'd153};
|
||||
24'b10111100110111101000????: {next, len, code} = {in[11], 5'd20, 32'd154};
|
||||
24'b01010001010111010000????: {next, len, code} = {in[11], 5'd20, 32'd155};
|
||||
24'b01010100111110001110????: {next, len, code} = {in[11], 5'd20, 32'd156};
|
||||
24'b11111110011001100111????: {next, len, code} = {in[11], 5'd20, 32'd157};
|
||||
24'b11110111111101010001????: {next, len, code} = {in[11], 5'd20, 32'd158};
|
||||
24'b10110000010111100000????: {next, len, code} = {in[11], 5'd20, 32'd159};
|
||||
24'b01001111100001000101????: {next, len, code} = {in[11], 5'd20, 32'd160};
|
||||
24'b01010010000111010110????: {next, len, code} = {in[11], 5'd20, 32'd161};
|
||||
24'b11101010101011101111????: {next, len, code} = {in[11], 5'd20, 32'd162};
|
||||
24'b11111110010011100011????: {next, len, code} = {in[11], 5'd20, 32'd163};
|
||||
24'b01010111001111101111????: {next, len, code} = {in[11], 5'd20, 32'd164};
|
||||
24'b10110001111111111101????: {next, len, code} = {in[11], 5'd20, 32'd165};
|
||||
24'b10110001001100110000????: {next, len, code} = {in[11], 5'd20, 32'd166};
|
||||
24'b11110100011000111101????: {next, len, code} = {in[11], 5'd20, 32'd167};
|
||||
24'b00101011101110100011????: {next, len, code} = {in[11], 5'd20, 32'd168};
|
||||
24'b01010000011011111110????: {next, len, code} = {in[11], 5'd20, 32'd169};
|
||||
24'b00000111000010000010????: {next, len, code} = {in[11], 5'd20, 32'd170};
|
||||
24'b00101010000011001000????: {next, len, code} = {in[11], 5'd20, 32'd171};
|
||||
24'b01001110010100101110????: {next, len, code} = {in[11], 5'd20, 32'd172};
|
||||
24'b11110000000010000000????: {next, len, code} = {in[11], 5'd20, 32'd173};
|
||||
24'b01001101011001111001????: {next, len, code} = {in[11], 5'd20, 32'd174};
|
||||
24'b11110111000111010101????: {next, len, code} = {in[11], 5'd20, 32'd175};
|
||||
24'b01111001101001110110????: {next, len, code} = {in[11], 5'd20, 32'd176};
|
||||
24'b11110000101011101111????: {next, len, code} = {in[11], 5'd20, 32'd177};
|
||||
24'b00100100100110101010????: {next, len, code} = {in[11], 5'd20, 32'd178};
|
||||
24'b11110001011011000011????: {next, len, code} = {in[11], 5'd20, 32'd179};
|
||||
24'b01010111001000110011????: {next, len, code} = {in[11], 5'd20, 32'd180};
|
||||
24'b01111000000100010101????: {next, len, code} = {in[11], 5'd20, 32'd181};
|
||||
24'b00100101101011001101????: {next, len, code} = {in[11], 5'd20, 32'd182};
|
||||
24'b10110010110000111001????: {next, len, code} = {in[11], 5'd20, 32'd183};
|
||||
24'b10110000101010000011????: {next, len, code} = {in[11], 5'd20, 32'd184};
|
||||
24'b00100100111110001101????: {next, len, code} = {in[11], 5'd20, 32'd185};
|
||||
24'b01111001101001101011????: {next, len, code} = {in[11], 5'd20, 32'd186};
|
||||
24'b01010001000000010001????: {next, len, code} = {in[11], 5'd20, 32'd187};
|
||||
24'b11110101111111101110????: {next, len, code} = {in[11], 5'd20, 32'd188};
|
||||
24'b10000010111110110011????: {next, len, code} = {in[11], 5'd20, 32'd189};
|
||||
24'b00000100011110100111????: {next, len, code} = {in[11], 5'd20, 32'd190};
|
||||
24'b11111101001111101100????: {next, len, code} = {in[11], 5'd20, 32'd191};
|
||||
24'b00101011100011110000????: {next, len, code} = {in[11], 5'd20, 32'd192};
|
||||
24'b00100100111001011001????: {next, len, code} = {in[11], 5'd20, 32'd193};
|
||||
24'b10000010101000000100????: {next, len, code} = {in[11], 5'd20, 32'd194};
|
||||
24'b11110001001000111100????: {next, len, code} = {in[11], 5'd20, 32'd195};
|
||||
24'b10111100011010011001????: {next, len, code} = {in[11], 5'd20, 32'd196};
|
||||
24'b000000??????????????????: begin
|
||||
casez (in[33:32])
|
||||
2'b1?: {next, len, code} = {1'b0, 5'd18, 32'd197};
|
||||
2'b01: {next, len, code} = {1'b0, 5'd19, 32'd198};
|
||||
2'b00: {next, len, code} = {1'b0, 5'd19, 32'd199};
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
@@ -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 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t/t_case_default_bad.v:\d+: Multiple default statements in case statement.
|
||||
|
||||
@@ -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 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t/t_case_genx_bad.v:\d+: Use of x/\? constant in generate case statement, \(no such thing as \'generate casez\'\)
|
||||
|
||||
@@ -60,6 +60,9 @@ module sub (/*AUTOARG*/
|
||||
output reg [4:0] out2;
|
||||
|
||||
always @* begin
|
||||
// Test empty cases
|
||||
casez (in[0])
|
||||
endcase
|
||||
casez (in)
|
||||
24'b0000_0000_0000_0000_0000_0000 : {out1,out2} = {1'b0,5'h00};
|
||||
24'b????_????_????_????_????_???1 : {out1,out2} = {1'b1,5'h00};
|
||||
|
||||
@@ -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 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t/t_case_x_bad.v:\d+: Use of x/. constant in case statement, \(perhaps intended casex/casez\)
|
||||
|
||||
@@ -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 (
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user