mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6d7e7e329 | ||
|
|
f942aba855 | ||
|
|
2f34132275 | ||
|
|
663b2be065 | ||
|
|
a1e4d676c3 | ||
|
|
6f28d21207 | ||
|
|
9f115e056e | ||
|
|
8352ba4af4 | ||
|
|
9b06310cbe | ||
|
|
77fe33e57f | ||
|
|
df58eb9bc7 | ||
|
|
2d0084308d | ||
|
|
7efa40966a | ||
|
|
6d644dc764 | ||
|
|
b0de0b1176 | ||
|
|
c72d473e96 | ||
|
|
c8a91bd46f | ||
|
|
498f19a6a1 | ||
|
|
c7a2138ece | ||
|
|
4078902543 | ||
|
|
9e38ed9a39 | ||
|
|
183cabc77d | ||
|
|
b582e481c6 | ||
|
|
ad39931e87 | ||
|
|
1ae22e1365 | ||
|
|
b748ddfe06 | ||
|
|
e52f5f1b63 | ||
|
|
bda4b326ab | ||
|
|
70ddf32719 | ||
|
|
3edba7b662 | ||
|
|
f74ef650ac | ||
|
|
f093c3d78b | ||
|
|
d933f33bdb | ||
|
|
813d62005d | ||
|
|
411de9bddf | ||
|
|
bd28945374 | ||
|
|
1e4c3751e1 | ||
|
|
5b6f47cd0f | ||
|
|
bec8c5bf4c | ||
|
|
15495bb200 | ||
|
|
999f278971 | ||
|
|
7ca1d35a4e | ||
|
|
2117fe414e | ||
|
|
7d8c51181d | ||
|
|
c30211cb27 | ||
|
|
901da118e5 | ||
|
|
f11757e43a | ||
|
|
3f143317a6 | ||
|
|
45d7312dfc | ||
|
|
26774eb045 | ||
|
|
6789d247e2 | ||
|
|
462bc3d707 | ||
|
|
e1755ea6a8 | ||
|
|
b4a7e4697e | ||
|
|
cd61b1d045 | ||
|
|
24dc36ba4c | ||
|
|
e8e4f1777d | ||
|
|
ae38a26af3 | ||
|
|
8ee94dd7aa | ||
|
|
e741a29d36 | ||
|
|
be1d275151 | ||
|
|
31c9e26e2e | ||
|
|
20ed1ada03 | ||
|
|
891214fa72 | ||
|
|
e819e285e2 | ||
|
|
171c175e54 | ||
|
|
675cbce8cb | ||
|
|
4f1398f773 | ||
|
|
ae89e399a3 | ||
|
|
2c9716c64c | ||
|
|
bc58245abf | ||
|
|
8c4aa8517e | ||
|
|
c0b7a54bb9 | ||
|
|
6b32bb635d | ||
|
|
691de22ae3 | ||
|
|
e64b2d3372 | ||
|
|
e190af9d87 | ||
|
|
8d14463b18 | ||
|
|
04977ef721 | ||
|
|
d84e6875c5 | ||
|
|
80678ae7bc | ||
|
|
482bdab0e0 | ||
|
|
b2623b9841 | ||
|
|
9ae40d64f0 | ||
|
|
cef097b7b7 | ||
|
|
b840334ad2 | ||
|
|
acff683e8e | ||
|
|
c5332de86d | ||
|
|
90ecf14a0a | ||
|
|
4945282369 | ||
|
|
ca532d23f0 | ||
|
|
a509b6a21c | ||
|
|
46229473cb | ||
|
|
65be2448dc | ||
|
|
be74806044 | ||
|
|
b488666c1e | ||
|
|
d1acaea611 | ||
|
|
db6e5ce7cf | ||
|
|
d56179df17 | ||
|
|
850100c9c2 | ||
|
|
0725999f0a | ||
|
|
cb2d8259f2 | ||
|
|
61a1f3d817 | ||
|
|
63f111b7f3 | ||
|
|
e061eb3003 | ||
|
|
29daa58222 | ||
|
|
340cc02171 | ||
|
|
b738d1960a | ||
|
|
38f5b780d7 | ||
|
|
fa9dac29e8 | ||
|
|
afc432042f | ||
|
|
21cb29baf0 | ||
|
|
e8b5001cfe | ||
|
|
849c1e46a2 | ||
|
|
ebad6cde36 | ||
|
|
f920b3945e | ||
|
|
178028a70a | ||
|
|
5e54d3e41a | ||
|
|
f0af8726e3 | ||
|
|
57f2fe77ea | ||
|
|
d56ca25089 | ||
|
|
d39ce17dea | ||
|
|
373a68ec8b | ||
|
|
5613758ee3 | ||
|
|
2102f86909 | ||
|
|
d5ea785de7 | ||
|
|
9edd28d2ed | ||
|
|
7698af5178 | ||
|
|
52ae451f5c | ||
|
|
9254443cd4 | ||
|
|
4e4bc7b90f | ||
|
|
c7e0f2e196 | ||
|
|
acabaab6ac | ||
|
|
b0a249f338 | ||
|
|
0cb5d5cc5a | ||
|
|
9208c87f91 | ||
|
|
0081ce4a75 | ||
|
|
7850f49963 | ||
|
|
c72ee41142 | ||
|
|
bf5dee955d | ||
|
|
3df23a148a | ||
|
|
0a1b55c296 | ||
|
|
14b8efe4bb | ||
|
|
64162efebd | ||
|
|
faf5e1de51 | ||
|
|
0d7b1a7dc7 | ||
|
|
fa63bc6b78 | ||
|
|
379bfd062f | ||
|
|
49108c23f0 | ||
|
|
4475060268 | ||
|
|
4f269e336d | ||
|
|
4464b13163 | ||
|
|
215d5f68b0 | ||
|
|
281f4e04ee | ||
|
|
17a3f9691d | ||
|
|
4fde6ee7af | ||
|
|
040b1b06d5 | ||
|
|
b16ea8b719 | ||
|
|
cc22847bc3 | ||
|
|
3702e17b2e | ||
|
|
7abc220fb3 | ||
|
|
4fc9a906f6 | ||
|
|
5de83c9805 | ||
|
|
f71d904a9b | ||
|
|
318ded4198 | ||
|
|
f1874b211f | ||
|
|
c60ffd7fd9 | ||
|
|
dc57282168 | ||
|
|
3c336e179f | ||
|
|
6bda57da5d | ||
|
|
9a16001e51 | ||
|
|
34870e899f | ||
|
|
d0653f72e2 | ||
|
|
64748b7b1d | ||
|
|
7163c8d048 | ||
|
|
d0ec991bb2 | ||
|
|
d458af4454 | ||
|
|
9e9e7c33ae | ||
|
|
ce7de5ed30 | ||
|
|
776d8edf52 |
@@ -1,7 +1,193 @@
|
|||||||
Revision history for Verilator
|
Revision history for Verilator
|
||||||
|
|
||||||
The contributors that suggested a given feature are shown in []. [by ...]
|
The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
indicates the contributor was also the author of the fix; Thanks!
|
|
||||||
|
|
||||||
|
* Verilator 3.900 2017-01-15
|
||||||
|
|
||||||
|
** Internal code changes for improved compatibility and performance.
|
||||||
|
|
||||||
|
*** Support old-style $display($time), bug467. [John Demme]
|
||||||
|
|
||||||
|
**** With --bbox-unsup, suppress desassign and mixed edges, bug1120. [Galen Seitz]
|
||||||
|
|
||||||
|
**** Fix parsing sensitivity with &&, bug934. [Luke Yang]
|
||||||
|
|
||||||
|
**** Fix internal error on double-for loop unrolling, bug1044. [Jan Egil Ruud]
|
||||||
|
|
||||||
|
**** Fix internal error on unique casez with --assert, bug1117. [Enzo Chi]
|
||||||
|
|
||||||
|
**** Fix bad code when tracing array of structs, bug1122. [Andrew Bardsley]
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.890 2016-11-25
|
||||||
|
|
||||||
|
*** Honor --output-split on coverage constructors, bug1098. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix various issues when making outside of the kit.
|
||||||
|
|
||||||
|
**** Fix flex 2.6.2 bug, bug1103. [Sergey Kvachonok]
|
||||||
|
|
||||||
|
**** Fix error on bad interface name, bug1097. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix error on referencing variable in parent, bug1099. [Ian Thompson]
|
||||||
|
|
||||||
|
**** Fix type parameters with low optimization, bug1101. [Stefan Wallentowitz]
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.888 2016-10-14
|
||||||
|
|
||||||
|
** Support foreach, bug1078. [Xuan Guo]
|
||||||
|
|
||||||
|
*** Add --no-decoration to remove output comments, msg2015. [Frederic Requin]
|
||||||
|
|
||||||
|
*** If VM_PARALLEL_BUILDS=1, use OPT_FAST and OPT_SLOW. [Frederic Requin]
|
||||||
|
Set VM_DEFAULT_RULES=0 for old behavior.
|
||||||
|
|
||||||
|
**** Add error on DPI functions > 32 bits, msg1995. [Elliot Mednick]
|
||||||
|
|
||||||
|
**** Fix SystemC compiles with VPI, bug1081. [Arthur Kahlich]
|
||||||
|
|
||||||
|
**** Fix error on wide numbers that represent shifts, msg1991, bug1088. [Mandy Xu]
|
||||||
|
|
||||||
|
**** Improve Verilation performance on internal strings, msg1975. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Improve Verilation performance on trace duplicates, bug1090. [Johan Bjork]
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.886 2016-07-30
|
||||||
|
|
||||||
|
**** Fix enum values of 11-16 bits wide using .next/.prev, bug1062. [Brian Flachs]
|
||||||
|
|
||||||
|
**** Fix false warnings on non-power-2 enums using .next/.prev.
|
||||||
|
|
||||||
|
**** Fix comparison of unpacked arrays, bug1071. [Andrew Bardsley]
|
||||||
|
|
||||||
|
**** Fix compiler warning in GCC 6. [David Horton]
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.884 2016-05-18
|
||||||
|
|
||||||
|
** Support parameter type, bug376. [Alan Hunter, et al]
|
||||||
|
|
||||||
|
** Support command-line -G/+pvalue param overrides, bug1045. [Stefan Wallentowitz]
|
||||||
|
|
||||||
|
*** The default l2 scope name is now the same as the top-level module, bug1050.
|
||||||
|
Use "--l2-name v" for the historical behavior.
|
||||||
|
|
||||||
|
*** Add --l2-name option for controlling "v" naming.
|
||||||
|
|
||||||
|
**** Fix --output-split of constructors, bug1035. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix removal of empty packages, modules and cells, bug1034. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix core dump on Arch Linux/GCC 6.1.1, bug1058. [Jannis Harder]
|
||||||
|
|
||||||
|
**** Fix $value$plusargs to string, msg1890. [Frederic Requin]
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.882 2016-03-01
|
||||||
|
|
||||||
|
**** Internal Verilation-time performance enhancements, bug1021. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Support inlining interfaces, bug1018. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Support SV strings to readmemh, bug1040. [Stefan Wallentowitz]
|
||||||
|
|
||||||
|
**** Fix unrolling complicated for-loop bounds, bug677. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix stats file containing multiple unroll entries, bug1020. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix using short parameter names on negative params, bug1022. [Duraid Madina]
|
||||||
|
|
||||||
|
**** Fix read-after-free error, bug1031. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix elaboration-time display warnings, bug1032. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix crash on very deep function trees, bug1028. [Jonathan Kimmitt]
|
||||||
|
|
||||||
|
**** Fix slicing mix of big and little-endian, bug1033. [Geoff Barrett]
|
||||||
|
|
||||||
|
**** Fix pattern assignment width propagation, bug1037. [Johan Bjork]
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.880 2015-12-19
|
||||||
|
|
||||||
|
*** Support display %u, %v, %p, %z, bug989. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix real parameters causing bad module names, bug992. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix size-changing cast on packed struct, bug993. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix function calls on arrayed interface, bug994. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix arrayed interfaces, bug879, bug1001. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix constant function assigned to packed structs, bug997. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix interface inside generate, bug998. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix $signed casts under generates, bug999. [Clifford Wolf]
|
||||||
|
|
||||||
|
**** Fix genvar constant propagation, bug1003. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix parameter constant propagation from package, bug1004. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix array slicing of non-const indexes, bug1006. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix dotted generated array error, bug1005. [Jeff Bush, Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix error instead of warning on large concat, msg1768. [Paul Rolfe]
|
||||||
|
|
||||||
|
**** Fix $bitstoreal constant propagation, bug1012. [Jonathan Kimmitt]
|
||||||
|
|
||||||
|
**** Fix model restore crash, bug1013. [Jason McMullan]
|
||||||
|
|
||||||
|
**** Fix arrayed instances to unpacked of same size, bug1015. [Varun Koyyalagunta]
|
||||||
|
|
||||||
|
**** Fix slices of unpacked arrays with non-zero LSBs.
|
||||||
|
|
||||||
|
**** Fix ternary operation with unpacked array, bug1017. [Varun Koyyalagunta].
|
||||||
|
|
||||||
|
|
||||||
|
* Verilator 3.878 2015-11-01
|
||||||
|
|
||||||
|
** Add --vpi flag, and fix VPI linkage, bug969. [Arthur Kahlich]
|
||||||
|
|
||||||
|
** Support genvar indexes into arrayed cells, bug517. [Todd Strader]
|
||||||
|
|
||||||
|
** Support $sformatf, bug977. [Johan Bjork]
|
||||||
|
|
||||||
|
*** Support elaboration assertions, bug973. [Johan Bjork]
|
||||||
|
|
||||||
|
*** Support $display with non-format arguments, bug467. [Jamey Hicks]
|
||||||
|
|
||||||
|
**** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader]
|
||||||
|
|
||||||
|
**** Ignore %l in $display, bug983. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix very long module names, bug937. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix internal error on dotted refs into generates, bug958. [Jie Xu]
|
||||||
|
|
||||||
|
**** Fix structure parameter constant propagation, bug968. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix enum constant propagation, bug970. [Todd Strader]
|
||||||
|
|
||||||
|
**** Fix mis-optimizing public DPI functions, bug963. [Wei Song]
|
||||||
|
|
||||||
|
**** Fix package:scope.scope variable references.
|
||||||
|
|
||||||
|
**** Fix $fwrite to constant stderr/stdout, bug961. [Wei Song]
|
||||||
|
|
||||||
|
**** Fix struct.enum.name method calls, bug855. [Jonathon Donaldson]
|
||||||
|
|
||||||
|
**** Fix dot indexing into arrayed inferfaces, bug978. [Johan Bjork]
|
||||||
|
|
||||||
|
**** Fix crash in commandArgsPlusMatch, bug987. [Jamie Iles]
|
||||||
|
|
||||||
|
**** Fix error message on missing interface, bug985. [Todd Strader]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 3.876 2015-08-12
|
* Verilator 3.876 2015-08-12
|
||||||
|
|
||||||
@@ -2601,12 +2787,12 @@ of input ports exists for tracing.
|
|||||||
|
|
||||||
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
||||||
|
|
||||||
Copyright 2001-2015 by Wilson Snyder. This program is free software; you
|
Copyright 2001-2017 by Wilson Snyder. This program is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License Version 3 or the Perl Artistic License
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|
||||||
Local variables:
|
Local variables:
|
||||||
mode: outline
|
mode: outline
|
||||||
paragraph-separate: "[ \f\n]*$"
|
paragraph-separate: "[ \f\n]*$"
|
||||||
end:
|
end:
|
||||||
|
|||||||
+7
-6
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -42,9 +42,6 @@
|
|||||||
# reconstructed with this Makefile. This typically includes
|
# reconstructed with this Makefile. This typically includes
|
||||||
# everything deleted by distclean, plus more: C source files
|
# everything deleted by distclean, plus more: C source files
|
||||||
# produced by Bison, tags tables, info files, and so on.
|
# produced by Bison, tags tables, info files, and so on.
|
||||||
#
|
|
||||||
# make extraclean
|
|
||||||
# Still more severe - delete backup and autosave files, too.
|
|
||||||
|
|
||||||
#### Start of system configuration section. ####
|
#### Start of system configuration section. ####
|
||||||
|
|
||||||
@@ -71,7 +68,7 @@ exec_prefix = @exec_prefix@
|
|||||||
# Directory in which to install scripts.
|
# Directory in which to install scripts.
|
||||||
bindir = @bindir@
|
bindir = @bindir@
|
||||||
|
|
||||||
# Directory in which to install scripts.
|
# Directory in which to install manpages.
|
||||||
mandir = @mandir@
|
mandir = @mandir@
|
||||||
|
|
||||||
# Directory in which to install library files.
|
# Directory in which to install library files.
|
||||||
@@ -100,6 +97,8 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
|
|||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
|
|
||||||
SUBDIRS = src test_verilated test_c test_sc test_regress
|
SUBDIRS = src test_verilated test_c test_sc test_regress
|
||||||
@@ -271,6 +270,7 @@ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg verilator_coverage
|
|||||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_profcfunc.1
|
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_profcfunc.1
|
||||||
|
|
||||||
VL_INST_INC_BLDDIR_FILES = \
|
VL_INST_INC_BLDDIR_FILES = \
|
||||||
|
include/verilated_config.h \
|
||||||
include/verilated.mk \
|
include/verilated.mk \
|
||||||
|
|
||||||
# Files under srcdir, instead of build time
|
# Files under srcdir, instead of build time
|
||||||
@@ -298,7 +298,8 @@ installbin:
|
|||||||
# So important we use $< so VPATH is searched
|
# So important we use $< so VPATH is searched
|
||||||
installman: $(VL_INST_MAN_FILES)
|
installman: $(VL_INST_MAN_FILES)
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||||
for p in $^ ; do \
|
cd $(srcdir) \
|
||||||
|
; for p in $(VL_INST_MAN_FILES) ; do \
|
||||||
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -11,7 +11,7 @@ This is the Verilator package README file.
|
|||||||
|
|
||||||
http://www.veripool.org/verilator
|
http://www.veripool.org/verilator
|
||||||
|
|
||||||
This package is Copyright 2003-2015 by Wilson Snyder. (Report bugs to
|
This package is Copyright 2003-2017 by Wilson Snyder. (Report bugs to
|
||||||
L<http://www.veripool.org/>.)
|
L<http://www.veripool.org/>.)
|
||||||
|
|
||||||
Verilator is free software; you can redistribute it and/or modify it under
|
Verilator is free software; you can redistribute it and/or modify it under
|
||||||
@@ -117,9 +117,10 @@ and add it to path using Modules/modulecmd:
|
|||||||
After installing you'll want a module file like the following:
|
After installing you'll want a module file like the following:
|
||||||
|
|
||||||
set install_root /CAD_DISK/verilator/{version-number-used-above}
|
set install_root /CAD_DISK/verilator/{version-number-used-above}
|
||||||
setenv VERILATOR_ROOT $install_root
|
unsetenv VERILATOR_ROOT
|
||||||
prepend-path PATH $install_root/bin
|
prepend-path PATH $install_root/bin
|
||||||
prepend-path MANPATH $install_root/man
|
prepend-path MANPATH $install_root/man
|
||||||
|
prepend-path PKG_CONFIG_PATH $install_root/share/pkgconfig
|
||||||
|
|
||||||
=item 3.
|
=item 3.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// DESCRIPTION: Verilator: List of To Do issues.
|
// DESCRIPTION: Verilator: List of To Do issues.
|
||||||
//
|
//
|
||||||
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+305
-190
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
|||||||
if 0;
|
if 0;
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -19,8 +19,8 @@ require 5.006_001;
|
|||||||
use warnings;
|
use warnings;
|
||||||
BEGIN {
|
BEGIN {
|
||||||
if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) {
|
if ($ENV{DIRPROJECT} && $ENV{DIRPROJECT_PERL_BOOT}) {
|
||||||
# Magic to allow author testing of perl packages in local directory
|
# Magic to allow author testing of perl packages in local directory
|
||||||
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
|
require $ENV{DIRPROJECT}."/".$ENV{DIRPROJECT_PERL_BOOT};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,22 +54,33 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
|
|||||||
# We sneak a look at the flags so we can do some pre-environment checks
|
# We sneak a look at the flags so we can do some pre-environment checks
|
||||||
# All flags will hit verilator...
|
# All flags will hit verilator...
|
||||||
foreach my $sw (@ARGV) {
|
foreach my $sw (@ARGV) {
|
||||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
# Some special treatment for parameters to allow verilog literals for numbers
|
||||||
|
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
|
||||||
|
# If there is a single quote in the parameter put it double quotes ,
|
||||||
|
# else just put it in double quotes
|
||||||
|
if ($sw =~ m![\']!) {
|
||||||
|
$sw = "\"$sw\"";
|
||||||
|
} else {
|
||||||
|
$sw = "'$sw'";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||||
|
}
|
||||||
push @Opt_Verilator_Sw, $sw;
|
push @Opt_Verilator_Sw, $sw;
|
||||||
}
|
}
|
||||||
|
|
||||||
Getopt::Long::config ("no_auto_abbrev","pass_through");
|
Getopt::Long::config ("no_auto_abbrev","pass_through");
|
||||||
if (! GetOptions (
|
if (! GetOptions (
|
||||||
# Major operating modes
|
# Major operating modes
|
||||||
"help" => \&usage,
|
"help" => \&usage,
|
||||||
"debug:s" => \&debug,
|
"debug:s" => \&debug,
|
||||||
# "version!" => \&version, # Also passthru'ed
|
# "version!" => \&version, # Also passthru'ed
|
||||||
# Switches
|
# Switches
|
||||||
"gdb!" => \$opt_gdb,
|
"gdb!" => \$opt_gdb,
|
||||||
"gdbbt!" => \$opt_gdbbt,
|
"gdbbt!" => \$opt_gdbbt,
|
||||||
# Additional parameters
|
# Additional parameters
|
||||||
"<>" => sub {}, # Ignored
|
"<>" => sub {}, # Ignored
|
||||||
)) {
|
)) {
|
||||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,22 +92,22 @@ if ($opt_gdbbt && !gdb_works()) {
|
|||||||
if ($opt_gdb) {
|
if ($opt_gdb) {
|
||||||
# Generic GDB interactive
|
# Generic GDB interactive
|
||||||
run (("gdb"||$ENV{VERILATOR_GDB})
|
run (("gdb"||$ENV{VERILATOR_GDB})
|
||||||
." ".verilator_bin()
|
." ".verilator_bin()
|
||||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||||
." -ex 'set width 0'"
|
." -ex 'set width 0'"
|
||||||
." -ex 'bt'");
|
." -ex 'bt'");
|
||||||
} elsif ($opt_gdbbt && $Debug) {
|
} elsif ($opt_gdbbt && $Debug) {
|
||||||
# Run under GDB to get gdbbt
|
# Run under GDB to get gdbbt
|
||||||
run ("gdb"
|
run ("gdb"
|
||||||
." ".verilator_bin()
|
." ".verilator_bin()
|
||||||
." --batch --quiet --return-child-result"
|
." --batch --quiet --return-child-result"
|
||||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||||
." -ex 'set width 0'"
|
." -ex 'set width 0'"
|
||||||
." -ex 'bt'");
|
." -ex 'bt'");
|
||||||
} else {
|
} else {
|
||||||
# Normal, non gdb
|
# Normal, non gdb
|
||||||
run (verilator_bin()
|
run (verilator_bin()
|
||||||
." ".join(' ',@Opt_Verilator_Sw));
|
." ".join(' ',@Opt_Verilator_Sw));
|
||||||
}
|
}
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@@ -119,23 +130,23 @@ sub verilator_bin {
|
|||||||
my $bin = "";
|
my $bin = "";
|
||||||
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
|
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
|
||||||
my $basename = ($ENV{VERILATOR_BIN}
|
my $basename = ($ENV{VERILATOR_BIN}
|
||||||
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
|
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
|
||||||
if (defined($ENV{VERILATOR_ROOT})) {
|
if (defined($ENV{VERILATOR_ROOT})) {
|
||||||
my $dir = $ENV{VERILATOR_ROOT};
|
my $dir = $ENV{VERILATOR_ROOT};
|
||||||
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
|
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
|
||||||
$bin = "$dir/bin/$basename";
|
$bin = "$dir/bin/$basename";
|
||||||
} else {
|
} else {
|
||||||
$bin = "$dir/$basename"; # From pointing to kit directory
|
$bin = "$dir/$basename"; # From pointing to kit directory
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (-x "$RealBin/$basename") {
|
if (-x "$RealBin/$basename") {
|
||||||
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
|
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
|
||||||
} else {
|
} else {
|
||||||
$bin = $basename; # Find in PATH
|
$bin = $basename; # Find in PATH
|
||||||
}
|
}
|
||||||
# Note we don't look under bin/$basename which would be right if running
|
# Note we don't look under bin/$basename which would be right if running
|
||||||
# in the kit dir. Running that would likely break, since
|
# in the kit dir. Running that would likely break, since
|
||||||
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
|
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
|
||||||
}
|
}
|
||||||
return $bin;
|
return $bin;
|
||||||
}
|
}
|
||||||
@@ -147,10 +158,10 @@ sub verilator_bin {
|
|||||||
sub gdb_works {
|
sub gdb_works {
|
||||||
$! = undef; # Cleanup -x
|
$! = undef; # Cleanup -x
|
||||||
system("gdb /bin/echo"
|
system("gdb /bin/echo"
|
||||||
." --batch-silent --quiet --return-child-result"
|
." --batch-silent --quiet --return-child-result"
|
||||||
." -ex 'run -n'" # `echo -n`
|
." -ex 'run -n'" # `echo -n`
|
||||||
." -ex 'set width 0'"
|
." -ex 'set width 0'"
|
||||||
." -ex 'bt'");
|
." -ex 'bt'");
|
||||||
my $status = $?;
|
my $status = $?;
|
||||||
return $status==0;
|
return $status==0;
|
||||||
}
|
}
|
||||||
@@ -163,23 +174,23 @@ sub run {
|
|||||||
system($command);
|
system($command);
|
||||||
my $status = $?;
|
my $status = $?;
|
||||||
if ($status) {
|
if ($status) {
|
||||||
if ($! =~ /no such file or directory/i) {
|
if ($! =~ /no such file or directory/i) {
|
||||||
warn "%Error: verilator: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
|
warn "%Error: verilator: Misinstalled, or VERILATOR_ROOT might need to be in environment\n";
|
||||||
}
|
}
|
||||||
if ($Debug) { # For easy rerunning
|
if ($Debug) { # For easy rerunning
|
||||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||||
warn "%Error: $command\n";
|
warn "%Error: $command\n";
|
||||||
}
|
}
|
||||||
if ($status & 127) {
|
if ($status & 127) {
|
||||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||||
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||||
} elsif (($status & 127) == 6) { # SIGABRT
|
} elsif (($status & 127) == 6) { # SIGABRT
|
||||||
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||||
} else {
|
} else {
|
||||||
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
|
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
die "%Error: Command Failed $command\n";
|
die "%Error: Command Failed $command\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,9 +209,9 @@ Verilator - Convert Verilog code to C++/SystemC
|
|||||||
|
|
||||||
verilator --help
|
verilator --help
|
||||||
verilator --version
|
verilator --version
|
||||||
verilator --cc [options] [top_level.v]... [opt_c_files.cpp/c/cc/a/o/so]
|
verilator --cc [options] [source_files.v]... [opt_c_files.cpp/c/cc/a/o/so]
|
||||||
verilator --sc [options] [top_level.v]... [opt_c_files.cpp/c/cc/a/o/so]
|
verilator --sc [options] [source_files.v]... [opt_c_files.cpp/c/cc/a/o/so]
|
||||||
verilator --lint-only [top_level.v]...
|
verilator --lint-only [source_files.v]...
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
@@ -228,7 +239,7 @@ To get started, jump down to "EXAMPLE C++ EXECUTION".
|
|||||||
This is a short summary of the arguments to Verilator. See the detailed
|
This is a short summary of the arguments to Verilator. See the detailed
|
||||||
descriptions in the next sections for more information.
|
descriptions in the next sections for more information.
|
||||||
|
|
||||||
{file.v} Verilog top level filenames
|
{file.v} Verilog package, module and top module filenames
|
||||||
{file.c/cc/cpp} Optional C++ files to compile in
|
{file.c/cc/cpp} Optional C++ files to compile in
|
||||||
{file.a/o/so} Optional C++ files to link in
|
{file.a/o/so} Optional C++ files to link in
|
||||||
|
|
||||||
@@ -269,6 +280,7 @@ descriptions in the next sections for more information.
|
|||||||
--exe Link to create executable
|
--exe Link to create executable
|
||||||
-F <file> Parse options from a file, relatively
|
-F <file> Parse options from a file, relatively
|
||||||
-f <file> Parse options from a file
|
-f <file> Parse options from a file
|
||||||
|
-G<name>=<value> Overwrite toplevel parameter
|
||||||
--gdb Run Verilator under GDB interactively
|
--gdb Run Verilator under GDB interactively
|
||||||
--gdbbt Run Verilator under GDB for backtrace
|
--gdbbt Run Verilator under GDB for backtrace
|
||||||
--help Display this help
|
--help Display this help
|
||||||
@@ -279,6 +291,7 @@ descriptions in the next sections for more information.
|
|||||||
--inline-mult <value> Tune module inlining
|
--inline-mult <value> Tune module inlining
|
||||||
-LDFLAGS <flags> Linker pre-object flags for makefile
|
-LDFLAGS <flags> Linker pre-object flags for makefile
|
||||||
-LDLIBS <flags> Linker library flags for makefile
|
-LDLIBS <flags> Linker library flags for makefile
|
||||||
|
--l2-name <value> Verilog scope name of the top module
|
||||||
--language <lang> Default language standard to parse
|
--language <lang> Default language standard to parse
|
||||||
+libext+<ext>+[ext]... Extensions for finding modules
|
+libext+<ext>+[ext]... Extensions for finding modules
|
||||||
--lint-only Lint, but do not make output
|
--lint-only Lint, but do not make output
|
||||||
@@ -287,6 +300,7 @@ descriptions in the next sections for more information.
|
|||||||
--Mdir <directory> Name of output object directory
|
--Mdir <directory> Name of output object directory
|
||||||
--mod-prefix <topname> Name to prepend to lower classes
|
--mod-prefix <topname> Name to prepend to lower classes
|
||||||
--no-clk <signal-name> Prevent marking specified signal as clock
|
--no-clk <signal-name> Prevent marking specified signal as clock
|
||||||
|
--no-decoration Disable comments and symbol decorations
|
||||||
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
||||||
--no-skip-identical Disable skipping identical output
|
--no-skip-identical Disable skipping identical output
|
||||||
+notimingchecks Ignored
|
+notimingchecks Ignored
|
||||||
@@ -308,8 +322,9 @@ descriptions in the next sections for more information.
|
|||||||
--profile-cfuncs Name functions for profiling
|
--profile-cfuncs Name functions for profiling
|
||||||
--private Debugging; see docs
|
--private Debugging; see docs
|
||||||
--public Debugging; see docs
|
--public Debugging; see docs
|
||||||
|
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||||
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
||||||
--savable Enable model save-restore
|
--savable Enable model save-restore
|
||||||
--sc Create SystemC output
|
--sc Create SystemC output
|
||||||
--stats Create statistics file
|
--stats Create statistics file
|
||||||
--stats-vars Provide statistics on variables
|
--stats-vars Provide statistics on variables
|
||||||
@@ -331,6 +346,7 @@ descriptions in the next sections for more information.
|
|||||||
-v <filename> Verilog library
|
-v <filename> Verilog library
|
||||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||||
|
--vpi Enable VPI compiles
|
||||||
-Werror-<message> Convert warning to error
|
-Werror-<message> Convert warning to error
|
||||||
-Wfuture-<message> Disable unknown message warnings
|
-Wfuture-<message> Disable unknown message warnings
|
||||||
-Wno-<message> Disable warning
|
-Wno-<message> Disable warning
|
||||||
@@ -428,9 +444,10 @@ calls.
|
|||||||
|
|
||||||
=item --bbox-unsup
|
=item --bbox-unsup
|
||||||
|
|
||||||
Black box some unsupported language features, currently UDP tables and the
|
Black box some unsupported language features, currently UDP tables, the
|
||||||
cmos and tran gate primitives. This may enable linting the rest of the
|
cmos and tran gate primitives, deassign statements, and mixed edge errors.
|
||||||
design even when unsupported constructs are present.
|
This may enable linting the rest of the design even when unsupported
|
||||||
|
constructs are present.
|
||||||
|
|
||||||
=item --bin I<filename>
|
=item --bin I<filename>
|
||||||
|
|
||||||
@@ -471,14 +488,14 @@ Verilator will mark the signal as clocker and propagate the clocker attribute
|
|||||||
automatically to other signals derived from that. In this way, Verilator will
|
automatically to other signals derived from that. In this way, Verilator will
|
||||||
try to avoid taking the clocker signal into checking list.
|
try to avoid taking the clocker signal into checking list.
|
||||||
|
|
||||||
Note signal-name is specified by the RTL hiearchy path. For example, v.foo.bar.
|
Note signal-name is specified by the RTL hierarchy path. For example, v.foo.bar.
|
||||||
If the signal is the input to top-module, the directly the signal name. If you
|
If the signal is the input to top-module, the directly the signal name. If you
|
||||||
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
|
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
|
||||||
RTL file to mark the signal directly.
|
RTL file to mark the signal directly.
|
||||||
|
|
||||||
=item --compiler I<compiler-name>
|
=item --compiler I<compiler-name>
|
||||||
|
|
||||||
Enables tunings and work-arounds for the specified C++ compiler.
|
Enables tunings and workarounds for the specified C++ compiler.
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
@@ -591,8 +608,8 @@ alias for GCC compatibility.
|
|||||||
=item --debug
|
=item --debug
|
||||||
|
|
||||||
Select the debug built image of Verilator (if available), and enable more
|
Select the debug built image of Verilator (if available), and enable more
|
||||||
internal assertions (equivelent to C<--debug-check>), debugging messages
|
internal assertions (equivalent to C<--debug-check>), debugging messages
|
||||||
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
|
(equivalent to C<--debugi 4>), and intermediate form dump files (equivalent
|
||||||
to C<--dump-treei 3>).
|
to C<--dump-treei 3>).
|
||||||
|
|
||||||
=item --debug-check
|
=item --debug-check
|
||||||
@@ -687,6 +704,35 @@ The file may contain // comments which are ignored to the end of the line.
|
|||||||
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
||||||
variable.
|
variable.
|
||||||
|
|
||||||
|
=item -GI<name>=I<value>
|
||||||
|
|
||||||
|
Overwrites the given parameter of the toplevel module. The value is limited
|
||||||
|
to basic data literals:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item Verilog integer literals
|
||||||
|
|
||||||
|
The standard verilog integer literals are supported, so values like 32'h8,
|
||||||
|
2'b00, 4 etc. are allowed. Care must be taken that the single quote (I') is
|
||||||
|
properly escaped in an interactive shell, e.g., as -GWIDTH=8\'hx.
|
||||||
|
|
||||||
|
=item C integer literals
|
||||||
|
|
||||||
|
It is also possible to use C integer notation, including hexadecimal (0x..),
|
||||||
|
octal (0..) or binary (0b..) notation.
|
||||||
|
|
||||||
|
=item Double literals
|
||||||
|
|
||||||
|
Double literals must contain a dot (.) and/or an exponent (e).
|
||||||
|
|
||||||
|
=item Strings
|
||||||
|
|
||||||
|
String must in double quotes ("). On the command line it is required to escape
|
||||||
|
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
=item --gdb
|
=item --gdb
|
||||||
|
|
||||||
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
|
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
|
||||||
@@ -742,9 +788,19 @@ called LDLIBS as that's the Makefile variable it controls. (In Make,
|
|||||||
LDFLAGS is before the first object, LDLIBS after. -L libraries need to be
|
LDFLAGS is before the first object, LDLIBS after. -L libraries need to be
|
||||||
in the Make variable LDLIBS, not LDFLAGS.)
|
in the Make variable LDLIBS, not LDFLAGS.)
|
||||||
|
|
||||||
|
=item --l2-name I<value>
|
||||||
|
|
||||||
|
Instead of using the module name when showing Verilog scope, use the name
|
||||||
|
provided. This allows simplifying some Verilator-embedded modeling
|
||||||
|
methodologies. Default is an l2-name matching the top module. The default
|
||||||
|
before 3.884 was "--l2-name v"
|
||||||
|
|
||||||
|
For example, the program "module t; initial $display("%m"); endmodule" will
|
||||||
|
show by default "t". With "--l2-name v" it will print "v".
|
||||||
|
|
||||||
=item --language I<value>
|
=item --language I<value>
|
||||||
|
|
||||||
A synonym for C<--default-langauge>, for compatibility with other tools and
|
A synonym for C<--default-language>, for compatibility with other tools and
|
||||||
earlier versions of Verilator.
|
earlier versions of Verilator.
|
||||||
|
|
||||||
=item +libext+I<ext>+I<ext>...
|
=item +libext+I<ext>+I<ext>...
|
||||||
@@ -789,6 +845,13 @@ the same as --prefix.
|
|||||||
|
|
||||||
Prevent the specified signal from being marked as clock. See C<--clk>.
|
Prevent the specified signal from being marked as clock. See C<--clk>.
|
||||||
|
|
||||||
|
=item --no-decoration
|
||||||
|
|
||||||
|
When creating output Verilated code, minimize comments, whitespace, symbol
|
||||||
|
names and other decorative items, at the cost of greatly reduced
|
||||||
|
readability. This may assist C++ compile times. This will not typically
|
||||||
|
change the ultimate model's performance, but may in some cases.
|
||||||
|
|
||||||
=item --no-pins64
|
=item --no-pins64
|
||||||
|
|
||||||
Backward compatible alias for "--pins-bv 33".
|
Backward compatible alias for "--pins-bv 33".
|
||||||
@@ -872,9 +935,10 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
|||||||
|
|
||||||
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
||||||
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
||||||
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
|
"--pins-bv 65", and the value must be less than or equal to 65. Versions
|
||||||
33". The more sc_bv is used, the worse for performance. Use the
|
before Verilator 3.671 defaulted to "--pins-bv 33". The more sc_bv is
|
||||||
"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv.
|
used, the worse for performance. Use the "/*verilator sc_bv*/" attribute
|
||||||
|
to select specific ports to be sc_bv.
|
||||||
|
|
||||||
=item --pins-sc-uint
|
=item --pins-sc-uint
|
||||||
|
|
||||||
@@ -945,6 +1009,11 @@ inlining. This will also turn off inlining as if all modules had a
|
|||||||
/*verilator public_module*/, unless the module specifically enabled it with
|
/*verilator public_module*/, unless the module specifically enabled it with
|
||||||
/*verilator inline_module*/.
|
/*verilator inline_module*/.
|
||||||
|
|
||||||
|
=item -pvalue+I<name>=I<value>
|
||||||
|
|
||||||
|
Overwrites the given parameter(s) of the toplevel module. See -G for a
|
||||||
|
detailed description.
|
||||||
|
|
||||||
=item --report-unoptflat
|
=item --report-unoptflat
|
||||||
|
|
||||||
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
|
Extra diagnostics for UNOPTFLAT warnings. This includes for each loop, the
|
||||||
@@ -1103,6 +1172,10 @@ Note -v is fairly standard across Verilog tools.
|
|||||||
|
|
||||||
Synonyms for C<+1364-1995ext+>I<ext> and C<+1364-2001ext+>I<ext> respectively
|
Synonyms for C<+1364-1995ext+>I<ext> and C<+1364-2001ext+>I<ext> respectively
|
||||||
|
|
||||||
|
=item --vpi
|
||||||
|
|
||||||
|
Enable use of VPI and linking against the verilated_vpi.cpp files.
|
||||||
|
|
||||||
=item -Wall
|
=item -Wall
|
||||||
|
|
||||||
Enable all warnings, including code style warnings that are normally
|
Enable all warnings, including code style warnings that are normally
|
||||||
@@ -1264,7 +1337,7 @@ We'll compile this example into C++.
|
|||||||
#include "Vour.h"
|
#include "Vour.h"
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
int main(int argc, char **argv, char **env) {
|
int main(int argc, char **argv, char **env) {
|
||||||
Verilated::commandArgs(argc, argv);
|
Verilated::commandArgs(argc, argv);
|
||||||
Vour* top = new Vour;
|
Vour* top = new Vour;
|
||||||
while (!Verilated::gotFinish()) { top->eval(); }
|
while (!Verilated::gotFinish()) { top->eval(); }
|
||||||
delete top;
|
delete top;
|
||||||
@@ -1272,9 +1345,15 @@ We'll compile this example into C++.
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
If you installed Verilator from sources, or a tarball, but not as part of
|
See the README in the source kit for various ways to install or point to
|
||||||
your operating system (as an RPM), first you need to point to the kit:
|
Verilator binaries. In brief, if you are running Verilator that came from
|
||||||
|
your operating system (as an RPM), or did a "make install" to place
|
||||||
|
Verilator into your default path, you do not need anything special in your
|
||||||
|
environment, and should not have VERILATOR_ROOT set. However, if you
|
||||||
|
installed Verilator from sources and want to run Verilator out of where you
|
||||||
|
compiled Verilator, you need to point to the kit:
|
||||||
|
|
||||||
|
# See above; don't do this if using an OS-distributed Verilator
|
||||||
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
|
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
|
||||||
export PATH=$VERILATOR_ROOT/bin:$PATH
|
export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||||
|
|
||||||
@@ -1289,8 +1368,7 @@ section below for descriptions of some of the files that were created.
|
|||||||
|
|
||||||
We then can compile it
|
We then can compile it
|
||||||
|
|
||||||
cd obj_dir
|
make -j -C obj_dir -f Vour.mk Vour
|
||||||
make -j -f Vour.mk Vour
|
|
||||||
|
|
||||||
(Verilator included a default compile rule and link rule, since we used
|
(Verilator included a default compile rule and link rule, since we used
|
||||||
--exe and passed a .cpp file on the Verilator command line. You can also
|
--exe and passed a .cpp file on the Verilator command line. You can also
|
||||||
@@ -1298,7 +1376,6 @@ write your own compile rules, as we'll show in the SYSTEMC section.)
|
|||||||
|
|
||||||
And now we run it
|
And now we run it
|
||||||
|
|
||||||
cd ..
|
|
||||||
obj_dir/Vour
|
obj_dir/Vour
|
||||||
|
|
||||||
And we get as output
|
And we get as output
|
||||||
@@ -1307,8 +1384,9 @@ And we get as output
|
|||||||
- our.v:2: Verilog $finish
|
- our.v:2: Verilog $finish
|
||||||
|
|
||||||
Really, you're better off writing 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
|
when your source changes it will automatically run all of these steps; to
|
||||||
the test_c directory in the distribution for an example.
|
aid this Verilator can create a makefile dependency file. See the test_c
|
||||||
|
directory in the distribution for an example.
|
||||||
|
|
||||||
|
|
||||||
=head1 EXAMPLE SYSTEMC EXECUTION
|
=head1 EXAMPLE SYSTEMC EXECUTION
|
||||||
@@ -1329,20 +1407,26 @@ This is an example similar to the above, but using SystemC.
|
|||||||
cat <<EOF >sc_main.cpp
|
cat <<EOF >sc_main.cpp
|
||||||
#include "Vour.h"
|
#include "Vour.h"
|
||||||
int sc_main(int argc, char **argv) {
|
int sc_main(int argc, char **argv) {
|
||||||
Verilated::commandArgs(argc, argv);
|
Verilated::commandArgs(argc, argv);
|
||||||
sc_clock clk ("clk",10, 0.5, 3, true);
|
sc_clock clk ("clk",10, 0.5, 3, true);
|
||||||
Vour* top;
|
Vour* top;
|
||||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||||
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
||||||
delete top;
|
delete top;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
If you installed Verilator from sources, or a tarball, but not as part of
|
See the README in the source kit for various ways to install or point to
|
||||||
your operating system (as an RPM), first you need to point to the kit:
|
Verilator binaries. In brief, if you are running Verilator that came from
|
||||||
|
your operating system (as an RPM), or did a "make install" to place
|
||||||
|
Verilator into your default path, you do not need anything special in your
|
||||||
|
environment, and should not have VERILATOR_ROOT set. However, if you
|
||||||
|
installed Verilator from sources and want to run Verilator out of where you
|
||||||
|
compiled Verilator, you need to point to the kit:
|
||||||
|
|
||||||
|
# See above; don't do this if using an OS-distributed Verilator
|
||||||
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
|
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
|
||||||
export PATH=$VERILATOR_ROOT/bin:$PATH
|
export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||||
|
|
||||||
@@ -1352,6 +1436,7 @@ Now we run Verilator on our little example.
|
|||||||
|
|
||||||
We then can compile it
|
We then can compile it
|
||||||
|
|
||||||
|
cd obj_dir
|
||||||
make -j -f Vour.mk Vour__ALL.a
|
make -j -f Vour.mk Vour__ALL.a
|
||||||
make -j -f Vour.mk ../sc_main.o verilated.o
|
make -j -f Vour.mk ../sc_main.o verilated.o
|
||||||
|
|
||||||
@@ -1457,42 +1542,42 @@ All output files are placed in the output directory name specified with the
|
|||||||
|
|
||||||
Verilator creates the following files in the output directory:
|
Verilator creates the following files in the output directory:
|
||||||
|
|
||||||
{prefix}.mk // Make include file for compiling
|
{prefix}.mk // Make include file for compiling
|
||||||
{prefix}_classes.mk // Make include file with class names
|
{prefix}_classes.mk // Make include file with class names
|
||||||
|
|
||||||
For -cc and -sc mode, it also creates:
|
For -cc and -sc mode, it also creates:
|
||||||
|
|
||||||
{prefix}.cpp // Top level C++ file
|
{prefix}.cpp // Top level C++ file
|
||||||
{prefix}.h // Top level header
|
{prefix}.h // Top level header
|
||||||
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files
|
{prefix}{each_verilog_module}.cpp // Lower level internal C++ files
|
||||||
{prefix}{each_verilog_module}.h // Lower level internal header files
|
{prefix}{each_verilog_module}.h // Lower level internal header files
|
||||||
|
|
||||||
In certain optimization modes, it also creates:
|
In certain optimization modes, it also creates:
|
||||||
|
|
||||||
{prefix}__Dpi.h // DPI import and export declarations
|
{prefix}__Dpi.h // DPI import and export declarations
|
||||||
{prefix}__Inlines.h // Inline support functions
|
{prefix}__Inlines.h // Inline support functions
|
||||||
{prefix}__Slow.cpp // Constructors and infrequent routines
|
{prefix}__Slow.cpp // Constructors and infrequent routines
|
||||||
{prefix}__Syms.cpp // Global symbol table C++
|
{prefix}__Syms.cpp // Global symbol table C++
|
||||||
{prefix}__Syms.h // Global symbol table header
|
{prefix}__Syms.h // Global symbol table header
|
||||||
{prefix}__Trace.cpp // Wave file generation code (--trace)
|
{prefix}__Trace.cpp // Wave file generation code (--trace)
|
||||||
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
||||||
{prefix}__stats.txt // Statistics (--stats)
|
{prefix}__stats.txt // Statistics (--stats)
|
||||||
|
|
||||||
It also creates internal files that can be mostly ignored:
|
It also creates internal files that can be mostly ignored:
|
||||||
|
|
||||||
{each_verilog_module}.vpp // Post-processed verilog (--debug)
|
{each_verilog_module}.vpp // Post-processed verilog (--debug)
|
||||||
{prefix}.flags_vbin // Verilator dependencies
|
{prefix}.flags_vbin // Verilator dependencies
|
||||||
{prefix}.flags_vpp // Pre-processor dependencies
|
{prefix}.flags_vpp // Pre-processor dependencies
|
||||||
{prefix}__verFiles.dat // Timestamps for skip-identical
|
{prefix}__verFiles.dat // Timestamps for skip-identical
|
||||||
{prefix}{misc}.d // Make dependencies (-MMD)
|
{prefix}{misc}.d // Make dependencies (-MMD)
|
||||||
{prefix}{misc}.dot // Debugging graph files (--debug)
|
{prefix}{misc}.dot // Debugging graph files (--debug)
|
||||||
{prefix}{misc}.tree // Debugging files (--debug)
|
{prefix}{misc}.tree // Debugging files (--debug)
|
||||||
|
|
||||||
After running Make, the C++ compiler should produce the following:
|
After running Make, the C++ compiler should produce the following:
|
||||||
|
|
||||||
{prefix} // Final executable (w/--exe argument)
|
{prefix} // Final executable (w/--exe argument)
|
||||||
{prefix}__ALL.a // Library of all Verilated objects
|
{prefix}__ALL.a // Library of all Verilated objects
|
||||||
{prefix}{misc}.o // Intermediate objects
|
{prefix}{misc}.o // Intermediate objects
|
||||||
|
|
||||||
|
|
||||||
=head1 ENVIRONMENT
|
=head1 ENVIRONMENT
|
||||||
@@ -1587,46 +1672,47 @@ simulation executable.
|
|||||||
The user must write the top level of the simulation. Here's a simple
|
The user must write the top level of the simulation. Here's a simple
|
||||||
example:
|
example:
|
||||||
|
|
||||||
#include <verilated.h> // Defines common routines
|
#include <verilated.h> // Defines common routines
|
||||||
#include "Vtop.h" // From Verilating "top.v"
|
#include <iostream> // Need std::cout
|
||||||
|
#include "Vtop.h" // From Verilating "top.v"
|
||||||
|
|
||||||
Vtop *top; // Instantiation of module
|
Vtop *top; // Instantiation of module
|
||||||
|
|
||||||
vluint64_t main_time = 0; // Current simulation time
|
vluint64_t main_time = 0; // Current simulation time
|
||||||
// This is a 64-bit integer to reduce wrap over issues and
|
// This is a 64-bit integer to reduce wrap over issues and
|
||||||
// allow modulus. You can also use a double, if you wish.
|
// allow modulus. You can also use a double, if you wish.
|
||||||
|
|
||||||
double sc_time_stamp () { // Called by $time in Verilog
|
double sc_time_stamp () { // Called by $time in Verilog
|
||||||
return main_time; // converts to double, to match
|
return main_time; // converts to double, to match
|
||||||
// what SystemC does
|
// what SystemC does
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
Verilated::commandArgs(argc, argv); // Remember args
|
Verilated::commandArgs(argc, argv); // Remember args
|
||||||
|
|
||||||
top = new Vtop; // Create instance
|
top = new Vtop; // Create instance
|
||||||
|
|
||||||
top->reset_l = 0; // Set some inputs
|
top->reset_l = 0; // Set some inputs
|
||||||
|
|
||||||
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
||||||
if (main_time > 10) {
|
if (main_time > 10) {
|
||||||
top->reset_l = 1; // Deassert reset
|
top->reset_l = 1; // Deassert reset
|
||||||
}
|
}
|
||||||
if ((main_time % 10) == 1) {
|
if ((main_time % 10) == 1) {
|
||||||
top->clk = 1; // Toggle clock
|
top->clk = 1; // Toggle clock
|
||||||
}
|
}
|
||||||
if ((main_time % 10) == 6) {
|
if ((main_time % 10) == 6) {
|
||||||
top->clk = 0;
|
top->clk = 0;
|
||||||
}
|
}
|
||||||
top->eval(); // Evaluate model
|
top->eval(); // Evaluate model
|
||||||
cout << top->out << endl; // Read a output
|
cout << top->out << endl; // Read a output
|
||||||
main_time++; // Time passes...
|
main_time++; // Time passes...
|
||||||
}
|
}
|
||||||
|
|
||||||
top->final(); // Done simulating
|
top->final(); // Done simulating
|
||||||
// // (Though this example doesn't get here)
|
// // (Though this example doesn't get here)
|
||||||
delete top;
|
delete top;
|
||||||
}
|
}
|
||||||
|
|
||||||
Note signals are read and written as member variables of the lower module.
|
Note signals are read and written as member variables of the lower module.
|
||||||
You call the eval() method to evaluate the model. When the simulation is
|
You call the eval() method to evaluate the model. When the simulation is
|
||||||
@@ -1802,6 +1888,8 @@ Verilator supports a very limited subset of the VPI. This subset allows
|
|||||||
inspection, examination, value change callbacks, and depositing of values
|
inspection, examination, value change callbacks, and depositing of values
|
||||||
to public signals only.
|
to public signals only.
|
||||||
|
|
||||||
|
VPI is enabled with the verilator --vpi switch.
|
||||||
|
|
||||||
To access signals via the VPI, Verilator must be told exactly which signals
|
To access signals via the VPI, Verilator must be told exactly which signals
|
||||||
are to be accessed. This is done using the Verilator public pragmas
|
are to be accessed. This is done using the Verilator public pragmas
|
||||||
documented below.
|
documented below.
|
||||||
@@ -1835,17 +1923,28 @@ changed on the specified clock edge.
|
|||||||
There are many online tutorials and books on the VPI, but an example that
|
There are many online tutorials and books on the VPI, but an example that
|
||||||
accesses the above would be:
|
accesses the above would be:
|
||||||
|
|
||||||
void read_and_check() {
|
void read_and_check() {
|
||||||
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
||||||
if (!vh1) { error... }
|
if (!vh1) { error... }
|
||||||
const char* name = vpi_get_str(vpiName, vh1);
|
const char* name = vpi_get_str(vpiName, vh1);
|
||||||
printf("Module name: %s\n"); // Prints "readme"
|
printf("Module name: %s\n"); // Prints "readme"
|
||||||
|
|
||||||
s_vpi_value v;
|
s_vpi_value v;
|
||||||
v.format = vpiIntVal;
|
v.format = vpiIntVal;
|
||||||
vpi_get_value(vh1, &v);
|
vpi_get_value(vh1, &v);
|
||||||
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
For signal callbacks to work the main loop of the program must call
|
||||||
|
VerilatedVpi::callValueCbs().
|
||||||
|
|
||||||
|
#include "verilated_vpi.h" // Required to get definitions
|
||||||
|
...
|
||||||
|
while (time passes) {
|
||||||
|
...
|
||||||
|
topp->eval();
|
||||||
|
VerilatedVpi::callValueCbs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
=head1 CROSS COMPILATION
|
=head1 CROSS COMPILATION
|
||||||
@@ -1888,10 +1987,10 @@ underneath NC:
|
|||||||
|
|
||||||
cd obj_dir
|
cd obj_dir
|
||||||
ncsc_run \
|
ncsc_run \
|
||||||
sc_main.cpp \
|
sc_main.cpp \
|
||||||
Vour__ALLcls.cpp \
|
Vour__ALLcls.cpp \
|
||||||
Vour__ALLsup.cpp \
|
Vour__ALLsup.cpp \
|
||||||
verilated.cpp
|
verilated.cpp
|
||||||
|
|
||||||
For larger designs you'll want to automate this using makefiles, which pull
|
For larger designs you'll want to automate this using makefiles, which pull
|
||||||
the names of the .cpp files to compile in from the make variables generated
|
the names of the .cpp files to compile in from the make variables generated
|
||||||
@@ -1943,8 +2042,9 @@ numbers (or all lines if omitted).
|
|||||||
With lint_off using '*' will override any lint_on directives in the source,
|
With lint_off using '*' will override any lint_on directives in the source,
|
||||||
i.e. the warning will still not be printed.
|
i.e. the warning will still not be printed.
|
||||||
|
|
||||||
If the -msg is omitted, all lint warnings are enabled/disabled. This will
|
If the -msg is omitted, all lint warnings (see list in -Wno-lint) are
|
||||||
override all later lint warning enables for the specified region.
|
enabled/disabled. This will override all later lint warning enables for
|
||||||
|
the specified region.
|
||||||
|
|
||||||
=item tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
=item tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||||
|
|
||||||
@@ -2085,45 +2185,52 @@ per the C standard (it's unspecified in Verilog).
|
|||||||
|
|
||||||
=item `coverage_block_off
|
=item `coverage_block_off
|
||||||
|
|
||||||
Specifies the entire begin/end block should be ignored for coverage analysis.
|
Specifies the entire begin/end block should be ignored for coverage
|
||||||
|
analysis. Must be inside a basic block, e.g. within a begin/end pair.
|
||||||
Same as /* verilator coverage_block_off */.
|
Same as /* verilator coverage_block_off */.
|
||||||
|
|
||||||
=item `systemc_header
|
=item `systemc_header
|
||||||
|
|
||||||
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
||||||
place it verbatim into the output .h file's header. Despite the name of this
|
place it verbatim into the output .h file's header. Must be placed as a
|
||||||
macro, this also works in pure C++ code.
|
module item, e.g. directly inside a module/endmodule pair. Despite the name
|
||||||
|
of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
=item `systemc_ctor
|
=item `systemc_ctor
|
||||||
|
|
||||||
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
||||||
place it verbatim into the C++ class constructor. Despite the name of this
|
place it verbatim into the C++ class constructor. Must be placed as a
|
||||||
macro, this also works in pure C++ code.
|
module item, e.g. directly inside a module/endmodule pair. Despite the name
|
||||||
|
of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
=item `systemc_dtor
|
=item `systemc_dtor
|
||||||
|
|
||||||
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
||||||
place it verbatim into the C++ class destructor. Despite the name of this
|
place it verbatim into the C++ class destructor. Must be placed as a
|
||||||
macro, this also works in pure C++ code.
|
module item, e.g. directly inside a module/endmodule pair. Despite the name
|
||||||
|
of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
=item `systemc_interface
|
=item `systemc_interface
|
||||||
|
|
||||||
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
||||||
place it verbatim into the C++ class interface. Despite the name of this
|
place it verbatim into the C++ class interface. Must be placed as a module
|
||||||
macro, this also works in pure C++ code.
|
item, e.g. directly inside a module/endmodule pair. Despite the name of
|
||||||
|
this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
=item `systemc_imp_header
|
=item `systemc_imp_header
|
||||||
|
|
||||||
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
||||||
place it verbatim into the header of all files for this C++ class
|
place it verbatim into the header of all files for this C++ class
|
||||||
implementation. Despite the name of this macro, this also works in pure
|
implementation. Must be placed as a module item, e.g. directly inside a
|
||||||
C++ code.
|
module/endmodule pair. Despite the name of this macro, this also works in
|
||||||
|
pure C++ code.
|
||||||
|
|
||||||
=item `systemc_implementation
|
=item `systemc_implementation
|
||||||
|
|
||||||
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
Take remaining text up to the next `verilog or `systemc_... mode switch and
|
||||||
place it verbatim into a single file of the C++ class implementation.
|
place it verbatim into a single file of the C++ class implementation. Must
|
||||||
Despite the name of this macro, this also works in pure C++ code.
|
be placed as a module item, e.g. directly inside a module/endmodule
|
||||||
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
If you will be reading or writing any Verilog variables in the C++
|
If you will be reading or writing any Verilog variables in the C++
|
||||||
functions, the Verilog signals must be declared with /*verilator public*/.
|
functions, the Verilog signals must be declared with /*verilator public*/.
|
||||||
@@ -2401,12 +2508,12 @@ such as $stop, $finish and $display. That is, you cannot use hierarchical
|
|||||||
references, events or similar features of the Verilog language. It also
|
references, events or similar features of the Verilog language. It also
|
||||||
simulates as Synopsys's Design Compiler would; namely a block of the form:
|
simulates as Synopsys's Design Compiler would; namely a block of the form:
|
||||||
|
|
||||||
always @ (x) y = x & z;
|
always @ (x) y = x & z;
|
||||||
|
|
||||||
This will recompute y when there is even a potential for change in x or a
|
This will recompute y when there is even a potential for change in x or a
|
||||||
change in z, that is when the flops computing x or z evaluate (which is
|
change in z, that is when the flops computing x or z evaluate (which is
|
||||||
what Design Compiler will synthesize.) A compliant simulator would only
|
what Design Compiler will synthesize.) A compliant simulator would only
|
||||||
calculate y if x changes. Use verilog-mode's /*AS*/ or Verilog 2001's
|
calculate y if x changes. Use Verilog-Mode's /*AS*/ or Verilog 2001's
|
||||||
always @* to reduce missing activity items. Avoid putting $displays in
|
always @* to reduce missing activity items. Avoid putting $displays in
|
||||||
combo blocks, as they may print multiple times when not desired, even on
|
combo blocks, as they may print multiple times when not desired, even on
|
||||||
compliant simulators as event ordering is not specified.
|
compliant simulators as event ordering is not specified.
|
||||||
@@ -2489,7 +2596,7 @@ variables are initialized to a random value.
|
|||||||
Event driven simulators will generally trigger an edge on a transition from X
|
Event driven simulators will generally trigger an edge on a transition from X
|
||||||
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
||||||
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||||
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
|
code (particularly for reset) may rely on X->0 triggering an edge. Verilator
|
||||||
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
||||||
runs with and without this switch will find such problems.
|
runs with and without this switch will find such problems.
|
||||||
|
|
||||||
@@ -2542,7 +2649,7 @@ clock_enable*/ attribute.
|
|||||||
=head2 Ranges must be big-bit-endian
|
=head2 Ranges must be big-bit-endian
|
||||||
|
|
||||||
Bit ranges must be numbered with the MSB being numbered greater or the same
|
Bit ranges must be numbered with the MSB being numbered greater or the same
|
||||||
as the LSB. Little-bit-endian busses [0:15] are not supported as they
|
as the LSB. Little-bit-endian buses [0:15] are not supported as they
|
||||||
aren't easily made compatible with C++.
|
aren't easily made compatible with C++.
|
||||||
|
|
||||||
=head2 Gate Primitives
|
=head2 Gate Primitives
|
||||||
@@ -2741,13 +2848,17 @@ when displaying all times, model wide.
|
|||||||
|
|
||||||
=head1 ERRORS AND WARNINGS
|
=head1 ERRORS AND WARNINGS
|
||||||
|
|
||||||
Warnings may be disabled in two ways. First, when the warning is
|
Warnings may be disabled in three ways. First, when the warning is
|
||||||
printed it will include a warning code. Simply surround the offending
|
printed it will include a warning code. Simply surround the offending
|
||||||
line with a warn_off/warn_on pair:
|
line with a warn_off/warn_on pair:
|
||||||
|
|
||||||
// verilator lint_off UNSIGNED
|
// verilator lint_off UNSIGNED
|
||||||
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
|
if (`DEF_THAT_IS_EQ_ZERO <= 3) $stop;
|
||||||
// verilator lint_on UNSIGNED
|
// verilator lint_on UNSIGNED
|
||||||
|
|
||||||
|
Second, warnings may be disabled using a configuration file with a lint_off
|
||||||
|
command. This is useful when a script is suppressing warnings and the
|
||||||
|
Verilog source should not be changed.
|
||||||
|
|
||||||
Warnings may also be globally disabled by invoking Verilator with the
|
Warnings may also be globally disabled by invoking Verilator with the
|
||||||
C<-Wno-I<warning>> switch. This should be avoided, as it removes all
|
C<-Wno-I<warning>> switch. This should be avoided, as it removes all
|
||||||
@@ -2841,10 +2952,10 @@ were used, the simulator would have to copy large arrays every cycle. (In
|
|||||||
smaller loops, loop unrolling allows the delayed assignment to work, though
|
smaller loops, loop unrolling allows the delayed assignment to work, though
|
||||||
it's a bit slower than a non-delayed assignment.) Here's an example
|
it's a bit slower than a non-delayed assignment.) Here's an example
|
||||||
|
|
||||||
always @ (posedge clk)
|
always @ (posedge clk)
|
||||||
if (~reset_l) begin
|
if (~reset_l) begin
|
||||||
for (i=0; i<`ARRAY_SIZE; i++) begin
|
for (i=0; i<`ARRAY_SIZE; i++) begin
|
||||||
array[i] = 0; // Non-delayed for verilator
|
array[i] = 0; // Non-delayed for verilator
|
||||||
end
|
end
|
||||||
|
|
||||||
This message is only seen on large or complicated loops because Verilator
|
This message is only seen on large or complicated loops because Verilator
|
||||||
@@ -3302,9 +3413,9 @@ A recommended style for unused nets is to put at the bottom of a file code
|
|||||||
similar to the following:
|
similar to the following:
|
||||||
|
|
||||||
wire _unused_ok = &{1'b0,
|
wire _unused_ok = &{1'b0,
|
||||||
sig_not_used_a,
|
sig_not_used_a,
|
||||||
sig_not_used_yet_b, // To be fixed
|
sig_not_used_yet_b, // To be fixed
|
||||||
1'b0};
|
1'b0};
|
||||||
|
|
||||||
The reduction AND and constant zeros mean the net will always be zero, so
|
The reduction AND and constant zeros mean the net will always be zero, so
|
||||||
won't use simulation time. The redundant leading and trailing zeros avoid
|
won't use simulation time. The redundant leading and trailing zeros avoid
|
||||||
@@ -3315,6 +3426,10 @@ with "unused" in the name, or put the appropriate lint_off around the wire.
|
|||||||
Having unused signals in one place makes it easy to find what is unused,
|
Having unused signals in one place makes it easy to find what is unused,
|
||||||
and reduces the number of lint_off pragmas, reducing bugs.
|
and reduces the number of lint_off pragmas, reducing bugs.
|
||||||
|
|
||||||
|
=item USERINFO, USERWARN, USERERROR, USERFATAL
|
||||||
|
|
||||||
|
A SystemVerilog elaboration-time assertion print was executed.
|
||||||
|
|
||||||
=item VARHIDDEN
|
=item VARHIDDEN
|
||||||
|
|
||||||
Warns that a task, function, or begin/end block is declaring a variable by
|
Warns that a task, function, or begin/end block is declaring a variable by
|
||||||
@@ -3337,11 +3452,11 @@ unwidthed. Verilator considers zero to be any width needed.
|
|||||||
|
|
||||||
Concatenate leading zeros when doing arithmetic. In the statement
|
Concatenate leading zeros when doing arithmetic. In the statement
|
||||||
|
|
||||||
wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0];
|
wire [5:0] plus_one = from[5:0] + 6'd1 + carry[0];
|
||||||
|
|
||||||
The best fix, which clarifies intent and will also make all tools happy is:
|
The best fix, which clarifies intent and will also make all tools happy is:
|
||||||
|
|
||||||
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
|
wire [5:0] plus_one = from[5:0] + 6'd1 + {5'd0,carry[0]};
|
||||||
|
|
||||||
Ignoring this warning will only suppress the lint check, it will simulate
|
Ignoring this warning will only suppress the lint check, it will simulate
|
||||||
correctly.
|
correctly.
|
||||||
@@ -3539,7 +3654,7 @@ trace file if you want all data to land in the same output file.
|
|||||||
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
||||||
...
|
...
|
||||||
sc_start(1);
|
sc_start(1);
|
||||||
...
|
...
|
||||||
tfp->close();
|
tfp->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3886,7 +4001,7 @@ Thanks to them, and all those we've missed including above.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify the Verilator internals under the terms of
|
redistribute it and/or modify the Verilator internals under the terms of
|
||||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||||
License Version 2.0.
|
License Version 2.0.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
|||||||
if 0;
|
if 0;
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you
|
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -271,7 +271,7 @@ Specifies a module search directory.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify the Verilator internals under the terms of
|
redistribute it and/or modify the Verilator internals under the terms of
|
||||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||||
License Version 2.0.
|
License Version 2.0.
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ Do not show differences in line numbering.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/verilator>.
|
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. This package is free software; you can
|
Copyright 2005-2017 by Wilson Snyder. This package is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
|||||||
if 0;
|
if 0;
|
||||||
# DESCRIPTION: Print include statements for each ARGV
|
# DESCRIPTION: Print include statements for each ARGV
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. This package is free software; you can
|
# Copyright 2003-2017 by Wilson Snyder. This package is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2007-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2007-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+17
-3
@@ -1,12 +1,12 @@
|
|||||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
|
# Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||||
#AC_INIT([Verilator],[#.### devel])
|
#AC_INIT([Verilator],[#.### devel])
|
||||||
AC_INIT([Verilator],[3.876 2015-08-12])
|
AC_INIT([Verilator],[3.900 2017-01-15])
|
||||||
# When releasing, also update header of Changes file
|
# When releasing, also update header of Changes file
|
||||||
|
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
@@ -15,7 +15,7 @@ AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk incl
|
|||||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||||
|
|
||||||
# Special Substitutions - CFG_WITH_DEFENV
|
# Special Substitutions - CFG_WITH_DEFENV
|
||||||
AC_MSG_CHECKING(whether to disable hardcoded paths)
|
AC_MSG_CHECKING(whether to use hardcoded paths)
|
||||||
AC_ARG_ENABLE([defenv],
|
AC_ARG_ENABLE([defenv],
|
||||||
[AS_HELP_STRING([--disable-defenv],
|
[AS_HELP_STRING([--disable-defenv],
|
||||||
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
|
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
|
||||||
@@ -120,6 +120,18 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
|
|||||||
fi
|
fi
|
||||||
fi],
|
fi],
|
||||||
[_my_result=no])
|
[_my_result=no])
|
||||||
|
# GCC is annoying, trying to be helpful, it postpones unknown -Wno-
|
||||||
|
# options if there's no error We want to see them regardless, so try
|
||||||
|
# forcing an error and see if we get a gcc warning
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([[an_error "intentional-error-for-test.h"
|
||||||
|
]],[])],
|
||||||
|
[], # Ignore ok exit
|
||||||
|
[if test -s conftest.err; then
|
||||||
|
if grep -e "$2" conftest.err >/dev/null; then
|
||||||
|
_my_result=no
|
||||||
|
fi
|
||||||
|
fi])
|
||||||
AC_MSG_RESULT($_my_result)
|
AC_MSG_RESULT($_my_result)
|
||||||
if test "$_my_result" = "yes" ; then
|
if test "$_my_result" = "yes" ; then
|
||||||
$1="$$1 $2"
|
$1="$$1 $2"
|
||||||
@@ -130,7 +142,9 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
|
|||||||
# Flags for compiling Verilator internals including parser
|
# Flags for compiling Verilator internals including parser
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
|
||||||
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
|
||||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
||||||
|
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks)
|
||||||
AC_SUBST(CFG_CXXFLAGS_SRC)
|
AC_SUBST(CFG_CXXFLAGS_SRC)
|
||||||
|
|
||||||
# Flags for compiling Verilator parser
|
# Flags for compiling Verilator parser
|
||||||
|
|||||||
+128
-80
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -374,7 +374,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
} else {
|
} else {
|
||||||
lwp = va_arg(ap,WDataInP);
|
lwp = va_arg(ap,WDataInP);
|
||||||
ld = lwp[0];
|
ld = lwp[0];
|
||||||
if (fmt == 'u' || fmt == 'd') fmt = 'x'; // Not supported, but show something
|
if (fmt == 'd' || fmt == '#') fmt = 'x'; // Not supported, but show something
|
||||||
}
|
}
|
||||||
int lsb=lbits-1;
|
int lsb=lbits-1;
|
||||||
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
||||||
@@ -404,7 +404,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
output += tmp;
|
output += tmp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'u': { // Unsigned decimal
|
case '#': { // Unsigned decimal
|
||||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||||
int needmore = width-digits;
|
int needmore = width-digits;
|
||||||
if (needmore>0) {
|
if (needmore>0) {
|
||||||
@@ -438,6 +438,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
for (; lsb>=0; lsb--) {
|
for (; lsb>=0; lsb--) {
|
||||||
lsb = (lsb / 3) * 3; // Next digit
|
lsb = (lsb / 3) * 3; // Next digit
|
||||||
@@ -450,6 +451,28 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
|||||||
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'u': // Packed 2-state
|
||||||
|
output.reserve(output.size() + 4*VL_WORDS_I(lbits));
|
||||||
|
for (int i=0; i<VL_WORDS_I(lbits); i++) {
|
||||||
|
output += (char)((lwp[i] >> 0) & 0xff);
|
||||||
|
output += (char)((lwp[i] >> 8) & 0xff);
|
||||||
|
output += (char)((lwp[i] >> 16) & 0xff);
|
||||||
|
output += (char)((lwp[i] >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
case 'z': // Packed 4-state
|
||||||
|
output.reserve(output.size() + 8*VL_WORDS_I(lbits));
|
||||||
|
for (int i=0; i<VL_WORDS_I(lbits); i++) {
|
||||||
|
output += (char)((lwp[i] >> 0) & 0xff);
|
||||||
|
output += (char)((lwp[i] >> 8) & 0xff);
|
||||||
|
output += (char)((lwp[i] >> 16) & 0xff);
|
||||||
|
output += (char)((lwp[i] >> 24) & 0xff);
|
||||||
|
output += "\0\0\0\0"; // No tristate
|
||||||
|
}
|
||||||
|
case 'v': // Strength; assume always strong
|
||||||
|
for (lsb=lbits-1; lsb>=0; lsb--) {
|
||||||
|
if ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) output += "St1 ";
|
||||||
|
else output += "St0 ";
|
||||||
|
}
|
||||||
case 'x':
|
case 'x':
|
||||||
for (; lsb>=0; lsb--) {
|
for (; lsb>=0; lsb--) {
|
||||||
lsb = (lsb / 4) * 4; // Next digit
|
lsb = (lsb / 4) * 4; // Next digit
|
||||||
@@ -627,13 +650,14 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE");
|
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE");
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
|
// cppcheck-suppress unusedStructMember // It's used
|
||||||
union { double r; vlsint64_t ld; } u;
|
union { double r; vlsint64_t ld; } u;
|
||||||
u.r = strtod(tmp, NULL);
|
u.r = strtod(tmp, NULL);
|
||||||
VL_SET_WQ(owp,u.ld);
|
VL_SET_WQ(owp,u.ld);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 't': // FALLTHRU // Time
|
case 't': // FALLTHRU // Time
|
||||||
case 'u': { // Unsigned decimal
|
case '#': { // Unsigned decimal
|
||||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
|
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
|
||||||
if (!tmp[0]) goto done;
|
if (!tmp[0]) goto done;
|
||||||
@@ -932,11 +956,18 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||||||
WDataInP ofilenamep, void* memp, IData start, IData end) {
|
WDataInP ofilenamep, void* memp, IData start, IData end) {
|
||||||
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||||
FILE* fp = fopen(ofilenamez, "r");
|
string ofilenames(ofilenamez);
|
||||||
|
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
const string& ofilenamep, void* memp, IData start, IData end) {
|
||||||
|
if (fnwords) {}
|
||||||
|
FILE* fp = fopen(ofilenamep.c_str(), "r");
|
||||||
if (VL_UNLIKELY(!fp)) {
|
if (VL_UNLIKELY(!fp)) {
|
||||||
// We don't report the Verilog source filename as it slow to have to pass it down
|
// We don't report the Verilog source filename as it slow to have to pass it down
|
||||||
vl_fatal (ofilenamez, 0, "", "$readmem file not found");
|
vl_fatal (ofilenamep.c_str(), 0, "", "$readmem file not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Prep for reading
|
// Prep for reading
|
||||||
IData addr = start;
|
IData addr = start;
|
||||||
@@ -951,81 +982,81 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||||||
// We process a character at a time, as then we don't need to deal
|
// We process a character at a time, as then we don't need to deal
|
||||||
// with changing buffer sizes dynamically, etc.
|
// with changing buffer sizes dynamically, etc.
|
||||||
while (1) {
|
while (1) {
|
||||||
int c = fgetc(fp);
|
int c = fgetc(fp);
|
||||||
if (VL_UNLIKELY(c==EOF)) break;
|
if (VL_UNLIKELY(c==EOF)) break;
|
||||||
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
||||||
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
|
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
|
||||||
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
||||||
// Skip // comments and detect /* comments
|
// Skip // comments and detect /* comments
|
||||||
else if (ignore_to_cmt && lastc=='*' && c=='/') {
|
else if (ignore_to_cmt && lastc=='*' && c=='/') {
|
||||||
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
|
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
|
||||||
} else if (!ignore_to_eol && !ignore_to_cmt) {
|
} else if (!ignore_to_eol && !ignore_to_cmt) {
|
||||||
if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
|
if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
|
||||||
else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
|
else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
|
||||||
else if (c=='/') {} // Part of /* or //
|
else if (c=='/') {} // Part of /* or //
|
||||||
else if (c=='_') {}
|
else if (c=='_') {}
|
||||||
else if (c=='@') { reading_addr = true; innum=false; needinc=false; }
|
else if (c=='@') { reading_addr = true; innum=false; needinc=false; }
|
||||||
// Check for hex or binary digits as file format requests
|
// Check for hex or binary digits as file format requests
|
||||||
else if (isxdigit(c)) {
|
else if (isxdigit(c)) {
|
||||||
c = tolower(c);
|
c = tolower(c);
|
||||||
int value = (c >= 'a' ? (c-'a'+10) : (c-'0'));
|
int value = (c >= 'a' ? (c-'a'+10) : (c-'0'));
|
||||||
if (!innum) { // Prep for next number
|
if (!innum) { // Prep for next number
|
||||||
if (needinc) { addr++; needinc=false; }
|
if (needinc) { addr++; needinc=false; }
|
||||||
}
|
}
|
||||||
if (reading_addr) {
|
if (reading_addr) {
|
||||||
// Decode @ addresses
|
// Decode @ addresses
|
||||||
if (!innum) addr=0;
|
if (!innum) addr=0;
|
||||||
addr = (addr<<4) + value;
|
addr = (addr<<4) + value;
|
||||||
} else {
|
} else {
|
||||||
needinc = true;
|
needinc = true;
|
||||||
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
||||||
if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) {
|
if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array");
|
vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array");
|
||||||
} else {
|
} else {
|
||||||
int entry = addr - array_lsb;
|
int entry = addr - array_lsb;
|
||||||
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
|
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
|
||||||
// Shift value in
|
// Shift value in
|
||||||
if (width<=8) {
|
if (width<=8) {
|
||||||
CData* datap = &((CData*)(memp))[entry];
|
CData* datap = &((CData*)(memp))[entry];
|
||||||
if (!innum) { *datap = 0; }
|
if (!innum) { *datap = 0; }
|
||||||
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||||
} else if (width<=16) {
|
} else if (width<=16) {
|
||||||
SData* datap = &((SData*)(memp))[entry];
|
SData* datap = &((SData*)(memp))[entry];
|
||||||
if (!innum) { *datap = 0; }
|
if (!innum) { *datap = 0; }
|
||||||
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||||
} else if (width<=VL_WORDSIZE) {
|
} else if (width<=VL_WORDSIZE) {
|
||||||
IData* datap = &((IData*)(memp))[entry];
|
IData* datap = &((IData*)(memp))[entry];
|
||||||
if (!innum) { *datap = 0; }
|
if (!innum) { *datap = 0; }
|
||||||
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||||
} else if (width<=VL_QUADSIZE) {
|
} else if (width<=VL_QUADSIZE) {
|
||||||
QData* datap = &((QData*)(memp))[entry];
|
QData* datap = &((QData*)(memp))[entry];
|
||||||
if (!innum) { *datap = 0; }
|
if (!innum) { *datap = 0; }
|
||||||
*datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width);
|
*datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width);
|
||||||
} else {
|
} else {
|
||||||
WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ];
|
WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ];
|
||||||
if (!innum) { VL_ZERO_RESET_W(width, datap); }
|
if (!innum) { VL_ZERO_RESET_W(width, datap); }
|
||||||
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
|
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
|
||||||
datap[0] |= value;
|
datap[0] |= value;
|
||||||
}
|
}
|
||||||
if (VL_UNLIKELY(value>=(1<<shift))) {
|
if (VL_UNLIKELY(value>=(1<<shift))) {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
|
vl_fatal (ofilenamep.c_str(), linenum, "", "$readmemb (binary) file contains hex characters");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
innum = true;
|
innum = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmem file syntax error");
|
vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file syntax error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastc = c;
|
lastc = c;
|
||||||
}
|
}
|
||||||
if (needinc) { addr++; needinc=false; }
|
if (needinc) { addr++; needinc=false; }
|
||||||
|
|
||||||
// Final checks
|
// Final checks
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
|
if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
|
||||||
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address");
|
vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file ended before specified ending-address");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,6 +1077,14 @@ IData VL_TESTPLUSARGS_I(const char* formatp) {
|
|||||||
else return 1;
|
else return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IData VL_VALUEPLUSARGS_IN(int, const char* prefixp, char, string& ldr) {
|
||||||
|
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||||
|
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||||
|
if (match == "") return 0;
|
||||||
|
ldr = string(dp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
||||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||||
@@ -1151,7 +1190,12 @@ void Verilated::commandArgs(int argc, const char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
||||||
return VerilatedImp::argPlusMatch(prefixp).c_str();
|
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||||
|
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
|
if (match == "") return "";
|
||||||
|
strncpy(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH);
|
||||||
|
outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
|
||||||
|
return outstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Verilated::internalsDump() {
|
void Verilated::internalsDump() {
|
||||||
@@ -1170,6 +1214,10 @@ int Verilated::exportFuncNum(const char* namep) {
|
|||||||
return VerilatedImp::exportFind(namep);
|
return VerilatedImp::exportFind(namep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VerilatedScopeNameMap* Verilated::scopeNameMap() {
|
||||||
|
return VerilatedImp::scopeNameMap();
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// VerilatedModule:: Methods
|
// VerilatedModule:: Methods
|
||||||
|
|
||||||
@@ -1178,7 +1226,7 @@ VerilatedModule::VerilatedModule(const char* namep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VerilatedModule::~VerilatedModule() {
|
VerilatedModule::~VerilatedModule() {
|
||||||
if (m_namep) free((void*)m_namep); m_namep=NULL;
|
if (m_namep) { free((void*)m_namep); m_namep=NULL; }
|
||||||
}
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
@@ -1292,7 +1340,7 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* VerilatedScope::exportFindNullError(int funcnum) const {
|
void* VerilatedScope::exportFindNullError(int funcnum) {
|
||||||
// Slowpath - Called only when find has failed
|
// Slowpath - Called only when find has failed
|
||||||
string msg = (string("Testbench C called '")
|
string msg = (string("Testbench C called '")
|
||||||
+VerilatedImp::exportName(funcnum)
|
+VerilatedImp::exportName(funcnum)
|
||||||
|
|||||||
+15
-10
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
// <iostream> avoided to reduce compile time
|
// <iostream> avoided to reduce compile time
|
||||||
|
// <map> avoided and instead in verilated_heavy.h to reduce compile time
|
||||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ typedef void (*VerilatedVoidCb)(void);
|
|||||||
|
|
||||||
class SpTraceVcd;
|
class SpTraceVcd;
|
||||||
class SpTraceVcdCFile;
|
class SpTraceVcdCFile;
|
||||||
|
class VerilatedScopeNameMap;
|
||||||
class VerilatedVar;
|
class VerilatedVar;
|
||||||
class VerilatedVarNameMap;
|
class VerilatedVarNameMap;
|
||||||
class VerilatedVcd;
|
class VerilatedVcd;
|
||||||
@@ -102,9 +104,9 @@ class VerilatedModule {
|
|||||||
private:
|
private:
|
||||||
const char* m_namep; ///< Module name
|
const char* m_namep; ///< Module name
|
||||||
VerilatedModule(); ///< N/A, always use named constructor below
|
VerilatedModule(); ///< N/A, always use named constructor below
|
||||||
VerilatedModule(const VerilatedModule& ); ///< N/A, no copying modules
|
VerilatedModule(const VerilatedModule& ); ///< N/A, no copy constructor
|
||||||
public:
|
public:
|
||||||
VerilatedModule(const char* namep); ///< Create module with given hierarchy name
|
explicit VerilatedModule(const char* namep); ///< Create module with given hierarchy name
|
||||||
~VerilatedModule();
|
~VerilatedModule();
|
||||||
const char* name() const { return m_namep; } ///< Return name of module
|
const char* name() const { return m_namep; } ///< Return name of module
|
||||||
};
|
};
|
||||||
@@ -199,16 +201,16 @@ public: // But internals only - called from VerilatedModule's
|
|||||||
inline VerilatedSyms* symsp() const { return m_symsp; }
|
inline VerilatedSyms* symsp() const { return m_symsp; }
|
||||||
VerilatedVar* varFind(const char* namep) const;
|
VerilatedVar* varFind(const char* namep) const;
|
||||||
VerilatedVarNameMap* varsp() const { return m_varsp; }
|
VerilatedVarNameMap* varsp() const { return m_varsp; }
|
||||||
void* exportFindError(int funcnum) const;
|
|
||||||
void* exportFindNullError(int funcnum) const;
|
|
||||||
void scopeDump() const;
|
void scopeDump() const;
|
||||||
inline void* exportFind(int funcnum) const {
|
void* exportFindError(int funcnum) const;
|
||||||
if (VL_UNLIKELY(!this)) return exportFindNullError(funcnum);
|
static void* exportFindNullError(int funcnum);
|
||||||
if (VL_LIKELY(funcnum < m_funcnumMax)) {
|
static inline void* exportFind(const VerilatedScope* scopep, int funcnum) {
|
||||||
|
if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum);
|
||||||
|
if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) {
|
||||||
// m_callbacksp must be declared, as Max'es are > 0
|
// m_callbacksp must be declared, as Max'es are > 0
|
||||||
return m_callbacksp[funcnum];
|
return scopep->m_callbacksp[funcnum];
|
||||||
} else {
|
} else {
|
||||||
return exportFindError(funcnum);
|
return scopep->exportFindError(funcnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -286,7 +288,9 @@ public:
|
|||||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||||
static void commandArgs(int argc, const char** argv);
|
static void commandArgs(int argc, const char** argv);
|
||||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||||
|
static void commandArgsAdd(int argc, const char** argv);
|
||||||
static CommandArgValues* getCommandArgs() {return &s_args;}
|
static CommandArgValues* getCommandArgs() {return &s_args;}
|
||||||
|
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
|
||||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||||
|
|
||||||
/// Produce name & version for (at least) VPI
|
/// Produce name & version for (at least) VPI
|
||||||
@@ -308,6 +312,7 @@ public:
|
|||||||
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
||||||
// Internal: Find scope
|
// Internal: Find scope
|
||||||
static const VerilatedScope* scopeFind(const char* namep);
|
static const VerilatedScope* scopeFind(const char* namep);
|
||||||
|
static const VerilatedScopeNameMap* scopeNameMap();
|
||||||
// Internal: Get and set DPI context
|
// Internal: Get and set DPI context
|
||||||
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
|
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
|
||||||
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
|
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
|
||||||
|
|||||||
+16
-16
@@ -2,7 +2,7 @@
|
|||||||
######################################################################
|
######################################################################
|
||||||
# DESCRIPTION: Makefile commands for all verilated target files
|
# DESCRIPTION: Makefile commands for all verilated target files
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. Verilator is free software; you can
|
# Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
######################################################################
|
######################################################################
|
||||||
@@ -43,8 +43,9 @@ VK_CPPFLAGS_ALWAYS += \
|
|||||||
-I$(VERILATOR_ROOT)/include \
|
-I$(VERILATOR_ROOT)/include \
|
||||||
-I$(VERILATOR_ROOT)/include/vltstd \
|
-I$(VERILATOR_ROOT)/include/vltstd \
|
||||||
-DVL_PRINTF=printf \
|
-DVL_PRINTF=printf \
|
||||||
-DVM_TRACE=$(VM_TRACE) \
|
|
||||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||||
|
-DVM_SC=$(VM_SC) \
|
||||||
|
-DVM_TRACE=$(VM_TRACE) \
|
||||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||||
|
|
||||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
@@ -123,19 +124,10 @@ else
|
|||||||
preproc:
|
preproc:
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#######################################################################
|
|
||||||
##### SystemC w/o SystemPerl builds
|
|
||||||
|
|
||||||
ifeq ($(VM_SC),1)
|
|
||||||
LIBS += -lm -lstdc++
|
|
||||||
endif
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##### C/H builds
|
##### C/H builds
|
||||||
|
|
||||||
ifeq ($(VM_PCLI),1)
|
LIBS += -lm -lstdc++
|
||||||
LIBS += -lm -lstdc++
|
|
||||||
endif
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Overall Objects Linking
|
# Overall Objects Linking
|
||||||
@@ -171,16 +163,24 @@ $(VM_PREFIX)__ALL.a: $(VK_OBJS)
|
|||||||
######################################################################
|
######################################################################
|
||||||
### Compile rules
|
### Compile rules
|
||||||
|
|
||||||
#Default rule embedded in make: (Not defined so user makefiles can override it)
|
ifneq ($(VM_DEFAULT_RULES),0)
|
||||||
#.cpp.o:
|
|
||||||
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
$(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp
|
$(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp
|
||||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
||||||
|
|
||||||
$(VM_PREFIX)__ALLcls.o: $(VM_PREFIX)__ALLcls.cpp
|
$(VM_PREFIX)__ALLcls.o: $(VM_PREFIX)__ALLcls.cpp
|
||||||
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
||||||
|
|
||||||
|
$(VM_PREFIX)%__Slow.o: $(VM_PREFIX)%__Slow.cpp
|
||||||
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
|
||||||
|
|
||||||
|
$(VM_PREFIX)%.o: $(VM_PREFIX)%.cpp
|
||||||
|
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
|
||||||
|
endif
|
||||||
|
|
||||||
|
#Default rule embedded in make:
|
||||||
|
#.cpp.o:
|
||||||
|
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Debugging
|
### Debugging
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -75,6 +75,7 @@ public:
|
|||||||
virtual vluint64_t count() const { return *m_countp; }
|
virtual vluint64_t count() const { return *m_countp; }
|
||||||
virtual void zero() const { *m_countp = 0; }
|
virtual void zero() const { *m_countp = 0; }
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
VerilatedCoverItemSpec(T* countp) : m_countp(countp) { zero(); }
|
VerilatedCoverItemSpec(T* countp) : m_countp(countp) { zero(); }
|
||||||
virtual ~VerilatedCoverItemSpec() {}
|
virtual ~VerilatedCoverItemSpec() {}
|
||||||
};
|
};
|
||||||
@@ -261,8 +262,8 @@ public:
|
|||||||
assert(m_insertp);
|
assert(m_insertp);
|
||||||
// First two key/vals are filename
|
// First two key/vals are filename
|
||||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||||
VlCovCvtToCStr linestrp (m_insertLineno);
|
string linestr = vlCovCvtToStr(m_insertLineno);
|
||||||
ckeyps[1]="lineno"; valps[1]=linestrp;
|
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
|
||||||
// Default page if not specified
|
// Default page if not specified
|
||||||
const char* fnstartp = m_insertFilenamep;
|
const char* fnstartp = m_insertFilenamep;
|
||||||
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1;
|
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1;
|
||||||
@@ -440,8 +441,10 @@ void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
|||||||
// Backward compatibility for Verilator
|
// Backward compatibility for Verilator
|
||||||
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
|
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
|
||||||
K(4),const string& val4, A(5),A(6)) {
|
K(4),const string& val4, A(5),A(6)) {
|
||||||
|
string val2str = vlCovCvtToStr(val2);
|
||||||
|
string val3str = vlCovCvtToStr(val3);
|
||||||
_insertp(C(0),C(1),
|
_insertp(C(0),C(1),
|
||||||
key2,VlCovCvtToCStr(val2), key3,VlCovCvtToCStr(val3), key4, val4.c_str(),
|
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
|
||||||
C(5),C(6),N(7),N(8),N(9),
|
C(5),C(6),N(7),N(8),N(9),
|
||||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||||
|
|||||||
+1
-14
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -78,19 +78,6 @@ template< class T> std::string vlCovCvtToStr (const T& t) {
|
|||||||
ostringstream os; os<<t; return os.str();
|
ostringstream os; os<<t; return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Usage: something(VlCovCvtToCStr(i))
|
|
||||||
/// Note the pointer will only be valid for as long as the object remains
|
|
||||||
/// in scope!
|
|
||||||
struct VlCovCvtToCStr {
|
|
||||||
string m_str;
|
|
||||||
// Casters
|
|
||||||
template< class T> VlCovCvtToCStr (const T& t) {
|
|
||||||
ostringstream os; os<<t; m_str=os.str();
|
|
||||||
}
|
|
||||||
~VlCovCvtToCStr() {}
|
|
||||||
operator const char* () const { return m_str.c_str(); };
|
|
||||||
};
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// VerilatedCov
|
// VerilatedCov
|
||||||
/// Verilator coverage global class
|
/// Verilator coverage global class
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -61,8 +61,11 @@ inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern IData VL_FOPEN_NI(const string& filename, IData mode);
|
extern IData VL_FOPEN_NI(const string& filename, IData mode);
|
||||||
|
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
const string& ofilename, void* memp, IData start, IData end);
|
||||||
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
||||||
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
||||||
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
||||||
|
extern IData VL_VALUEPLUSARGS_IN(int rbits, const char* prefixp, char fmt, string& ldr);
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+14
-8
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -49,7 +49,6 @@ class VerilatedImp {
|
|||||||
// TYPES
|
// TYPES
|
||||||
typedef vector<string> ArgVec;
|
typedef vector<string> ArgVec;
|
||||||
typedef map<pair<const void*,void*>,void*> UserMap;
|
typedef map<pair<const void*,void*>,void*> UserMap;
|
||||||
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
|
|
||||||
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
@@ -60,7 +59,7 @@ class VerilatedImp {
|
|||||||
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
||||||
bool m_argVecLoaded; ///< Ever loaded argument list
|
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||||
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
||||||
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
VerilatedScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
||||||
// Slow - somewhat static:
|
// Slow - somewhat static:
|
||||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||||
int m_exportNext; ///< Next export funcnum
|
int m_exportNext; ///< Next export funcnum
|
||||||
@@ -93,7 +92,11 @@ public: // But only for verilated*.cpp
|
|||||||
|
|
||||||
// METHODS - arguments
|
// METHODS - arguments
|
||||||
static void commandArgs(int argc, const char** argv) {
|
static void commandArgs(int argc, const char** argv) {
|
||||||
s_s.m_argVec.clear();
|
s_s.m_argVec.clear(); // Always clear
|
||||||
|
commandArgsAdd(argc, argv);
|
||||||
|
}
|
||||||
|
static void commandArgsAdd(int argc, const char** argv) {
|
||||||
|
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||||
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
|
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
|
||||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||||
}
|
}
|
||||||
@@ -154,30 +157,33 @@ public: // But only for verilated*.cpp
|
|||||||
// METHODS - scope name
|
// METHODS - scope name
|
||||||
static void scopeInsert(const VerilatedScope* scopep) {
|
static void scopeInsert(const VerilatedScope* scopep) {
|
||||||
// Slow ok - called once/scope at construction
|
// Slow ok - called once/scope at construction
|
||||||
ScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||||
if (it == s_s.m_nameMap.end()) {
|
if (it == s_s.m_nameMap.end()) {
|
||||||
s_s.m_nameMap.insert(it, make_pair(scopep->name(),scopep));
|
s_s.m_nameMap.insert(it, make_pair(scopep->name(),scopep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline const VerilatedScope* scopeFind(const char* namep) {
|
static inline const VerilatedScope* scopeFind(const char* namep) {
|
||||||
ScopeNameMap::iterator it=s_s.m_nameMap.find(namep);
|
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(namep);
|
||||||
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
|
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
|
||||||
else return NULL;
|
else return NULL;
|
||||||
}
|
}
|
||||||
static void scopeErase(const VerilatedScope* scopep) {
|
static void scopeErase(const VerilatedScope* scopep) {
|
||||||
// Slow ok - called once/scope at destruction
|
// Slow ok - called once/scope at destruction
|
||||||
userEraseScope(scopep);
|
userEraseScope(scopep);
|
||||||
ScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
||||||
}
|
}
|
||||||
static void scopesDump() {
|
static void scopesDump() {
|
||||||
VL_PRINTF(" scopesDump:\n");
|
VL_PRINTF(" scopesDump:\n");
|
||||||
for (ScopeNameMap::iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
for (VerilatedScopeNameMap::iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||||
const VerilatedScope* scopep = it->second;
|
const VerilatedScope* scopep = it->second;
|
||||||
scopep->scopeDump();
|
scopep->scopeDump();
|
||||||
}
|
}
|
||||||
VL_PRINTF("\n");
|
VL_PRINTF("\n");
|
||||||
}
|
}
|
||||||
|
static const VerilatedScopeNameMap* scopeNameMap() {
|
||||||
|
return &s_s.m_nameMap;
|
||||||
|
}
|
||||||
|
|
||||||
public: // But only for verilated*.cpp
|
public: // But only for verilated*.cpp
|
||||||
// METHODS - export names
|
// METHODS - export names
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -201,7 +201,7 @@ void VerilatedRestore::fill() {
|
|||||||
if (VL_UNLIKELY(!isOpen())) return;
|
if (VL_UNLIKELY(!isOpen())) return;
|
||||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||||
vluint8_t* rp = m_bufp;
|
vluint8_t* rp = m_bufp;
|
||||||
for (vluint8_t* sp=m_cp; rp < m_endp;) *rp++ = *sp++; // Overlaps
|
for (vluint8_t* sp=m_cp; sp < m_endp;) *rp++ = *sp++; // Overlaps
|
||||||
m_endp = m_bufp + (m_endp - m_cp);
|
m_endp = m_bufp + (m_endp - m_cp);
|
||||||
m_cp = m_bufp; // Reset buffer
|
m_cp = m_bufp; // Reset buffer
|
||||||
// Read into buffer starting at m_endp
|
// Read into buffer starting at m_endp
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2012-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2012-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -48,6 +48,8 @@ protected:
|
|||||||
m_bufp = new vluint8_t [bufferSize()];
|
m_bufp = new vluint8_t [bufferSize()];
|
||||||
m_cp = m_bufp;
|
m_cp = m_bufp;
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
VerilatedSerialBase(const VerilatedSerialBase& ); ///< N/A, no copy constructor
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
virtual ~VerilatedSerialBase() {
|
virtual ~VerilatedSerialBase() {
|
||||||
@@ -223,7 +225,7 @@ inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
|
|||||||
return os.write(rhs.data(), len);
|
return os.write(rhs.data(), len);
|
||||||
}
|
}
|
||||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
||||||
vluint32_t len;
|
vluint32_t len=0;
|
||||||
os>>len;
|
os>>len;
|
||||||
rhs.resize(len);
|
rhs.resize(len);
|
||||||
return os.read((void*)rhs.data(), len);
|
return os.read((void*)rhs.data(), len);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2009-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+15
-11
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -32,16 +32,6 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
//======================================================================
|
|
||||||
// Types
|
|
||||||
|
|
||||||
struct VerilatedCStrCmp {
|
|
||||||
/// Ordering maps keyed by const char*'s
|
|
||||||
bool operator() (const char *a, const char *b) const {
|
|
||||||
return std::strcmp(a, b) < 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator range
|
/// Verilator range
|
||||||
|
|
||||||
@@ -93,6 +83,20 @@ public:
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
/// Types
|
/// Types
|
||||||
|
|
||||||
|
struct VerilatedCStrCmp {
|
||||||
|
/// Ordering maps keyed by const char*'s
|
||||||
|
bool operator() (const char *a, const char *b) const {
|
||||||
|
return std::strcmp(a, b) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VerilatedScopeNameMap
|
||||||
|
: public map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
||||||
|
public:
|
||||||
|
VerilatedScopeNameMap() {}
|
||||||
|
~VerilatedScopeNameMap() {}
|
||||||
|
};
|
||||||
|
|
||||||
class VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
class VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||||
public:
|
public:
|
||||||
VerilatedVarNameMap() {}
|
VerilatedVarNameMap() {}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -144,13 +144,15 @@ private:
|
|||||||
return out + ((char)((code)%94+33));
|
return out + ((char)((code)%94+33));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VerilatedVcd(const VerilatedVcd& ); ///< N/A, no copy constructor
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// METHODS
|
// METHODS
|
||||||
void evcd(bool flag) { m_evcd = flag; }
|
void evcd(bool flag) { m_evcd = flag; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATORS
|
// CREATORS
|
||||||
VerilatedVcd(VerilatedVcdFile* filep=NULL);
|
explicit VerilatedVcd(VerilatedVcdFile* filep=NULL);
|
||||||
~VerilatedVcd();
|
~VerilatedVcd();
|
||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
@@ -399,7 +401,7 @@ class VerilatedVcdC {
|
|||||||
VerilatedVcd m_sptrace; ///< Trace file being created
|
VerilatedVcd m_sptrace; ///< Trace file being created
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
|
explicit VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
|
||||||
~VerilatedVcdC() {}
|
~VerilatedVcdC() {}
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
/// Is file open?
|
/// Is file open?
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#if (SYSTEMC_VERSION>=20050714)
|
#if (SYSTEMC_VERSION>=20050714)
|
||||||
// SystemC 2.1.v1
|
// SystemC 2.1.v1
|
||||||
|
// cppcheck-suppress unusedFunction
|
||||||
void VerilatedVcdSc::write_comment (const std::string &) {}
|
void VerilatedVcdSc::write_comment (const std::string &) {}
|
||||||
void VerilatedVcdSc::trace (const unsigned int &, const std::string &, const char **) {}
|
void VerilatedVcdSc::trace (const unsigned int &, const std::string &, const char **) {}
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ void VerilatedVcdSc::trace (const unsigned int &, const std::string &, const cha
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#elif (SYSTEMC_VERSION>20011000)
|
#elif (SYSTEMC_VERSION>20011000)
|
||||||
// SystemC 2.0.1
|
// SystemC 2.0.1
|
||||||
|
// cppcheck-suppress unusedFunction
|
||||||
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
||||||
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
||||||
|
|
||||||
@@ -116,6 +118,7 @@ void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
#else
|
#else
|
||||||
// SystemC 1.2.1beta
|
// SystemC 1.2.1beta
|
||||||
|
// cppcheck-suppress unusedFunction
|
||||||
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
||||||
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// THIS MODULE IS PUBLICLY LICENSED
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
//
|
//
|
||||||
// Copyright 2001-2015 by Wilson Snyder. This program is free software;
|
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
//
|
//
|
||||||
|
|||||||
+1043
-1
File diff suppressed because it is too large
Load Diff
+18
-994
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -95,6 +95,12 @@
|
|||||||
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||||
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||||
|
|
||||||
|
#ifdef VL_CPPCHECK
|
||||||
|
# define VL_DANGLING(v)
|
||||||
|
#else
|
||||||
|
# define VL_DANGLING(v) do { (v) = NULL; } while(0) ///< After e.g. delete, set variable to NULL to indicate must not use later
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// C++-2011
|
// C++-2011
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -785,7 +785,7 @@ in C<src/Makefile_obj.in> and reconfigure.
|
|||||||
|
|
||||||
The latest version is available from L<http://www.veripool.org/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2008-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2008-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you
|
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you
|
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2015 by Wilson Snyder. This package is free software; you
|
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||||
# can redistribute it and/or modify it under the terms of either the GNU
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+3
-2
@@ -115,7 +115,8 @@ sub write_verilog {
|
|||||||
|
|
||||||
sub cleanenv {
|
sub cleanenv {
|
||||||
foreach my $var (keys %ENV) {
|
foreach my $var (keys %ENV) {
|
||||||
if ($var eq "VERILATOR_ROOT") {
|
if ($var eq "VERILATOR_ROOT"
|
||||||
|
|| $var eq "VERILATOR_INCLUDE") {
|
||||||
print "unset $var # Was '$ENV{$var}'\n";
|
print "unset $var # Was '$ENV{$var}'\n";
|
||||||
delete $ENV{$var}
|
delete $ENV{$var}
|
||||||
}
|
}
|
||||||
@@ -183,7 +184,7 @@ Runs a specific test stage (see the script).
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2009-2015 by Wilson Snyder. This package is free software; you
|
Copyright 2009-2017 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License Version 3 or the Perl Artistic License
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License Version 3 or the Perl Artistic License
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2007-2015 by Wilson Snyder. This package is free software; you
|
Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License Version 3 or the Perl Artistic License
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License Version 3 or the Perl Artistic License
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License Version 3 or the Perl Artistic License
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
Version 2.0.
|
Version 2.0.
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2015 by Wilson Snyder. Verilator is free software; you can
|
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
|
||||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# DESCRIPTION: Verilator: GDB startup file with useful defines
|
# DESCRIPTION: Verilator: GDB startup file with useful defines
|
||||||
#
|
#
|
||||||
# Copyright 2012-2015 by Wilson Snyder. This program is free software; you can
|
# Copyright 2012-2017 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|||||||
+3
-1
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -46,6 +46,8 @@ obj_opt:
|
|||||||
obj_dbg:
|
obj_dbg:
|
||||||
mkdir $@
|
mkdir $@
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
.PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
|
.PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
|
||||||
|
|
||||||
opt: ../verilator_bin
|
opt: ../verilator_bin
|
||||||
|
|||||||
+7
-2
@@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
@@ -99,6 +99,8 @@ CPPFLAGS += -MP # Only works on recent GCC versions
|
|||||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||||
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
|
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
|
||||||
#CPPFLAGS += -pedantic-errors
|
#CPPFLAGS += -pedantic-errors
|
||||||
|
else
|
||||||
|
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
|
||||||
endif
|
endif
|
||||||
CPPFLAGSWALL = $(CPPFLAGS)
|
CPPFLAGSWALL = $(CPPFLAGS)
|
||||||
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
|
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
|
||||||
@@ -164,6 +166,7 @@ RAW_OBJS = \
|
|||||||
V3Begin.o \
|
V3Begin.o \
|
||||||
V3Branch.o \
|
V3Branch.o \
|
||||||
V3Broken.o \
|
V3Broken.o \
|
||||||
|
V3CCtors.o \
|
||||||
V3Case.o \
|
V3Case.o \
|
||||||
V3Cast.o \
|
V3Cast.o \
|
||||||
V3Cdc.o \
|
V3Cdc.o \
|
||||||
@@ -299,7 +302,7 @@ serial:: V3Ast__gen_classes.h V3ParseBison.c
|
|||||||
|
|
||||||
serial_vlcov:: vlcovgen.d
|
serial_vlcov:: vlcovgen.d
|
||||||
|
|
||||||
vlcovgen.d: $(VLCOVGEN) $(srcdir)/include/verilated_cov_key.h
|
vlcovgen.d: $(VLCOVGEN) $(srcdir)/../include/verilated_cov_key.h
|
||||||
$(PERL) $(VLCOVGEN) --srcdir $(srcdir)
|
$(PERL) $(VLCOVGEN) --srcdir $(srcdir)
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
@@ -327,6 +330,8 @@ V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
|||||||
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
|
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
|
||||||
$(PERL) $(FLEXFIX) V3PreLex <$< >$@
|
$(PERL) $(FLEXFIX) V3PreLex <$< >$@
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|||||||
+35
-33
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -73,7 +73,7 @@ private:
|
|||||||
m_scopep->addActivep(nodep);
|
m_scopep->addActivep(nodep);
|
||||||
}
|
}
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep) {
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
m_iActivep = NULL;
|
m_iActivep = NULL;
|
||||||
m_cActivep = NULL;
|
m_cActivep = NULL;
|
||||||
@@ -81,15 +81,15 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Don't clear scopep, the namer persists beyond this visit
|
// Don't clear scopep, the namer persists beyond this visit
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
virtual void visit(AstSenTree* nodep) {
|
||||||
// Simplify sensitivity list
|
// Simplify sensitivity list
|
||||||
V3Const::constifyExpensiveEdit(nodep); nodep=NULL;
|
V3Const::constifyExpensiveEdit(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
// Empty visitors, speed things up
|
// Empty visitors, speed things up
|
||||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) { }
|
virtual void visit(AstNodeStmt* nodep) { }
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default
|
// Default
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ private:
|
|||||||
AstNode* m_alwaysp; // Always we're under
|
AstNode* m_alwaysp; // Always we're under
|
||||||
AstNode* m_assignp; // In assign
|
AstNode* m_assignp; // In assign
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
virtual void visit(AstAssignDly* nodep) {
|
||||||
if (m_check != CT_SEQ) {
|
if (m_check != CT_SEQ) {
|
||||||
// Convert to a non-delayed assignment
|
// Convert to a non-delayed assignment
|
||||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||||
@@ -184,10 +184,10 @@ private:
|
|||||||
nodep->lhsp()->unlinkFrBack(),
|
nodep->lhsp()->unlinkFrBack(),
|
||||||
nodep->rhsp()->unlinkFrBack());
|
nodep->rhsp()->unlinkFrBack());
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssign* nodep, AstNUser*) {
|
virtual void visit(AstAssign* nodep) {
|
||||||
if (m_check == CT_SEQ) {
|
if (m_check == CT_SEQ) {
|
||||||
AstNode* las = m_assignp;
|
AstNode* las = m_assignp;
|
||||||
m_assignp = nodep;
|
m_assignp = nodep;
|
||||||
@@ -195,7 +195,7 @@ private:
|
|||||||
m_assignp = las;
|
m_assignp = las;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
AstVar* varp=nodep->varp();
|
AstVar* varp=nodep->varp();
|
||||||
if (m_check == CT_SEQ
|
if (m_check == CT_SEQ
|
||||||
&& m_assignp
|
&& m_assignp
|
||||||
@@ -214,7 +214,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -244,7 +244,7 @@ private:
|
|||||||
bool m_itemSequent; // Found a SenItem sequential
|
bool m_itemSequent; // Found a SenItem sequential
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep) {
|
||||||
// Create required actives and add to scope
|
// Create required actives and add to scope
|
||||||
UINFO(4," SCOPE "<<nodep<<endl);
|
UINFO(4," SCOPE "<<nodep<<endl);
|
||||||
// Clear last scope's names, and collect this scope's existing names
|
// Clear last scope's names, and collect this scope's existing names
|
||||||
@@ -252,10 +252,10 @@ private:
|
|||||||
m_scopeFinalp = NULL;
|
m_scopeFinalp = NULL;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
virtual void visit(AstActive* nodep) {
|
||||||
// Actives are being formed, so we can ignore any already made
|
// Actives are being formed, so we can ignore any already made
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
virtual void visit(AstInitial* nodep) {
|
||||||
// Relink to IACTIVE, unless already under it
|
// Relink to IACTIVE, unless already under it
|
||||||
UINFO(4," INITIAL "<<nodep<<endl);
|
UINFO(4," INITIAL "<<nodep<<endl);
|
||||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||||
@@ -263,32 +263,32 @@ private:
|
|||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
virtual void visit(AstAssignAlias* nodep) {
|
||||||
// Relink to CACTIVE, unless already under it
|
// Relink to CACTIVE, unless already under it
|
||||||
UINFO(4," ASSIGNW "<<nodep<<endl);
|
UINFO(4," ASSIGNW "<<nodep<<endl);
|
||||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
virtual void visit(AstAssignW* nodep) {
|
||||||
// Relink to CACTIVE, unless already under it
|
// Relink to CACTIVE, unless already under it
|
||||||
UINFO(4," ASSIGNW "<<nodep<<endl);
|
UINFO(4," ASSIGNW "<<nodep<<endl);
|
||||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
virtual void visit(AstCoverToggle* nodep) {
|
||||||
// Relink to CACTIVE, unless already under it
|
// Relink to CACTIVE, unless already under it
|
||||||
UINFO(4," COVERTOGGLE "<<nodep<<endl);
|
UINFO(4," COVERTOGGLE "<<nodep<<endl);
|
||||||
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
virtual void visit(AstFinal* nodep) {
|
||||||
// Relink to CFUNC for the final
|
// Relink to CFUNC for the final
|
||||||
UINFO(4," FINAL "<<nodep<<endl);
|
UINFO(4," FINAL "<<nodep<<endl);
|
||||||
if (!nodep->bodysp()) { // Empty, Kill it.
|
if (!nodep->bodysp()) { // Empty, Kill it.
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||||
@@ -304,7 +304,7 @@ private:
|
|||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName()));
|
m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName()));
|
||||||
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
|
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -316,7 +316,7 @@ private:
|
|||||||
&& oldsensesp->sensesp()->castSenItem()->isNever()) {
|
&& oldsensesp->sensesp()->castSenItem()->isNever()) {
|
||||||
// Never executing. Kill it.
|
// Never executing. Kill it.
|
||||||
if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +329,9 @@ private:
|
|||||||
|
|
||||||
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
||||||
if (combo && sequent) {
|
if (combo && sequent) {
|
||||||
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
|
if (!v3Global.opt.bboxUnsup()) {
|
||||||
|
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
|
||||||
|
}
|
||||||
sequent = false;
|
sequent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +353,7 @@ private:
|
|||||||
|
|
||||||
// Delete sensitivity list
|
// Delete sensitivity list
|
||||||
if (oldsensesp) {
|
if (oldsensesp) {
|
||||||
oldsensesp->unlinkFrBackWithNext()->deleteTree(); oldsensesp=NULL;
|
oldsensesp->unlinkFrBackWithNext()->deleteTree(); VL_DANGLING(oldsensesp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move node to new active
|
// Move node to new active
|
||||||
@@ -370,25 +372,25 @@ private:
|
|||||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
|
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep) {
|
||||||
// Move always to appropriate ACTIVE based on its sense list
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
UINFO(4," ALW "<<nodep<<endl);
|
UINFO(4," ALW "<<nodep<<endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||||
|
|
||||||
if (!nodep->bodysp()) {
|
if (!nodep->bodysp()) {
|
||||||
// Empty always. Kill it.
|
// Empty always. Kill it.
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
virtual void visit(AstAlwaysPublic* nodep) {
|
||||||
// Move always to appropriate ACTIVE based on its sense list
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
UINFO(4," ALWPub "<<nodep<<endl);
|
UINFO(4," ALWPub "<<nodep<<endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||||
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
|
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
virtual void visit(AstSenGate* nodep) {
|
||||||
AstSenItem* subitemp = nodep->sensesp();
|
AstSenItem* subitemp = nodep->sensesp();
|
||||||
if (subitemp->edgeType() != AstEdgeType::ET_ANYEDGE
|
if (subitemp->edgeType() != AstEdgeType::ET_ANYEDGE
|
||||||
&& subitemp->edgeType() != AstEdgeType::ET_POSEDGE
|
&& subitemp->edgeType() != AstEdgeType::ET_POSEDGE
|
||||||
@@ -397,12 +399,12 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep) {
|
||||||
if (nodep->edgeType() == AstEdgeType::ET_ANYEDGE) {
|
if (nodep->edgeType() == AstEdgeType::ET_ANYEDGE) {
|
||||||
m_itemCombo = true;
|
m_itemCombo = true;
|
||||||
// Delete the sensitivity
|
// Delete the sensitivity
|
||||||
// We'll add it as a generic COMBO SenItem in a moment.
|
// We'll add it as a generic COMBO SenItem in a moment.
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
} else if (nodep->varrefp()) {
|
} else if (nodep->varrefp()) {
|
||||||
// V3LinkResolve should have cleaned most of these up
|
// V3LinkResolve should have cleaned most of these up
|
||||||
if (!nodep->varrefp()->width1()) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
if (!nodep->varrefp()->width1()) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||||
@@ -413,15 +415,15 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Empty visitors, speed things up
|
// Empty visitors, speed things up
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
virtual void visit(AstNodeMath* nodep) {}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {}
|
virtual void visit(AstVarScope* nodep) {}
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveVisitor(AstNetlist* nodep) {
|
explicit ActiveVisitor(AstNetlist* nodep) {
|
||||||
m_scopeFinalp = NULL;
|
m_scopeFinalp = NULL;
|
||||||
m_itemCombo = false;
|
m_itemCombo = false;
|
||||||
m_itemSequent = false;
|
m_itemSequent = false;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+15
-15
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -65,19 +65,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
virtual void visit(AstTopScope* nodep) {
|
||||||
m_topscopep = nodep;
|
m_topscopep = nodep;
|
||||||
m_finder.main(m_topscopep);
|
m_finder.main(m_topscopep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_topscopep = NULL;
|
m_topscopep = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
// Create required actives and add to module
|
// Create required actives and add to module
|
||||||
// We can start ordering at a module, or a scope
|
// We can start ordering at a module, or a scope
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
virtual void visit(AstActive* nodep) {
|
||||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||||
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
|
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
|
||||||
AstSenTree* sensesp = nodep->sensesp();
|
AstSenTree* sensesp = nodep->sensesp();
|
||||||
@@ -87,7 +87,7 @@ private:
|
|||||||
&& sensesp->sensesp()->castSenItem()->isNever()) {
|
&& sensesp->sensesp()->castSenItem()->isNever()) {
|
||||||
// Never executing. Kill it.
|
// Never executing. Kill it.
|
||||||
if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Copy combo tree to settlement tree with duplicated statements
|
// Copy combo tree to settlement tree with duplicated statements
|
||||||
@@ -120,34 +120,34 @@ private:
|
|||||||
// No need to do statements under it, they're already moved.
|
// No need to do statements under it, they're already moved.
|
||||||
//nodep->iterateChildren(*this);
|
//nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
virtual void visit(AstInitial* nodep) {
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
virtual void visit(AstAssignAlias* nodep) {
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
virtual void visit(AstAssignW* nodep) {
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep) {
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
virtual void visit(AstAlwaysPublic* nodep) {
|
||||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||||
}
|
}
|
||||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
virtual void visit(AstFinal* nodep) {
|
||||||
nodep->v3fatalSrc("Node should have been deleted");
|
nodep->v3fatalSrc("Node should have been deleted");
|
||||||
}
|
}
|
||||||
// Empty visitors, speed things up
|
// Empty visitors, speed things up
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
virtual void visit(AstNodeMath* nodep) {}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {}
|
virtual void visit(AstVarScope* nodep) {}
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveTopVisitor(AstNetlist* nodep) {
|
explicit ActiveTopVisitor(AstNetlist* nodep) {
|
||||||
m_topscopep = NULL;
|
m_topscopep = NULL;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+38
-21
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -138,7 +138,7 @@ private:
|
|||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
}
|
}
|
||||||
// Bye
|
// Bye
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void newVAssertion(AstVAssert* nodep, AstNode* propp) {
|
void newVAssertion(AstVAssert* nodep, AstNode* propp) {
|
||||||
@@ -160,10 +160,10 @@ private:
|
|||||||
// Install it
|
// Install it
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
// Bye
|
// Bye
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstIf* nodep, AstNUser*) {
|
virtual void visit(AstIf* nodep) {
|
||||||
if (nodep->user1SetOnce()) return;
|
if (nodep->user1SetOnce()) return;
|
||||||
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||||
AstNodeIf* ifp = nodep;
|
AstNodeIf* ifp = nodep;
|
||||||
@@ -205,8 +205,8 @@ private:
|
|||||||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||||
// predicates evaluates to true.
|
// predicates evaluates to true.
|
||||||
AstNode* ohot = ((allow_none || hasDefaultElse)
|
AstNode* ohot = ((allow_none || hasDefaultElse)
|
||||||
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||||
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
: static_cast<AstNode*>(new AstOneHot (nodep->fileline(), propp)));
|
||||||
AstIf* checkifp = new AstIf (nodep->fileline(),
|
AstIf* checkifp = new AstIf (nodep->fileline(),
|
||||||
new AstLogNot (nodep->fileline(), ohot),
|
new AstLogNot (nodep->fileline(), ohot),
|
||||||
newFireAssert(nodep, "'unique if' statement violated"),
|
newFireAssert(nodep, "'unique if' statement violated"),
|
||||||
@@ -220,7 +220,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Case assertions
|
// VISITORS //========== Case assertions
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->user1SetOnce()) {
|
if (!nodep->user1SetOnce()) {
|
||||||
bool has_default=false;
|
bool has_default=false;
|
||||||
@@ -245,17 +245,34 @@ private:
|
|||||||
AstNode* propp = NULL;
|
AstNode* propp = NULL;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||||
AstNode* onep = new AstEq(icondp->fileline(),
|
AstNode* onep;
|
||||||
nodep->exprp()->cloneTree(false),
|
AstConst* iconstp = icondp->castConst();
|
||||||
icondp->cloneTree(false));
|
if (iconstp && iconstp->num().isFourState()
|
||||||
|
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
|
||||||
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
|
nummask.opBitsNonX(iconstp->num());
|
||||||
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
|
numval.opBitsOne(iconstp->num());
|
||||||
|
AstNode* and1p = new AstAnd(itemp->fileline(), nodep->exprp()->cloneTree(false),
|
||||||
|
new AstConst(itemp->fileline(), nummask));
|
||||||
|
AstNode* and2p = new AstAnd(itemp->fileline(),
|
||||||
|
new AstConst(itemp->fileline(), numval),
|
||||||
|
new AstConst(itemp->fileline(), nummask));
|
||||||
|
onep = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
onep = AstEq::newTyped(icondp->fileline(),
|
||||||
|
nodep->exprp()->cloneTree(false),
|
||||||
|
icondp->cloneTree(false));
|
||||||
|
}
|
||||||
if (propp) propp = new AstConcat(icondp->fileline(), onep, propp);
|
if (propp) propp = new AstConcat(icondp->fileline(), onep, propp);
|
||||||
else propp = onep;
|
else propp = onep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool allow_none = has_default || nodep->unique0Pragma();
|
bool allow_none = has_default || nodep->unique0Pragma();
|
||||||
AstNode* ohot = (allow_none
|
AstNode* ohot = (allow_none
|
||||||
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||||
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
: static_cast<AstNode*>(new AstOneHot (nodep->fileline(), propp)));
|
||||||
AstIf* ifp = new AstIf (nodep->fileline(),
|
AstIf* ifp = new AstIf (nodep->fileline(),
|
||||||
new AstLogNot (nodep->fileline(), ohot),
|
new AstLogNot (nodep->fileline(), ohot),
|
||||||
newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"),
|
newFireAssert(nodep, "synthesis parallel_case, but multiple matches found"),
|
||||||
@@ -268,7 +285,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
// VISITORS //========== Statements
|
||||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
virtual void visit(AstDisplay* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Replace the special types with standard text
|
// Replace the special types with standard text
|
||||||
if (nodep->displayType()==AstDisplayType::DT_INFO) {
|
if (nodep->displayType()==AstDisplayType::DT_INFO) {
|
||||||
@@ -281,27 +298,27 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep);
|
||||||
++m_statAsCover;
|
++m_statAsCover;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
virtual void visit(AstVAssert* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
newVAssertion(nodep, nodep->propp()); VL_DANGLING(nodep);
|
||||||
++m_statAsSV;
|
++m_statAsSV;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
//
|
//
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Reset defaults
|
// Reset defaults
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
virtual void visit(AstBegin* nodep) {
|
||||||
// This code is needed rather than a visitor in V3Begin,
|
// This code is needed rather than a visitor in V3Begin,
|
||||||
// because V3Assert is called before V3Begin
|
// because V3Assert is called before V3Begin
|
||||||
AstBegin* lastp = m_beginp;
|
AstBegin* lastp = m_beginp;
|
||||||
@@ -312,12 +329,12 @@ private:
|
|||||||
m_beginp = lastp;
|
m_beginp = lastp;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AssertVisitor(AstNetlist* nodep) {
|
explicit AssertVisitor(AstNetlist* nodep) {
|
||||||
m_beginp = NULL;
|
m_beginp = NULL;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
// Process
|
// Process
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+9
-9
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -73,7 +73,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
// VISITORS //========== Statements
|
||||||
virtual void visit(AstClocking* nodep, AstNUser*) {
|
virtual void visit(AstClocking* nodep) {
|
||||||
UINFO(8," CLOCKING"<<nodep<<endl);
|
UINFO(8," CLOCKING"<<nodep<<endl);
|
||||||
// Store the new default clock, reset on new module
|
// Store the new default clock, reset on new module
|
||||||
m_seniDefaultp = nodep->sensesp();
|
m_seniDefaultp = nodep->sensesp();
|
||||||
@@ -83,17 +83,17 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
}
|
}
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep) {
|
||||||
if (nodep->sentreep()) return; // Already processed
|
if (nodep->sentreep()) return; // Already processed
|
||||||
clearAssertInfo();
|
clearAssertInfo();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
clearAssertInfo();
|
clearAssertInfo();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
virtual void visit(AstPslClocked* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_senip) {
|
if (m_senip) {
|
||||||
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
|
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
|
||||||
@@ -109,20 +109,20 @@ private:
|
|||||||
// Unlink and just keep a pointer to it, convert to sentree as needed
|
// Unlink and just keep a pointer to it, convert to sentree as needed
|
||||||
m_senip = nodep->sensesp();
|
m_senip = nodep->sensesp();
|
||||||
nodep->replaceWith(blockp);
|
nodep->replaceWith(blockp);
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Reset defaults
|
// Reset defaults
|
||||||
m_seniDefaultp = NULL;
|
m_seniDefaultp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AssertPreVisitor(AstNetlist* nodep) {
|
explicit AssertPreVisitor(AstNetlist* nodep) {
|
||||||
m_seniDefaultp = NULL;
|
m_seniDefaultp = NULL;
|
||||||
clearAssertInfo();
|
clearAssertInfo();
|
||||||
// Process
|
// Process
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+160
-140
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "V3File.h"
|
#include "V3File.h"
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Broken.h"
|
#include "V3Broken.h"
|
||||||
|
#include "V3String.h"
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Statics
|
// Statics
|
||||||
@@ -79,30 +80,30 @@ void AstNode::init() {
|
|||||||
// Attributes
|
// Attributes
|
||||||
m_didWidth = false;
|
m_didWidth = false;
|
||||||
m_doingWidth = false;
|
m_doingWidth = false;
|
||||||
m_user1p = NULL;
|
m_user1u = VNUser(0);
|
||||||
m_user1Cnt = 0;
|
m_user1Cnt = 0;
|
||||||
m_user2p = NULL;
|
m_user2u = VNUser(0);
|
||||||
m_user2Cnt = 0;
|
m_user2Cnt = 0;
|
||||||
m_user3p = NULL;
|
m_user3u = VNUser(0);
|
||||||
m_user3Cnt = 0;
|
m_user3Cnt = 0;
|
||||||
m_user4p = NULL;
|
m_user4u = VNUser(0);
|
||||||
m_user4Cnt = 0;
|
m_user4Cnt = 0;
|
||||||
m_user5p = NULL;
|
m_user5u = VNUser(0);
|
||||||
m_user5Cnt = 0;
|
m_user5Cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstNode::encodeName(const string& namein) {
|
string AstNode::encodeName(const string& namein) {
|
||||||
// Encode signal name raw from parser, then not called again on same signal
|
// Encode signal name raw from parser, then not called again on same signal
|
||||||
const char* start = namein.c_str();
|
|
||||||
string out;
|
string out;
|
||||||
for (const char* pos = start; *pos; pos++) {
|
for (string::const_iterator pos = namein.begin(); pos!=namein.end(); ++pos) {
|
||||||
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers
|
if ((pos==namein.begin()) ? isalpha(pos[0]) // digits can't lead identifiers
|
||||||
: isalnum(pos[0])) {
|
: isalnum(pos[0])) {
|
||||||
out += pos[0];
|
out += pos[0];
|
||||||
} else if (pos[0]=='_') {
|
} else if (pos[0]=='_') {
|
||||||
if (pos[1]=='_') {
|
if (pos[1]=='_') {
|
||||||
out += "_"; out += "__05F"; // hex(_) = 0x5F
|
out += "_"; out += "__05F"; // hex(_) = 0x5F
|
||||||
pos++;
|
++pos;
|
||||||
|
if (pos==namein.end()) break;
|
||||||
} else {
|
} else {
|
||||||
out += pos[0];
|
out += pos[0];
|
||||||
}
|
}
|
||||||
@@ -115,6 +116,10 @@ string AstNode::encodeName(const string& namein) {
|
|||||||
out += hex;
|
out += hex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Shorten names
|
||||||
|
// TODO long term use VName in place of "string name"
|
||||||
|
VName vname(out);
|
||||||
|
out = vname.hashedName();
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,44 +166,53 @@ string AstNode::vcdName(const string& namein) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string AstNode::prettyName(const string& namein) {
|
string AstNode::prettyName(const string& namein) {
|
||||||
|
// This function is somewhat hot, so we short-circuit some compares
|
||||||
string pretty;
|
string pretty;
|
||||||
pretty = "";
|
pretty = "";
|
||||||
|
pretty.reserve(namein.length());
|
||||||
for (const char* pos = namein.c_str(); *pos; ) {
|
for (const char* pos = namein.c_str(); *pos; ) {
|
||||||
if (0==strncmp(pos,"__BRA__",7)) {
|
if (pos[0]=='-' && pos[1]=='>') { // ->
|
||||||
pretty += "[";
|
|
||||||
pos += 7;
|
|
||||||
}
|
|
||||||
else if (0==strncmp(pos,"__KET__",7)) {
|
|
||||||
pretty += "]";
|
|
||||||
pos += 7;
|
|
||||||
}
|
|
||||||
else if (0==strncmp(pos,"__DOT__",7)) {
|
|
||||||
pretty += ".";
|
|
||||||
pos += 7;
|
|
||||||
}
|
|
||||||
else if (0==strncmp(pos,"->",2)) {
|
|
||||||
pretty += ".";
|
pretty += ".";
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (0==strncmp(pos,"__PVT__",7)) {
|
if (pos[0]=='_' && pos[1]=='_') { // Short-circuit
|
||||||
pretty += "";
|
if (0==strncmp(pos,"__BRA__",7)) {
|
||||||
pos += 7;
|
pretty += "[";
|
||||||
}
|
pos += 7;
|
||||||
else if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0'
|
continue;
|
||||||
&& isxdigit(pos[3]) && isxdigit(pos[4])) {
|
}
|
||||||
char value = 0;
|
if (0==strncmp(pos,"__KET__",7)) {
|
||||||
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
|
pretty += "]";
|
||||||
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10));
|
pos += 7;
|
||||||
pretty += value;
|
continue;
|
||||||
pos += 5;
|
}
|
||||||
}
|
if (0==strncmp(pos,"__DOT__",7)) {
|
||||||
else {
|
pretty += ".";
|
||||||
pretty += pos[0];
|
pos += 7;
|
||||||
pos++;
|
continue;
|
||||||
|
}
|
||||||
|
if (0==strncmp(pos,"__PVT__",7)) {
|
||||||
|
pretty += "";
|
||||||
|
pos += 7;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0'
|
||||||
|
&& isxdigit(pos[3]) && isxdigit(pos[4])) {
|
||||||
|
char value = 0;
|
||||||
|
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
|
||||||
|
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10));
|
||||||
|
pretty += value;
|
||||||
|
pos += 5;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Default
|
||||||
|
pretty += pos[0];
|
||||||
|
++pos;
|
||||||
}
|
}
|
||||||
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
if (pretty[0]=='T' && pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||||
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
if (pretty[0]=='T' && pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
||||||
return pretty;
|
return pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,20 +244,20 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::addNext(AstNode* newp) {
|
AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) {
|
||||||
// Add to m_nextp, returns this
|
// Add to m_nextp, returns this
|
||||||
UASSERT(newp,"Null item passed to addNext\n");
|
UDEBUGONLY(if (!newp) nodep->v3fatalSrc("Null item passed to addNext"););
|
||||||
this->debugTreeChange("-addNextThs: ", __LINE__, false);
|
nodep->debugTreeChange("-addNextThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-addNextNew: ", __LINE__, true);
|
newp->debugTreeChange("-addNextNew: ", __LINE__, true);
|
||||||
if (this == NULL) {
|
if (!nodep) { // verilog.y and lots of other places assume this
|
||||||
return (newp);
|
return (newp);
|
||||||
} else {
|
} else {
|
||||||
// Find end of old list
|
// Find end of old list
|
||||||
AstNode* oldtailp = this;
|
AstNode* oldtailp = nodep;
|
||||||
if (oldtailp->m_nextp) {
|
if (oldtailp->m_nextp) {
|
||||||
if (oldtailp->m_headtailp) {
|
if (oldtailp->m_headtailp) {
|
||||||
oldtailp = oldtailp->m_headtailp; // This=beginning of list, jump to end
|
oldtailp = oldtailp->m_headtailp; // This=beginning of list, jump to end
|
||||||
UASSERT(!oldtailp->m_nextp, "Node had next, but headtail says it shouldn't");
|
UDEBUGONLY(if (oldtailp->m_nextp) nodep->v3fatalSrc("Node had next, but headtail says it shouldn't"););
|
||||||
} else {
|
} else {
|
||||||
// Though inefficent, we are occasionally passed a addNext in the middle of a list.
|
// Though inefficent, we are occasionally passed a addNext in the middle of a list.
|
||||||
while (oldtailp->m_nextp != NULL) oldtailp = oldtailp->m_nextp;
|
while (oldtailp->m_nextp != NULL) oldtailp = oldtailp->m_nextp;
|
||||||
@@ -262,21 +276,21 @@ AstNode* AstNode::addNext(AstNode* newp) {
|
|||||||
newp->editCountInc();
|
newp->editCountInc();
|
||||||
if (oldtailp->m_iterpp) *(oldtailp->m_iterpp) = newp; // Iterate on new item
|
if (oldtailp->m_iterpp) *(oldtailp->m_iterpp) = newp; // Iterate on new item
|
||||||
}
|
}
|
||||||
this->debugTreeChange("-addNextOut:", __LINE__, true);
|
nodep->debugTreeChange("-addNextOut:", __LINE__, true);
|
||||||
return this;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::addNextNull(AstNode* newp) {
|
AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) {
|
||||||
if (!newp) return this;
|
if (!newp) return nodep;
|
||||||
return addNext(newp);
|
return addNext(nodep, newp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::addNextHere(AstNode* newp) {
|
void AstNode::addNextHere(AstNode* newp) {
|
||||||
// Add to m_nextp on exact node passed, not at the end.
|
// Add to m_nextp on exact node passed, not at the end.
|
||||||
// This could be at head, tail, or both (single)
|
// This could be at head, tail, or both (single)
|
||||||
// New could be head of single node, or list
|
// New could be head of single node, or list
|
||||||
|
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
|
||||||
UASSERT(newp,"Null item passed to addNext");
|
UASSERT(newp,"Null item passed to addNext");
|
||||||
UASSERT(this,"Null base node");
|
|
||||||
UASSERT(newp->backp()==NULL,"New node (back) already assigned?");
|
UASSERT(newp->backp()==NULL,"New node (back) already assigned?");
|
||||||
this->debugTreeChange("-addHereThs: ", __LINE__, false);
|
this->debugTreeChange("-addHereThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-addHereNew: ", __LINE__, true);
|
newp->debugTreeChange("-addHereNew: ", __LINE__, true);
|
||||||
@@ -600,12 +614,12 @@ void AstNode::swapWith (AstNode* bp) {
|
|||||||
// Clone
|
// Clone
|
||||||
|
|
||||||
AstNode* AstNode::cloneTreeIter() {
|
AstNode* AstNode::cloneTreeIter() {
|
||||||
if (!this) return NULL;
|
// private: Clone single node and children
|
||||||
AstNode* newp = this->clone();
|
AstNode* newp = this->clone();
|
||||||
newp->op1p(this->m_op1p->cloneTreeIterList());
|
if (this->m_op1p) newp->op1p(this->m_op1p->cloneTreeIterList());
|
||||||
newp->op2p(this->m_op2p->cloneTreeIterList());
|
if (this->m_op2p) newp->op2p(this->m_op2p->cloneTreeIterList());
|
||||||
newp->op3p(this->m_op3p->cloneTreeIterList());
|
if (this->m_op3p) newp->op3p(this->m_op3p->cloneTreeIterList());
|
||||||
newp->op4p(this->m_op4p->cloneTreeIterList());
|
if (this->m_op4p) newp->op4p(this->m_op4p->cloneTreeIterList());
|
||||||
newp->m_iterpp = NULL;
|
newp->m_iterpp = NULL;
|
||||||
newp->clonep(this); // Save pointers to/from both to simplify relinking.
|
newp->clonep(this); // Save pointers to/from both to simplify relinking.
|
||||||
this->clonep(newp); // Save pointers to/from both to simplify relinking.
|
this->clonep(newp); // Save pointers to/from both to simplify relinking.
|
||||||
@@ -613,10 +627,10 @@ AstNode* AstNode::cloneTreeIter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::cloneTreeIterList() {
|
AstNode* AstNode::cloneTreeIterList() {
|
||||||
// Clone list of nodes, set m_headtailp
|
// private: Clone list of nodes, set m_headtailp
|
||||||
if (!this) return NULL;
|
|
||||||
AstNode* newheadp = NULL;
|
AstNode* newheadp = NULL;
|
||||||
AstNode* newtailp = NULL;
|
AstNode* newtailp = NULL;
|
||||||
|
// Audited to make sure this is never NULL
|
||||||
for (AstNode* oldp = this; oldp; oldp=oldp->m_nextp) {
|
for (AstNode* oldp = this; oldp; oldp=oldp->m_nextp) {
|
||||||
AstNode* newp = oldp->cloneTreeIter();
|
AstNode* newp = oldp->cloneTreeIter();
|
||||||
newp->m_headtailp = NULL;
|
newp->m_headtailp = NULL;
|
||||||
@@ -631,7 +645,7 @@ AstNode* AstNode::cloneTreeIterList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::cloneTree(bool cloneNextLink) {
|
AstNode* AstNode::cloneTree(bool cloneNextLink) {
|
||||||
if (!this) return NULL;
|
if (!this) return NULL; // verilog.y relies on this
|
||||||
this->debugTreeChange("-cloneThs: ", __LINE__, cloneNextLink);
|
this->debugTreeChange("-cloneThs: ", __LINE__, cloneNextLink);
|
||||||
cloneClearTree();
|
cloneClearTree();
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
@@ -652,7 +666,7 @@ AstNode* AstNode::cloneTree(bool cloneNextLink) {
|
|||||||
// Delete
|
// Delete
|
||||||
|
|
||||||
void AstNode::deleteNode() {
|
void AstNode::deleteNode() {
|
||||||
if (!this) return;
|
// private: Delete single node. Publicly call deleteTree() instead.
|
||||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||||
editCountInc();
|
editCountInc();
|
||||||
// Change links of old node so we coredump if used
|
// Change links of old node so we coredump if used
|
||||||
@@ -672,14 +686,15 @@ AstNode::~AstNode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::deleteTreeIter() {
|
void AstNode::deleteTreeIter() {
|
||||||
if (!this) return;
|
// private: Delete list of nodes. Publicly call deleteTree() instead.
|
||||||
|
// Audited to make sure this is never NULL
|
||||||
for (AstNode* nodep=this, *nnextp; nodep; nodep=nnextp) {
|
for (AstNode* nodep=this, *nnextp; nodep; nodep=nnextp) {
|
||||||
nnextp = nodep->m_nextp;
|
nnextp = nodep->m_nextp;
|
||||||
// MUST be depth first!
|
// MUST be depth first!
|
||||||
nodep->m_op1p->deleteTreeIter();
|
if (nodep->m_op1p) nodep->m_op1p->deleteTreeIter();
|
||||||
nodep->m_op2p->deleteTreeIter();
|
if (nodep->m_op2p) nodep->m_op2p->deleteTreeIter();
|
||||||
nodep->m_op3p->deleteTreeIter();
|
if (nodep->m_op3p) nodep->m_op3p->deleteTreeIter();
|
||||||
nodep->m_op4p->deleteTreeIter();
|
if (nodep->m_op4p) nodep->m_op4p->deleteTreeIter();
|
||||||
nodep->m_nextp = NULL;
|
nodep->m_nextp = NULL;
|
||||||
nodep->m_backp = NULL;
|
nodep->m_backp = NULL;
|
||||||
nodep->deleteNode();
|
nodep->deleteNode();
|
||||||
@@ -689,7 +704,6 @@ void AstNode::deleteTreeIter() {
|
|||||||
void AstNode::deleteTree() {
|
void AstNode::deleteTree() {
|
||||||
// deleteTree always deletes the next link, because you must have called
|
// deleteTree always deletes the next link, because you must have called
|
||||||
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
|
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
|
||||||
if (!this) return;
|
|
||||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||||
this->debugTreeChange("-delTree: ", __LINE__, true);
|
this->debugTreeChange("-delTree: ", __LINE__, true);
|
||||||
this->editCountInc();
|
this->editCountInc();
|
||||||
@@ -718,53 +732,48 @@ void AstNode::operator delete(void* objp, size_t size) {
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Iterators
|
// Iterators
|
||||||
|
|
||||||
void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateChildren(AstNVisitor& v) {
|
||||||
// This is a very hot function
|
// This is a very hot function
|
||||||
if (!this) return;
|
|
||||||
ASTNODE_PREFETCH(m_op1p);
|
ASTNODE_PREFETCH(m_op1p);
|
||||||
ASTNODE_PREFETCH(m_op2p);
|
ASTNODE_PREFETCH(m_op2p);
|
||||||
ASTNODE_PREFETCH(m_op3p);
|
ASTNODE_PREFETCH(m_op3p);
|
||||||
ASTNODE_PREFETCH(m_op4p);
|
ASTNODE_PREFETCH(m_op4p);
|
||||||
// if () not needed since iterateAndNext accepts null this, but faster with it.
|
if (m_op1p) m_op1p->iterateAndNext(v);
|
||||||
if (m_op1p) m_op1p->iterateAndNext(v, vup);
|
if (m_op2p) m_op2p->iterateAndNext(v);
|
||||||
if (m_op2p) m_op2p->iterateAndNext(v, vup);
|
if (m_op3p) m_op3p->iterateAndNext(v);
|
||||||
if (m_op3p) m_op3p->iterateAndNext(v, vup);
|
if (m_op4p) m_op4p->iterateAndNext(v);
|
||||||
if (m_op4p) m_op4p->iterateAndNext(v, vup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateChildrenConst(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateChildrenConst(AstNVisitor& v) {
|
||||||
// This is a very hot function
|
// This is a very hot function
|
||||||
if (!this) return;
|
|
||||||
ASTNODE_PREFETCH(m_op1p);
|
ASTNODE_PREFETCH(m_op1p);
|
||||||
ASTNODE_PREFETCH(m_op2p);
|
ASTNODE_PREFETCH(m_op2p);
|
||||||
ASTNODE_PREFETCH(m_op3p);
|
ASTNODE_PREFETCH(m_op3p);
|
||||||
ASTNODE_PREFETCH(m_op4p);
|
ASTNODE_PREFETCH(m_op4p);
|
||||||
// if () not needed since iterateAndNext accepts null this, but faster with it.
|
if (m_op1p) m_op1p->iterateAndNextConst(v);
|
||||||
if (m_op1p) m_op1p->iterateAndNextConst(v, vup);
|
if (m_op2p) m_op2p->iterateAndNextConst(v);
|
||||||
if (m_op2p) m_op2p->iterateAndNextConst(v, vup);
|
if (m_op3p) m_op3p->iterateAndNextConst(v);
|
||||||
if (m_op3p) m_op3p->iterateAndNextConst(v, vup);
|
if (m_op4p) m_op4p->iterateAndNextConst(v);
|
||||||
if (m_op4p) m_op4p->iterateAndNextConst(v, vup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateAndNext(AstNVisitor& v) {
|
||||||
// This is a very hot function
|
// This is a very hot function
|
||||||
// IMPORTANT: If you replace a node that's the target of this iterator,
|
// IMPORTANT: If you replace a node that's the target of this iterator,
|
||||||
// then the NEW node will be iterated on next, it isn't skipped!
|
// then the NEW node will be iterated on next, it isn't skipped!
|
||||||
// if (!this) return; // Part of for()
|
|
||||||
// Future versions of this function may require the node to have a back to be iterated;
|
// Future versions of this function may require the node to have a back to be iterated;
|
||||||
// there's no lower level reason yet though the back must exist.
|
// there's no lower level reason yet though the back must exist.
|
||||||
AstNode* nodep=this;
|
AstNode* nodep=this;
|
||||||
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
|
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
|
||||||
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||||
#endif
|
#endif
|
||||||
while (nodep) {
|
while (nodep) { // effectively: if (!this) return; // Callers rely on this
|
||||||
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
||||||
ASTNODE_PREFETCH(nodep->m_nextp);
|
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||||
// Desirable check, but many places where multiple iterations are OK
|
// Desirable check, but many places where multiple iterations are OK
|
||||||
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
|
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
|
||||||
// cppcheck-suppress nullPointer
|
// cppcheck-suppress nullPointer
|
||||||
niterp->m_iterpp = &niterp;
|
niterp->m_iterpp = &niterp;
|
||||||
niterp->accept(v, vup);
|
niterp->accept(v);
|
||||||
// accept may do a replaceNode and change niterp on us...
|
// accept may do a replaceNode and change niterp on us...
|
||||||
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
|
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
|
||||||
if (!niterp) return; // Perhaps node deleted inside accept
|
if (!niterp) return; // Perhaps node deleted inside accept
|
||||||
@@ -777,38 +786,37 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateListBackwards(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateListBackwards(AstNVisitor& v) {
|
||||||
if (!this) return;
|
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
|
||||||
AstNode* nodep=this;
|
AstNode* nodep=this;
|
||||||
while (nodep->m_nextp) nodep=nodep->m_nextp;
|
while (nodep->m_nextp) nodep=nodep->m_nextp;
|
||||||
while (nodep) {
|
while (nodep) {
|
||||||
// Edits not supported: nodep->m_iterpp = &nodep;
|
// Edits not supported: nodep->m_iterpp = &nodep;
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v);
|
||||||
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
|
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
|
||||||
else nodep = NULL; // else: backp points up the tree.
|
else nodep = NULL; // else: backp points up the tree.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateChildrenBackwards(AstNVisitor& v) {
|
||||||
if (!this) return;
|
if (m_op1p) m_op1p->iterateListBackwards(v);
|
||||||
this->op1p()->iterateListBackwards(v,vup);
|
if (m_op2p) m_op2p->iterateListBackwards(v);
|
||||||
this->op2p()->iterateListBackwards(v,vup);
|
if (m_op3p) m_op3p->iterateListBackwards(v);
|
||||||
this->op3p()->iterateListBackwards(v,vup);
|
if (m_op4p) m_op4p->iterateListBackwards(v);
|
||||||
this->op4p()->iterateListBackwards(v,vup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateAndNextConst(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateAndNextConst(AstNVisitor& v) {
|
||||||
// Keep following the current list even if edits change it
|
// Keep following the current list even if edits change it
|
||||||
if (!this) return;
|
if (!this) return; // A few cases could be cleaned up, but want symmetry with iterateAndNext
|
||||||
for (AstNode* nodep=this; nodep; ) {
|
for (AstNode* nodep=this; nodep; ) { // effectively: if (!this) return; // Callers rely on this
|
||||||
AstNode* nnextp = nodep->m_nextp;
|
AstNode* nnextp = nodep->m_nextp;
|
||||||
ASTNODE_PREFETCH(nnextp);
|
ASTNODE_PREFETCH(nnextp);
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v);
|
||||||
nodep = nnextp;
|
nodep = nnextp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) {
|
||||||
// Some visitors perform tree edits (such as V3Const), and may even
|
// Some visitors perform tree edits (such as V3Const), and may even
|
||||||
// replace/delete the exact nodep that the visitor is called with. If
|
// replace/delete the exact nodep that the visitor is called with. If
|
||||||
// this happens, the parent will lose the handle to the node that was
|
// this happens, the parent will lose the handle to the node that was
|
||||||
@@ -818,15 +826,15 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
|||||||
AstNode* nodep = this; // Note "this" may point to bogus point later in this function
|
AstNode* nodep = this; // Note "this" may point to bogus point later in this function
|
||||||
if (nodep->castNetlist()) {
|
if (nodep->castNetlist()) {
|
||||||
// Calling on top level; we know the netlist won't get replaced
|
// Calling on top level; we know the netlist won't get replaced
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v);
|
||||||
} else if (!nodep->backp()) {
|
} else if (!nodep->backp()) {
|
||||||
// Calling on standalone tree; insert a shim node so we can keep track, then delete it on completion
|
// Calling on standalone tree; insert a shim node so we can keep track, then delete it on completion
|
||||||
AstBegin* tempp = new AstBegin(nodep->fileline(),"[EditWrapper]",nodep);
|
AstBegin* tempp = new AstBegin(nodep->fileline(),"[EditWrapper]",nodep);
|
||||||
{
|
{
|
||||||
tempp->stmtsp()->accept(v, vup); nodep=NULL; // nodep to null as may be replaced
|
tempp->stmtsp()->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced
|
||||||
}
|
}
|
||||||
nodep = tempp->stmtsp()->unlinkFrBackWithNext();
|
nodep = tempp->stmtsp()->unlinkFrBackWithNext();
|
||||||
tempp->deleteTree(); tempp=NULL;
|
tempp->deleteTree(); VL_DANGLING(tempp);
|
||||||
} else {
|
} else {
|
||||||
// Use back to determine who's pointing at us (IE assume new node grafts into same place as old one)
|
// Use back to determine who's pointing at us (IE assume new node grafts into same place as old one)
|
||||||
AstNode** nextnodepp = NULL;
|
AstNode** nextnodepp = NULL;
|
||||||
@@ -837,7 +845,7 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
|||||||
else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp);
|
else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp);
|
||||||
if (!nextnodepp) this->v3fatalSrc("Node's back doesn't point to forward to node itself");
|
if (!nextnodepp) this->v3fatalSrc("Node's back doesn't point to forward to node itself");
|
||||||
{
|
{
|
||||||
nodep->accept(v, vup); nodep=NULL; // nodep to null as may be replaced
|
nodep->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced
|
||||||
}
|
}
|
||||||
nodep = *nextnodepp; // Grab new node from point where old was connected
|
nodep = *nextnodepp; // Grab new node from point where old was connected
|
||||||
}
|
}
|
||||||
@@ -847,37 +855,47 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
||||||
void AstNode::cloneRelinkTree() {
|
void AstNode::cloneRelinkTree() {
|
||||||
if (!this) return;
|
// private: Cleanup clone() operation on whole tree. Publicly call cloneTree() instead.
|
||||||
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
|
for (AstNode* nodep=this; nodep; nodep=nodep->m_nextp) {
|
||||||
if (m_dtypep && m_dtypep->clonep()) {
|
if (m_dtypep && m_dtypep->clonep()) {
|
||||||
m_dtypep = m_dtypep->clonep()->castNodeDType();
|
m_dtypep = m_dtypep->clonep();
|
||||||
}
|
}
|
||||||
nodep->cloneRelink();
|
nodep->cloneRelink();
|
||||||
nodep->m_op1p->cloneRelinkTree();
|
if (nodep->m_op1p) nodep->m_op1p->cloneRelinkTree();
|
||||||
nodep->m_op2p->cloneRelinkTree();
|
if (nodep->m_op2p) nodep->m_op2p->cloneRelinkTree();
|
||||||
nodep->m_op3p->cloneRelinkTree();
|
if (nodep->m_op3p) nodep->m_op3p->cloneRelinkTree();
|
||||||
nodep->m_op4p->cloneRelinkTree();
|
if (nodep->m_op4p) nodep->m_op4p->cloneRelinkTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Comparison
|
// Comparison
|
||||||
|
|
||||||
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
|
bool AstNode::gateTreeIter() {
|
||||||
// Return true if the two trees are identical
|
// private: Return true if the two trees are identical
|
||||||
if (this==NULL && node2p==NULL) return true;
|
if (!isGateOptimizable()) return false;
|
||||||
if (this==NULL || node2p==NULL) return false;
|
if (m_op1p && !m_op1p->gateTreeIter()) return false;
|
||||||
if (this->type() != node2p->type()
|
if (m_op2p && !m_op2p->gateTreeIter()) return false;
|
||||||
|| this->dtypep() != node2p->dtypep()
|
if (m_op3p && !m_op3p->gateTreeIter()) return false;
|
||||||
|| !this->same(node2p)
|
if (m_op4p && !m_op4p->gateTreeIter()) return false;
|
||||||
|| (gateOnly && !this->isGateOptimizable())) {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AstNode::sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly) {
|
||||||
|
// private: Return true if the two trees are identical
|
||||||
|
if (!node1p && !node2p) return true;
|
||||||
|
if (!node1p || !node2p) return false;
|
||||||
|
if (node1p->type() != node2p->type()
|
||||||
|
|| node1p->dtypep() != node2p->dtypep()
|
||||||
|
|| !node1p->same(node2p)
|
||||||
|
|| (gateOnly && !node1p->isGateOptimizable())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (this->op1p()->sameTreeIter(node2p->op1p(),false,gateOnly)
|
return (sameTreeIter(node1p->m_op1p, node2p->m_op1p,false,gateOnly)
|
||||||
&& this->op2p()->sameTreeIter(node2p->op2p(),false,gateOnly)
|
&& sameTreeIter(node1p->m_op2p, node2p->m_op2p,false,gateOnly)
|
||||||
&& this->op3p()->sameTreeIter(node2p->op3p(),false,gateOnly)
|
&& sameTreeIter(node1p->m_op3p, node2p->m_op3p,false,gateOnly)
|
||||||
&& this->op4p()->sameTreeIter(node2p->op4p(),false,gateOnly)
|
&& sameTreeIter(node1p->m_op4p, node2p->m_op4p,false,gateOnly)
|
||||||
&& (ignNext || this->nextp()->sameTreeIter(node2p->nextp(),false,gateOnly))
|
&& (ignNext || sameTreeIter(node1p->m_nextp, node2p->m_nextp,false,gateOnly))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,6 +919,7 @@ V3Hash::V3Hash(const string& name) {
|
|||||||
// Debugging
|
// Debugging
|
||||||
|
|
||||||
void AstNode::checkTreeIter(AstNode* backp) {
|
void AstNode::checkTreeIter(AstNode* backp) {
|
||||||
|
// private: Check a tree and children
|
||||||
if (backp != this->backp()) {
|
if (backp != this->backp()) {
|
||||||
this->v3fatalSrc("Back node inconsistent");
|
this->v3fatalSrc("Back node inconsistent");
|
||||||
}
|
}
|
||||||
@@ -909,15 +928,15 @@ void AstNode::checkTreeIter(AstNode* backp) {
|
|||||||
if (op1p()||op2p()||op3p()||op4p())
|
if (op1p()||op2p()||op3p()||op4p())
|
||||||
this->v3fatalSrc("Terminal operation with non-terminals");
|
this->v3fatalSrc("Terminal operation with non-terminals");
|
||||||
}
|
}
|
||||||
if (op1p()) op1p()->checkTreeIterList(this);
|
if (m_op1p) m_op1p->checkTreeIterList(this);
|
||||||
if (op2p()) op2p()->checkTreeIterList(this);
|
if (m_op2p) m_op2p->checkTreeIterList(this);
|
||||||
if (op3p()) op3p()->checkTreeIterList(this);
|
if (m_op3p) m_op3p->checkTreeIterList(this);
|
||||||
if (op4p()) op4p()->checkTreeIterList(this);
|
if (m_op4p) m_op4p->checkTreeIterList(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::checkTreeIterList(AstNode* backp) {
|
void AstNode::checkTreeIterList(AstNode* backp) {
|
||||||
// Check a (possible) list of nodes, this is always the head of the list
|
// private: Check a (possible) list of nodes, this is always the head of the list
|
||||||
if (!this) v3fatalSrc("Null nodep");
|
// Audited to make sure this is never NULL
|
||||||
AstNode* headp = this;
|
AstNode* headp = this;
|
||||||
AstNode* tailp = this;
|
AstNode* tailp = this;
|
||||||
for (AstNode* nodep=headp; nodep; nodep=nodep->nextp()) {
|
for (AstNode* nodep=headp; nodep; nodep=nodep->nextp()) {
|
||||||
@@ -931,7 +950,6 @@ void AstNode::checkTreeIterList(AstNode* backp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::checkTree() {
|
void AstNode::checkTree() {
|
||||||
if (!this) return;
|
|
||||||
if (!debug()) return;
|
if (!debug()) return;
|
||||||
if (this->backp()) {
|
if (this->backp()) {
|
||||||
// Linked tree- check only the passed node
|
// Linked tree- check only the passed node
|
||||||
@@ -942,17 +960,17 @@ void AstNode::checkTree() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::dumpGdb() { // For GDB only
|
void AstNode::dumpGdb() { // For GDB only
|
||||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
if (!dynamic_cast<const AstNode*>(this)) { cout<<"This=NULL"<<endl; return; }
|
||||||
dumpGdbHeader();
|
dumpGdbHeader();
|
||||||
cout<<" "; dump(cout); cout<<endl;
|
cout<<" "; dump(cout); cout<<endl;
|
||||||
}
|
}
|
||||||
void AstNode::dumpGdbHeader() const { // For GDB only
|
void AstNode::dumpGdbHeader() const { // For GDB only
|
||||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
if (!dynamic_cast<const AstNode*>(this)) { cout<<"This=NULL"<<endl; return; }
|
||||||
dumpPtrs(cout);
|
dumpPtrs(cout);
|
||||||
cout<<" Fileline = "<<fileline()<<endl;
|
cout<<" Fileline = "<<fileline()<<endl;
|
||||||
}
|
}
|
||||||
void AstNode::dumpTreeGdb() { // For GDB only
|
void AstNode::dumpTreeGdb() { // For GDB only
|
||||||
if (!this) { cout<<"This=NULL"<<endl; return; }
|
if (!dynamic_cast<const AstNode*>(this)) { cout<<"This=NULL"<<endl; return; }
|
||||||
dumpGdbHeader();
|
dumpGdbHeader();
|
||||||
dumpTree(cout);
|
dumpTree(cout);
|
||||||
}
|
}
|
||||||
@@ -992,7 +1010,6 @@ void AstNode::dumpPtrs(ostream& os) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::dumpTree(ostream& os, const string& indent, int maxDepth) {
|
void AstNode::dumpTree(ostream& os, const string& indent, int maxDepth) {
|
||||||
if (!this) return;
|
|
||||||
os<<indent<<" "<<this<<endl;
|
os<<indent<<" "<<this<<endl;
|
||||||
if (debug()>8) { os<<indent<<" "; dumpPtrs(os); }
|
if (debug()>8) { os<<indent<<" "; dumpPtrs(os); }
|
||||||
if (maxDepth==1) {
|
if (maxDepth==1) {
|
||||||
@@ -1006,7 +1023,7 @@ void AstNode::dumpTree(ostream& os, const string& indent, int maxDepth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
|
void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
|
||||||
if (!this) return;
|
// Audited to make sure this is never NULL
|
||||||
for (AstNode* nodep=this; nodep; nodep=nodep->nextp()) {
|
for (AstNode* nodep=this; nodep; nodep=nodep->nextp()) {
|
||||||
nodep->dumpTree(os, indent, maxDepth);
|
nodep->dumpTree(os, indent, maxDepth);
|
||||||
}
|
}
|
||||||
@@ -1016,7 +1033,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
|||||||
if (doDump) {
|
if (doDump) {
|
||||||
{ // Write log & close
|
{ // Write log & close
|
||||||
UINFO(2,"Dumping "<<filename<<endl);
|
UINFO(2,"Dumping "<<filename<<endl);
|
||||||
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
const VL_UNIQUE_PTR<ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||||
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
|
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
|
||||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||||
@@ -1041,7 +1058,13 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::v3errorEnd(ostringstream& str) const {
|
void AstNode::v3errorEnd(ostringstream& str) const {
|
||||||
if (this && m_fileline) {
|
if (!dynamic_cast<const AstNode*>(this)) {
|
||||||
|
// No known cases cause this, but better than a core dump
|
||||||
|
if (debug()) UINFO(0, "-node: NULL. Please report this along with a --gdbbt backtrace as a Verilator bug.\n");
|
||||||
|
V3Error::v3errorEnd(str);
|
||||||
|
} else if (!m_fileline) {
|
||||||
|
V3Error::v3errorEnd(str);
|
||||||
|
} else {
|
||||||
ostringstream nsstr;
|
ostringstream nsstr;
|
||||||
nsstr<<str.str();
|
nsstr<<str.str();
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
@@ -1049,14 +1072,11 @@ void AstNode::v3errorEnd(ostringstream& str) const {
|
|||||||
nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl;
|
nsstr<<"-node: "; ((AstNode*)this)->dump(nsstr); nsstr<<endl;
|
||||||
}
|
}
|
||||||
m_fileline->v3errorEnd(nsstr);
|
m_fileline->v3errorEnd(nsstr);
|
||||||
} else {
|
|
||||||
V3Error::v3errorEnd(str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstNode::warnMore() const {
|
string AstNode::warnMore() const {
|
||||||
if (this) return this->fileline()->warnMore();
|
return fileline()->warnMore();
|
||||||
else return V3Error::warnMore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|||||||
+178
-127
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -53,6 +53,7 @@ public:
|
|||||||
enum en m_e;
|
enum en m_e;
|
||||||
// cppcheck-suppress uninitVar // responsiblity of each subclass
|
// cppcheck-suppress uninitVar // responsiblity of each subclass
|
||||||
inline AstType () {}
|
inline AstType () {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstType (en _e) : m_e(_e) {}
|
inline AstType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -87,7 +88,9 @@ public:
|
|||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
};
|
||||||
inline AstNumeric () : m_e(UNSIGNED) {}
|
inline AstNumeric () : m_e(UNSIGNED) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstNumeric (en _e) : m_e(_e) {}
|
inline AstNumeric (en _e) : m_e(_e) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstNumeric (VSignedState signst) {
|
inline AstNumeric (VSignedState signst) {
|
||||||
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
|
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
|
||||||
else if (signst==signedst_SIGNED) m_e=SIGNED;
|
else if (signst==signedst_SIGNED) m_e=SIGNED;
|
||||||
@@ -121,6 +124,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstPragmaType () : m_e(ILLEGAL) {}
|
inline AstPragmaType () : m_e(ILLEGAL) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstPragmaType (en _e) : m_e(_e) {}
|
inline AstPragmaType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -144,6 +148,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstCFuncType () : m_e(FT_NORMAL) {}
|
inline AstCFuncType () : m_e(FT_NORMAL) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstCFuncType (en _e) : m_e(_e) {}
|
inline AstCFuncType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -212,6 +217,7 @@ public:
|
|||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
};
|
||||||
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstEdgeType (en _e) : m_e(_e) {}
|
inline AstEdgeType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -279,6 +285,7 @@ public:
|
|||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
};
|
||||||
inline AstAttrType () : m_e(ILLEGAL) {}
|
inline AstAttrType () : m_e(ILLEGAL) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstAttrType (en _e) : m_e(_e) {}
|
inline AstAttrType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -338,6 +345,7 @@ public:
|
|||||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
||||||
}
|
}
|
||||||
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
||||||
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -432,6 +440,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstVarType () : m_e(UNKNOWN) {}
|
inline AstVarType () : m_e(UNKNOWN) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstVarType (en _e) : m_e(_e) {}
|
inline AstVarType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -469,6 +478,7 @@ public:
|
|||||||
enum en m_e;
|
enum en m_e;
|
||||||
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
||||||
inline AstBranchPred () : m_e(BP_UNKNOWN) {}
|
inline AstBranchPred () : m_e(BP_UNKNOWN) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstBranchPred (en _e) : m_e(_e) {}
|
inline AstBranchPred (en _e) : m_e(_e) {}
|
||||||
explicit inline AstBranchPred (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstBranchPred (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -500,9 +510,11 @@ public:
|
|||||||
enum en m_e;
|
enum en m_e;
|
||||||
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
||||||
inline AstVarAttrClocker () : m_e(CLOCKER_UNKNOWN) {}
|
inline AstVarAttrClocker () : m_e(CLOCKER_UNKNOWN) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
||||||
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
|
bool unknown() const { return m_e==CLOCKER_UNKNOWN; }
|
||||||
AstVarAttrClocker invert() const {
|
AstVarAttrClocker invert() const {
|
||||||
if (m_e==CLOCKER_YES) return CLOCKER_NO;
|
if (m_e==CLOCKER_YES) return CLOCKER_NO;
|
||||||
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
|
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
|
||||||
@@ -530,6 +542,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline VAlwaysKwd () : m_e(ALWAYS) {}
|
inline VAlwaysKwd () : m_e(ALWAYS) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline VAlwaysKwd (en _e) : m_e(_e) {}
|
inline VAlwaysKwd (en _e) : m_e(_e) {}
|
||||||
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -554,6 +567,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline VCaseType () : m_e(CT_CASE) {}
|
inline VCaseType () : m_e(CT_CASE) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline VCaseType (en _e) : m_e(_e) {}
|
inline VCaseType (en _e) : m_e(_e) {}
|
||||||
explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -576,6 +590,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstDisplayType () : m_e(DT_DISPLAY) {}
|
inline AstDisplayType () : m_e(DT_DISPLAY) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstDisplayType (en _e) : m_e(_e) {}
|
inline AstDisplayType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -600,6 +615,7 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstParseRefExp() : m_e(PX_NONE) {}
|
inline AstParseRefExp() : m_e(PX_NONE) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline AstParseRefExp (en _e) : m_e(_e) {}
|
inline AstParseRefExp (en _e) : m_e(_e) {}
|
||||||
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; }
|
operator en () const { return m_e; }
|
||||||
@@ -699,7 +715,7 @@ struct VBasicTypeKey {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// AstNUser - Generic pointer base class for AST User nodes.
|
// AstNUser - Generic base class for AST User nodes.
|
||||||
// - Also used to allow parameter passing up/down iterate calls
|
// - Also used to allow parameter passing up/down iterate calls
|
||||||
|
|
||||||
class WidthVP;
|
class WidthVP;
|
||||||
@@ -708,26 +724,30 @@ class OrderBlockNU;
|
|||||||
class OrderVarNU;
|
class OrderVarNU;
|
||||||
class V3GraphVertex;
|
class V3GraphVertex;
|
||||||
class VSymEnt;
|
class VSymEnt;
|
||||||
struct AstNUser {
|
|
||||||
AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p())
|
class VNUser {
|
||||||
|
union {
|
||||||
|
void* up;
|
||||||
|
int ui;
|
||||||
|
} m_u;
|
||||||
|
public:
|
||||||
|
VNUser() {}
|
||||||
|
VNUser(int i) { m_u.up = 0; m_u.ui = i; }
|
||||||
|
VNUser(void* p) { m_u.up = p; }
|
||||||
|
~VNUser() {}
|
||||||
// Casters
|
// Casters
|
||||||
WidthVP* c() { return ((WidthVP*)this); }
|
WidthVP* c() { return ((WidthVP*)m_u.up); }
|
||||||
LinkVP* castLinkVP() { return ((LinkVP*)this); }
|
LinkVP* toLinkVP() { return ((LinkVP*)m_u.up); }
|
||||||
VSymEnt* castSymEnt() { return ((VSymEnt*)this); }
|
VSymEnt* toSymEnt() { return ((VSymEnt*)m_u.up); }
|
||||||
AstNode* castNode() { return ((AstNode*)this); }
|
AstNode* toNodep() { return ((AstNode*)m_u.up); }
|
||||||
OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); }
|
OrderBlockNU* toOrderBlock() { return ((OrderBlockNU*)m_u.up); }
|
||||||
OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); }
|
OrderVarNU* toOrderVar() { return ((OrderVarNU*)m_u.up); }
|
||||||
V3GraphVertex* castGraphVertex() { return ((V3GraphVertex*)this); }
|
V3GraphVertex* toGraphVertex() { return ((V3GraphVertex*)m_u.up); }
|
||||||
inline int castInt() {
|
inline int toInt() {
|
||||||
union { AstNUser* up; int ui; } u;
|
return m_u.ui;
|
||||||
u.up = this;
|
|
||||||
return u.ui;
|
|
||||||
}
|
|
||||||
static inline AstNUser* fromInt (int i) {
|
|
||||||
union { AstNUser* up; int ui; } u;
|
|
||||||
u.up=0; u.ui=i;
|
|
||||||
return u.up;
|
|
||||||
}
|
}
|
||||||
|
static inline VNUser fromZero () { return VNUser(0); }
|
||||||
|
static inline VNUser fromInt (int i) { return VNUser(i); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -846,7 +866,8 @@ public:
|
|||||||
}
|
}
|
||||||
#include "V3Ast__gen_visitor.h" // From ./astgen
|
#include "V3Ast__gen_visitor.h" // From ./astgen
|
||||||
// Things like:
|
// Things like:
|
||||||
// virtual void visit(type*) = 0;
|
// virtual void visit(AstBreak* nodep) { visit((AstNodeStmt*)(nodep)); }
|
||||||
|
// virtual void visit(AstNodeStmt* nodep) { visit((AstNode*)(nodep)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -897,16 +918,19 @@ public:
|
|||||||
// CREATORS
|
// CREATORS
|
||||||
class Illegal {}; // for creator type-overload selection
|
class Illegal {}; // for creator type-overload selection
|
||||||
class FullValue {}; // for creator type-overload selection
|
class FullValue {}; // for creator type-overload selection
|
||||||
V3Hash(Illegal) { m_both=0; }
|
explicit V3Hash(Illegal) { m_both=0; }
|
||||||
// Saving and restoring inside a userp
|
// Saving and restoring inside a userp
|
||||||
V3Hash(AstNUser* up) { m_both=up->castInt(); }
|
explicit V3Hash(VNUser u) { m_both=u.toInt(); }
|
||||||
V3Hash operator+= (const V3Hash& rh) {
|
V3Hash operator+= (const V3Hash& rh) {
|
||||||
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
|
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
|
||||||
return *this; };
|
return *this; };
|
||||||
// Creating from raw data (sameHash functions)
|
// Creating from raw data (sameHash functions)
|
||||||
V3Hash() { setBoth(1,0); }
|
V3Hash() { setBoth(1,0); }
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
V3Hash(uint32_t val) { setBoth(1,val); }
|
V3Hash(uint32_t val) { setBoth(1,val); }
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
V3Hash(const void* vp) { setBoth(1,cvtToHash(vp)); }
|
V3Hash(const void* vp) { setBoth(1,cvtToHash(vp)); }
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
V3Hash(const string& name);
|
V3Hash(const string& name);
|
||||||
V3Hash(V3Hash h1, V3Hash h2) {
|
V3Hash(V3Hash h1, V3Hash h2) {
|
||||||
setBoth(1,h1.hshval()*31+h2.hshval()); }
|
setBoth(1,h1.hshval()*31+h2.hshval()); }
|
||||||
@@ -955,15 +979,15 @@ class AstNode {
|
|||||||
// // Space for more bools here
|
// // Space for more bools here
|
||||||
|
|
||||||
// This member ordering both allows 64 bit alignment and puts associated data together
|
// This member ordering both allows 64 bit alignment and puts associated data together
|
||||||
AstNUser* m_user1p; // Pointer to any information the user iteration routine wants
|
VNUser m_user1u; // Contains any information the user iteration routine wants
|
||||||
uint32_t m_user1Cnt; // Mark of when userp was set
|
uint32_t m_user1Cnt; // Mark of when userp was set
|
||||||
uint32_t m_user2Cnt; // Mark of when userp was set
|
uint32_t m_user2Cnt; // Mark of when userp was set
|
||||||
AstNUser* m_user2p; // Pointer to any information the user iteration routine wants
|
VNUser m_user2u; // Contains any information the user iteration routine wants
|
||||||
AstNUser* m_user3p; // Pointer to any information the user iteration routine wants
|
VNUser m_user3u; // Contains any information the user iteration routine wants
|
||||||
uint32_t m_user3Cnt; // Mark of when userp was set
|
uint32_t m_user3Cnt; // Mark of when userp was set
|
||||||
uint32_t m_user4Cnt; // Mark of when userp was set
|
uint32_t m_user4Cnt; // Mark of when userp was set
|
||||||
AstNUser* m_user4p; // Pointer to any information the user iteration routine wants
|
VNUser m_user4u; // Contains any information the user iteration routine wants
|
||||||
AstNUser* m_user5p; // Pointer to any information the user iteration routine wants
|
VNUser m_user5u; // Contains any information the user iteration routine wants
|
||||||
uint32_t m_user5Cnt; // Mark of when userp was set
|
uint32_t m_user5Cnt; // Mark of when userp was set
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -973,14 +997,17 @@ class AstNode {
|
|||||||
void op4p(AstNode* nodep) { m_op4p = nodep; if (nodep) nodep->m_backp = this; }
|
void op4p(AstNode* nodep) { m_op4p = nodep; if (nodep) nodep->m_backp = this; }
|
||||||
|
|
||||||
void init(); // initialize value of AstNode
|
void init(); // initialize value of AstNode
|
||||||
void iterateListBackwards(AstNVisitor& v, AstNUser* vup=NULL);
|
void iterateListBackwards(AstNVisitor& v);
|
||||||
|
private:
|
||||||
AstNode* cloneTreeIter();
|
AstNode* cloneTreeIter();
|
||||||
AstNode* cloneTreeIterList();
|
AstNode* cloneTreeIterList();
|
||||||
void checkTreeIter(AstNode* backp);
|
void checkTreeIter(AstNode* backp);
|
||||||
void checkTreeIterList(AstNode* backp);
|
void checkTreeIterList(AstNode* backp);
|
||||||
bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
|
bool gateTreeIter();
|
||||||
|
bool sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly);
|
||||||
void deleteTreeIter();
|
void deleteTreeIter();
|
||||||
void deleteNode();
|
void deleteNode();
|
||||||
|
public:
|
||||||
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
||||||
// cppcheck-suppress functionConst
|
// cppcheck-suppress functionConst
|
||||||
void debugTreeChange(const char* prefix, int lineno, bool next);
|
void debugTreeChange(const char* prefix, int lineno, bool next);
|
||||||
@@ -988,7 +1015,7 @@ class AstNode {
|
|||||||
protected:
|
protected:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
AstNode() {init(); }
|
AstNode() {init(); }
|
||||||
AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
|
explicit AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
|
||||||
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
||||||
virtual void cloneRelink() {}
|
virtual void cloneRelink() {}
|
||||||
void cloneRelinkTree();
|
void cloneRelinkTree();
|
||||||
@@ -1088,57 +1115,75 @@ public:
|
|||||||
bool isSigned() const;
|
bool isSigned() const;
|
||||||
bool isString() const;
|
bool isString() const;
|
||||||
|
|
||||||
AstNUser* user1p() const {
|
VNUser user1u() const {
|
||||||
// Slows things down measurably, so disabled by default
|
// Slows things down measurably, so disabled by default
|
||||||
//UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy");
|
//UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy");
|
||||||
return ((m_user1Cnt==AstUser1InUse::s_userCntGbl)?m_user1p:NULL);
|
return ((m_user1Cnt==AstUser1InUse::s_userCntGbl) ? m_user1u : VNUser(0));
|
||||||
}
|
}
|
||||||
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
AstNode* user1p() const { return user1u().toNodep(); }
|
||||||
int user1() const { return user1p()->castInt(); }
|
void user1u(const VNUser& user) { m_user1u=user; m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
||||||
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
void user1p(void* userp) { user1u(VNUser(userp)); }
|
||||||
int user1Inc() { int v=user1(); user1(v+1); return v; }
|
int user1() const { return user1u().toInt(); }
|
||||||
|
void user1(int val) { user1u(VNUser(val)); }
|
||||||
|
int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; }
|
||||||
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
||||||
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
AstNUser* user2p() const {
|
VNUser user2u() const {
|
||||||
//UASSERT_STATIC(AstUser2InUse::s_userBusy, "user2p set w/o busy");
|
// Slows things down measurably, so disabled by default
|
||||||
return ((m_user2Cnt==AstUser2InUse::s_userCntGbl)?m_user2p:NULL); }
|
//UASSERT_STATIC(AstUser2InUse::s_userBusy, "userp set w/o busy");
|
||||||
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
return ((m_user2Cnt==AstUser2InUse::s_userCntGbl) ? m_user2u : VNUser(0));
|
||||||
int user2() const { return user2p()->castInt(); }
|
}
|
||||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
AstNode* user2p() const { return user2u().toNodep(); }
|
||||||
int user2Inc() { int v=user2(); user2(v+1); return v; }
|
void user2u(const VNUser& user) { m_user2u=user; m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
||||||
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
|
void user2p(void* userp) { user2u(VNUser(userp)); }
|
||||||
static void user2ClearTree() { AstUser2InUse::clear(); }
|
int user2() const { return user2u().toInt(); }
|
||||||
|
void user2(int val) { user2u(VNUser(val)); }
|
||||||
|
int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; }
|
||||||
|
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; } // Better for cache than user2Inc()
|
||||||
|
static void user2ClearTree() { AstUser2InUse::clear(); } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
AstNUser* user3p() const {
|
VNUser user3u() const {
|
||||||
//UASSERT_STATIC(AstUser3InUse::s_userBusy, "user3p set w/o busy");
|
// Slows things down measurably, so disabled by default
|
||||||
return ((m_user3Cnt==AstUser3InUse::s_userCntGbl)?m_user3p:NULL); }
|
//UASSERT_STATIC(AstUser3InUse::s_userBusy, "userp set w/o busy");
|
||||||
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
return ((m_user3Cnt==AstUser3InUse::s_userCntGbl) ? m_user3u : VNUser(0));
|
||||||
int user3() const { return user3p()->castInt(); }
|
}
|
||||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
AstNode* user3p() const { return user3u().toNodep(); }
|
||||||
int user3Inc() { int v=user3(); user3(v+1); return v; }
|
void user3u(const VNUser& user) { m_user3u=user; m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
||||||
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
|
void user3p(void* userp) { user3u(VNUser(userp)); }
|
||||||
static void user3ClearTree() { AstUser3InUse::clear(); }
|
int user3() const { return user3u().toInt(); }
|
||||||
|
void user3(int val) { user3u(VNUser(val)); }
|
||||||
|
int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; }
|
||||||
|
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; } // Better for cache than user3Inc()
|
||||||
|
static void user3ClearTree() { AstUser3InUse::clear(); } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
AstNUser* user4p() const {
|
VNUser user4u() const {
|
||||||
//UASSERT_STATIC(AstUser4InUse::s_userBusy, "user4p set w/o busy");
|
// Slows things down measurably, so disabled by default
|
||||||
return ((m_user4Cnt==AstUser4InUse::s_userCntGbl)?m_user4p:NULL); }
|
//UASSERT_STATIC(AstUser4InUse::s_userBusy, "userp set w/o busy");
|
||||||
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
return ((m_user4Cnt==AstUser4InUse::s_userCntGbl) ? m_user4u : VNUser(0));
|
||||||
int user4() const { return user4p()->castInt(); }
|
}
|
||||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
AstNode* user4p() const { return user4u().toNodep(); }
|
||||||
int user4Inc() { int v=user4(); user4(v+1); return v; }
|
void user4u(const VNUser& user) { m_user4u=user; m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
||||||
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
|
void user4p(void* userp) { user4u(VNUser(userp)); }
|
||||||
static void user4ClearTree() { AstUser4InUse::clear(); }
|
int user4() const { return user4u().toInt(); }
|
||||||
|
void user4(int val) { user4u(VNUser(val)); }
|
||||||
|
int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; }
|
||||||
|
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; } // Better for cache than user4Inc()
|
||||||
|
static void user4ClearTree() { AstUser4InUse::clear(); } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
AstNUser* user5p() const {
|
VNUser user5u() const {
|
||||||
//UASSERT_STATIC(AstUser5InUse::s_userBusy, "user5p set w/o busy");
|
// Slows things down measurably, so disabled by default
|
||||||
return ((m_user5Cnt==AstUser5InUse::s_userCntGbl)?m_user5p:NULL); }
|
//UASSERT_STATIC(AstUser5InUse::s_userBusy, "userp set w/o busy");
|
||||||
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
return ((m_user5Cnt==AstUser5InUse::s_userCntGbl) ? m_user5u : VNUser(0));
|
||||||
int user5() const { return user5p()->castInt(); }
|
}
|
||||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
AstNode* user5p() const { return user5u().toNodep(); }
|
||||||
int user5Inc() { int v=user5(); user5(v+1); return v; }
|
void user5u(const VNUser& user) { m_user5u=user; m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
||||||
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
|
void user5p(void* userp) { user5u(VNUser(userp)); }
|
||||||
static void user5ClearTree() { AstUser5InUse::clear(); }
|
int user5() const { return user5u().toInt(); }
|
||||||
|
void user5(int val) { user5u(VNUser(val)); }
|
||||||
|
int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; }
|
||||||
|
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; } // Better for cache than user5Inc()
|
||||||
|
static void user5ClearTree() { AstUser5InUse::clear(); } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
vluint64_t editCount() const { return m_editCount; }
|
vluint64_t editCount() const { return m_editCount; }
|
||||||
void editCountInc() { m_editCount = ++s_editCntGbl; } // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
void editCountInc() { m_editCount = ++s_editCntGbl; } // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
||||||
@@ -1190,8 +1235,10 @@ public:
|
|||||||
void dumpGdbHeader() const;
|
void dumpGdbHeader() const;
|
||||||
|
|
||||||
// METHODS - Tree modifications
|
// METHODS - Tree modifications
|
||||||
AstNode* addNext(AstNode* newp); // Returns this, adds to end of list
|
static AstNode* addNext(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp to end of nodep's list
|
||||||
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK
|
static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list
|
||||||
|
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
|
||||||
|
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
|
||||||
void addNextHere(AstNode* newp); // Adds after speced node
|
void addNextHere(AstNode* newp); // Adds after speced node
|
||||||
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
|
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
|
||||||
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
||||||
@@ -1207,6 +1254,7 @@ public:
|
|||||||
|
|
||||||
// METHODS - Iterate on a tree
|
// METHODS - Iterate on a tree
|
||||||
AstNode* cloneTree(bool cloneNextLink);
|
AstNode* cloneTree(bool cloneNextLink);
|
||||||
|
bool gateTree() { return gateTreeIter(); } // Is tree gateOptimizable?
|
||||||
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
||||||
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
|
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
|
||||||
void deleteTree(); // Always deletes the next link
|
void deleteTree(); // Always deletes the next link
|
||||||
@@ -1239,18 +1287,16 @@ public:
|
|||||||
virtual const char* broken() const { return NULL; }
|
virtual const char* broken() const { return NULL; }
|
||||||
|
|
||||||
// INVOKERS
|
// INVOKERS
|
||||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
virtual void accept(AstNVisitor& v) = 0;
|
||||||
void iterate(AstNVisitor& v, AstNUser* vup=NULL) { this->accept(v,vup); } // Does this; excludes following this->next
|
void iterate(AstNVisitor& v) { this->accept(v); } // Does this; excludes following this->next
|
||||||
void iterateAndNext(AstNVisitor& v, AstNUser* vup=NULL);
|
void iterateAndNext(AstNVisitor& v);
|
||||||
void iterateAndNextConst(AstNVisitor& v, AstNUser* vup=NULL);
|
void iterateAndNextConst(AstNVisitor& v);
|
||||||
void iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup=NULL) { iterateAndNextConst(v, vup); }
|
void iterateChildren(AstNVisitor& v); // Excludes following this->next
|
||||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
|
void iterateChildrenBackwards(AstNVisitor& v); // Excludes following this->next
|
||||||
void iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
|
void iterateChildrenConst(AstNVisitor& v); // Excludes following this->next
|
||||||
void iterateChildrenConst(AstNVisitor& v, AstNUser* vup=NULL); // Excludes following this->next
|
AstNode* iterateSubtreeReturnEdits(AstNVisitor& v); // Return edited nodep; see comments in V3Ast.cpp
|
||||||
AstNode* acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup=NULL); // Return edited nodep; see comments in V3Ast.cpp
|
|
||||||
|
|
||||||
// CONVERSION
|
// CONVERSION
|
||||||
AstNode* castNode() { return this; }
|
|
||||||
#include "V3Ast__gen_interface.h" // From ./astgen
|
#include "V3Ast__gen_interface.h" // From ./astgen
|
||||||
// Things like:
|
// Things like:
|
||||||
// AstAlways* castAlways();
|
// AstAlways* castAlways();
|
||||||
@@ -1265,12 +1311,13 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
|||||||
|
|
||||||
#define ASTNODE_BASE_FUNCS(name) \
|
#define ASTNODE_BASE_FUNCS(name) \
|
||||||
virtual ~Ast ##name() {} \
|
virtual ~Ast ##name() {} \
|
||||||
Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##name(); }
|
Ast ##name * cloneTree(bool cloneNext) { return static_cast<Ast ##name *>(AstNode::cloneTree(cloneNext)); } \
|
||||||
|
Ast ##name * clonep() const { return static_cast<Ast ##name *>(AstNode::clonep()); }
|
||||||
|
|
||||||
class AstNodeMath : public AstNode {
|
class AstNodeMath : public AstNode {
|
||||||
// Math -- anything that's part of an expression tree
|
// Math -- anything that's part of an expression tree
|
||||||
public:
|
public:
|
||||||
AstNodeMath(FileLine* fl)
|
explicit AstNodeMath(FileLine* fl)
|
||||||
: AstNode(fl) {}
|
: AstNode(fl) {}
|
||||||
ASTNODE_BASE_FUNCS(NodeMath)
|
ASTNODE_BASE_FUNCS(NodeMath)
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -1287,13 +1334,13 @@ public:
|
|||||||
class AstNodeTermop : public AstNodeMath {
|
class AstNodeTermop : public AstNodeMath {
|
||||||
// Terminal operator -- a operator with no "inputs"
|
// Terminal operator -- a operator with no "inputs"
|
||||||
public:
|
public:
|
||||||
AstNodeTermop(FileLine* fl)
|
explicit AstNodeTermop(FileLine* fl)
|
||||||
: AstNodeMath(fl) {}
|
: AstNodeMath(fl) {}
|
||||||
ASTNODE_BASE_FUNCS(NodeTermop)
|
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||||
// Know no children, and hot function, so skip iterator for speed
|
// Know no children, and hot function, so skip iterator for speed
|
||||||
// See checkTreeIter also that asserts no children
|
// See checkTreeIter also that asserts no children
|
||||||
// cppcheck-suppress functionConst
|
// cppcheck-suppress functionConst
|
||||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
void iterateChildren(AstNVisitor& v) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstNodeUniop : public AstNodeMath {
|
class AstNodeUniop : public AstNodeMath {
|
||||||
@@ -1304,7 +1351,7 @@ public:
|
|||||||
dtypeFrom(lhsp);
|
dtypeFrom(lhsp);
|
||||||
setOp1p(lhsp); }
|
setOp1p(lhsp); }
|
||||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p(); }
|
||||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
||||||
@@ -1325,8 +1372,10 @@ public:
|
|||||||
: AstNodeMath(fl) {
|
: AstNodeMath(fl) {
|
||||||
setOp1p(lhs); setOp2p(rhs); }
|
setOp1p(lhs); setOp2p(rhs); }
|
||||||
ASTNODE_BASE_FUNCS(NodeBiop)
|
ASTNODE_BASE_FUNCS(NodeBiop)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
// ACCESSORS
|
||||||
|
AstNode* lhsp() const { return op1p(); }
|
||||||
|
AstNode* rhsp() const { return op2p(); }
|
||||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||||
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -1350,9 +1399,9 @@ public:
|
|||||||
: AstNodeMath(fl) {
|
: AstNodeMath(fl) {
|
||||||
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
||||||
ASTNODE_BASE_FUNCS(NodeTriop)
|
ASTNODE_BASE_FUNCS(NodeTriop)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p(); }
|
||||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
AstNode* rhsp() const { return op2p(); }
|
||||||
AstNode* thsp() const { return op3p()->castNode(); }
|
AstNode* thsp() const { return op3p(); }
|
||||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||||
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
||||||
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
||||||
@@ -1394,9 +1443,9 @@ public:
|
|||||||
ASTNODE_BASE_FUNCS(NodeCond)
|
ASTNODE_BASE_FUNCS(NodeCond)
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
||||||
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
|
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
|
||||||
AstNode* condp() const { return op1p()->castNode(); } // op1 = Condition
|
AstNode* condp() const { return op1p(); } // op1 = Condition
|
||||||
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
|
AstNode* expr1p() const { return op2p(); } // op2 = If true...
|
||||||
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
|
AstNode* expr2p() const { return op3p(); } // op3 = If false...
|
||||||
virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; }
|
virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; }
|
||||||
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
||||||
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
||||||
@@ -1414,10 +1463,10 @@ public:
|
|||||||
: AstNode(fl) {
|
: AstNode(fl) {
|
||||||
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
||||||
ASTNODE_BASE_FUNCS(NodePreSel)
|
ASTNODE_BASE_FUNCS(NodePreSel)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p(); }
|
||||||
AstNode* fromp() const { return lhsp(); }
|
AstNode* fromp() const { return lhsp(); }
|
||||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
AstNode* rhsp() const { return op2p(); }
|
||||||
AstNode* thsp() const { return op3p()->castNode(); }
|
AstNode* thsp() const { return op3p(); }
|
||||||
AstAttrOf* attrp() const { return op4p()->castAttrOf(); }
|
AstAttrOf* attrp() const { return op4p()->castAttrOf(); }
|
||||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||||
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
||||||
@@ -1431,7 +1480,7 @@ public:
|
|||||||
class AstNodeStmt : public AstNode {
|
class AstNodeStmt : public AstNode {
|
||||||
// Statement -- anything that's directly under a function
|
// Statement -- anything that's directly under a function
|
||||||
public:
|
public:
|
||||||
AstNodeStmt(FileLine* fl)
|
explicit AstNodeStmt(FileLine* fl)
|
||||||
: AstNode(fl) {}
|
: AstNode(fl) {}
|
||||||
ASTNODE_BASE_FUNCS(NodeStmt)
|
ASTNODE_BASE_FUNCS(NodeStmt)
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -1449,8 +1498,8 @@ public:
|
|||||||
ASTNODE_BASE_FUNCS(NodeAssign)
|
ASTNODE_BASE_FUNCS(NodeAssign)
|
||||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||||
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
|
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
|
||||||
AstNode* rhsp() const { return op1p()->castNode(); } // op1 = Assign from
|
AstNode* rhsp() const { return op1p(); } // op1 = Assign from
|
||||||
AstNode* lhsp() const { return op2p()->castNode(); } // op2 = Assign to
|
AstNode* lhsp() const { return op2p(); } // op2 = Assign to
|
||||||
void rhsp(AstNode* np) { setOp1p(np); }
|
void rhsp(AstNode* np) { setOp1p(np); }
|
||||||
void lhsp(AstNode* np) { setOp2p(np); }
|
void lhsp(AstNode* np) { setOp2p(np); }
|
||||||
virtual bool hasDType() const { return true; }
|
virtual bool hasDType() const { return true; }
|
||||||
@@ -1469,10 +1518,10 @@ public:
|
|||||||
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
|
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
|
||||||
}
|
}
|
||||||
ASTNODE_BASE_FUNCS(NodeFor)
|
ASTNODE_BASE_FUNCS(NodeFor)
|
||||||
AstNode* initsp() const { return op1p()->castNode(); } // op1= initial statements
|
AstNode* initsp() const { return op1p(); } // op1= initial statements
|
||||||
AstNode* condp() const { return op2p()->castNode(); } // op2= condition to continue
|
AstNode* condp() const { return op2p(); } // op2= condition to continue
|
||||||
AstNode* incsp() const { return op3p()->castNode(); } // op3= increment statements
|
AstNode* incsp() const { return op3p(); } // op3= increment statements
|
||||||
AstNode* bodysp() const { return op4p()->castNode(); } // op4= body of loop
|
AstNode* bodysp() const { return op4p(); } // op4= body of loop
|
||||||
virtual bool isGateOptimizable() const { return false; }
|
virtual bool isGateOptimizable() const { return false; }
|
||||||
virtual int instrCount() const { return instrCountBranch(); }
|
virtual int instrCount() const { return instrCountBranch(); }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
@@ -1511,9 +1560,9 @@ public:
|
|||||||
}
|
}
|
||||||
ASTNODE_BASE_FUNCS(NodeCase)
|
ASTNODE_BASE_FUNCS(NodeCase)
|
||||||
virtual int instrCount() const { return instrCountBranch(); }
|
virtual int instrCount() const { return instrCountBranch(); }
|
||||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = case condition <expression>
|
AstNode* exprp() const { return op1p(); } // op1 = case condition <expression>
|
||||||
AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions
|
AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions
|
||||||
AstNode* notParallelp() const { return op3p()->castNode(); } // op3 = assertion code for non-full case's
|
AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's
|
||||||
void addItemsp(AstNode* nodep) { addOp2p(nodep); }
|
void addItemsp(AstNode* nodep) { addOp2p(nodep); }
|
||||||
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
||||||
};
|
};
|
||||||
@@ -1521,7 +1570,7 @@ public:
|
|||||||
class AstNodeSenItem : public AstNode {
|
class AstNodeSenItem : public AstNode {
|
||||||
// An AstSenItem or AstSenGate
|
// An AstSenItem or AstSenGate
|
||||||
public:
|
public:
|
||||||
AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
explicit AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
||||||
ASTNODE_BASE_FUNCS(NodeSenItem)
|
ASTNODE_BASE_FUNCS(NodeSenItem)
|
||||||
virtual bool isClocked() const = 0;
|
virtual bool isClocked() const = 0;
|
||||||
virtual bool isCombo() const = 0;
|
virtual bool isCombo() const = 0;
|
||||||
@@ -1575,7 +1624,7 @@ public:
|
|||||||
// Know no children, and hot function, so skip iterator for speed
|
// Know no children, and hot function, so skip iterator for speed
|
||||||
// See checkTreeIter also that asserts no children
|
// See checkTreeIter also that asserts no children
|
||||||
// cppcheck-suppress functionConst
|
// cppcheck-suppress functionConst
|
||||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
void iterateChildren(AstNVisitor& v) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstNodeText : public AstNode {
|
class AstNodeText : public AstNode {
|
||||||
@@ -1608,7 +1657,7 @@ private:
|
|||||||
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AstNodeDType(FileLine* fl) : AstNode(fl) {
|
explicit AstNodeDType(FileLine* fl) : AstNode(fl) {
|
||||||
m_width=0; m_widthMin=0; m_generic=false;
|
m_width=0; m_widthMin=0; m_generic=false;
|
||||||
}
|
}
|
||||||
ASTNODE_BASE_FUNCS(NodeDType)
|
ASTNODE_BASE_FUNCS(NodeDType)
|
||||||
@@ -1697,7 +1746,7 @@ private:
|
|||||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||||
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
||||||
public:
|
public:
|
||||||
AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
explicit AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
||||||
m_refDTypep = NULL;
|
m_refDTypep = NULL;
|
||||||
}
|
}
|
||||||
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
||||||
@@ -1706,7 +1755,7 @@ public:
|
|||||||
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
||||||
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
||||||
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
||||||
m_refDTypep = m_refDTypep->clonep()->castNodeDType();
|
m_refDTypep = m_refDTypep->clonep();
|
||||||
}}
|
}}
|
||||||
virtual bool same(AstNode* samep) const {
|
virtual bool same(AstNode* samep) const {
|
||||||
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
||||||
@@ -1742,9 +1791,9 @@ public:
|
|||||||
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
||||||
:AstNodeBiop(fl, fromp, bitp) {}
|
:AstNodeBiop(fl, fromp, bitp) {}
|
||||||
ASTNODE_BASE_FUNCS(NodeSel)
|
ASTNODE_BASE_FUNCS(NodeSel)
|
||||||
AstNode* fromp() const { return op1p()->castNode(); } // op1 = Extracting what (NULL=TBD during parsing)
|
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
|
||||||
void fromp(AstNode* nodep) { setOp1p(nodep); }
|
void fromp(AstNode* nodep) { setOp1p(nodep); }
|
||||||
AstNode* bitp() const { return op2p()->castNode(); } // op2 = Msb selection expression
|
AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression
|
||||||
void bitp(AstNode* nodep) { setOp2p(nodep); }
|
void bitp(AstNode* nodep) { setOp2p(nodep); }
|
||||||
int bitConst() const;
|
int bitConst() const;
|
||||||
virtual bool hasDType() const { return true; }
|
virtual bool hasDType() const { return true; }
|
||||||
@@ -1790,16 +1839,17 @@ public:
|
|||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
virtual string name() const { return m_name; } // * = Var name
|
virtual string name() const { return m_name; } // * = Var name
|
||||||
virtual bool maybePointedTo() const { return true; }
|
virtual bool maybePointedTo() const { return true; }
|
||||||
|
virtual bool isGateOptimizable() const { return !((m_dpiExport || m_dpiImport) && !m_pure); }
|
||||||
// {AstFunc only} op1 = Range output variable
|
// {AstFunc only} op1 = Range output variable
|
||||||
virtual void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
string cname() const { return m_cname; }
|
string cname() const { return m_cname; }
|
||||||
void cname(const string& cname) { m_cname = cname; }
|
void cname(const string& cname) { m_cname = cname; }
|
||||||
// op1 = Output variable (functions only, NULL for tasks)
|
// op1 = Output variable (functions only, NULL for tasks)
|
||||||
AstNode* fvarp() const { return op1p()->castNode(); }
|
AstNode* fvarp() const { return op1p(); }
|
||||||
void addFvarp(AstNode* nodep) { addNOp1p(nodep); }
|
void addFvarp(AstNode* nodep) { addNOp1p(nodep); }
|
||||||
bool isFunction() const { return fvarp()!=NULL; }
|
bool isFunction() const { return fvarp()!=NULL; }
|
||||||
// op3 = Statements/Ports/Vars
|
// op3 = Statements/Ports/Vars
|
||||||
AstNode* stmtsp() const { return op3p()->castNode(); } // op3 = List of statements
|
AstNode* stmtsp() const { return op3p(); } // op3 = List of statements
|
||||||
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
|
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
|
||||||
// op4 = scope name
|
// op4 = scope name
|
||||||
AstScopeName* scopeNamep() const { return op4p()->castScopeName(); }
|
AstScopeName* scopeNamep() const { return op4p()->castScopeName(); }
|
||||||
@@ -1844,10 +1894,11 @@ public:
|
|||||||
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
||||||
virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; }
|
virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; }
|
||||||
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
||||||
m_taskp = m_taskp->clonep()->castNodeFTask();
|
m_taskp = m_taskp->clonep();
|
||||||
}}
|
}}
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
virtual string name() const { return m_name; } // * = Var name
|
virtual string name() const { return m_name; } // * = Var name
|
||||||
|
virtual bool isGateOptimizable() const { return m_taskp && m_taskp->isGateOptimizable(); }
|
||||||
string dotted() const { return m_dotted; } // * = Scope name or ""
|
string dotted() const { return m_dotted; } // * = Scope name or ""
|
||||||
string prettyDotted() const { return prettyName(dotted()); }
|
string prettyDotted() const { return prettyName(dotted()); }
|
||||||
string inlinedDots() const { return m_inlinedDots; }
|
string inlinedDots() const { return m_inlinedDots; }
|
||||||
@@ -1861,7 +1912,7 @@ public:
|
|||||||
// op1 = namep
|
// op1 = namep
|
||||||
AstNode* namep() const { return op1p(); }
|
AstNode* namep() const { return op1p(); }
|
||||||
// op2 = Pin interconnection list
|
// op2 = Pin interconnection list
|
||||||
AstNode* pinsp() const { return op2p()->castNode(); }
|
AstNode* pinsp() const { return op2p(); }
|
||||||
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
|
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
|
||||||
// op3 = scope tracking
|
// op3 = scope tracking
|
||||||
AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
|
AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
|
||||||
@@ -1893,7 +1944,7 @@ public:
|
|||||||
virtual void dump(ostream& str);
|
virtual void dump(ostream& str);
|
||||||
virtual bool maybePointedTo() const { return true; }
|
virtual bool maybePointedTo() const { return true; }
|
||||||
virtual string name() const { return m_name; }
|
virtual string name() const { return m_name; }
|
||||||
AstNode* stmtsp() const { return op2p()->castNode(); } // op2 = List of statements
|
AstNode* stmtsp() const { return op2p(); } // op2 = List of statements
|
||||||
AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks
|
AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks
|
||||||
// METHODS
|
// METHODS
|
||||||
void addInlinesp(AstNode* nodep) { addOp1p(nodep); }
|
void addInlinesp(AstNode* nodep) { addOp1p(nodep); }
|
||||||
@@ -1943,8 +1994,8 @@ inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst
|
|||||||
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
|
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
|
||||||
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
|
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
|
||||||
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
|
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
|
||||||
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(node2p, true, false); }
|
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, false); }
|
||||||
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(node2p, true, true); }
|
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, true); }
|
||||||
|
|
||||||
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
||||||
|
|
||||||
@@ -1955,8 +2006,8 @@ inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsC
|
|||||||
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
|
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
|
||||||
|
|
||||||
inline void AstIfaceRefDType::cloneRelink() {
|
inline void AstIfaceRefDType::cloneRelink() {
|
||||||
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep()->castCell();
|
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep();
|
||||||
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep()->castIface();
|
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep();
|
||||||
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep()->castModport(); }
|
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); }
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+9
-5
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -53,7 +53,7 @@ const char* AstNodeVarRef::broken() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstNodeVarRef::cloneRelink() {
|
void AstNodeVarRef::cloneRelink() {
|
||||||
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep()->castVar(); }
|
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
int AstNodeSel::bitConst() const {
|
int AstNodeSel::bitConst() const {
|
||||||
@@ -386,6 +386,7 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
|||||||
// TODO this function should be removed in favor of recursing the dtype(),
|
// TODO this function should be removed in favor of recursing the dtype(),
|
||||||
// as that allows for more complicated data types.
|
// as that allows for more complicated data types.
|
||||||
int dim = 0;
|
int dim = 0;
|
||||||
|
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
@@ -420,6 +421,7 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
|||||||
|
|
||||||
uint32_t AstNodeDType::arrayUnpackedElements() {
|
uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||||
uint32_t entries=1;
|
uint32_t entries=1;
|
||||||
|
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
if (AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType()) {
|
||||||
@@ -438,6 +440,7 @@ pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
|
|||||||
// How many array dimensions (packed,unpacked) does this Var have?
|
// How many array dimensions (packed,unpacked) does this Var have?
|
||||||
uint32_t packed = 0;
|
uint32_t packed = 0;
|
||||||
uint32_t unpacked = 0;
|
uint32_t unpacked = 0;
|
||||||
|
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
|
||||||
for (AstNodeDType* dtypep=this; dtypep; ) {
|
for (AstNodeDType* dtypep=this; dtypep; ) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
if (AstNodeArrayDType* adtypep = dtypep->castNodeArrayDType()) {
|
||||||
@@ -492,9 +495,9 @@ const char* AstScope::broken() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AstScope::cloneRelink() {
|
void AstScope::cloneRelink() {
|
||||||
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep()->castScope();
|
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep();
|
||||||
if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep()->castCell();
|
if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep();
|
||||||
if (m_modp && ((AstNode*)m_modp)->clonep()) ((AstNode*)m_modp)->clonep()->castNodeModule();
|
if (m_modp && ((AstNode*)m_modp)->clonep()) ((AstNode*)m_modp)->clonep();
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstScope::nameDotless() const {
|
string AstScope::nameDotless() const {
|
||||||
@@ -974,6 +977,7 @@ void AstVar::dump(ostream& str) {
|
|||||||
if (attrFileDescr()) str<<" [aFD]";
|
if (attrFileDescr()) str<<" [aFD]";
|
||||||
if (isFuncReturn()) str<<" [FUNCRTN]";
|
if (isFuncReturn()) str<<" [FUNCRTN]";
|
||||||
else if (isFuncLocal()) str<<" [FUNC]";
|
else if (isFuncLocal()) str<<" [FUNC]";
|
||||||
|
if (!attrClocker().unknown()) str<<" ["<<attrClocker().ascii()<<"] ";
|
||||||
str<<" "<<varType();
|
str<<" "<<varType();
|
||||||
}
|
}
|
||||||
void AstSenTree::dump(ostream& str) {
|
void AstSenTree::dump(ostream& str) {
|
||||||
|
|||||||
+598
-351
File diff suppressed because it is too large
Load Diff
+40
-15
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -56,7 +56,7 @@ public:
|
|||||||
m_anyFuncInBegin = false;
|
m_anyFuncInBegin = false;
|
||||||
}
|
}
|
||||||
~BeginState() {}
|
~BeginState() {}
|
||||||
void userMarkChanged(AstNodeFTask* nodep) {
|
void userMarkChanged(AstNode* nodep) {
|
||||||
nodep->user1(true);
|
nodep->user1(true);
|
||||||
m_anyFuncInBegin = true;
|
m_anyFuncInBegin = true;
|
||||||
}
|
}
|
||||||
@@ -84,13 +84,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_repeatNum = 0;
|
m_repeatNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTask* nodep) {
|
||||||
UINFO(8," "<<nodep<<endl);
|
UINFO(8," "<<nodep<<endl);
|
||||||
// Rename it
|
// Rename it
|
||||||
if (m_unnamedScope != "") {
|
if (m_unnamedScope != "") {
|
||||||
@@ -113,7 +113,7 @@ private:
|
|||||||
m_namedScope = oldScope;
|
m_namedScope = oldScope;
|
||||||
m_unnamedScope = oldUnnamed;
|
m_unnamedScope = oldUnnamed;
|
||||||
}
|
}
|
||||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
virtual void visit(AstBegin* nodep) {
|
||||||
// Begin blocks were only useful in variable creation, change names and delete
|
// Begin blocks were only useful in variable creation, change names and delete
|
||||||
UINFO(8," "<<nodep<<endl);
|
UINFO(8," "<<nodep<<endl);
|
||||||
string oldScope = m_namedScope;
|
string oldScope = m_namedScope;
|
||||||
@@ -160,21 +160,23 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
}
|
}
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep) {
|
||||||
if (m_unnamedScope != "") {
|
if (m_unnamedScope != "") {
|
||||||
// Rename it
|
// Rename it
|
||||||
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
|
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
|
||||||
|
m_statep->userMarkChanged(nodep);
|
||||||
// Move to module
|
// Move to module
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
if (m_ftaskp) m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func
|
if (m_ftaskp) m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func
|
||||||
else m_modp->addStmtp(nodep);
|
else m_modp->addStmtp(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep) {
|
||||||
UINFO(8," CELL "<<nodep<<endl);
|
UINFO(8," CELL "<<nodep<<endl);
|
||||||
if (m_namedScope != "") {
|
if (m_namedScope != "") {
|
||||||
|
m_statep->userMarkChanged(nodep);
|
||||||
// Rename it
|
// Rename it
|
||||||
nodep->name(m_namedScope+"__DOT__"+nodep->name());
|
nodep->name(m_namedScope+"__DOT__"+nodep->name());
|
||||||
UINFO(8," rename to "<<nodep->name()<<endl);
|
UINFO(8," rename to "<<nodep->name()<<endl);
|
||||||
@@ -182,8 +184,16 @@ private:
|
|||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
m_modp->addStmtp(nodep);
|
m_modp->addStmtp(nodep);
|
||||||
}
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
virtual void visit(AstVarXRef* nodep) {
|
||||||
|
UINFO(9, " VARXREF "<<nodep<<endl);
|
||||||
|
if (m_namedScope != "" && nodep->inlinedDots() == "") {
|
||||||
|
nodep->inlinedDots(m_namedScope);
|
||||||
|
UINFO(9, " rescope to "<<nodep<<endl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstScopeName* nodep) {
|
||||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||||
// Similar code in V3Inline
|
// Similar code in V3Inline
|
||||||
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
||||||
@@ -196,13 +206,13 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
virtual void visit(AstCoverDecl* nodep) {
|
||||||
// Don't need to fix path in coverage statements, they're not under
|
// Don't need to fix path in coverage statements, they're not under
|
||||||
// any BEGINs, but V3Coverage adds them all under the module itself.
|
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
// VISITORS - LINT CHECK
|
// VISITORS - LINT CHECK
|
||||||
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
virtual void visit(AstIf* nodep) { // Note not AstNodeIf; other types don't get covered
|
||||||
// Check IFDEPTH warning - could be in other transform files if desire
|
// Check IFDEPTH warning - could be in other transform files if desire
|
||||||
int prevIfDepth = m_ifDepth;
|
int prevIfDepth = m_ifDepth;
|
||||||
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
|
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
|
||||||
@@ -215,8 +225,8 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_ifDepth = prevIfDepth;
|
m_ifDepth = prevIfDepth;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -242,15 +252,30 @@ private:
|
|||||||
// AstNodeFTask::user1p // Node replaced, rename it
|
// AstNodeFTask::user1p // Node replaced, rename it
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTaskRef* nodep) {
|
||||||
if (nodep->taskp()->user1()) { // It was converted
|
if (nodep->taskp()->user1()) { // It was converted
|
||||||
UINFO(9, " relinkFTask "<<nodep<<endl);
|
UINFO(9, " relinkFTask "<<nodep<<endl);
|
||||||
nodep->name(nodep->taskp()->name());
|
nodep->name(nodep->taskp()->name());
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstVarRef* nodep) {
|
||||||
|
if (nodep->varp()->user1()) { // It was converted
|
||||||
|
UINFO(9, " relinVarRef "<<nodep<<endl);
|
||||||
|
nodep->name(nodep->varp()->name());
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
virtual void visit(AstIfaceRefDType* nodep) {
|
||||||
|
// May have changed cell names
|
||||||
|
// TypeTable is always after all modules, so names are stable
|
||||||
|
UINFO(8," IFACEREFDTYPE "<<nodep<<endl);
|
||||||
|
if (nodep->cellp()) nodep->cellName(nodep->cellp()->name());
|
||||||
|
UINFO(8," rename to "<<nodep<<endl);
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+6
-6
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -75,7 +75,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
virtual void visit(AstNodeIf* nodep) {
|
||||||
UINFO(4," IF: "<<nodep<<endl);
|
UINFO(4," IF: "<<nodep<<endl);
|
||||||
int lastLikely = m_likely;
|
int lastLikely = m_likely;
|
||||||
int lastUnlikely = m_unlikely;
|
int lastUnlikely = m_unlikely;
|
||||||
@@ -101,17 +101,17 @@ private:
|
|||||||
m_likely = lastLikely;
|
m_likely = lastLikely;
|
||||||
m_unlikely = lastUnlikely;
|
m_unlikely = lastUnlikely;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCCall* nodep, AstNUser*) {
|
virtual void visit(AstCCall* nodep) {
|
||||||
checkUnlikely(nodep);
|
checkUnlikely(nodep);
|
||||||
nodep->funcp()->user1Inc();
|
nodep->funcp()->user1Inc();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
checkUnlikely(nodep);
|
checkUnlikely(nodep);
|
||||||
m_cfuncsp.push_back(nodep);
|
m_cfuncsp.push_back(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
checkUnlikely(nodep);
|
checkUnlikely(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
BranchVisitor(AstNetlist* nodep) {
|
explicit BranchVisitor(AstNetlist* nodep) {
|
||||||
reset();
|
reset();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
calc_tasks();
|
calc_tasks();
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+13
-6
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -186,14 +186,18 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Nothing! // This may be called deep inside other routines
|
// Nothing! // This may be called deep inside other routines
|
||||||
// // so userp and friends may not be used
|
// // so userp and friends may not be used
|
||||||
// VISITORS
|
// METHODS
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
void processAndIterate(AstNode* nodep) {
|
||||||
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
|
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
|
||||||
nodep->iterateChildrenConst(*this);
|
nodep->iterateChildrenConst(*this);
|
||||||
}
|
}
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstNode* nodep) {
|
||||||
|
processAndIterate(nodep);
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
BrokenMarkVisitor(AstNetlist* nodep) {
|
explicit BrokenMarkVisitor(AstNetlist* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~BrokenMarkVisitor() {}
|
virtual ~BrokenMarkVisitor() {}
|
||||||
@@ -210,7 +214,7 @@ private:
|
|||||||
nodep->v3fatalSrc("Width != WidthMin");
|
nodep->v3fatalSrc("Width != WidthMin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
void processAndIterate(AstNode* nodep) {
|
||||||
BrokenTable::setUnder(nodep,true);
|
BrokenTable::setUnder(nodep,true);
|
||||||
if (const char* whyp=nodep->broken()) {
|
if (const char* whyp=nodep->broken()) {
|
||||||
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
|
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
|
||||||
@@ -232,9 +236,12 @@ private:
|
|||||||
nodep->iterateChildrenConst(*this);
|
nodep->iterateChildrenConst(*this);
|
||||||
BrokenTable::setUnder(nodep,false);
|
BrokenTable::setUnder(nodep,false);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstNode* nodep) {
|
||||||
|
processAndIterate(nodep);
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
BrokenCheckVisitor(AstNetlist* nodep) {
|
explicit BrokenCheckVisitor(AstNetlist* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~BrokenCheckVisitor() {}
|
virtual ~BrokenCheckVisitor() {}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Generate C language constructors and AstCReset nodes.
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
//
|
||||||
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
// V3CCtors's Transformations:
|
||||||
|
// Iterates over all modules and
|
||||||
|
// for all AstVar, create a creates a AstCReset node in an _ctor_var_reset AstCFunc.
|
||||||
|
// for all AstCoverDecl, move the declaration into a _configure_coverage AstCFunc.
|
||||||
|
// For each variable that needs reset, add a AstCReset node.
|
||||||
|
//
|
||||||
|
// This transformation honors outputSplitCFuncs.
|
||||||
|
//*************************************************************************
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "V3Global.h"
|
||||||
|
#include "V3EmitCBase.h"
|
||||||
|
#include "V3CCtors.h"
|
||||||
|
|
||||||
|
class V3CCtorsVisitor {
|
||||||
|
private:
|
||||||
|
string m_basename;
|
||||||
|
string m_argsp;
|
||||||
|
string m_callargsp;
|
||||||
|
AstNodeModule* m_modp; // Current module
|
||||||
|
AstCFunc* m_tlFuncp; // Top level function being built
|
||||||
|
AstCFunc* m_funcp; // Current function
|
||||||
|
int m_numStmts; // Number of statements output
|
||||||
|
int m_funcNum; // Function number being built
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add(AstNode* nodep) {
|
||||||
|
if (v3Global.opt.outputSplitCFuncs()
|
||||||
|
&& v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||||
|
m_funcp = NULL;
|
||||||
|
}
|
||||||
|
if (!m_funcp) {
|
||||||
|
m_funcp = new AstCFunc(m_modp->fileline(), m_basename + "_" + cvtToStr(++m_funcNum), NULL, "void");
|
||||||
|
m_funcp->isStatic(false);
|
||||||
|
m_funcp->declPrivate(true);
|
||||||
|
m_funcp->slow(true);
|
||||||
|
m_funcp->argTypes(m_argsp);
|
||||||
|
m_modp->addStmtp(m_funcp);
|
||||||
|
|
||||||
|
// Add a top call to it
|
||||||
|
AstCCall* callp = new AstCCall(m_modp->fileline(), m_funcp);
|
||||||
|
callp->argTypes(m_callargsp);
|
||||||
|
|
||||||
|
m_tlFuncp->addStmtsp(callp);
|
||||||
|
m_numStmts = 0;
|
||||||
|
}
|
||||||
|
m_funcp->addStmtsp(nodep);
|
||||||
|
m_numStmts += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="") {
|
||||||
|
m_basename = basename;
|
||||||
|
m_argsp = argsp;
|
||||||
|
m_callargsp = callargsp;
|
||||||
|
m_modp = nodep;
|
||||||
|
m_numStmts = 0;
|
||||||
|
m_funcNum = 0;
|
||||||
|
m_tlFuncp = new AstCFunc(nodep->fileline(), basename, NULL, "void");
|
||||||
|
m_tlFuncp->declPrivate(true);
|
||||||
|
m_tlFuncp->isStatic(false);
|
||||||
|
m_tlFuncp->slow(true);
|
||||||
|
m_tlFuncp->argTypes(m_argsp);
|
||||||
|
m_funcp = m_tlFuncp;
|
||||||
|
m_modp->addStmtp(m_tlFuncp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
void V3CCtors::cctorsAll() {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
|
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
|
||||||
|
// Process each module in turn
|
||||||
|
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
|
||||||
|
V3CCtorsVisitor configure_coverage (modp, "_configure_coverage",
|
||||||
|
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first");
|
||||||
|
|
||||||
|
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||||
|
AstVar* varp = np->castVar();
|
||||||
|
if (varp) var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
|
||||||
|
AstCoverDecl* coverp = np->castCoverDecl();
|
||||||
|
if (coverp) {
|
||||||
|
AstNode* backp = coverp->backp();
|
||||||
|
coverp->unlinkFrBack();
|
||||||
|
configure_coverage.add(coverp);
|
||||||
|
np = backp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Emit CFunc's for class construction and configuration
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
//
|
||||||
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef _V3CCTORS_H_
|
||||||
|
#define _V3CCTORS_H_ 1
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "V3Error.h"
|
||||||
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
class V3CCtors {
|
||||||
|
public:
|
||||||
|
static void cctorsAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
+19
-21
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -65,7 +65,7 @@ private:
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
virtual void visit(AstNodeCase* nodep) {
|
||||||
if (nodep->castCase() && nodep->castCase()->casex()) {
|
if (nodep->castCase() && nodep->castCase()->casex()) {
|
||||||
nodep->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)");
|
nodep->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)");
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ private:
|
|||||||
m_caseExprp = NULL;
|
m_caseExprp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep) {
|
||||||
// See also neverItem
|
// See also neverItem
|
||||||
if (m_caseExprp && nodep->num().isFourState()) {
|
if (m_caseExprp && nodep->num().isFourState()) {
|
||||||
if (m_caseExprp->castGenCase()) {
|
if (m_caseExprp->castGenCase()) {
|
||||||
@@ -107,12 +107,12 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CaseLintVisitor(AstNodeCase* nodep) {
|
explicit CaseLintVisitor(AstNodeCase* nodep) {
|
||||||
m_caseExprp = NULL;
|
m_caseExprp = NULL;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ private:
|
|||||||
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
|
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
|
||||||
}
|
}
|
||||||
if (same) {
|
if (same) {
|
||||||
tree1p->deleteTree(); tree1p=NULL;
|
tree1p->deleteTree(); VL_DANGLING(tree1p);
|
||||||
return tree0p;
|
return tree0p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,8 +295,8 @@ private:
|
|||||||
|
|
||||||
if (ifrootp) nodep->replaceWith(ifrootp);
|
if (ifrootp) nodep->replaceWith(ifrootp);
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
cexprp->deleteTree(); cexprp=NULL;
|
cexprp->deleteTree(); VL_DANGLING(cexprp);
|
||||||
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
|
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ private:
|
|||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (iconstp && neverItem(nodep, iconstp)) {
|
if (iconstp && neverItem(nodep, iconstp)) {
|
||||||
// X in casez can't ever be executed
|
// X in casez can't ever be executed
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); VL_DANGLING(icondp); VL_DANGLING(iconstp);
|
||||||
// For simplicity, make expression that is not equal, and let later
|
// For simplicity, make expression that is not equal, and let later
|
||||||
// optimizations remove it
|
// optimizations remove it
|
||||||
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
||||||
@@ -351,7 +351,7 @@ private:
|
|||||||
AstNode* and2p = new AstAnd(itemp->fileline(),
|
AstNode* and2p = new AstAnd(itemp->fileline(),
|
||||||
new AstConst(itemp->fileline(), numval),
|
new AstConst(itemp->fileline(), numval),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); VL_DANGLING(icondp); VL_DANGLING(iconstp);
|
||||||
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
|
||||||
} else {
|
} else {
|
||||||
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
||||||
@@ -369,7 +369,7 @@ private:
|
|||||||
itemp->condsp(ifexprp);
|
itemp->condsp(ifexprp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cexprp->deleteTree(); cexprp=NULL;
|
cexprp->deleteTree(); VL_DANGLING(cexprp);
|
||||||
if (!hadDefault) {
|
if (!hadDefault) {
|
||||||
// If there was no default, add a empty one, this greatly simplifies below code
|
// If there was no default, add a empty one, this greatly simplifies below code
|
||||||
// and constant propagation will just eliminate it for us later.
|
// and constant propagation will just eliminate it for us later.
|
||||||
@@ -408,10 +408,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // Make the new lower IF and attach in the tree
|
{ // Make the new lower IF and attach in the tree
|
||||||
AstNode* itemexprp = ifexprp; ifexprp=NULL;
|
AstNode* itemexprp = ifexprp; VL_DANGLING(ifexprp);
|
||||||
if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
|
if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
|
||||||
itemexprp->deleteTree(); itemexprp=NULL;
|
itemexprp->deleteTree(); VL_DANGLING(itemexprp);
|
||||||
// cppcheck-suppress redundantAssignment
|
|
||||||
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
|
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
|
||||||
}
|
}
|
||||||
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
|
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
|
||||||
@@ -427,7 +426,7 @@ private:
|
|||||||
if (debug()>=9) grouprootp->dumpTree(cout," _new: ");
|
if (debug()>=9) grouprootp->dumpTree(cout," _new: ");
|
||||||
if (grouprootp) nodep->replaceWith(grouprootp);
|
if (grouprootp) nodep->replaceWith(grouprootp);
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceCaseParallel(AstCase* nodep, bool noOverlapsAllCovered) {
|
void replaceCaseParallel(AstCase* nodep, bool noOverlapsAllCovered) {
|
||||||
@@ -452,7 +451,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep) {
|
||||||
V3Case::caseLint(nodep);
|
V3Case::caseLint(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (debug()>=9) nodep->dumpTree(cout," case_old: ");
|
if (debug()>=9) nodep->dumpTree(cout," case_old: ");
|
||||||
@@ -460,22 +459,21 @@ private:
|
|||||||
// It's a simple priority encoder or complete statement
|
// It's a simple priority encoder or complete statement
|
||||||
// we can make a tree of statements to avoid extra comparisons
|
// we can make a tree of statements to avoid extra comparisons
|
||||||
++m_statCaseFast;
|
++m_statCaseFast;
|
||||||
replaceCaseFast(nodep); nodep=NULL;
|
replaceCaseFast(nodep); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
++m_statCaseSlow;
|
++m_statCaseSlow;
|
||||||
// cppcheck-supporess uselessAssignmentPtrArg
|
replaceCaseComplicated(nodep); VL_DANGLING(nodep);
|
||||||
replaceCaseComplicated(nodep); nodep=NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CaseVisitor(AstNetlist* nodep) {
|
explicit CaseVisitor(AstNetlist* nodep) {
|
||||||
m_caseNoOverlapsAllCovered = false;
|
m_caseNoOverlapsAllCovered = false;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+11
-11
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -107,19 +107,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
virtual void visit(AstNodeUniop* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user1(nodep->lhsp()->user1());
|
nodep->user1(nodep->lhsp()->user1());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
virtual void visit(AstNodeBiop* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user1(nodep->lhsp()->user1()
|
nodep->user1(nodep->lhsp()->user1()
|
||||||
| nodep->rhsp()->user1());
|
| nodep->rhsp()->user1());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
|
virtual void visit(AstNodeTriop* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user1(nodep->lhsp()->user1()
|
nodep->user1(nodep->lhsp()->user1()
|
||||||
| nodep->rhsp()->user1()
|
| nodep->rhsp()->user1()
|
||||||
@@ -128,12 +128,12 @@ private:
|
|||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
virtual void visit(AstCCast* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureLower32Cast(nodep);
|
insureLower32Cast(nodep);
|
||||||
nodep->user1(1);
|
nodep->user1(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNegate* nodep, AstNUser*) {
|
virtual void visit(AstNegate* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user1(nodep->lhsp()->user1());
|
nodep->user1(nodep->lhsp()->user1());
|
||||||
if (nodep->lhsp()->widthMin()==1) {
|
if (nodep->lhsp()->widthMin()==1) {
|
||||||
@@ -145,7 +145,7 @@ private:
|
|||||||
insureCast(nodep->lhsp());
|
insureCast(nodep->lhsp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (!nodep->lvalue()
|
if (!nodep->lvalue()
|
||||||
&& !nodep->backp()->castCCast()
|
&& !nodep->backp()->castCCast()
|
||||||
&& nodep->backp()->castNodeMath()
|
&& nodep->backp()->castNodeMath()
|
||||||
@@ -158,7 +158,7 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->user1(1);
|
nodep->user1(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep) {
|
||||||
// Constants are of unknown size if smaller than 33 bits, becase
|
// Constants are of unknown size if smaller than 33 bits, becase
|
||||||
// we're too lazy to wrap every constant in the universe in
|
// we're too lazy to wrap every constant in the universe in
|
||||||
// ((IData)#).
|
// ((IData)#).
|
||||||
@@ -166,17 +166,17 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOPs
|
// NOPs
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {}
|
virtual void visit(AstVar* nodep) {}
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CastVisitor(AstNetlist* nodep) {
|
explicit CastVisitor(AstNetlist* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CastVisitor() {}
|
virtual ~CastVisitor() {}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+30
-30
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -138,7 +138,7 @@ private:
|
|||||||
ofstream* m_ofp; // Output file
|
ofstream* m_ofp; // Output file
|
||||||
string m_prefix;
|
string m_prefix;
|
||||||
|
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
*m_ofp<<m_prefix;
|
*m_ofp<<m_prefix;
|
||||||
if (nodep->user3()) *m_ofp<<" %%";
|
if (nodep->user3()) *m_ofp<<" %%";
|
||||||
else *m_ofp<<" ";
|
else *m_ofp<<" ";
|
||||||
@@ -172,7 +172,7 @@ private:
|
|||||||
int m_maxLineno;
|
int m_maxLineno;
|
||||||
size_t m_maxFilenameLen;
|
size_t m_maxFilenameLen;
|
||||||
|
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Keeping line+filename lengths separate is much faster than calling ascii().length()
|
// Keeping line+filename lengths separate is much faster than calling ascii().length()
|
||||||
if (nodep->fileline()->lineno() >= m_maxLineno) {
|
if (nodep->fileline()->lineno() >= m_maxLineno) {
|
||||||
@@ -184,7 +184,7 @@ private:
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CdcWidthVisitor(AstNode* nodep) {
|
explicit CdcWidthVisitor(AstNode* nodep) {
|
||||||
m_maxLineno = 0;
|
m_maxLineno = 0;
|
||||||
m_maxFilenameLen = 0;
|
m_maxFilenameLen = 0;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
@@ -496,7 +496,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc_edges.txt";
|
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc_edges.txt";
|
||||||
const auto_ptr<ofstream> ofp (V3File::new_ofstream(filename));
|
const VL_UNIQUE_PTR<ofstream> ofp (V3File::new_ofstream(filename));
|
||||||
if (ofp->fail()) v3fatalSrc("Can't write "<<filename);
|
if (ofp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||||
*ofp<<"Edge Report for "<<v3Global.opt.prefix()<<endl;
|
*ofp<<"Edge Report for "<<v3Global.opt.prefix()<<endl;
|
||||||
|
|
||||||
@@ -604,19 +604,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep) {
|
||||||
UINFO(4," SCOPE "<<nodep<<endl);
|
UINFO(4," SCOPE "<<nodep<<endl);
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
m_logicVertexp = NULL;
|
m_logicVertexp = NULL;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_scopep = NULL;
|
m_scopep = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
virtual void visit(AstActive* nodep) {
|
||||||
// Create required blocks and add to module
|
// Create required blocks and add to module
|
||||||
UINFO(4," BLOCK "<<nodep<<endl);
|
UINFO(4," BLOCK "<<nodep<<endl);
|
||||||
AstNode::user2ClearTree();
|
AstNode::user2ClearTree();
|
||||||
@@ -627,7 +627,7 @@ private:
|
|||||||
m_domainp = NULL;
|
m_domainp = NULL;
|
||||||
AstNode::user2ClearTree();
|
AstNode::user2ClearTree();
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
if (m_scopep) {
|
if (m_scopep) {
|
||||||
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
|
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
|
||||||
AstVarScope* varscp = nodep->varScopep();
|
AstVarScope* varscp = nodep->varScopep();
|
||||||
@@ -655,78 +655,78 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
virtual void visit(AstAssignDly* nodep) {
|
||||||
m_inDly = true;
|
m_inDly = true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_inDly = false;
|
m_inDly = false;
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep) {
|
||||||
// Note we look at only AstSenItems, not AstSenGate's
|
// Note we look at only AstSenItems, not AstSenGate's
|
||||||
// The gating term of a AstSenGate is normal logic
|
// The gating term of a AstSenGate is normal logic
|
||||||
m_inSenItem = true;
|
m_inSenItem = true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_inSenItem = false;
|
m_inSenItem = false;
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep) {
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
virtual void visit(AstAlwaysPublic* nodep) {
|
||||||
// CDC doesn't care about public variables
|
// CDC doesn't care about public variables
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
virtual void visit(AstSenGate* nodep) {
|
||||||
// First handle the clock part will be handled in a minute by visit AstSenItem
|
// First handle the clock part will be handled in a minute by visit AstSenItem
|
||||||
// The logic gating term is delt with as logic
|
// The logic gating term is delt with as logic
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
virtual void visit(AstAssignAlias* nodep) {
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
virtual void visit(AstAssignW* nodep) {
|
||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Math that shouldn't cause us to clear hazard
|
// Math that shouldn't cause us to clear hazard
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) { }
|
virtual void visit(AstConst* nodep) { }
|
||||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
virtual void visit(AstReplicate* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstConcat* nodep, AstNUser*) {
|
virtual void visit(AstConcat* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNot* nodep, AstNUser*) {
|
virtual void visit(AstNot* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep) {
|
||||||
if (!nodep->lsbp()->castConst()) setNodeHazard(nodep);
|
if (!nodep->lsbp()->castConst()) setNodeHazard(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeSel* nodep, AstNUser*) {
|
virtual void visit(AstNodeSel* nodep) {
|
||||||
if (!nodep->bitp()->castConst()) setNodeHazard(nodep);
|
if (!nodep->bitp()->castConst()) setNodeHazard(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignores
|
// Ignores
|
||||||
virtual void visit(AstInitial* nodep, AstNUser*) { }
|
virtual void visit(AstInitial* nodep) { }
|
||||||
virtual void visit(AstTraceInc* nodep, AstNUser*) { }
|
virtual void visit(AstTraceInc* nodep) { }
|
||||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) { }
|
virtual void visit(AstCoverToggle* nodep) { }
|
||||||
virtual void visit(AstNodeDType* nodep, AstNUser*) { }
|
virtual void visit(AstNodeDType* nodep) { }
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default
|
// Default
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
virtual void visit(AstNodeMath* nodep) {
|
||||||
setNodeHazard(nodep);
|
setNodeHazard(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CdcVisitor(AstNode* nodep) {
|
explicit CdcVisitor(AstNode* nodep) {
|
||||||
m_logicVertexp = NULL;
|
m_logicVertexp = NULL;
|
||||||
m_scopep = NULL;
|
m_scopep = NULL;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+69
-19
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -51,12 +51,54 @@ public:
|
|||||||
AstNodeModule* m_topModp; // Top module
|
AstNodeModule* m_topModp; // Top module
|
||||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||||
AstCFunc* m_chgFuncp; // Change function we're building
|
AstCFunc* m_chgFuncp; // Change function we're building
|
||||||
|
AstCFunc* m_tlChgFuncp; // Top level change function we're building
|
||||||
|
int m_numStmts; // Number of statements added to m_chgFuncp
|
||||||
|
int m_funcNum; // Number of change functions emitted
|
||||||
|
|
||||||
ChangedState() {
|
ChangedState() {
|
||||||
m_topModp = NULL;
|
m_topModp = NULL;
|
||||||
m_chgFuncp = NULL;
|
m_chgFuncp = NULL;
|
||||||
m_scopetopp = NULL;
|
m_scopetopp = NULL;
|
||||||
|
m_tlChgFuncp = NULL;
|
||||||
|
m_numStmts = 0;
|
||||||
|
m_funcNum = 0;
|
||||||
}
|
}
|
||||||
~ChangedState() {}
|
~ChangedState() {}
|
||||||
|
|
||||||
|
void maybeCreateChgFuncp() {
|
||||||
|
// Don't create an extra function call if splitting is disabled
|
||||||
|
if (!v3Global.opt.outputSplitCFuncs()) {
|
||||||
|
m_chgFuncp = m_tlChgFuncp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_chgFuncp || v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||||
|
m_chgFuncp = new AstCFunc(m_scopetopp->fileline(), "_change_request_" + cvtToStr(++m_funcNum), m_scopetopp, "QData");
|
||||||
|
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
|
m_chgFuncp->symProlog(true);
|
||||||
|
m_chgFuncp->declPrivate(true);
|
||||||
|
m_scopetopp->addActivep(m_chgFuncp);
|
||||||
|
|
||||||
|
// Add a top call to it
|
||||||
|
AstCCall* callp = new AstCCall(m_scopetopp->fileline(), m_chgFuncp);
|
||||||
|
callp->argTypes("vlSymsp");
|
||||||
|
|
||||||
|
if (!m_tlChgFuncp->stmtsp()) {
|
||||||
|
m_tlChgFuncp->addStmtsp(new AstCReturn(m_scopetopp->fileline(), callp));
|
||||||
|
} else {
|
||||||
|
AstCReturn* returnp = m_tlChgFuncp->stmtsp()->castCReturn();
|
||||||
|
if (!returnp) m_scopetopp->v3fatalSrc("Lost CReturn in top change function");
|
||||||
|
// This is currently using AstLogOr which will shortcut the evaluation if
|
||||||
|
// any function returns true. This is likely what we want and is similar to the logic already in use
|
||||||
|
// inside V3EmitC, however, it also means that verbose logging may miss to print change detect variables.
|
||||||
|
AstNode* newp = new AstCReturn(m_scopetopp->fileline(),
|
||||||
|
new AstLogOr(m_scopetopp->fileline(), callp,
|
||||||
|
returnp->lhsp()->unlinkFrBack()));
|
||||||
|
returnp->replaceWith(newp);
|
||||||
|
returnp->deleteTree(); VL_DANGLING(returnp);
|
||||||
|
}
|
||||||
|
m_numStmts = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -87,6 +129,8 @@ private:
|
|||||||
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl);
|
<<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<<endl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_statep->maybeCreateChgFuncp();
|
||||||
|
|
||||||
AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(),
|
AstChangeDet* changep = new AstChangeDet (m_vscp->fileline(),
|
||||||
m_varEqnp->cloneTree(true),
|
m_varEqnp->cloneTree(true),
|
||||||
m_newRvEqnp->cloneTree(true), false);
|
m_newRvEqnp->cloneTree(true), false);
|
||||||
@@ -95,15 +139,17 @@ private:
|
|||||||
m_newLvEqnp->cloneTree(true),
|
m_newLvEqnp->cloneTree(true),
|
||||||
m_varEqnp->cloneTree(true));
|
m_varEqnp->cloneTree(true));
|
||||||
m_statep->m_chgFuncp->addFinalsp(initp);
|
m_statep->m_chgFuncp->addFinalsp(initp);
|
||||||
|
EmitCBaseCounterVisitor visitor(initp);
|
||||||
|
m_statep->m_numStmts += visitor.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
virtual void visit(AstBasicDType* nodep) {
|
||||||
newChangeDet();
|
newChangeDet();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPackArrayDType* nodep, AstNUser*) {
|
virtual void visit(AstPackArrayDType* nodep) {
|
||||||
newChangeDet();
|
newChangeDet();
|
||||||
}
|
}
|
||||||
virtual void visit(AstUnpackArrayDType* nodep, AstNUser*) {
|
virtual void visit(AstUnpackArrayDType* nodep) {
|
||||||
for (int index=0; index < nodep->elementsConst(); ++index) {
|
for (int index=0; index < nodep->elementsConst(); ++index) {
|
||||||
AstNode* origVEp = m_varEqnp;
|
AstNode* origVEp = m_varEqnp;
|
||||||
AstNode* origNLEp = m_newLvEqnp;
|
AstNode* origNLEp = m_newLvEqnp;
|
||||||
@@ -124,7 +170,7 @@ private:
|
|||||||
m_newRvEqnp = origNREp;
|
m_newRvEqnp = origNREp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
virtual void visit(AstNodeClassDType* nodep) {
|
||||||
if (nodep->packedUnsup()) {
|
if (nodep->packedUnsup()) {
|
||||||
newChangeDet();
|
newChangeDet();
|
||||||
} else {
|
} else {
|
||||||
@@ -132,7 +178,7 @@ private:
|
|||||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
|
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-");
|
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-");
|
||||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
|
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
|
||||||
@@ -193,14 +239,15 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
if (nodep->isTop()) {
|
if (nodep->isTop()) {
|
||||||
m_statep->m_topModp = nodep;
|
m_statep->m_topModp = nodep;
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
|
||||||
|
virtual void visit(AstTopScope* nodep) {
|
||||||
UINFO(4," TS "<<nodep<<endl);
|
UINFO(4," TS "<<nodep<<endl);
|
||||||
// Clearing
|
// Clearing
|
||||||
AstNode::user1ClearTree();
|
AstNode::user1ClearTree();
|
||||||
@@ -208,18 +255,21 @@ private:
|
|||||||
AstScope* scopep = nodep->scopep();
|
AstScope* scopep = nodep->scopep();
|
||||||
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
||||||
m_statep->m_scopetopp = scopep;
|
m_statep->m_scopetopp = scopep;
|
||||||
// Create change detection function
|
|
||||||
m_statep->m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
// Create a wrapper change detection function that calls each change detection function
|
||||||
m_statep->m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
m_statep->m_tlChgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData");
|
||||||
m_statep->m_chgFuncp->symProlog(true);
|
m_statep->m_tlChgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
m_statep->m_chgFuncp->declPrivate(true);
|
m_statep->m_tlChgFuncp->symProlog(true);
|
||||||
m_statep->m_scopetopp->addActivep(m_statep->m_chgFuncp);
|
m_statep->m_tlChgFuncp->declPrivate(true);
|
||||||
// We need at least one change detect so we know to emit the correct code
|
m_statep->m_scopetopp->addActivep(m_statep->m_tlChgFuncp);
|
||||||
|
// Each change detection function needs at least one AstChangeDet
|
||||||
|
// to ensure that V3EmitC outputs the necessary code.
|
||||||
|
m_statep->maybeCreateChgFuncp();
|
||||||
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
|
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
|
||||||
//
|
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep) {
|
||||||
if (nodep->isCircular()) {
|
if (nodep->isCircular()) {
|
||||||
UINFO(8," CIRC "<<nodep<<endl);
|
UINFO(8," CIRC "<<nodep<<endl);
|
||||||
if (!nodep->user1SetOnce()) {
|
if (!nodep->user1SetOnce()) {
|
||||||
@@ -227,12 +277,12 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
virtual void visit(AstNodeMath* nodep) {
|
||||||
// Short-circuit
|
// Short-circuit
|
||||||
}
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+29
-24
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -78,7 +78,7 @@ private:
|
|||||||
if (old_dtypep->width() != width) {
|
if (old_dtypep->width() != width) {
|
||||||
// Since any given dtype's cppWidth() is the same, we can just
|
// Since any given dtype's cppWidth() is the same, we can just
|
||||||
// remember one convertion for each, and reuse it
|
// remember one convertion for each, and reuse it
|
||||||
if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNode()->castNodeDType()) {
|
if (AstNodeDType* new_dtypep = old_dtypep->user3p()->castNodeDType()) {
|
||||||
nodep->dtypep(new_dtypep);
|
nodep->dtypep(new_dtypep);
|
||||||
} else {
|
} else {
|
||||||
nodep->dtypeChgWidth(width, nodep->widthMin());
|
nodep->dtypeChgWidth(width, nodep->widthMin());
|
||||||
@@ -173,12 +173,12 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
virtual void visit(AstNodeUniop* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
computeCppWidth(nodep);
|
computeCppWidth(nodep);
|
||||||
if (nodep->cleanLhs()) {
|
if (nodep->cleanLhs()) {
|
||||||
@@ -186,45 +186,45 @@ private:
|
|||||||
}
|
}
|
||||||
setClean (nodep, nodep->cleanOut());
|
setClean (nodep, nodep->cleanOut());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
virtual void visit(AstNodeBiop* nodep) {
|
||||||
operandBiop(nodep);
|
operandBiop(nodep);
|
||||||
setClean (nodep, nodep->cleanOut());
|
setClean (nodep, nodep->cleanOut());
|
||||||
}
|
}
|
||||||
virtual void visit(AstAnd* nodep, AstNUser*) {
|
virtual void visit(AstAnd* nodep) {
|
||||||
operandBiop(nodep);
|
operandBiop(nodep);
|
||||||
setClean (nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp()));
|
setClean (nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp()));
|
||||||
}
|
}
|
||||||
virtual void visit(AstXor* nodep, AstNUser*) {
|
virtual void visit(AstXor* nodep) {
|
||||||
operandBiop(nodep);
|
operandBiop(nodep);
|
||||||
setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
||||||
}
|
}
|
||||||
virtual void visit(AstOr* nodep, AstNUser*) {
|
virtual void visit(AstOr* nodep) {
|
||||||
operandBiop(nodep);
|
operandBiop(nodep);
|
||||||
setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
setClean (nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
virtual void visit(AstNodeMath* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
computeCppWidth(nodep);
|
computeCppWidth(nodep);
|
||||||
setClean (nodep, nodep->cleanOut());
|
setClean (nodep, nodep->cleanOut());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
virtual void visit(AstNodeAssign* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
computeCppWidth(nodep);
|
computeCppWidth(nodep);
|
||||||
if (nodep->cleanRhs()) {
|
if (nodep->cleanRhs()) {
|
||||||
insureClean(nodep->rhsp());
|
insureClean(nodep->rhsp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstText* nodep, AstNUser*) {
|
virtual void visit(AstText* nodep) {
|
||||||
setClean (nodep, true);
|
setClean (nodep, true);
|
||||||
}
|
}
|
||||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
virtual void visit(AstScopeName* nodep) {
|
||||||
setClean (nodep, true);
|
setClean (nodep, true);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep) {
|
||||||
operandTriop(nodep);
|
operandTriop(nodep);
|
||||||
setClean (nodep, nodep->cleanOut());
|
setClean (nodep, nodep->cleanOut());
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
virtual void visit(AstUCFunc* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
computeCppWidth(nodep);
|
computeCppWidth(nodep);
|
||||||
setClean (nodep, false);
|
setClean (nodep, false);
|
||||||
@@ -234,53 +234,58 @@ private:
|
|||||||
}
|
}
|
||||||
insureCleanAndNext (nodep->bodysp());
|
insureCleanAndNext (nodep->bodysp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstTraceInc* nodep, AstNUser*) {
|
virtual void visit(AstTraceInc* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureCleanAndNext (nodep->valuep());
|
insureCleanAndNext (nodep->valuep());
|
||||||
}
|
}
|
||||||
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
virtual void visit(AstTypedef* nodep) {
|
||||||
|
// No cleaning, or would loose pointer to enum
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
virtual void visit(AstParamTypeDType* nodep) {
|
||||||
// No cleaning, or would loose pointer to enum
|
// No cleaning, or would loose pointer to enum
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control flow operators
|
// Control flow operators
|
||||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
virtual void visit(AstNodeCond* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureClean(nodep->condp());
|
insureClean(nodep->condp());
|
||||||
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
|
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
|
||||||
}
|
}
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureClean(nodep->condp());
|
insureClean(nodep->condp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
virtual void visit(AstNodeIf* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureClean(nodep->condp());
|
insureClean(nodep->condp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
virtual void visit(AstSFormatF* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureCleanAndNext (nodep->exprsp());
|
insureCleanAndNext (nodep->exprsp());
|
||||||
setClean(nodep, true); // generates a string, so not relevant
|
setClean(nodep, true); // generates a string, so not relevant
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCStmt* nodep, AstNUser*) {
|
virtual void visit(AstUCStmt* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureCleanAndNext (nodep->bodysp());
|
insureCleanAndNext (nodep->bodysp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstCCall* nodep, AstNUser*) {
|
virtual void visit(AstCCall* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureCleanAndNext (nodep->argsp());
|
insureCleanAndNext (nodep->argsp());
|
||||||
|
setClean (nodep, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
computeCppWidth(nodep);
|
computeCppWidth(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CleanVisitor(AstNetlist* nodep) {
|
explicit CleanVisitor(AstNetlist* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CleanVisitor() {}
|
virtual ~CleanVisitor() {}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+32
-32
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2008-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2008-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -66,7 +66,7 @@ class GaterVarVertex;
|
|||||||
class GaterVertex : public V3GraphVertex {
|
class GaterVertex : public V3GraphVertex {
|
||||||
static uint32_t s_rankNum;
|
static uint32_t s_rankNum;
|
||||||
public:
|
public:
|
||||||
GaterVertex(V3Graph* graphp)
|
explicit GaterVertex(V3Graph* graphp)
|
||||||
: V3GraphVertex(graphp) {
|
: V3GraphVertex(graphp) {
|
||||||
s_rankNum++; rank(s_rankNum);
|
s_rankNum++; rank(s_rankNum);
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ uint32_t GaterVertex::s_rankNum = 0;
|
|||||||
|
|
||||||
class GaterHeadVertex : public GaterVertex {
|
class GaterHeadVertex : public GaterVertex {
|
||||||
public:
|
public:
|
||||||
GaterHeadVertex(V3Graph* graphp)
|
explicit GaterHeadVertex(V3Graph* graphp)
|
||||||
: GaterVertex(graphp) {}
|
: GaterVertex(graphp) {}
|
||||||
virtual ~GaterHeadVertex() {}
|
virtual ~GaterHeadVertex() {}
|
||||||
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
|
|
||||||
class GaterPliVertex : public GaterVertex {
|
class GaterPliVertex : public GaterVertex {
|
||||||
public:
|
public:
|
||||||
GaterPliVertex(V3Graph* graphp)
|
explicit GaterPliVertex(V3Graph* graphp)
|
||||||
: GaterVertex(graphp) {}
|
: GaterVertex(graphp) {}
|
||||||
virtual ~GaterPliVertex() {}
|
virtual ~GaterPliVertex() {}
|
||||||
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||||
@@ -199,25 +199,25 @@ private:
|
|||||||
if (m_isSimple) nodep->iterateChildren(*this);
|
if (m_isSimple) nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstOr* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstOr* nodep) { okIterate(nodep); }
|
||||||
virtual void visit(AstAnd* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstAnd* nodep) { okIterate(nodep); }
|
||||||
virtual void visit(AstNot* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstNot* nodep) { okIterate(nodep); }
|
||||||
virtual void visit(AstLogOr* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstLogOr* nodep) { okIterate(nodep); }
|
||||||
virtual void visit(AstLogAnd* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstLogAnd* nodep) { okIterate(nodep); }
|
||||||
virtual void visit(AstLogNot* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstLogNot* nodep) { okIterate(nodep); }
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) { okIterate(nodep); }
|
virtual void visit(AstVarRef* nodep) { okIterate(nodep); }
|
||||||
|
|
||||||
// Other possibilities are equals, etc
|
// Other possibilities are equals, etc
|
||||||
// But, we don't want to get too complicated or it will take too much
|
// But, we don't want to get too complicated or it will take too much
|
||||||
// effort to calculate the gater
|
// effort to calculate the gater
|
||||||
|
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
m_isSimple = false;
|
m_isSimple = false;
|
||||||
//nodep->iterateChildren(*this);
|
//nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
GaterCondVisitor(AstNode* nodep) {
|
explicit GaterCondVisitor(AstNode* nodep) {
|
||||||
m_isSimple = true;
|
m_isSimple = true;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
@@ -248,10 +248,10 @@ class GaterBodyVisitor : public GaterBaseVisitor {
|
|||||||
uint32_t m_state; // Parsing state
|
uint32_t m_state; // Parsing state
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (nodep->lvalue()) {
|
if (nodep->lvalue()) {
|
||||||
AstVarScope* vscp = nodep->varScopep();
|
AstVarScope* vscp = nodep->varScopep();
|
||||||
if (vscp->user2p()->castNode() == m_exprp) {
|
if (vscp->user2p() == m_exprp) {
|
||||||
// This variable's block needs to move to the new always
|
// This variable's block needs to move to the new always
|
||||||
if (m_original) {
|
if (m_original) {
|
||||||
UINFO(9," VARREF delete in old: "<<nodep<<endl);
|
UINFO(9," VARREF delete in old: "<<nodep<<endl);
|
||||||
@@ -272,11 +272,11 @@ class GaterBodyVisitor : public GaterBaseVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//virtual void visit(AstNodeIf* nodep, AstNUser*) { ... }
|
//virtual void visit(AstNodeIf* nodep) { ... }
|
||||||
// Not needed, it's the same handling as any other statement. Cool, huh?
|
// Not needed, it's the same handling as any other statement. Cool, huh?
|
||||||
// (We may get empty IFs but the constant propagater will rip them up for us)
|
// (We may get empty IFs but the constant propagater will rip them up for us)
|
||||||
|
|
||||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
virtual void visit(AstNodeStmt* nodep) {
|
||||||
uint32_t oldstate = m_state;
|
uint32_t oldstate = m_state;
|
||||||
// Find if children want to delete this or not.
|
// Find if children want to delete this or not.
|
||||||
// Note children may bicker, and want to both keep and delete (branches on a if)
|
// Note children may bicker, and want to both keep and delete (branches on a if)
|
||||||
@@ -296,7 +296,7 @@ class GaterBodyVisitor : public GaterBaseVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((childstate & STATE_DELETE) && !(childstate & STATE_KEEP)) {
|
if ((childstate & STATE_DELETE) && !(childstate & STATE_KEEP)) {
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
// Pass upwards we did delete
|
// Pass upwards we did delete
|
||||||
m_state |= STATE_DELETE;
|
m_state |= STATE_DELETE;
|
||||||
} else {
|
} else {
|
||||||
@@ -304,7 +304,7 @@ class GaterBodyVisitor : public GaterBaseVisitor {
|
|||||||
m_state |= STATE_KEEP;
|
m_state |= STATE_KEEP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -427,7 +427,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
for (V3GraphEdge* nextp,* edgep = m_pliVertexp->outBeginp(); edgep; edgep = nextp) {
|
for (V3GraphEdge* nextp,* edgep = m_pliVertexp->outBeginp(); edgep; edgep = nextp) {
|
||||||
nextp = edgep->outNextp(); // We may edit the list
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
if (GaterVarVertex* vVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
if (GaterVarVertex* vVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
||||||
vVxp->unlinkDelete(&m_graph); vVxp=NULL; edgep=NULL;
|
vVxp->unlinkDelete(&m_graph); VL_DANGLING(vVxp); VL_DANGLING(edgep);
|
||||||
} else {
|
} else {
|
||||||
m_graph.dump();
|
m_graph.dump();
|
||||||
v3fatalSrc("PLI vertex points to non-signal");
|
v3fatalSrc("PLI vertex points to non-signal");
|
||||||
@@ -463,7 +463,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
V3GraphVertex* toVxp = edgep->top();
|
V3GraphVertex* toVxp = edgep->top();
|
||||||
//UINFO(9," to "<<toVxp->user()<<" "<<toVxp<<endl);
|
//UINFO(9," to "<<toVxp->user()<<" "<<toVxp<<endl);
|
||||||
if ((toVxp->user() & VU_IF) && (toVxp->user() & VU_ELSE)) {
|
if ((toVxp->user() & VU_IF) && (toVxp->user() & VU_ELSE)) {
|
||||||
edgep->unlinkDelete(); edgep = NULL;
|
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||||
if (!(toVxp->user() & VU_MADE)) { // Make an edge only once
|
if (!(toVxp->user() & VU_MADE)) { // Make an edge only once
|
||||||
toVxp->user(toVxp->user() | VU_MADE);
|
toVxp->user(toVxp->user() | VU_MADE);
|
||||||
GaterEdge* inedgep = static_cast<GaterEdge*>(vertexp->inBeginp());
|
GaterEdge* inedgep = static_cast<GaterEdge*>(vertexp->inBeginp());
|
||||||
@@ -487,7 +487,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
if (toVxp->user() && toVxp->user() < depth) {
|
if (toVxp->user() && toVxp->user() < depth) {
|
||||||
// A recursion "above" us marked it,
|
// A recursion "above" us marked it,
|
||||||
// Remove this edge, it's redundant with the upper edge
|
// Remove this edge, it's redundant with the upper edge
|
||||||
edgep->unlinkDelete(); edgep=NULL;
|
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||||
} else {
|
} else {
|
||||||
GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
|
GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
|
||||||
if (cedgep->ifelseBoth()) {
|
if (cedgep->ifelseBoth()) {
|
||||||
@@ -515,7 +515,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
if (GaterIfVertex* toVxp = dynamic_cast<GaterIfVertex*>(edgep->top())) {
|
if (GaterIfVertex* toVxp = dynamic_cast<GaterIfVertex*>(edgep->top())) {
|
||||||
if (!toVxp->outBeginp()) {
|
if (!toVxp->outBeginp()) {
|
||||||
if (!nextp || nextp->top() != edgep->top()) { // Else next would disappear; we'll do it next loop
|
if (!nextp || nextp->top() != edgep->top()) { // Else next would disappear; we'll do it next loop
|
||||||
toVxp->unlinkDelete(&m_graph); toVxp=NULL; edgep=NULL;
|
toVxp->unlinkDelete(&m_graph); VL_DANGLING(toVxp); VL_DANGLING(edgep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,7 +529,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
nextp = edgep->outNextp(); // We may edit the list
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
if (GaterVarVertex* toVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
if (GaterVarVertex* toVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
||||||
if (!nextp || nextp->top() != edgep->top()) { // Else next would disappear; we'll do it next loop
|
if (!nextp || nextp->top() != edgep->top()) { // Else next would disappear; we'll do it next loop
|
||||||
toVxp->unlinkDelete(&m_graph); toVxp=NULL; edgep=NULL;
|
toVxp->unlinkDelete(&m_graph); VL_DANGLING(toVxp); VL_DANGLING(edgep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -701,7 +701,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep) {
|
||||||
if (debug()>=9) cout<<endl<<endl<<endl;
|
if (debug()>=9) cout<<endl<<endl<<endl;
|
||||||
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
||||||
if (nodep->user4SetOnce()) return;
|
if (nodep->user4SetOnce()) return;
|
||||||
@@ -751,7 +751,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
}
|
}
|
||||||
UINFO(5, " Gater done"<<endl);
|
UINFO(5, " Gater done"<<endl);
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (nodep->lvalue()) {
|
if (nodep->lvalue()) {
|
||||||
AstVarScope* vscp = nodep->varScopep();
|
AstVarScope* vscp = nodep->varScopep();
|
||||||
if (nodep->varp()->isSigPublic()) {
|
if (nodep->varp()->isSigPublic()) {
|
||||||
@@ -778,7 +778,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
virtual void visit(AstNodeIf* nodep) {
|
||||||
m_ifDepth++;
|
m_ifDepth++;
|
||||||
bool allowGater = m_directlyUnderAlw && m_ifDepth <= IF_DEPTH_MAX;
|
bool allowGater = m_directlyUnderAlw && m_ifDepth <= IF_DEPTH_MAX;
|
||||||
if (allowGater) {
|
if (allowGater) {
|
||||||
@@ -819,12 +819,12 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
m_ifDepth--;
|
m_ifDepth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
virtual void visit(AstAssignDly* nodep) {
|
||||||
// iterateChildrenAlw will detect this is a statement for us
|
// iterateChildrenAlw will detect this is a statement for us
|
||||||
iterateChildrenAlw(nodep, false);
|
iterateChildrenAlw(nodep, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
virtual void visit(AstNodeAssign* nodep) {
|
||||||
// Note NOT AssignDly; handled above, We'll just mark this block as
|
// Note NOT AssignDly; handled above, We'll just mark this block as
|
||||||
// not optimizable.
|
// not optimizable.
|
||||||
//
|
//
|
||||||
@@ -836,7 +836,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
// No reason to iterate.
|
// No reason to iterate.
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep) {
|
||||||
if (!nodep->isClocked()) {
|
if (!nodep->isClocked()) {
|
||||||
nonOptimizable(nodep, "Non-clocked sensitivity");
|
nonOptimizable(nodep, "Non-clocked sensitivity");
|
||||||
}
|
}
|
||||||
@@ -844,7 +844,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
if (m_nonopt=="") { // Else accelerate
|
if (m_nonopt=="") { // Else accelerate
|
||||||
iterateChildrenAlw(nodep, false);
|
iterateChildrenAlw(nodep, false);
|
||||||
}
|
}
|
||||||
@@ -878,7 +878,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
GaterVisitor(AstNode* nodep) {
|
explicit GaterVisitor(AstNode* nodep) {
|
||||||
// AstAlways visitor does the real work, so most zeroing needs to be in clear()
|
// AstAlways visitor does the real work, so most zeroing needs to be in clear()
|
||||||
clear();
|
clear();
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+25
-19
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -108,6 +108,12 @@ private:
|
|||||||
// HIGHEDGE: var
|
// HIGHEDGE: var
|
||||||
// LOWEDGE: ~var
|
// LOWEDGE: ~var
|
||||||
AstNode* newp = NULL;
|
AstNode* newp = NULL;
|
||||||
|
if (nodep->edgeType()==AstEdgeType::ET_ILLEGAL) {
|
||||||
|
if (!v3Global.opt.bboxUnsup()) {
|
||||||
|
nodep->v3error("Unsupported: Complicated event expression in sensitive activity list");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
AstVarScope* clkvscp = nodep->varrefp()->varScopep();
|
AstVarScope* clkvscp = nodep->varrefp()->varScopep();
|
||||||
if (nodep->edgeType()==AstEdgeType::ET_POSEDGE) {
|
if (nodep->edgeType()==AstEdgeType::ET_POSEDGE) {
|
||||||
AstVarScope* lastVscp = getCreateLastClk(clkvscp);
|
AstVarScope* lastVscp = getCreateLastClk(clkvscp);
|
||||||
@@ -182,7 +188,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
virtual void visit(AstTopScope* nodep) {
|
||||||
UINFO(4," TOPSCOPE "<<nodep<<endl);
|
UINFO(4," TOPSCOPE "<<nodep<<endl);
|
||||||
m_topScopep=nodep;
|
m_topScopep=nodep;
|
||||||
m_scopep = nodep->scopep();
|
m_scopep = nodep->scopep();
|
||||||
@@ -243,14 +249,14 @@ private:
|
|||||||
m_topScopep=NULL;
|
m_topScopep=NULL;
|
||||||
m_scopep = NULL;
|
m_scopep = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
//UINFO(4," MOD "<<nodep<<endl);
|
//UINFO(4," MOD "<<nodep<<endl);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_stableNum = 0;
|
m_stableNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp= NULL;
|
m_modp= NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep) {
|
||||||
//UINFO(4," SCOPE "<<nodep<<endl);
|
//UINFO(4," SCOPE "<<nodep<<endl);
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -261,25 +267,25 @@ private:
|
|||||||
}
|
}
|
||||||
m_scopep = NULL;
|
m_scopep = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep) {
|
||||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||||
nodep->replaceWith(cmtp);
|
nodep->replaceWith(cmtp);
|
||||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||||
stmtsp->unlinkFrBackWithNext();
|
stmtsp->unlinkFrBackWithNext();
|
||||||
cmtp->addNextHere(stmtsp);
|
cmtp->addNextHere(stmtsp);
|
||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstAlwaysPost* nodep, AstNUser*) {
|
virtual void visit(AstAlwaysPost* nodep) {
|
||||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||||
nodep->replaceWith(cmtp);
|
nodep->replaceWith(cmtp);
|
||||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||||
stmtsp->unlinkFrBackWithNext();
|
stmtsp->unlinkFrBackWithNext();
|
||||||
cmtp->addNextHere(stmtsp);
|
cmtp->addNextHere(stmtsp);
|
||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
virtual void visit(AstCoverToggle* nodep) {
|
||||||
//nodep->dumpTree(cout,"ct:");
|
//nodep->dumpTree(cout,"ct:");
|
||||||
//COVERTOGGLE(INC, ORIG, CHANGE) ->
|
//COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||||
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||||
@@ -297,18 +303,18 @@ private:
|
|||||||
newp->addIfsp(new AstAssign(nodep->fileline(),
|
newp->addIfsp(new AstAssign(nodep->fileline(),
|
||||||
changep->cloneTree(false),
|
changep->cloneTree(false),
|
||||||
origp->cloneTree(false)));
|
origp->cloneTree(false)));
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
virtual void visit(AstInitial* nodep) {
|
||||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||||
nodep->replaceWith(cmtp);
|
nodep->replaceWith(cmtp);
|
||||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||||
stmtsp->unlinkFrBackWithNext();
|
stmtsp->unlinkFrBackWithNext();
|
||||||
cmtp->addNextHere(stmtsp);
|
cmtp->addNextHere(stmtsp);
|
||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Link to global function
|
// Link to global function
|
||||||
if (nodep->formCallTree()) {
|
if (nodep->formCallTree()) {
|
||||||
@@ -318,7 +324,7 @@ private:
|
|||||||
m_finalFuncp->addStmtsp(callp);
|
m_finalFuncp->addStmtsp(callp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
virtual void visit(AstSenTree* nodep) {
|
||||||
// Delete it later; Actives still pointing to it
|
// Delete it later; Actives still pointing to it
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
pushDeletep(nodep);
|
pushDeletep(nodep);
|
||||||
@@ -335,14 +341,14 @@ private:
|
|||||||
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
||||||
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
|
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
|
||||||
}
|
}
|
||||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
virtual void visit(AstActive* nodep) {
|
||||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||||
// Need to save and restore any member state in AstUntilStable block
|
// Need to save and restore any member state in AstUntilStable block
|
||||||
if (!m_topScopep || !nodep->stmtsp()) {
|
if (!m_topScopep || !nodep->stmtsp()) {
|
||||||
// Not at the top or empty block...
|
// Not at the top or empty block...
|
||||||
// Only empty blocks should be leftover on the non-top. Killem.
|
// Only empty blocks should be leftover on the non-top. Killem.
|
||||||
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||||
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||||
@@ -374,19 +380,19 @@ private:
|
|||||||
// Move statements to function
|
// Move statements to function
|
||||||
addToEvalLoop(stmtsp);
|
addToEvalLoop(stmtsp);
|
||||||
}
|
}
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep = NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ClockVisitor(AstNetlist* nodep) {
|
explicit ClockVisitor(AstNetlist* nodep) {
|
||||||
m_modp=NULL; m_activep=NULL;
|
m_modp=NULL; m_activep=NULL;
|
||||||
m_evalFuncp = NULL;
|
m_evalFuncp = NULL;
|
||||||
m_topScopep=NULL;
|
m_topScopep=NULL;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+22
-22
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -111,7 +111,7 @@ public:
|
|||||||
callp->unlinkFrBack();
|
callp->unlinkFrBack();
|
||||||
}
|
}
|
||||||
callp->user3(true); // Dead now
|
callp->user3(true); // Dead now
|
||||||
pushDeletep(callp); callp=NULL;
|
pushDeletep(callp); VL_DANGLING(callp);
|
||||||
m_callMmap.erase(eqit); // Fix the table
|
m_callMmap.erase(eqit); // Fix the table
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,13 +134,13 @@ public:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCCall* nodep, AstNUser*) {
|
virtual void visit(AstCCall* nodep) {
|
||||||
addCall(nodep);
|
addCall(nodep);
|
||||||
}
|
}
|
||||||
// Speed things up
|
// Speed things up
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {}
|
virtual void visit(AstNodeAssign* nodep) {}
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
virtual void visit(AstNodeMath* nodep) {}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
@@ -163,13 +163,13 @@ private:
|
|||||||
// OUTPUT:
|
// OUTPUT:
|
||||||
// AstNode::user3() -> bool. True to indicate duplicated
|
// AstNode::user3() -> bool. True to indicate duplicated
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->user3(true);
|
nodep->user3(true);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
CombMarkVisitor(AstNode* nodep) {
|
explicit CombMarkVisitor(AstNode* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CombMarkVisitor() {}
|
virtual ~CombMarkVisitor() {}
|
||||||
@@ -230,7 +230,7 @@ private:
|
|||||||
CombMarkVisitor visitor(oldfuncp);
|
CombMarkVisitor visitor(oldfuncp);
|
||||||
m_call.replaceFunc(oldfuncp, NULL);
|
m_call.replaceFunc(oldfuncp, NULL);
|
||||||
oldfuncp->unlinkFrBack();
|
oldfuncp->unlinkFrBack();
|
||||||
pushDeletep(oldfuncp); oldfuncp=NULL;
|
pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ private:
|
|||||||
CombMarkVisitor visitor(oldfuncp);
|
CombMarkVisitor visitor(oldfuncp);
|
||||||
m_call.replaceFunc(oldfuncp, newfuncp);
|
m_call.replaceFunc(oldfuncp, newfuncp);
|
||||||
oldfuncp->unlinkFrBack();
|
oldfuncp->unlinkFrBack();
|
||||||
pushDeletep(oldfuncp); oldfuncp=NULL;
|
pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
|
||||||
}
|
}
|
||||||
void replaceOnlyCallFunc(AstCCall* nodep) {
|
void replaceOnlyCallFunc(AstCCall* nodep) {
|
||||||
if (AstCFunc* oldfuncp = nodep->backp()->castCFunc()) {
|
if (AstCFunc* oldfuncp = nodep->backp()->castCFunc()) {
|
||||||
@@ -274,7 +274,7 @@ private:
|
|||||||
UINFO(9," Function only has call "<<oldfuncp<<endl);
|
UINFO(9," Function only has call "<<oldfuncp<<endl);
|
||||||
m_call.deleteCall(nodep);
|
m_call.deleteCall(nodep);
|
||||||
CombMarkVisitor visitor(oldfuncp);
|
CombMarkVisitor visitor(oldfuncp);
|
||||||
replaceFuncWFunc(oldfuncp, nodep->funcp()); nodep=NULL;
|
replaceFuncWFunc(oldfuncp, nodep->funcp()); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,12 +384,12 @@ private:
|
|||||||
m_call.addCall(call2p);
|
m_call.addCall(call2p);
|
||||||
// If either new statement makes a func with only a single call, replace
|
// If either new statement makes a func with only a single call, replace
|
||||||
// the above callers to call it directly
|
// the above callers to call it directly
|
||||||
replaceOnlyCallFunc(call1p); call1p=NULL;
|
replaceOnlyCallFunc(call1p); VL_DANGLING(call1p);
|
||||||
replaceOnlyCallFunc(call2p); call2p=NULL;
|
replaceOnlyCallFunc(call2p); VL_DANGLING(call2p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep) {
|
||||||
// Track all callers of each function
|
// Track all callers of each function
|
||||||
m_call.main(nodep);
|
m_call.main(nodep);
|
||||||
//
|
//
|
||||||
@@ -398,7 +398,7 @@ private:
|
|||||||
// Required so that a module instantiating another can benefit from collapsing.
|
// Required so that a module instantiating another can benefit from collapsing.
|
||||||
nodep->iterateChildrenBackwards(*this);
|
nodep->iterateChildrenBackwards(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_modNFuncs = 0;
|
m_modNFuncs = 0;
|
||||||
@@ -426,7 +426,7 @@ private:
|
|||||||
}
|
}
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
m_funcp = nodep;
|
m_funcp = nodep;
|
||||||
if (!nodep->dontCombine()) {
|
if (!nodep->dontCombine()) {
|
||||||
if (m_state == STATE_HASH) {
|
if (m_state == STATE_HASH) {
|
||||||
@@ -437,7 +437,7 @@ private:
|
|||||||
}
|
}
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
virtual void visit(AstNodeStmt* nodep) {
|
||||||
if (m_state == STATE_HASH && m_funcp) {
|
if (m_state == STATE_HASH && m_funcp) {
|
||||||
hashStatement(nodep);
|
hashStatement(nodep);
|
||||||
}
|
}
|
||||||
@@ -448,16 +448,16 @@ private:
|
|||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstVar*, AstNUser*) {}
|
virtual void visit(AstVar*) {}
|
||||||
virtual void visit(AstTraceDecl*, AstNUser*) {}
|
virtual void visit(AstTraceDecl*) {}
|
||||||
virtual void visit(AstTraceInc*, AstNUser*) {}
|
virtual void visit(AstTraceInc*) {}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CombineVisitor(AstNetlist* nodep) {
|
explicit CombineVisitor(AstNetlist* nodep) {
|
||||||
m_modp=NULL;
|
m_modp=NULL;
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
m_state = STATE_IDLE;
|
m_state = STATE_IDLE;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2010-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+164
-147
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
|
#include "V3String.h"
|
||||||
#include "V3Const.h"
|
#include "V3Const.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3Width.h"
|
#include "V3Width.h"
|
||||||
@@ -46,15 +47,15 @@ class ConstVarMarkVisitor : public AstNVisitor {
|
|||||||
// AstVar::user4p -> bool, Var marked, 0=not set yet
|
// AstVar::user4p -> bool, Var marked, 0=not set yet
|
||||||
private:
|
private:
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (nodep->varp()) nodep->varp()->user4(1);
|
if (nodep->varp()) nodep->varp()->user4(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ConstVarMarkVisitor(AstNode* nodep) {
|
explicit ConstVarMarkVisitor(AstNode* nodep) {
|
||||||
AstNode::user4ClearTree(); // Check marked InUse before we're called
|
AstNode::user4ClearTree(); // Check marked InUse before we're called
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
@@ -68,17 +69,17 @@ class ConstVarFindVisitor : public AstNVisitor {
|
|||||||
bool m_found;
|
bool m_found;
|
||||||
private:
|
private:
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (nodep->varp() && nodep->varp()->user4()) m_found = true;
|
if (nodep->varp() && nodep->varp()->user4()) m_found = true;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ConstVarFindVisitor(AstNode* nodep) {
|
explicit ConstVarFindVisitor(AstNode* nodep) {
|
||||||
m_found = false;
|
m_found = false;
|
||||||
nodep->iterateAndNext(*this, NULL);
|
nodep->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
virtual ~ConstVarFindVisitor() {}
|
virtual ~ConstVarFindVisitor() {}
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -214,7 +215,7 @@ private:
|
|||||||
if (!operandsSame(ap, bp)) return false;
|
if (!operandsSame(ap, bp)) return false;
|
||||||
// Do it
|
// Do it
|
||||||
cp->unlinkFrBack();
|
cp->unlinkFrBack();
|
||||||
andp->unlinkFrBack()->deleteTree(); andp=NULL; notp=NULL;
|
andp->unlinkFrBack()->deleteTree(); VL_DANGLING(andp); VL_DANGLING(notp);
|
||||||
// Replace whichever branch is now dangling
|
// Replace whichever branch is now dangling
|
||||||
if (nodep->rhsp()) nodep->lhsp(cp);
|
if (nodep->rhsp()) nodep->lhsp(cp);
|
||||||
else nodep->rhsp(cp);
|
else nodep->rhsp(cp);
|
||||||
@@ -319,7 +320,7 @@ private:
|
|||||||
&& nodep->lsbConst()==0
|
&& nodep->lsbConst()==0
|
||||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||||
)) return false;
|
)) return false;
|
||||||
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
|
replaceWChild(nodep, extendp->lhsp()); VL_DANGLING(nodep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool operandSelBiLower(AstSel* nodep) {
|
bool operandSelBiLower(AstSel* nodep) {
|
||||||
@@ -338,7 +339,7 @@ private:
|
|||||||
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
|
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
|
||||||
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
|
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
|
||||||
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
|
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
|
||||||
replaceWChild(nodep, bip); nodep=NULL;
|
replaceWChild(nodep, bip); VL_DANGLING(nodep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +365,7 @@ private:
|
|||||||
V3Number num (constp->fileline(), subsize);
|
V3Number num (constp->fileline(), subsize);
|
||||||
num.opAssign(constp->num());
|
num.opAssign(constp->num());
|
||||||
nodep->lhsp(new AstConst(constp->fileline(), num));
|
nodep->lhsp(new AstConst(constp->fileline(), num));
|
||||||
constp->deleteTree(); constp=NULL;
|
constp->deleteTree(); VL_DANGLING(constp);
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -450,6 +451,8 @@ private:
|
|||||||
if (!ifvarp || !elsevarp) return false;
|
if (!ifvarp || !elsevarp) return false;
|
||||||
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
|
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
|
||||||
if (!ifvarp->sameGateTree(elsevarp)) return false;
|
if (!ifvarp->sameGateTree(elsevarp)) return false;
|
||||||
|
if (!ifp->rhsp()->gateTree()) return false;
|
||||||
|
if (!elsep->rhsp()->gateTree()) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool operandIfIf(AstNodeIf* nodep) {
|
bool operandIfIf(AstNodeIf* nodep) {
|
||||||
@@ -559,58 +562,58 @@ private:
|
|||||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||||
if (debug()>5) newp->dumpTree(cout," _new: ");
|
if (debug()>5) newp->dumpTree(cout," _new: ");
|
||||||
oldp->replaceWith(newp);
|
oldp->replaceWith(newp);
|
||||||
oldp->deleteTree(); oldp=NULL;
|
oldp->deleteTree(); VL_DANGLING(oldp);
|
||||||
}
|
}
|
||||||
void replaceNum (AstNode* nodep, uint32_t val) {
|
void replaceNum (AstNode* nodep, uint32_t val) {
|
||||||
V3Number num (nodep->fileline(), nodep->width(), val);
|
V3Number num (nodep->fileline(), nodep->width(), val);
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceNumSigned(AstNodeBiop* nodep, uint32_t val) {
|
void replaceNumSigned(AstNodeBiop* nodep, uint32_t val) {
|
||||||
// We allow both sides to be constant, as one may have come from parameter propagation, etc.
|
// We allow both sides to be constant, as one may have come from parameter propagation, etc.
|
||||||
if (m_warn && !(nodep->lhsp()->castConst() && nodep->rhsp()->castConst())) {
|
if (m_warn && !(nodep->lhsp()->castConst() && nodep->rhsp()->castConst())) {
|
||||||
nodep->v3warn(UNSIGNED,"Comparison is constant due to unsigned arithmetic");
|
nodep->v3warn(UNSIGNED,"Comparison is constant due to unsigned arithmetic");
|
||||||
}
|
}
|
||||||
replaceNum(nodep, val); nodep=NULL;
|
replaceNum(nodep, val); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceNumLimited(AstNodeBiop* nodep, uint32_t val) {
|
void replaceNumLimited(AstNodeBiop* nodep, uint32_t val) {
|
||||||
// Avoids gcc warning about same
|
// Avoids gcc warning about same
|
||||||
if (m_warn) nodep->v3warn(CMPCONST,"Comparison is constant due to limited range");
|
if (m_warn) nodep->v3warn(CMPCONST,"Comparison is constant due to limited range");
|
||||||
replaceNum(nodep, val); nodep=NULL;
|
replaceNum(nodep, val); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceZero(AstNode* nodep) {
|
void replaceZero(AstNode* nodep) {
|
||||||
replaceNum(nodep, 0); nodep=NULL;
|
replaceNum(nodep, 0); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
|
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
|
||||||
// For example, "0 * n" -> 0 if n has no side effects
|
// For example, "0 * n" -> 0 if n has no side effects
|
||||||
// Else strength reduce it to 0 & n.
|
// Else strength reduce it to 0 & n.
|
||||||
// If ever change the operation note AstAnd rule specially ignores this created pattern
|
// If ever change the operation note AstAnd rule specially ignores this created pattern
|
||||||
if (isTPure(checkp)) {
|
if (isTPure(checkp)) {
|
||||||
replaceNum(nodep, 0); nodep=NULL;
|
replaceNum(nodep, 0); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
AstNode* newp = new AstAnd(nodep->fileline(),
|
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||||
new AstConst(nodep->fileline(), 0),
|
new AstConst(nodep->fileline(), 0),
|
||||||
checkp->unlinkFrBack());
|
checkp->unlinkFrBack());
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void replaceAllOnes (AstNode* nodep) {
|
void replaceAllOnes (AstNode* nodep) {
|
||||||
V3Number ones (nodep->fileline(), nodep->width(), 0);
|
V3Number ones (nodep->fileline(), nodep->width(), 0);
|
||||||
ones.setMask(nodep->width());
|
ones.setMask(nodep->width());
|
||||||
replaceNum(nodep, ones); nodep=NULL;
|
replaceNum(nodep, ones); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceConst(AstNodeUniop* nodep) {
|
void replaceConst(AstNodeUniop* nodep) {
|
||||||
V3Number num (nodep->fileline(), nodep->width());
|
V3Number num (nodep->fileline(), nodep->width());
|
||||||
nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
|
nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
|
||||||
UINFO(4,"UNICONST -> "<<num<<endl);
|
UINFO(4,"UNICONST -> "<<num<<endl);
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceConst(AstNodeBiop* nodep) {
|
void replaceConst(AstNodeBiop* nodep) {
|
||||||
V3Number num (nodep->fileline(), nodep->width());
|
V3Number num (nodep->fileline(), nodep->width());
|
||||||
nodep->numberOperate(num, nodep->lhsp()->castConst()->num(), nodep->rhsp()->castConst()->num());
|
nodep->numberOperate(num, nodep->lhsp()->castConst()->num(), nodep->rhsp()->castConst()->num());
|
||||||
UINFO(4,"BICONST -> "<<num<<endl);
|
UINFO(4,"BICONST -> "<<num<<endl);
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceConst(AstNodeTriop* nodep) {
|
void replaceConst(AstNodeTriop* nodep) {
|
||||||
V3Number num (nodep->fileline(), nodep->width());
|
V3Number num (nodep->fileline(), nodep->width());
|
||||||
@@ -618,7 +621,7 @@ private:
|
|||||||
nodep->rhsp()->castConst()->num(),
|
nodep->rhsp()->castConst()->num(),
|
||||||
nodep->thsp()->castConst()->num());
|
nodep->thsp()->castConst()->num());
|
||||||
UINFO(4,"TRICONST -> "<<num<<endl);
|
UINFO(4,"TRICONST -> "<<num<<endl);
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceConstString (AstNode* oldp, const string& num) {
|
void replaceConstString (AstNode* oldp, const string& num) {
|
||||||
@@ -628,7 +631,7 @@ private:
|
|||||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||||
if (debug()>5) newp->dumpTree(cout," _new: ");
|
if (debug()>5) newp->dumpTree(cout," _new: ");
|
||||||
oldp->replaceWith(newp);
|
oldp->replaceWith(newp);
|
||||||
oldp->deleteTree(); oldp=NULL;
|
oldp->deleteTree(); VL_DANGLING(oldp);
|
||||||
}
|
}
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Replacement functions.
|
// Replacement functions.
|
||||||
@@ -641,7 +644,7 @@ private:
|
|||||||
// This may adversly affect the operation of the node being replaced.
|
// This may adversly affect the operation of the node being replaced.
|
||||||
childp->dtypeFrom(nodep);
|
childp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(childp);
|
nodep->replaceWith(childp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Replace a ternary node with its RHS after iterating
|
//! Replace a ternary node with its RHS after iterating
|
||||||
@@ -775,9 +778,9 @@ private:
|
|||||||
UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
|
UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
|
||||||
|
|
||||||
nodep->replaceWith(newselp);
|
nodep->replaceWith(newselp);
|
||||||
lselp->deleteTree(); lselp = NULL;
|
lselp->deleteTree(); VL_DANGLING(lselp);
|
||||||
rselp->deleteTree(); rselp = NULL;
|
rselp->deleteTree(); VL_DANGLING(rselp);
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceConcatMerge(AstConcat* nodep) {
|
void replaceConcatMerge(AstConcat* nodep) {
|
||||||
AstNodeBiop* lp = nodep->lhsp()->castNodeBiop();
|
AstNodeBiop* lp = nodep->lhsp()->castNodeBiop();
|
||||||
@@ -794,8 +797,8 @@ private:
|
|||||||
lp->rhsp()->replaceWith(newrp);
|
lp->rhsp()->replaceWith(newrp);
|
||||||
lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::fromBool(true));
|
lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::fromBool(true));
|
||||||
UINFO(5, "merged "<< nodep <<endl);
|
UINFO(5, "merged "<< nodep <<endl);
|
||||||
rp->unlinkFrBack()->deleteTree(); rp = NULL;
|
rp->unlinkFrBack()->deleteTree(); VL_DANGLING(rp);
|
||||||
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); nodep = NULL;
|
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
lp->lhsp()->accept(*this);
|
lp->lhsp()->accept(*this);
|
||||||
lp->rhsp()->accept(*this);
|
lp->rhsp()->accept(*this);
|
||||||
} else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
|
} else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
|
||||||
@@ -805,10 +808,10 @@ private:
|
|||||||
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
|
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
|
||||||
arg0p->unlinkFrBack();
|
arg0p->unlinkFrBack();
|
||||||
AstNode* newp = (nodep->castExtendS()
|
AstNode* newp = (nodep->castExtendS()
|
||||||
? (new AstExtendS(nodep->fileline(), arg0p))->castNode()
|
? static_cast<AstNode*>(new AstExtendS(nodep->fileline(), arg0p))
|
||||||
: (new AstExtend (nodep->fileline(), arg0p))->castNode());
|
: static_cast<AstNode*>(new AstExtend (nodep->fileline(), arg0p)));
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replacePowShift (AstNodeBiop* nodep) { // Pow or PowS
|
void replacePowShift (AstNodeBiop* nodep) { // Pow or PowS
|
||||||
UINFO(5,"POW(2,b)->SHIFTL(1,b) "<<nodep<<endl);
|
UINFO(5,"POW(2,b)->SHIFTL(1,b) "<<nodep<<endl);
|
||||||
@@ -818,7 +821,7 @@ private:
|
|||||||
rhsp);
|
rhsp);
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
newp->lhsp()->dtypeFrom(nodep);
|
newp->lhsp()->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift
|
void replaceMulShift (AstMul* nodep) { // Mul, but not MulS as not simple shift
|
||||||
UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<<nodep<<endl);
|
UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<<nodep<<endl);
|
||||||
@@ -827,7 +830,7 @@ private:
|
|||||||
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
||||||
opp, new AstConst(nodep->fileline(), amount));
|
opp, new AstConst(nodep->fileline(), amount));
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift
|
void replaceDivShift (AstDiv* nodep) { // Mul, but not MulS as not simple shift
|
||||||
UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<<nodep<<endl);
|
UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<<nodep<<endl);
|
||||||
@@ -836,7 +839,7 @@ private:
|
|||||||
AstShiftR* newp = new AstShiftR(nodep->fileline(),
|
AstShiftR* newp = new AstShiftR(nodep->fileline(),
|
||||||
opp, new AstConst(nodep->fileline(), amount));
|
opp, new AstConst(nodep->fileline(), amount));
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceShiftOp (AstNodeBiop* nodep) {
|
void replaceShiftOp (AstNodeBiop* nodep) {
|
||||||
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
||||||
@@ -867,8 +870,8 @@ private:
|
|||||||
int shift1 = shift1p->castConst()->toUInt();
|
int shift1 = shift1p->castConst()->toUInt();
|
||||||
int shift2 = shift2p->castConst()->toUInt();
|
int shift2 = shift2p->castConst()->toUInt();
|
||||||
int newshift = shift1+shift2;
|
int newshift = shift1+shift2;
|
||||||
shift1p->deleteTree(); shift1p=NULL;
|
shift1p->deleteTree(); VL_DANGLING(shift1p);
|
||||||
shift2p->deleteTree(); shift2p=NULL;
|
shift2p->deleteTree(); VL_DANGLING(shift2p);
|
||||||
nodep->lhsp(ap);
|
nodep->lhsp(ap);
|
||||||
nodep->rhsp(new AstConst(nodep->fileline(), newshift));
|
nodep->rhsp(new AstConst(nodep->fileline(), newshift));
|
||||||
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
||||||
@@ -877,8 +880,8 @@ private:
|
|||||||
int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
||||||
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
|
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
|
||||||
int newshift = shift1+shift2;
|
int newshift = shift1+shift2;
|
||||||
shift1p->deleteTree(); shift1p=NULL;
|
shift1p->deleteTree(); VL_DANGLING(shift1p);
|
||||||
shift2p->deleteTree(); shift2p=NULL;
|
shift2p->deleteTree(); VL_DANGLING(shift2p);
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
V3Number mask1 (nodep->fileline(), nodep->width());
|
V3Number mask1 (nodep->fileline(), nodep->width());
|
||||||
V3Number ones (nodep->fileline(), nodep->width());
|
V3Number ones (nodep->fileline(), nodep->width());
|
||||||
@@ -906,11 +909,11 @@ private:
|
|||||||
newp,
|
newp,
|
||||||
new AstConst (nodep->fileline(), mask));
|
new AstConst (nodep->fileline(), mask));
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
//newp->dumpTree(cout, " repShiftShift_new: ");
|
//newp->dumpTree(cout, " repShiftShift_new: ");
|
||||||
newp->accept(*this); // Further reduce, either node may have more reductions.
|
newp->accept(*this); // Further reduce, either node may have more reductions.
|
||||||
}
|
}
|
||||||
lhsp->deleteTree(); lhsp=NULL;
|
lhsp->deleteTree(); VL_DANGLING(lhsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool replaceAssignMultiSel(AstNodeAssign* nodep) {
|
bool replaceAssignMultiSel(AstNodeAssign* nodep) {
|
||||||
@@ -983,7 +986,7 @@ private:
|
|||||||
nodep->v3error("Wire inputs its own output, creating circular logic (wire x=x)");
|
nodep->v3error("Wire inputs its own output, creating circular logic (wire x=x)");
|
||||||
return false; // Don't delete the assign, or V3Gate will freak out
|
return false; // Don't delete the assign, or V3Gate will freak out
|
||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1034,10 +1037,8 @@ private:
|
|||||||
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||||
asn1ap->dtypeFrom(sel1p);
|
asn1ap->dtypeFrom(sel1p);
|
||||||
asn2ap->dtypeFrom(sel2p);
|
asn2ap->dtypeFrom(sel2p);
|
||||||
// cppcheck-suppress nullPointer // addNext deals with it
|
newp = AstNode::addNext(newp, asn1ap);
|
||||||
newp = newp->addNext(asn1ap);
|
newp = AstNode::addNext(newp, asn2ap);
|
||||||
// cppcheck-suppress nullPointer // addNext deals with it
|
|
||||||
newp = newp->addNext(asn2ap);
|
|
||||||
} else {
|
} else {
|
||||||
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
||||||
// We could create just one temp variable, but we'll get better optimization
|
// We could create just one temp variable, but we'll get better optimization
|
||||||
@@ -1067,20 +1068,16 @@ private:
|
|||||||
asn2ap->dtypeFrom(temp2p);
|
asn2ap->dtypeFrom(temp2p);
|
||||||
asn2bp->dtypeFrom(temp2p);
|
asn2bp->dtypeFrom(temp2p);
|
||||||
// This order matters
|
// This order matters
|
||||||
// cppcheck-suppress nullPointer // addNext deals with it
|
newp = AstNode::addNext(newp, asn1ap);
|
||||||
newp = newp->addNext(asn1ap);
|
newp = AstNode::addNext(newp, asn2ap);
|
||||||
// cppcheck-suppress nullPointer // addNext deals with it
|
newp = AstNode::addNext(newp, asn1bp);
|
||||||
newp = newp->addNext(asn2ap);
|
newp = AstNode::addNext(newp, asn2bp);
|
||||||
// cppcheck-suppress nullPointer // addNext deals with it
|
|
||||||
newp = newp->addNext(asn1bp);
|
|
||||||
// cppcheck-suppress nullPointer // addNext deals with it
|
|
||||||
newp = newp->addNext(asn2bp);
|
|
||||||
}
|
}
|
||||||
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
|
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
|
||||||
nodep->addNextHere(newp);
|
nodep->addNextHere(newp);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
conp->deleteTree(); conp=NULL;
|
conp->deleteTree(); VL_DANGLING(conp);
|
||||||
// Further reduce, either node may have more reductions.
|
// Further reduce, either node may have more reductions.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1093,8 +1090,8 @@ private:
|
|||||||
AstNode* streamp = nodep->rhsp()->castStreamR()->unlinkFrBack();
|
AstNode* streamp = nodep->rhsp()->castStreamR()->unlinkFrBack();
|
||||||
nodep->rhsp(srcp);
|
nodep->rhsp(srcp);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
sizep->deleteTree(); sizep=NULL;
|
sizep->deleteTree(); VL_DANGLING(sizep);
|
||||||
streamp->deleteTree(); streamp=NULL;
|
streamp->deleteTree(); VL_DANGLING(streamp);
|
||||||
// Further reduce, any of the nodes may have more reductions.
|
// Further reduce, any of the nodes may have more reductions.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1137,8 +1134,8 @@ private:
|
|||||||
nodep->lhsp(dstp);
|
nodep->lhsp(dstp);
|
||||||
nodep->rhsp(srcp);
|
nodep->rhsp(srcp);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
sizep->deleteTree(); sizep=NULL;
|
sizep->deleteTree(); VL_DANGLING(sizep);
|
||||||
streamp->deleteTree(); streamp=NULL;
|
streamp->deleteTree(); VL_DANGLING(streamp);
|
||||||
// Further reduce, any of the nodes may have more reductions.
|
// Further reduce, any of the nodes may have more reductions.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1171,7 +1168,7 @@ private:
|
|||||||
fromp);
|
fromp);
|
||||||
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
|
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1185,36 +1182,36 @@ private:
|
|||||||
<<nodep->prettyTypeName()<<endl
|
<<nodep->prettyTypeName()<<endl
|
||||||
<<errorp->warnMore()<<"... Location of non-constant "
|
<<errorp->warnMore()<<"... Location of non-constant "
|
||||||
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||||
replaceZero(nodep); nodep=NULL;
|
replaceZero(nodep); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
// Fetch the result
|
// Fetch the result
|
||||||
V3Number* outnump = simvis.fetchNumberNull(nodep);
|
V3Number* outnump = simvis.fetchNumberNull(nodep);
|
||||||
if (!outnump) nodep->v3fatalSrc("No number returned from simulation");
|
if (!outnump) nodep->v3fatalSrc("No number returned from simulation");
|
||||||
// Replace it
|
// Replace it
|
||||||
replaceNum(nodep,*outnump); nodep=NULL;
|
replaceNum(nodep,*outnump); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep) {
|
||||||
// Iterate modules backwards, in bottom-up order. That's faster
|
// Iterate modules backwards, in bottom-up order. That's faster
|
||||||
nodep->iterateChildrenBackwards(*this);
|
nodep->iterateChildrenBackwards(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
// No ASSIGNW removals under funcs, we've long eliminated INITIALs
|
// No ASSIGNW removals under funcs, we've long eliminated INITIALs
|
||||||
// (We should perhaps rename the assignw's to just assigns)
|
// (We should perhaps rename the assignw's to just assigns)
|
||||||
m_wremove = false;
|
m_wremove = false;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_wremove = true;
|
m_wremove = true;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep) {
|
||||||
// No ASSIGNW removals under scope, we've long eliminated INITIALs
|
// No ASSIGNW removals under scope, we've long eliminated INITIALs
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
m_wremove = false;
|
m_wremove = false;
|
||||||
@@ -1271,7 +1268,7 @@ private:
|
|||||||
// If bp was a concat, then we have this exact same form again!
|
// If bp was a concat, then we have this exact same form again!
|
||||||
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
||||||
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
||||||
bcConcp->deleteTree(); bcConcp=NULL;
|
bcConcp->deleteTree(); VL_DANGLING(bcConcp);
|
||||||
} else {
|
} else {
|
||||||
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
||||||
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
||||||
@@ -1282,21 +1279,21 @@ private:
|
|||||||
nodep->lhsp(ap);
|
nodep->lhsp(ap);
|
||||||
nodep->rhsp(bcConcp);
|
nodep->rhsp(bcConcp);
|
||||||
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
|
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
|
||||||
abConcp->deleteTree(); abConcp=NULL;
|
abConcp->deleteTree(); VL_DANGLING(abConcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special cases
|
// Special cases
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {} // Already constant
|
virtual void visit(AstConst* nodep) {} // Already constant
|
||||||
|
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep) {
|
||||||
if (m_params) {
|
if (m_params) {
|
||||||
nodep->paramsp()->iterateAndNext(*this);
|
nodep->paramsp()->iterateAndNext(*this);
|
||||||
} else {
|
} else {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstPin* nodep, AstNUser*) {
|
virtual void visit(AstPin* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1313,8 +1310,8 @@ private:
|
|||||||
if (lsb1p->castConst() && lsb2p->castConst()) {
|
if (lsb1p->castConst() && lsb2p->castConst()) {
|
||||||
newlsbp = new AstConst(lsb1p->fileline(),
|
newlsbp = new AstConst(lsb1p->fileline(),
|
||||||
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
|
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
|
||||||
lsb1p->deleteTree(); lsb1p=NULL;
|
lsb1p->deleteTree(); VL_DANGLING(lsb1p);
|
||||||
lsb2p->deleteTree(); lsb2p=NULL;
|
lsb2p->deleteTree(); VL_DANGLING(lsb2p);
|
||||||
} else {
|
} else {
|
||||||
// Width is important, we need the width of the fromp's
|
// Width is important, we need the width of the fromp's
|
||||||
// expression, not the potentially smaller lsb1p's width
|
// expression, not the potentially smaller lsb1p's width
|
||||||
@@ -1328,7 +1325,7 @@ private:
|
|||||||
newlsbp,
|
newlsbp,
|
||||||
widthp);
|
widthp);
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceSelConcat(AstSel* nodep) {
|
void replaceSelConcat(AstSel* nodep) {
|
||||||
@@ -1368,7 +1365,7 @@ private:
|
|||||||
conRhsp->width()-nodep->lsbConst()));
|
conRhsp->width()-nodep->lsbConst()));
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceSelReplicate(AstSel* nodep) {
|
void replaceSelReplicate(AstSel* nodep) {
|
||||||
@@ -1382,7 +1379,7 @@ private:
|
|||||||
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||||
widthp);
|
widthp);
|
||||||
newp->dtypeFrom(nodep);
|
newp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceSelIntoBiop(AstSel* nodep) {
|
void replaceSelIntoBiop(AstSel* nodep) {
|
||||||
@@ -1400,7 +1397,7 @@ private:
|
|||||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||||
birhsp, lsbp, widthp));
|
birhsp, lsbp, widthp));
|
||||||
fromp->dtypeFrom(nodep);
|
fromp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
void replaceSelIntoUniop(AstSel* nodep) {
|
void replaceSelIntoUniop(AstSel* nodep) {
|
||||||
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
|
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
|
||||||
@@ -1414,17 +1411,17 @@ private:
|
|||||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||||
bilhsp, lsbp, widthp));
|
bilhsp, lsbp, widthp));
|
||||||
fromp->dtypeFrom(nodep);
|
fromp->dtypeFrom(nodep);
|
||||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
virtual void visit(AstAttrOf* nodep) {
|
||||||
AstAttrOf* oldAttr = m_attrp;
|
AstAttrOf* oldAttr = m_attrp;
|
||||||
m_attrp = nodep;
|
m_attrp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_attrp = oldAttr;
|
m_attrp = oldAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstArraySel* nodep, AstNUser*) {
|
virtual void visit(AstArraySel* nodep) {
|
||||||
nodep->bitp()->iterateAndNext(*this);
|
nodep->bitp()->iterateAndNext(*this);
|
||||||
if (nodep->bitp()->castConst()
|
if (nodep->bitp()->castConst()
|
||||||
&& nodep->fromp()->castVarRef()
|
&& nodep->fromp()->castVarRef()
|
||||||
@@ -1438,12 +1435,17 @@ private:
|
|||||||
if (!m_selp) {
|
if (!m_selp) {
|
||||||
nodep->v3error("Illegal assignment of constant to unpacked array");
|
nodep->v3error("Illegal assignment of constant to unpacked array");
|
||||||
} else {
|
} else {
|
||||||
nodep->replaceWith(nodep->fromp()->unlinkFrBack());
|
AstNode* fromp = nodep->fromp()->unlinkFrBack();
|
||||||
|
nodep->replaceWith(fromp);
|
||||||
|
if (fromp->dtypep()->skipRefp()->castNodeArrayDType()) {
|
||||||
|
// Strip off array to find what array references
|
||||||
|
fromp->dtypeFrom(fromp->dtypep()->skipRefp()->castNodeArrayDType()->subDTypep());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_selp = NULL;
|
m_selp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||||
bool did=false;
|
bool did=false;
|
||||||
@@ -1463,17 +1465,29 @@ private:
|
|||||||
if (operandConst(valuep)) {
|
if (operandConst(valuep)) {
|
||||||
const V3Number& num = valuep->castConst()->num();
|
const V3Number& num = valuep->castConst()->num();
|
||||||
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
did=true;
|
did=true;
|
||||||
}
|
}
|
||||||
else if (m_selp && valuep->castInitArray()) {
|
else if (m_selp && valuep->castInitArray()) {
|
||||||
int bit = m_selp->bitConst();
|
AstInitArray* initarp = valuep->castInitArray();
|
||||||
AstNode* itemp = valuep->castInitArray()->initsp();
|
uint32_t bit = m_selp->bitConst();
|
||||||
for (int n=0; n<bit && itemp; ++n, itemp=itemp->nextp()) {}
|
int pos = 0;
|
||||||
|
AstNode* itemp = initarp->initsp();
|
||||||
|
for (; itemp; ++pos, itemp=itemp->nextp()) {
|
||||||
|
uint32_t index = initarp->posIndex(pos);
|
||||||
|
if (index == bit) break;
|
||||||
|
if (index > bit) {
|
||||||
|
if (initarp->defaultp()) {
|
||||||
|
itemp = initarp->defaultp();
|
||||||
|
} else {
|
||||||
|
initarp->v3fatalSrc("Not enough values in array initalizement");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (itemp->castConst()) {
|
if (itemp->castConst()) {
|
||||||
const V3Number& num = itemp->castConst()->num();
|
const V3Number& num = itemp->castConst()->num();
|
||||||
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
did=true;
|
did=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1483,7 +1497,7 @@ private:
|
|||||||
nodep->v3error("Expecting expression to be constant, but variable isn't const: "<<nodep->varp()->prettyName());
|
nodep->v3error("Expecting expression to be constant, but variable isn't const: "<<nodep->varp()->prettyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
virtual void visit(AstEnumItemRef* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->itemp()) nodep->v3fatalSrc("Not linked");
|
if (!nodep->itemp()) nodep->v3fatalSrc("Not linked");
|
||||||
bool did=false;
|
bool did=false;
|
||||||
@@ -1492,7 +1506,7 @@ private:
|
|||||||
nodep->itemp()->valuep()->iterateAndNext(*this);
|
nodep->itemp()->valuep()->iterateAndNext(*this);
|
||||||
if (AstConst* valuep = nodep->itemp()->valuep()->castConst()) {
|
if (AstConst* valuep = nodep->itemp()->valuep()->castConst()) {
|
||||||
const V3Number& num = valuep->num();
|
const V3Number& num = valuep->num();
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||||
did=true;
|
did=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1501,7 +1515,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual void visit(AstCvtPackString* nodep, AstNUser*) {
|
// virtual void visit(AstCvtPackString* nodep) {
|
||||||
// Not constant propagated (for today) because AstMath::isOpaque is set
|
// Not constant propagated (for today) because AstMath::isOpaque is set
|
||||||
// Someday if lower is constant, convert to quoted "string".
|
// Someday if lower is constant, convert to quoted "string".
|
||||||
|
|
||||||
@@ -1509,7 +1523,7 @@ private:
|
|||||||
// Only one if it's not in a list
|
// Only one if it's not in a list
|
||||||
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst
|
if (m_doNConst
|
||||||
&& (nodep->sensp()->castConst()
|
&& (nodep->sensp()->castConst()
|
||||||
@@ -1519,13 +1533,13 @@ private:
|
|||||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||||
if (onlySenItemInSenTree(nodep)) {
|
if (onlySenItemInSenTree(nodep)) {
|
||||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
} else { // Otherwise it may compute a result that needs to settle out
|
} else { // Otherwise it may compute a result that needs to settle out
|
||||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
} else if (m_doNConst && nodep->sensp()->castNot()) {
|
} else if (m_doNConst && nodep->sensp()->castNot()) {
|
||||||
// V3Gate may propagate NOTs into clocks... Just deal with it
|
// V3Gate may propagate NOTs into clocks... Just deal with it
|
||||||
@@ -1541,30 +1555,31 @@ private:
|
|||||||
AstNodeVarRef* senvarp = lastSensp->unlinkFrBack()->castNodeVarRef();
|
AstNodeVarRef* senvarp = lastSensp->unlinkFrBack()->castNodeVarRef();
|
||||||
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
||||||
sensp->replaceWith(senvarp);
|
sensp->replaceWith(senvarp);
|
||||||
sensp->deleteTree(); sensp=NULL;
|
sensp->deleteTree(); VL_DANGLING(sensp);
|
||||||
} else if (!m_doNConst // Deal with later when doNConst missing
|
} else if (!m_doNConst // Deal with later when doNConst missing
|
||||||
&& (nodep->sensp()->castEnumItemRef()
|
&& (nodep->sensp()->castEnumItemRef()
|
||||||
|| nodep->sensp()->castConst())) {
|
|| nodep->sensp()->castConst())) {
|
||||||
|
} else if (nodep->isIllegal()) { // Deal with later
|
||||||
} else {
|
} else {
|
||||||
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
virtual void visit(AstSenGate* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
||||||
if (constp->isZero()) {
|
if (constp->isZero()) {
|
||||||
UINFO(4,"SENGATE(...,0)->NEVER"<<endl);
|
UINFO(4,"SENGATE(...,0)->NEVER"<<endl);
|
||||||
if (onlySenItemInSenTree(nodep)) {
|
if (onlySenItemInSenTree(nodep)) {
|
||||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UINFO(4,"SENGATE(SENITEM,0)->ALWAYS SENITEM"<<endl);
|
UINFO(4,"SENGATE(SENITEM,0)->ALWAYS SENITEM"<<endl);
|
||||||
AstNode* senitemp = nodep->sensesp()->unlinkFrBack();
|
AstNode* senitemp = nodep->sensesp()->unlinkFrBack();
|
||||||
nodep->replaceWith(senitemp);
|
nodep->replaceWith(senitemp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1595,7 +1610,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
virtual void visit(AstSenTree* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doExpensive) {
|
if (m_doExpensive) {
|
||||||
//cout<<endl; nodep->dumpTree(cout,"ssin: ");
|
//cout<<endl; nodep->dumpTree(cout,"ssin: ");
|
||||||
@@ -1630,7 +1645,7 @@ private:
|
|||||||
// Found, push this item up to the top
|
// Found, push this item up to the top
|
||||||
itemp->unlinkFrBack();
|
itemp->unlinkFrBack();
|
||||||
nodep->addSensesp(itemp);
|
nodep->addSensesp(itemp);
|
||||||
gatep->unlinkFrBack()->deleteTree(); gatep=NULL; senp=NULL;
|
gatep->unlinkFrBack()->deleteTree(); VL_DANGLING(gatep); VL_DANGLING(senp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1686,7 +1701,7 @@ private:
|
|||||||
&& ritemp->edgeType()==AstEdgeType::ET_NEGEDGE)
|
&& ritemp->edgeType()==AstEdgeType::ET_NEGEDGE)
|
||||||
litemp->edgeType(AstEdgeType::ET_BOTHEDGE);
|
litemp->edgeType(AstEdgeType::ET_BOTHEDGE);
|
||||||
// Remove redundant node
|
// Remove redundant node
|
||||||
ritemp->unlinkFrBack()->deleteTree(); ritemp=NULL; cmpp=NULL;
|
ritemp->unlinkFrBack()->deleteTree(); VL_DANGLING(ritemp); VL_DANGLING(cmpp);
|
||||||
// Try to collapse again
|
// Try to collapse again
|
||||||
nextp=litemp;
|
nextp=litemp;
|
||||||
}
|
}
|
||||||
@@ -1699,17 +1714,17 @@ private:
|
|||||||
|
|
||||||
//-----
|
//-----
|
||||||
// Zero elimination
|
// Zero elimination
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
virtual void visit(AstNodeAssign* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
virtual void visit(AstAssignAlias* nodep) {
|
||||||
// Don't perform any optimizations, keep the alias around
|
// Don't perform any optimizations, keep the alias around
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
|
virtual void visit(AstAssignVarScope* nodep) {
|
||||||
// Don't perform any optimizations, the node won't be linked yet
|
// Don't perform any optimizations, the node won't be linked yet
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
virtual void visit(AstAssignW* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||||
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
|
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
|
||||||
@@ -1729,14 +1744,14 @@ private:
|
|||||||
new AstAssign(nodep->fileline(),
|
new AstAssign(nodep->fileline(),
|
||||||
varrefp, exprp));
|
varrefp, exprp));
|
||||||
m_modp->addStmtp(newinitp);
|
m_modp->addStmtp(newinitp);
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
// Set the initial value right in the variable so we can constant propagate
|
// Set the initial value right in the variable so we can constant propagate
|
||||||
AstNode* initvaluep = exprp->cloneTree(false);
|
AstNode* initvaluep = exprp->cloneTree(false);
|
||||||
varrefp->varp()->valuep(initvaluep);
|
varrefp->varp()->valuep(initvaluep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
virtual void visit(AstNodeIf* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst) {
|
if (m_doNConst) {
|
||||||
if (AstConst* constp = nodep->condp()->castConst()) {
|
if (AstConst* constp = nodep->condp()->castConst()) {
|
||||||
@@ -1754,12 +1769,12 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||||
// Empty block, remove it
|
// Empty block, remove it
|
||||||
// Note if we support more C++ then there might be side effects in the condition itself
|
// Note if we support more C++ then there might be side effects in the condition itself
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (!afterComment(nodep->ifsp())) {
|
else if (!afterComment(nodep->ifsp())) {
|
||||||
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
||||||
@@ -1781,7 +1796,7 @@ private:
|
|||||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||||
ifp->branchPred(nodep->branchPred().invert());
|
ifp->branchPred(nodep->branchPred().invert());
|
||||||
nodep->replaceWith(ifp);
|
nodep->replaceWith(ifp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (ifSameAssign(nodep)) {
|
else if (ifSameAssign(nodep)) {
|
||||||
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
||||||
@@ -1794,7 +1809,7 @@ private:
|
|||||||
ifp->rhsp(new AstCond(truep->fileline(),
|
ifp->rhsp(new AstCond(truep->fileline(),
|
||||||
condp, truep, falsep));
|
condp, truep, falsep));
|
||||||
nodep->replaceWith(ifp);
|
nodep->replaceWith(ifp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||||
&& operandIfIf(nodep)) {
|
&& operandIfIf(nodep)) {
|
||||||
@@ -1806,7 +1821,7 @@ private:
|
|||||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
||||||
condp, lowerCondp));
|
condp, lowerCondp));
|
||||||
lowerIfp->replaceWith(lowerIfsp);
|
lowerIfp->replaceWith(lowerIfsp);
|
||||||
lowerIfp->deleteTree(); lowerIfp=NULL;
|
lowerIfp->deleteTree(); VL_DANGLING(lowerIfp);
|
||||||
}
|
}
|
||||||
else if (operandBoolShift(nodep->condp())) {
|
else if (operandBoolShift(nodep->condp())) {
|
||||||
replaceBoolShift(nodep->condp());
|
replaceBoolShift(nodep->condp());
|
||||||
@@ -1814,7 +1829,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
virtual void visit(AstSFormatF* nodep) {
|
||||||
// Substitute constants into displays. The main point of this is to
|
// Substitute constants into displays. The main point of this is to
|
||||||
// simplify assertion methodologies which call functions with display's.
|
// simplify assertion methodologies which call functions with display's.
|
||||||
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
|
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
|
||||||
@@ -1825,7 +1840,7 @@ private:
|
|||||||
}
|
}
|
||||||
if (m_doNConst && anyconst) {
|
if (m_doNConst && anyconst) {
|
||||||
//UINFO(9," Display in "<<nodep->text()<<endl);
|
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||||
string dispout = "";
|
string newFormat = "";
|
||||||
string fmt = "";
|
string fmt = "";
|
||||||
bool inPct = false;
|
bool inPct = false;
|
||||||
AstNode* argp = nodep->exprsp();
|
AstNode* argp = nodep->exprsp();
|
||||||
@@ -1843,84 +1858,82 @@ private:
|
|||||||
switch (tolower(ch)) {
|
switch (tolower(ch)) {
|
||||||
case '%': break; // %% - just output a %
|
case '%': break; // %% - just output a %
|
||||||
case 'm': break; // %m - auto insert "name"
|
case 'm': break; // %m - auto insert "name"
|
||||||
|
case 'l': break; // %l - auto insert "library"
|
||||||
default: // Most operators, just move to next argument
|
default: // Most operators, just move to next argument
|
||||||
if (argp) {
|
if (argp) {
|
||||||
AstNode* nextp=argp->nextp();
|
AstNode* nextp=argp->nextp();
|
||||||
if (argp && argp->castConst()) { // Convert it
|
if (argp && argp->castConst()) { // Convert it
|
||||||
string out = argp->castConst()->num().displayed(fmt);
|
string out = argp->castConst()->num().displayed(nodep->fileline(), fmt);
|
||||||
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
||||||
{ // fmt = out w/ replace % with %% as it must be literal.
|
// fmt = out w/ replace % with %% as it must be literal.
|
||||||
fmt = "";
|
fmt = VString::quotePercent(out);
|
||||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
|
||||||
if (*pos == '%') fmt += '%';
|
|
||||||
fmt += *pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argp->unlinkFrBack()->deleteTree();
|
argp->unlinkFrBack()->deleteTree();
|
||||||
}
|
}
|
||||||
argp=nextp;
|
argp=nextp;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} // switch
|
} // switch
|
||||||
dispout += fmt;
|
newFormat += fmt;
|
||||||
} else {
|
} else {
|
||||||
dispout += ch;
|
newFormat += ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodep->text(dispout);
|
if (newFormat != nodep->text()) {
|
||||||
//UINFO(9," Display out "<<nodep->text()<<endl);
|
nodep->text(newFormat);
|
||||||
|
UINFO(9," Display out "<<nodep<<endl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!nodep->exprsp()
|
if (!nodep->exprsp()
|
||||||
&& nodep->name().find("%") == string::npos
|
&& nodep->name().find("%") == string::npos
|
||||||
&& !nodep->hidden()) {
|
&& !nodep->hidden()) {
|
||||||
// Just a simple constant string - the formatting is pointless
|
// Just a simple constant string - the formatting is pointless
|
||||||
replaceConstString(nodep, nodep->name()); nodep=NULL;
|
replaceConstString(nodep, nodep->name()); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstFuncRef* nodep, AstNUser*) {
|
virtual void visit(AstFuncRef* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_params) { // Only parameters force us to do constant function call propagation
|
if (m_params) { // Only parameters force us to do constant function call propagation
|
||||||
replaceWithSimulation(nodep);
|
replaceWithSimulation(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstArg* nodep, AstNUser*) {
|
virtual void visit(AstArg* nodep) {
|
||||||
// replaceWithSimulation on the Arg's parent FuncRef replaces these
|
// replaceWithSimulation on the Arg's parent FuncRef replaces these
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst) {
|
if (m_doNConst) {
|
||||||
if (nodep->condp()->isZero()) {
|
if (nodep->condp()->isZero()) {
|
||||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (operandBoolShift(nodep->condp())) {
|
else if (operandBoolShift(nodep->condp())) {
|
||||||
replaceBoolShift(nodep->condp());
|
replaceBoolShift(nodep->condp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstInitArray* nodep, AstNUser*) {
|
virtual void visit(AstInitArray* nodep) {
|
||||||
// Constant if all children are constant
|
// Constant if all children are constant
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any
|
// These are converted by V3Param. Don't constify as we don't want the from() VARREF to disappear, if any
|
||||||
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
|
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
|
||||||
virtual void visit(AstNodePreSel* nodep, AstNUser*) {}
|
virtual void visit(AstNodePreSel* nodep) {}
|
||||||
|
|
||||||
// Ignored, can eliminate early
|
// Ignored, can eliminate early
|
||||||
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
|
virtual void visit(AstSysIgnore* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doNConst) {
|
if (m_doNConst) {
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simplify
|
// Simplify
|
||||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
virtual void visit(AstBasicDType* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->cvtRangeConst();
|
nodep->cvtRangeConst();
|
||||||
}
|
}
|
||||||
@@ -1928,12 +1941,12 @@ private:
|
|||||||
//-----
|
//-----
|
||||||
// Jump elimination
|
// Jump elimination
|
||||||
|
|
||||||
virtual void visit(AstJumpGo* nodep, AstNUser*) {
|
virtual void visit(AstJumpGo* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_doExpensive) { nodep->labelp()->user4(true); }
|
if (m_doExpensive) { nodep->labelp()->user4(true); }
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
|
virtual void visit(AstJumpLabel* nodep) {
|
||||||
// Because JumpLabels disable many optimizations,
|
// Because JumpLabels disable many optimizations,
|
||||||
// remove JumpLabels that are not pointed to by any AstJumpGos
|
// remove JumpLabels that are not pointed to by any AstJumpGos
|
||||||
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
|
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
|
||||||
@@ -1945,7 +1958,7 @@ private:
|
|||||||
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
|
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||||
if (underp) nodep->replaceWith(underp);
|
if (underp) nodep->replaceWith(underp);
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2262,11 +2275,15 @@ private:
|
|||||||
// Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101
|
// Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101
|
||||||
|
|
||||||
//-----
|
//-----
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
if (m_required) {
|
if (m_required) {
|
||||||
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
if (nodep->castNodeDType() || nodep->castRange()) {
|
||||||
<<nodep->prettyTypeName()<<" to constant.");
|
// Ignore dtypes for parameter type pins
|
||||||
|
} else {
|
||||||
|
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
||||||
|
<<nodep->prettyTypeName()<<" to constant.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Calculate the width of this operation
|
// Calculate the width of this operation
|
||||||
if (m_params && !nodep->width()) {
|
if (m_params && !nodep->width()) {
|
||||||
@@ -2289,7 +2306,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ConstVisitor(ProcMode pmode) {
|
explicit ConstVisitor(ProcMode pmode) {
|
||||||
m_params = false;
|
m_params = false;
|
||||||
m_required = false;
|
m_required = false;
|
||||||
m_doExpensive = false;
|
m_doExpensive = false;
|
||||||
@@ -2318,7 +2335,7 @@ public:
|
|||||||
virtual ~ConstVisitor() {}
|
virtual ~ConstVisitor() {}
|
||||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||||
// Operate starting at a random place
|
// Operate starting at a random place
|
||||||
return nodep->acceptSubtreeReturnEdits(*this);
|
return nodep->iterateSubtreeReturnEdits(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+15
-15
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -83,11 +83,11 @@ private:
|
|||||||
const char* varIgnoreToggle(AstVar* nodep) {
|
const char* varIgnoreToggle(AstVar* nodep) {
|
||||||
// Return true if this shouldn't be traced
|
// Return true if this shouldn't be traced
|
||||||
// See also similar rule in V3TraceDecl::varIgnoreTrace
|
// See also similar rule in V3TraceDecl::varIgnoreTrace
|
||||||
string prettyName = nodep->prettyName();
|
|
||||||
if (!nodep->isToggleCoverable())
|
if (!nodep->isToggleCoverable())
|
||||||
return "Not relevant signal type";
|
return "Not relevant signal type";
|
||||||
if (!v3Global.opt.coverageUnderscore()) {
|
if (!v3Global.opt.coverageUnderscore()) {
|
||||||
if (prettyName.c_str()[0] == '_')
|
string prettyName = nodep->prettyName();
|
||||||
|
if (prettyName[0] == '_')
|
||||||
return "Leading underscore";
|
return "Leading underscore";
|
||||||
if (prettyName.find("._") != string::npos)
|
if (prettyName.find("._") != string::npos)
|
||||||
return "Inlined leading underscore";
|
return "Inlined leading underscore";
|
||||||
@@ -128,7 +128,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS - BOTH
|
// VISITORS - BOTH
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
|
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
|
||||||
m_fileps.clear();
|
m_fileps.clear();
|
||||||
@@ -138,7 +138,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS - TOGGLE COVERAGE
|
// VISITORS - TOGGLE COVERAGE
|
||||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTask* nodep) {
|
||||||
bool oldtog = m_inToggleOff;
|
bool oldtog = m_inToggleOff;
|
||||||
{
|
{
|
||||||
m_inToggleOff = true;
|
m_inToggleOff = true;
|
||||||
@@ -146,7 +146,7 @@ private:
|
|||||||
}
|
}
|
||||||
m_inToggleOff = oldtog;
|
m_inToggleOff = oldtog;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_modp && !m_inModOff && !m_inToggleOff
|
if (m_modp && !m_inModOff && !m_inToggleOff
|
||||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
||||||
@@ -279,7 +279,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS - LINE COVERAGE
|
// VISITORS - LINE COVERAGE
|
||||||
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
virtual void visit(AstIf* nodep) { // Note not AstNodeIf; other types don't get covered
|
||||||
UINFO(4," IF: "<<nodep<<endl);
|
UINFO(4," IF: "<<nodep<<endl);
|
||||||
if (m_checkBlock) {
|
if (m_checkBlock) {
|
||||||
// An else-if. When we iterate the if, use "elsif" marking
|
// An else-if. When we iterate the if, use "elsif" marking
|
||||||
@@ -312,7 +312,7 @@ private:
|
|||||||
m_checkBlock = true; // Reset as a child may have cleared it
|
m_checkBlock = true; // Reset as a child may have cleared it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
virtual void visit(AstCaseItem* nodep) {
|
||||||
UINFO(4," CASEI: "<<nodep<<endl);
|
UINFO(4," CASEI: "<<nodep<<endl);
|
||||||
if (m_checkBlock && !m_inModOff
|
if (m_checkBlock && !m_inModOff
|
||||||
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
||||||
@@ -324,7 +324,7 @@ private:
|
|||||||
m_checkBlock = true; // Reset as a child may have cleared it
|
m_checkBlock = true; // Reset as a child may have cleared it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep) {
|
||||||
UINFO(4," PSLCOVER: "<<nodep<<endl);
|
UINFO(4," PSLCOVER: "<<nodep<<endl);
|
||||||
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -334,21 +334,21 @@ private:
|
|||||||
}
|
}
|
||||||
m_checkBlock = true; // Reset as a child may have cleared it
|
m_checkBlock = true; // Reset as a child may have cleared it
|
||||||
}
|
}
|
||||||
virtual void visit(AstStop* nodep, AstNUser*) {
|
virtual void visit(AstStop* nodep) {
|
||||||
UINFO(4," STOP: "<<nodep<<endl);
|
UINFO(4," STOP: "<<nodep<<endl);
|
||||||
m_checkBlock = false;
|
m_checkBlock = false;
|
||||||
}
|
}
|
||||||
virtual void visit(AstPragma* nodep, AstNUser*) {
|
virtual void visit(AstPragma* nodep) {
|
||||||
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
||||||
// Skip all NEXT nodes under this block, and skip this if/case branch
|
// Skip all NEXT nodes under this block, and skip this if/case branch
|
||||||
UINFO(4," OFF: "<<nodep<<endl);
|
UINFO(4," OFF: "<<nodep<<endl);
|
||||||
m_checkBlock = false;
|
m_checkBlock = false;
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
} else {
|
} else {
|
||||||
if (m_checkBlock) nodep->iterateChildren(*this);
|
if (m_checkBlock) nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
virtual void visit(AstBegin* nodep) {
|
||||||
// Record the hierarchy of any named begins, so we can apply to user
|
// Record the hierarchy of any named begins, so we can apply to user
|
||||||
// coverage points. This is because there may be cov points inside
|
// coverage points. This is because there may be cov points inside
|
||||||
// generate blocks; each point should get separate consideration.
|
// generate blocks; each point should get separate consideration.
|
||||||
@@ -368,7 +368,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS - BOTH
|
// VISITORS - BOTH
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
if (m_checkBlock) {
|
if (m_checkBlock) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -378,7 +378,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CoverageVisitor(AstNetlist* rootp) {
|
explicit CoverageVisitor(AstNetlist* rootp) {
|
||||||
// Operate on all modules
|
// Operate on all modules
|
||||||
m_checkBlock = true;
|
m_checkBlock = true;
|
||||||
m_beginHier = "";
|
m_beginHier = "";
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -93,7 +93,7 @@ private:
|
|||||||
UINFO(8," new "<<removep->incp()->declp()<<endl);
|
UINFO(8," new "<<removep->incp()->declp()<<endl);
|
||||||
// Mark the found node as a duplicate of the first node
|
// Mark the found node as a duplicate of the first node
|
||||||
// (Not vice-versa as we have the iterator for the found node)
|
// (Not vice-versa as we have the iterator for the found node)
|
||||||
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
|
removep->unlinkFrBack(); pushDeletep(removep); VL_DANGLING(removep);
|
||||||
// Remove node from comparison so don't hit it again
|
// Remove node from comparison so don't hit it again
|
||||||
hashed.erase(dupit);
|
hashed.erase(dupit);
|
||||||
++m_statToggleJoins;
|
++m_statToggleJoins;
|
||||||
@@ -103,25 +103,25 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep) {
|
||||||
// Find all Coverage's
|
// Find all Coverage's
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
// Simplify
|
// Simplify
|
||||||
detectDuplicates();
|
detectDuplicates();
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
virtual void visit(AstCoverToggle* nodep) {
|
||||||
m_toggleps.push_back(nodep);
|
m_toggleps.push_back(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
//--------------------
|
//--------------------
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
virtual void visit(AstNodeMath* nodep) {} // Accelerate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CoverageJoinVisitor(AstNetlist* nodep) {
|
explicit CoverageJoinVisitor(AstNetlist* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CoverageJoinVisitor() {
|
virtual ~CoverageJoinVisitor() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+196
-51
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -25,7 +25,18 @@
|
|||||||
// dependencies easier to resolve.
|
// dependencies easier to resolve.
|
||||||
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
// NOTE: If redo this, consider using maybePointedTo()/broken() ish scheme
|
||||||
// instead of needing as many visitors.
|
// instead of needing as many visitors.
|
||||||
//*************************************************************************
|
//
|
||||||
|
// The following nodes have package pointers and are cleaned up here:
|
||||||
|
// AstRefDType, AstEnumItemRef, AstNodeVarRef, AstNodeFTask
|
||||||
|
// These have packagep but will not exist at this stage
|
||||||
|
// AstPackageImport, AstDot, AstPackageRef
|
||||||
|
//
|
||||||
|
// Note on packagep: After the V3Scope/V3LinkDotScoped stage, package links
|
||||||
|
// are no longer used, but their presence prevents us from removing empty
|
||||||
|
// packages. As the links as no longer used after V3Scope, we remove them
|
||||||
|
// here after scoping to allow more dead node
|
||||||
|
// removal.
|
||||||
|
// *************************************************************************
|
||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
@@ -47,18 +58,18 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// ** Shared with DeadVisitor **
|
// ** Shared with DeadVisitor **
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->modp()->user1(nodep->modp()->user1() - 1);
|
nodep->modp()->user1Inc(-1);
|
||||||
}
|
}
|
||||||
//-----
|
//-----
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
virtual void visit(AstNodeMath* nodep) {} // Accelerate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
DeadModVisitor(AstNodeModule* nodep) {
|
explicit DeadModVisitor(AstNodeModule* nodep) {
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~DeadModVisitor() {}
|
virtual ~DeadModVisitor() {}
|
||||||
@@ -71,10 +82,10 @@ class DeadVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire Netlist:
|
// Entire Netlist:
|
||||||
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
// AstNodeModule::user1() -> int. Count of number of cells referencing this module.
|
||||||
// AstVar::user1() -> int. Count of number of references
|
// AstVar::user1() -> int. Count of number of references
|
||||||
// AstVarScope::user1() -> int. Count of number of references
|
// AstVarScope::user1() -> int. Count of number of references
|
||||||
// AstNodeDType::user1() -> int. Count of number of references
|
// AstNodeDType::user1() -> int. Count of number of references
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
@@ -82,11 +93,16 @@ private:
|
|||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
vector<AstNode*> m_varEtcsp; // List of all encountered to avoid another loop through tree
|
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
||||||
|
vector<AstNode*> m_dtypesp; // List of all encountered to avoid another loop through tree
|
||||||
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
||||||
|
vector<AstScope*> m_scopesp; // List of all encountered to avoid another loop through tree
|
||||||
|
vector<AstCell*> m_cellsp; // List of all encountered to avoid another loop through tree
|
||||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||||
bool m_elimUserVars; // Allow removal of user's vars
|
bool m_elimUserVars; // Allow removal of user's vars
|
||||||
bool m_elimDTypes; // Allow removal of DTypes
|
bool m_elimDTypes; // Allow removal of DTypes
|
||||||
|
bool m_elimScopes; // Allow removal of Scopes
|
||||||
|
bool m_elimCells; // Allow removal of Cells
|
||||||
bool m_sideEffect; // Side effects discovered in assign RHS
|
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -97,34 +113,56 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void checkAll(AstNode* nodep) {
|
void checkAll(AstNode* nodep) {
|
||||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||||
if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc();
|
if (AstNode* subnodep = nodep->dtypep()) {
|
||||||
|
subnodep->user1Inc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AstNode* subnodep = nodep->getChildDTypep()) {
|
||||||
|
subnodep->user1Inc();
|
||||||
}
|
}
|
||||||
if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc();
|
|
||||||
}
|
}
|
||||||
void checkDType(AstNodeDType* nodep) {
|
void checkDType(AstNodeDType* nodep) {
|
||||||
if (!nodep->generic() // Don't remove generic types
|
if (!nodep->generic() // Don't remove generic types
|
||||||
&& m_elimDTypes // dtypes stick around until post-widthing
|
&& m_elimDTypes // dtypes stick around until post-widthing
|
||||||
&& !nodep->castMemberDType() // Keep member names iff upper type exists
|
&& !nodep->castMemberDType() // Keep member names iff upper type exists
|
||||||
) {
|
) {
|
||||||
m_varEtcsp.push_back(nodep);
|
m_dtypesp.push_back(nodep);
|
||||||
|
}
|
||||||
|
if (AstNode* subnodep = nodep->virtRefDTypep()) {
|
||||||
|
subnodep->user1Inc();
|
||||||
}
|
}
|
||||||
if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
|
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||||
|
}
|
||||||
|
virtual void visit(AstScope* nodep) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
|
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
|
||||||
|
|
||||||
|
if (!nodep->isTop() && !nodep->varsp() && !nodep->blocksp() && !nodep->finalClksp()) {
|
||||||
|
m_scopesp.push_back(nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstCell* nodep) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
checkAll(nodep);
|
||||||
|
m_cellsp.push_back(nodep);
|
||||||
nodep->modp()->user1Inc();
|
nodep->modp()->user1Inc();
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
|
||||||
|
virtual void visit(AstNodeVarRef* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (nodep->varScopep()) {
|
if (nodep->varScopep()) {
|
||||||
@@ -135,60 +173,79 @@ private:
|
|||||||
nodep->varp()->user1Inc();
|
nodep->varp()->user1Inc();
|
||||||
}
|
}
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1Inc();
|
if (m_elimCells) nodep->packagep(NULL);
|
||||||
|
else nodep->packagep()->user1Inc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeFTaskRef* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1Inc();
|
if (m_elimCells) nodep->packagep(NULL);
|
||||||
|
else nodep->packagep()->user1Inc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
virtual void visit(AstRefDType* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkDType(nodep);
|
checkDType(nodep);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1Inc();
|
if (m_elimCells) nodep->packagep(NULL);
|
||||||
|
else nodep->packagep()->user1Inc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeDType* nodep, AstNUser*) {
|
virtual void visit(AstNodeDType* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkDType(nodep);
|
checkDType(nodep);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
virtual void visit(AstEnumItemRef* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (nodep->packagep()) {
|
if (nodep->packagep()) {
|
||||||
nodep->packagep()->user1Inc();
|
if (m_elimCells) nodep->packagep(NULL);
|
||||||
|
else nodep->packagep()->user1Inc();
|
||||||
}
|
}
|
||||||
|
checkAll(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
virtual void visit(AstModport* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_elimCells) {
|
||||||
|
if (!nodep->varsp()) {
|
||||||
|
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkAll(nodep);
|
||||||
|
}
|
||||||
|
virtual void visit(AstTypedef* nodep) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_elimCells && !nodep->attrPublic()) {
|
||||||
|
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
// Don't let packages with only public variables disappear
|
// Don't let packages with only public variables disappear
|
||||||
// Normal modules may disappear, e.g. if they are parameterized then removed
|
// Normal modules may disappear, e.g. if they are parameterized then removed
|
||||||
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
if (nodep->attrPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (mightElim(nodep->varp())) {
|
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||||
|
if (mightElimVar(nodep->varp())) {
|
||||||
m_vscsp.push_back(nodep);
|
m_vscsp.push_back(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
if (nodep->isSigPublic() && m_modp && m_modp->castPackage()) m_modp->user1Inc();
|
||||||
if (mightElim(nodep)) {
|
if (mightElimVar(nodep)) {
|
||||||
m_varEtcsp.push_back(nodep);
|
m_varsp.push_back(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstNodeAssign* nodep) {
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
|
||||||
// See if simple assignments to variables may be eliminated because that variable is never used.
|
// See if simple assignments to variables may be eliminated because that variable is never used.
|
||||||
// Similar code in V3Life
|
// Similar code in V3Life
|
||||||
m_sideEffect = false;
|
m_sideEffect = false;
|
||||||
@@ -199,7 +256,7 @@ private:
|
|||||||
if (varrefp && !m_sideEffect
|
if (varrefp && !m_sideEffect
|
||||||
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||||
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||||
checkAll(varrefp); // Must track reference to dtype()
|
checkAll(varrefp); // Must track reference to dtype()
|
||||||
} else { // Track like any other statement
|
} else { // Track like any other statement
|
||||||
nodep->lhsp()->iterateAndNext(*this);
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
@@ -207,7 +264,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----
|
//-----
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
if (nodep->isOutputter()) m_sideEffect=true;
|
if (nodep->isOutputter()) m_sideEffect=true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
checkAll(nodep);
|
checkAll(nodep);
|
||||||
@@ -229,19 +286,51 @@ private:
|
|||||||
// And its children may now be killable too; correct counts
|
// And its children may now be killable too; correct counts
|
||||||
// Recurse, as cells may not be directly under the module but in a generate
|
// Recurse, as cells may not be directly under the module but in a generate
|
||||||
DeadModVisitor visitor(modp);
|
DeadModVisitor visitor(modp);
|
||||||
modp->unlinkFrBack()->deleteTree(); modp=NULL;
|
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
|
||||||
retry = true;
|
retry = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool mightElim(AstVar* nodep) {
|
bool mightElimVar(AstVar* nodep) {
|
||||||
return (!nodep->isSigPublic() // Can't elim publics!
|
return (!nodep->isSigPublic() // Can't elim publics!
|
||||||
&& !nodep->isIO()
|
&& !nodep->isIO()
|
||||||
&& (nodep->isTemp()
|
&& (nodep->isTemp()
|
||||||
|| (nodep->isParam() && !nodep->isTrace())
|
|| (nodep->isParam() && !nodep->isTrace())
|
||||||
|| m_elimUserVars)); // Post-Trace can kill most anything
|
|| m_elimUserVars)); // Post-Trace can kill most anything
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deadCheckScope() {
|
||||||
|
for (bool retry=true; retry; ) {
|
||||||
|
retry = false;
|
||||||
|
for (vector<AstScope*>::iterator it = m_scopesp.begin(); it != m_scopesp.end();++it) {
|
||||||
|
AstScope* scp = *it;
|
||||||
|
if (!scp)
|
||||||
|
continue;
|
||||||
|
if (scp->user1() == 0) {
|
||||||
|
UINFO(4, " Dead AstScope " << scp << endl);
|
||||||
|
scp->aboveScopep()->user1Inc(-1);
|
||||||
|
if (scp->dtypep()) {
|
||||||
|
scp->dtypep()->user1Inc(-1);
|
||||||
|
}
|
||||||
|
scp->unlinkFrBack()->deleteTree(); VL_DANGLING(scp);
|
||||||
|
*it = NULL;
|
||||||
|
retry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deadCheckCells() {
|
||||||
|
for (vector<AstCell*>::iterator it = m_cellsp.begin(); it!=m_cellsp.end(); ++it) {
|
||||||
|
AstCell* cellp = *it;
|
||||||
|
if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) {
|
||||||
|
cellp->modp()->user1Inc(-1);
|
||||||
|
cellp->unlinkFrBack()->deleteTree(); VL_DANGLING(cellp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void deadCheckVar() {
|
void deadCheckVar() {
|
||||||
// Delete any unused varscopes
|
// Delete any unused varscopes
|
||||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||||
@@ -251,34 +340,76 @@ private:
|
|||||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||||
AstNodeAssign* assp = it->second;
|
AstNodeAssign* assp = it->second;
|
||||||
UINFO(4," Dead assign "<<assp<<endl);
|
UINFO(4," Dead assign "<<assp<<endl);
|
||||||
assp->unlinkFrBack()->deleteTree(); assp=NULL;
|
assp->dtypep()->user1Inc(-1);
|
||||||
|
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
|
||||||
}
|
}
|
||||||
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
|
if (vscp->scopep()) vscp->scopep()->user1Inc(-1);
|
||||||
|
vscp->dtypep()->user1Inc(-1);
|
||||||
|
vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
|
for (bool retry=true; retry; ) {
|
||||||
|
retry = false;
|
||||||
|
for (vector<AstVar *>::iterator it = m_varsp.begin(); it != m_varsp.end();++it) {
|
||||||
|
AstVar* varp = *it;
|
||||||
|
if (!varp)
|
||||||
|
continue;
|
||||||
|
if (varp->user1() == 0) {
|
||||||
|
UINFO(4, " Dead " << varp << endl);
|
||||||
|
if (varp->dtypep()) {
|
||||||
|
varp->dtypep()->user1Inc(-1);
|
||||||
|
}
|
||||||
|
varp->unlinkFrBack()->deleteTree(); VL_DANGLING(varp);
|
||||||
|
*it = NULL;
|
||||||
|
retry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (vector<AstNode*>::iterator it = m_dtypesp.begin(); it != m_dtypesp.end();++it) {
|
||||||
if ((*it)->user1() == 0) {
|
if ((*it)->user1() == 0) {
|
||||||
UINFO(4," Dead "<<(*it)<<endl);
|
AstNodeClassDType *classp;
|
||||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
// It's possible that there if a reference to each individual member, but
|
||||||
|
// not to the dtype itself. Check and don't remove the parent dtype if
|
||||||
|
// members are still alive.
|
||||||
|
if ((classp = (*it)->castNodeClassDType())) {
|
||||||
|
bool cont = true;
|
||||||
|
for (AstMemberDType *memberp = classp->membersp(); memberp; memberp = memberp->nextp()->castMemberDType()) {
|
||||||
|
if (memberp->user1() != 0) {
|
||||||
|
cont = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cont)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(*it)->unlinkFrBack()->deleteTree(); VL_DANGLING(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes) {
|
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes, bool elimCells) {
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
m_elimCells = elimCells;
|
||||||
m_elimUserVars = elimUserVars;
|
m_elimUserVars = elimUserVars;
|
||||||
m_elimDTypes = elimDTypes;
|
m_elimDTypes = elimDTypes;
|
||||||
|
m_elimScopes = elimScopes;
|
||||||
m_sideEffect = false;
|
m_sideEffect = false;
|
||||||
// Prepare to remove some datatypes
|
// Prepare to remove some datatypes
|
||||||
nodep->typeTablep()->clearCache();
|
nodep->typeTablep()->clearCache();
|
||||||
// Operate on whole netlist
|
// Operate on whole netlist
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
|
|
||||||
deadCheckVar();
|
deadCheckVar();
|
||||||
|
// We only elimate scopes when in a flattened structure
|
||||||
|
// Otherwise we have no easy way to know if a scope is used
|
||||||
|
if (elimScopes) deadCheckScope();
|
||||||
|
if (elimCells) deadCheckCells();
|
||||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||||
deadCheckMod();
|
deadCheckMod();
|
||||||
|
|
||||||
// We may have removed some datatypes, cleanup
|
// We may have removed some datatypes, cleanup
|
||||||
nodep->typeTablep()->repairCache();
|
nodep->typeTablep()->repairCache();
|
||||||
}
|
}
|
||||||
@@ -290,16 +421,30 @@ public:
|
|||||||
|
|
||||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
DeadVisitor visitor (nodep, false, false);
|
DeadVisitor visitor (nodep, false, false, false, false);
|
||||||
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
DeadVisitor visitor (nodep, false, true);
|
DeadVisitor visitor (nodep, false, true, false, false);
|
||||||
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
V3Global::dumpCheckGlobalTree("deadDtypes.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
|
DeadVisitor visitor (nodep, false, true, true, false);
|
||||||
|
V3Global::dumpCheckGlobalTree("deadDtypesScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
|
}
|
||||||
|
|
||||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
DeadVisitor visitor (nodep, true, true);
|
DeadVisitor visitor (nodep, true, true, false, true);
|
||||||
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
|
DeadVisitor visitor (nodep, true, true, true, true);
|
||||||
|
V3Global::dumpCheckGlobalTree("deadAllScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||||
|
}
|
||||||
|
|||||||
+3
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -33,8 +33,10 @@ public:
|
|||||||
static void deadifyModules(AstNetlist* nodep);
|
static void deadifyModules(AstNetlist* nodep);
|
||||||
// Modules, Data types
|
// Modules, Data types
|
||||||
static void deadifyDTypes(AstNetlist* nodep);
|
static void deadifyDTypes(AstNetlist* nodep);
|
||||||
|
static void deadifyDTypesScoped(AstNetlist* nodep);
|
||||||
// Everything that's possible
|
// Everything that's possible
|
||||||
static void deadifyAll(AstNetlist* nodep);
|
static void deadifyAll(AstNetlist* nodep);
|
||||||
|
static void deadifyAllScoped(AstNetlist* nodep);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+21
-21
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -268,7 +268,7 @@ private:
|
|||||||
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
||||||
// This is good for code like:
|
// This is good for code like:
|
||||||
// for (i=0; i<5; i++) vector[i] <= something;
|
// for (i=0; i<5; i++) vector[i] <= something;
|
||||||
setvscp = nodep->user3p()->castNode()->castVarScope();
|
setvscp = nodep->user3p()->castVarScope();
|
||||||
++m_statSharedSet;
|
++m_statSharedSet;
|
||||||
} else { // Create new one
|
} else { // Create new one
|
||||||
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
@@ -303,9 +303,9 @@ private:
|
|||||||
// Build "IF (changeit) ...
|
// Build "IF (changeit) ...
|
||||||
UINFO(9," For "<<setvscp<<endl);
|
UINFO(9," For "<<setvscp<<endl);
|
||||||
UINFO(9," & "<<varrefp<<endl);
|
UINFO(9," & "<<varrefp<<endl);
|
||||||
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castAlwaysPost();
|
||||||
if (finalp) {
|
if (finalp) {
|
||||||
AstActive* oldactivep = finalp->user2p()->castNode()->castActive();
|
AstActive* oldactivep = finalp->user2p()->castActive();
|
||||||
checkActivePost(varrefp, oldactivep);
|
checkActivePost(varrefp, oldactivep);
|
||||||
if (setinitp) oldactivep->addStmtsp(setinitp);
|
if (setinitp) oldactivep->addStmtsp(setinitp);
|
||||||
} else { // first time we've dealt with this memory
|
} else { // first time we've dealt with this memory
|
||||||
@@ -318,10 +318,10 @@ private:
|
|||||||
if (setinitp) newactp->addStmtsp(setinitp);
|
if (setinitp) newactp->addStmtsp(setinitp);
|
||||||
}
|
}
|
||||||
AstIf* postLogicp;
|
AstIf* postLogicp;
|
||||||
if (finalp->user3p()->castNode() == setvscp) {
|
if (finalp->user3p() == setvscp) {
|
||||||
// Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*,
|
// Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*,
|
||||||
// we can share the IF statement too
|
// we can share the IF statement too
|
||||||
postLogicp = finalp->user4p()->castNode()->castIf();
|
postLogicp = finalp->user4p()->castIf();
|
||||||
if (!postLogicp) nodep->v3fatalSrc("Delayed assignment misoptimized; prev var found w/o associated IF");
|
if (!postLogicp) nodep->v3fatalSrc("Delayed assignment misoptimized; prev var found w/o associated IF");
|
||||||
} else {
|
} else {
|
||||||
postLogicp = new AstIf (nodep->fileline(),
|
postLogicp = new AstIf (nodep->fileline(),
|
||||||
@@ -338,22 +338,22 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep) {
|
||||||
//VV***** We reset all userp() on the netlist
|
//VV***** We reset all userp() on the netlist
|
||||||
m_modVarMap.clear();
|
m_modVarMap.clear();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep) {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
AstNode::user3ClearTree();
|
AstNode::user3ClearTree();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
m_cfuncp = nodep;
|
m_cfuncp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_cfuncp = NULL;
|
m_cfuncp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
virtual void visit(AstActive* nodep) {
|
||||||
m_activep = nodep;
|
m_activep = nodep;
|
||||||
bool oldinit = m_inInitial;
|
bool oldinit = m_inInitial;
|
||||||
m_inInitial = nodep->hasInitial();
|
m_inInitial = nodep->hasInitial();
|
||||||
@@ -361,7 +361,7 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_inInitial = oldinit;
|
m_inInitial = oldinit;
|
||||||
}
|
}
|
||||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
virtual void visit(AstAssignDly* nodep) {
|
||||||
m_inDly = true;
|
m_inDly = true;
|
||||||
m_nextDlyp = nodep->nextp()->castAssignDly(); // Next assignment in same block, maybe NULL.
|
m_nextDlyp = nodep->nextp()->castAssignDly(); // Next assignment in same block, maybe NULL.
|
||||||
if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task");
|
if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task");
|
||||||
@@ -374,9 +374,9 @@ private:
|
|||||||
if (newlhsp) {
|
if (newlhsp) {
|
||||||
nodep->lhsp(newlhsp);
|
nodep->lhsp(newlhsp);
|
||||||
} else {
|
} else {
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
lhsp->deleteTree(); lhsp=NULL;
|
lhsp->deleteTree(); VL_DANGLING(lhsp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -385,7 +385,7 @@ private:
|
|||||||
m_nextDlyp = NULL;
|
m_nextDlyp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
if (!nodep->user2Inc()) { // Not done yet
|
if (!nodep->user2Inc()) { // Not done yet
|
||||||
if (m_inDly && nodep->lvalue()) {
|
if (m_inDly && nodep->lvalue()) {
|
||||||
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
||||||
@@ -394,9 +394,9 @@ private:
|
|||||||
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
|
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
|
||||||
AstVarScope* oldvscp = nodep->varScopep();
|
AstVarScope* oldvscp = nodep->varScopep();
|
||||||
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||||
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
|
AstVarScope* dlyvscp = oldvscp->user1p()->castVarScope();
|
||||||
if (dlyvscp) { // Multiple use of delayed variable
|
if (dlyvscp) { // Multiple use of delayed variable
|
||||||
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
|
AstActive* oldactivep = dlyvscp->user2p()->castActive();
|
||||||
checkActivePost(nodep, oldactivep);
|
checkActivePost(nodep, oldactivep);
|
||||||
}
|
}
|
||||||
if (!dlyvscp) { // First use of this delayed variable
|
if (!dlyvscp) { // First use of this delayed variable
|
||||||
@@ -420,7 +420,7 @@ private:
|
|||||||
}
|
}
|
||||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
||||||
newrefp->user2(true); // No reason to do it again
|
newrefp->user2(true); // No reason to do it again
|
||||||
nodep->replaceWith(newrefp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newrefp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
else if (!m_inDly && nodep->lvalue()) {
|
else if (!m_inDly && nodep->lvalue()) {
|
||||||
//UINFO(9,"NBA "<<nodep<<endl);
|
//UINFO(9,"NBA "<<nodep<<endl);
|
||||||
@@ -432,10 +432,10 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
virtual void visit(AstNodeFor* nodep) {
|
||||||
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
|
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep) {
|
||||||
bool oldloop = m_inLoop;
|
bool oldloop = m_inLoop;
|
||||||
m_inLoop = true;
|
m_inLoop = true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -444,13 +444,13 @@ private:
|
|||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
DelayedVisitor(AstNetlist* nodep) {
|
explicit DelayedVisitor(AstNetlist* nodep) {
|
||||||
m_inDly = false;
|
m_inDly = false;
|
||||||
m_activep=NULL;
|
m_activep=NULL;
|
||||||
m_cfuncp=NULL;
|
m_cfuncp=NULL;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
+11
-11
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -85,14 +85,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
m_funcp = nodep;
|
m_funcp = nodep;
|
||||||
m_depth = 0;
|
m_depth = 0;
|
||||||
m_maxdepth = 0;
|
m_maxdepth = 0;
|
||||||
@@ -106,13 +106,13 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_stmtp = NULL;
|
m_stmtp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
virtual void visit(AstNodeStmt* nodep) {
|
||||||
visitStmt(nodep);
|
visitStmt(nodep);
|
||||||
}
|
}
|
||||||
// Operators
|
// Operators
|
||||||
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
virtual void visit(AstNodeTermop* nodep) {
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
virtual void visit(AstNodeMath* nodep) {
|
||||||
// We have some operator defines that use 2 parens, so += 2.
|
// We have some operator defines that use 2 parens, so += 2.
|
||||||
m_depth += 2;
|
m_depth += 2;
|
||||||
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
||||||
@@ -139,25 +139,25 @@ private:
|
|||||||
m_funcp->isStatic(false);
|
m_funcp->isStatic(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
virtual void visit(AstUCFunc* nodep) {
|
||||||
needNonStaticFunc(nodep);
|
needNonStaticFunc(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCStmt* nodep, AstNUser*) {
|
virtual void visit(AstUCStmt* nodep) {
|
||||||
needNonStaticFunc(nodep);
|
needNonStaticFunc(nodep);
|
||||||
visitStmt(nodep);
|
visitStmt(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
|
virtual void visit(AstVar* nodep) {} // Don't hit varrefs under vars
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
DepthVisitor(AstNetlist* nodep) {
|
explicit DepthVisitor(AstNetlist* nodep) {
|
||||||
m_modp=NULL;
|
m_modp=NULL;
|
||||||
m_funcp=NULL;
|
m_funcp=NULL;
|
||||||
m_stmtp=NULL;
|
m_stmtp=NULL;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2015 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
// Version 2.0.
|
// Version 2.0.
|
||||||
@@ -76,14 +76,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_deepNum = 0;
|
m_deepNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep) {
|
||||||
// We recurse into this.
|
// We recurse into this.
|
||||||
int lastDepth = m_depth;
|
int lastDepth = m_depth;
|
||||||
AstCFunc* lastFuncp = m_funcp;
|
AstCFunc* lastFuncp = m_funcp;
|
||||||
@@ -111,21 +111,21 @@ private:
|
|||||||
}
|
}
|
||||||
m_depth--;
|
m_depth--;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
virtual void visit(AstNodeStmt* nodep) {
|
||||||
visitStmt(nodep);
|
visitStmt(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
virtual void visit(AstNodeMath* nodep) {} // Accelerate
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
|
virtual void visit(AstVar* nodep) {} // Don't hit varrefs under vars
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
DepthBlockVisitor(AstNetlist* nodep) {
|
explicit DepthBlockVisitor(AstNetlist* nodep) {
|
||||||
m_modp=NULL;
|
m_modp=NULL;
|
||||||
m_depth=0;
|
m_depth=0;
|
||||||
//
|
//
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user