Compare commits

...
58 Commits
Author SHA1 Message Date
Wilson Snyder c5f0ed9c99 Fix makefile typo, and remove unneeded PWD variable
git-svn-id: file://localhost/svn/verilator/trunk/verilator@844 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-18 20:05:02 +00:00
Wilson Snyder 2ce30e78a1 Move some test_v tests into test_regress area
git-svn-id: file://localhost/svn/verilator/trunk/verilator@843 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-18 19:49:36 +00:00
Wilson Snyder 3b554f4c5b Rename config.h to config_build.h, and add cross compile notes.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@842 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-18 19:20:45 +00:00
Wilson Snyder cf40fd356f Fix split list ordering causing circular refs
git-svn-id: file://localhost/svn/verilator/trunk/verilator@841 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-18 18:20:13 +00:00
Wilson Snyder 8848469bf9 Fix dotted references into generate fors
git-svn-id: file://localhost/svn/verilator/trunk/verilator@840 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-18 18:14:53 +00:00
Wilson Snyder 4100417f83 Show known scopes when dotted errors show up
git-svn-id: file://localhost/svn/verilator/trunk/verilator@839 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-15 22:28:18 +00:00
Wilson Snyder bd6d743f9c Move configure.in to configure.ac
git-svn-id: file://localhost/svn/verilator/trunk/verilator@838 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-15 21:18:41 +00:00
Wilson Snyder 857ac24ba7 Fix dotted ref signals under generate cells
git-svn-id: file://localhost/svn/verilator/trunk/verilator@837 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-12 18:25:33 +00:00
Wilson Snyder 5672b99203 Add t_extend_class example
git-svn-id: file://localhost/svn/verilator/trunk/verilator@836 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-10 22:48:26 +00:00
Wilson Snyder 3d8de3194c Fix SuSE10.0 compile warnings
git-svn-id: file://localhost/svn/verilator/trunk/verilator@833 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-05 15:24:38 +00:00
Wilson Snyder 8b91a9f898 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@832 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-12-05 15:12:19 +00:00
Wilson Snyder 038ee69a96 Add M32 make variable
git-svn-id: file://localhost/svn/verilator/trunk/verilator@831 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-11-02 19:13:07 +00:00
Wilson Snyder 8986d1f16f Avoid some duplicate sensitivity ifs.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@830 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-26 01:20:49 +00:00
Wilson Snyder 86c8e7b3e6 Add --output-split-cfuncs for accelerating GCC.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@829 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-26 01:08:44 +00:00
Wilson Snyder 9026118a7c Fix (blah) with width violation
git-svn-id: file://localhost/svn/verilator/trunk/verilator@828 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-25 21:41:32 +00:00
Wilson Snyder 58fc922737 Test fix
git-svn-id: file://localhost/svn/verilator/trunk/verilator@825 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-18 13:56:54 +00:00
Wilson Snyder 3b5c791332 Test fix
git-svn-id: file://localhost/svn/verilator/trunk/verilator@824 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-18 13:54:36 +00:00
Wilson Snyder 6e16bc1b7b Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@823 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-18 13:50:44 +00:00
Wilson Snyder 1aba0f6379 Show error code on non-generic errors; add TASKNSVAR
git-svn-id: file://localhost/svn/verilator/trunk/verilator@822 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-18 13:45:50 +00:00
Wilson Snyder 11cfa3c072 Suppress unused warnings using attribute
git-svn-id: file://localhost/svn/verilator/trunk/verilator@821 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-18 12:59:30 +00:00
Wilson Snyder 59141b1678 Fix --skip-identical
git-svn-id: file://localhost/svn/verilator/trunk/verilator@820 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-12 14:01:06 +00:00
Wilson Snyder 2083c071ce Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@817 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-11 15:42:32 +00:00
Wilson Snyder 3ad5872d30 Add verilator no_inline_task
git-svn-id: file://localhost/svn/verilator/trunk/verilator@816 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-11 15:41:42 +00:00
Wilson Snyder ea6bb21cdc Fix V3Subst mis-optimizing concats in t_case_write
git-svn-id: file://localhost/svn/verilator/trunk/verilator@815 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-11 15:34:50 +00:00
Wilson Snyder 3d4fe0364a No functional change; have V3Subst use a sub-structure.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@814 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-11 14:13:37 +00:00
Wilson Snyder 710d7c0ee5 Fix link error when using --exe with --trace.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@813 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-09 13:38:15 +00:00
Wilson Snyder 1c8fd37745 Fix some Coverity Prevent warnings
git-svn-id: file://localhost/svn/verilator/trunk/verilator@812 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-06 16:08:46 +00:00
Wilson Snyder 956c854662 Add t_case_write test
git-svn-id: file://localhost/svn/verilator/trunk/verilator@811 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-05 17:54:52 +00:00
Wilson Snyder 318a6e348c Support wide public task outputs.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@810 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-05 14:53:17 +00:00
Wilson Snyder e471a34323 Add maybePointedTo to v3Broken for better and faster checks
git-svn-id: file://localhost/svn/verilator/trunk/verilator@809 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-05 00:45:39 +00:00
Wilson Snyder 95c5b85e88 Unlink .vpp files without --debug
git-svn-id: file://localhost/svn/verilator/trunk/verilator@808 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-04 18:46:42 +00:00
Wilson Snyder a46a556a64 Don't coredump without --debug
git-svn-id: file://localhost/svn/verilator/trunk/verilator@807 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-04 15:46:13 +00:00
Wilson Snyder fa3e03e071 version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@804 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-04 12:57:29 +00:00
Wilson Snyder 74d7c55f1b Fix dotted variables in always sensitivity lists.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@803 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-03 13:02:21 +00:00
Wilson Snyder 79e02858cb Add --debug-check flag
git-svn-id: file://localhost/svn/verilator/trunk/verilator@802 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-10-02 17:09:56 +00:00
Wilson Snyder 7738b202ac Remove --bin from perl shell, use argv[0] instead
git-svn-id: file://localhost/svn/verilator/trunk/verilator@801 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-30 00:27:05 +00:00
Wilson Snyder b4d4917c6c Fix coredump in XREFs under FUNCREF's
git-svn-id: file://localhost/svn/verilator/trunk/verilator@800 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-30 00:08:09 +00:00
Wilson Snyder 5c93520b27 Associative same variable elimination
git-svn-id: file://localhost/svn/verilator/trunk/verilator@799 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-28 14:37:28 +00:00
Wilson Snyder 94f0809d33 Add more boolean identity fixes
git-svn-id: file://localhost/svn/verilator/trunk/verilator@798 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-27 18:00:53 +00:00
Wilson Snyder ca4e3c1737 Eliminate assigned only variables
git-svn-id: file://localhost/svn/verilator/trunk/verilator@797 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-26 17:05:08 +00:00
Wilson Snyder ba7b4f261a Redo V3Life to also do constant propagation
git-svn-id: file://localhost/svn/verilator/trunk/verilator@796 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-26 15:05:35 +00:00
Wilson Snyder 4f42c25c7c Fix inout task arguments
git-svn-id: file://localhost/svn/verilator/trunk/verilator@795 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-25 20:40:52 +00:00
Wilson Snyder 621ef70c31 Allow overriding PERL, YACC, LEX versions.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@794 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-25 15:58:17 +00:00
Wilson Snyder e3f17e7853 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@791 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-20 13:25:03 +00:00
Wilson Snyder 73c897ac69 Fix printf ULL warnings with a cast.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@790 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-20 13:24:18 +00:00
Wilson Snyder a4db880809 Use vluint8/16/64 in source code
git-svn-id: file://localhost/svn/verilator/trunk/verilator@789 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-19 15:27:15 +00:00
Wilson Snyder f9697463cc Have preprocessor strip all DOS returns
git-svn-id: file://localhost/svn/verilator/trunk/verilator@788 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-13 14:38:48 +00:00
Wilson Snyder f283076570 Rename {newline} in lex; no functional change
git-svn-id: file://localhost/svn/verilator/trunk/verilator@787 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-13 13:18:24 +00:00
Wilson Snyder e15228498d Define VL_PRINTF by default, and remove old coverageRequest
git-svn-id: file://localhost/svn/verilator/trunk/verilator@786 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-12 00:55:27 +00:00
Wilson Snyder 53155b3a36 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@783 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-11 20:44:54 +00:00
Wilson Snyder 12ae70ba95 Prep for removing begin under first generate, but doesn't work. Commentary instead
git-svn-id: file://localhost/svn/verilator/trunk/verilator@782 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-11 20:42:47 +00:00
Wilson Snyder 88809587f9 Fix function references under top inlined module.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@781 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-08 16:16:30 +00:00
Wilson Snyder 1b20481100 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@778 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-06 17:50:47 +00:00
Wilson Snyder 21eb939f37 Allow dotted references of arrayed cells
git-svn-id: file://localhost/svn/verilator/trunk/verilator@777 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-06 17:48:41 +00:00
Wilson Snyder 0a765fbb54 Fix function calls inside loop bounds
git-svn-id: file://localhost/svn/verilator/trunk/verilator@776 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-05 20:06:23 +00:00
Wilson Snyder 749fdaae31 Optimize n*powers of 2. (For parameterized DDR model)
git-svn-id: file://localhost/svn/verilator/trunk/verilator@775 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-01 16:53:14 +00:00
Wilson Snyder 6f48185a1f Fix arrayed instances
git-svn-id: file://localhost/svn/verilator/trunk/verilator@774 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-01 15:31:07 +00:00
Wilson Snyder 7f1b16837e Fix dead modules under generate cells not getting removed
git-svn-id: file://localhost/svn/verilator/trunk/verilator@773 77ca24e4-aefa-0310-84f0-b9a241c72d87
2006-09-01 14:05:20 +00:00
238 changed files with 11425 additions and 1170 deletions
+81 -5
View File
@@ -3,9 +3,76 @@ 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.60**
* Verilator 3.62***
*** Changed how internal functions are invoked to avoid aliasing in GCC 3.3+.
*** Fixed configure and compiling under Solaris. [Bob Farrell]
*** When dotted signal lookup fails, help the user by showing known scopes.
**** Fix dotted references inside generated cells. [David Hewson]
**** Fix 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]
**** 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]
* Verilator 3.621 10/11/2006 Beta
** Add /*verilator no_inline_task*/ to prevent over-expansion. [Eugene Weber]
*** Public functions now allow > 64 bit arguments.
**** Remove .vpp intermediate files when not under --debug.
**** Fix link error when using --exe with --trace. [Eugene Weber]
**** Fix mis-optimization of wide concats with constants.
**** Fix core dump on printing error when not under --debug. [Allan Cochrane]
* Verilator 3.620 10/04/2006 Stable
*** Support simple inout task ports. [Eugene Weber]
*** Allow overriding Perl, Flex and Bison versions. [by Robert Farrell]
*** Optimize variables set to constants within basic blocks for ~3%.
**** Default make no longer makes the docs; if you edit the documentation.
sources, run "make info" to get them.
**** Optimize additional boolean identities (a|a = a, etc.)
**** Fix coredump when dotted cross-ref inside task call. [Eugene Weber]
**** Fix dotted variables in always sensitivity lists. [Allan Cochrane]
* Verilator 3.610 09/20/2006 Stable
*** Verilator now works under DJGPP (Pentium GCC). [John Stroebel]
**** Add default define for VL_PRINTF. [John Stroebel]
**** Removed coverage request variable; see Coverage limitations in docs.
**** Fix DOS carrage returns in multiline defines. [Ralf Karge]
**** Fix printf format warnings on 64-bit linux.
* Verilator 3.602 09/11/2006 Stable
**** Fix 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.
@@ -13,13 +80,22 @@ indicates the contributor was also the author of the fix; Thanks!
*** Added -MP to make phony dependencies, ala GCC's.
**** Declare optimized lookup tables as 'static', to reduce D-Cache miss rate.
*** 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]
**** Fix coredump when unused modules have unused cells. [David Hewson]
**** Fix 3.600 internal error with arrayed instances. [David Hewson]
**** Fix 3.600 internal error with non-unrolled function loops. [David Hewson]
**** Fix $display %m name not matching Verilog name inside SystemC modules.
* Verilator 3.600 08/28/2006
**** Declare optimized lookup tables as 'static', to reduce D-Cache miss rate.
* Verilator 3.600 08/28/2006 Beta
** Support dotted cross-hierarchy variable and task references.
@@ -386,7 +462,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Added NC Verilog as alternative to VCS for reference tests.
**** Support implicit wire declarations on input-only signals.
(Dangerous, as leads to wires without drivers, but allowed by spec.)
(Dangerous, as leads to wires without drivers, but allowed by spec.)
**** Fixed compile warnings on Suse 9.1
+10 -11
View File
@@ -78,7 +78,6 @@ datadir = @datadir@
infodir = @infodir@
# Directory in which to install package specific files
# Note this gets coded into v3c/config.h also
pkgdatadir = @pkgdatadir@
#### End of system configuration section. ####
@@ -91,7 +90,7 @@ SUBDIRS = src test_verilated test_c test_sc test_sp test_regress test_vcs
INFOS = README verilator.txt verilator.html verilator.1 verilator.pdf
# Files that can be generated, but should be up to date for a distribution.
DISTDEP = $(INFOS) Makefile
DISTDEP = info Makefile
# Files to distribute.
DISTBIN = $(wildcard bin/verilator-*)
@@ -126,7 +125,7 @@ INST_PROJ_BIN_FILES = \
DISTFILES := $(DISTFILES_INC)
all: all_nomsg msg_test
all_nomsg: verilator_exe info
all_nomsg: verilator_exe
.PHONY:verilator_exe
verilator_exe verilator_bin verilator_bin_dbg:
@@ -218,7 +217,7 @@ installman:
$(INSTALL_PROGRAM) $$p $(mandir)/man1/$$p; \
done
install: all_nomsg info installdirs installbin installman install-msg
install: all_nomsg installdirs installbin installman install-msg
install-here: installman ftp
@@ -265,16 +264,16 @@ uninstall:
-cd $(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
-cd $(bindir) && rm -f $(VL_INST_BIN_FILES)
# autoheader might not change config.h.in, so touch a stamp file.
# autoheader might not change config_build.h.in, so touch a stamp file.
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
*.in */*.in */*.in
${srcdir}/config.h.in: stamp-h.in
${srcdir}/stamp-h.in: configure.in $(wildcard $(IN_WILD))
${srcdir}/config_build.h.in: stamp-h.in
${srcdir}/stamp-h.in: configure.ac $(wildcard $(IN_WILD))
cd ${srcdir} && autoheader
echo timestamp > ${srcdir}/stamp-h.in
config.h: stamp-h
stamp-h: config.h.in config.status
config_build.h: stamp-h
stamp-h: config_build.h.in config.status
./config.status
Makefile: Makefile.in config.status
./config.status
@@ -282,7 +281,7 @@ src/Makefile: src/Makefile.in config.status
./config.status
config.status: configure
./config.status --recheck
configure: configure.in
configure: configure.ac
autoconf
maintainer-clean::
@@ -317,7 +316,7 @@ TAGS: $(TAGFILES)
######################################################################
# Distributions
DISTCONFIG = src/config.h.in
DISTCONFIG = src/config_build.h.in
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
+1
View File
@@ -97,6 +97,7 @@ Performance:
Track recirculation and convert into clock-enables
Clock enables should become new clocking domains for speed
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)
//**********************************************************************
//* Detailed notes on 'todo' features
+247 -65
View File
@@ -113,7 +113,6 @@ if ($Opt_Sp eq 'sp' || $Opt_Trace) {
# Determine runtime flags
my $vcmd =(($opt_gdb?"$opt_gdb ":"")
.verilator_bin()
." --bin ".verilator_bin() # So we get binary name into .d file
." ".join(' ',@Opt_Verilator_Sw)
);
@@ -169,7 +168,7 @@ sub run {
warn "%Error: export VERILATOR_ROOT=$ENV{VERILATOR_ROOT}\n";
warn "%Error: $command\n";
}
die "%Error: Command Failed $command, $status, stopped";
die "%Error: Command Failed $command\n";
}
}
@@ -234,6 +233,13 @@ linking with make rules you write yourself.
Enable all assertions, includes enabling the --psl flag. (If psl is not
desired, but other assertions are, use --assert --nopsl.)
=item --bin I<filename>
Rarely needed. Override the default filename for Verilator itself. When a
dependancy (.d) file is created, this filename will become a source
dependency, such that a change in this binary will have make rebuild the
output files.
=item --cc
Specifies C++ without SystemC output mode; see also --sc and --sp.
@@ -248,9 +254,9 @@ Specifies basic block line coverage analysis code should be inserted.
Coverage analysis adds statements at each code flow change point, which are
the branches of IF and CASE statements, a superset of normal Verilog Line
Coverage. At each such branch a C++ macro is called, which SystemPerl uses
to increment an array. At the end of a test, logs/coverage.pl is written
with the data from the array.
Coverage. At each such branch a unique counter is incremented. At the end
of a test, the counters along with the filename and line number
corresponding to each counter are written into logs/coverage.pl.
After running multiple tests, the vcoverage utility (from the SystemPerl
package) is executed. Vcoverage reads the logs/coverage.pl file(s), and
@@ -261,6 +267,10 @@ them, as it is assumed $stop branches contain an error check that should
not occur. A /*verilator coverage_block_off*/ comment will perform a
similar function on any code in that block or below.
Note Verilator may over-count combinatorial (non-clocked) blocks when those
blocks receive signals which have had the UNOPTFLAT warning disabled; for
most accurate results do not disable this warning when using coverage.
For an example, after running 'make test' in the Verilator distribution,
see the test_sp/logs/coverage_source directory. Grep for lines starting
with '%' to see what lines Verilator believes need more coverage.
@@ -279,8 +289,13 @@ the comment "DefaultClock":
=item --debug
Select the debug built image of Verilator (if available), and enable
debugging messages and intermediate form dump files.
Select the debug built image of Verilator (if available), and enable more
internal assertions, debugging messages, and intermediate form dump files.
=item --debug-check
Rarely needed. Enable internal debugging assertion checks, without
changing debug verbosity. Enabled automatically when --debug specified.
=item -E
@@ -299,10 +314,10 @@ Displays this message and program version and exits.
=item --inhibit-sim
Create a "inhibitSim(bool)" function to enable and disable evaluation.
This allows a upper level testbench to disable modules that are not
important in a given simulation, without needing to recompile or change the
SystemC modules instantiated.
Rarely needed. Create a "inhibitSim(bool)" function to enable and disable
evaluation. This allows a upper level testbench to disable modules that
are not important in a given simulation, without needing to recompile or
change the SystemC modules instantiated.
=item --inline-mult I<value>
@@ -335,8 +350,8 @@ the same as --prefix.
=item --no-skip-identical
Disables skipping execution of Verilator if all source files are identical,
and all output files exist with newer dates.
Rarely needed. Disables skipping execution of Verilator if all source
files are identical, and all output files exist with newer dates.
=item -O0
@@ -349,11 +364,11 @@ cost of compile time. This currently sets --inline-mult -1.
=item -OI<optimization-letter>
Enables or disables a specific optimizations, with the optimization
selected based on the letter passed. A lowercase letter disables an
optimization, an upper case letter enables it. This is intended for
debugging use only; see the source code for version-dependent mappings of
optimizations to -O letters.
Rarely needed. Enables or disables a specific optimizations, with the
optimization selected based on the letter passed. A lowercase letter
disables an optimization, an upper case letter enables it. This is
intended for debugging use only; see the source code for version-dependent
mappings of optimizations to -O letters.
=item --output-split I<bytes>
@@ -362,9 +377,18 @@ C++ file exceeds the specified number of operations, a new file will be
created. In addition, any slow routines will be placed into __Slow files.
This accelerates compilation by as optimization can be disabled on the slow
routines, and the remaining files can be compiled on parallel machines.
Using --output-split should have only a trivial impact on performance.
With GCC 3.3 on a 2GHz Opteron, --output-split 20000 will result in
splitting into approximately one-minute-compile chunks.
=item --output-split-cfuncs I<statements>
Enables splitting functions in the output .cpp/.sp files into multiple
functions. When a generated function exceeds the specified number of
operations, a new function will be created. With --output-split, this will
enable GCC to compile faster, at a small loss in performance that increases
with smaller statement values.
=item --pins64
Specifies SystemC outputs of 33-64 bits wide should use uint64_t instead of
@@ -392,17 +416,20 @@ compatibility.
=item --psl
Enable PSL parsing. Without this switch, psl meta-comments are ignored.
Enable PSL parsing. Without this switch, PSL meta-comments are ignored.
See the --assert flag to enable all assertions, and --coverage-user to
enable functional coverage.
=item --public
This is only for debug, and 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. This
will also turn off inlining as if all modules had a /*verilator
public_module*/, unless the module specifically enabled it with /*verilator
inline_module*/.
optimizations as if all signals had a /*verilator public*/ comments and
inlining. This will also turn off inlining as if all modules had a
/*verilator public_module*/, unless the module specifically enabled it with
/*verilator inline_module*/.
=item --sc
@@ -424,10 +451,10 @@ on during model execution.
=item --underline-zero
Signals starting with a underline should be initialized to zero, as was
done in Verilator 2. Default is for all signals including those with
underlines being randomized. This option may be depreciated in future
versions.
Rarely needed. Signals starting with a underline should be initialized to
zero, as was done in Verilator 2. Default is for all signals including
those with underlines being randomized. This option may be depreciated in
future versions.
=item -Werror-I<message>
@@ -548,7 +575,7 @@ And we get as output
Hello World
- our.v:2: Verilog $finish
Really, you're better off using a Makefile to do all this for you. Then,
Really, you're better off writing a Makefile to do all this for you. Then,
when your source changes it will automatically run all of these steps. See
the test_c directory in the distribution for an example.
@@ -591,7 +618,7 @@ Then we convert the SystemPerl output to SystemC.
$SYSTEMPERL/sp_preproc --preproc *.sp
(You can also skip the above sp_preproc by getting pure SystemC from
verilator by replacing the verilator --sp flag in the previous step with
Verilator by replacing the verilator --sp flag in the previous step with
-sc.)
We then can compile it
@@ -702,7 +729,7 @@ In certain optimization modes, it also creates:
It also creates internal files that can be mostly ignored:
{each_verilog_module}.vpp // Post-processed verilog source code
{each_verilog_module}.vpp // Post-processed verilog (--debug)
{prefix}.flags_vbin // Verilator dependencies
{prefix}.flags_vpp // Pre-processor dependencies
{prefix}{misc}.d // Make dependencies (-MMD)
@@ -828,6 +855,30 @@ Lower modules are not pure SystemC code. This is a feature, as using the
SystemC pin interconnect scheme everywhere would reduce performance by an
order of magnitude.
=head1 CROSS COMPILATION
Verilator supports cross-compling Verilated code. This is generally used
to run Verilator on a Linux system and produce C++ code that is then compiled
on Windows.
Cross compilation involves up to three different OSes. The build system is
where you configured and compiled Verilator, the host system where you run
Verilator, and the target system where you compile the Verilated code and
run the simulation.
Currently, Verilator requires the build and host system type to be the
same, though the target system type may be different. To support this,
./configure and make Verilator on the build system. Then, run Verilator on
the host system. Finally, the output of Verilator may be compiled on the
different target system.
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
configure.
=head1 VERILOG 2001 SUPPORT
Verilator supports the more common Verilog 2001 language features. This
@@ -920,7 +971,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 hardcoding variable
output C++ code. For input arguments, rather then 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
@@ -936,9 +987,9 @@ each different output width.
=item $display, $write, $fdisplay, $fwrite
$display format arguments may use C fprintf sizes after the % escape. Per
the Verilog standard, %x prints a number with the natural width, %0x prints
a number with minimum width, however %5x prints 5 digits per the C standard
Format arguments may use C fprintf sizes after the % escape. Per the
Verilog standard, %x prints a number with the natural width, %0x prints a
number with minimum width, however %5x prints 5 digits per the C standard
(it's unspecified in Verilog).
=item $fopen, $fclose, $fdisplay, $fwrite
@@ -1038,6 +1089,14 @@ 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*/
Used in a function or task variable definition section to specify the
function or task should not be inlined into where it is used. This may
reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself.
=item /*verilator sc_clock*/
Used after a input declaration to indicate the signal should be declared in
@@ -1057,7 +1116,7 @@ Re-enable waveform tracing for all future signals that are declared.
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. Set for all signals when using the --public switch.
of the signal.
=item /*verilator public*/ (task/function)
@@ -1070,9 +1129,9 @@ function. Any output arguments will become C++ reference arguments. Any
local registers/integers will become function automatic variables on the
stack.
Wide variables over 64 bits cannot be I/O to the module, to avoid exposing
complexities; generally the cleanest technique is to pass a word number to
the function, and do appropriate bit selection.
Wide variables over 64 bits cannot be function returns, to avoid exposing
complexities. However, wide variables can be input/outputs; they will be
passed as references to an array of 32 bit numbers.
This feature is still somewhat experimental. Generally, only the values of
stored state (flops) should be written, as the model will NOT notice
@@ -1116,7 +1175,25 @@ always @* to prevent these issues.)
Verilator supports dotted references to variables, functions and tasks in
different modules. However, references into named blocks and function-local
variables are not supported.
variables are not supported. References into arrayed and generated
instances work, but still require some work-arounds in the Verilog code:
References into arrayed instances use different names from the Verilog
standard; arrayed instances are named {cellName}__{instanceNumber}. For
example a[2] is instead a__2. Thus you cannot use a parameter or variable
to select the index number; expand it into a case statement manually.
References into generate statements also use different names from the
Verilog standard; the top level generate, any begin statement, and any
place where there is a implied begin statement (under each generate-if or
generate-case) adds a hierarchy level named genblkI<instanceNumber>. And
each generate-for adds genforI<loopCount>. The best bet is to comment out
the references and run with --debug and look in the at the _begin.tree
file, and see the hierarchy by looking at the names of all of the CELLs in
question. Replace __DOT__ with . in your program. For example most cells
under a for loop would be something like
"genblk__DOT__genfor0__DOT__I<cellname>"; so use genblk.genfor0.I<cellname> to
see inside that cell.
=head2 Latches
@@ -1230,7 +1307,12 @@ 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.
=head1 ERRORS
=item $display, $write, $fdisplay, $fwrite
$display and friends must have a constant format string as the first
argument (as with C's printf), you cannot simply list variables standalone.
=head1 ERRORS AND WARNINGS
Warnings may be disabled in two ways. First, when the warning is
printed it will include a warning code. Simply surround the offending
@@ -1240,13 +1322,13 @@ line with a warn_off/warn_on pair:
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
// verilator lint_on UNSIGNED
They may also be globally disabled by invoking Verilator with the
C<-Wno-I<warning>> switch. This should be avoided, as it removes
all checking across the designs, and prevents other users from
compiling your code without knowing the magic set of disables needed
to successfully compile your design.
Warnings may also be globally disabled by invoking Verilator with the
C<-Wno-I<warning>> switch. This should be avoided, as it removes all
checking across the designs, and prevents other users from compiling your
code without knowing the magic set of disables needed to successfully
compile your design.
Warnings:
List of all warnings:
=over 4
@@ -1303,12 +1385,41 @@ 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/>
=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.
=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.
=item TASKNSVAR
Error when a call to a task or function has a output from that task tied to
a non-simple signal. Instead connect the task output to a temporary signal
of the appropriate width, and use that signal to set the appropriate
expression as the next statement. For example:
task foo; output sig; ... endtask
always @* begin
foo(bus_we_select_from[2]); // Will get TASKNSVAR error
end
Change this to:
reg foo_temp_out;
always @* begin
foo(foo_temp_out);
bus_we_select_from[2] = foo_temp_out;
end
Verilator doesn't do this conversion for you, as some more complicated
cases would result in simulator mismatches.
=item UNDRIVEN
Warns that the specified signal is never sourced.
@@ -1334,11 +1445,11 @@ may be only one particular usage of a multiply instantiated block. The
construct should be cleaned up to improve runtime; two times better
performance may be possible by fixing these warnings.
Unlike UNOPT this occurs after netlist flattening, and indicates a more
basic problem, as the less obvious case described under UNOPT does not
apply.
Unlike the UNOPT warning, this occurs after netlist flattening, and
indicates a more basic problem, as the less obvious case described under
UNOPT does not apply.
Often this is caused by logic that isn't truly circular as viewed by
Often UNOPTFLAT is caused by logic that isn't truly circular as viewed by
synthesis which analyzes interconnection per-bit, but is circular to
simulation which analyzes per-bus:
@@ -1346,10 +1457,32 @@ simulation which analyzes per-bus:
This statement needs to be evaluated multiple times, as a change in
"shift_in" requires "x" to be computed 3 times before it becomes stable.
This is because a change in "x" requires "x" itself to change value, which
causes the warning.
For significantly better performance, split this into 2 separate signals:
wire [2:1] x_21 = x[1:0];
wire [0:0] x_0 = shift_in;
wire [2:0] xout = {x[1:0],shift_in};
and change all receiving logic to instead receive "xout". Alternatively,
change it to
wire [2:0] x = {xin[1:0],shift_in};
and change all driving logic to instead drive "xin".
With this change this assignment needs to be evaluated only once. These
sort of changes may also speed up your traditional event driven simulator,
as it will result in fewer events per cycle.
The most complicated UNOPTFLAT path we've seen was due to low bits of a bus
being generated from an always statement that consumed high bits of the
same bus processed by another series of always blocks. The fix is the
same; split it into two separate signals generated from each block.
The UNOPTFLAT warning may also be due to clock enables, identified from the
reported path going through a clock gating cell. To fix these, use the
clock_enable meta comment described above.
=item UNSIGNED
@@ -1406,8 +1539,8 @@ that is not yet supported in Verilator. See the Limitations chapter.
=item Verilated model didn't converge
Verilator sometimes has to evaluate combinatorial logic multiple times,
usually around code where a UNOPT warning was issued, but disabled. For
example:
usually around code where a UNOPTFLAT warning was issued, but disabled.
For example:
always @ (a) b=~a;
always @ (b) a=b
@@ -1453,18 +1586,32 @@ 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 How do I generate waveforms (traces)?
=item How do I generate waveforms (traces) in C++?
See the next question for SystemC mode.
Add the --trace switch to Verilator, and make sure the SystemPerl package
is installed (SystemC itself isn't required for C++ only tracing.) In your
top level C code, call Verilated::traceEverOn(true).
is installed. SystemC itself does not need to be installed for C++ only
tracing. You do not even need to compile SystemPerl; you may simply untar
the SystemPerl kit and point the SYSTEMPERL environment variable to the
untarred directory.
Then, in SystemC mode, create a SpTraceFile object. For an example, see
the call to SpTraceFile in the test_sp/sc_main.cpp file of the
distribution.
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.
Or, in C++ mode, create a SpTraceVcdCFile object, and see
test_c/sim_main.cpp.
You also need to compile SpTraceVcdC.cpp and add it to your link. This is
done for you if using the Verilator --exe flag.
=item How do I generate waveforms (traces) in SystemC?
Add the --trace switch to Verilator, and make sure the SystemPerl package
is installed.
In your top level C sc_main code, call Verilated::traceEverOn(true). Then
create a SpTraceFile object as you would create a normal SystemC trace
file. For an example, see the call to SpTraceFile in the
test_sp/sc_main.cpp file of the distribution.
=item Where is the translate_off command? (How do I ignore a construct?)
@@ -1483,6 +1630,16 @@ Call Verilated::assertOn(false) before you first call the model, then turn
it back on after reset. It defaults to true. When false, all assertions
controlled by --assert are disabled.
=item Why do I get "undefined reference to `sc_time_stamp()'"?
In C++ (non SystemC) code you need to define this function so that the
simulator knows the current time. See the "CONNECTING TO C++" examples.
=item Why do I get "undefined reference to `VL_RAND_RESET_I' or `Verilated::...'"?
You need to link your compiled Verilated code against the verilated.cpp
file found in the include directory of the Verilator kit.
=item Is the PLI supported?
No.
@@ -1493,6 +1650,12 @@ complex, since Verilator emits standard C++ code, you can simply write your
own C++ routines that can access and modify signal values without needing
any PLI interface code, and call it with $c("{any_c++_statement}").
=item How do I make a Verilog module that contain a C++ object?
You need to add the object to the structure that Verilator creates, then
use $c to call a method inside your object. The
test_regress/t/t_extend_class files show an example of how to do this.
=item How do I get faster build times?
Between GCC 3.0 to 3.3, each compiled progressively slower, thus if you can
@@ -1542,6 +1705,25 @@ In this example, clk is a bool you can read or set as any other variable.
The value of normal signals may be set, though clocks shouldn't be changed
by your code or you'll get strange results.
=item Should a module be in Verilog or SystemC?
Sometimes there is a block that just interconnects cells, and have a choice
as to if you write it in Verilog or SystemC. Everything else being equal,
best performance is when Verilator sees all of the design. So, look at the
hierarchy of your design, labeling cells as to if they are SystemC or
Verilog. Then:
A module with only SystemC cells below must be SystemC.
A module with a mix of Verilog and SystemC cells below must be SystemC. (As
Verilator cannot connect to lower-level SystemC cells.)
A module with only Verilog cells below can be either, but for best
performance should be Verilog. (The exception is if you have a design that
is instantiated many times; in this case Verilating one of the lower
modules and instantiating that Verilated cells multiple times into a
SystemC module *may* be faster.)
=back
=head1 BUGS
@@ -1566,7 +1748,7 @@ outputs. Now, the following should fail:
cd test_regress
t/t_BUG.pl
Finally, Mail the bug report to C<[email protected]>
Finally, Mail the bug report to C<[email protected]>.
=head1 HISTORY
@@ -1593,8 +1775,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
as fast as most popular commercial simulators.
as the need arises. Verilator is now about 2x faster then in 2002, and is
faster then many popular commercial simulators.
=head1 CONTRIBUTORS
+1 -1
View File
@@ -192,5 +192,5 @@ C<verilator>
######################################################################
### Local Variables:
### compile-command: "$V4/bin/verilator_difftree ~/SandBox/workwsnyder/verilator/test_c/obj_dir/V*_03_*.tree $V4/test_c/obj_dir/V*_03_*.tree"
### compile-command: "$V4/bin/verilator_difftree $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
### End:
+4 -2
View File
@@ -6,7 +6,7 @@ dnl General Public License or the Perl Artistic License.
AC_REVISION($Revision$)dnl
AC_INIT(src/Verilator.cpp)
AC_CONFIG_HEADER(src/config.h)
AC_CONFIG_HEADER(src/config_build.h)
dnl Special Substitutions
@@ -16,13 +16,15 @@ AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PATH_PROG(PERL,perl)
AC_PATH_PROG(YACC,bison)
AC_PATH_PROG(LEX,flex)
dnl Checks for libraries.
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(fcntl.h unistd.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
AC_CHECK_HEADERS(fcntl.h unistd.h inttypes.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
dnl Checks for typedefs, structures
AC_CHECK_TYPE(size_t,unsigned int)
+44 -5
View File
@@ -40,11 +40,11 @@ using namespace std;
//=========================================================================
// Basic types
typedef uint8_t CData; ///< Verilated data, 1-8 bits
typedef uint16_t SData; ///< Verilated data, 9-16 bits
typedef uint32_t IData; ///< Verilated data, 17-32 bits
typedef vluint64_t QData; ///< Verilated data, 33-64 bits
typedef uint32_t WData; ///< Verilated data, >64 bits, as an array
typedef vluint8_t CData; ///< Verilated data, 1-8 bits
typedef vluint16_t SData; ///< Verilated data, 9-16 bits
typedef vluint32_t IData; ///< Verilated data, 17-32 bits
typedef vluint64_t QData; ///< Verilated data, 33-64 bits
typedef vluint32_t WData; ///< Verilated data, >64 bits, as an array
typedef const WData* WDataInP; ///< Array input to a function
typedef WData* WDataOutP; ///< Array output from a function
@@ -115,6 +115,13 @@ public:
#endif
//=========================================================================
// Functions overridable by user defines
#ifndef VL_PRINTF
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired
#endif
//===========================================================================
/// Verilator global static information class
@@ -1321,6 +1328,38 @@ static inline WDataOutP VL_CONST_W_16X(int obits, WDataOutP o,
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,
+3
View File
@@ -48,6 +48,9 @@ VPATH += $(VERILATOR_ROOT)/include
#OPT = -ggdb -DPRINTINITSTR
CPPFLAGS += $(OPT)
CPPFLAGS += $(M32)
LDFLAGS += $(M32)
# See the benchmarking section of bin/verilator.
# Support class optimizations. This includes the tracing and symbol table.
# SystemC takes minutes to optimize, thus it is off by default.
+27 -15
View File
@@ -15,9 +15,11 @@
/// \file
/// \brief Verilator: Common include for OS portability (verilated & verilator)
///
/// This header is used by both verilated code, and the verilator
/// program itself Code needed by only one goes into verilated.h or
/// config.h.in respectively.
/// This header is used by both the Verilator source code (run on the
/// build and host system), and the Verilated output (run on the target
/// system). Code needed by only the host system goes into
/// config_build.h.in, code needed by Verilated code only goes into
/// verilated.h, and code needed by both goes here (verilatedos.h).
///
/// Code available from: http://www.veripool.com/verilator
///
@@ -68,24 +70,34 @@
#ifdef VL_UINTS_DEFINED
#elif defined(__CYGWIN__)
# include <stdint.h>
typedef unsigned char uint8_t; ///< 8-bit basic type
typedef unsigned short int uint16_t; ///< 16-bit basic type
typedef unsigned long uint32_t; ///< 32-bit basic type
typedef unsigned long long vluint64_t; ///< 64-bit basic type
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)
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
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)
typedef unsigned char uint8_t; ///< 8-bit basic type
typedef unsigned short int uint16_t; ///< 16-bit basic type
typedef unsigned int uint32_t; ///< 32-bit basic type
typedef unsigned __int64 vluint64_t; ///< 64-bit basic type
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)
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type
typedef unsigned int vluint32_t; ///< 32-bit unsigned type
typedef __int64 vlsint64_t; ///< 64-bit signed type
#else // Linux or compliant Unix flavors
# include <stdint.h>
typedef unsigned long long vluint64_t; ///< 64-bit basic type
typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
#else // Linux or compliant Unix flavors, -m64
# include <stdint.h> // Linux and most flavors
# include <inttypes.h> // Solaris
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
typedef int vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit signed type
typedef long long vlsint64_t; ///< 64-bit signed type
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#endif
//=========================================================================
+1 -1
View File
@@ -1,5 +1,5 @@
*.old
config.h
config_build.h
Makefile
Makefile_obj
.objcache*
+3
View File
@@ -85,3 +85,6 @@ clean mostlyclean distclean maintainer-clean::
-rm -f *__gen*
-rm -f *.yy.* y.output y.tab.[cho] *_test
-rm -f .objcache*
distclean maintainer-clean::
-rm -f Makefile Makefile_obj config_build.h
+6 -7
View File
@@ -28,6 +28,8 @@ CC = @CC@
CXX = @CXX@
LINK = @CXX@
LDFLAGS += @LDFLAGS@
#### End of system configuration section. ####
VPATH += . $(srcdir)
@@ -36,22 +38,20 @@ TGT = ../../verilator_bin
#################
ifeq ($(VL_DEBUG),)
# Optimize
LDFLAGS =
COPT = -O
else
# Debug
LDFLAGS =
COPT = -ggdb -DVL_DEBUG
# Debug & Profile:
#LDFLAGS = -pg -g
#LDFLAGS += -pg -g
#COPT = -ggdb -pg -g
endif
#################
LEX = flex
LEX = @LEX@
LFLAGS = -d
YACC = bison -y
YFLAGS = -d -v
YACC = @YACC@
YFLAGS = -y -d -v
#LIBS += -ldl
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
@@ -89,7 +89,6 @@ clean mostlyclean distclean maintainer-clean::
-rm -f obj_* .objcache*
distclean maintainer-clean:: clean
rm -f Makefile config.h
maintainer-clean::
+4 -1
View File
@@ -31,7 +31,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -298,8 +299,10 @@ private:
// OPTIMIZE: We could substitute a constant for things in the sense list, for example
// always (posedge RESET) { if (RESET).... } we know RESET is true.
// Summarize a long list of combo inputs as just "combo"
#ifndef __COVERITY__ // Else dead code on next line.
if (combo) nodep->sensesp()->addSensesp
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
#endif
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp());
}
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3ACTIVE_H_
#define _V3ACTIVE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -28,7 +28,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3ACTIVETOP_H_
#define _V3ACTIVETOP_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+3 -2
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -88,7 +89,7 @@ private:
bodysp = newFireAssert(nodep,message);
// We assert the property is always true... so report when it fails
// (Note this is opposite the behavior of coverage statements.)
//FIX 'never' operator: not hold in current or any future cycle
// Need: 'never' operator: not hold in current or any future cycle
propp = new AstLogNot (nodep->fileline(), propp);
} else {
nodep->v3fatalSrc("Unknown node type");
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3ASSERT_H_
#define _V3ASSERT_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -22,7 +22,8 @@
// Attach clocks to each assertion
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3ASSERTPRE_H_
#define _V3ASSERTPRE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+12 -4
View File
@@ -33,8 +33,8 @@
//======================================================================
// Statics
uint64_t AstNode::s_editCntGbl=0;
uint64_t AstNode::s_editCntLast=0;
vluint64_t AstNode::s_editCntGbl=0;
vluint64_t AstNode::s_editCntLast=0;
// To allow for fast clearing of all user pointers, we keep a "timestamp"
// along with each userp, and thus by bumping this count we can make it look
@@ -98,6 +98,12 @@ string AstNode::prettyName(const string& namein) {
while ((pos=pretty.find("__DOT__")) != string::npos) {
pretty.replace(pos, 7, ".");
}
while ((pos=pretty.find("__BRA__")) != string::npos) {
pretty.replace(pos, 7, "[");
}
while ((pos=pretty.find("__KET__")) != string::npos) {
pretty.replace(pos, 7, "]");
}
while ((pos=pretty.find("__PVT__")) != string::npos) {
pretty.replace(pos, 7, "");
}
@@ -784,14 +790,16 @@ void AstNode::dumpTreeFile(const string& filename, bool append) {
dumpTree(*logsp);
}
}
}
if (v3Global.opt.debugCheck() || v3Global.opt.dumpTree()) {
// Error check
checkTree();
// Broken isn't part of check tree because it can munge iterp's
// set by other steps if it is called in the middle of other operations
if (AstNetlist* netp=this->castNetlist()) V3Broken::brokenAll(netp);
// Next dump can indicate start from here
editCountSetLast();
}
// Next dump can indicate start from here
editCountSetLast();
}
void AstNode::v3errorEnd(ostringstream& str) {
+15 -11
View File
@@ -21,7 +21,8 @@
#ifndef _V3AST_H_
#define _V3AST_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Number.h"
#include <vector>
@@ -57,6 +58,7 @@ public:
COVERAGE_BLOCK_OFF,
INLINE_MODULE,
NO_INLINE_MODULE,
NO_INLINE_TASK,
PUBLIC_MODULE,
PUBLIC_TASK
};
@@ -391,9 +393,9 @@ private:
static int s_cloneCntGbl; // Count of which userp is set
FileLine* m_fileline; // Where it was declared
uint64_t m_editCount; // When it was last edited
static uint64_t s_editCntGbl;// Global edit counter
static uint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
vluint64_t m_editCount; // When it was last edited
static vluint64_t s_editCntGbl; // Global edit counter
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
// Attributes
bool m_signed; // Node is signed
@@ -539,10 +541,10 @@ public:
void user5(int val) { user5p(AstNUser::fromInt(val)); }
static void user5ClearTree() { s_user5CntGbl++; } // Clear userp()'s across the entire tree
uint64_t editCount() const { return m_editCount; }
vluint64_t editCount() const { return m_editCount; }
void editCountInc() { m_editCount = s_editCntGbl++; }
static uint64_t editCountLast() { return s_editCntLast; }
static uint64_t editCountGbl() { return s_editCntGbl; }
static vluint64_t editCountLast() { return s_editCntLast; }
static vluint64_t editCountGbl() { return s_editCntGbl; }
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
// ACCESSORS for specific types
@@ -585,6 +587,7 @@ public:
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
virtual bool same(AstNode* otherp) const { return true; }
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
virtual bool broken() const { return false; }
virtual bool emitWordForm() { return false; }
@@ -774,14 +777,14 @@ struct AstNodeAssign : public AstNodeStmt {
struct AstNodeFor : public AstNodeStmt {
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* assignsp, AstNode* bodysp)
AstNode* incsp, AstNode* bodysp)
: AstNodeStmt(fileline) {
addNOp1p(initsp); setOp2p(condp); addNOp3p(assignsp); addNOp4p(bodysp);
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
}
virtual ~AstNodeFor() {}
AstNode* initsp() const { return op1p()->castNode(); } // op1= initial statement
AstNode* initsp() const { return op1p()->castNode(); } // op1= initial statements
AstNode* condp() const { return op2p()->castNode(); } // op2= condition to continue
AstNode* assignsp() const { return op3p()->castNode(); } // op3= final statements
AstNode* incsp() const { return op3p()->castNode(); } // op3= increment statements
AstNode* bodysp() const { return op4p()->castNode(); } // op4= body of loop
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
@@ -922,6 +925,7 @@ public:
virtual ~AstNodeFTask() {}
virtual void dump(ostream& str=cout);
virtual string name() const { return m_name; } // * = Var name
virtual bool maybePointedTo() const { return true; }
// {AstFunc only} op1 = Range output variable
// op3 = Statements/Ports/Vars
void name(const string& name) { m_name = name; }
+27 -6
View File
@@ -19,6 +19,8 @@
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <fstream>
@@ -85,7 +87,7 @@ int AstVar::widthTotalBytes() const {
}
string AstVar::verilogKwd() const {
if (isTristate()) {
if (isInout()) {
return "inout";
} else if (isInput()) {
return "input";
@@ -93,6 +95,8 @@ string AstVar::verilogKwd() const {
return "output";
} else if (isInteger()) {
return "integer";
} else if (isTristate()) {
return "tri";
} else if (varType()==AstVarType::WIRE) {
return "wire";
} else {
@@ -101,6 +105,18 @@ string AstVar::verilogKwd() const {
}
string AstVar::cType() const {
if (widthMin() == 1) {
return "bool";
} else if (widthMin() <= VL_WORDSIZE) {
return "uint32_t";
} else if (isScWide()) {
return "uint32_t"; // []'s added later
} else {
return "uint64_t";
}
}
string AstVar::scType() const {
if (widthMin() == 1) {
return "bool";
} else if (widthMin() <= VL_WORDSIZE) {
@@ -130,7 +146,7 @@ uint32_t AstVar::arrayElements() const {
bool AstScope::broken() const {
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|| !m_modp || !((AstNode*)m_modp)->brokeExists());
|| !m_modp || !m_modp->brokeExists());
}
void AstScope::cloneRelink() {
@@ -325,14 +341,18 @@ void AstVarRef::dump(ostream& str) {
void AstVar::dump(ostream& str) {
this->AstNode::dump(str);
if (isSc()) str<<" [SC]";
if (isInput()) str<<" [I]";
if (isPrimaryIO()) str<<(isInput()?" [PI]":" [PO]");
if (isOutput()) str<<" [O]";
if (isPrimaryIO()) str<<(isInout()?" [PIO]":(isInput()?" [PI]":" [PO]"));
else {
if (isInout()) str<<" [IO]";
else if (isInput()) str<<" [I]";
else if (isOutput()) str<<" [O]";
}
if (isUsedClock()) str<<" [C]";
if (isSigPublic()) str<<" [P]";
if (attrClockEn()) str<<" [aCLKEN]";
if (attrFileDescr()) str<<" [aFD]";
if (isFuncLocal() || isFuncReturn()) str<<" [FUNC]";
if (isFuncReturn()) str<<" [FUNCRTN]";
else if (isFuncLocal()) str<<" [FUNC]";
str<<" "<<varType();
}
void AstSenTree::dump(ostream& str) {
@@ -358,6 +378,7 @@ void AstNodeFTaskRef::dump(ostream& str) {
}
void AstNodeFTask::dump(ostream& str) {
this->AstNode::dump(str);
if (taskPublic()) str<<" [PUBLIC]";
}
void AstCoverDecl::dump(ostream& str) {
this->AstNode::dump(str);
+36 -15
View File
@@ -286,8 +286,10 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void dump(ostream& str);
virtual string name() const { return m_name; } // * = Var name
virtual bool maybePointedTo() const { return true; }
AstVarType varType() const { return m_varType; } // * = Type of variable
string cType() const; // Return C type: bool, uint32_t, uint64_t, etc.
string cType() const; // Return C type for declaration: bool, uint32_t, uint64_t, etc.
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
void combineType(AstVarType type);
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
AstRange* arraysp() const { return op2p()->castRange(); } // op2 = Array(s) of variable
@@ -314,10 +316,13 @@ public:
void name(const string& name) { m_name = name; }
bool isInput() const { return m_input; }
bool isOutput() const { return m_output; }
bool isTristate() const { return (m_tristate); }
bool isInOnly() const { return m_input && !m_output; }
bool isOutOnly() const { return m_output && !m_input; }
bool isInout() const { return m_input && m_output; }
bool isTristate() const { return m_tristate; }
bool isPrimaryIO() const { return m_primaryIO; }
bool isPrimaryIn() const { return isPrimaryIO() && isInput(); }
bool isIO() const { return (m_input||m_output||m_tristate); }
bool isIO() const { return (m_input||m_output); }
bool isSignal() const { return (varType()==AstVarType::WIRE || varType()==AstVarType::IMPLICIT
|| varType()==AstVarType::REG || varType()==AstVarType::INTEGER); }
bool isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
@@ -419,6 +424,7 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void cloneRelink();
virtual bool broken() const;
virtual bool maybePointedTo() const { return true; }
virtual string name() const { return m_name; } // * = Scope name
void name(const string& name) { m_name = name; }
string nameDotless() const;
@@ -480,6 +486,7 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual bool broken() const { return ( (m_varp && !m_varp->brokeExists())
|| (m_scopep && !m_scopep->brokeExists())); }
virtual bool maybePointedTo() const { return true; }
virtual string name() const {return scopep()->name()+"->"+varp()->name();} // * = Var name
virtual void dump(ostream& str);
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
@@ -604,6 +611,7 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void dump(ostream& str);
virtual bool broken() const { return (m_clkReqVarp && !m_clkReqVarp->brokeExists()); }
virtual bool maybePointedTo() const { return true; }
virtual string name() const { return m_name; }
AstNode* stmtsp() const { return op2p()->castNode(); } // op2 = List of statements
AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks
@@ -648,19 +656,21 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void dump(ostream& str);
virtual bool broken() const { return (m_modp && !m_modp->brokeExists()); }
virtual bool maybePointedTo() const { return true; }
// ACCESSORS
virtual string name() const { return m_name; } // * = Cell name
void name(const string& name) { m_name = name; }
string origName() const { return m_origName; } // * = Original name
void origName(const string& name) { m_origName = name; }
string modName() const { return m_modName; } // * = Instance name
void modName(const string& name) { m_modName = name; }
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)
AstModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated
void addPinsp(AstPin* pinp) { addOp1p(pinp); }
void addParamsp(AstPin* pinp) { addOp2p(pinp); }
void modp(AstModule* modp) { m_modp = modp; }
void modName(const string& name) { m_modName = name; }
void name(const string& name) { m_name = name; }
void addPinsp(AstPin* nodep) { addOp1p(nodep); }
void addParamsp(AstPin* nodep) { addOp2p(nodep); }
void modp(AstModule* nodep) { m_modp = nodep; }
};
struct AstCellInline : public AstNode {
@@ -805,7 +815,7 @@ public:
class Initial {}; // for creator type-overload selection
class Settle {}; // for creator type-overload selection
class Never {}; // for creator type-overload selection
AstSenItem(FileLine* fl, AstEdgeType edgeType, AstVarRef* varrefp)
AstSenItem(FileLine* fl, AstEdgeType edgeType, AstNodeVarRef* varrefp)
: AstNode(fl) {
m_edgeType = edgeType;
setOp1p(varrefp);
@@ -838,7 +848,7 @@ public:
AstEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge
void edgeType(AstEdgeType type) { m_edgeType=type; editCountInc(); }// * = Posedge/negedge
AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized
AstVarRef* varrefp() const { return op1p()->castVarRef(); } // op1 = Signal sensitized
AstNodeVarRef* varrefp() const { return op1p()->castNodeVarRef(); } // op1 = Signal sensitized
//
bool isClocked() const { return edgeType().clockedStmt(); }
bool isCombo() const { return edgeType()==AstEdgeType::COMBO; }
@@ -864,6 +874,7 @@ public:
virtual AstNode* clone() { return new AstSenTree(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void dump(ostream& str);
virtual bool maybePointedTo() const { return true; }
bool isMulti() const { return m_multi; }
AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list
void addSensesp(AstSenItem* nodep) { addOp1p(nodep); }
@@ -1049,6 +1060,7 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void dump(ostream& str);
virtual int instrCount() const { return 1+2*instrCountLd(); }
virtual bool maybePointedTo() const { return true; }
int column() const { return m_column; }
const string& comment() const { return m_text; } // text to insert in code
const string& typeText() const { return m_typeText; }
@@ -1241,8 +1253,8 @@ struct AstFOpen : public AstNodeStmt {
struct AstGenFor : public AstNodeFor {
AstGenFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* assignsp, AstNode* bodysp)
: AstNodeFor(fileline, initsp, condp, assignsp, bodysp) {
AstNode* incsp, AstNode* bodysp)
: AstNodeFor(fileline, initsp, condp, incsp, bodysp) {
}
virtual ~AstGenFor() {}
virtual AstType type() const { return AstType::GENFOR;}
@@ -1252,8 +1264,8 @@ struct AstGenFor : public AstNodeFor {
struct AstFor : public AstNodeFor {
AstFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNode* assignsp, AstNode* bodysp)
: AstNodeFor(fileline, initsp, condp, assignsp, bodysp) {
AstNode* incsp, AstNode* bodysp)
: AstNodeFor(fileline, initsp, condp, incsp, bodysp) {
}
virtual ~AstFor() {}
virtual AstType type() const { return AstType::FOR;}
@@ -1502,6 +1514,7 @@ public:
virtual AstNode* clone() { return new AstTraceDecl(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string name() const { return m_showname; }
virtual bool maybePointedTo() const { return true; }
string showname() const { return m_showname; } // * = Var name
virtual bool same(AstNode* samep) const { return false; }
// Details on what we're tracing
@@ -1593,7 +1606,8 @@ public:
bool hasClocked() const { return m_sensesp->hasClocked(); }
};
class AstAttrOf : public AstNode {
struct AstAttrOf : public AstNode {
private:
// Return a value of a attribute, for example a LSB or array LSB of a signal
AstAttrType m_attrType; // What sort of extraction
int m_dimension; // Dimension number (0 is leftmost), for ARRAY_LSB extractions
@@ -1735,6 +1749,7 @@ struct AstRedXor : public AstNodeUniop {
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
};
struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); }
virtual ~AstRedXnor() {}
@@ -2772,6 +2787,7 @@ private:
bool m_funcPublic:1; // From user public task/function
bool m_isStatic:1; // Function is declared static (no this)
bool m_symProlog:1; // Setup symbol table for later instructions
bool m_entryPoint:1; // User may call into this top level function
public:
AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType="")
: AstNode(fl) {
@@ -2787,12 +2803,15 @@ public:
m_funcPublic = false;
m_isStatic = true; // Note defaults to static, later we see where thisp is needed
m_symProlog = false;
m_entryPoint = false;
}
virtual ~AstCFunc() {}
virtual AstType type() const { return AstType::CFUNC;}
virtual AstNode* clone() { return new AstCFunc(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string name() const { return m_name; }
virtual bool broken() const { return ( (m_scopep && !m_scopep->brokeExists())); }
virtual bool maybePointedTo() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return ((funcType()==samep->castCFunc()->funcType())
&& (rtnTypeVoid()==samep->castCFunc()->rtnTypeVoid())
@@ -2822,6 +2841,8 @@ public:
void isStatic(bool flag) { m_isStatic = flag; }
bool symProlog() const { return m_symProlog; }
void symProlog(bool flag) { m_symProlog = flag; }
bool entryPoint() const { return m_entryPoint; }
void entryPoint(bool flag) { m_entryPoint = flag; }
//
// If adding node accessors, see below
AstNode* argsp() const { return op1p()->castNode(); }
+20 -30
View File
@@ -23,10 +23,12 @@
// Each module:
// Look for BEGINs
// BEGIN(VAR...) -> VAR ... {renamed}
// FOR -> WHILEs
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -48,25 +50,6 @@ private:
string m_beginScope; // Name of begin blocks above us
//int debug() { return 9; }
bool nameMatchesGen(const char* namep, string& numr) {
numr = "";
bool needbar = false;
for (const char* cp=namep; *cp; ) {
if (0==strncmp(cp,"genblk",6) || 0==strncmp(cp,"genfor",6)) {
cp += 6;
} else if (isdigit(*cp)) {
if (needbar) { numr += '_'; needbar = false; }
numr += *cp++;
} else if (*cp=='_') {
cp++;
needbar = true;
} else {
return false; // Not exact match
}
}
return true;
}
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
m_modp = nodep;
@@ -83,15 +66,6 @@ private:
UINFO(8," "<<nodep<<endl);
string oldScope = m_beginScope;
{
//string nameNum;
//string oldNum;
//if (nameMatchesGen(oldScope.c_str(), oldNum/*ref*/)
// && nameMatchesGen(nodep->name().c_str(), nameNum/*ref*/)
// && 0) { // Messes up V3Link
// // Need to leave the dot or we mess up later V3LinkDot
// // gen[blk|for]##_gen[blk|for]## -> gen[blk|for]##__DOT__##...
// m_beginScope = oldScope + "__DOT__"+nameNum;
//UINFO(8,"nname "<<m_beginScope<<endl);
// Create data for dotted variable resolution
string dottedname = nodep->name() + "__DOT__"; // So always found
@@ -99,7 +73,7 @@ private:
while ((pos=dottedname.find("__DOT__")) != string::npos) {
string ident = dottedname.substr(0,pos);
dottedname = dottedname.substr(pos+strlen("__DOT__"));
if (m_beginScope=="") m_beginScope = nodep->name();
if (m_beginScope=="") m_beginScope = ident;
else m_beginScope = m_beginScope + "__DOT__"+ident;
// Create CellInline for dotted resolution
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
@@ -141,6 +115,22 @@ private:
m_modp->addStmtp(nodep);
}
}
virtual void visit(AstFor* nodep, AstNUser*) {
// So later optimizations don't need to deal with them,
// FOR(init,cond,assign,body) -> init,WHILE(cond) { body, assign }
AstNode* initsp = nodep->initsp(); if (initsp) initsp->unlinkFrBackWithNext();
AstNode* condp = nodep->condp(); if (condp) condp->unlinkFrBackWithNext();
AstNode* incsp = nodep->incsp(); if (incsp) incsp->unlinkFrBackWithNext();
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
bodysp = bodysp->addNext(incsp);
AstNode* newp = new AstWhile(nodep->fileline(),
condp,
bodysp);
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3BEGIN_H_
#define _V3BEGIN_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -25,7 +25,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3BRANCH_H_
#define _V3BRANCH_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+8 -5
View File
@@ -26,7 +26,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -81,13 +82,15 @@ private:
// // so userp and friends may not be used
// VISITORS
virtual void visit(AstNode* nodep, AstNUser*) {
BrokenTable::add(nodep);
if (nodep->maybePointedTo()) {
BrokenTable::add(nodep);
}
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
BrokenMarkVisitor(AstNode* nodep) {
nodep->iterateAndNext(*this, NULL);
BrokenMarkVisitor(AstNetlist* nodep) {
nodep->accept(*this);
}
virtual ~BrokenMarkVisitor() {}
};
@@ -99,7 +102,7 @@ class BrokenCheckVisitor : public AstNVisitor {
private:
virtual void visit(AstNode* nodep, AstNUser*) {
if (nodep->broken()) {
nodep->v3fatalSrc("Broken link in node\n");
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)\n");
}
if (v3Global.assertWidthsSame()) {
if (nodep->width() != nodep->widthMin()) {
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3BROKEN_H_
#define _V3BROKEN_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+18 -16
View File
@@ -29,16 +29,17 @@
// (other items))
// body
// Or, converts to a if/else tree.
// Constants:
// RHS, Replace 5'bx_1_x with a module global we init to a random value
// CONST(5'bx_1_x) -> VARREF(_{numberedtemp})
// -> VAR(_{numberedtemp})
// -> INITIAL(VARREF(_{numberedtemp}), OR(5'bx_1_x,AND(random,5'b0_1_x))
// OPTIMIZE: Must not collapse this initial back into the equation.
// FUTURES:
// Large 16+ bit tables with constants and no masking (address muxes)
// Enter all into multimap, sort by value and use a tree of < and == compares.
// "Diagonal" find of {rightmost,leftmost} bit {set,clear}
// Ignoring mask, check each value is unique (using multimap as above?)
// Each branch is then mask-and-compare operation (IE <000000001_000000000 at midpoint.)
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -49,7 +50,8 @@
#include "V3Ast.h"
#include "V3Stats.h"
#define CASE_OVERLAP_WIDTH 12 // Maximum width we can check for overlaps in
#define CASE_OVERLAP_WIDTH 12 // Maximum width we can check for overlaps in
#define CASE_BARF 999999 // Magic width when non-constant
//######################################################################
@@ -126,22 +128,22 @@ private:
//int debug() { return 9; }
// METHODS
bool checkCaseTree(AstCase* nodep) {
bool isCaseTreeFast(AstCase* nodep) {
int width = 0;
m_caseItems = 0;
m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width();
if (!icondp->castConst()) width = 999; // Can't parse; not a constant
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++;
}
}
m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH) {
m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis
}
m_caseWidth = width;
UINFO(8,"Simple case statement: "<<nodep<<endl);
// Zero list of items for each value
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
@@ -172,7 +174,7 @@ private:
}
}
// Defaults were moved to last in the caseitem list by V3Link
if (!itemp->condsp()) { // Case statement's default... Fill the table
if (itemp->isDefault()) { // Case statement's default... Fill the table
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if (!m_valueItem[i]) m_valueItem[i] = itemp;
}
@@ -207,7 +209,7 @@ private:
AstNode* tree1p = replaceCaseFastRecurse(cexprp, msb-1, upperValue | (1UL<<msb));
if (tree0p == tree1p) {
// Same logic on both sides, so we can just return one of em
// Same logic on both sides, so we can just return one of 'em
return tree0p;
}
// We could have a "checkerboard" with A B A B, we can use the same IF on both edges
@@ -357,7 +359,7 @@ private:
V3Case::caseLint(nodep);
nodep->iterateChildren(*this);
if (debug()>=9) nodep->dumpTree(cout," case_old: ");
if (checkCaseTree(nodep) && v3Global.opt.oCase()) {
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
// It's a simple priority encoder or complete statement
// we can make a tree of statements to avoid extra comparisons
m_statCaseFast++;
@@ -375,13 +377,13 @@ private:
public:
// CONSTUCTORS
CaseVisitor(AstNode* nodep) {
CaseVisitor(AstNetlist* nodep) {
m_caseNoOverlapsAllCovered = false;
nodep->accept(*this);
}
virtual ~CaseVisitor() {
V3Stats::addStat("Optimizations, Cases parallelized", m_statCaseFast);
V3Stats::addStat("Optimizations, Cases priority-encoded", m_statCaseSlow);
V3Stats::addStat("Optimizations, Cases complex", m_statCaseSlow);
}
};
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3CASE_H_
#define _V3CASE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -42,7 +42,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3CAST_H_
#define _V3CAST_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -31,7 +31,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3CHANGED_H_
#define _V3CHANGED_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+6 -1
View File
@@ -28,7 +28,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -239,6 +240,10 @@ private:
nodep->iterateChildren(*this);
insureCleanAndNext (nodep->bodysp());
}
virtual void visit(AstCCall* nodep, AstNUser*) {
nodep->iterateChildren(*this);
insureCleanAndNext (nodep->argsp());
}
//--------------------
// Default: Just iterate
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3CLEAN_H_
#define _V3CLEAN_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+7 -3
View File
@@ -32,7 +32,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -192,6 +193,7 @@ private:
funcp->dontCombine(true);
funcp->symProlog(true);
funcp->isStatic(true);
funcp->entryPoint(true);
m_scopep->addActivep(funcp);
m_evalFuncp = funcp;
}
@@ -202,6 +204,7 @@ private:
funcp->slow(true);
funcp->symProlog(true);
funcp->isStatic(true);
funcp->entryPoint(true);
m_scopep->addActivep(funcp);
m_initFuncp = funcp;
}
@@ -211,6 +214,7 @@ private:
funcp->dontCombine(true);
funcp->slow(true);
funcp->isStatic(false);
funcp->entryPoint(true);
funcp->addInitsp(
new AstCStmt(nodep->fileline(),
" "+EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
@@ -225,6 +229,7 @@ private:
funcp->slow(true);
funcp->isStatic(true);
funcp->symProlog(true);
funcp->entryPoint(true);
m_scopep->addActivep(funcp);
m_settleFuncp = funcp;
}
@@ -360,8 +365,7 @@ private:
// Move statements to if
m_lastIfp->addIfsp(stmtsp);
} else if (nodep->hasSettle()) {
// Settlement
clearLastSen();
// Don't need to: clearLastSen();, as we're adding it to different cfunc
// Move statements to function
addToSettleLoop(stmtsp);
} else {
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3CLOCK_H_
#define _V3CLOCK_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -35,7 +35,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3COMBINE_H_
#define _V3COMBINE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+92 -19
View File
@@ -25,7 +25,8 @@
// If operands are constant, replace this node with constant.
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -70,6 +71,16 @@ private:
if (!rnodep->lhsp()->castConst()) return false;
return true;
}
bool operandAsvSame (AstNode* nodep) {
// BIASV(SAMEa, BIASV(SAMEb,...)) -> BIASV( BIASV(SAMEa,SAMEb), ...)
AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv();
if (!bnodep) return false;
AstNodeBiComAsv* rnodep = bnodep->rhsp()->castNodeBiComAsv();
if (!rnodep) return false;
if (rnodep->type() != bnodep->type()) return false;
if (rnodep->width() != bnodep->width()) return false;
return operandsSame(bnodep->lhsp(), rnodep->lhsp());
}
bool operandHugeShiftL(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst()
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->width()));
@@ -87,6 +98,10 @@ private:
return (nodep->castConst()
&& !nodep->castConst()->num().isFourState());
}
bool operandIsPowTwo(AstNode* nodep) {
if (!operandIsTwostate(nodep)) return false;
return (1==nodep->castConst()->num().countOnes());
}
bool operandShiftOp(AstNodeBiop* nodep) {
if (!nodep->rhsp()->castConst()) return false;
AstNodeBiop* lhsp = nodep->lhsp()->castNodeBiop();
@@ -166,15 +181,10 @@ private:
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
// For now we just detect constants & simple vars, though it could be more generic
if (node1p->castConst() && node2p->castConst()) {
// Match ignoring any X values
V3Number num (node1p->fileline(), 1);
num.opCaseEq(node1p->castConst()->num(), node2p->castConst()->num());
return num.isNeqZero();
return node1p->sameTree(node2p);
}
else if (node1p->castVarRef() && node2p->castVarRef()
&& node1p->sameTree(node2p)) {
// Same variable
return true;
else if (node1p->castVarRef() && node2p->castVarRef()) {
return node1p->sameTree(node2p);
} else {
return false;
}
@@ -235,6 +245,12 @@ private:
void replaceZero(AstNode* nodep) {
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);
replaceNum(nodep, ones); nodep=NULL;
}
void replaceConst(AstNodeUniop* nodep) {
V3Number num (nodep->fileline(), nodep->width());
nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
@@ -279,8 +295,9 @@ private:
// Keep RHS, remove LHS
replaceWChild(nodep, nodep->rhsp());
}
void replaceAsvConst (AstNodeBiop* nodep) {
void replaceAsv (AstNodeBiop* nodep) {
// BIASV(CONSTa, BIASV(CONSTb, c)) -> BIASV( BIASV_CONSTED(a,b), c)
// BIASV(SAMEa, BIASV(SAMEb, c)) -> BIASV( BIASV(SAMEa,SAMEb), c)
//nodep->dumpTree(cout, " repAsvConst_old: ");
AstNode* ap = nodep->lhsp();
AstNodeBiop* rp = nodep->rhsp()->castNodeBiop();
@@ -294,7 +311,7 @@ private:
nodep->rhsp(cp);
rp->lhsp(ap);
rp->rhsp(bp);
replaceConst(rp);
if (rp->lhsp()->castConst() && rp->rhsp()->castConst()) replaceConst(rp);
//nodep->dumpTree(cout, " repAsvConst_new: ");
}
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
@@ -317,6 +334,24 @@ private:
newp->lhsp()->widthSignedFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift
UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<<nodep<<endl);
int amount = nodep->lhsp()->castConst()->num().mostSetBitP1()-1; // 2^n->n+1
AstNode* opp = nodep->rhsp()->unlinkFrBack();
AstShiftL* newp = new AstShiftL(nodep->fileline(),
opp, new AstConst(nodep->fileline(), amount));
newp->widthSignedFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift
UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<<nodep<<endl);
int amount = nodep->rhsp()->castConst()->num().mostSetBitP1()-1; // 2^n->n+1
AstNode* opp = nodep->lhsp()->unlinkFrBack();
AstShiftR* newp = new AstShiftR(nodep->fileline(),
opp, new AstConst(nodep->fileline(), amount));
newp->widthSignedFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
}
void replaceShiftOp (AstNodeBiop* nodep) {
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
AstNRelinker handle;
@@ -781,7 +816,7 @@ private:
}
UINFO(8,"senItem(NOT...) "<<nodep<<" "<<invert<<endl);
if (invert) nodep->edgeType( nodep->edgeType().invert() );
AstVarRef* senvarp = lastSensp->unlinkFrBack()->castVarRef();
AstNodeVarRef* senvarp = lastSensp->unlinkFrBack()->castNodeVarRef();
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
sensp->replaceWith(senvarp);
sensp->deleteTree(); sensp=NULL;
@@ -923,6 +958,7 @@ private:
// }" # bracket not paren
// ,"function to call"
// or ,"AstREPLACEMENT_TYPE{ $accessor }"
// or ,"! # Print line number when matches, so can see operations
// Lint Checks
// v--- *1* These ops are always first, as we warn before replacing
@@ -947,6 +983,7 @@ private:
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
@@ -960,6 +997,7 @@ private:
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
// Non-zero on one side or the other
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
@@ -970,8 +1008,15 @@ private:
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}","replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}","replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
TREEOP("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
TREEOP("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
// Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
@@ -984,8 +1029,9 @@ private:
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
TREEOP("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
TREEOP("AstNodeBiCom{$lhsp, $rhsp.castConst}", "swapSides(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsvConst(nodep)");
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
// v--- *1* as These ops are always first, as we warn before replacing
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
@@ -1030,6 +1076,31 @@ private:
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
// Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon
TREEOP("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
TREEOP("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP("AstEqCase {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)");
TREEOP("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{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
// Comparison against 1'b0/1'b1; must be careful about widths.
// These use Not, so must be Verilog only
@@ -1047,7 +1118,6 @@ private:
TREEOPV("AstLte {$lhsp->width()==$rhsp->width(), $rhsp.isAllOnes}", "replaceNum(nodep,1)");
// Simplify reduction operators
// This also gets &{...,0,....} => const 0 (Common for unused_ok signals)
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstRedAnd{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
TREEOPV("AstRedOr {$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
TREEOPV("AstRedXor{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
@@ -1080,6 +1150,7 @@ private:
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
// Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
@@ -1143,12 +1214,14 @@ void V3Const::constifyAll(AstNetlist* nodep) {
visitor.main(nodep);
}
void V3Const::constifyAllLint(AstNode* nodep) {
void V3Const::constifyAllLint(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,false,true,false);
visitor.main(nodep);
}
void V3Const::constifyCpp(AstNode* nodep) {
void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (false,false,false,true);
visitor.main(nodep);
}
+4 -3
View File
@@ -21,7 +21,8 @@
#ifndef _V3CONST_H_
#define _V3CONST_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
@@ -34,9 +35,9 @@ public:
// Everything that's possible
static void constifyAll(AstNetlist* nodep);
// Also, warn
static void constifyAllLint(AstNode* nodep);
static void constifyAllLint(AstNetlist* nodep);
// C++ datatypes
static void constifyCpp(AstNode* nodep);
static void constifyCpp(AstNetlist* nodep);
// Only the current node and lower
static void constifyTree(AstNode* nodep);
};
+2 -1
View File
@@ -29,7 +29,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3COVERAGE_H_
#define _V3COVERAGE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+72 -13
View File
@@ -24,16 +24,43 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <vector>
#include <map>
#include "V3Global.h"
#include "V3Dead.h"
#include "V3Ast.h"
//######################################################################
class DeadModVisitor : public AstNVisitor {
// In a module that is dead, cleanup the in-use counts of the modules
private:
// NODE STATE
// ** Shared with DeadVisitor **
// VISITORS
virtual void visit(AstCell* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->modp()->user(nodep->modp()->user() - 1);
}
//-----
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTRUCTORS
DeadModVisitor(AstModule* nodep) {
nodep->accept(*this);
}
virtual ~DeadModVisitor() {}
};
//######################################################################
// Dead state, as a visitor of each AstNode
@@ -45,10 +72,15 @@ private:
// AstVar::user() -> int. Count of number of references
// AstVarScope::user() -> int. Count of number of references
// TYPES
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
// STATE
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through three
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through three
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
AssignMap m_assignMap; // List of all simple assignments for each variable
bool m_elimUserVars; // Allow removal of user's vars
bool m_sideEffect; // Side effects discovered in assign RHS
//int debug() { return 9; }
// METHODS
@@ -77,6 +109,25 @@ private:
m_varsp.push_back(nodep);
}
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
// See if simple assignments to variables may be eliminated because that variable is never used.
// Similar code in V3Life
m_sideEffect = false;
nodep->rhsp()->iterateAndNext(*this);
// Has to be direct assignment without any EXTRACTing.
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
if (varrefp && !m_sideEffect
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
} else { // Track like any other statement
nodep->lhsp()->iterateAndNext(*this);
}
}
virtual void visit(AstUCFunc* nodep, AstNUser*) {
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
nodep->iterateChildren(*this);
}
//-----
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
@@ -85,6 +136,8 @@ private:
// METHODS
void deadCheckMod() {
// Kill any unused modules
// V3LinkCells has a graph that is capable of this too, but we need to do it
// after we've done all the generate blocks
for (bool retry=true; retry; ) {
retry=false;
AstModule* nextmodp;
@@ -93,28 +146,33 @@ private:
if (modp->level()>2 && modp->user()==0) {
// > 2 because L1 is the wrapper, L2 is the top user module
UINFO(4," Dead module "<<modp<<endl);
// And its children may now be killable too....
for (AstNode* nodep = modp->stmtsp(); nodep; nodep=nodep->nextp()) {
if (AstCell* cellp=nodep->castCell()) {
cellp->modp()->user( cellp->modp()->user() - 1);
retry = true;
}
}
// And its children may now be killable too; correct counts
// Recurse, as cells may not be directly under the module but in a generate
DeadModVisitor visitor(modp);
modp->unlinkFrBack()->deleteTree(); modp=NULL;
retry = true;
}
}
}
}
bool canElim(AstVar* nodep) {
return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO()
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
}
void deadCheckVar() {
// Delete any unused varscopes
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
if ((*it)->user() == 0 && canElim((*it)->varp())) {
UINFO(4," Dead "<<(*it)<<endl);
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
AstVarScope* vscp = *it;
if (vscp->user() == 0 && canElim(vscp->varp())) {
UINFO(4," Dead "<<vscp<<endl);
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
AstNodeAssign* assp = it->second;
UINFO(4," Dead assign "<<assp<<endl);
assp->unlinkFrBack()->deleteTree(); assp=NULL;
}
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
}
}
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
@@ -129,6 +187,7 @@ public:
// CONSTRUCTORS
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
m_elimUserVars = elimUserVars;
m_sideEffect = false;
// Operate on whole netlist
AstNode::userClearTree(); // userp() used on entire tree
nodep->accept(*this);
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3DEAD_H_
#define _V3DEAD_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -52,7 +52,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3DELAYED_H_
#define _V3DELAYED_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -28,7 +28,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3DEPTH_H_
#define _V3DEPTH_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+9 -7
View File
@@ -27,7 +27,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -224,12 +225,13 @@ private:
if (m_scopep) {
nodep->unlinkFrBack();
m_modp->addStmtp(nodep);
}
if (nodep->funcPublic()) {
// There may be multiple public functions by the same name;
// record for later correction or making of shells
m_modFuncs.insert(make_pair(nodep->name(), nodep));
nodep->name(m_scopep->nameDotless() +"__" + nodep->name());
if (nodep->funcPublic()) {
// There may be multiple public functions by the same name;
// record for later correction or making of shells
m_modFuncs.insert(make_pair(nodep->name(), nodep));
nodep->name(m_scopep->nameDotless() +"__" + nodep->name());
}
}
}
}
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3DESCOPE_H_
#define _V3DESCOPE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+26 -19
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -96,12 +97,17 @@ public:
string cFuncArgs(AstCFunc* nodep) {
// Return argument list for given C function
string args = nodep->argTypes();
if (args=="") {
// Might be a user function with argument list.
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = stmtp->castVar()) {
if (portp->isIO() && !portp->isFuncReturn()) {
if (args != "") args+= ", ";
// Might be a user function with argument list.
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = stmtp->castVar()) {
if (portp->isIO() && !portp->isFuncReturn()) {
if (args != "") args+= ", ";
if (portp->isWide()) {
if (portp->isInOnly()) args += "const ";
args += portp->cType();
args += " (& "+portp->name();
args += ")["+cvtToStr(portp->widthWords())+"]";
} else {
args += portp->cType();
if (portp->isOutput()) args += "&";
args += " "+portp->name();
@@ -217,8 +223,7 @@ public:
puts(");\n");
}
virtual void visit(AstCoverInc* nodep, AstNUser*) {
puts("if (VL_LIKELY(vlSymsp->__Vm_coverageRequest))");
puts(" ++this->__Vcoverage[");
puts("++this->__Vcoverage[");
puts(cvtToStr(m_coverIds.remap(nodep->declp()))); puts("];\n");
}
virtual void visit(AstCReturn* nodep, AstNUser*) {
@@ -703,19 +708,19 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->attrScClocked() && nodep->isInput()) {
puts("sc_in_clk\t");
} else {
if (nodep->isTristate()) puts("sc_inout<");
if (nodep->isInout()) puts("sc_inout<");
else if (nodep->isInput()) puts("sc_in<");
else if (nodep->isOutput()) puts("sc_out<");
else nodep->v3fatalSrc("Unknown type");
puts(nodep->cType());
puts(nodep->scType());
puts(">\t");
}
puts(nodep->name());
puts(";\n");
} else { // C++ signals
ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes());
if (nodep->isTristate()) puts("VL_INOUT");
if (nodep->isInout()) puts("VL_INOUT");
else if (nodep->isInput()) puts("VL_IN");
else if (nodep->isOutput()) puts("VL_OUT");
else nodep->v3fatalSrc("Unknown type");
@@ -910,7 +915,6 @@ string EmitCStmts::displayFormat(AstNode* widthNodep, string in,
} else {
fmt=in;
}
if (widthNodep->isQuad() && fmtLetter!='c' && fmtLetter!='s' && !reallyString) fmt+="ll";
return fmt;
}
@@ -941,10 +945,17 @@ void EmitCStmts::displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, cha
emitDispState.pushFormat(pfmt);
emitDispState.pushArg(*elistp,func);
} else {
string func;
string nfmt = displayFormat(*elistp, fmt, fmtLetter, true, false);
// We don't need to check for fmtLetter=='d', as it is above.
if ((*elistp)->isQuad() && (fmtLetter=='u'||fmtLetter=='o'||fmtLetter=='x')) {
nfmt+="ll";
func="(unsigned long long)("; // Must match %ull to avoid warnings
}
string pfmt = "%"+nfmt+fmtLetter;
emitDispState.pushFormat(pfmt);
emitDispState.pushArg(*elistp,"");
emitDispState.pushArg(*elistp,func);
}
// Next parameter
*elistp = (*elistp)->nextp();
@@ -1246,12 +1257,8 @@ void EmitCImp::emitWrapEval(AstModule* modp) {
puts("while (VL_LIKELY(__Vchange)) {\n");
puts( "VL_DEBUG_IF(cout<<\" Clock loop\"<<endl;);\n");
#endif
// Not exactly correct for coverage. w/combo logic interspersed, this is complicated. Punt.
// Perhaps have temp & each _combo_ turn it on or off
if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = true;\n");
puts( "vlSymsp->__Vm_activity = true;\n");
puts( "_eval(vlSymsp);\n");
if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = false;\n");
#ifndef NEW_ORDERING
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
@@ -1284,7 +1291,7 @@ void EmitCImp::emitWrapEval(AstModule* modp) {
void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp) {
// Put out a list of signal declarations
// in order of 0:clocks, 1:uint8, 2:uint16, 4:uint32, 5:uint64, 6:wide, 7:arrays
// in order of 0:clocks, 1:vluint8, 2:vluint16, 4:vluint32, 5:vluint64, 6:wide, 7:arrays
// This aids cache packing and locality
// Largest->smallest reduces the number of pad variables.
// But for now, Smallest->largest makes it more likely a small offset will allow access to the signal.
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3EMITC_H_
#define _V3EMITC_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+3 -2
View File
@@ -22,7 +22,8 @@
#ifndef _V3EMITCBASE_H_
#define _V3EMITCBASE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -109,7 +110,7 @@ public:
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
static string symTopAssign() { return v3Global.opt.prefix()+"* __restrict vlTOPp = vlSymsp->TOPp;"; }
static string symTopAssign() { return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
static string modClassName(AstModule* modp) { // Return name of current module being processed
if (modp->isTop()) {
return v3Global.opt.prefix();
+4 -8
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -124,18 +125,14 @@ void EmitCSyms::emitInt() {
//puts("\n// STATIC STATE\n");
puts("\n// LOCAL STATE\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint64_t));
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(vluint64_t));
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_didInit;\n");
if (v3Global.opt.coverage()) {
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool __Vm_coverageRequest;\n");
}
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint64_t));
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(vluint64_t));
puts("\n// SUBCELL STATE\n");
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstModule* modp = it->second;
@@ -184,7 +181,6 @@ void EmitCSyms::emitImp() {
puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
puts("\t, __Vm_activity(false)\n");
puts("\t, __Vm_didInit(false)\n");
if (v3Global.opt.coverage()) puts("\t, __Vm_coverageRequest(false)\n");
puts("\t// Setup submodule names\n");
char comma=',';
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
+5 -1
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -96,6 +97,9 @@ public:
// Imply generating verilated.o
if (v3Global.opt.exe()) {
v3Global.opt.addCppFile("verilated.cpp");
if (v3Global.opt.trace()) {
v3Global.opt.addCppFile("SpTraceVcdC.cpp");
}
}
V3StringSet dirs;
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3EMITMK_H_
#define _V3EMITMK_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+3 -2
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -199,7 +200,7 @@ public:
puts(";");
nodep->condp()->iterateAndNext(*this);
puts(";");
nodep->assignsp()->iterateAndNext(*this);
nodep->incsp()->iterateAndNext(*this);
m_suppressSemi = false;
puts(") {\n");
nodep->bodysp()->iterateAndNext(*this);
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3EMITV_H_
#define _V3EMITV_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+15 -7
View File
@@ -92,7 +92,7 @@ void FileLine::lineDirective(const char* textp) {
bool FileLine::warnOff(const string& msg, bool flag) {
V3ErrorCode code (msg.c_str());
if (code == V3ErrorCode::ERROR) {
if (code < V3ErrorCode::FIRST_WARN) {
return false;
} else {
warnOff(code, flag);
@@ -168,9 +168,8 @@ void FileLine::v3errorEnd(ostringstream& str) {
void V3Error::init() {
for (int i=0; i<V3ErrorCode::MAX; i++) {
s_describedEachWarn[i] = false;
s_pretendError[i] = false;
s_pretendError[i] = V3ErrorCode(i).pretendError();
}
pretendError(V3ErrorCode::BLKANDNBLK, true);
if (string(V3ErrorCode(V3ErrorCode::MAX).ascii()) != " MAX") {
v3fatalSrc("Enum table in V3ErrorCode::ascii() is munged");
@@ -204,8 +203,9 @@ void V3Error::abortIfErrors() {
string V3Error::msgPrefix(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
else if (code==V3ErrorCode::FATAL) return "%Error: ";
else if (code==V3ErrorCode::ERROR
|| s_pretendError[code]) return "%Error: ";
else if (code==V3ErrorCode::ERROR) return "%Error: ";
else if (code<V3ErrorCode::FIRST_WARN
|| s_pretendError[code]) return "%Error-"+(string)code.ascii()+": ";
else return "%Warning-"+(string)code.ascii()+": ";
}
@@ -236,6 +236,9 @@ void V3Error::v3abort () {
}
void V3Error::v3errorEnd (ostringstream& sstr) {
#ifdef __COVERITY__
if (s_errorCode==V3ErrorCode::FATAL) __coverity_panic__(x);
#endif
if (s_errorCode!=V3ErrorCode::SUPPRESS || debug()) {
cerr<<msgPrefix()<<sstr.str();
if (sstr.str()[sstr.str().length()-1] != '\n') {
@@ -268,8 +271,13 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
}
#endif
}
abort();
// exit(10);
if (V3Error::debugDefault()) {
cerr<<msgPrefix()<<"Aborting since under --debug"<<endl;
abort();
} else {
exit(10);
}
}
}
}
+12 -3
View File
@@ -21,7 +21,8 @@
#ifndef _V3ERROR_H_
#define _V3ERROR_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <string>
#include <iostream>
#include <sstream>
@@ -34,9 +35,12 @@ public:
enum en {
SUPPRESS, // Warning suppressed by user
FATAL, // Kill the program
ERROR, // Error out, can't suppress
ERROR, // General error out, can't suppress
// Error codes:
TASKNSVAR, // Error: Task I/O not simple
// Warning codes:
FIRST_WARN, // Just a code so the program knows where to start warnings
//
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
CASEINCOMPLETE, // Case statement has missing values
CASEOVERLAP, // Case statements overlap
@@ -45,6 +49,7 @@ public:
COMBDLY, // Combinatorial delayed assignment
GENCLK, // Generated Clock
IMPLICIT, // Implicit wire
IMPURE, // Impure function not being inlined
MULTIDRIVEN, // Driven from multiple blocks
UNDRIVEN, // No drivers
UNOPT, // Unoptimizable block
@@ -66,10 +71,11 @@ public:
const char* names[] = {
// Leading spaces indicate it can't be disabled.
" SUPPRESS", " FATAL", " ERROR",
"TASKNSVAR",
" FIRST_WARN",
"BLKANDNBLK",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
"COMBDLY", "GENCLK", "IMPLICIT",
"COMBDLY", "GENCLK", "IMPLICIT", "IMPURE",
"MULTIDRIVEN",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH",
@@ -79,6 +85,9 @@ public:
};
// Warnings that warn about nasty side effects
bool dangerous() const { return ( m_e==COMBDLY );};
// 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); };
};
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); }
+5 -1
View File
@@ -30,7 +30,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -660,6 +661,9 @@ private:
// Lhs or Rhs may be word, long, or quad.
// newAstWordSelClone nicely abstracts the difference.
int rhsshift = rhsp->rhsp()->widthMin();
// Sometimes doing the words backwards is preferrable.
// When we have x={x,foo} backwards is better, when x={foo,x} forward is better
// However V3Subst tends to rip this up, so not worth optimizing now.
for (int w=0; w<rhsp->widthWords(); w++) {
addWordAssign(nodep, w,
new AstOr (rhsp->fileline(),
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3EXPAND_H_
#define _V3EXPAND_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdarg.h>
#include <sys/stat.h>
#include <unistd.h>
+5 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3FILE_H_
#define _V3FILE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include <stdio.h>
#include <stack>
@@ -42,6 +43,9 @@ public:
}
static ofstream* new_ofstream(const string& filename, bool append=false) {
addTgtDepend(filename);
return new_ofstream_nodepend (filename, append);
}
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
if (append) {
return new ofstream(filename.c_str(), ios::app);
} else {
+2 -1
View File
@@ -26,7 +26,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3GATE_H_
#define _V3GATE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -24,7 +24,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3GENCLK_H_
#define _V3GENCLK_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -22,7 +22,8 @@
#ifndef _V3GLOBAL_H_
#define _V3GLOBAL_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <string>
#include "V3Error.h"
+2 -1
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3GRAPH_H_
#define _V3GRAPH_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3List.h"
#include <vector>
+2 -1
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3GRAPHALG_H_
#define _V3GRAPHALG_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Global.h"
#include "V3Graph.h"
+3 -2
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -64,7 +65,7 @@ class GraphNfaToDfa : GraphAlg {
private:
// TYPES
typedef deque<DfaVertex*> DfaStates;
typedef multimap<uint64_t,DfaVertex*> HashMap;
typedef multimap<vluint64_t,DfaVertex*> HashMap;
// MEMBERS
uint32_t m_step; // Processing step, so we can avoid clearUser all the time
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3GRAPHDFA_H_
#define _V3GRAPHDFA_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <vector>
#include "V3Global.h"
+2 -1
View File
@@ -19,7 +19,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -26,7 +26,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3HASHED_H_
#define _V3HASHED_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+3 -4
View File
@@ -29,7 +29,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -111,7 +112,6 @@ private:
nodep->name(), nodep->modp()->origName());
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
// Create assignments to the pins
AstNode* assignlistsp = NULL;
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
UINFO(6," Pin change from "<<pinp->modVarp()<<endl);
// First, simplify it
@@ -142,13 +142,11 @@ private:
// Cleanup var names, etc, to not conflict
m_cellp = nodep;
newmodp->iterateAndNext(*this);
if (assignlistsp) assignlistsp->iterateAndNext(*this); // And cleanup any varrefs under assigns we created...
m_cellp = NULL;
// Move statements to top module
if (debug()>=9) { newmodp->dumpTree(cout,"fixmod:"); }
AstNode* stmtsp = newmodp->stmtsp();
if (stmtsp) stmtsp->unlinkFrBackWithNext();
if (assignlistsp) m_modp->addStmtp(assignlistsp);
if (stmtsp) m_modp->addStmtp(stmtsp);
// Remove the cell
newmodp->deleteTree(); newmodp=NULL; // Clear any leftover ports, etc
@@ -353,6 +351,7 @@ private:
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
// Cleanup link until V3LinkDot can correct it
nodep->taskp(NULL);
nodep->iterateChildren(*this);
}
// Nop's to speed up the loop
virtual void visit(AstAlways* nodep, AstNUser*) {
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3INLINE_H_
#define _V3INLINE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+16 -7
View File
@@ -26,7 +26,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -79,7 +80,7 @@ private:
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
UINFO(4," PIN "<<nodep<<endl);
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
if (nodep->modVarp()->isOutput() && nodep->exprp()->castConst())
if (nodep->modVarp()->isOutOnly() && nodep->exprp()->castConst())
nodep->v3error("Output pin is assigned to a constant, electrical short");
// Use userp on the PIN to indicate we created an assign for this pin
if (!nodep->user()) {
@@ -90,7 +91,9 @@ private:
AstNode* exprp = nodep->exprp()->cloneTree(false);
if (nodep->width() != nodep->modVarp()->width())
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
if (nodep->modVarp()->isOutput()) {
if (nodep->modVarp()->isInout()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isOutput()) {
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
rhsp->widthSignedFrom(nodep);
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
@@ -157,7 +160,11 @@ private:
nodep->addNextHere(newp);
// Remove ranging and fix name
newp->rangep()->unlinkFrBack()->deleteTree();
// Somewhat illogically, we need to rename the orignal name of the cell too.
// as that is the name users expect for dotting
// The spec says we add [x], but that won't work in C...
newp->name(newp->name()+"__"+cvtToStr(m_instNum));
newp->origName(newp->origName()+"__"+cvtToStr(m_instNum));
// Fixup pins
newp->pinsp()->iterateAndNext(*this);
if (debug()==9) { newp->dumpTree(cout,"newcell: "); cout<<endl; }
@@ -194,7 +201,7 @@ private:
}
// Save some time
virtual void visit(AstNodeStmt*, AstNUser*) {}
virtual void visit(AstNodeMath*, AstNUser*) {}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep, AstNUser*) {
@@ -232,12 +239,14 @@ void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstModule* modp) {
} else {
// Make a new temp wire
//if (1||debug()>=9) { pinp->dumpTree(cout,"in_pin:"); }
AstAssignW* assignp;
AstAssignW* assignp = NULL;
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
modp->addStmtp(newvarp);
if (pinVarp->isOutput()) {
if (pinVarp->isInout()) {
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
} else if (pinVarp->isOutput()) {
// See also V3Inst
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
if (pinp->width() > rhsp->width()) {
@@ -261,7 +270,7 @@ void V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstModule* modp) {
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
}
pinp->widthSignedFrom(pinp->exprp());
modp->addStmtp(assignp);
if (assignp) modp->addStmtp(assignp);
//if (1||debug()) { pinp->dumpTree(cout," out:"); }
//if (1||debug()) { assignp->dumpTree(cout," aout:"); }
}
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3INST_H_
#define _V3INST_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3LANGUAGEWORDS_H_
#define _V3LANGUAGEWORDS_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <map>
//============================================================================
+299 -137
View File
@@ -28,7 +28,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -38,152 +39,243 @@
#include "V3Life.h"
#include "V3Stats.h"
#include "V3Ast.h"
#include "V3Const.h"
//######################################################################
// Life state, as a visitor of each AstNode
// Structure for global state
class LifeVarEntry {
AstNode* m_assignp; // Last assignment to this varscope
bool m_firstSet; // True if creation was a set (and thus block above may have a set that can be deleted
class LifeState {
// STATE
public:
LifeVarEntry() { // Construction for when a var is used
clearAssign();
m_firstSet = false;
V3Double0 m_statAssnDel; // Statistic tracking
V3Double0 m_statAssnCon; // Statistic tracking
public:
LifeState() {}
~LifeState() {
V3Stats::addStat("Optimizations, Lifetime assign deletions", m_statAssnDel);
V3Stats::addStat("Optimizations, Lifetime constant prop", m_statAssnCon);
}
LifeVarEntry(AstNode* assp) { // Construction for when a var is set
m_assignp = assp;
m_firstSet = true;
}
LifeVarEntry(bool) { // Construction for when a var is set, but ass isn't
m_assignp = NULL;
m_firstSet = true;
}
AstNode* assignp() const { return m_assignp; }
bool firstSet() const { return m_firstSet; }
void clearAssign() { m_assignp = NULL; }
void newerAssign(AstNode* assp) { m_assignp = assp; }
};
class LifeVisitor : public AstNVisitor {
private:
// NODE STATE
// AstVarScope::user() -> int. Used in combining to detect duplicates
//######################################################################
// Structure for each variable encountered
// STATE
//static int debug() { return 9; }
int m_ifCount; // If counter
V3Double0 m_statAssnDel; // Statistic tracking
class LifeVarEntry {
AstNodeAssign* m_assignp; // Last assignment to this varscope, NULL if no longer relevant
AstConst* m_constp; // Known constant value
bool m_setBeforeUse; // First access was a set (and thus block above may have a set that can be deleted
bool m_everSet; // Was ever assigned (and thus above block may not preserve constant propagation)
inline void init (bool setBeforeUse) {
m_assignp = NULL;
m_constp = NULL;
m_setBeforeUse = setBeforeUse;
m_everSet = false;
}
public:
class SIMPLEASSIGN {};
class COMPLEXASSIGN {};
class CONSUMED {};
LifeVarEntry(SIMPLEASSIGN, AstNodeAssign* assp) {
init(true); simpleAssign(assp);
}
LifeVarEntry(COMPLEXASSIGN) {
init(false); complexAssign();
}
LifeVarEntry(CONSUMED) {
init(false); consumed();
}
~LifeVarEntry() {}
inline void simpleAssign(AstNodeAssign* assp) { // New simple A=.... assignment
m_assignp = assp;
m_constp = NULL;
m_everSet = true;
if (assp->rhsp()->castConst()) m_constp = assp->rhsp()->castConst();
}
inline void complexAssign() { // A[x]=... or some complicated assignment
m_assignp = NULL;
m_constp = NULL;
m_everSet = true;
}
inline void consumed() { // Rvalue read of A
m_assignp = NULL;
}
AstNodeAssign* assignp() const { return m_assignp; }
AstConst* constNodep() const { return m_constp; }
bool setBeforeUse() const { return m_setBeforeUse; }
bool everSet() const { return m_everSet; }
};
//######################################################################
// Structure for all variables under a given meta-basic block
class LifeBlock {
// NODE STATE
// Cleared each AstIf:
// AstVarScope::user() -> int. Used in combining to detect duplicates
// LIFE MAP
// For each basic block, we'll make a new map of what variables that if/else is changing
typedef std::map<AstVarScope*, LifeVarEntry> LifeMap;
LifeMap *m_lifep; // Current active lifetime map for current scope
LifeMap m_map; // Current active lifetime map for current scope
LifeBlock* m_aboveLifep; // Upper life, or NULL
LifeState* m_statep; // Current global state
public:
LifeBlock(LifeBlock* aboveLifep, LifeState* statep) {
m_aboveLifep = aboveLifep; // Null if top
m_statep = statep;
}
~LifeBlock() {}
// METHODS
void checkRemoveAssign(LifeVarEntry* entp) {
// Check the var entry, and remove if appropriate
if (AstNode* oldassp = entp->assignp()) {
UINFO(7," PREV: "<<oldassp<<endl);
// Redundant assignment, in same level block
if (debug()>4) oldassp->dumpTree(cout, " REMOVE/SAMEBLK ");
entp->clearAssign();
oldassp->unlinkFrBack();
pushDeletep(oldassp);
m_statAssnDel++;
void checkRemoveAssign(const LifeMap::iterator& it) {
AstVar* varp = it->first->varp();
LifeVarEntry* entp = &(it->second);
if (!varp->isSigPublic()) {
// Rather then 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()) {
UINFO(7," PREV: "<<oldassp<<endl);
// Redundant assignment, in same level block
if (debug()>4) oldassp->dumpTree(cout, " REMOVE/SAMEBLK ");
entp->complexAssign();
oldassp->unlinkFrBack()->deleteTree(); oldassp=NULL;
m_statep->m_statAssnDel++;
}
}
}
void setLast(AstVarScope* nodep, AstNode* assp) {
void simpleAssign(AstVarScope* nodep, AstNodeAssign* assp) {
// Do we have a old assignment we can nuke?
UINFO(4," ASSIGNof: "<<nodep<<endl);
UINFO(7," new: "<<assp<<endl);
LifeMap::iterator iter = m_lifep->find(nodep);
if (iter != m_lifep->end()) {
checkRemoveAssign(&(iter->second));
iter->second.newerAssign(assp);
LifeMap::iterator it = m_map.find(nodep);
if (it != m_map.end()) {
checkRemoveAssign(it);
it->second.simpleAssign(assp);
} else {
m_lifep->insert(make_pair(nodep,LifeVarEntry(assp)));
m_map.insert(make_pair(nodep,LifeVarEntry(LifeVarEntry::SIMPLEASSIGN(), assp)));
}
//lifeDump();
}
void clearLastAssign(AstVarScope* nodep) {
void complexAssign(AstVarScope* nodep) {
UINFO(4," clearof: "<<nodep<<endl);
LifeMap::iterator iter = m_lifep->find(nodep);
if (iter != m_lifep->end()) {
iter->second.clearAssign();
LifeMap::iterator it = m_map.find(nodep);
if (it != m_map.end()) {
it->second.complexAssign();
} else {
m_lifep->insert(make_pair(nodep,LifeVarEntry()));
m_map.insert(make_pair(nodep,LifeVarEntry(LifeVarEntry::COMPLEXASSIGN())));
}
}
void lifeDump(LifeMap* lifep) {
void varUsageReplace (AstVarScope* nodep, AstVarRef* varrefp) {
// Variable rvalue. If it references a constant, we can simply replace it
LifeMap::iterator it = m_map.find(nodep);
if (it != m_map.end()) {
if (AstConst* constp = it->second.constNodep()) {
if (!varrefp->varp()->isSigPublic()) {
// Aha, variable is constant; substitute in.
// We'll later constant propagate
UINFO(4," replaceconst: "<<varrefp<<endl);
varrefp->replaceWith(constp->cloneTree(false));
varrefp->deleteTree(); varrefp=NULL;
m_statep->m_statAssnCon++;
return; // **DONE, no longer a var reference**
}
}
UINFO(4," usage: "<<nodep<<endl);
it->second.consumed();
} else {
m_map.insert(make_pair(nodep,LifeVarEntry(LifeVarEntry::CONSUMED())));
}
}
void complexAssignFind(AstVarScope* nodep) {
LifeMap::iterator it = m_map.find(nodep);
if (it != m_map.end()) {
UINFO(4," casfind: "<<it->first<<endl);
it->second.complexAssign();
} else {
m_map.insert(make_pair(nodep,LifeVarEntry(LifeVarEntry::COMPLEXASSIGN())));
}
}
void consumedFind(AstVarScope* nodep) {
LifeMap::iterator it = m_map.find(nodep);
if (it != m_map.end()) {
it->second.consumed();
} else {
m_map.insert(make_pair(nodep,LifeVarEntry(LifeVarEntry::CONSUMED())));
}
}
void lifeToAbove() {
// Any varrefs under a if/else branch affect statements outside and after the if/else
if (!m_aboveLifep) v3fatalSrc("Pushing life when already at the top level");
for (LifeMap::iterator it = m_map.begin(); it!=m_map.end(); ++it) {
AstVarScope* nodep = it->first;
m_aboveLifep->complexAssignFind(nodep);
if (it->second.everSet()) {
// Record there may be an assignment, so we don't constant propagate across the if.
complexAssignFind(nodep);
} else {
// Record consumption, so we don't eliminate earlier assignments
consumedFind(nodep);
}
}
}
void dualBranch (LifeBlock* life1p, LifeBlock* life2p) {
// Find any common sets on both branches of IF and propagate upwards
//life1p->lifeDump();
//life2p->lifeDump();
AstNode::userClearTree(); // userp() used on entire tree
for (LifeMap::iterator it = life1p->m_map.begin(); it!=life1p->m_map.end(); ++it) {
// When the if branch sets a var before it's used, mark that variable
if (it->second.setBeforeUse()) it->first->user(1);
}
for (LifeMap::iterator it = life2p->m_map.begin(); it!=life2p->m_map.end(); ++it) {
// When the else branch sets a var before it's used
AstVarScope* nodep = it->first;
if (it->second.setBeforeUse() && nodep->user()) {
// Both branches set the var, we can remove the assignment before the IF.
UINFO(4,"DUALBRANCH "<<nodep<<endl);
LifeMap::iterator itab = m_map.find(nodep);
if (itab != m_map.end()) {
checkRemoveAssign(itab);
}
}
}
//this->lifeDump();
}
// DEBUG
void lifeDump() {
UINFO(5, " LifeMap:"<<endl);
for (LifeMap::iterator it = lifep->begin(); it!=lifep->end(); ++it) {
for (LifeMap::iterator it = m_map.begin(); it!=m_map.end(); ++it) {
UINFO(5, " Ent: "
<<(it->second.firstSet()?"[F] ":" ")
<<(it->second.setBeforeUse()?"[F] ":" ")
<<it->first<<endl);
if (it->second.assignp()) {
UINFO(5, " Ass: "<<it->second.assignp()<<endl);
}
}
}
void clearLifeFromSublife (LifeMap* sublifep) {
// Any varrefs under a if/else branch affect statements outside and after the if/else
for (LifeMap::iterator it = sublifep->begin(); it!=sublifep->end(); ++it) {
clearLastAssign(it->first);
}
}
void dualBranch (LifeMap* life1p, LifeMap* life2p) {
// Find any common sets on both branches of IF and propagate upwards
//lifeDump(life1p);
//lifeDump(life2p);
m_ifCount++;
for (LifeMap::iterator it = life1p->begin(); it!=life1p->end(); ++it) {
// When the if branch sets a var before it's used, mark that variable
if (it->second.firstSet()) it->first->user(m_ifCount);
}
for (LifeMap::iterator it = life2p->begin(); it!=life2p->end(); ++it) {
// When the else branch sets a var before it's used
AstVarScope* nodep = it->first;
if (it->second.firstSet()
&& nodep->user()==m_ifCount) { // And the if hit the same var
UINFO(4,"DUALBRANCH "<<nodep<<endl);
LifeMap::iterator iter = m_lifep->find(nodep);
if (iter != m_lifep->end()) {
checkRemoveAssign(&(iter->second));
iter->second.clearAssign();
} else {
m_lifep->insert(make_pair(nodep,LifeVarEntry(true)));
}
}
}
//lifeDump(m_lifep);
}
};
//######################################################################
// Life state, as a visitor of each AstNode
class LifeVisitor : public AstNVisitor {
private:
// STATE
LifeState* m_statep; // Current state
bool m_sideEffect; // Side effects discovered in assign RHS
//static int debug() { return 9; }
// LIFE MAP
// For each basic block, we'll make a new map of what variables that if/else is changing
typedef std::map<AstVarScope*, LifeVarEntry> LifeMap;
LifeBlock* m_lifep; // Current active lifetime map for current scope
// METHODS
// VISITORS
virtual void visit(AstModule* nodep, AstNUser*) {
// Only track the top scopes, not lower level functions
if (nodep->isTop()) nodep->iterateChildren(*this);
}
virtual void visit(AstTopScope* nodep, AstNUser*) {
AstNode::userClearTree(); // userp() used on entire tree
AstNode::user2ClearTree(); // userp() used on entire tree
AstNode::user3ClearTree(); // userp() used on entire tree
AstNode::user4ClearTree(); // userp() used on entire tree
AstScope* scopep = nodep->scopep();
if (!scopep) nodep->v3fatalSrc("TopScope has no scope\n");
AstCFunc* evalp = NULL;
for (AstNode* searchp = scopep->blocksp(); searchp; searchp=searchp->nextp()) {
if (AstCFunc* funcp = searchp->castCFunc()) {
if (funcp->name() == "_eval") {
evalp = funcp;
break;
}
}
}
if (!evalp) nodep->v3fatalSrc("Top _eval entry function not found\n");
evalp->iterateChildren(*this);
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
// Consumption/generation of a variable,
// it's used so can't elim assignment before this use.
@@ -191,44 +283,61 @@ private:
//
AstVarScope* vscp = nodep->varScopep();
if (!vscp) nodep->v3fatalSrc("Scope not assigned");
clearLastAssign(vscp);
if (nodep->lvalue()) {
m_lifep->complexAssign(vscp);
} else {
m_lifep->varUsageReplace(vscp, nodep); nodep=NULL;
}
}
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
// Collect any used variables first, as lhs may also be on rhs
// Similar code in V3Dead
vluint64_t lastEdit = AstNode::editCountGbl(); // When it was last edited
m_sideEffect = false;
nodep->rhsp()->iterateAndNext(*this);
if (lastEdit != AstNode::editCountGbl()) {
// We changed something, try to constant propagate, but don't delete the
// assignment as we still need nodep to remain.
V3Const::constifyTree(nodep->rhsp());
}
// Has to be direct assignment without any EXTRACTing.
if (nodep->lhsp()->castVarRef()) {
if (nodep->lhsp()->castVarRef() && !m_sideEffect) {
AstVarScope* vscp = nodep->lhsp()->castVarRef()->varScopep();
if (!vscp) vscp->v3fatalSrc("Scope lost on variable");
setLast(vscp, nodep);
m_lifep->simpleAssign(vscp, nodep);
} else {
nodep->lhsp()->iterateAndNext(*this);
}
}
virtual void visit(AstAssignDly* nodep, AstNUser*) {
// Don't treat as normal assign; V3Life doesn't understand time sense
nodep->iterateChildren(*this);
}
//---- Track control flow changes
virtual void visit(AstNodeIf* nodep, AstNUser*) {
UINFO(4," IF "<<nodep<<endl);
// Condition is part of PREVIOUS block
nodep->condp()->iterateAndNext(*this);
LifeMap* prevLifeMapp = m_lifep;
LifeMap* ifLifep = new LifeMap;
LifeMap* elseLifep = new LifeMap;
LifeBlock* prevLifep = m_lifep;
LifeBlock* ifLifep = new LifeBlock (prevLifep, m_statep);
LifeBlock* elseLifep = new LifeBlock (prevLifep, m_statep);
{
m_lifep = ifLifep;
nodep->ifsp()->iterateAndNext(*this);
m_lifep = prevLifep;
}
{
m_lifep = elseLifep;
nodep->elsesp()->iterateAndNext(*this);
m_lifep = prevLifep;
}
UINFO(4," join "<<endl);
m_lifep = prevLifeMapp;
// Find sets on both flows
dualBranch (ifLifep, elseLifep);
m_lifep->dualBranch (ifLifep, elseLifep);
// For the next assignments, clear any variables that were read or written in the block
clearLifeFromSublife(ifLifep);
clearLifeFromSublife(elseLifep);
ifLifep->lifeToAbove();
elseLifep->lifeToAbove();
delete ifLifep;
delete elseLifep;
}
@@ -240,24 +349,25 @@ private:
// assignment in the body that's used in the cond. (And otherwise
// would because it only appears used after-the-fact. So, we model
// it as a IF statement, and just don't allow elimination of
// variables in the body.
LifeMap* prevLifeMapp = m_lifep;
LifeMap* condLifep = new LifeMap;
LifeMap* bodyLifep = new LifeMap;
// variables across the body.
LifeBlock* prevLifep = m_lifep;
LifeBlock* condLifep = new LifeBlock (prevLifep, m_statep);
LifeBlock* bodyLifep = new LifeBlock (prevLifep, m_statep);
{
m_lifep = condLifep;
nodep->precondsp()->iterateAndNext(*this);
nodep->condp()->iterateAndNext(*this);
m_lifep = prevLifep;
}
{
m_lifep = bodyLifep;
nodep->bodysp()->iterateAndNext(*this);
m_lifep = prevLifep;
}
UINFO(4," joinfor"<<endl);
m_lifep = prevLifeMapp;
// For the next assignments, clear any variables that were read or written in the block
clearLifeFromSublife(condLifep);
clearLifeFromSublife(bodyLifep);
condLifep->lifeToAbove();
bodyLifep->lifeToAbove();
delete condLifep;
delete bodyLifep;
}
@@ -265,8 +375,15 @@ private:
//UINFO(4," CCALL "<<nodep<<endl);
nodep->iterateChildren(*this);
// Enter the function and trace it
nodep->funcp()->accept(*this);
if (!nodep->funcp()->entryPoint()) { // else is non-inline or public function we optimize separately
nodep->funcp()->accept(*this);
}
}
virtual void visit(AstUCFunc* nodep, AstNUser*) {
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
nodep->iterateChildren(*this);
}
virtual void visit(AstVar*, AstNUser*) {} // Don't want varrefs under it
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
@@ -274,15 +391,60 @@ private:
public:
// CONSTRUCTORS
LifeVisitor(AstNetlist* nodep) {
m_ifCount = 1;
m_lifep = new LifeMap;
LifeVisitor(AstNode* nodep, LifeState* statep) {
UINFO(4," LifeVisitor on "<<nodep<<endl);
m_statep = statep;
m_sideEffect = false;
{
m_lifep = new LifeBlock (NULL, m_statep);
nodep->accept(*this);
delete m_lifep; m_lifep=NULL;
}
}
virtual ~LifeVisitor() {}
};
//######################################################################
class LifeTopVisitor : public AstNVisitor {
// Visit all top nodes searching for functions that are entry points we want to start
// finding code within.
private:
// STATE
LifeState* m_statep; // Current state
// VISITORS
virtual void visit(AstCFunc* nodep, AstNUser*) {
if (nodep->entryPoint()) {
// Usage model 1: Simulate all C code, doing lifetime analysis
LifeVisitor visitor (nodep, m_statep);
}
}
virtual void visit(AstAlways* nodep, AstNUser*) {
// Usage model 2: Cleanup basic blocks
LifeVisitor visitor (nodep, m_statep);
}
virtual void visit(AstInitial* nodep, AstNUser*) {
// Usage model 2: Cleanup basic blocks
LifeVisitor visitor (nodep, m_statep);
}
virtual void visit(AstFinal* nodep, AstNUser*) {
// Usage model 2: Cleanup basic blocks
LifeVisitor visitor (nodep, m_statep);
}
virtual void visit(AstVar*, AstNUser*) {} // Accelerate
virtual void visit(AstNodeStmt*, AstNUser*) {} // Accelerate
virtual void visit(AstNodeMath*, AstNUser*) {} // Accelerate
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTRUCTORS
LifeTopVisitor(AstNetlist* nodep, LifeState* statep) {
m_statep = statep;
nodep->accept(*this);
delete m_lifep;
}
virtual ~LifeVisitor() {
V3Stats::addStat("Optimizations, Lifetime assign deletions", m_statAssnDel);
}
virtual ~LifeTopVisitor() {}
};
//######################################################################
@@ -290,6 +452,6 @@ public:
void V3Life::lifeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
// Delete lifelicate assignments
LifeVisitor visitor (nodep);
LifeState state;
LifeTopVisitor visitor (nodep, &state);
}
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3LIFE_H_
#define _V3LIFE_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -29,7 +29,8 @@
//
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3LIFEPOST_H_
#define _V3LIFEPOST_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -26,7 +26,8 @@
// Link to var they reference
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3LINK_H_
#define _V3LINK_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+2 -1
View File
@@ -25,7 +25,8 @@
// Link to module that instantiates it
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3LINKCELLS_H_
#define _V3LINKCELLS_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
+125 -38
View File
@@ -29,7 +29,8 @@
// Find appropriate named cell and link to var they reference
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -68,12 +69,38 @@ public:
void insertSubcellName(const string& name, LinkDotBaseVertex* toVertexp) {
m_nameToVtxMap.insert(make_pair(name,toVertexp));
}
LinkDotBaseVertex* findSubcell(const string& name) {
LinkDotBaseVertex* findSubcell(const string& name, const string& altname) {
// Find a vertex under this one by name.
// We could walk the edge top() list, but that would be O(n) for large lists of cells
NameVtxMap::iterator iter = m_nameToVtxMap.find(name);
if (iter == m_nameToVtxMap.end()) return NULL;
else return iter->second;
{
NameVtxMap::iterator iter = m_nameToVtxMap.find(name);
if (iter != m_nameToVtxMap.end()) return iter->second;
}
if (altname != "") {
NameVtxMap::iterator iter = m_nameToVtxMap.find(altname);
if (iter != m_nameToVtxMap.end()) return iter->second;
}
return NULL;
}
void errorScopes(AstNode* nodep) {
if (!this) { // Silence if we messed it up and aren't debugging
if (debug()) nodep->v3fatalSrc("Void pointer; perhaps used null vxp instead of okVxp?");
return;
}
{
string scopes;
for (NameVtxMap::iterator it = m_nameToVtxMap.begin(); it!=m_nameToVtxMap.end(); ++it) {
if (scopes != "") scopes += ", ";
scopes += AstNode::prettyName(it->second->cellName());
}
cerr<<V3Error::msgPrefix()<<" Known scopes under '"<<cellName()<<"': "
<<scopes<<endl;
}
if (debug()) {
for (NameVtxMap::iterator it = m_nameToVtxMap.begin(); it!=m_nameToVtxMap.end(); ++it) {
UINFO(1,"\t\t KnownScope: "<<it->second->name()<<endl);
}
}
}
};
@@ -119,6 +146,27 @@ public:
virtual string dotColor() const { return "yellow"; }
};
class LinkDotBeginVertex : public LinkDotBaseVertex {
// A fake point in the hierarchy, corresponding to a begin block
// After we remove begins these will go away
// Note we use the symbol table of the parent, as we want to find variables there
// However, cells walk the graph, so cells will appear under the begin itself
AstBegin* m_nodep; // Relevant node
LinkDotCellVertex* m_symVxp; // Above cell so we can find real symbol table
// // (Could walk graph to find it, but that's much slower.)
public:
LinkDotBeginVertex(V3Graph* graphp, AstBegin* nodep, LinkDotCellVertex* symVxp)
: LinkDotBaseVertex(graphp, nodep->name()+"__DOT__")
, m_nodep(nodep), m_symVxp(symVxp) {}
virtual ~LinkDotBeginVertex() {}
// Search up through tree to find the real symbol table.
virtual V3SymTable& syms() { return m_symVxp->syms(); }
virtual string modName() const { return m_nodep->name(); }
virtual string cellName() const { return m_nodep->name(); }
virtual string name() const { return (string)("BEG C:")+cellName(); }
virtual string dotColor() const { return "blue"; }
};
//######################################################################
// LinkDot state, as a visitor of each AstNode
@@ -134,18 +182,20 @@ private:
// MEMBERS
LinkDotGraph m_graph; // Graph of hiearchy
NameScopeMap m_nameScopeMap; // Hash of scope referenced by textual name
bool m_forPrearray; // Compress cell__[array] refs
bool m_forScopeCreation; // Remove VarXRefs for V3Scope
public:
static int debug() { return V3Error::debugDefault(); }
// static int debug() { return 9; }
// CONSTRUCTORS
LinkDotState(bool forScopeCreation) {
LinkDotState(bool forPrearray, bool forScopeCreation) {
UINFO(4,__FUNCTION__<<": "<<endl);
m_forPrearray = forPrearray;
m_forScopeCreation = forScopeCreation;
//VV***** We reset all userp() on each netlist!!!
AstNode::userClearTree();
AstNode::user2ClearTree();
m_forScopeCreation = forScopeCreation;
}
~LinkDotState() {}
@@ -186,6 +236,14 @@ public:
}
return vxp;
}
LinkDotBeginVertex* insertBegin(LinkDotBaseVertex* abovep, LinkDotCellVertex* cellVxp,
AstBegin* nodep) {
UINFO(9," INSERTbeg "<<nodep<<endl);
LinkDotBeginVertex* vxp = new LinkDotBeginVertex(&m_graph, nodep, cellVxp);
new V3GraphEdge(&m_graph, abovep, vxp, 1, false);
abovep->insertSubcellName(nodep->name(), vxp);
return vxp;
}
void insertSym(LinkDotCellVertex* abovep, const string& name, AstNode* nodep) {
UINFO(9," INSERTsym "<<name<<" "<<nodep<<endl);
abovep->syms().insert(name, nodep);
@@ -217,12 +275,14 @@ private:
return NULL;
}
public:
LinkDotBaseVertex* findDotted(LinkDotBaseVertex* cellVxp, const string& dotname, string& baddot) {
LinkDotBaseVertex* findDotted(LinkDotBaseVertex* cellVxp, const string& dotname,
string& baddot, LinkDotBaseVertex*& okVxp) {
// Given a dotted hiearchy 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;
string leftname = dotname;
okVxp = cellVxp; // So can list bad scopes
while (leftname != "") { // foreach dotted part of xref name
string::size_type pos;
string ident;
@@ -234,18 +294,27 @@ public:
leftname = "";
}
baddot = ident; // So user can see where they botched it
okVxp = cellVxp;
string altIdent = "";
if (m_forPrearray) {
// Cell foo__[array] before we've expanded arrays is just foo.
if ((pos = ident.find("__")) != string::npos) {
altIdent = ident.substr(0,pos);
}
}
UINFO(8," id "<<ident<<" left "<<leftname<<" at "<<cellVxp<<endl);
// Spec says; Look at exiting module (cellnames then modname),
// then look up (inst name or modname)
if (firstId) {
// Check this module - subcellnames
if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident)) {
if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident, altIdent)) {
cellVxp = findVxp;
}
// Check this module - cur modname
else if (cellVxp->modName() == ident) {}
// Check this module - cur cellname
else if (cellVxp->cellName() == ident) {}
else if (cellVxp->cellName() == altIdent) {}
// Move up and check cellname + modname
else {
while (cellVxp) {
@@ -253,10 +322,11 @@ public:
if (cellVxp) {
UINFO(9,"\t\tUp to "<<cellVxp<<endl);
if (cellVxp->modName() == ident
|| cellVxp->cellName() == ident) {
|| cellVxp->cellName() == ident
|| cellVxp->cellName() == altIdent) {
break;
}
else if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident)) {
else if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident, altIdent)) {
cellVxp = findVxp;
break;
}
@@ -265,7 +335,7 @@ public:
if (!cellVxp) return NULL; // Not found
}
} else { // Searching for middle submodule, must be a cell name
if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident)) {
if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident, altIdent)) {
cellVxp = findVxp;
} else {
return NULL; // Not found
@@ -336,29 +406,36 @@ private:
}
virtual void visit(AstCell* nodep, AstNUser*) {
UINFO(5," CELL under "<<m_scope<<" is "<<nodep<<endl);
// Process XREFs inside pins
nodep->iterateChildren(*this);
// Recurse in, preserving state
string oldscope = m_scope;
AstBegin* oldbeginp = m_beginp;
LinkDotCellVertex* oldVxp = m_cellVxp;
LinkDotBaseVertex* oldInlineVxp = m_inlineVxp;
// Where do we add it?
LinkDotBaseVertex* aboveVxp = m_cellVxp;
LinkDotBaseVertex* aboveVxp = m_inlineVxp;
string origname = nodep->prettyName();
string::size_type pos;
if ((pos = origname.rfind(".")) != string::npos) {
// Flattened, find what CellInline it should live under
string scope = origname.substr(0,pos);
string baddot;
aboveVxp = m_statep->findDotted(aboveVxp, scope, baddot);
LinkDotBaseVertex* okVxp;
aboveVxp = m_statep->findDotted(aboveVxp, scope, baddot, okVxp);
if (!aboveVxp) nodep->v3fatalSrc("Can't find cell insertion point at '"<<baddot<<"' in: "<<nodep->prettyName());
}
{
m_scope = m_scope+"."+nodep->name();
m_cellVxp = m_statep->insertCell(aboveVxp, m_cellVxp, nodep, m_scope);
m_inlineVxp = m_cellVxp;
m_beginp = NULL;
if (nodep->modp()) nodep->modp()->accept(*this);
}
m_scope = oldscope;
m_beginp = oldbeginp;
m_cellVxp = oldVxp;
m_inlineVxp = m_cellVxp;
m_inlineVxp = oldInlineVxp;
}
virtual void visit(AstCellInline* nodep, AstNUser*) {
UINFO(5," CELLINLINE under "<<m_scope<<" is "<<nodep<<endl);
@@ -370,7 +447,8 @@ private:
string dotted = dottedname.substr(0, pos);
string ident = dottedname.substr(pos+strlen("__DOT__"));
string baddot;
aboveVxp = m_statep->findDotted(aboveVxp, dotted, baddot);
LinkDotBaseVertex* okVxp;
aboveVxp = m_statep->findDotted(aboveVxp, dotted, baddot, okVxp);
if (!aboveVxp) nodep->v3fatalSrc("Can't find cellinline insertion point at '"<<baddot<<"' in: "<<nodep->prettyName());
m_statep->insertInline(aboveVxp, m_cellVxp, nodep, ident);
} else { // No __DOT__, just directly underneath
@@ -379,10 +457,16 @@ private:
}
virtual void visit(AstBegin* nodep, AstNUser*) {
UINFO(5," "<<nodep<<endl);
// We don't pickup variables, but do need to find cells
AstBegin* oldbegin = m_beginp;
m_beginp = nodep;
nodep->iterateChildren(*this);
LinkDotBaseVertex* oldVxp = m_inlineVxp;
{
m_beginp = nodep;
// Ignore begin names
m_inlineVxp = m_statep->insertBegin(m_inlineVxp, m_cellVxp, nodep);
// We don't pickup variables, but do need to find cells
nodep->iterateChildren(*this);
}
m_inlineVxp = oldVxp;
m_beginp = oldbegin;
}
virtual void visit(AstVar* nodep, AstNUser*) {
@@ -390,6 +474,8 @@ private:
&& !m_beginp // For now, we don't support xrefs into begin blocks
&& !nodep->isFuncLocal()) {
m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
} else {
UINFO(9," Not allowing dot refs to: "<<nodep<<endl);
}
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
@@ -401,7 +487,7 @@ private:
}
// For speed, don't recurse things that can't have cells
virtual void visit(AstNodeStmt*, AstNUser*) {}
// Note we allow AstNodeStmt's as generates may be under them
virtual void visit(AstNodeMath*, AstNUser*) {}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
@@ -462,9 +548,9 @@ private:
nodep->iterateChildren(*this);
}
// For speed, don't recurse things that can't have scope
// Note we allow AstNodeStmt's as generates may be under them
virtual void visit(AstCell*, AstNUser*) {}
virtual void visit(AstVar*, AstNUser*) {}
virtual void visit(AstNodeStmt*, AstNUser*) {}
virtual void visit(AstNodeMath*, AstNUser*) {}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
@@ -527,12 +613,14 @@ private:
nodep->varp(NULL); // Module that is not in hiearchy. We'll be dead code eliminating it later.
} else {
string baddot;
LinkDotBaseVertex* okVxp;
LinkDotBaseVertex* dotVxp = m_cellVxp; // Start search at current scope
if (nodep->inlinedDots()!="") { // Correct for current scope
dotVxp = m_statep->findDotted(dotVxp, nodep->inlinedDots(), baddot);
string inl = AstNode::prettyName(nodep->inlinedDots());
dotVxp = m_statep->findDotted(dotVxp, inl, baddot, okVxp);
if (!dotVxp) nodep->v3fatalSrc("Couldn't resolve inlined scope '"<<baddot<<"' in: "<<nodep->inlinedDots());
}
dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot); // Maybe NULL
dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot, okVxp); // Maybe NULL
if (!m_statep->forScopeCreation()) {
AstVar* varp = (m_statep->findSym(dotVxp, nodep->name(), baddot)
->castVar()); // maybe NULL
@@ -540,6 +628,7 @@ private:
UINFO(7," Resolved "<<nodep<<endl); // Also prints varp
if (!nodep->varp()) {
nodep->v3error("Can't find definition of '"<<baddot<<"' in dotted signal: "<<nodep->dotted()+"."+nodep->prettyName());
okVxp->errorScopes(nodep);
}
} else {
string baddot;
@@ -547,6 +636,7 @@ private:
->castVarScope()); // maybe NULL
if (!vscp) {
nodep->v3error("Can't find varpin scope of '"<<baddot<<"' in dotted signal: "<<nodep->dotted()+"."+nodep->prettyName());
okVxp->errorScopes(nodep);
} else {
while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal
UINFO(7," Resolved pre-alias "<<vscp<<endl); // Also prints taskp
@@ -570,12 +660,15 @@ private:
nodep->taskp(NULL); // Module that is not in hiearchy. We'll be dead code eliminating it later.
} else {
string baddot;
LinkDotBaseVertex* okVxp;
LinkDotBaseVertex* dotVxp = m_cellVxp; // Start search at current scope
if (nodep->inlinedDots()!="") { // Correct for current scope
dotVxp = m_statep->findDotted(dotVxp, nodep->inlinedDots(), baddot);
string inl = AstNode::prettyName(nodep->inlinedDots());
UINFO(8,"\t\tInlined "<<inl<<endl);
dotVxp = m_statep->findDotted(dotVxp, inl, baddot, okVxp);
if (!dotVxp) nodep->v3fatalSrc("Couldn't resolve inlined scope '"<<baddot<<"' in: "<<nodep->inlinedDots());
}
dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot); // Maybe NULL
dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot, okVxp); // Maybe NULL
AstNodeFTask* taskp = (m_statep->findSym(dotVxp, nodep->name(), baddot)
->castNodeFTask()); // maybe NULL
@@ -583,6 +676,7 @@ private:
UINFO(7," Resolved "<<nodep<<endl); // Also prints taskp
if (!nodep->taskp()) {
nodep->v3error("Can't find definition of '"<<baddot<<"' in dotted task/function: "<<nodep->dotted()+"."+nodep->prettyName());
okVxp->errorScopes(nodep);
}
}
nodep->iterateChildren(*this);
@@ -606,22 +700,15 @@ public:
//######################################################################
// Link class functions
void V3LinkDot::linkDot(AstNetlist* rootp) {
void V3LinkDot::linkDotGuts(AstNetlist* rootp, bool prearray, bool scoped) {
UINFO(2,__FUNCTION__<<": "<<endl);
if (LinkDotState::debug()>=5) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
LinkDotState state (false);
LinkDotState state (prearray,scoped);
LinkDotFindVisitor visitor(rootp,&state);
state.dump();
LinkDotResolveVisitor visitorb(rootp,&state);
}
void V3LinkDot::linkDotScope(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
if (LinkDotState::debug()>=5) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
LinkDotState state (true);
LinkDotFindVisitor visitor(rootp,&state);
// Process AstScope's. This needs to be separate pass after whole hiearchy graph created.
LinkDotScopeVisitor visitors(rootp,&state);
if (scoped) {
// Process AstScope's. This needs to be separate pass after whole hierarchy graph created.
LinkDotScopeVisitor visitors(rootp,&state);
}
state.dump();
LinkDotResolveVisitor visitorb(rootp,&state);
}
+7 -3
View File
@@ -21,16 +21,20 @@
#ifndef _V3LINKDOT_H_
#define _V3LINKDOT_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3LinkDot {
private:
static void linkDotGuts(AstNetlist* nodep, bool preparam, bool scoped);
public:
static void linkDot(AstNetlist* nodep);
static void linkDotScope(AstNetlist* nodep);
static void linkDotPrearrayed(AstNetlist* nodep) { linkDotGuts(nodep,true,false); }
static void linkDotArrayed(AstNetlist* nodep) { linkDotGuts(nodep,false,false); }
static void linkDotScope(AstNetlist* nodep) { linkDotGuts(nodep,false,true); }
};
#endif // Guard
+3 -2
View File
@@ -24,7 +24,8 @@
// Create new MODULE TOP with connections to below signals
//*************************************************************************
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -140,7 +141,7 @@ void V3LinkLevel::wrapTop(AstNetlist* netlistp) {
AstVar* varp = oldvarp->cloneTree(false)->castVar();
newmodp->addStmtp(varp);
varp->sigPublic(true); // User needs to be able to get to it...
if (oldvarp->isInput() || oldvarp->isOutput()) {
if (oldvarp->isIO()) {
oldvarp->primaryIO(true);
varp->primaryIO(true);
}
+2 -1
View File
@@ -21,7 +21,8 @@
#ifndef _V3LINKLEVEL_H_
#define _V3LINKLEVEL_H_ 1
#include "config.h"
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"

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