mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
5f21385e41 | ||
|
|
94fed93f54 | ||
|
|
a950e4816d | ||
|
|
c87c66efb1 | ||
|
|
5a5a0006fe | ||
|
|
60b48a6830 | ||
|
|
5e41350588 | ||
|
|
ff9f5b62ac | ||
|
|
882913f0ca | ||
|
|
2062f7e97b | ||
|
|
445c83a60d | ||
|
|
1891cfd79a | ||
|
|
06d5a7b2bf | ||
|
|
5af8a8aa4c | ||
|
|
dc6b085d8b | ||
|
|
00759f777e | ||
|
|
95ac0e61b2 | ||
|
|
6c5884853f | ||
|
|
7578ef889f | ||
|
|
da254af8d5 | ||
|
|
98123dc422 | ||
|
|
466909b3d9 | ||
|
|
0d4305192a | ||
|
|
9e61b9f696 | ||
|
|
491539ff32 | ||
|
|
4c29a13a6e | ||
|
|
b66e1bdb9e | ||
|
|
7312de6bc2 | ||
|
|
1d6bcda014 | ||
|
|
5a747bad7d | ||
|
|
9542783a7e | ||
|
|
a59639413d | ||
|
|
d5eb92a071 | ||
|
|
994cde57af | ||
|
|
238a5809bf | ||
|
|
49fa65c0dd | ||
|
|
49123f169c | ||
|
|
4dc64c387f | ||
|
|
98a63711dd | ||
|
|
cb95cf4745 | ||
|
|
acd48fa61d | ||
|
|
cb7abcbaea |
@@ -24,3 +24,4 @@ internals.txt
|
||||
verilator.txt
|
||||
verilator_bin*
|
||||
verilator_coverage_bin*
|
||||
verilator.pc
|
||||
|
||||
@@ -3,6 +3,138 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.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
|
||||
|
||||
*** Add tracing_on, etc to vlt files, bug932. [Frederic Requin]
|
||||
|
||||
**** Support extraction of enum bits, bug951. [Jonathon Donaldson]
|
||||
|
||||
**** Fix MinGW compiler error, bug927, bug929. [Hans Tichelaar]
|
||||
|
||||
**** Fix .c files to be treated as .cpp, bug930. [Jonathon Donaldson]
|
||||
|
||||
**** Fix string-to-int space conversion, bug931. [Fabrizio Ferrandi]
|
||||
|
||||
**** Fix dpi imports inside generates. [Michael Tresidder]
|
||||
|
||||
**** Fix rounding in trace $timescale, bug946. [Frederic Requin]
|
||||
|
||||
**** Fix $fopen with SV string, bug947. [Sven Stucki]
|
||||
|
||||
**** Fix hashed error with typedef inside block, bug948. [Sven Stucki]
|
||||
|
||||
**** Fix makefile with --coverage, bug953. [Eivind Liland]
|
||||
|
||||
**** Fix coverage documentation, bug954. [Thomas J Whatson]
|
||||
|
||||
**** Fix parameters with function parameter arguments, bug952. [Jie Xu]
|
||||
|
||||
**** Fix size casts as second argument of cast item, bug950. [Jonathon Donaldson]
|
||||
|
||||
|
||||
* Verilator 3.874 2015-06-06
|
||||
|
||||
*** Add pkg-config .pc file, bug919. [Stefan Wallentowitz]
|
||||
|
||||
**** Fix installing missing manpages, bug908. [Ahmed El-Mahmoudy]
|
||||
|
||||
**** Fix sign extension in large localparams, bug910. [Mike Thyer]
|
||||
|
||||
**** Fix core dump in sync-async warnings, bug911. [Sebastian Dressler]
|
||||
|
||||
**** Fix truncation warning with -pins-bv, bug912. [Alfonso Martinez]
|
||||
|
||||
**** Fix Cygwin uint32 compile, bug914. [Matthew Barr]
|
||||
|
||||
**** Fix preprocessing stringified newline escapes, bug915. [Anton Rapp]
|
||||
|
||||
**** Fix part-select in constant function, bug916. [Andrew Bardsley]
|
||||
|
||||
**** Fix width extension on mis-width ports, bug918. [Patrick Maupin]
|
||||
|
||||
**** Fix width propagation on sized casts, bug925. [Jonathon Donaldson]
|
||||
|
||||
**** Fix MSVC++ compiler error, bug927. [Hans Tichelaar]
|
||||
|
||||
|
||||
* Verilator 3.872 2015-04-05
|
||||
|
||||
*** Add VerilatedVcdFile to allow real-time waveforms, bug890. [HyungKi Jeong]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
.*\.tex
|
||||
.*\.key
|
||||
.*\.vcd
|
||||
.*\.1
|
||||
/obj_dir/
|
||||
/obj_dbg/
|
||||
/obj_opt/
|
||||
@@ -27,6 +28,7 @@ config.cache$
|
||||
config.status$
|
||||
verilator.log
|
||||
verilator.tex
|
||||
verilator.pc$
|
||||
verilator_bin.*
|
||||
verilator_coverage_bin.*
|
||||
.vcsmx_rebuild$
|
||||
|
||||
+16
-9
@@ -84,6 +84,10 @@ infodir = @infodir@
|
||||
# Generally ${prefix}/share/verilator
|
||||
pkgdatadir = @pkgdatadir@
|
||||
|
||||
# Directory in which to install pkgconfig file
|
||||
# Generall ${prefix}/share/pkgconfig
|
||||
pkgconfigdir = @pkgconfigdir@
|
||||
|
||||
# Directory in which to install data across multiple architectures
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
@@ -96,13 +100,15 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
#### End of system configuration section. ####
|
||||
######################################################################
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
SUBDIRS = src test_verilated test_c test_sc test_regress
|
||||
|
||||
INFOS = README README.html README.pdf internals.txt internals.html \
|
||||
internals.pdf verilator.txt verilator.html verilator.1 verilator.pdf \
|
||||
verilator_coverage.1
|
||||
internals.pdf verilator.txt verilator.html verilator.pdf \
|
||||
$(VL_INST_MAN_FILES)
|
||||
|
||||
# Files that can be generated, but should be up to date for a distribution.
|
||||
DISTDEP = info Makefile
|
||||
@@ -207,10 +213,7 @@ test_regress: all_nomsg
|
||||
info: $(INFOS)
|
||||
|
||||
# Use --no-split to avoid creating filenames > 14 chars.
|
||||
verilator.1: ${srcdir}/bin/verilator
|
||||
pod2man $< $@
|
||||
|
||||
verilator_coverage.1: ${srcdir}/bin/verilator_coverage
|
||||
%.1: ${srcdir}/bin/%
|
||||
pod2man $< $@
|
||||
|
||||
verilator.txt: ${srcdir}/bin/verilator
|
||||
@@ -267,7 +270,7 @@ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg verilator_coverage
|
||||
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||
|
||||
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1
|
||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_profcfunc.1
|
||||
|
||||
VL_INST_INC_BLDDIR_FILES = \
|
||||
include/verilated.mk \
|
||||
@@ -297,7 +300,7 @@ installbin:
|
||||
# So important we use $< so VPATH is searched
|
||||
installman: $(VL_INST_MAN_FILES)
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||
for p in $< ; do \
|
||||
for p in $^ ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||
done
|
||||
|
||||
@@ -317,6 +320,8 @@ installdata:
|
||||
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
|
||||
done
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgconfigdir)
|
||||
$(INSTALL_DATA) verilator.pc $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
|
||||
uninstall:
|
||||
@@ -326,6 +331,7 @@ uninstall:
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
|
||||
-rm $(DESTDIR)$(pkgconfigdir)/verilator.pc
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/bin
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include
|
||||
@@ -335,6 +341,7 @@ uninstall:
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)
|
||||
-rmdir $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
install: all_nomsg install-all
|
||||
install-all: installbin installman installdata install-msg
|
||||
@@ -420,7 +427,7 @@ ftp: info
|
||||
install-msg:
|
||||
@echo "Installed!"
|
||||
@echo
|
||||
@echo "Fod documentation see 'man verilator' or 'verilator --help'"
|
||||
@echo "For documentation see 'man verilator' or 'verilator --help'"
|
||||
@echo "For forums and to report bugs see http://www.veripool.org/verilator"
|
||||
@echo
|
||||
|
||||
|
||||
+2
-1
@@ -117,9 +117,10 @@ and add it to path using Modules/modulecmd:
|
||||
After installing you'll want a module file like the following:
|
||||
|
||||
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 MANPATH $install_root/man
|
||||
prepend-path PKG_CONFIG_PATH $install_root/share/pkgconfig
|
||||
|
||||
=item 3.
|
||||
|
||||
|
||||
+87
-38
@@ -331,6 +331,7 @@ descriptions in the next sections for more information.
|
||||
-v <filename> Verilog library
|
||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||
--vpi Enable VPI compiles
|
||||
-Werror-<message> Convert warning to error
|
||||
-Wfuture-<message> Disable unknown message warnings
|
||||
-Wno-<message> Disable warning
|
||||
@@ -471,7 +472,7 @@ Verilator will mark the signal as clocker and propagate the clocker attribute
|
||||
automatically to other signals derived from that. In this way, Verilator will
|
||||
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
|
||||
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
|
||||
RTL file to mark the signal directly.
|
||||
@@ -1103,6 +1104,10 @@ Note -v is fairly standard across Verilog tools.
|
||||
|
||||
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
|
||||
|
||||
Enable all warnings, including code style warnings that are normally
|
||||
@@ -1359,6 +1364,7 @@ And link with SystemC. Note your path to the libraries may vary,
|
||||
depending on the operating system.
|
||||
|
||||
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
|
||||
export LD_LIBRARY_PATH=$SYSTEMC_LIBDIR:$LD_LIBRARY_PATH
|
||||
# Might be needed if SystemC 2.3.0
|
||||
export SYSTEMC_CXX_FLAGS=-pthread
|
||||
|
||||
@@ -1498,6 +1504,12 @@ After running Make, the C++ compiler should produce the following:
|
||||
|
||||
=over 4
|
||||
|
||||
=item LD_LIBRARY_PATH
|
||||
|
||||
A generic Linux/OS variable specifying what directories have shared object
|
||||
(.so) files. This path should include SystemC and any other shared objects
|
||||
needed at runtime.
|
||||
|
||||
=item OBJCACHE
|
||||
|
||||
Optionally specifies a caching or distribution program to place in front of
|
||||
@@ -1795,6 +1807,8 @@ Verilator supports a very limited subset of the VPI. This subset allows
|
||||
inspection, examination, value change callbacks, and depositing of values
|
||||
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
|
||||
are to be accessed. This is done using the Verilator public pragmas
|
||||
documented below.
|
||||
@@ -1828,17 +1842,28 @@ changed on the specified clock edge.
|
||||
There are many online tutorials and books on the VPI, but an example that
|
||||
accesses the above would be:
|
||||
|
||||
void read_and_check() {
|
||||
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
||||
if (!vh1) { error... }
|
||||
const char* name = vpi_get_str(vpiName, vh1);
|
||||
printf("Module name: %s\n"); // Prints "readme"
|
||||
void read_and_check() {
|
||||
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
||||
if (!vh1) { error... }
|
||||
const char* name = vpi_get_str(vpiName, vh1);
|
||||
printf("Module name: %s\n"); // Prints "readme"
|
||||
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
vpi_get_value(vh1, &v);
|
||||
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
||||
}
|
||||
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
vpi_get_value(vh1, &v);
|
||||
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
|
||||
@@ -1916,30 +1941,40 @@ The grammar of configuration commands is as follows:
|
||||
Take remaining text up the the next `verilog mode switch and treat it as
|
||||
Verilator configuration commands.
|
||||
|
||||
=item coverage_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
=item coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
Disable coverage for the specified filename (or wildcard with '*' or '?',
|
||||
or all files if omitted) and range of line numbers (or all lines if
|
||||
Enable/disable coverage for the specified filename (or wildcard with '*' or
|
||||
'?', or all files if omitted) and range of line numbers (or all lines if
|
||||
omitted). Often used to ignore an entire module for coverage analysis
|
||||
purposes.
|
||||
|
||||
=item lint_on [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
=item lint_off [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
Disables the specified lint warning, in the specified filename (or wildcard
|
||||
with '*' or '?', or all files if omitted) and range of line numbers (or all
|
||||
lines if omitted).
|
||||
Enable/disables the specified lint warning, in the specified filename (or
|
||||
wildcard with '*' or '?', or all files if omitted) and range of line
|
||||
numbers (or all lines if omitted).
|
||||
|
||||
Using '*' will override any lint_on directives in the source, i.e. the
|
||||
warning will still not be printed.
|
||||
With lint_off using '*' will override any lint_on directives in the source,
|
||||
i.e. the warning will still not be printed.
|
||||
|
||||
If the -msg is omitted, all lint warnings are disabled. This will override
|
||||
all later lint warning enables for the specified region.
|
||||
If the -msg is omitted, all lint warnings are enabled/disabled. This will
|
||||
override all later lint warning enables for the specified region.
|
||||
|
||||
=item tracing_on [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
=item tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
Disable waveform tracing for all future signals declared in the specified
|
||||
filename (or wildcard with '*' or '?', or all files if omitted) and range
|
||||
of line numbers (or all lines if omitted).
|
||||
Enable/disable waveform tracing for all future signals declared in the
|
||||
specified filename (or wildcard with '*' or '?', or all files if omitted)
|
||||
and range of line numbers (or all lines if omitted).
|
||||
|
||||
For tracing_off, cells below any module in the files/ranges specified will
|
||||
also not be traced.
|
||||
|
||||
|
||||
=back
|
||||
|
||||
@@ -2068,45 +2103,52 @@ per the C standard (it's unspecified in Verilog).
|
||||
|
||||
=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 */.
|
||||
|
||||
=item `systemc_header
|
||||
|
||||
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
|
||||
macro, this also works in pure C++ code.
|
||||
place it verbatim into the output .h file's header. Must 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.
|
||||
|
||||
=item `systemc_ctor
|
||||
|
||||
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
|
||||
macro, this also works in pure C++ code.
|
||||
place it verbatim into the C++ class constructor. Must 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.
|
||||
|
||||
=item `systemc_dtor
|
||||
|
||||
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
|
||||
macro, this also works in pure C++ code.
|
||||
place it verbatim into the C++ class destructor. Must 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.
|
||||
|
||||
=item `systemc_interface
|
||||
|
||||
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
|
||||
macro, this also works in pure C++ code.
|
||||
place it verbatim into the C++ class interface. Must 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.
|
||||
|
||||
=item `systemc_imp_header
|
||||
|
||||
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
|
||||
implementation. Despite the name of this macro, this also works in pure
|
||||
C++ code.
|
||||
implementation. Must 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.
|
||||
|
||||
=item `systemc_implementation
|
||||
|
||||
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.
|
||||
Despite the name of this macro, this also works in pure C++ code.
|
||||
place it verbatim into a single file of the C++ class implementation. Must
|
||||
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++
|
||||
functions, the Verilog signals must be declared with /*verilator public*/.
|
||||
@@ -2887,7 +2929,7 @@ this warning is enabled only if user has explicitly marked some signal as
|
||||
clocker using command line option or in-source meta comment (see C<--clk>).
|
||||
|
||||
The warning can be disabled without affecting the simulation result. But it
|
||||
is recommanded to check the warning as this may degrade the performance of
|
||||
is recommended to check the warning as this may degrade the performance of
|
||||
the Verilated model.
|
||||
|
||||
=item CMPCONST
|
||||
@@ -3298,6 +3340,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,
|
||||
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
|
||||
|
||||
Warns that a task, function, or begin/end block is declaring a variable by
|
||||
@@ -3556,7 +3602,10 @@ First, run verilator with the --coverage option. If you're using your own
|
||||
makefile, compile the model with the GCC flag -DVM_COVERAGE (if using
|
||||
Verilator's, it will do this for you.)
|
||||
|
||||
Run your tests in different directories. Each test will create a
|
||||
At the end of your test, call VerilatedCov::write passing the name of the
|
||||
coverage data file (typically "logs/coverage.dat").
|
||||
|
||||
Run each of your tests in different directories. Each test will create a
|
||||
logs/coverage.pl file.
|
||||
|
||||
After running all of your tests, verilator_coverage is executed.
|
||||
|
||||
+6
-2
@@ -6,9 +6,11 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.872 2015-04-05])
|
||||
AC_INIT([Verilator],[3.880 2015-12-19])
|
||||
# When releasing, also update header of Changes file
|
||||
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc)
|
||||
|
||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
|
||||
@@ -161,6 +163,8 @@ AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
# Other install directories
|
||||
pkgdatadir=${datadir}/verilator
|
||||
AC_SUBST(pkgdatadir)
|
||||
pkgconfigdir=${datadir}/pkgconfig
|
||||
AC_SUBST(pkgconfigdir)
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
+43
-6
@@ -374,7 +374,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
} else {
|
||||
lwp = va_arg(ap,WDataInP);
|
||||
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;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
case '#': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
int needmore = width-digits;
|
||||
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';
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'o':
|
||||
for (; lsb>=0; lsb--) {
|
||||
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));
|
||||
}
|
||||
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':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 4) * 4; // Next digit
|
||||
@@ -633,7 +656,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
break;
|
||||
}
|
||||
case 't': // FALLTHRU // Time
|
||||
case 'u': { // Unsigned decimal
|
||||
case '#': { // Unsigned decimal
|
||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
@@ -708,8 +731,8 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
start = false; // Drop leading 0s
|
||||
}
|
||||
}
|
||||
*destp++ = '\0'; // Terminate
|
||||
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||
*destp = '\0'; // Terminate
|
||||
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||
}
|
||||
|
||||
void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
@@ -750,6 +773,11 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||
return got;
|
||||
}
|
||||
|
||||
IData VL_FOPEN_NI(const string& filename, IData mode) {
|
||||
char modez[5];
|
||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||
return VL_FOPEN_S(filename.c_str(), modez);
|
||||
}
|
||||
IData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
return VL_FOPEN_WI(2, fnw, mode);
|
||||
@@ -1146,7 +1174,12 @@ void Verilated::commandArgs(int argc, const char** argv) {
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -1165,6 +1198,10 @@ int Verilated::exportFuncNum(const char* namep) {
|
||||
return VerilatedImp::exportFind(namep);
|
||||
}
|
||||
|
||||
const VerilatedScopeNameMap* Verilated::scopeNameMap() {
|
||||
return VerilatedImp::scopeNameMap();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// VerilatedModule:: Methods
|
||||
|
||||
|
||||
+10
-5
@@ -38,6 +38,7 @@
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
// <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
|
||||
using namespace std;
|
||||
|
||||
@@ -68,6 +69,7 @@ typedef void (*VerilatedVoidCb)(void);
|
||||
|
||||
class SpTraceVcd;
|
||||
class SpTraceVcdCFile;
|
||||
class VerilatedScopeNameMap;
|
||||
class VerilatedVar;
|
||||
class VerilatedVarNameMap;
|
||||
class VerilatedVcd;
|
||||
@@ -102,9 +104,9 @@ class VerilatedModule {
|
||||
private:
|
||||
const char* m_namep; ///< Module name
|
||||
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:
|
||||
VerilatedModule(const char* namep); ///< Create module with given hierarchy name
|
||||
explicit VerilatedModule(const char* namep); ///< Create module with given hierarchy name
|
||||
~VerilatedModule();
|
||||
const char* name() const { return m_namep; } ///< Return name of module
|
||||
};
|
||||
@@ -287,6 +289,7 @@ public:
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
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);
|
||||
|
||||
/// Produce name & version for (at least) VPI
|
||||
@@ -308,6 +311,7 @@ public:
|
||||
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
||||
// Internal: Find scope
|
||||
static const VerilatedScope* scopeFind(const char* namep);
|
||||
static const VerilatedScopeNameMap* scopeNameMap();
|
||||
// Internal: Get and set DPI context
|
||||
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
|
||||
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
|
||||
@@ -357,6 +361,7 @@ extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
@@ -594,13 +599,13 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
|
||||
#define VL_ASSIGN_SWI(obits,svar,rd) { \
|
||||
sc_bv<obits> _bvtemp; \
|
||||
_bvtemp.set_word(0,rd); \
|
||||
_bvtemp.set_word(0,(rd)); \
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
#define VL_ASSIGN_SWQ(obits,svar,rd) { \
|
||||
sc_bv<obits> _bvtemp; \
|
||||
_bvtemp.set_word(0,rd); \
|
||||
_bvtemp.set_word(1,rd>>VL_WORDSIZE); \
|
||||
_bvtemp.set_word(0,(IData)(rd)); \
|
||||
_bvtemp.set_word(1,(IData)((rd)>>VL_WORDSIZE)); \
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
|
||||
|
||||
@@ -120,10 +120,6 @@ ifeq ($(VM_SP),1)
|
||||
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
||||
--preproc $(VK_CLASSES_SP)
|
||||
else
|
||||
ifeq ($(VM_COVERAGE),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||
endif
|
||||
preproc:
|
||||
endif
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
virtual vluint64_t count() const { return *m_countp; }
|
||||
virtual void zero() const { *m_countp = 0; }
|
||||
// CONSTRUCTORS
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
VerilatedCoverItemSpec(T* countp) : m_countp(countp) { zero(); }
|
||||
virtual ~VerilatedCoverItemSpec() {}
|
||||
};
|
||||
@@ -261,8 +262,8 @@ public:
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
VlCovCvtToCStr linestrp (m_insertLineno);
|
||||
ckeyps[1]="lineno"; valps[1]=linestrp;
|
||||
string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
|
||||
// Default page if not specified
|
||||
const char* fnstartp = m_insertFilenamep;
|
||||
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
|
||||
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
K(4),const string& val4, A(5),A(6)) {
|
||||
string val2str = vlCovCvtToStr(val2);
|
||||
string val3str = vlCovCvtToStr(val3);
|
||||
_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),
|
||||
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));
|
||||
|
||||
@@ -78,19 +78,6 @@ template< class T> std::string vlCovCvtToStr (const T& t) {
|
||||
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
|
||||
/// Verilator coverage global class
|
||||
|
||||
@@ -60,6 +60,7 @@ inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs
|
||||
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
|
||||
}
|
||||
|
||||
extern IData VL_FOPEN_NI(const string& filename, IData mode);
|
||||
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 string VL_SFORMATF_NX(const char* formatp, ...);
|
||||
|
||||
@@ -49,7 +49,6 @@ class VerilatedImp {
|
||||
// TYPES
|
||||
typedef vector<string> ArgVec;
|
||||
typedef map<pair<const void*,void*>,void*> UserMap;
|
||||
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
|
||||
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||
|
||||
// MEMBERS
|
||||
@@ -60,7 +59,7 @@ class VerilatedImp {
|
||||
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||
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:
|
||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext; ///< Next export funcnum
|
||||
@@ -154,30 +153,33 @@ public: // But only for verilated*.cpp
|
||||
// METHODS - scope name
|
||||
static void scopeInsert(const VerilatedScope* scopep) {
|
||||
// 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()) {
|
||||
s_s.m_nameMap.insert(it, make_pair(scopep->name(),scopep));
|
||||
}
|
||||
}
|
||||
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;
|
||||
else return NULL;
|
||||
}
|
||||
static void scopeErase(const VerilatedScope* scopep) {
|
||||
// Slow ok - called once/scope at destruction
|
||||
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);
|
||||
}
|
||||
static void scopesDump() {
|
||||
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;
|
||||
scopep->scopeDump();
|
||||
}
|
||||
VL_PRINTF("\n");
|
||||
}
|
||||
static const VerilatedScopeNameMap* scopeNameMap() {
|
||||
return &s_s.m_nameMap;
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - export names
|
||||
|
||||
@@ -201,7 +201,7 @@ void VerilatedRestore::fill() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||
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_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
|
||||
@@ -48,6 +48,8 @@ protected:
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
private:
|
||||
VerilatedSerialBase(const VerilatedSerialBase& ); ///< N/A, no copy constructor
|
||||
public:
|
||||
// CREATORS
|
||||
virtual ~VerilatedSerialBase() {
|
||||
@@ -223,7 +225,7 @@ inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
||||
vluint32_t len;
|
||||
vluint32_t len=0;
|
||||
os>>len;
|
||||
rhs.resize(len);
|
||||
return os.read((void*)rhs.data(), len);
|
||||
|
||||
+14
-10
@@ -32,16 +32,6 @@
|
||||
|
||||
#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
|
||||
|
||||
@@ -93,6 +83,20 @@ public:
|
||||
//======================================================================
|
||||
/// 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> {
|
||||
public:
|
||||
VerilatedVarNameMap() {}
|
||||
|
||||
@@ -378,7 +378,7 @@ string VerilatedVcd::doubleToTimescale (double value) {
|
||||
else if (value>=1e-12) { suffixp="ps"; value *= 1e12; }
|
||||
else if (value>=1e-15) { suffixp="fs"; value *= 1e15; }
|
||||
else if (value>=1e-18) { suffixp="as"; value *= 1e18; }
|
||||
char valuestr[100]; sprintf(valuestr,"%d%s",(int)(value), suffixp);
|
||||
char valuestr[100]; sprintf(valuestr,"%3.0f%s", value, suffixp);
|
||||
return valuestr; // Gets converted to string, so no ref to stack
|
||||
}
|
||||
|
||||
|
||||
@@ -144,13 +144,15 @@ private:
|
||||
return out + ((char)((code)%94+33));
|
||||
}
|
||||
|
||||
VerilatedVcd(const VerilatedVcd& ); ///< N/A, no copy constructor
|
||||
|
||||
protected:
|
||||
// METHODS
|
||||
void evcd(bool flag) { m_evcd = flag; }
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedVcd(VerilatedVcdFile* filep=NULL);
|
||||
explicit VerilatedVcd(VerilatedVcdFile* filep=NULL);
|
||||
~VerilatedVcd();
|
||||
|
||||
// ACCESSORS
|
||||
@@ -399,7 +401,7 @@ class VerilatedVcdC {
|
||||
VerilatedVcd m_sptrace; ///< Trace file being created
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
|
||||
explicit VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
|
||||
~VerilatedVcdC() {}
|
||||
// ACCESSORS
|
||||
/// Is file open?
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
//--------------------------------------------------
|
||||
#if (SYSTEMC_VERSION>=20050714)
|
||||
// SystemC 2.1.v1
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment (const std::string &) {}
|
||||
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)
|
||||
// SystemC 2.0.1
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
||||
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
|
||||
// SystemC 1.2.1beta
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
||||
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+18
-994
File diff suppressed because it is too large
Load Diff
+19
-1
@@ -95,6 +95,12 @@
|
||||
// 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
|
||||
|
||||
#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
|
||||
|
||||
@@ -139,7 +145,7 @@ typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward comp
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
# ifdef __uint32_t_defined // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
# else // Older Cygwin has long==uint32_t
|
||||
@@ -207,6 +213,18 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
# if (_MSC_VER < 1900)
|
||||
# define VL_SNPRINTF _snprintf
|
||||
# else
|
||||
# define VL_SNPRINTF snprintf
|
||||
# endif
|
||||
# define VL_VSNPRINTF vsnprintf
|
||||
#else
|
||||
# define VL_SNPRINTF snprintf
|
||||
# define VL_VSNPRINTF vsnprintf
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
// File system functions
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ obj_opt:
|
||||
obj_dbg:
|
||||
mkdir $@
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
.PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
|
||||
|
||||
opt: ../verilator_bin
|
||||
|
||||
@@ -327,6 +327,8 @@ V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
||||
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp $(FLEXFIX)
|
||||
$(PERL) $(FLEXFIX) V3PreLex <$< >$@
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
######################################################################
|
||||
######################################################################
|
||||
|
||||
|
||||
+9
-9
@@ -83,7 +83,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||
// Simplify sensitivity list
|
||||
V3Const::constifyExpensiveEdit(nodep); nodep=NULL;
|
||||
V3Const::constifyExpensiveEdit(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
// Empty visitors, speed things up
|
||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) { }
|
||||
@@ -184,7 +184,7 @@ private:
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssign* nodep, AstNUser*) {
|
||||
@@ -288,7 +288,7 @@ private:
|
||||
// Relink to CFUNC for the final
|
||||
UINFO(4," FINAL "<<nodep<<endl);
|
||||
if (!nodep->bodysp()) { // Empty, Kill it.
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
@@ -304,7 +304,7 @@ private:
|
||||
nodep->unlinkFrBack();
|
||||
m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName()));
|
||||
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
// METHODS
|
||||
@@ -316,7 +316,7 @@ private:
|
||||
&& oldsensesp->sensesp()->castSenItem()->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ private:
|
||||
|
||||
// Delete sensitivity list
|
||||
if (oldsensesp) {
|
||||
oldsensesp->unlinkFrBackWithNext()->deleteTree(); oldsensesp=NULL;
|
||||
oldsensesp->unlinkFrBackWithNext()->deleteTree(); VL_DANGLING(oldsensesp);
|
||||
}
|
||||
|
||||
// Move node to new active
|
||||
@@ -377,7 +377,7 @@ private:
|
||||
|
||||
if (!nodep->bodysp()) {
|
||||
// Empty always. Kill it.
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||
@@ -402,7 +402,7 @@ private:
|
||||
m_itemCombo = true;
|
||||
// Delete the sensitivity
|
||||
// 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()) {
|
||||
// V3LinkResolve should have cleaned most of these up
|
||||
if (!nodep->varrefp()->width1()) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||
@@ -421,7 +421,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveVisitor(AstNetlist* nodep) {
|
||||
explicit ActiveVisitor(AstNetlist* nodep) {
|
||||
m_scopeFinalp = NULL;
|
||||
m_itemCombo = false;
|
||||
m_itemSequent = false;
|
||||
|
||||
+2
-2
@@ -87,7 +87,7 @@ private:
|
||||
&& sensesp->sensesp()->castSenItem()->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
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;
|
||||
}
|
||||
// Copy combo tree to settlement tree with duplicated statements
|
||||
@@ -147,7 +147,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveTopVisitor(AstNetlist* nodep) {
|
||||
explicit ActiveTopVisitor(AstNetlist* nodep) {
|
||||
m_topscopep = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
|
||||
+5
-5
@@ -138,7 +138,7 @@ private:
|
||||
nodep->replaceWith(newp);
|
||||
}
|
||||
// Bye
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void newVAssertion(AstVAssert* nodep, AstNode* propp) {
|
||||
@@ -160,7 +160,7 @@ private:
|
||||
// Install it
|
||||
nodep->replaceWith(newp);
|
||||
// Bye
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstIf* nodep, AstNUser*) {
|
||||
@@ -285,12 +285,12 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
||||
nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep);
|
||||
++m_statAsCover;
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
||||
newVAssertion(nodep, nodep->propp()); VL_DANGLING(nodep);
|
||||
++m_statAsSV;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
AssertVisitor(AstNetlist* nodep) {
|
||||
explicit AssertVisitor(AstNetlist* nodep) {
|
||||
m_beginp = NULL;
|
||||
m_modp = NULL;
|
||||
// Process
|
||||
|
||||
+3
-3
@@ -83,7 +83,7 @@ private:
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
// Unlink and just keep a pointer to it, convert to sentree as needed
|
||||
m_senip = nodep->sensesp();
|
||||
nodep->replaceWith(blockp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -122,7 +122,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
AssertPreVisitor(AstNetlist* nodep) {
|
||||
explicit AssertPreVisitor(AstNetlist* nodep) {
|
||||
m_seniDefaultp = NULL;
|
||||
clearAssertInfo();
|
||||
// Process
|
||||
|
||||
+21
-7
@@ -28,6 +28,7 @@
|
||||
#include "V3File.h"
|
||||
#include "V3Global.h"
|
||||
#include "V3Broken.h"
|
||||
#include "V3String.h"
|
||||
|
||||
//======================================================================
|
||||
// Statics
|
||||
@@ -93,10 +94,9 @@ void AstNode::init() {
|
||||
|
||||
string AstNode::encodeName(const string& namein) {
|
||||
// Encode signal name raw from parser, then not called again on same signal
|
||||
const char* start = namein.c_str();
|
||||
string out;
|
||||
for (const char* pos = start; *pos; pos++) {
|
||||
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers
|
||||
for (string::const_iterator pos = namein.begin(); pos!=namein.end(); ++pos) {
|
||||
if ((pos==namein.begin()) ? isalpha(pos[0]) // digits can't lead identifiers
|
||||
: isalnum(pos[0])) {
|
||||
out += pos[0];
|
||||
} else if (pos[0]=='_') {
|
||||
@@ -115,6 +115,10 @@ string AstNode::encodeName(const string& namein) {
|
||||
out += hex;
|
||||
}
|
||||
}
|
||||
// Shorten names
|
||||
// TODO long term use VName in place of "string name"
|
||||
VName vname(out);
|
||||
out = vname.hashedName();
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -823,10 +827,10 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||
// 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);
|
||||
{
|
||||
tempp->stmtsp()->accept(v, vup); nodep=NULL; // nodep to null as may be replaced
|
||||
tempp->stmtsp()->accept(v, vup); VL_DANGLING(nodep); // nodep to null as may be replaced
|
||||
}
|
||||
nodep = tempp->stmtsp()->unlinkFrBackWithNext();
|
||||
tempp->deleteTree(); tempp=NULL;
|
||||
tempp->deleteTree(); VL_DANGLING(tempp);
|
||||
} else {
|
||||
// Use back to determine who's pointing at us (IE assume new node grafts into same place as old one)
|
||||
AstNode** nextnodepp = NULL;
|
||||
@@ -837,7 +841,7 @@ AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||
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");
|
||||
{
|
||||
nodep->accept(v, vup); nodep=NULL; // nodep to null as may be replaced
|
||||
nodep->accept(v, vup); VL_DANGLING(nodep); // nodep to null as may be replaced
|
||||
}
|
||||
nodep = *nextnodepp; // Grab new node from point where old was connected
|
||||
}
|
||||
@@ -863,6 +867,16 @@ void AstNode::cloneRelinkTree() {
|
||||
//======================================================================
|
||||
// Comparison
|
||||
|
||||
bool AstNode::gateTreeIter() {
|
||||
// Return true if the two trees are identical
|
||||
if (this==NULL) return true;
|
||||
if (!isGateOptimizable()) return false;
|
||||
return (this->op1p()->gateTreeIter()
|
||||
&& this->op2p()->gateTreeIter()
|
||||
&& this->op3p()->gateTreeIter()
|
||||
&& this->op4p()->gateTreeIter());
|
||||
}
|
||||
|
||||
bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly) {
|
||||
// Return true if the two trees are identical
|
||||
if (this==NULL && node2p==NULL) return true;
|
||||
@@ -1016,7 +1030,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
||||
if (doDump) {
|
||||
{ // Write log & close
|
||||
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);
|
||||
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||
|
||||
+36
-10
@@ -53,6 +53,7 @@ public:
|
||||
enum en m_e;
|
||||
// cppcheck-suppress uninitVar // responsiblity of each subclass
|
||||
inline AstType () {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstType (en _e) : m_e(_e) {}
|
||||
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -87,7 +88,9 @@ public:
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () : m_e(UNSIGNED) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstNumeric (VSignedState signst) {
|
||||
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
|
||||
else if (signst==signedst_SIGNED) m_e=SIGNED;
|
||||
@@ -121,6 +124,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstPragmaType () : m_e(ILLEGAL) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstPragmaType (en _e) : m_e(_e) {}
|
||||
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -144,6 +148,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstCFuncType () : m_e(FT_NORMAL) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstCFuncType (en _e) : m_e(_e) {}
|
||||
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -212,6 +217,7 @@ public:
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstEdgeType (en _e) : m_e(_e) {}
|
||||
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -239,6 +245,7 @@ public:
|
||||
//
|
||||
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
|
||||
//
|
||||
ENUM_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
ENUM_FIRST, // V3Width processes
|
||||
ENUM_LAST, // V3Width processes
|
||||
ENUM_NUM, // V3Width processes
|
||||
@@ -268,7 +275,7 @@ public:
|
||||
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||
"DT_PUBLIC",
|
||||
"ENUM_FIRST", "ENUM_LAST", "ENUM_NUM", "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME",
|
||||
"ENUM_BASE", "ENUM_FIRST", "ENUM_LAST", "ENUM_NUM", "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME",
|
||||
"MEMBER_BASE",
|
||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
@@ -278,6 +285,7 @@ public:
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstAttrType () : m_e(ILLEGAL) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstAttrType (en _e) : m_e(_e) {}
|
||||
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -337,6 +345,7 @@ public:
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
||||
}
|
||||
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
||||
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -431,6 +440,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstVarType () : m_e(UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstVarType (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -468,6 +478,7 @@ public:
|
||||
enum en m_e;
|
||||
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
||||
inline AstBranchPred () : m_e(BP_UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstBranchPred (en _e) : m_e(_e) {}
|
||||
explicit inline AstBranchPred (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -499,6 +510,7 @@ public:
|
||||
enum en m_e;
|
||||
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
||||
inline AstVarAttrClocker () : m_e(CLOCKER_UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -529,6 +541,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline VAlwaysKwd () : m_e(ALWAYS) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VAlwaysKwd (en _e) : m_e(_e) {}
|
||||
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -553,6 +566,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline VCaseType () : m_e(CT_CASE) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VCaseType (en _e) : m_e(_e) {}
|
||||
explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -575,6 +589,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstDisplayType () : m_e(DT_DISPLAY) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstDisplayType (en _e) : m_e(_e) {}
|
||||
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -599,6 +614,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstParseRefExp() : m_e(PX_NONE) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstParseRefExp (en _e) : m_e(_e) {}
|
||||
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -896,16 +912,19 @@ public:
|
||||
// CREATORS
|
||||
class Illegal {}; // 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
|
||||
V3Hash(AstNUser* up) { m_both=up->castInt(); }
|
||||
explicit V3Hash(AstNUser* up) { m_both=up->castInt(); }
|
||||
V3Hash operator+= (const V3Hash& rh) {
|
||||
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
|
||||
return *this; };
|
||||
// Creating from raw data (sameHash functions)
|
||||
V3Hash() { setBoth(1,0); }
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
V3Hash(uint32_t val) { setBoth(1,val); }
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
V3Hash(const void* vp) { setBoth(1,cvtToHash(vp)); }
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
V3Hash(const string& name);
|
||||
V3Hash(V3Hash h1, V3Hash h2) {
|
||||
setBoth(1,h1.hshval()*31+h2.hshval()); }
|
||||
@@ -973,12 +992,15 @@ class AstNode {
|
||||
|
||||
void init(); // initialize value of AstNode
|
||||
void iterateListBackwards(AstNVisitor& v, AstNUser* vup=NULL);
|
||||
private:
|
||||
AstNode* cloneTreeIter();
|
||||
AstNode* cloneTreeIterList();
|
||||
void checkTreeIter(AstNode* backp);
|
||||
void checkTreeIterList(AstNode* backp);
|
||||
bool gateTreeIter();
|
||||
bool sameTreeIter(AstNode* node2p, bool ignNext, bool gateOnly);
|
||||
void deleteTreeIter();
|
||||
public:
|
||||
void deleteNode();
|
||||
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
||||
// cppcheck-suppress functionConst
|
||||
@@ -987,7 +1009,7 @@ class AstNode {
|
||||
protected:
|
||||
// CONSTUCTORS
|
||||
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 void cloneRelink() {}
|
||||
void cloneRelinkTree();
|
||||
@@ -1079,6 +1101,7 @@ public:
|
||||
//TODO stomp these width functions out, and call via dtypep() instead
|
||||
int width() const;
|
||||
int widthMin() const;
|
||||
int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
@@ -1205,6 +1228,7 @@ public:
|
||||
|
||||
// METHODS - Iterate on a tree
|
||||
AstNode* cloneTree(bool cloneNextLink);
|
||||
bool gateTree() { return gateTreeIter(); } // Is tree gateOptimizable?
|
||||
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
||||
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
|
||||
void deleteTree(); // Always deletes the next link
|
||||
@@ -1268,7 +1292,7 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
||||
class AstNodeMath : public AstNode {
|
||||
// Math -- anything that's part of an expression tree
|
||||
public:
|
||||
AstNodeMath(FileLine* fl)
|
||||
explicit AstNodeMath(FileLine* fl)
|
||||
: AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeMath)
|
||||
// METHODS
|
||||
@@ -1285,7 +1309,7 @@ public:
|
||||
class AstNodeTermop : public AstNodeMath {
|
||||
// Terminal operator -- a operator with no "inputs"
|
||||
public:
|
||||
AstNodeTermop(FileLine* fl)
|
||||
explicit AstNodeTermop(FileLine* fl)
|
||||
: AstNodeMath(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||
// Know no children, and hot function, so skip iterator for speed
|
||||
@@ -1429,7 +1453,7 @@ public:
|
||||
class AstNodeStmt : public AstNode {
|
||||
// Statement -- anything that's directly under a function
|
||||
public:
|
||||
AstNodeStmt(FileLine* fl)
|
||||
explicit AstNodeStmt(FileLine* fl)
|
||||
: AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeStmt)
|
||||
// METHODS
|
||||
@@ -1519,7 +1543,7 @@ public:
|
||||
class AstNodeSenItem : public AstNode {
|
||||
// An AstSenItem or AstSenGate
|
||||
public:
|
||||
AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
||||
explicit AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
||||
ASTNODE_BASE_FUNCS(NodeSenItem)
|
||||
virtual bool isClocked() const = 0;
|
||||
virtual bool isCombo() const = 0;
|
||||
@@ -1606,7 +1630,7 @@ private:
|
||||
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
AstNodeDType(FileLine* fl) : AstNode(fl) {
|
||||
explicit AstNodeDType(FileLine* fl) : AstNode(fl) {
|
||||
m_width=0; m_widthMin=0; m_generic=false;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeDType)
|
||||
@@ -1695,7 +1719,7 @@ private:
|
||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
||||
public:
|
||||
AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
||||
explicit AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
||||
m_refDTypep = NULL;
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
||||
@@ -1788,6 +1812,7 @@ public:
|
||||
virtual void dump(ostream& str=cout);
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
virtual bool maybePointedTo() const { return true; }
|
||||
virtual bool isGateOptimizable() const { return !((m_dpiExport || m_dpiImport) && !m_pure); }
|
||||
// {AstFunc only} op1 = Range output variable
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
string cname() const { return m_cname; }
|
||||
@@ -1846,6 +1871,7 @@ public:
|
||||
}}
|
||||
virtual void dump(ostream& str=cout);
|
||||
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 prettyDotted() const { return prettyName(dotted()); }
|
||||
string inlinedDots() const { return m_inlinedDots; }
|
||||
|
||||
+4
-22
@@ -506,9 +506,9 @@ string AstScope::nameDotless() const {
|
||||
return out;
|
||||
}
|
||||
|
||||
string AstScopeName::scopePrettyName() const {
|
||||
string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const {
|
||||
string out;
|
||||
for (AstText* textp=scopeAttrp(); textp; textp=textp->nextp()->castText()) {
|
||||
for (AstText* textp=scopeTextp; textp; textp=textp->nextp()->castText()) {
|
||||
out += textp->text();
|
||||
}
|
||||
// TOP will be replaced by top->name()
|
||||
@@ -518,27 +518,9 @@ string AstScopeName::scopePrettyName() const {
|
||||
return AstNode::prettyName(out);
|
||||
}
|
||||
|
||||
string AstScopeName::scopeSymName() const {
|
||||
string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const {
|
||||
string out;
|
||||
for (AstText* textp=scopeAttrp(); textp; textp=textp->nextp()->castText()) {
|
||||
out += textp->text();
|
||||
}
|
||||
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
|
||||
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
|
||||
if (out.substr(0,1) == ".") out.replace(0,1,"");
|
||||
string::size_type pos;
|
||||
while ((pos=out.find(".")) != string::npos) {
|
||||
out.replace(pos, 1, "__");
|
||||
}
|
||||
while ((pos=out.find("__DOT__")) != string::npos) {
|
||||
out.replace(pos, 7, "__");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
string AstScopeName::scopeDpiName() const {
|
||||
string out;
|
||||
for (AstText* textp=scopeEntrp(); textp; textp=textp->nextp()->castText()) {
|
||||
for (AstText* textp=scopeTextp; textp; textp=textp->nextp()->castText()) {
|
||||
out += textp->text();
|
||||
}
|
||||
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
|
||||
|
||||
+73
-15
@@ -103,7 +103,7 @@ public:
|
||||
return num().isCaseEq(samep->castConst()->num()); }
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
bool isEqAllOnes() const { return num().isEqAllOnes(width()); }
|
||||
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMin()); }
|
||||
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
|
||||
};
|
||||
|
||||
class AstRange : public AstNode {
|
||||
@@ -1311,6 +1311,7 @@ public:
|
||||
ASTNODE_NODE_FUNCS(VarXRef, VARXREF)
|
||||
virtual void dump(ostream& str);
|
||||
string dotted() const { return m_dotted; }
|
||||
void dotted(const string& dotted) { m_dotted = dotted; }
|
||||
string prettyDotted() const { return prettyName(dotted()); }
|
||||
string inlinedDots() const { return m_inlinedDots; }
|
||||
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
||||
@@ -1570,6 +1571,56 @@ public:
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
};
|
||||
|
||||
class AstCellRef : public AstNode {
|
||||
// As-of-yet unlinkable reference into a cell
|
||||
private:
|
||||
string m_name; // Cell name
|
||||
public:
|
||||
AstCellRef(FileLine* fl,
|
||||
string name, AstNode* cellp, AstNode* exprp)
|
||||
: AstNode(fl)
|
||||
, m_name(name) {
|
||||
addNOp1p(cellp); addNOp2p(exprp); }
|
||||
ASTNODE_NODE_FUNCS(CellRef, CELLREF)
|
||||
// ACCESSORS
|
||||
virtual string name() const { return m_name; } // * = Array name
|
||||
AstNode* cellp() const { return op1p(); } // op1 = Cell
|
||||
AstNode* exprp() const { return op2p(); } // op2 = Expression
|
||||
};
|
||||
|
||||
class AstCellArrayRef : public AstNode {
|
||||
// As-of-yet unlinkable reference into an array of cells
|
||||
private:
|
||||
string m_name; // Array name
|
||||
public:
|
||||
AstCellArrayRef(FileLine* fl,
|
||||
string name, AstNode* selectExprp)
|
||||
: AstNode(fl)
|
||||
, m_name(name) {
|
||||
addNOp1p(selectExprp); }
|
||||
ASTNODE_NODE_FUNCS(CellArrayRef, CELLARRAYREF)
|
||||
// ACCESSORS
|
||||
virtual string name() const { return m_name; } // * = Array name
|
||||
AstNode* selp() const { return op1p(); } // op1 = Select expression
|
||||
};
|
||||
|
||||
class AstUnlinkedRef : public AstNode {
|
||||
// As-of-yet unlinkable Ref
|
||||
private:
|
||||
string m_name; // Var name
|
||||
public:
|
||||
AstUnlinkedRef(FileLine* fl,
|
||||
AstNode* refp, string name, AstNode* crp)
|
||||
: AstNode(fl)
|
||||
, m_name(name) {
|
||||
addNOp1p(refp); addNOp2p(crp); }
|
||||
ASTNODE_NODE_FUNCS(UnlinkedRef, UNLINKEDREF)
|
||||
// ACCESSORS
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef
|
||||
AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef
|
||||
};
|
||||
|
||||
class AstBind : public AstNode {
|
||||
// Parents: MODULE
|
||||
// Children: CELL
|
||||
@@ -2208,11 +2259,13 @@ class AstSFormatF : public AstNode {
|
||||
public:
|
||||
AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp)
|
||||
: AstNode(fl), m_text(text), m_hidden(hidden) {
|
||||
dtypeSetString();
|
||||
addNOp1p(exprsp); addNOp2p(NULL); }
|
||||
ASTNODE_NODE_FUNCS(SFormatF, SFORMATF)
|
||||
virtual string name() const { return m_text; }
|
||||
virtual int instrCount() const { return instrCountPli(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
||||
virtual bool hasDType() const { return true; }
|
||||
virtual bool same(AstNode* samep) const { return text()==samep->castSFormatF()->text(); }
|
||||
virtual string verilogKwd() const { return "$sformatf"; }
|
||||
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||
@@ -2602,7 +2655,7 @@ public:
|
||||
|
||||
class AstBreak : public AstNodeStmt {
|
||||
public:
|
||||
AstBreak(FileLine* fileline)
|
||||
explicit AstBreak(FileLine* fileline)
|
||||
: AstNodeStmt (fileline) {}
|
||||
ASTNODE_NODE_FUNCS(Break, BREAK)
|
||||
virtual string verilogKwd() const { return "break"; };
|
||||
@@ -2612,7 +2665,7 @@ public:
|
||||
|
||||
class AstContinue : public AstNodeStmt {
|
||||
public:
|
||||
AstContinue(FileLine* fileline)
|
||||
explicit AstContinue(FileLine* fileline)
|
||||
: AstNodeStmt (fileline) {}
|
||||
ASTNODE_NODE_FUNCS(Continue, CONTINUE)
|
||||
virtual string verilogKwd() const { return "continue"; };
|
||||
@@ -2905,7 +2958,7 @@ public:
|
||||
|
||||
class AstStop : public AstNodeStmt {
|
||||
public:
|
||||
AstStop(FileLine* fl)
|
||||
explicit AstStop(FileLine* fl)
|
||||
: AstNodeStmt(fl) {}
|
||||
ASTNODE_NODE_FUNCS(Stop, STOP)
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
@@ -2921,7 +2974,7 @@ public:
|
||||
|
||||
class AstFinish : public AstNodeStmt {
|
||||
public:
|
||||
AstFinish(FileLine* fl)
|
||||
explicit AstFinish(FileLine* fl)
|
||||
: AstNodeStmt(fl) {}
|
||||
ASTNODE_NODE_FUNCS(Finish, FINISH)
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
@@ -3067,8 +3120,10 @@ class AstScopeName : public AstNodeMath {
|
||||
// Children: TEXT
|
||||
private:
|
||||
bool m_dpiExport; // Is for dpiExport
|
||||
string scopeNameFormatter(AstText* textp) const;
|
||||
string scopePrettyNameFormatter(AstText* textp) const;
|
||||
public:
|
||||
AstScopeName(FileLine* fl) : AstNodeMath(fl), m_dpiExport(false) {
|
||||
explicit AstScopeName(FileLine* fl) : AstNodeMath(fl), m_dpiExport(false) {
|
||||
dtypeSetUInt64(); }
|
||||
ASTNODE_NODE_FUNCS(ScopeName, SCOPENAME)
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
@@ -3080,9 +3135,10 @@ public:
|
||||
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstText* scopeEntrp() const { return op2p()->castText(); }
|
||||
void scopeEntrp(AstNode* nodep) { addOp2p(nodep); }
|
||||
string scopeSymName() const; // Name for __Vscope variable including children
|
||||
string scopeDpiName() const; // Name for DPI import scope
|
||||
string scopePrettyName() const; // Name for __Vscope printing
|
||||
string scopeSymName() const { return scopeNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
|
||||
string scopeDpiName() const { return scopeNameFormatter(scopeEntrp()); } // Name for DPI import scope
|
||||
string scopePrettySymName() const { return scopePrettyNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
|
||||
string scopePrettyDpiName() const { return scopePrettyNameFormatter(scopeEntrp()); } // Name for __Vscope variable including children
|
||||
bool dpiExport() const { return m_dpiExport; }
|
||||
void dpiExport(bool flag) { m_dpiExport=flag; }
|
||||
};
|
||||
@@ -3117,7 +3173,7 @@ private:
|
||||
public:
|
||||
AstRand(FileLine* fl, AstNodeDType* dtp, bool reset) : AstNodeTermop(fl) {
|
||||
dtypep(dtp); m_reset=reset; }
|
||||
AstRand(FileLine* fl) : AstNodeTermop(fl), m_reset(false) { }
|
||||
explicit AstRand(FileLine* fl) : AstNodeTermop(fl), m_reset(false) { }
|
||||
ASTNODE_NODE_FUNCS(Rand, RAND)
|
||||
virtual string emitVerilog() { return "%f$random"; }
|
||||
virtual string emitC() {
|
||||
@@ -3134,7 +3190,7 @@ public:
|
||||
|
||||
class AstTime : public AstNodeTermop {
|
||||
public:
|
||||
AstTime(FileLine* fl) : AstNodeTermop(fl) {
|
||||
explicit AstTime(FileLine* fl) : AstNodeTermop(fl) {
|
||||
dtypeSetUInt64(); }
|
||||
ASTNODE_NODE_FUNCS(Time, TIME)
|
||||
virtual string emitVerilog() { return "%f$time"; }
|
||||
@@ -3149,7 +3205,7 @@ public:
|
||||
|
||||
class AstTimeD : public AstNodeTermop {
|
||||
public:
|
||||
AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
|
||||
explicit AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(TimeD, TIMED)
|
||||
virtual string emitVerilog() { return "%f$realtime"; }
|
||||
@@ -3310,7 +3366,8 @@ public:
|
||||
dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(ExtendS, EXTENDS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.opExtendS(lhs, lhsp()->widthMin()); }
|
||||
out.opExtendS(lhs, lhsp()->widthMinV());
|
||||
}
|
||||
virtual string emitVerilog() { return "%l"; }
|
||||
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
@@ -3510,6 +3567,7 @@ public:
|
||||
setOp1p(lhsp); setOp2p(rhsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(CastSize, CASTSIZE)
|
||||
// No hasDType because widthing removes this node before the hasDType check
|
||||
virtual string emitVerilog() { return "((%r)'(%l))"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;}
|
||||
@@ -4150,7 +4208,7 @@ public:
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMin()); }
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMinV()); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>>> %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
@@ -5075,7 +5133,7 @@ class AstTypeTable : public AstNode {
|
||||
typedef map<VBasicTypeKey,AstBasicDType*> DetailedMap;
|
||||
DetailedMap m_detailedMap;
|
||||
public:
|
||||
AstTypeTable(FileLine* fl) : AstNode(fl) {
|
||||
explicit AstTypeTable(FileLine* fl) : AstNode(fl) {
|
||||
for (int i=0; i<AstBasicDTypeKwd::_ENUM_MAX; ++i) m_basicps[i] = NULL;
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(TypeTable, TYPETABLE)
|
||||
|
||||
+28
-3
@@ -56,7 +56,7 @@ public:
|
||||
m_anyFuncInBegin = false;
|
||||
}
|
||||
~BeginState() {}
|
||||
void userMarkChanged(AstNodeFTask* nodep) {
|
||||
void userMarkChanged(AstNode* nodep) {
|
||||
nodep->user1(true);
|
||||
m_anyFuncInBegin = true;
|
||||
}
|
||||
@@ -160,12 +160,13 @@ private:
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
if (m_unnamedScope != "") {
|
||||
// Rename it
|
||||
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
|
||||
m_statep->userMarkChanged(nodep);
|
||||
// Move to module
|
||||
nodep->unlinkFrBack();
|
||||
if (m_ftaskp) m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func
|
||||
@@ -175,6 +176,7 @@ private:
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
UINFO(8," CELL "<<nodep<<endl);
|
||||
if (m_namedScope != "") {
|
||||
m_statep->userMarkChanged(nodep);
|
||||
// Rename it
|
||||
nodep->name(m_namedScope+"__DOT__"+nodep->name());
|
||||
UINFO(8," rename to "<<nodep->name()<<endl);
|
||||
@@ -182,6 +184,14 @@ private:
|
||||
nodep->unlinkFrBack();
|
||||
m_modp->addStmtp(nodep);
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
||||
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, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
@@ -215,7 +225,7 @@ private:
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
m_ifDepth = prevIfDepth;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -249,6 +259,21 @@ private:
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
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, AstNUser*) {
|
||||
// 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*) {
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BranchVisitor(AstNetlist* nodep) {
|
||||
explicit BranchVisitor(AstNetlist* nodep) {
|
||||
reset();
|
||||
nodep->iterateChildren(*this);
|
||||
calc_tasks();
|
||||
|
||||
+20
-16
@@ -186,14 +186,18 @@ private:
|
||||
// NODE STATE
|
||||
// Nothing! // This may be called deep inside other routines
|
||||
// // so userp and friends may not be used
|
||||
// VISITORS
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// METHODS
|
||||
void processAndIterate(AstNode* nodep) {
|
||||
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
|
||||
nodep->iterateChildrenConst(*this);
|
||||
}
|
||||
// VISITORS
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BrokenMarkVisitor(AstNetlist* nodep) {
|
||||
explicit BrokenMarkVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~BrokenMarkVisitor() {}
|
||||
@@ -204,7 +208,13 @@ public:
|
||||
|
||||
class BrokenCheckVisitor : public AstNVisitor {
|
||||
private:
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
void checkWidthMin(AstNode* nodep) {
|
||||
if (nodep->width() != nodep->widthMin()
|
||||
&& v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH) {
|
||||
nodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
void processAndIterate(AstNode* nodep) {
|
||||
BrokenTable::setUnder(nodep,true);
|
||||
if (const char* whyp=nodep->broken()) {
|
||||
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
|
||||
@@ -220,24 +230,18 @@ private:
|
||||
if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName());
|
||||
}
|
||||
if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed");
|
||||
if (AstNodeDType* dnodep = nodep->castNodeDType()) {
|
||||
if (dnodep->width() != dnodep->widthMin()
|
||||
&& v3Global.assertWidthsMatch()) {
|
||||
dnodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v3Global.assertWidthsMatch()) {
|
||||
if (nodep->width() != nodep->widthMin()) {
|
||||
nodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
if (AstNodeDType* dnodep = nodep->castNodeDType()) checkWidthMin(dnodep);
|
||||
}
|
||||
checkWidthMin(nodep);
|
||||
nodep->iterateChildrenConst(*this);
|
||||
BrokenTable::setUnder(nodep,false);
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BrokenCheckVisitor(AstNetlist* nodep) {
|
||||
explicit BrokenCheckVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~BrokenCheckVisitor() {}
|
||||
|
||||
+13
-15
@@ -112,7 +112,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CaseLintVisitor(AstNodeCase* nodep) {
|
||||
explicit CaseLintVisitor(AstNodeCase* nodep) {
|
||||
m_caseExprp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -246,7 +246,7 @@ private:
|
||||
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
|
||||
}
|
||||
if (same) {
|
||||
tree1p->deleteTree(); tree1p=NULL;
|
||||
tree1p->deleteTree(); VL_DANGLING(tree1p);
|
||||
return tree0p;
|
||||
}
|
||||
|
||||
@@ -295,8 +295,8 @@ private:
|
||||
|
||||
if (ifrootp) nodep->replaceWith(ifrootp);
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
cexprp->deleteTree(); cexprp=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
cexprp->deleteTree(); VL_DANGLING(cexprp);
|
||||
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ private:
|
||||
AstConst* iconstp = icondp->castConst();
|
||||
if (iconstp && neverItem(nodep, iconstp)) {
|
||||
// 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
|
||||
// optimizations remove it
|
||||
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
|
||||
@@ -351,7 +351,7 @@ private:
|
||||
AstNode* and2p = new AstAnd(itemp->fileline(),
|
||||
new AstConst(itemp->fileline(), numval),
|
||||
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);
|
||||
} else {
|
||||
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
||||
@@ -369,7 +369,7 @@ private:
|
||||
itemp->condsp(ifexprp);
|
||||
}
|
||||
}
|
||||
cexprp->deleteTree(); cexprp=NULL;
|
||||
cexprp->deleteTree(); VL_DANGLING(cexprp);
|
||||
if (!hadDefault) {
|
||||
// If there was no default, add a empty one, this greatly simplifies below code
|
||||
// and constant propagation will just eliminate it for us later.
|
||||
@@ -408,10 +408,9 @@ private:
|
||||
}
|
||||
}
|
||||
{ // 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
|
||||
itemexprp->deleteTree(); itemexprp=NULL;
|
||||
// cppcheck-suppress redundantAssignment
|
||||
itemexprp->deleteTree(); VL_DANGLING(itemexprp);
|
||||
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
|
||||
}
|
||||
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
|
||||
@@ -427,7 +426,7 @@ private:
|
||||
if (debug()>=9) grouprootp->dumpTree(cout," _new: ");
|
||||
if (grouprootp) nodep->replaceWith(grouprootp);
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void replaceCaseParallel(AstCase* nodep, bool noOverlapsAllCovered) {
|
||||
@@ -460,11 +459,10 @@ private:
|
||||
// It's a simple priority encoder or complete statement
|
||||
// we can make a tree of statements to avoid extra comparisons
|
||||
++m_statCaseFast;
|
||||
replaceCaseFast(nodep); nodep=NULL;
|
||||
replaceCaseFast(nodep); VL_DANGLING(nodep);
|
||||
} else {
|
||||
++m_statCaseSlow;
|
||||
// cppcheck-supporess uselessAssignmentPtrArg
|
||||
replaceCaseComplicated(nodep); nodep=NULL;
|
||||
replaceCaseComplicated(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
//--------------------
|
||||
@@ -475,7 +473,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CaseVisitor(AstNetlist* nodep) {
|
||||
explicit CaseVisitor(AstNetlist* nodep) {
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CastVisitor(AstNetlist* nodep) {
|
||||
explicit CastVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~CastVisitor() {}
|
||||
|
||||
+3
-3
@@ -184,7 +184,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CdcWidthVisitor(AstNode* nodep) {
|
||||
explicit CdcWidthVisitor(AstNode* nodep) {
|
||||
m_maxLineno = 0;
|
||||
m_maxFilenameLen = 0;
|
||||
nodep->accept(*this);
|
||||
@@ -496,7 +496,7 @@ private:
|
||||
}
|
||||
|
||||
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);
|
||||
*ofp<<"Edge Report for "<<v3Global.opt.prefix()<<endl;
|
||||
|
||||
@@ -726,7 +726,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CdcVisitor(AstNode* nodep) {
|
||||
explicit CdcVisitor(AstNode* nodep) {
|
||||
m_logicVertexp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_modp = NULL;
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CleanVisitor(AstNetlist* nodep) {
|
||||
explicit CleanVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~CleanVisitor() {}
|
||||
|
||||
+11
-11
@@ -66,7 +66,7 @@ class GaterVarVertex;
|
||||
class GaterVertex : public V3GraphVertex {
|
||||
static uint32_t s_rankNum;
|
||||
public:
|
||||
GaterVertex(V3Graph* graphp)
|
||||
explicit GaterVertex(V3Graph* graphp)
|
||||
: V3GraphVertex(graphp) {
|
||||
s_rankNum++; rank(s_rankNum);
|
||||
}
|
||||
@@ -79,7 +79,7 @@ uint32_t GaterVertex::s_rankNum = 0;
|
||||
|
||||
class GaterHeadVertex : public GaterVertex {
|
||||
public:
|
||||
GaterHeadVertex(V3Graph* graphp)
|
||||
explicit GaterHeadVertex(V3Graph* graphp)
|
||||
: GaterVertex(graphp) {}
|
||||
virtual ~GaterHeadVertex() {}
|
||||
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
|
||||
class GaterPliVertex : public GaterVertex {
|
||||
public:
|
||||
GaterPliVertex(V3Graph* graphp)
|
||||
explicit GaterPliVertex(V3Graph* graphp)
|
||||
: GaterVertex(graphp) {}
|
||||
virtual ~GaterPliVertex() {}
|
||||
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||
@@ -217,7 +217,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
GaterCondVisitor(AstNode* nodep) {
|
||||
explicit GaterCondVisitor(AstNode* nodep) {
|
||||
m_isSimple = true;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -296,7 +296,7 @@ class GaterBodyVisitor : public GaterBaseVisitor {
|
||||
}
|
||||
|
||||
if ((childstate & STATE_DELETE) && !(childstate & STATE_KEEP)) {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
// Pass upwards we did delete
|
||||
m_state |= STATE_DELETE;
|
||||
} else {
|
||||
@@ -427,7 +427,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
for (V3GraphEdge* nextp,* edgep = m_pliVertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->outNextp(); // We may edit the list
|
||||
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 {
|
||||
m_graph.dump();
|
||||
v3fatalSrc("PLI vertex points to non-signal");
|
||||
@@ -463,7 +463,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
V3GraphVertex* toVxp = edgep->top();
|
||||
//UINFO(9," to "<<toVxp->user()<<" "<<toVxp<<endl);
|
||||
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
|
||||
toVxp->user(toVxp->user() | VU_MADE);
|
||||
GaterEdge* inedgep = static_cast<GaterEdge*>(vertexp->inBeginp());
|
||||
@@ -487,7 +487,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
if (toVxp->user() && toVxp->user() < depth) {
|
||||
// A recursion "above" us marked it,
|
||||
// Remove this edge, it's redundant with the upper edge
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
} else {
|
||||
GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
|
||||
if (cedgep->ifelseBoth()) {
|
||||
@@ -515,7 +515,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
if (GaterIfVertex* toVxp = dynamic_cast<GaterIfVertex*>(edgep->top())) {
|
||||
if (!toVxp->outBeginp()) {
|
||||
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
|
||||
if (GaterVarVertex* toVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -878,7 +878,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
GaterVisitor(AstNode* nodep) {
|
||||
explicit GaterVisitor(AstNode* nodep) {
|
||||
// AstAlways visitor does the real work, so most zeroing needs to be in clear()
|
||||
clear();
|
||||
nodep->accept(*this);
|
||||
|
||||
+7
-7
@@ -268,7 +268,7 @@ private:
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstAlwaysPost* nodep, AstNUser*) {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
@@ -277,7 +277,7 @@ private:
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
||||
//nodep->dumpTree(cout,"ct:");
|
||||
@@ -297,7 +297,7 @@ private:
|
||||
newp->addIfsp(new AstAssign(nodep->fileline(),
|
||||
changep->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*) {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
@@ -306,7 +306,7 @@ private:
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -342,7 +342,7 @@ private:
|
||||
// Not at the top or empty block...
|
||||
// Only empty blocks should be leftover on the non-top. Killem.
|
||||
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
@@ -374,7 +374,7 @@ private:
|
||||
// Move statements to function
|
||||
addToEvalLoop(stmtsp);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep = NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ClockVisitor(AstNetlist* nodep) {
|
||||
explicit ClockVisitor(AstNetlist* nodep) {
|
||||
m_modp=NULL; m_activep=NULL;
|
||||
m_evalFuncp = NULL;
|
||||
m_topScopep=NULL;
|
||||
|
||||
+8
-8
@@ -111,7 +111,7 @@ public:
|
||||
callp->unlinkFrBack();
|
||||
}
|
||||
callp->user3(true); // Dead now
|
||||
pushDeletep(callp); callp=NULL;
|
||||
pushDeletep(callp); VL_DANGLING(callp);
|
||||
m_callMmap.erase(eqit); // Fix the table
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
CombMarkVisitor(AstNode* nodep) {
|
||||
explicit CombMarkVisitor(AstNode* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~CombMarkVisitor() {}
|
||||
@@ -230,7 +230,7 @@ private:
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
m_call.replaceFunc(oldfuncp, NULL);
|
||||
oldfuncp->unlinkFrBack();
|
||||
pushDeletep(oldfuncp); oldfuncp=NULL;
|
||||
pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,7 +262,7 @@ private:
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
m_call.replaceFunc(oldfuncp, newfuncp);
|
||||
oldfuncp->unlinkFrBack();
|
||||
pushDeletep(oldfuncp); oldfuncp=NULL;
|
||||
pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
|
||||
}
|
||||
void replaceOnlyCallFunc(AstCCall* nodep) {
|
||||
if (AstCFunc* oldfuncp = nodep->backp()->castCFunc()) {
|
||||
@@ -274,7 +274,7 @@ private:
|
||||
UINFO(9," Function only has call "<<oldfuncp<<endl);
|
||||
m_call.deleteCall(nodep);
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
replaceFuncWFunc(oldfuncp, nodep->funcp()); nodep=NULL;
|
||||
replaceFuncWFunc(oldfuncp, nodep->funcp()); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,8 +384,8 @@ private:
|
||||
m_call.addCall(call2p);
|
||||
// If either new statement makes a func with only a single call, replace
|
||||
// the above callers to call it directly
|
||||
replaceOnlyCallFunc(call1p); call1p=NULL;
|
||||
replaceOnlyCallFunc(call2p); call2p=NULL;
|
||||
replaceOnlyCallFunc(call1p); VL_DANGLING(call1p);
|
||||
replaceOnlyCallFunc(call2p); VL_DANGLING(call2p);
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
@@ -457,7 +457,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CombineVisitor(AstNetlist* nodep) {
|
||||
explicit CombineVisitor(AstNetlist* nodep) {
|
||||
m_modp=NULL;
|
||||
m_funcp = NULL;
|
||||
m_state = STATE_IDLE;
|
||||
|
||||
+4
-4
@@ -144,12 +144,12 @@ V3ConfigIgnores V3ConfigIgnores::s_singleton;
|
||||
//######################################################################
|
||||
// V3Config
|
||||
|
||||
void V3Config::addIgnore(V3ErrorCode code, string filename, int min, int max) {
|
||||
void V3Config::addIgnore(V3ErrorCode code, bool on, string filename, int min, int max) {
|
||||
if (filename=="*") {
|
||||
FileLine::globalWarnOff(code,true);
|
||||
FileLine::globalWarnOff(code,!on);
|
||||
} else {
|
||||
V3ConfigIgnores::singleton().addIgnore(code, filename, min, false);
|
||||
if (max) V3ConfigIgnores::singleton().addIgnore(code, filename, max, true);
|
||||
V3ConfigIgnores::singleton().addIgnore(code, filename, min, on);
|
||||
if (max) V3ConfigIgnores::singleton().addIgnore(code, filename, max, !on);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
|
||||
class V3Config {
|
||||
public:
|
||||
static void addIgnore(V3ErrorCode code, string filename, int min, int max);
|
||||
static void addIgnore(V3ErrorCode code, bool on, string filename, int min, int max);
|
||||
static void applyIgnores(FileLine* filelinep);
|
||||
};
|
||||
|
||||
|
||||
+92
-90
@@ -33,6 +33,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Width.h"
|
||||
@@ -54,7 +55,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ConstVarMarkVisitor(AstNode* nodep) {
|
||||
explicit ConstVarMarkVisitor(AstNode* nodep) {
|
||||
AstNode::user4ClearTree(); // Check marked InUse before we're called
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -76,7 +77,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ConstVarFindVisitor(AstNode* nodep) {
|
||||
explicit ConstVarFindVisitor(AstNode* nodep) {
|
||||
m_found = false;
|
||||
nodep->iterateAndNext(*this, NULL);
|
||||
}
|
||||
@@ -214,7 +215,7 @@ private:
|
||||
if (!operandsSame(ap, bp)) return false;
|
||||
// Do it
|
||||
cp->unlinkFrBack();
|
||||
andp->unlinkFrBack()->deleteTree(); andp=NULL; notp=NULL;
|
||||
andp->unlinkFrBack()->deleteTree(); VL_DANGLING(andp); VL_DANGLING(notp);
|
||||
// Replace whichever branch is now dangling
|
||||
if (nodep->rhsp()) nodep->lhsp(cp);
|
||||
else nodep->rhsp(cp);
|
||||
@@ -319,7 +320,7 @@ private:
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
)) return false;
|
||||
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
|
||||
replaceWChild(nodep, extendp->lhsp()); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
bool operandSelBiLower(AstSel* nodep) {
|
||||
@@ -338,7 +339,7 @@ private:
|
||||
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
|
||||
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
|
||||
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
|
||||
replaceWChild(nodep, bip); nodep=NULL;
|
||||
replaceWChild(nodep, bip); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -364,7 +365,7 @@ private:
|
||||
V3Number num (constp->fileline(), subsize);
|
||||
num.opAssign(constp->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:");
|
||||
return true;
|
||||
}
|
||||
@@ -450,6 +451,9 @@ private:
|
||||
if (!ifvarp || !elsevarp) return false;
|
||||
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
|
||||
if (!ifvarp->sameGateTree(elsevarp)) return false;
|
||||
UINFO(1,"HERE "<<nodep<<endl);
|
||||
if (!ifp->rhsp()->gateTree()) return false;
|
||||
if (!elsep->rhsp()->gateTree()) return false;
|
||||
return true;
|
||||
}
|
||||
bool operandIfIf(AstNodeIf* nodep) {
|
||||
@@ -559,58 +563,58 @@ private:
|
||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||
if (debug()>5) newp->dumpTree(cout," _new: ");
|
||||
oldp->replaceWith(newp);
|
||||
oldp->deleteTree(); oldp=NULL;
|
||||
oldp->deleteTree(); VL_DANGLING(oldp);
|
||||
}
|
||||
void replaceNum (AstNode* nodep, uint32_t 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) {
|
||||
// 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())) {
|
||||
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) {
|
||||
// Avoids gcc warning about same
|
||||
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) {
|
||||
replaceNum(nodep, 0); nodep=NULL;
|
||||
replaceNum(nodep, 0); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
|
||||
// For example, "0 * n" -> 0 if n has no side effects
|
||||
// Else strength reduce it to 0 & n.
|
||||
// If ever change the operation note AstAnd rule specially ignores this created pattern
|
||||
if (isTPure(checkp)) {
|
||||
replaceNum(nodep, 0); nodep=NULL;
|
||||
replaceNum(nodep, 0); VL_DANGLING(nodep);
|
||||
} else {
|
||||
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), 0),
|
||||
checkp->unlinkFrBack());
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
void replaceAllOnes (AstNode* nodep) {
|
||||
V3Number ones (nodep->fileline(), nodep->width(), 0);
|
||||
ones.setMask(nodep->width());
|
||||
replaceNum(nodep, ones); nodep=NULL;
|
||||
replaceNum(nodep, ones); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceConst(AstNodeUniop* nodep) {
|
||||
V3Number num (nodep->fileline(), nodep->width());
|
||||
nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
|
||||
UINFO(4,"UNICONST -> "<<num<<endl);
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceConst(AstNodeBiop* nodep) {
|
||||
V3Number num (nodep->fileline(), nodep->width());
|
||||
nodep->numberOperate(num, nodep->lhsp()->castConst()->num(), nodep->rhsp()->castConst()->num());
|
||||
UINFO(4,"BICONST -> "<<num<<endl);
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceConst(AstNodeTriop* nodep) {
|
||||
V3Number num (nodep->fileline(), nodep->width());
|
||||
@@ -618,7 +622,7 @@ private:
|
||||
nodep->rhsp()->castConst()->num(),
|
||||
nodep->thsp()->castConst()->num());
|
||||
UINFO(4,"TRICONST -> "<<num<<endl);
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void replaceConstString (AstNode* oldp, const string& num) {
|
||||
@@ -628,7 +632,7 @@ private:
|
||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||
if (debug()>5) newp->dumpTree(cout," _new: ");
|
||||
oldp->replaceWith(newp);
|
||||
oldp->deleteTree(); oldp=NULL;
|
||||
oldp->deleteTree(); VL_DANGLING(oldp);
|
||||
}
|
||||
//----------------------------------------
|
||||
// Replacement functions.
|
||||
@@ -641,7 +645,7 @@ private:
|
||||
// This may adversly affect the operation of the node being replaced.
|
||||
childp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(childp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
//! Replace a ternary node with its RHS after iterating
|
||||
@@ -775,9 +779,9 @@ private:
|
||||
UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
|
||||
|
||||
nodep->replaceWith(newselp);
|
||||
lselp->deleteTree(); lselp = NULL;
|
||||
rselp->deleteTree(); rselp = NULL;
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
lselp->deleteTree(); VL_DANGLING(lselp);
|
||||
rselp->deleteTree(); VL_DANGLING(rselp);
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceConcatMerge(AstConcat* nodep) {
|
||||
AstNodeBiop* lp = nodep->lhsp()->castNodeBiop();
|
||||
@@ -794,8 +798,8 @@ private:
|
||||
lp->rhsp()->replaceWith(newrp);
|
||||
lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::fromBool(true));
|
||||
UINFO(5, "merged "<< nodep <<endl);
|
||||
rp->unlinkFrBack()->deleteTree(); rp = NULL;
|
||||
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); nodep = NULL;
|
||||
rp->unlinkFrBack()->deleteTree(); VL_DANGLING(rp);
|
||||
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
lp->lhsp()->accept(*this);
|
||||
lp->rhsp()->accept(*this);
|
||||
} else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
|
||||
@@ -808,7 +812,7 @@ private:
|
||||
? (new AstExtendS(nodep->fileline(), arg0p))->castNode()
|
||||
: (new AstExtend (nodep->fileline(), arg0p))->castNode());
|
||||
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
|
||||
UINFO(5,"POW(2,b)->SHIFTL(1,b) "<<nodep<<endl);
|
||||
@@ -818,7 +822,7 @@ private:
|
||||
rhsp);
|
||||
newp->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
|
||||
UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<<nodep<<endl);
|
||||
@@ -827,7 +831,7 @@ private:
|
||||
AstShiftL* newp = new AstShiftL(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), amount));
|
||||
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
|
||||
UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<<nodep<<endl);
|
||||
@@ -836,7 +840,7 @@ private:
|
||||
AstShiftR* newp = new AstShiftR(nodep->fileline(),
|
||||
opp, new AstConst(nodep->fileline(), amount));
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceShiftOp (AstNodeBiop* nodep) {
|
||||
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
|
||||
@@ -867,8 +871,8 @@ private:
|
||||
int shift1 = shift1p->castConst()->toUInt();
|
||||
int shift2 = shift2p->castConst()->toUInt();
|
||||
int newshift = shift1+shift2;
|
||||
shift1p->deleteTree(); shift1p=NULL;
|
||||
shift2p->deleteTree(); shift2p=NULL;
|
||||
shift1p->deleteTree(); VL_DANGLING(shift1p);
|
||||
shift2p->deleteTree(); VL_DANGLING(shift2p);
|
||||
nodep->lhsp(ap);
|
||||
nodep->rhsp(new AstConst(nodep->fileline(), newshift));
|
||||
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
||||
@@ -877,8 +881,8 @@ private:
|
||||
int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
||||
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
|
||||
int newshift = shift1+shift2;
|
||||
shift1p->deleteTree(); shift1p=NULL;
|
||||
shift2p->deleteTree(); shift2p=NULL;
|
||||
shift1p->deleteTree(); VL_DANGLING(shift1p);
|
||||
shift2p->deleteTree(); VL_DANGLING(shift2p);
|
||||
AstNode* newp;
|
||||
V3Number mask1 (nodep->fileline(), nodep->width());
|
||||
V3Number ones (nodep->fileline(), nodep->width());
|
||||
@@ -906,11 +910,11 @@ private:
|
||||
newp,
|
||||
new AstConst (nodep->fileline(), mask));
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
//newp->dumpTree(cout, " repShiftShift_new: ");
|
||||
newp->accept(*this); // Further reduce, either node may have more reductions.
|
||||
}
|
||||
lhsp->deleteTree(); lhsp=NULL;
|
||||
lhsp->deleteTree(); VL_DANGLING(lhsp);
|
||||
}
|
||||
|
||||
bool replaceAssignMultiSel(AstNodeAssign* nodep) {
|
||||
@@ -983,7 +987,7 @@ private:
|
||||
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
|
||||
} else {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1079,8 +1083,8 @@ private:
|
||||
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
|
||||
nodep->addNextHere(newp);
|
||||
// Cleanup
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
conp->deleteTree(); conp=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
conp->deleteTree(); VL_DANGLING(conp);
|
||||
// Further reduce, either node may have more reductions.
|
||||
return true;
|
||||
}
|
||||
@@ -1093,8 +1097,8 @@ private:
|
||||
AstNode* streamp = nodep->rhsp()->castStreamR()->unlinkFrBack();
|
||||
nodep->rhsp(srcp);
|
||||
// Cleanup
|
||||
sizep->deleteTree(); sizep=NULL;
|
||||
streamp->deleteTree(); streamp=NULL;
|
||||
sizep->deleteTree(); VL_DANGLING(sizep);
|
||||
streamp->deleteTree(); VL_DANGLING(streamp);
|
||||
// Further reduce, any of the nodes may have more reductions.
|
||||
return true;
|
||||
}
|
||||
@@ -1137,8 +1141,8 @@ private:
|
||||
nodep->lhsp(dstp);
|
||||
nodep->rhsp(srcp);
|
||||
// Cleanup
|
||||
sizep->deleteTree(); sizep=NULL;
|
||||
streamp->deleteTree(); streamp=NULL;
|
||||
sizep->deleteTree(); VL_DANGLING(sizep);
|
||||
streamp->deleteTree(); VL_DANGLING(streamp);
|
||||
// Further reduce, any of the nodes may have more reductions.
|
||||
return true;
|
||||
}
|
||||
@@ -1171,7 +1175,7 @@ private:
|
||||
fromp);
|
||||
newp->dtypeSetLogicSized(nodep->width(), nodep->width(), AstNumeric::UNSIGNED); // widthMin no longer applicable if different C-expanded width
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
||||
}
|
||||
|
||||
@@ -1185,13 +1189,13 @@ private:
|
||||
<<nodep->prettyTypeName()<<endl
|
||||
<<errorp->warnMore()<<"... Location of non-constant "
|
||||
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||
replaceZero(nodep); nodep=NULL;
|
||||
replaceZero(nodep); VL_DANGLING(nodep);
|
||||
} else {
|
||||
// Fetch the result
|
||||
V3Number* outnump = simvis.fetchNumberNull(nodep);
|
||||
if (!outnump) nodep->v3fatalSrc("No number returned from simulation");
|
||||
// Replace it
|
||||
replaceNum(nodep,*outnump); nodep=NULL;
|
||||
replaceNum(nodep,*outnump); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1271,7 +1275,7 @@ private:
|
||||
// If bp was a concat, then we have this exact same form again!
|
||||
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
||||
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
||||
bcConcp->deleteTree(); bcConcp=NULL;
|
||||
bcConcp->deleteTree(); VL_DANGLING(bcConcp);
|
||||
} else {
|
||||
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
||||
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
||||
@@ -1282,7 +1286,7 @@ private:
|
||||
nodep->lhsp(ap);
|
||||
nodep->rhsp(bcConcp);
|
||||
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
|
||||
abConcp->deleteTree(); abConcp=NULL;
|
||||
abConcp->deleteTree(); VL_DANGLING(abConcp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1313,8 +1317,8 @@ private:
|
||||
if (lsb1p->castConst() && lsb2p->castConst()) {
|
||||
newlsbp = new AstConst(lsb1p->fileline(),
|
||||
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
|
||||
lsb1p->deleteTree(); lsb1p=NULL;
|
||||
lsb2p->deleteTree(); lsb2p=NULL;
|
||||
lsb1p->deleteTree(); VL_DANGLING(lsb1p);
|
||||
lsb2p->deleteTree(); VL_DANGLING(lsb2p);
|
||||
} else {
|
||||
// Width is important, we need the width of the fromp's
|
||||
// expression, not the potentially smaller lsb1p's width
|
||||
@@ -1328,7 +1332,7 @@ private:
|
||||
newlsbp,
|
||||
widthp);
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void replaceSelConcat(AstSel* nodep) {
|
||||
@@ -1368,7 +1372,7 @@ private:
|
||||
conRhsp->width()-nodep->lsbConst()));
|
||||
nodep->replaceWith(newp);
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void replaceSelReplicate(AstSel* nodep) {
|
||||
@@ -1382,7 +1386,7 @@ private:
|
||||
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||
widthp);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void replaceSelIntoBiop(AstSel* nodep) {
|
||||
@@ -1400,7 +1404,7 @@ private:
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
void replaceSelIntoUniop(AstSel* nodep) {
|
||||
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
|
||||
@@ -1414,7 +1418,7 @@ private:
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp, widthp));
|
||||
fromp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
@@ -1443,7 +1447,7 @@ private:
|
||||
}
|
||||
m_selp = NULL;
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
bool did=false;
|
||||
@@ -1463,7 +1467,7 @@ private:
|
||||
if (operandConst(valuep)) {
|
||||
const V3Number& num = valuep->castConst()->num();
|
||||
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||
did=true;
|
||||
}
|
||||
else if (m_selp && valuep->castInitArray()) {
|
||||
@@ -1473,7 +1477,7 @@ private:
|
||||
if (itemp->castConst()) {
|
||||
const V3Number& num = itemp->castConst()->num();
|
||||
//UINFO(2,"constVisit "<<(void*)valuep<<" "<<num<<endl);
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||
did=true;
|
||||
}
|
||||
}
|
||||
@@ -1492,7 +1496,7 @@ private:
|
||||
nodep->itemp()->valuep()->iterateAndNext(*this);
|
||||
if (AstConst* valuep = nodep->itemp()->valuep()->castConst()) {
|
||||
const V3Number& num = valuep->num();
|
||||
replaceNum(nodep, num); nodep=NULL;
|
||||
replaceNum(nodep, num); VL_DANGLING(nodep);
|
||||
did=true;
|
||||
}
|
||||
}
|
||||
@@ -1519,13 +1523,13 @@ private:
|
||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||
if (onlySenItemInSenTree(nodep)) {
|
||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
} else { // Otherwise it may compute a result that needs to settle out
|
||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
} else if (m_doNConst && nodep->sensp()->castNot()) {
|
||||
// V3Gate may propagate NOTs into clocks... Just deal with it
|
||||
@@ -1541,7 +1545,7 @@ private:
|
||||
AstNodeVarRef* senvarp = lastSensp->unlinkFrBack()->castNodeVarRef();
|
||||
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
||||
sensp->replaceWith(senvarp);
|
||||
sensp->deleteTree(); sensp=NULL;
|
||||
sensp->deleteTree(); VL_DANGLING(sensp);
|
||||
} else if (!m_doNConst // Deal with later when doNConst missing
|
||||
&& (nodep->sensp()->castEnumItemRef()
|
||||
|| nodep->sensp()->castConst())) {
|
||||
@@ -1556,15 +1560,15 @@ private:
|
||||
UINFO(4,"SENGATE(...,0)->NEVER"<<endl);
|
||||
if (onlySenItemInSenTree(nodep)) {
|
||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
} else {
|
||||
UINFO(4,"SENGATE(SENITEM,0)->ALWAYS SENITEM"<<endl);
|
||||
AstNode* senitemp = nodep->sensesp()->unlinkFrBack();
|
||||
nodep->replaceWith(senitemp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1630,7 +1634,7 @@ private:
|
||||
// Found, push this item up to the top
|
||||
itemp->unlinkFrBack();
|
||||
nodep->addSensesp(itemp);
|
||||
gatep->unlinkFrBack()->deleteTree(); gatep=NULL; senp=NULL;
|
||||
gatep->unlinkFrBack()->deleteTree(); VL_DANGLING(gatep); VL_DANGLING(senp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1686,7 +1690,7 @@ private:
|
||||
&& ritemp->edgeType()==AstEdgeType::ET_NEGEDGE)
|
||||
litemp->edgeType(AstEdgeType::ET_BOTHEDGE);
|
||||
// Remove redundant node
|
||||
ritemp->unlinkFrBack()->deleteTree(); ritemp=NULL; cmpp=NULL;
|
||||
ritemp->unlinkFrBack()->deleteTree(); VL_DANGLING(ritemp); VL_DANGLING(cmpp);
|
||||
// Try to collapse again
|
||||
nextp=litemp;
|
||||
}
|
||||
@@ -1729,7 +1733,7 @@ private:
|
||||
new AstAssign(nodep->fileline(),
|
||||
varrefp, exprp));
|
||||
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
|
||||
AstNode* initvaluep = exprp->cloneTree(false);
|
||||
varrefp->varp()->valuep(initvaluep);
|
||||
@@ -1754,12 +1758,12 @@ private:
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||
// Empty block, remove it
|
||||
// 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())) {
|
||||
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
||||
@@ -1781,7 +1785,7 @@ private:
|
||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||
ifp->branchPred(nodep->branchPred().invert());
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (ifSameAssign(nodep)) {
|
||||
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
||||
@@ -1794,7 +1798,7 @@ private:
|
||||
ifp->rhsp(new AstCond(truep->fileline(),
|
||||
condp, truep, falsep));
|
||||
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
|
||||
&& operandIfIf(nodep)) {
|
||||
@@ -1806,7 +1810,7 @@ private:
|
||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
||||
condp, lowerCondp));
|
||||
lowerIfp->replaceWith(lowerIfsp);
|
||||
lowerIfp->deleteTree(); lowerIfp=NULL;
|
||||
lowerIfp->deleteTree(); VL_DANGLING(lowerIfp);
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
@@ -1825,7 +1829,7 @@ private:
|
||||
}
|
||||
if (m_doNConst && anyconst) {
|
||||
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||
string dispout = "";
|
||||
string newFormat = "";
|
||||
string fmt = "";
|
||||
bool inPct = false;
|
||||
AstNode* argp = nodep->exprsp();
|
||||
@@ -1843,38 +1847,36 @@ private:
|
||||
switch (tolower(ch)) {
|
||||
case '%': break; // %% - just output a %
|
||||
case 'm': break; // %m - auto insert "name"
|
||||
case 'l': break; // %l - auto insert "library"
|
||||
default: // Most operators, just move to next argument
|
||||
if (argp) {
|
||||
AstNode* nextp=argp->nextp();
|
||||
if (argp && argp->castConst()) { // Convert it
|
||||
string out = argp->castConst()->num().displayed(fmt);
|
||||
string out = argp->castConst()->num().displayed(nodep->fileline(), fmt);
|
||||
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
||||
{ // fmt = out w/ replace % with %% as it must be literal.
|
||||
fmt = "";
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
if (*pos == '%') fmt += '%';
|
||||
fmt += *pos;
|
||||
}
|
||||
}
|
||||
// fmt = out w/ replace % with %% as it must be literal.
|
||||
fmt = VString::quotePercent(out);
|
||||
argp->unlinkFrBack()->deleteTree();
|
||||
}
|
||||
argp=nextp;
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
dispout += fmt;
|
||||
newFormat += fmt;
|
||||
} else {
|
||||
dispout += ch;
|
||||
newFormat += ch;
|
||||
}
|
||||
}
|
||||
nodep->text(dispout);
|
||||
//UINFO(9," Display out "<<nodep->text()<<endl);
|
||||
if (newFormat != nodep->text()) {
|
||||
nodep->text(newFormat);
|
||||
UINFO(9," Display out "<<nodep<<endl);
|
||||
}
|
||||
}
|
||||
if (!nodep->exprsp()
|
||||
&& nodep->name().find("%") == string::npos
|
||||
&& !nodep->hidden()) {
|
||||
// Just a simple constant string - the formatting is pointless
|
||||
replaceConstString(nodep, nodep->name()); nodep=NULL;
|
||||
replaceConstString(nodep, nodep->name()); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1895,7 +1897,7 @@ private:
|
||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
@@ -1915,7 +1917,7 @@ private:
|
||||
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst) {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1945,7 +1947,7 @@ private:
|
||||
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
if (underp) nodep->replaceWith(underp);
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2289,7 +2291,7 @@ public:
|
||||
};
|
||||
|
||||
// CONSTUCTORS
|
||||
ConstVisitor(ProcMode pmode) {
|
||||
explicit ConstVisitor(ProcMode pmode) {
|
||||
m_params = false;
|
||||
m_required = false;
|
||||
m_doExpensive = false;
|
||||
|
||||
+3
-3
@@ -87,7 +87,7 @@ private:
|
||||
if (!nodep->isToggleCoverable())
|
||||
return "Not relevant signal type";
|
||||
if (!v3Global.opt.coverageUnderscore()) {
|
||||
if (prettyName.c_str()[0] == '_')
|
||||
if (prettyName[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
@@ -343,7 +343,7 @@ private:
|
||||
// Skip all NEXT nodes under this block, and skip this if/case branch
|
||||
UINFO(4," OFF: "<<nodep<<endl);
|
||||
m_checkBlock = false;
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
if (m_checkBlock) nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -378,7 +378,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CoverageVisitor(AstNetlist* rootp) {
|
||||
explicit CoverageVisitor(AstNetlist* rootp) {
|
||||
// Operate on all modules
|
||||
m_checkBlock = true;
|
||||
m_beginHier = "";
|
||||
|
||||
@@ -93,7 +93,7 @@ private:
|
||||
UINFO(8," new "<<removep->incp()->declp()<<endl);
|
||||
// Mark the found node as a duplicate of the first 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
|
||||
hashed.erase(dupit);
|
||||
++m_statToggleJoins;
|
||||
@@ -121,7 +121,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
CoverageJoinVisitor(AstNetlist* nodep) {
|
||||
explicit CoverageJoinVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~CoverageJoinVisitor() {
|
||||
|
||||
+4
-4
@@ -58,7 +58,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DeadModVisitor(AstNodeModule* nodep) {
|
||||
explicit DeadModVisitor(AstNodeModule* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~DeadModVisitor() {}
|
||||
@@ -229,7 +229,7 @@ private:
|
||||
// And its children may now be killable too; correct counts
|
||||
// Recurse, as cells may not be directly under the module but in a generate
|
||||
DeadModVisitor visitor(modp);
|
||||
modp->unlinkFrBack()->deleteTree(); modp=NULL;
|
||||
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
@@ -252,9 +252,9 @@ private:
|
||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
AstNodeAssign* assp = it->second;
|
||||
UINFO(4," Dead assign "<<assp<<endl);
|
||||
assp->unlinkFrBack()->deleteTree(); assp=NULL;
|
||||
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
|
||||
}
|
||||
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
|
||||
vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp);
|
||||
}
|
||||
}
|
||||
for (vector<AstNode*>::iterator it = m_varEtcsp.begin(); it!=m_varEtcsp.end(); ++it) {
|
||||
|
||||
+4
-4
@@ -374,9 +374,9 @@ private:
|
||||
if (newlhsp) {
|
||||
nodep->lhsp(newlhsp);
|
||||
} else {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
lhsp->deleteTree(); lhsp=NULL;
|
||||
lhsp->deleteTree(); VL_DANGLING(lhsp);
|
||||
}
|
||||
else {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -420,7 +420,7 @@ private:
|
||||
}
|
||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
||||
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()) {
|
||||
//UINFO(9,"NBA "<<nodep<<endl);
|
||||
@@ -450,7 +450,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
DelayedVisitor(AstNetlist* nodep) {
|
||||
explicit DelayedVisitor(AstNetlist* nodep) {
|
||||
m_inDly = false;
|
||||
m_activep=NULL;
|
||||
m_cfuncp=NULL;
|
||||
|
||||
+1
-1
@@ -157,7 +157,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
DepthVisitor(AstNetlist* nodep) {
|
||||
explicit DepthVisitor(AstNetlist* nodep) {
|
||||
m_modp=NULL;
|
||||
m_funcp=NULL;
|
||||
m_stmtp=NULL;
|
||||
|
||||
@@ -125,7 +125,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
DepthBlockVisitor(AstNetlist* nodep) {
|
||||
explicit DepthBlockVisitor(AstNetlist* nodep) {
|
||||
m_modp=NULL;
|
||||
m_depth=0;
|
||||
//
|
||||
|
||||
+1
-1
@@ -247,7 +247,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
DescopeVisitor(AstNetlist* nodep) {
|
||||
explicit DescopeVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_needThis = false;
|
||||
|
||||
+20
-18
@@ -295,6 +295,7 @@ public:
|
||||
case 'h': // FALLTHRU
|
||||
case 'x': // FALLTHRU
|
||||
case 'b': // FALLTHRU
|
||||
case 'v': // FALLTHRU
|
||||
case 's':
|
||||
got++; format = tolower(ch);
|
||||
break;
|
||||
@@ -656,7 +657,7 @@ public:
|
||||
}
|
||||
} else if (nodep->isQuad()) {
|
||||
vluint64_t num = nodep->toUQuad();
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "u)", num);
|
||||
else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", num);
|
||||
} else {
|
||||
uint32_t num = nodep->toUInt();
|
||||
@@ -1273,17 +1274,18 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any $display-like arguments");
|
||||
}
|
||||
if (argp && argp->isWide()
|
||||
&& (fmtLetter=='d'||fmtLetter=='u')) {
|
||||
&& (fmtLetter=='d'||fmtLetter=='#')) {
|
||||
argp->v3error("Unsupported: "<<dispp->verilogKwd()<<" of dec format of > 64 bit results (use hex format instead)");
|
||||
}
|
||||
if (argp && argp->widthMin()>8 && fmtLetter=='c') {
|
||||
// Technically legal, but surely not what the user intended.
|
||||
argp->v3error(dispp->verilogKwd()<<" of char format of > 8 bit result");
|
||||
argp->v3warn(WIDTH,dispp->verilogKwd()<<"of %c format of > 8 bit value");
|
||||
|
||||
}
|
||||
|
||||
//string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter;
|
||||
string pfmt;
|
||||
if ((fmtLetter=='u' || fmtLetter=='d' || fmtLetter=='t')
|
||||
if ((fmtLetter=='#' || fmtLetter=='d' || fmtLetter=='t')
|
||||
&& !isScan
|
||||
&& vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros
|
||||
double mantissabits = argp->widthMin() - ((fmtLetter=='d')?1:0);
|
||||
@@ -1341,29 +1343,29 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
case 'b': displayArg(nodep,&elistp,isScan, vfmt,'b'); break;
|
||||
case 'c': displayArg(nodep,&elistp,isScan, vfmt,'c'); break;
|
||||
case 't': displayArg(nodep,&elistp,isScan, vfmt,'t'); break;
|
||||
case 'd': displayArg(nodep,&elistp,isScan, vfmt,'u'); break; // Unsigned decimal
|
||||
case 'd': displayArg(nodep,&elistp,isScan, vfmt,'#'); break; // Unsigned decimal
|
||||
case 'o': displayArg(nodep,&elistp,isScan, vfmt,'o'); break;
|
||||
case 'h':
|
||||
case 'h': //FALLTHRU
|
||||
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
|
||||
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
|
||||
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
|
||||
case 'v': displayArg(nodep,&elistp,isScan, vfmt,'v'); break;
|
||||
case 'm': {
|
||||
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
string suffix = scopenamep->scopePrettyName();
|
||||
string suffix = scopenamep->scopePrettySymName();
|
||||
if (suffix=="") emitDispState.pushFormat("%S");
|
||||
else emitDispState.pushFormat("%N"); // Add a . when needed
|
||||
emitDispState.pushArg(' ',NULL, "vlSymsp->name()");
|
||||
emitDispState.pushFormat(suffix);
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
case 'z':
|
||||
case 'l':
|
||||
case 'v':
|
||||
nodep->v3error("Unsupported: $display-like format code: %"<<pos[0]);
|
||||
case 'l': {
|
||||
// Better than not compiling
|
||||
emitDispState.pushFormat("----");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
nodep->v3error("Unknown $display-like format code: %"<<pos[0]);
|
||||
break;
|
||||
@@ -1560,15 +1562,15 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
puts("void "+modClassName(modp)+"::"+funcname+"("+classname+"& os) {\n");
|
||||
// Place a computed checksum to insure proper structure save/restore formatting
|
||||
// OK if this hash includes some things we won't dump, since just looking for loading the wrong model
|
||||
VHashFnv hash;
|
||||
VHashSha1 hash;
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
hash.hash(varp->name());
|
||||
hash.hash(varp->dtypep()->width());
|
||||
hash.insert(varp->name());
|
||||
hash.insert(varp->dtypep()->width());
|
||||
}
|
||||
}
|
||||
ofp()->printf( "vluint64_t __Vcheckval = VL_ULL(0x%" VL_PRI64 "x);\n",
|
||||
hash.value());
|
||||
hash.digestUInt64());
|
||||
if (de) {
|
||||
puts("os.readAssert(__Vcheckval);\n");
|
||||
} else {
|
||||
@@ -1785,7 +1787,7 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
|
||||
}
|
||||
}
|
||||
}
|
||||
ofp()->putAlign(isstatic, 4, 0, prefixIfImp.c_str());
|
||||
ofp()->putAlign(isstatic, 4, 0, prefixIfImp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2434,7 +2436,7 @@ class EmitCTrace : EmitCStmts {
|
||||
}
|
||||
|
||||
public:
|
||||
EmitCTrace(bool slow) {
|
||||
explicit EmitCTrace(bool slow) {
|
||||
m_funcp = NULL;
|
||||
m_slow = slow;
|
||||
}
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
EmitCBaseCounterVisitor(AstNode* nodep) {
|
||||
explicit EmitCBaseCounterVisitor(AstNode* nodep) {
|
||||
m_count = 0;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class EmitCInlines : EmitCBaseVisitor {
|
||||
//---------------------------------------
|
||||
// ACCESSORS
|
||||
public:
|
||||
EmitCInlines(AstNetlist* nodep) {
|
||||
explicit EmitCInlines(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
if (v3Global.needHInlines()) {
|
||||
emitInt();
|
||||
|
||||
+7
-3
@@ -193,14 +193,18 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
string name = nodep->scopeSymName();
|
||||
//UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettyName()<<" ss "<<name<<endl);
|
||||
//UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()<<" ss "<<name<<endl);
|
||||
if (m_scopeNames.find(name) == m_scopeNames.end()) {
|
||||
m_scopeNames.insert(make_pair(name, ScopeNameData(name, nodep->scopePrettyName())));
|
||||
m_scopeNames.insert(make_pair(name, ScopeNameData(name, nodep->scopePrettySymName())));
|
||||
}
|
||||
if (nodep->dpiExport()) {
|
||||
if (!m_funcp) nodep->v3fatalSrc("ScopeName not under DPI function");
|
||||
m_scopeFuncs.insert(make_pair(name + " " + m_funcp->name(),
|
||||
ScopeFuncData(nodep, m_funcp, m_modp)));
|
||||
} else {
|
||||
if (m_scopeNames.find(nodep->scopeDpiName()) == m_scopeNames.end()) {
|
||||
m_scopeNames.insert(make_pair(nodep->scopeDpiName(), ScopeNameData(nodep->scopeDpiName(), nodep->scopePrettyDpiName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
@@ -240,7 +244,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
//---------------------------------------
|
||||
// ACCESSORS
|
||||
public:
|
||||
EmitCSyms(AstNetlist* nodep) {
|
||||
explicit EmitCSyms(AstNetlist* nodep) {
|
||||
m_funcp = NULL;
|
||||
m_modp = NULL;
|
||||
m_coverBins = 0;
|
||||
|
||||
+4
-1
@@ -81,6 +81,9 @@ public:
|
||||
if (v3Global.dpi()) {
|
||||
putMakeClassEntry(of, "verilated_dpi.cpp");
|
||||
}
|
||||
if (v3Global.opt.vpi()) {
|
||||
putMakeClassEntry(of, "verilated_vpi.cpp");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
putMakeClassEntry(of, "verilated_save.cpp");
|
||||
}
|
||||
@@ -231,7 +234,7 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
EmitMkVisitor(AstNetlist*) {
|
||||
explicit EmitMkVisitor(AstNetlist*) {
|
||||
emitClassMake();
|
||||
emitOverallMake();
|
||||
}
|
||||
|
||||
+1
-1
@@ -589,7 +589,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
}
|
||||
|
||||
public:
|
||||
EmitVBaseVisitor(AstSenTree* domainp=NULL) { // Domain for printing one a ALWAYS under a ACTIVE
|
||||
explicit EmitVBaseVisitor(AstSenTree* domainp=NULL) { // Domain for printing one a ALWAYS under a ACTIVE
|
||||
m_suppressSemi = false;
|
||||
m_sensesp = domainp;
|
||||
}
|
||||
|
||||
+7
-1
@@ -96,6 +96,10 @@ public:
|
||||
UNPACKED, // Unsupported unpacked
|
||||
UNSIGNED, // Comparison is constant due to unsigned arithmetic
|
||||
UNUSED, // No receivers
|
||||
USERERROR, // Elaboration time $error
|
||||
USERFATAL, // Elaboration time $fatal
|
||||
USERINFO, // Elaboration time $info
|
||||
USERWARN, // Elaboration time $warning
|
||||
VARHIDDEN, // Hiding variable
|
||||
WIDTH, // Width mismatch
|
||||
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
|
||||
@@ -104,8 +108,9 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
inline V3ErrorCode () : m_e(EC_MIN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline V3ErrorCode (en _e) : m_e(_e) {}
|
||||
V3ErrorCode (const char* msgp); // Matching code or ERROR
|
||||
explicit V3ErrorCode (const char* msgp); // Matching code or ERROR
|
||||
explicit inline V3ErrorCode (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
@@ -131,6 +136,7 @@ public:
|
||||
"REALCVT", "REDEFMACRO",
|
||||
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNPACKED", "UNSIGNED", "UNUSED",
|
||||
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
|
||||
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
||||
" MAX"
|
||||
};
|
||||
|
||||
+17
-17
@@ -86,7 +86,7 @@ private:
|
||||
void replaceWithDelete (AstNode* nodep, AstNode* newp) {
|
||||
newp->user1(1); // Already processed, don't need to re-iterate
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
AstNode* newWordAssign (AstNodeAssign* placep, int word, AstNode* lhsp, AstNode* rhsp) {
|
||||
AstAssign* newp = new AstAssign (placep->fileline(),
|
||||
@@ -332,7 +332,7 @@ private:
|
||||
lhsp->dtypeFrom(nodep); // Just mark it, else nop
|
||||
}
|
||||
}
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
bool expandWide (AstNodeAssign* nodep, AstExtend* rhsp) {
|
||||
@@ -438,7 +438,7 @@ private:
|
||||
if (midp) newp = new AstOr (nodep->fileline(), midp, newp);
|
||||
if (hip) newp = new AstOr (nodep->fileline(), hip, newp);
|
||||
newp->dtypeFrom(nodep);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
else { // Long/Quad from Long/Quad
|
||||
UINFO(8," SEL->SHIFT "<<nodep<<endl);
|
||||
@@ -454,7 +454,7 @@ private:
|
||||
newp = new AstCCast (newp->fileline(), newp, nodep);
|
||||
}
|
||||
newp->dtypeFrom(nodep);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,8 +541,8 @@ private:
|
||||
rhsp, lsb)));
|
||||
}
|
||||
}
|
||||
rhsp->deleteTree(); rhsp=NULL;
|
||||
destp->deleteTree(); destp=NULL;
|
||||
rhsp->deleteTree(); VL_DANGLING(rhsp);
|
||||
destp->deleteTree(); VL_DANGLING(destp);
|
||||
} else {
|
||||
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
|
||||
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
|
||||
@@ -667,7 +667,7 @@ private:
|
||||
nodep->width()),
|
||||
rhsp);
|
||||
newp->dtypeFrom(nodep); // Unsigned
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
bool expandWide (AstNodeAssign* nodep, AstConcat* rhsp) {
|
||||
@@ -720,7 +720,7 @@ private:
|
||||
lhsp->deleteTree(); // Never used
|
||||
}
|
||||
newp->dtypeFrom(nodep); // Unsigned
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
bool expandWide (AstNodeAssign* nodep, AstReplicate* rhsp) {
|
||||
@@ -761,7 +761,7 @@ private:
|
||||
newAstWordSelClone (nodep->rhsp(), w));
|
||||
newp = (newp==NULL) ? eqp : (new AstOr (nodep->fileline(), newp, eqp));
|
||||
}
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void visitEqNeq(AstNodeBiop* nodep) {
|
||||
@@ -784,7 +784,7 @@ private:
|
||||
newp = new AstEq (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), 0), newp);
|
||||
}
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEq* nodep, AstNUser*) { visitEqNeq (nodep); }
|
||||
@@ -803,7 +803,7 @@ private:
|
||||
}
|
||||
newp = new AstNeq (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), 0), newp);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
} else {
|
||||
UINFO(8," REDOR->EQ "<<nodep<<endl);
|
||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
@@ -811,7 +811,7 @@ private:
|
||||
AstNode* newp = new AstNeq (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), zero),
|
||||
lhsp);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedAnd* nodep, AstNUser*) {
|
||||
@@ -833,14 +833,14 @@ private:
|
||||
}
|
||||
newp = new AstEq (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), ~0), newp);
|
||||
replaceWithDelete(nodep, newp); nodep=NULL;
|
||||
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
|
||||
} else {
|
||||
UINFO(8," REDAND->EQ "<<nodep<<endl);
|
||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNode* newp = new AstEq (nodep->fileline(),
|
||||
new AstConst (nodep->fileline(), wordMask(lhsp)),
|
||||
lhsp);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
replaceWithDelete(nodep,newp); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep, AstNUser*) {
|
||||
@@ -856,7 +856,7 @@ private:
|
||||
}
|
||||
newp = new AstRedXor (nodep->fileline(), newp);
|
||||
UINFO(8," Wordize REDXORnew "<<newp<<endl);
|
||||
replaceWithDelete(nodep, newp); nodep=NULL;
|
||||
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
|
||||
}
|
||||
// We don't reduce non-wide XORs, as its more efficient to use a temp register,
|
||||
// which the inlined function does nicely.
|
||||
@@ -907,7 +907,7 @@ private:
|
||||
}
|
||||
// Cleanup common code
|
||||
if (did) {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
m_stmtp = NULL;
|
||||
}
|
||||
@@ -921,7 +921,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ExpandVisitor(AstNetlist* nodep) {
|
||||
explicit ExpandVisitor(AstNetlist* nodep) {
|
||||
m_stmtp=NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
|
||||
+17
-13
@@ -185,7 +185,7 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm
|
||||
}
|
||||
|
||||
inline bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) {
|
||||
const auto_ptr<ifstream> ifp (V3File::new_ifstream_nodepend(filename));
|
||||
const VL_UNIQUE_PTR<ifstream> ifp (V3File::new_ifstream_nodepend(filename));
|
||||
if (ifp->fail()) {
|
||||
UINFO(2," --check-times failed: no input "<<filename<<endl);
|
||||
return false;
|
||||
@@ -345,6 +345,7 @@ private:
|
||||
while (!m_readEof && (size<0 || size>sizegot)) {
|
||||
ssize_t todo = INFILTER_IPC_BUFSIZ;
|
||||
if (size>0 && size<todo) todo = size;
|
||||
errno = 0;
|
||||
ssize_t got = read (fd, buf, todo);
|
||||
//UINFO(9,"RD GOT g "<< got<<" e "<<errno<<" "<<strerror(errno)<<endl); usleep(50*1000);
|
||||
if (got>0) {
|
||||
@@ -362,6 +363,7 @@ private:
|
||||
}
|
||||
return out;
|
||||
}
|
||||
// cppcheck-suppress unusedFunction unusedPrivateFunction
|
||||
string readFilterLine() {
|
||||
// Slow, but we don't need it much
|
||||
UINFO(9,"readFilterLine\n");
|
||||
@@ -379,11 +381,13 @@ private:
|
||||
UINFO(6,"filter-line-in: "<<line);
|
||||
return line;
|
||||
}
|
||||
// cppcheck-suppress unusedFunction unusedPrivateFunction
|
||||
void writeFilter(const string& out) {
|
||||
if (debug()>=6) { UINFO(6,"filter-out: "<<out); if (out[out.length()-1]!='\n') cout<<endl; }
|
||||
if (!m_pid) { v3error("--pipe-filter: write to closed file\n"); m_readEof = true; stop(); }
|
||||
unsigned offset = 0;
|
||||
while (!m_readEof && out.length()>offset) {
|
||||
errno = 0;
|
||||
int got = write (m_writeFd, (out.c_str())+offset, out.length()-offset);
|
||||
//UINFO(9,"WR GOT g "<< got<<" e "<<errno<<" "<<strerror(errno)<<endl); usleep(50*1000);
|
||||
if (got>0) offset += got;
|
||||
@@ -519,7 +523,7 @@ protected:
|
||||
return out;
|
||||
}
|
||||
// CONSTRUCTORS
|
||||
V3InFilterImp(const string& command) {
|
||||
explicit V3InFilterImp(const string& command) {
|
||||
m_readEof = false;
|
||||
m_pid = 0;
|
||||
m_pidExited = false;
|
||||
@@ -547,7 +551,7 @@ bool V3InFilter::readWholefile(const string& filename, V3InFilter::StrList& outl
|
||||
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
|
||||
|
||||
V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang)
|
||||
: m_filename(filename), m_lang(lang)
|
||||
: m_filename(filename), m_lang(lang), m_blockIndent(4)
|
||||
, m_lineno(1), m_column(0)
|
||||
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
||||
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
||||
@@ -615,7 +619,7 @@ int V3OutFormatter::endLevels (const char *strg) {
|
||||
// label/public/private: Deindent by 2 spaces
|
||||
const char* mp=cp;
|
||||
for (; isalnum(*mp); mp++) ;
|
||||
if (mp[0]==':' && mp[1]!=':') return (levels-INDBLK/2);
|
||||
if (mp[0]==':' && mp[1]!=':') return (levels-m_blockIndent/2);
|
||||
}
|
||||
|
||||
// We want "} else {" to be one level to the left of normal
|
||||
@@ -623,16 +627,16 @@ int V3OutFormatter::endLevels (const char *strg) {
|
||||
switch (*cp) {
|
||||
case '}':
|
||||
case ')':
|
||||
levels-=INDBLK;
|
||||
levels-=m_blockIndent;
|
||||
break;
|
||||
case '<':
|
||||
if (m_lang==LA_XML) {
|
||||
if (cp[1] == '/') levels-=INDBLK;
|
||||
if (cp[1] == '/') levels-=m_blockIndent;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
if (m_lang==LA_VERILOG && tokenEnd(cp)) {
|
||||
levels-=INDBLK;
|
||||
levels-=m_blockIndent;
|
||||
}
|
||||
break;
|
||||
case '\t':
|
||||
@@ -746,19 +750,19 @@ void V3OutFormatter::putBreak () {
|
||||
}
|
||||
}
|
||||
|
||||
void V3OutFormatter::putsQuoted(const char* strg) {
|
||||
void V3OutFormatter::putsQuoted(const string& strg) {
|
||||
// Quote \ and " for use inside C programs
|
||||
// Don't use to quote a filename for #include - #include doesn't \ escape.
|
||||
putcNoTracking('"');
|
||||
string quoted = V3Number::quoteNameControls(strg);
|
||||
for (const char* cp=quoted.c_str(); *cp; cp++) {
|
||||
putcNoTracking (*cp);
|
||||
for (string::const_iterator cp=quoted.begin(); cp!=quoted.end(); ++cp) {
|
||||
putcNoTracking (*cp);
|
||||
}
|
||||
putcNoTracking('"');
|
||||
}
|
||||
void V3OutFormatter::putsNoTracking (const char *strg) {
|
||||
void V3OutFormatter::putsNoTracking (const string& strg) {
|
||||
// Don't track {}'s, probably because it's a $display format string
|
||||
for (const char* cp=strg; *cp; cp++) {
|
||||
for (string::const_iterator cp=strg.begin(); cp!=strg.end(); ++cp) {
|
||||
putcNoTracking (*cp);
|
||||
}
|
||||
}
|
||||
@@ -787,7 +791,7 @@ void V3OutFormatter::putcNoTracking (char chr) {
|
||||
putcOutput (chr);
|
||||
}
|
||||
|
||||
void V3OutFormatter::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const char* prefix) {
|
||||
void V3OutFormatter::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const string& prefix) {
|
||||
if (size==0) size=align;
|
||||
int alignSize = size; if (alignSize>8) alignSize=8;
|
||||
int& alignr = isStatic ? m_declSAlign : m_declNSAlign;
|
||||
|
||||
+20
-17
@@ -77,6 +77,7 @@ class V3InFilterImp;
|
||||
|
||||
class V3InFilter {
|
||||
V3InFilterImp* m_impp;
|
||||
V3InFilter(const V3InFilter&); ///< N/A, no copy constructor
|
||||
public:
|
||||
// TYPES
|
||||
typedef list<string> StrList;
|
||||
@@ -86,7 +87,7 @@ public:
|
||||
bool readWholefile(const string& filename, StrList& outl);
|
||||
|
||||
// CONSTRUCTORS
|
||||
V3InFilter(const string& command);
|
||||
explicit V3InFilter(const string& command);
|
||||
~V3InFilter();
|
||||
};
|
||||
|
||||
@@ -96,7 +97,6 @@ public:
|
||||
class V3OutFormatter {
|
||||
// TYPES
|
||||
enum MiscConsts {
|
||||
INDBLK = 4, // Indentation per block level
|
||||
WIDTH = 50, // Width after which to break at ,'s
|
||||
MAXSPACE = 80}; // After this indent, stop indenting more
|
||||
public:
|
||||
@@ -114,6 +114,7 @@ private:
|
||||
// MEMBERS
|
||||
string m_filename;
|
||||
Language m_lang; // Indenting Verilog code
|
||||
int m_blockIndent; // Characters per block indent
|
||||
int m_lineno;
|
||||
int m_column;
|
||||
int m_nobreak; // Basic operator or begin paren, don't break next
|
||||
@@ -132,29 +133,29 @@ public:
|
||||
V3OutFormatter(const string& filename, Language lang);
|
||||
virtual ~V3OutFormatter() {}
|
||||
// ACCESSORS
|
||||
int column() const { return m_column; }
|
||||
int column() const { return m_column; }
|
||||
int blockIndent() const { return m_blockIndent; }
|
||||
void blockIndent(int flag) { m_blockIndent=flag; }
|
||||
// METHODS
|
||||
void printf(const char* fmt...) VL_ATTR_PRINTF(2);
|
||||
void puts(const char* strg);
|
||||
void puts(const string& strg) { puts(strg.c_str()); }
|
||||
void putsNoTracking(const char* strg);
|
||||
void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); }
|
||||
void putsQuoted(const char* strg);
|
||||
void putsQuoted(const string& strg) { putsQuoted(strg.c_str()); }
|
||||
void putsNoTracking(const string& strg);
|
||||
void putsQuoted(const string& strg);
|
||||
void putBreak(); // Print linebreak if line is too wide
|
||||
void putBreakExpr(); // Print linebreak in expression if line is too wide
|
||||
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment
|
||||
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const string& prefix=""); // Declare a variable, with natural alignment
|
||||
void putbs(const char* strg) { putBreakExpr(); puts(strg); }
|
||||
void putbs(const string& strg) { putBreakExpr(); puts(strg); }
|
||||
bool exceededWidth() const { return m_column > WIDTH; }
|
||||
bool tokenStart(const char* cp, const char* cmp);
|
||||
bool tokenEnd(const char* cp);
|
||||
void indentInc() { m_indentLevel += INDBLK; }
|
||||
void indentInc() { m_indentLevel += m_blockIndent; }
|
||||
void indentDec() {
|
||||
m_indentLevel -= INDBLK;
|
||||
m_indentLevel -= m_blockIndent;
|
||||
UASSERT(m_indentLevel>=0, ": "<<m_filename<<": Underflow of indentation\n");
|
||||
}
|
||||
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
|
||||
void blockInc() { m_parenVec.push(m_indentLevel + m_blockIndent); }
|
||||
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
|
||||
// STATIC METHODS
|
||||
static const string indentSpaces(int levels);
|
||||
@@ -183,7 +184,7 @@ private:
|
||||
class V3OutCFile : public V3OutFile {
|
||||
int m_private;
|
||||
public:
|
||||
V3OutCFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_C) {
|
||||
explicit V3OutCFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_C) {
|
||||
resetPrivate();
|
||||
}
|
||||
virtual ~V3OutCFile() {}
|
||||
@@ -208,7 +209,7 @@ public:
|
||||
|
||||
class V3OutScFile : public V3OutCFile {
|
||||
public:
|
||||
V3OutScFile(const string& filename) : V3OutCFile(filename) {}
|
||||
explicit V3OutScFile(const string& filename) : V3OutCFile(filename) {}
|
||||
virtual ~V3OutScFile() {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() {
|
||||
@@ -219,7 +220,7 @@ public:
|
||||
|
||||
class V3OutSpFile : public V3OutCFile {
|
||||
public:
|
||||
V3OutSpFile(const string& filename) : V3OutCFile(filename) {}
|
||||
explicit V3OutSpFile(const string& filename) : V3OutCFile(filename) {}
|
||||
virtual ~V3OutSpFile() {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() {
|
||||
@@ -230,21 +231,23 @@ public:
|
||||
|
||||
class V3OutVFile : public V3OutFile {
|
||||
public:
|
||||
V3OutVFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_VERILOG) {}
|
||||
explicit V3OutVFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_VERILOG) {}
|
||||
virtual ~V3OutVFile() {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); }
|
||||
};
|
||||
|
||||
class V3OutXmlFile : public V3OutFile {
|
||||
public:
|
||||
V3OutXmlFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_XML) {}
|
||||
explicit V3OutXmlFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_XML) {
|
||||
blockIndent(2);
|
||||
}
|
||||
virtual ~V3OutXmlFile() {}
|
||||
virtual void putsHeader() { puts("<?xml version=\"1.0\" ?>\n"); }
|
||||
};
|
||||
|
||||
class V3OutMkFile : public V3OutFile {
|
||||
public:
|
||||
V3OutMkFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_MK) {}
|
||||
explicit V3OutMkFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_MK) {}
|
||||
virtual ~V3OutMkFile() {}
|
||||
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
|
||||
// No automatic indentation yet.
|
||||
|
||||
+2
-2
@@ -102,9 +102,9 @@ public:
|
||||
FileLine (const string& filename, int lineno) {
|
||||
m_lineno=lineno; m_filenameno = singleton().nameToNumber(filename);
|
||||
m_warnOn=defaultFileLine().m_warnOn; }
|
||||
FileLine (FileLine* fromp) {
|
||||
explicit FileLine (FileLine* fromp) {
|
||||
m_lineno=fromp->m_lineno; m_filenameno = fromp->m_filenameno; m_warnOn=fromp->m_warnOn; }
|
||||
FileLine (EmptySecret);
|
||||
explicit FileLine (EmptySecret);
|
||||
~FileLine() { }
|
||||
FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); }
|
||||
FileLine* create(int lineno) { return create(filename(), lineno); }
|
||||
|
||||
+20
-20
@@ -362,6 +362,7 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
//if (debug()>6) m_graph.dump();
|
||||
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
|
||||
warnSignals(); // Before loss of sync/async pointers
|
||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||
m_graph.dumpDotFilePrefixed("gate_simp");
|
||||
// Find gate interconnect and optimize
|
||||
@@ -373,8 +374,7 @@ private:
|
||||
// Remove redundant logic
|
||||
if (v3Global.opt.oDedupe()) dedupe();
|
||||
if (v3Global.opt.oAssemble()) mergeAssigns();
|
||||
// Warn
|
||||
warnSignals();
|
||||
// Consumption warnings
|
||||
consumedMark();
|
||||
m_graph.dumpDotFilePrefixed("gate_opt");
|
||||
// Rewrite assignments
|
||||
@@ -496,7 +496,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
GateVisitor(AstNode* nodep) {
|
||||
explicit GateVisitor(AstNode* nodep) {
|
||||
AstNode::user1ClearTree();
|
||||
m_logicVertexp = NULL;
|
||||
m_scopep = NULL;
|
||||
@@ -617,7 +617,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
||||
varvertexp->propagateAttrClocksFrom(vvertexp);
|
||||
}
|
||||
// Remove the edge
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
++m_statRefs;
|
||||
edgep = vvertexp->outBeginp();
|
||||
}
|
||||
@@ -625,7 +625,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
||||
if (removedAllUsages) {
|
||||
// Remove input links
|
||||
while (V3GraphEdge* edgep = vvertexp->inBeginp()) {
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
}
|
||||
// Clone tree so we remember it for tracing, and keep the pointer
|
||||
// to the "ALWAYS" part of the tree as part of this statement
|
||||
@@ -678,25 +678,25 @@ void GateVisitor::replaceAssigns() {
|
||||
if (vscp->valuep() && !vscp->valuep()->castNodeMath()) {
|
||||
//if (debug()>9) vscp->dumpTree(cout, "-vscPre: ");
|
||||
while (AstNode* delp=vscp->valuep()->castComment()) {
|
||||
delp->unlinkFrBack()->deleteTree(); delp=NULL;
|
||||
delp->unlinkFrBack()->deleteTree(); VL_DANGLING(delp);
|
||||
}
|
||||
if (AstInitial* delp=vscp->valuep()->castInitial()) {
|
||||
AstNode* bodyp=delp->bodysp();
|
||||
bodyp->unlinkFrBackWithNext();
|
||||
delp->replaceWith(bodyp);
|
||||
delp->deleteTree(); delp=NULL;
|
||||
delp->deleteTree(); VL_DANGLING(delp);
|
||||
}
|
||||
if (AstAlways* delp=vscp->valuep()->castAlways()) {
|
||||
AstNode* bodyp=delp->bodysp();
|
||||
bodyp->unlinkFrBackWithNext();
|
||||
delp->replaceWith(bodyp);
|
||||
delp->deleteTree(); delp=NULL;
|
||||
delp->deleteTree(); VL_DANGLING(delp);
|
||||
}
|
||||
if (AstNodeAssign* delp=vscp->valuep()->castNodeAssign()) {
|
||||
AstNode* rhsp=delp->rhsp();
|
||||
rhsp->unlinkFrBack();
|
||||
delp->replaceWith(rhsp);
|
||||
delp->deleteTree(); delp=NULL;
|
||||
delp->deleteTree(); VL_DANGLING(delp);
|
||||
}
|
||||
//if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<<endl;}
|
||||
if (!vscp->valuep()->castNodeMath()
|
||||
@@ -749,7 +749,7 @@ void GateVisitor::consumedMove() {
|
||||
// Eventually: Move the statement to a new active block with "tracing-on" sensitivity
|
||||
UINFO(8," Remove unconsumed "<<nodep<<endl);
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -817,7 +817,7 @@ private:
|
||||
// Make the substp an rvalue like nodep. This facilitate the hashing in dedupe.
|
||||
if (AstNodeVarRef* varrefp = substp->castNodeVarRef()) varrefp->lvalue(false);
|
||||
nodep->replaceWith(substp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
@@ -1039,7 +1039,7 @@ private:
|
||||
|
||||
// Remove inputs links
|
||||
while (V3GraphEdge* inedgep = vvertexp->inBeginp()) {
|
||||
inedgep->unlinkDelete(); inedgep=NULL;
|
||||
inedgep->unlinkDelete(); VL_DANGLING(inedgep);
|
||||
}
|
||||
// replaceAssigns() does the deleteTree on lvertexNodep in a later step
|
||||
AstNode* lvertexNodep = lvertexp->nodep();
|
||||
@@ -1161,14 +1161,14 @@ private:
|
||||
if (AstSel* newselp = merge(preselp, curselp)) {
|
||||
UINFO(5, "assemble to new sel: "<<newselp<<endl);
|
||||
// replace preSel with newSel
|
||||
preselp->replaceWith(newselp); preselp->deleteTree(); preselp = NULL;
|
||||
preselp->replaceWith(newselp); preselp->deleteTree(); VL_DANGLING(preselp);
|
||||
// create new rhs for pre assignment
|
||||
AstNode* newrhsp = new AstConcat(m_assignp->rhsp()->fileline(), m_assignp->rhsp()->cloneTree(false), assignp->rhsp()->cloneTree(false));
|
||||
AstNode* oldrhsp = m_assignp->rhsp();
|
||||
oldrhsp->replaceWith(newrhsp); oldrhsp->deleteTree(); oldrhsp = NULL;
|
||||
oldrhsp->replaceWith(newrhsp); oldrhsp->deleteTree(); VL_DANGLING(oldrhsp);
|
||||
m_assignp->dtypeChgWidthSigned(m_assignp->width()+assignp->width(), m_assignp->width()+assignp->width(), AstNumeric::fromBool(true));
|
||||
// don't need to delete, will be handled
|
||||
//assignp->unlinkFrBack(); assignp->deleteTree(); assignp = NULL;
|
||||
//assignp->unlinkFrBack(); assignp->deleteTree(); VL_DANGLING(assignp);
|
||||
|
||||
// update the graph
|
||||
{
|
||||
@@ -1179,11 +1179,11 @@ private:
|
||||
ledgep = ledgep->inNextp();
|
||||
GateEitherVertex* fromvp = dynamic_cast<GateEitherVertex*>(oedgep->fromp());
|
||||
new V3GraphEdge(m_graphp, fromvp, m_logicvp, 1);
|
||||
oedgep->unlinkDelete(); oedgep = NULL;
|
||||
oedgep->unlinkDelete(); VL_DANGLING(oedgep);
|
||||
}
|
||||
}
|
||||
// delete all outedges to lvertexp, only one
|
||||
oldedgep->unlinkDelete(); oldedgep = NULL;
|
||||
oldedgep->unlinkDelete(); VL_DANGLING(oldedgep);
|
||||
}
|
||||
++m_numMergedAssigns;
|
||||
} else {
|
||||
@@ -1202,7 +1202,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
GateMergeAssignsGraphVisitor(V3Graph* graphp) {
|
||||
explicit GateMergeAssignsGraphVisitor(V3Graph* graphp) {
|
||||
m_assignp = NULL;
|
||||
m_activep = NULL;
|
||||
m_logicvp = NULL;
|
||||
@@ -1241,7 +1241,7 @@ private:
|
||||
AstNode* valuep = assp->rhsp();
|
||||
valuep->unlinkFrBack();
|
||||
assp->replaceWith(valuep);
|
||||
assp->deleteTree(); assp=NULL;
|
||||
assp->deleteTree(); VL_DANGLING(assp);
|
||||
}
|
||||
}
|
||||
// Speedups
|
||||
@@ -1253,7 +1253,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
GateDeassignVisitor(AstNode* nodep) {
|
||||
explicit GateDeassignVisitor(AstNode* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~GateDeassignVisitor() {}
|
||||
|
||||
+2
-2
@@ -109,7 +109,7 @@ private:
|
||||
AstVarScope* newvscp = genInpClk(vscp);
|
||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue());
|
||||
nodep->replaceWith(newrefp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
GenClkReadVisitor(AstNetlist* nodep) {
|
||||
explicit GenClkReadVisitor(AstNetlist* nodep) {
|
||||
m_activep = NULL;
|
||||
m_assignp = NULL;
|
||||
m_topModp = NULL;
|
||||
|
||||
+25
-5
@@ -36,15 +36,35 @@ class AstNetlist;
|
||||
|
||||
|
||||
//######################################################################
|
||||
// V3 - The top level class for the entire program
|
||||
|
||||
class VWidthMinUsage {
|
||||
public:
|
||||
enum en {
|
||||
LINT_WIDTH,
|
||||
MATCHES_WIDTH,
|
||||
VERILOG_WIDTH
|
||||
};
|
||||
enum en m_e;
|
||||
inline VWidthMinUsage () : m_e(LINT_WIDTH) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VWidthMinUsage (en _e) : m_e(_e) {}
|
||||
explicit inline VWidthMinUsage (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
};
|
||||
inline bool operator== (VWidthMinUsage lhs, VWidthMinUsage rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (VWidthMinUsage lhs, VWidthMinUsage::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (VWidthMinUsage::en lhs, VWidthMinUsage rhs) { return (lhs == rhs.m_e); }
|
||||
|
||||
//######################################################################
|
||||
// V3Global - The top level class for the entire program
|
||||
|
||||
class V3Global {
|
||||
// Globals
|
||||
AstNetlist* m_rootp; // Root of entire netlist
|
||||
VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for
|
||||
|
||||
int m_debugFileNumber; // Number to append to debug files created
|
||||
bool m_assertDTypesResolved; // Tree should have dtypep()'s
|
||||
bool m_assertWidthsMatch; // Tree should have width()==widthMin()
|
||||
bool m_constRemoveXs; // Const needs to strip any Xs
|
||||
bool m_needHInlines; // Need __Inlines file
|
||||
bool m_needHeavy; // Need verilated_heavy.h include
|
||||
@@ -58,8 +78,8 @@ public:
|
||||
// CREATORS
|
||||
V3Global() {
|
||||
m_debugFileNumber = 0;
|
||||
m_widthMinUsage = VWidthMinUsage::LINT_WIDTH;
|
||||
m_assertDTypesResolved = false;
|
||||
m_assertWidthsMatch = false;
|
||||
m_constRemoveXs = false;
|
||||
m_needHInlines = false;
|
||||
m_needHeavy = false;
|
||||
@@ -71,15 +91,15 @@ public:
|
||||
void clear();
|
||||
// ACCESSORS (general)
|
||||
AstNetlist* rootp() const { return m_rootp; }
|
||||
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
||||
bool assertDTypesResolved() const { return m_assertDTypesResolved; }
|
||||
bool assertWidthsMatch() const { return m_assertWidthsMatch; }
|
||||
|
||||
// METHODS
|
||||
void readFiles();
|
||||
void checkTree();
|
||||
static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
|
||||
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
||||
|
||||
+1
-1
@@ -288,7 +288,7 @@ void V3Graph::dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsS
|
||||
void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
||||
// This generates a file used by graphviz, http://www.graphviz.org
|
||||
// "hardcoded" parameters:
|
||||
const auto_ptr<ofstream> logp (V3File::new_ofstream(filename));
|
||||
const VL_UNIQUE_PTR<ofstream> logp (V3File::new_ofstream(filename));
|
||||
if (logp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
|
||||
// Header
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ protected:
|
||||
// CONSTRUCTORS
|
||||
V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old);
|
||||
public:
|
||||
V3GraphVertex(V3Graph* graphp);
|
||||
explicit V3GraphVertex(V3Graph* graphp);
|
||||
//! Clone copy constructor. Doesn't copy edges or user/userp.
|
||||
virtual V3GraphVertex* clone(V3Graph* graphp) const {
|
||||
return new V3GraphVertex(graphp, *this); }
|
||||
|
||||
+15
-13
@@ -269,7 +269,7 @@ void GraphAcyc::deleteMarked () {
|
||||
nextp = vertexp->verticesNextp();
|
||||
GraphAcycVertex* avertexp = (GraphAcycVertex*)vertexp;
|
||||
if (avertexp->isDelete()) {
|
||||
avertexp->unlinkDelete(&m_breakGraph); avertexp=NULL;
|
||||
avertexp->unlinkDelete(&m_breakGraph); VL_DANGLING(avertexp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,13 +285,13 @@ void GraphAcyc::simplifyNone (GraphAcycVertex* avertexp) {
|
||||
while (V3GraphEdge* edgep = avertexp->outBeginp()) {
|
||||
V3GraphVertex* otherVertexp = edgep->top();
|
||||
//UINFO(9," out "<<otherVertexp<<endl);
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
workPush(otherVertexp);
|
||||
}
|
||||
while (V3GraphEdge* edgep = avertexp->inBeginp()) {
|
||||
V3GraphVertex* otherVertexp = edgep->fromp();
|
||||
//UINFO(9," in "<<otherVertexp<<endl);
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
workPush(otherVertexp);
|
||||
}
|
||||
}
|
||||
@@ -319,10 +319,11 @@ void GraphAcyc::simplifyOne (GraphAcycVertex* avertexp) {
|
||||
&& (!outEdgep->cutable()
|
||||
|| inEdgep->weight()<outEdgep->weight() ))
|
||||
? inEdgep : outEdgep);
|
||||
// cppcheck-suppress leakReturnValNotUsed
|
||||
edgeFromEdge(templateEdgep, inVertexp, outVertexp);
|
||||
// Remove old edge
|
||||
inEdgep->unlinkDelete(); inEdgep = NULL;
|
||||
outEdgep->unlinkDelete(); outEdgep = NULL; templateEdgep=NULL;
|
||||
inEdgep->unlinkDelete(); VL_DANGLING(inEdgep);
|
||||
outEdgep->unlinkDelete(); VL_DANGLING(outEdgep); VL_DANGLING(templateEdgep);
|
||||
workPush(inVertexp);
|
||||
workPush(outVertexp);
|
||||
}
|
||||
@@ -353,12 +354,13 @@ void GraphAcyc::simplifyOut (GraphAcycVertex* avertexp) {
|
||||
return;
|
||||
}
|
||||
// Make a new edge connecting the two vertices directly
|
||||
// cppcheck-suppress leakReturnValNotUsed
|
||||
edgeFromEdge(inEdgep, inVertexp, outVertexp);
|
||||
// Remove old edge
|
||||
inEdgep->unlinkDelete(); inEdgep = NULL;
|
||||
inEdgep->unlinkDelete(); VL_DANGLING(inEdgep);
|
||||
workPush(inVertexp);
|
||||
}
|
||||
outEdgep->unlinkDelete(); outEdgep = NULL;
|
||||
outEdgep->unlinkDelete(); VL_DANGLING(outEdgep);
|
||||
workPush(outVertexp);
|
||||
}
|
||||
}
|
||||
@@ -381,18 +383,18 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
|
||||
// !cutable duplicates prev !cutable: we can ignore it, redundant
|
||||
// cutable duplicates prev !cutable: know it's not a relevant loop, ignore it
|
||||
UINFO(8," DelDupEdge "<<avertexp<<" -> "<<edgep->top()<<endl);
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
} else if (!edgep->cutable()) {
|
||||
// !cutable duplicates prev cutable: delete the earlier cutable
|
||||
UINFO(8," DelDupPrev "<<avertexp<<" -> "<<prevEdgep->top()<<endl);
|
||||
prevEdgep->unlinkDelete(); prevEdgep = NULL;
|
||||
prevEdgep->unlinkDelete(); VL_DANGLING(prevEdgep);
|
||||
outVertexp->userp(edgep);
|
||||
} else {
|
||||
// cutable duplicates prev cutable: combine weights
|
||||
UINFO(8," DelDupComb "<<avertexp<<" -> "<<edgep->top()<<endl);
|
||||
prevEdgep->weight (prevEdgep->weight() + edgep->weight());
|
||||
addOrigEdgep (prevEdgep, edgep);
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
}
|
||||
workPush(outVertexp);
|
||||
workPush(avertexp);
|
||||
@@ -410,7 +412,7 @@ void GraphAcyc::cutBasic (GraphAcycVertex* avertexp) {
|
||||
nextp = edgep->outNextp();
|
||||
if (edgep->cutable() && edgep->top()==avertexp) {
|
||||
cutOrigEdge (edgep, " Cut Basic");
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
workPush(avertexp);
|
||||
}
|
||||
}
|
||||
@@ -431,7 +433,7 @@ void GraphAcyc::cutBackward (GraphAcycVertex* avertexp) {
|
||||
nextp = edgep->outNextp();
|
||||
if (edgep->cutable() && edgep->top()->user()) {
|
||||
cutOrigEdge (edgep, " Cut A->B->A");
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
workPush(avertexp);
|
||||
}
|
||||
}
|
||||
@@ -495,7 +497,7 @@ void GraphAcyc::placeTryEdge(V3GraphEdge* edgep) {
|
||||
// Adding this edge would cause a loop, kill it
|
||||
edgep->cutable(true); // So graph still looks pretty
|
||||
cutOrigEdge (edgep, " Cut loop");
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
// Backout the ranks we calculated
|
||||
while (GraphAcycVertex* vertexp = workBeginp()) {
|
||||
workPop();
|
||||
|
||||
+2
-2
@@ -109,10 +109,10 @@ private:
|
||||
}
|
||||
if (saveOld) {
|
||||
if (m_sumWeights) prevEdgep->weight(prevEdgep->weight() + edgep->weight());
|
||||
edgep->unlinkDelete(); edgep = NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
} else {
|
||||
if (m_sumWeights) edgep->weight(prevEdgep->weight() + edgep->weight());
|
||||
prevEdgep->unlinkDelete(); prevEdgep = NULL;
|
||||
prevEdgep->unlinkDelete(); VL_DANGLING(prevEdgep);
|
||||
outVertexp->userp(edgep);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -331,7 +331,7 @@ private:
|
||||
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
|
||||
nextp = vertexp->verticesNextp();
|
||||
if (nfaState(vertexp)) {
|
||||
vertexp->unlinkDelete(m_graphp); vertexp=NULL;
|
||||
vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ private:
|
||||
if (vvertexp->accepting()) {
|
||||
for (V3GraphEdge* nextp,*edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||
nextp = edgep->outNextp();
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,7 +417,7 @@ private:
|
||||
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
|
||||
nextp = vertexp->verticesNextp();
|
||||
if (!vertexp->user()) {
|
||||
vertexp->unlinkDelete(m_graphp); vertexp=NULL;
|
||||
vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,7 +458,7 @@ private:
|
||||
}
|
||||
}
|
||||
// Transitions to this state removed by the unlink function
|
||||
vertexp->unlinkDelete(m_graphp); vertexp=NULL;
|
||||
vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -535,7 +535,7 @@ private:
|
||||
DfaVertex* tovertexp = static_cast<DfaVertex*>(edgep->top());
|
||||
if (tovertexp->accepting()) {
|
||||
new DfaEdge(graphp(), vvertexp, m_tempNewerReject, vedgep);
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
}
|
||||
|
||||
// NOT of all values goes to accept
|
||||
|
||||
+3
-2
@@ -89,13 +89,14 @@ private:
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar*, AstNUser*) {}
|
||||
virtual void visit(AstTypedef*, AstNUser*) {}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodeHashIterate(nodep);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
HashedVisitor(AstNode* nodep) {
|
||||
explicit HashedVisitor(AstNode* nodep) {
|
||||
nodeHashIterate(nodep);
|
||||
//UINFO(9," stmthash "<<hex<<V3Hashed::nodeHash(nodep)<<" "<<nodep<<endl);
|
||||
}
|
||||
@@ -139,7 +140,7 @@ void V3Hashed::dumpFilePrefixed(const string& nameComment, bool tree) {
|
||||
}
|
||||
|
||||
void V3Hashed::dumpFile(const string& filename, bool tree) {
|
||||
const auto_ptr<ofstream> logp (V3File::new_ofstream(filename));
|
||||
const VL_UNIQUE_PTR<ofstream> logp (V3File::new_ofstream(filename));
|
||||
if (logp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
|
||||
map<int,int> dist;
|
||||
|
||||
+9
-9
@@ -135,14 +135,14 @@ private:
|
||||
} else {
|
||||
m_modp->user1(1);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell...
|
||||
} else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) {
|
||||
if (!m_modp) {
|
||||
nodep->v3error("Inline pragma not under a module");
|
||||
} else {
|
||||
cantInline("Pragma NO_INLINE_MODULE",false);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell...
|
||||
} else {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
InlineMarkVisitor(AstNode* nodep) {
|
||||
explicit InlineMarkVisitor(AstNode* nodep) {
|
||||
m_modp = NULL;
|
||||
m_stmtCnt = 0;
|
||||
nodep->accept(*this);
|
||||
@@ -227,7 +227,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
InlineCollectVisitor(AstNodeModule* nodep) { // passed OLD module, not new one
|
||||
explicit InlineCollectVisitor(AstNodeModule* nodep) { // passed OLD module, not new one
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~InlineCollectVisitor() {}
|
||||
@@ -347,7 +347,7 @@ private:
|
||||
AstVarRef* exprvarrefp = nodep->varp()->user2p()->castNode()->castVarRef();
|
||||
if (exprconstp) {
|
||||
nodep->replaceWith(exprconstp->cloneTree(true));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
else if (exprvarrefp) {
|
||||
@@ -521,9 +521,9 @@ private:
|
||||
if (stmtsp) stmtsp->unlinkFrBackWithNext();
|
||||
if (stmtsp) m_modp->addStmtp(stmtsp);
|
||||
// Remove the cell
|
||||
newmodp->deleteTree(); newmodp=NULL; // Clear any leftover ports, etc
|
||||
newmodp->deleteTree(); VL_DANGLING(newmodp); // Clear any leftover ports, etc
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep); nodep = NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
if (debug()>=9) { m_modp->dumpTree(cout,"donemod:"); }
|
||||
}
|
||||
}
|
||||
@@ -537,7 +537,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
InlineVisitor(AstNode* nodep) {
|
||||
explicit InlineVisitor(AstNode* nodep) {
|
||||
m_modp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -560,7 +560,7 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
|
||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
||||
nextmodp = modp->nextp()->castNodeModule();
|
||||
if (modp->user1()) { // Was inlined
|
||||
modp->unlinkFrBack()->deleteTree(); modp=NULL;
|
||||
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
|
||||
}
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("inline.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
|
||||
+246
-79
@@ -36,6 +36,7 @@
|
||||
#include "V3Inst.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Changed.h"
|
||||
#include "V3Const.h"
|
||||
|
||||
//######################################################################
|
||||
// Inst state, as a visitor of each AstNode
|
||||
@@ -105,12 +106,15 @@ private:
|
||||
exprp);
|
||||
m_modp->addStmtp(assp);
|
||||
if (debug()>=9) assp->dumpTree(cout," _new: ");
|
||||
} else if (nodep->modVarp()->isIfaceRef()) {
|
||||
} else if (nodep->modVarp()->isIfaceRef()
|
||||
|| (nodep->modVarp()->subDTypep()->castUnpackArrayDType()
|
||||
&& nodep->modVarp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType())) {
|
||||
// Create an AstAssignVarScope for Vars to Cells so we can link with their scope later
|
||||
AstNode* lhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
|
||||
AstVarRef* refp = exprp->castVarRef();
|
||||
if (!refp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef");
|
||||
AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, refp);
|
||||
AstVarXRef* xrefp = exprp->castVarXRef();
|
||||
if (!refp && !xrefp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef or VarXRef");
|
||||
AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, exprp);
|
||||
m_modp->addStmtp(assp);
|
||||
} else {
|
||||
nodep->v3error("Assigned pin is neither input nor output");
|
||||
@@ -118,7 +122,7 @@ private:
|
||||
}
|
||||
|
||||
// We're done with the pin
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstUdpTable* nodep, AstNUser*) {
|
||||
@@ -139,7 +143,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
InstVisitor(AstNode* nodep) {
|
||||
explicit InstVisitor(AstNode* nodep) {
|
||||
m_modp=NULL;
|
||||
m_cellp=NULL;
|
||||
//
|
||||
@@ -169,6 +173,12 @@ private:
|
||||
if (nodep->rangep()) {
|
||||
m_cellRangep = nodep->rangep();
|
||||
UINFO(4," CELL "<<nodep<<endl);
|
||||
|
||||
AstVar* ifaceVarp = nodep->nextp()->castVar();
|
||||
bool isIface = ifaceVarp
|
||||
&& ifaceVarp->dtypep()->castUnpackArrayDType()
|
||||
&& ifaceVarp->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
|
||||
// Make all of the required clones
|
||||
m_instLsb = m_cellRangep->lsbConst();
|
||||
for (m_instNum = m_instLsb; m_instNum<=m_cellRangep->msbConst(); m_instNum++) {
|
||||
@@ -181,6 +191,24 @@ private:
|
||||
// The spec says we add [x], but that won't work in C...
|
||||
newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
||||
newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
||||
|
||||
// If this AstCell is actually an interface instantiation, let's ensure we also clone
|
||||
// the IfaceRef.
|
||||
if (isIface) {
|
||||
AstUnpackArrayDType* arrdtype = ifaceVarp->dtypep()->castUnpackArrayDType();
|
||||
AstIfaceRefDType* origIfaceRefp = arrdtype->subDTypep()->castIfaceRefDType();
|
||||
origIfaceRefp->cellp(NULL);
|
||||
AstVar* varNewp = ifaceVarp->cloneTree(false);
|
||||
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
|
||||
arrdtype->addNextHere(ifaceRefp);
|
||||
ifaceRefp->cellp(newp);
|
||||
ifaceRefp->cellName(newp->name());
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
newp->addNextHere(varNewp);
|
||||
if (debug()==9) { varNewp->dumpTree(cout, "newintf: "); cout << endl; }
|
||||
}
|
||||
// Fixup pins
|
||||
newp->pinsp()->iterateAndNext(*this);
|
||||
if (debug()==9) { newp->dumpTree(cout,"newcell: "); cout<<endl; }
|
||||
@@ -188,9 +216,40 @@ private:
|
||||
|
||||
// Done. Delete original
|
||||
m_cellRangep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
if (isIface) {
|
||||
ifaceVarp->unlinkFrBack(); pushDeletep(ifaceVarp); VL_DANGLING(ifaceVarp);
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
bool isIface = nodep->dtypep()->castUnpackArrayDType()
|
||||
&& nodep->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
if (isIface) {
|
||||
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
|
||||
AstNode* prev = NULL;
|
||||
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
|
||||
AstVar* varNewp = nodep->cloneTree(false);
|
||||
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
|
||||
arrdtype->addNextHere(ifaceRefp);
|
||||
ifaceRefp->cellp(NULL);
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
if (!prev) {
|
||||
prev = varNewp;
|
||||
} else {
|
||||
prev->addNextHere(varNewp);
|
||||
}
|
||||
}
|
||||
nodep->addNextHere(prev);
|
||||
if (debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; }
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstPin* nodep, AstNUser*) {
|
||||
// Any non-direct pins need reconnection with a part-select
|
||||
if (!nodep->exprp()) return; // No-connect
|
||||
@@ -198,7 +257,20 @@ private:
|
||||
UINFO(4," PIN "<<nodep<<endl);
|
||||
int pinwidth = nodep->modVarp()->width();
|
||||
int expwidth = nodep->exprp()->width();
|
||||
if (expwidth == pinwidth) {
|
||||
pair<uint32_t,uint32_t> pinDim = nodep->modVarp()->dtypep()->dimensions(false);
|
||||
pair<uint32_t,uint32_t> expDim = nodep->exprp()->dtypep()->dimensions(false);
|
||||
UINFO(4," PINVAR "<<nodep->modVarp()<<endl);
|
||||
UINFO(4," EXP "<<nodep->exprp()<<endl);
|
||||
UINFO(4," pinwidth ew="<<expwidth<<" pw="<<pinwidth
|
||||
<<" ed="<<expDim.first<<","<<expDim.second
|
||||
<<" pd="<<pinDim.first<<","<<pinDim.second<<endl);
|
||||
if (expDim.first == pinDim.first && expDim.second == pinDim.second+1) {
|
||||
// Connection to array, where array dimensions match the instant dimension
|
||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||
exprp = new AstArraySel (exprp->fileline(), exprp,
|
||||
(m_instNum-m_instLsb));
|
||||
nodep->exprp(exprp);
|
||||
} else if (expwidth == pinwidth) {
|
||||
// NOP: Arrayed instants: widths match so connect to each instance
|
||||
} else if (expwidth == pinwidth*m_cellRangep->elementsConst()) {
|
||||
// Arrayed instants: one bit for each of the instants (each assign is 1 pinwidth wide)
|
||||
@@ -217,6 +289,69 @@ private:
|
||||
} else {
|
||||
nodep->v3fatalSrc("Width mismatch; V3Width should have errored out.");
|
||||
}
|
||||
} else if (AstArraySel* arrselp = nodep->exprp()->castArraySel()) {
|
||||
if (AstUnpackArrayDType* arrp = arrselp->lhsp()->dtypep()->castUnpackArrayDType()) {
|
||||
if (!arrp->subDTypep()->castIfaceRefDType())
|
||||
return;
|
||||
|
||||
V3Const::constifyParamsEdit(arrselp->rhsp());
|
||||
AstConst* constp = arrselp->rhsp()->castConst();
|
||||
if (!constp) {
|
||||
nodep->v3error("Unsupported: Non-constant index when passing interface to module");
|
||||
return;
|
||||
}
|
||||
string index = AstNode::encodeNumber(constp->toSInt());
|
||||
AstVarRef* varrefp = arrselp->lhsp()->castVarRef();
|
||||
AstVarXRef* newp = new AstVarXRef(nodep->fileline(),varrefp->name () + "__BRA__" + index + "__KET__", "", true);
|
||||
newp->dtypep(nodep->modVarp()->dtypep());
|
||||
newp->packagep(varrefp->packagep());
|
||||
arrselp->addNextHere(newp);
|
||||
arrselp->unlinkFrBack()->deleteTree();
|
||||
}
|
||||
} else {
|
||||
AstVar* pinVarp = nodep->modVarp();
|
||||
AstUnpackArrayDType* pinArrp = pinVarp->dtypep()->castUnpackArrayDType();
|
||||
if (!pinArrp || !pinArrp->subDTypep()->castIfaceRefDType())
|
||||
return;
|
||||
AstNode* prevp = NULL;
|
||||
AstNode* prevPinp = NULL;
|
||||
// Clone the var referenced by the pin, and clone each var referenced by the varref
|
||||
// Clone pin varp:
|
||||
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) {
|
||||
AstVar* varNewp = pinVarp->cloneTree(false);
|
||||
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
|
||||
ifaceRefp->cellp(NULL);
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
if (!prevp) {
|
||||
prevp = varNewp;
|
||||
} else {
|
||||
prevp->addNextHere(varNewp);
|
||||
}
|
||||
// Now also clone the pin itself and update its varref
|
||||
AstPin* newp = nodep->cloneTree(false);
|
||||
newp->modVarp(varNewp);
|
||||
newp->name(newp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
|
||||
// And replace exprp with a new varxref
|
||||
AstVarRef* varrefp = newp->exprp()->castVarRef();
|
||||
string newname = varrefp->name () + "__BRA__" + cvtToStr(i) + "__KET__";
|
||||
AstVarXRef* newVarXRefp = new AstVarXRef (nodep->fileline(), newname, "", true);
|
||||
newVarXRefp->varp(newp->modVarp());
|
||||
newVarXRefp->dtypep(newp->modVarp()->dtypep());
|
||||
newp->exprp()->unlinkFrBack()->deleteTree();
|
||||
newp->exprp(newVarXRefp);
|
||||
if (!prevPinp) {
|
||||
prevPinp = newp;
|
||||
} else {
|
||||
prevPinp->addNextHere(newp);
|
||||
}
|
||||
}
|
||||
pinVarp->replaceWith(prevp);
|
||||
nodep->replaceWith(prevPinp);
|
||||
pushDeletep(pinVarp);
|
||||
pushDeletep(nodep);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +364,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
InstDeVisitor(AstNode* nodep) {
|
||||
explicit InstDeVisitor(AstNode* nodep) {
|
||||
m_cellRangep=NULL;
|
||||
m_instNum=0;
|
||||
m_instLsb=0;
|
||||
@@ -239,81 +374,113 @@ public:
|
||||
virtual ~InstDeVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Inst static function
|
||||
|
||||
class InstStatic {
|
||||
private:
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
InstStatic() {} // Static class
|
||||
|
||||
static AstNode* extendOrSel(FileLine* fl, AstNode* rhsp, AstNode* cmpWidthp) {
|
||||
if (cmpWidthp->width() > rhsp->width()) {
|
||||
rhsp = (rhsp->isSigned()
|
||||
? (new AstExtendS(fl, rhsp))->castNode()
|
||||
: (new AstExtend (fl, rhsp))->castNode());
|
||||
rhsp->dtypeFrom(cmpWidthp); // Need proper widthMin, which may differ from AstSel created above
|
||||
} else if (cmpWidthp->width() < rhsp->width()) {
|
||||
rhsp = new AstSel (fl, rhsp, 0, cmpWidthp->width());
|
||||
rhsp->dtypeFrom(cmpWidthp); // Need proper widthMin, which may differ from AstSel created above
|
||||
}
|
||||
// else don't change dtype, as might be e.g. array of something
|
||||
return rhsp;
|
||||
}
|
||||
|
||||
public:
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
// If a pin connection is "simple" leave it as-is
|
||||
// Else create a intermediate wire to perform the interconnect
|
||||
// Return the new assignment, if one was made
|
||||
// Note this module calles cloneTree() via new AstVar
|
||||
|
||||
AstVar* pinVarp = pinp->modVarp();
|
||||
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
|
||||
AstVarXRef* connectXRefp = pinp->exprp()->castVarXRef();
|
||||
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
|
||||
AstBasicDType* connBasicp = NULL;
|
||||
AstAssignW* assignp = NULL;
|
||||
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
|
||||
//
|
||||
if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
|
||||
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
|
||||
// Done. Same data type
|
||||
} else if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->isIfaceRef()) {
|
||||
// Done. Interface
|
||||
} else if (!alwaysCvt
|
||||
&& connectXRefp
|
||||
&& connectXRefp->varp()
|
||||
&& connectXRefp->varp()->isIfaceRef()) {
|
||||
} else if (!alwaysCvt
|
||||
&& connBasicp
|
||||
&& pinBasicp
|
||||
&& connBasicp->width() == pinBasicp->width()
|
||||
&& connBasicp->lsb() == pinBasicp->lsb()
|
||||
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
|
||||
&& connBasicp->width() == pinVarp->width()
|
||||
&& 1) {
|
||||
// Done. One to one interconnect won't need a temporary variable.
|
||||
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
|
||||
// Done. Constant.
|
||||
} else {
|
||||
// Make a new temp wire
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
string newvarname = ((string)(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
|
||||
+(forTristate?"t":"") // Prevent name conflict if both tri & non-tri add signals
|
||||
+"__"+cellp->name()+"__"+pinp->name());
|
||||
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||
// Important to add statement next to cell, in case there is a generate with same named cell
|
||||
cellp->addNextHere(newvarp);
|
||||
if (pinVarp->isInout()) {
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||
} else if (pinVarp->isOutput()) {
|
||||
// See also V3Inst
|
||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||
UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
|
||||
rhsp = extendOrSel (pinp->fileline(), rhsp, pinVarp);
|
||||
pinp->exprp(new AstVarRef (newvarp->fileline(), newvarp, true));
|
||||
AstNode* rhsSelp = extendOrSel (pinp->fileline(), rhsp, pinexprp);
|
||||
assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsSelp);
|
||||
} else {
|
||||
// V3 width should have range/extended to make the widths correct
|
||||
assignp = new AstAssignW (pinp->fileline(),
|
||||
new AstVarRef(pinp->fileline(), newvarp, true),
|
||||
pinexprp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
||||
}
|
||||
if (assignp) cellp->addNextHere(assignp);
|
||||
//if (debug()) { pinp->dumpTree(cout,"- out:"); }
|
||||
//if (debug()) { assignp->dumpTree(cout,"- aout:"); }
|
||||
}
|
||||
return assignp;
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Inst class functions
|
||||
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
// If a pin connection is "simple" leave it as-is
|
||||
// Else create a intermediate wire to perform the interconnect
|
||||
// Return the new assignment, if one was made
|
||||
// Note this module calles cloneTree() via new AstVar
|
||||
AstVar* pinVarp = pinp->modVarp();
|
||||
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
|
||||
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
|
||||
AstBasicDType* connBasicp = NULL;
|
||||
AstAssignW* assignp = NULL;
|
||||
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
|
||||
//
|
||||
if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
|
||||
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
|
||||
// Done. Same data type
|
||||
} else if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->isIfaceRef()) {
|
||||
// Done. Interface
|
||||
} else if (!alwaysCvt
|
||||
&& connBasicp
|
||||
&& pinBasicp
|
||||
&& connBasicp->width() == pinBasicp->width()
|
||||
&& connBasicp->lsb() == pinBasicp->lsb()
|
||||
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
|
||||
&& connBasicp->width() == pinVarp->width()
|
||||
&& 1) {
|
||||
// Done. One to one interconnect won't need a temporary variable.
|
||||
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
|
||||
// Done. Constant.
|
||||
} else {
|
||||
// Make a new temp wire
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
string newvarname = ((string)(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
|
||||
+(forTristate?"t":"") // Prevent name conflict if both tri & non-tri add signals
|
||||
+"__"+cellp->name()+"__"+pinp->name());
|
||||
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||
// Important to add statement next to cell, in case there is a generate with same named cell
|
||||
cellp->addNextHere(newvarp);
|
||||
if (pinVarp->isInout()) {
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||
} else if (pinVarp->isOutput()) {
|
||||
// See also V3Inst
|
||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||
if (pinVarp->width() > rhsp->width()) {
|
||||
if (rhsp->isSigned()) {
|
||||
rhsp = new AstExtendS(pinp->fileline(), rhsp);
|
||||
} else {
|
||||
rhsp = new AstExtend (pinp->fileline(), rhsp);
|
||||
}
|
||||
} else if (pinVarp->width() < rhsp->width()) {
|
||||
rhsp = new AstSel (pinp->fileline(), rhsp, 0, pinVarp->width());
|
||||
}
|
||||
rhsp->dtypeFrom(pinVarp); // Need proper widthMin, which may differ from AstSel created above
|
||||
assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
|
||||
} else {
|
||||
// V3 width should have range/extended to make the widths correct
|
||||
assignp = new AstAssignW (pinp->fileline(),
|
||||
new AstVarRef(pinp->fileline(), newvarp, true),
|
||||
pinexprp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
||||
}
|
||||
if (assignp) cellp->addNextHere(assignp);
|
||||
//if (debug()) { pinp->dumpTree(cout,"- out:"); }
|
||||
//if (debug()) { assignp->dumpTree(cout,"- aout:"); }
|
||||
}
|
||||
return assignp;
|
||||
return InstStatic::pinReconnectSimple(pinp, cellp, modp, forTristate, alwaysCvt);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
+2
-1
@@ -64,8 +64,9 @@ public:
|
||||
//
|
||||
enum en m_e;
|
||||
inline V3LangCode () : m_e(L_ERROR) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline V3LangCode (en _e) : m_e(_e) {}
|
||||
V3LangCode (const char* textp);
|
||||
explicit V3LangCode (const char* textp);
|
||||
explicit inline V3LangCode (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
};
|
||||
|
||||
+9
-9
@@ -93,10 +93,10 @@ public:
|
||||
LifeVarEntry(SIMPLEASSIGN, AstNodeAssign* assp) {
|
||||
init(true); simpleAssign(assp);
|
||||
}
|
||||
LifeVarEntry(COMPLEXASSIGN) {
|
||||
explicit LifeVarEntry(COMPLEXASSIGN) {
|
||||
init(false); complexAssign();
|
||||
}
|
||||
LifeVarEntry(CONSUMED) {
|
||||
explicit LifeVarEntry(CONSUMED) {
|
||||
init(false); consumed();
|
||||
}
|
||||
~LifeVarEntry() {}
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
// above our current iteration point.
|
||||
if (debug()>4) oldassp->dumpTree(cout, " REMOVE/SAMEBLK ");
|
||||
entp->complexAssign();
|
||||
m_statep->pushUnlinkDeletep(oldassp); oldassp=NULL;
|
||||
m_statep->pushUnlinkDeletep(oldassp); VL_DANGLING(oldassp);
|
||||
++m_statep->m_statAssnDel;
|
||||
}
|
||||
}
|
||||
@@ -199,7 +199,7 @@ public:
|
||||
// We'll later constant propagate
|
||||
UINFO(4," replaceconst: "<<varrefp<<endl);
|
||||
varrefp->replaceWith(constp->cloneTree(false));
|
||||
varrefp->deleteTree(); varrefp=NULL;
|
||||
varrefp->deleteTree(); VL_DANGLING(varrefp);
|
||||
++m_statep->m_statAssnCon;
|
||||
return; // **DONE, no longer a var reference**
|
||||
}
|
||||
@@ -313,7 +313,7 @@ private:
|
||||
if (nodep->lvalue()) {
|
||||
m_lifep->complexAssign(vscp);
|
||||
} else {
|
||||
m_lifep->varUsageReplace(vscp, nodep); nodep=NULL;
|
||||
m_lifep->varUsageReplace(vscp, nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
@@ -455,14 +455,14 @@ public:
|
||||
m_sideEffect = false;
|
||||
m_noopt = false;
|
||||
{
|
||||
// Cpp check bug, it is deleted
|
||||
// cppcheck-suppress leak
|
||||
m_lifep = new LifeBlock (NULL, m_statep);
|
||||
nodep->accept(*this);
|
||||
delete m_lifep; m_lifep=NULL;
|
||||
if (m_lifep) { delete m_lifep; m_lifep=NULL; }
|
||||
}
|
||||
}
|
||||
virtual ~LifeVisitor() {}
|
||||
virtual ~LifeVisitor() {
|
||||
if (m_lifep) { delete m_lifep; m_lifep=NULL; }
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
+4
-4
@@ -68,7 +68,7 @@ private:
|
||||
UINFO(9, " Replace "<<nodep<<" to "<<newvscp<<endl);
|
||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue());
|
||||
nodep->replaceWith(newrefp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
LifePostElimVisitor(AstTopScope* nodep) {
|
||||
explicit LifePostElimVisitor(AstTopScope* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~LifePostElimVisitor() {}
|
||||
@@ -155,7 +155,7 @@ private:
|
||||
UINFO(4," DELETE "<<nodep<<endl);
|
||||
// Mark so LifePostElimVisitor will get it
|
||||
rhsp->varScopep()->user4p(lhsp->varScopep());
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
++m_statAssnDel;
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
LifePostDlyVisitor(AstNetlist* nodep) {
|
||||
explicit LifePostDlyVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~LifePostDlyVisitor() {
|
||||
|
||||
+17
-7
@@ -66,7 +66,7 @@ public:
|
||||
|
||||
class LibraryVertex : public V3GraphVertex {
|
||||
public:
|
||||
LibraryVertex(V3Graph* graphp)
|
||||
explicit LibraryVertex(V3Graph* graphp)
|
||||
: V3GraphVertex(graphp) {}
|
||||
virtual ~LibraryVertex() {}
|
||||
virtual string name() const { return "*LIBRARY*"; }
|
||||
@@ -292,7 +292,7 @@ private:
|
||||
if (pinStar) pinp->v3error("Duplicate .* in a cell");
|
||||
pinStar = true;
|
||||
// Done with this fake pin
|
||||
pinp->unlinkFrBack()->deleteTree(); pinp=NULL;
|
||||
pinp->unlinkFrBack()->deleteTree(); VL_DANGLING(pinp);
|
||||
}
|
||||
}
|
||||
// Convert unnamed pins to pin number based assignments
|
||||
@@ -348,11 +348,21 @@ private:
|
||||
// This is quite similar to how classes work; when unpacked classes are better supported
|
||||
// may remap interfaces to be more like a class.
|
||||
if (!nodep->hasIfaceVar()) {
|
||||
string varName = nodep->name()+"__Viftop"; // V3LinkDot looks for this naming
|
||||
AstIfaceRefDType* idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(), nodep->modp()->name());
|
||||
idtypep->cellp(nodep); // Only set when real parent cell known
|
||||
string varName = nodep->name() + "__Viftop"; // V3LinkDot looks for this naming
|
||||
AstIfaceRefDType* idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(),
|
||||
nodep->modp()->name());
|
||||
idtypep->ifacep(NULL); // cellp overrides
|
||||
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName, VFlagChildDType(), idtypep);
|
||||
// In the case of arrayed interfaces, we replace cellp when de-arraying in V3Inst
|
||||
idtypep->cellp(nodep); // Only set when real parent cell known.
|
||||
AstVar* varp;
|
||||
if (nodep->rangep()) {
|
||||
AstNodeArrayDType* arrp = new AstUnpackArrayDType(nodep->fileline(),VFlagChildDType(), idtypep, nodep->rangep()->cloneTree(true));
|
||||
varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
|
||||
VFlagChildDType(), arrp);
|
||||
} else {
|
||||
varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName,
|
||||
VFlagChildDType(), idtypep);
|
||||
}
|
||||
varp->isIfaceParent(true);
|
||||
nodep->addNextHere(varp);
|
||||
nodep->hasIfaceVar(true);
|
||||
@@ -384,7 +394,7 @@ private:
|
||||
<<foundp->warnMore()<<"... Location of original declaration");
|
||||
}
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
} else if (!foundp) {
|
||||
m_mods.rootp()->insert(nodep->name(), new VSymEnt(&m_mods, nodep));
|
||||
}
|
||||
|
||||
+147
-49
@@ -365,14 +365,31 @@ public:
|
||||
void insertIfaceVarSym(VSymEnt* symp) { // Where sym is for a VAR of dtype IFACEREFDTYPE
|
||||
m_ifaceVarSyms.push_back(symp);
|
||||
}
|
||||
// Iface for a raw or arrayed iface
|
||||
static AstIfaceRefDType* ifaceRefFromArray(AstNodeDType* nodep) {
|
||||
AstIfaceRefDType* ifacerefp = nodep->castIfaceRefDType();
|
||||
if (!ifacerefp) {
|
||||
if (AstUnpackArrayDType* arrp = nodep->castUnpackArrayDType()) {
|
||||
ifacerefp = arrp->subDTypep()->castIfaceRefDType();
|
||||
}
|
||||
}
|
||||
return ifacerefp;
|
||||
}
|
||||
void computeIfaceVarSyms() {
|
||||
for (IfaceVarSyms::iterator it = m_ifaceVarSyms.begin(); it != m_ifaceVarSyms.end(); ++it) {
|
||||
VSymEnt* varSymp = *it;
|
||||
AstVar* varp = varSymp->nodep()->castVar();
|
||||
UINFO(9, " insAllIface se"<<(void*)varSymp<<" "<<varp<<endl);
|
||||
AstIfaceRefDType* ifacerefp = varp->subDTypep()->castIfaceRefDType();
|
||||
AstIfaceRefDType* ifacerefp = ifaceRefFromArray(varp->subDTypep());
|
||||
if (!ifacerefp) varp->v3fatalSrc("Non-ifacerefs on list!");
|
||||
if (!ifacerefp->ifaceViaCellp()) ifacerefp->v3fatalSrc("Unlinked interface");
|
||||
if (!ifacerefp->ifaceViaCellp()) {
|
||||
if (!ifacerefp->cellp()) { // Probably a NotFoundModule, or a normal module if made mistake
|
||||
ifacerefp->v3error("Cannot find file containing interface: "<<AstNode::prettyName(ifacerefp->ifaceName()));
|
||||
continue;
|
||||
} else {
|
||||
ifacerefp->v3fatalSrc("Unlinked interface");
|
||||
}
|
||||
}
|
||||
VSymEnt* ifaceSymp = getNodeSym(ifacerefp->ifaceViaCellp());
|
||||
VSymEnt* ifOrPortSymp = ifaceSymp;
|
||||
// Link Modport names to the Modport Node under the Interface
|
||||
@@ -401,6 +418,10 @@ public:
|
||||
// Track and later insert scope aliases; an interface referenced by a child cell connecting to that interface
|
||||
// Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell
|
||||
UINFO(9," insertScopeAlias se"<<(void*)lhsp<<" se"<<(void*)rhsp<<endl);
|
||||
if (rhsp->nodep()->castCell()
|
||||
&& !rhsp->nodep()->castCell()->modp()->castIface()) {
|
||||
rhsp->nodep()->v3fatalSrc("Got a non-IFACE alias RHS");
|
||||
}
|
||||
m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp));
|
||||
}
|
||||
void computeScopeAliases() {
|
||||
@@ -508,6 +529,17 @@ public:
|
||||
return lookupSymp;
|
||||
}
|
||||
|
||||
static string removeLastInlineScope(const string& name) {
|
||||
string out = name;
|
||||
string dot = "__DOT__";
|
||||
size_t dotPos = out.rfind(dot, out.size() - dot.length() - 2);
|
||||
if (dotPos == string::npos) {
|
||||
return "";
|
||||
} else {
|
||||
return out.erase(dotPos + dot.length(), string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
VSymEnt* findSymPrefixed(VSymEnt* lookupSymp, const string& dotname, string& baddot) {
|
||||
// Find symbol in given point in hierarchy, allowing prefix (post-Inline)
|
||||
// For simplicity lookupSymp may be passed NULL result from findDotted
|
||||
@@ -518,7 +550,15 @@ public:
|
||||
<<((lookupSymp->symPrefix()=="") ? "" : lookupSymp->symPrefix()+dotname)
|
||||
<<" at se"<<lookupSymp
|
||||
<<endl);
|
||||
VSymEnt* foundp = lookupSymp->findIdFallback(lookupSymp->symPrefix() + dotname); // Might be NULL
|
||||
string prefix = lookupSymp->symPrefix();
|
||||
VSymEnt* foundp = NULL;
|
||||
while (!foundp) {
|
||||
foundp = lookupSymp->findIdFallback(prefix + dotname); // Might be NULL
|
||||
if (prefix == "") {
|
||||
break;
|
||||
}
|
||||
prefix = removeLastInlineScope(prefix);
|
||||
}
|
||||
if (!foundp) baddot = dotname;
|
||||
return foundp;
|
||||
}
|
||||
@@ -814,7 +854,7 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
newdtypep->unlinkFrBack();
|
||||
findvarp->childDTypep(newdtypep);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->v3error("Duplicate declaration of signal: "<<nodep->prettyName()<<endl
|
||||
<<findvarp->warnMore()<<"... Location of original declaration");
|
||||
@@ -835,10 +875,12 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
|
||||
if (m_statep->forPrimary() && nodep->isGParam()) {
|
||||
m_paramNum++;
|
||||
VSymEnt* symp = m_statep->insertSym(m_curSymp, "__paramNumber"+cvtToStr(m_paramNum), nodep, m_packagep);
|
||||
VSymEnt* symp = m_statep->insertSym(m_curSymp, "__paramNumber" + cvtToStr(m_paramNum),
|
||||
nodep, m_packagep);
|
||||
symp->exported(false);
|
||||
}
|
||||
if (nodep->subDTypep()->castIfaceRefDType()) {
|
||||
AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(nodep->subDTypep());
|
||||
if (ifacerefp) {
|
||||
// Can't resolve until interfaces and modport names are known; see notes at top
|
||||
m_statep->insertIfaceVarSym(insp);
|
||||
}
|
||||
@@ -1005,7 +1047,7 @@ private:
|
||||
nodep->name(),
|
||||
exprp);
|
||||
cellp->addParamsp(pinp);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstPort* nodep, AstNUser*) {
|
||||
@@ -1025,7 +1067,7 @@ private:
|
||||
symp->exported(false);
|
||||
}
|
||||
// Ports not needed any more
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||
// Deal with implicit definitions
|
||||
@@ -1050,7 +1092,7 @@ private:
|
||||
// Unsupported gates need implicit creation
|
||||
pinImplicitExprRecurse(nodep);
|
||||
// We're done with implicit gates
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
@@ -1104,7 +1146,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
|
||||
&& nodep->varp()->isIfaceParent()) {
|
||||
UINFO(9,"Iface parent ref var "<<nodep->varp()->name()<<" "<<nodep<<endl);
|
||||
// Find the interface cell the var references
|
||||
AstIfaceRefDType* dtypep = nodep->varp()->dtypep()->castIfaceRefDType();
|
||||
AstIfaceRefDType* dtypep = LinkDotState::ifaceRefFromArray(nodep->varp()->dtypep());
|
||||
if (!dtypep) nodep->v3fatalSrc("Non AstIfaceRefDType on isIfaceRef() var");
|
||||
UINFO(9,"Iface parent dtype "<<dtypep<<endl);
|
||||
string ifcellname = dtypep->cellName();
|
||||
@@ -1145,10 +1187,20 @@ class LinkDotScopeVisitor : public AstNVisitor {
|
||||
VSymEnt* rhsSymp;
|
||||
{
|
||||
AstVarRef* refp = nodep->rhsp()->castVarRef();
|
||||
if (!refp) nodep->v3fatalSrc("Unsupported: Non VarRef attached to interface pin");
|
||||
string scopename = refp->name();
|
||||
string baddot; VSymEnt* okSymp;
|
||||
VSymEnt* symp = m_statep->findDotted(m_modSymp, scopename, baddot, okSymp);
|
||||
AstVarXRef* xrefp = nodep->rhsp()->castVarXRef();
|
||||
if (!refp && !xrefp) nodep->v3fatalSrc("Unsupported: Non Var(X)Ref attached to interface pin");
|
||||
string inl = (xrefp && xrefp->inlinedDots().size()) ? (xrefp->inlinedDots() + "__DOT__") : "";
|
||||
VSymEnt* symp = NULL;
|
||||
string scopename;
|
||||
while (!symp) {
|
||||
scopename = refp ? refp->name() : (inl.size() ? (inl + xrefp->name()) : xrefp->name());
|
||||
string baddot; VSymEnt* okSymp;
|
||||
symp = m_statep->findDotted(m_modSymp, scopename, baddot, okSymp);
|
||||
if (inl == "")
|
||||
break;
|
||||
inl = LinkDotState::removeLastInlineScope(inl);
|
||||
}
|
||||
if (!symp) UINFO(9,"No symbol for interface alias rhs ("<<string(refp?"VARREF ":"VARXREF ")<<scopename<<")"<<endl);
|
||||
if (!symp) nodep->v3fatalSrc("No symbol for interface alias rhs");
|
||||
UINFO(5, " Found a linked scope RHS: "<<scopename<<" se"<<(void*)symp<<" "<<symp->nodep()<<endl);
|
||||
rhsSymp = symp;
|
||||
@@ -1168,7 +1220,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
|
||||
// or maybe an alias of an alias
|
||||
m_statep->insertScopeAlias(LinkDotState::SAMN_IFTOP, lhsSymp, rhsSymp);
|
||||
// We have stored the link, we don't need these any more
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
// For speed, don't recurse things that can't have scope
|
||||
// Note we allow AstNodeStmt's as generates may be under them
|
||||
@@ -1235,7 +1287,7 @@ class LinkDotIfaceVisitor : public AstNVisitor {
|
||||
if (m_statep->forScopeCreation()) {
|
||||
// Done with AstModportFTaskRef.
|
||||
// Delete to prevent problems if we dead-delete pointed to ftask
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstModportVarRef* nodep, AstNUser*) {
|
||||
@@ -1258,7 +1310,7 @@ class LinkDotIfaceVisitor : public AstNVisitor {
|
||||
if (m_statep->forScopeCreation()) {
|
||||
// Done with AstModportVarRef.
|
||||
// Delete to prevent problems if we dead-delete pointed to variable
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
@@ -1322,12 +1374,15 @@ private:
|
||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||
VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup
|
||||
AstDot* m_dotp; // Current dot
|
||||
bool m_unresolved; // Unresolved, needs help from V3Param
|
||||
AstNode* m_unlinkedScope;// Unresolved scope, needs corresponding VarXRef
|
||||
bool m_dotErr; // Error found in dotted resolution, ignore upwards
|
||||
string m_dotText; // String of dotted names found in below parseref
|
||||
DotStates() { init(NULL); }
|
||||
~DotStates() {}
|
||||
void init(VSymEnt* curSymp) {
|
||||
m_dotPos = DP_NONE; m_dotSymp = curSymp; m_dotp = NULL; m_dotErr = false; m_dotText = "";
|
||||
m_unresolved = false; m_unlinkedScope = NULL;
|
||||
}
|
||||
string ascii() const {
|
||||
static const char* names[] = { "NONE","PACKAGE","SCOPE","FINAL","MEMBER" };
|
||||
@@ -1335,6 +1390,7 @@ private:
|
||||
sstr<<"ds="<<names[m_dotPos];
|
||||
sstr<<" dse"<<(void*)m_dotSymp;
|
||||
sstr<<" txt="<<m_dotText;
|
||||
sstr<<" unr="<<m_unresolved;
|
||||
return sstr.str();
|
||||
}
|
||||
} m_ds; // State to preserve across recursions
|
||||
@@ -1416,7 +1472,7 @@ private:
|
||||
virtual void visit(AstCellInline* nodep, AstNUser*) {
|
||||
checkNoDot(nodep);
|
||||
if (m_statep->forScopeCreation()) {
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
@@ -1460,7 +1516,7 @@ private:
|
||||
if (!refp) {
|
||||
if (nodep->name() == "__paramNumber1" && m_cellp->modp()->castPrimitive()) {
|
||||
// Primitive parameter is really a delay we can just ignore
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
}
|
||||
nodep->v3error(ucfirst(whatp)<<" not found: "<<nodep->prettyName());
|
||||
@@ -1487,7 +1543,7 @@ private:
|
||||
if (nodep->user3SetOnce()) return;
|
||||
UINFO(8," "<<nodep<<endl);
|
||||
DotStates lastStates = m_ds;
|
||||
bool start = !m_ds.m_dotp; // Save, as m_dotp will be changed
|
||||
bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
|
||||
{
|
||||
if (start) { // Starting dot sequence
|
||||
if (debug()>=9) nodep->dumpTree("-dot-in: ");
|
||||
@@ -1498,13 +1554,16 @@ private:
|
||||
|
||||
// m_ds.m_dotText communicates the cell prefix between stages
|
||||
if (nodep->lhsp()->castPackageRef()) {
|
||||
if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in dotted reference"); m_ds.m_dotErr=true; }
|
||||
//if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in dotted reference"); m_ds.m_dotErr=true; }
|
||||
m_ds.m_dotPos = DP_PACKAGE;
|
||||
} else {
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
//if (debug()>=9) nodep->dumpTree("-dot-lho: ");
|
||||
}
|
||||
if (m_ds.m_unresolved && (nodep->lhsp()->castCellRef() || nodep->lhsp()->castCellArrayRef())) {
|
||||
m_ds.m_unlinkedScope = nodep->lhsp();
|
||||
}
|
||||
if (!m_ds.m_dotErr) { // Once something wrong, give up
|
||||
if (start && m_ds.m_dotPos==DP_SCOPE) m_ds.m_dotPos = DP_FINAL; // Top 'final' dot RHS is final RHS, else it's a DOT(DOT(x,*here*),real-rhs) which we consider a RHS
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
@@ -1520,11 +1579,15 @@ private:
|
||||
}
|
||||
if (debug()>=9) newp->dumpTree("-dot-out: ");
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
} else { // Dot midpoint
|
||||
AstNode* newp = nodep->rhsp()->unlinkFrBack();
|
||||
if (m_ds.m_unresolved) {
|
||||
AstCellRef* crp = new AstCellRef(nodep->fileline(), nodep->name(), nodep->lhsp()->unlinkFrBack(), newp);
|
||||
newp = crp;
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
if (start) {
|
||||
@@ -1541,7 +1604,7 @@ private:
|
||||
if (!m_ds.m_dotSymp) nodep->v3fatalSrc("NULL lookup symbol table");
|
||||
if (!m_statep->forPrimary()) nodep->v3fatalSrc("ParseRefs should no longer exist");
|
||||
DotStates lastStates = m_ds;
|
||||
bool start = !m_ds.m_dotp;
|
||||
bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
|
||||
if (start) {
|
||||
m_ds.init(m_curSymp);
|
||||
// Note m_ds.m_dot remains NULL; this is a reference not under a dot
|
||||
@@ -1551,7 +1614,7 @@ private:
|
||||
AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
|
||||
AstNode* newp = new AstMemberSel(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name());
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
else {
|
||||
//
|
||||
@@ -1624,11 +1687,12 @@ private:
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
|
||||
AstNode* newp = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep = NULL;
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
else if (AstVar* varp = foundp->nodep()->castVar()) {
|
||||
if (AstIfaceRefDType* ifacerefp = varp->subDTypep()->castIfaceRefDType()) {
|
||||
AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(varp->subDTypep());
|
||||
if (ifacerefp) {
|
||||
if (!ifacerefp->ifaceViaCellp()) ifacerefp->v3fatalSrc("Unlinked interface");
|
||||
// Really this is a scope reference into an interface
|
||||
UINFO(9,"varref-ifaceref "<<m_ds.m_dotText<<" "<<nodep<<endl);
|
||||
@@ -1638,21 +1702,30 @@ private:
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
ok = true;
|
||||
AstNode* newp = new AstVarRef(nodep->fileline(), varp, false);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep = NULL;
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (allowVar) {
|
||||
AstNodeVarRef* newp;
|
||||
AstNode* newp;
|
||||
if (m_ds.m_dotText != "") {
|
||||
newp = new AstVarXRef(nodep->fileline(), nodep->name(), m_ds.m_dotText, false); // lvalue'ness computed later
|
||||
newp->varp(varp);
|
||||
AstVarXRef* refp = new AstVarXRef(nodep->fileline(), nodep->name(),
|
||||
m_ds.m_dotText, false); // lvalue'ness computed later
|
||||
refp->varp(varp);
|
||||
m_ds.m_dotText = "";
|
||||
if (m_ds.m_unresolved && m_ds.m_unlinkedScope) {
|
||||
newp = new AstUnlinkedRef(nodep->fileline(), refp->castVarXRef(),
|
||||
refp->name(), m_ds.m_unlinkedScope->unlinkFrBack());
|
||||
m_ds.m_unlinkedScope = NULL;
|
||||
m_ds.m_unresolved = false;
|
||||
} else {
|
||||
newp = refp;
|
||||
}
|
||||
} else {
|
||||
newp = new AstVarRef(nodep->fileline(), nodep->name(), false); // lvalue'ness computed later
|
||||
newp->varp(varp);
|
||||
newp->packagep(foundp->packagep());
|
||||
UINFO(9," new "<<newp<<endl);
|
||||
AstVarRef* refp = new AstVarRef(nodep->fileline(), varp, false); // lvalue'ness computed later
|
||||
refp->packagep(foundp->packagep());
|
||||
newp = refp;
|
||||
}
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep = NULL;
|
||||
UINFO(9," new "<<newp<<endl);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
m_ds.m_dotPos = DP_MEMBER;
|
||||
ok = true;
|
||||
}
|
||||
@@ -1682,13 +1755,13 @@ private:
|
||||
ok = true;
|
||||
AstVar* varp = makeIfaceModportVar(nodep->fileline(), cellp, ifacep, modportp);
|
||||
AstVarRef* refp = new AstVarRef(varp->fileline(), varp, false);
|
||||
nodep->replaceWith(refp); pushDeletep(nodep); nodep = NULL;
|
||||
nodep->replaceWith(refp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
else if (AstEnumItem* valuep = foundp->nodep()->castEnumItem()) {
|
||||
if (allowVar) {
|
||||
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep());
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); nodep = NULL;
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
ok = true;
|
||||
m_ds.m_dotText = "";
|
||||
}
|
||||
@@ -1717,7 +1790,7 @@ private:
|
||||
// Create if implicit, and also if error (so only complain once)
|
||||
AstVarRef* newp = new AstVarRef(nodep->fileline(), nodep->name(), false);
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep = NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
createImplicitVar (m_curSymp, newp, m_modp, m_modSymp, err);
|
||||
}
|
||||
}
|
||||
@@ -1795,7 +1868,7 @@ private:
|
||||
UINFO(7," Resolved "<<nodep<<endl); // Also prints taskp
|
||||
AstVarRef* newvscp = new AstVarRef(nodep->fileline(), vscp, nodep->lvalue());
|
||||
nodep->replaceWith(newvscp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
UINFO(9," new "<<newvscp<<endl); // Also prints taskp
|
||||
}
|
||||
}
|
||||
@@ -1831,14 +1904,24 @@ private:
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
m_ds.m_dotp = NULL;
|
||||
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) {
|
||||
nodep->dotted(m_ds.m_dotText); // Maybe ""
|
||||
if (m_ds.m_unresolved && m_ds.m_unlinkedScope) {
|
||||
AstNodeFTaskRef *newftaskp = nodep->cloneTree(false);
|
||||
newftaskp->dotted(m_ds.m_dotText);
|
||||
AstNode* newp = new AstUnlinkedRef(nodep->fileline(), newftaskp, nodep->name(), m_ds.m_unlinkedScope->unlinkFrBack());
|
||||
m_ds.m_unlinkedScope = NULL;
|
||||
m_ds.m_unresolved = false;
|
||||
nodep->replaceWith(newp);
|
||||
return;
|
||||
} else {
|
||||
nodep->dotted(m_ds.m_dotText); // Maybe ""
|
||||
}
|
||||
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_MEMBER) {
|
||||
// Found a Var, everything following is method call. {scope}.{var}.HERE {method} ( ARGS )
|
||||
AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
|
||||
AstNode* argsp = NULL; if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext();
|
||||
AstNode* newp = new AstMethodSel(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name(), argsp);
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
return;
|
||||
} else {
|
||||
checkNoDot(nodep);
|
||||
@@ -1906,12 +1989,9 @@ private:
|
||||
if (nodep->user3SetOnce()) return;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart}
|
||||
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
||||
string index = AstNode::encodeNumber(constp->toSInt());
|
||||
m_ds.m_dotText += "__BRA__"+index+"__KET__";
|
||||
} else {
|
||||
nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference");
|
||||
}
|
||||
UINFO(9," deferring until after a V3Param pass: "<<nodep<<endl);
|
||||
m_ds.m_dotText += "__BRA__??__KET__";
|
||||
m_ds.m_unresolved = true;
|
||||
// And pass up m_ds.m_dotText
|
||||
}
|
||||
// Pass dot state down to fromp()
|
||||
@@ -1923,6 +2003,11 @@ private:
|
||||
nodep->attrp()->iterateAndNext(*this);
|
||||
}
|
||||
m_ds = lastStates;
|
||||
if (m_ds.m_unresolved && m_ds.m_dotPos == DP_SCOPE) {
|
||||
AstNode* exprp = nodep->bitp()->unlinkFrBack();
|
||||
AstCellArrayRef* newp = new AstCellArrayRef(nodep->fileline(), nodep->fromp()->name(), exprp);
|
||||
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
|
||||
// Excludes simple AstSelBit, see above
|
||||
@@ -2016,8 +2101,21 @@ private:
|
||||
virtual void visit(AstPackageImport* nodep, AstNUser*) {
|
||||
// No longer needed
|
||||
checkNoDot(nodep);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstCellRef* nodep, AstNUser*) {
|
||||
UINFO(5," AstCellRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstCellArrayRef* nodep, AstNUser*) {
|
||||
UINFO(5," AstCellArrayRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
|
||||
// Expression already iterated
|
||||
}
|
||||
virtual void visit(AstUnlinkedRef* nodep, AstNUser*) {
|
||||
UINFO(5," AstCellArrayRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
|
||||
// No need to iterate, if we have a UnlinkedVarXRef, we're already done
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
checkNoDot(nodep);
|
||||
|
||||
+6
-6
@@ -159,7 +159,7 @@ private:
|
||||
initsp = initsp->addNext(newp);
|
||||
newp = initsp;
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
// Don't need to track AstRepeat/AstFor as they have already been converted
|
||||
@@ -192,7 +192,7 @@ private:
|
||||
AstJumpLabel* labelp = findAddLabel(m_ftaskp, false);
|
||||
nodep->addPrev(new AstJumpGo(nodep->fileline(), labelp));
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstBreak* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -202,7 +202,7 @@ private:
|
||||
AstJumpLabel* labelp = findAddLabel(m_loopp, false);
|
||||
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstContinue* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -213,7 +213,7 @@ private:
|
||||
AstJumpLabel* labelp = findAddLabel(m_loopp, true);
|
||||
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstDisable* nodep, AstNUser*) {
|
||||
UINFO(8," DISABLE "<<nodep<<endl);
|
||||
@@ -233,7 +233,7 @@ private:
|
||||
AstJumpLabel* labelp = findAddLabel(beginp, false);
|
||||
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labelo: "); }
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
@@ -246,7 +246,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
LinkJumpVisitor(AstNetlist* nodep) {
|
||||
explicit LinkJumpVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_loopp = NULL;
|
||||
|
||||
@@ -211,6 +211,14 @@ private:
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstCellArrayRef* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{ // selp is not an lvalue
|
||||
m_setRefLvalue = false;
|
||||
nodep->selp()->iterateAndNext(*this);
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{ // Only set lvalues on the from
|
||||
|
||||
+15
-15
@@ -190,62 +190,62 @@ private:
|
||||
AstTypedef* typep = nodep->backp()->castTypedef();
|
||||
if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef");
|
||||
typep->attrPublic(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrScClocked(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrClockEn(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->sigUserRWPublic(true); m_varp->sigModPublic(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->sigUserRWPublic(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->sigUserRdPublic(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->sigUserRWPublic(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrIsolateAssign(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrSFormat(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_SC_BV) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrScBv(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_YES);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_NO);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ private:
|
||||
if (backp->castTypedef()) { // A typedef doesn't need us to make yet another level of typedefing
|
||||
// For typedefs just remove the AstRefDType level of abstraction
|
||||
nodep->replaceWith(dtypep);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
return;
|
||||
} else {
|
||||
defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), dtypep);
|
||||
@@ -297,7 +297,7 @@ private:
|
||||
}
|
||||
}
|
||||
nodep->replaceWith(new AstRefDType(nodep->fileline(), defp->name()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstTypedefFwd* nodep, AstNUser*) {
|
||||
@@ -349,7 +349,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
LinkParseVisitor(AstNetlist* rootp) {
|
||||
explicit LinkParseVisitor(AstNetlist* rootp) {
|
||||
m_varp = NULL;
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
|
||||
+87
-45
@@ -38,6 +38,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3LinkResolve.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
@@ -82,7 +83,7 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
// Initial assignments under function/tasks can just be simple assignments without the initial
|
||||
if (m_ftaskp) {
|
||||
nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()); nodep=NULL;
|
||||
nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||
@@ -167,18 +168,18 @@ private:
|
||||
did=0;
|
||||
if (AstNodeSel* selp = nodep->sensp()->castNodeSel()) {
|
||||
AstNode* fromp = selp->fromp()->unlinkFrBack();
|
||||
selp->replaceWith(fromp); selp->deleteTree(); selp=NULL;
|
||||
selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp);
|
||||
did=1;
|
||||
}
|
||||
// NodeSel doesn't include AstSel....
|
||||
if (AstSel* selp = nodep->sensp()->castSel()) {
|
||||
AstNode* fromp = selp->fromp()->unlinkFrBack();
|
||||
selp->replaceWith(fromp); selp->deleteTree(); selp=NULL;
|
||||
selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp);
|
||||
did=1;
|
||||
}
|
||||
if (AstNodePreSel* selp = nodep->sensp()->castNodePreSel()) {
|
||||
AstNode* fromp = selp->lhsp()->unlinkFrBack();
|
||||
selp->replaceWith(fromp); selp->deleteTree(); selp=NULL;
|
||||
selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp);
|
||||
did=1;
|
||||
}
|
||||
}
|
||||
@@ -204,10 +205,17 @@ private:
|
||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) { // Maybe varxref - so need to clone
|
||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE,
|
||||
varrefp->cloneTree(false)));
|
||||
} else if (AstUnlinkedRef* uvxrp = basefromp->castUnlinkedRef()) { // Maybe unlinked - so need to clone
|
||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE,
|
||||
uvxrp->cloneTree(false)));
|
||||
} else if (AstMemberSel* fromp = basefromp->castMemberSel()) {
|
||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::MEMBER_BASE,
|
||||
fromp->cloneTree(false)));
|
||||
} else if (AstEnumItemRef* fromp = basefromp->castEnumItemRef()) {
|
||||
nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::ENUM_BASE,
|
||||
fromp->cloneTree(false)));
|
||||
} else {
|
||||
if (basefromp) { UINFO(1," Related node: "<<basefromp<<endl); }
|
||||
nodep->v3fatalSrc("Illegal bit select; no signal/member being extracted from");
|
||||
}
|
||||
}
|
||||
@@ -229,17 +237,17 @@ private:
|
||||
if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) {
|
||||
if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module\n");
|
||||
m_modp->modPublic(true);
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) {
|
||||
if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task\n");
|
||||
m_ftaskp->taskPublic(true);
|
||||
m_modp->modPublic(true); // Need to get to the task...
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
else if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
||||
if (!v3Global.opt.coverageLine()) { // No need for block statements; may optimize better without
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -247,24 +255,30 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
|
||||
// Check display arguments
|
||||
string expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
|
||||
// Check display arguments, return new format string
|
||||
string newFormat;
|
||||
bool inPct = false;
|
||||
string fmt = "";
|
||||
for (string::const_iterator it = format.begin(); it != format.end(); ++it) {
|
||||
char ch = tolower(*it);
|
||||
char ch = *it;
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
} else if (inPct && (isdigit(ch) || ch=='.')) {
|
||||
fmt += ch;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
fmt += ch;
|
||||
switch (tolower(ch)) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
inPct = true;
|
||||
case '%': // %% - just output a %
|
||||
break;
|
||||
case '%': break; // %% - just output a %
|
||||
case 'm': // %m - auto insert "name"
|
||||
if (isScan) nodep->v3error("Unsupported: %m in $fscanf");
|
||||
if (isScan) { nodep->v3error("Unsupported: %m in $fscanf"); fmt = ""; }
|
||||
break;
|
||||
case 'l': // %l - auto insert "library"
|
||||
if (isScan) { nodep->v3error("Unsupported: %l in $fscanf"); fmt = ""; }
|
||||
if (m_modp) fmt = VString::quotePercent(m_modp->prettyName());
|
||||
break;
|
||||
default: // Most operators, just move to next argument
|
||||
if (!V3Number::displayedFmtLegal(ch)) {
|
||||
@@ -278,11 +292,61 @@ private:
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
newFormat += fmt;
|
||||
} else {
|
||||
newFormat += ch;
|
||||
}
|
||||
}
|
||||
if (argp) {
|
||||
argp->v3error("Extra arguments for $display-like format");
|
||||
|
||||
if (argp && !isScan) {
|
||||
int skipCount = 0; // number of args consume by any additional format strings
|
||||
while (argp) {
|
||||
if (skipCount) {
|
||||
argp = argp->nextp();
|
||||
skipCount--;
|
||||
continue;
|
||||
}
|
||||
AstConst *constp = argp->castConst();
|
||||
bool isFromString = (constp) ? constp->num().isFromString() : false;
|
||||
if (isFromString) {
|
||||
int numchars = argp->dtypep()->width()/8;
|
||||
string str(numchars, ' ');
|
||||
// now scan for % operators
|
||||
bool inpercent = false;
|
||||
for (int i = 0; i < numchars; i++) {
|
||||
int ii = numchars - i - 1;
|
||||
char c = constp->num().dataByte(ii);
|
||||
str[i] = c;
|
||||
if (!inpercent && c == '%') {
|
||||
inpercent = true;
|
||||
} else if (inpercent) {
|
||||
inpercent = 0;
|
||||
switch (c) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
inpercent = true;
|
||||
break;
|
||||
case '%':
|
||||
break;
|
||||
default:
|
||||
if (V3Number::displayedFmtLegal(c)) {
|
||||
skipCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newFormat.append(str);
|
||||
AstNode *nextp = argp->nextp();
|
||||
argp->unlinkFrBack(); pushDeletep(argp); VL_DANGLING(argp);
|
||||
argp = nextp;
|
||||
} else {
|
||||
newFormat.append("%h");
|
||||
argp = argp->nextp();
|
||||
}
|
||||
}
|
||||
}
|
||||
return newFormat;
|
||||
}
|
||||
|
||||
void expectDescriptor(AstNode* nodep, AstNodeVarRef* filep) {
|
||||
@@ -302,23 +366,8 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->filep()) {
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFGetC* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFGetS* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||
@@ -327,7 +376,8 @@ private:
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), false);
|
||||
string newFormat = expectFormat(nodep, nodep->text(), nodep->exprsp(), false);
|
||||
nodep->text(newFormat);
|
||||
if ((nodep->backp()->castDisplay() && nodep->backp()->castDisplay()->displayType().needScopeTracking())
|
||||
|| nodep->formatScopeTracking()) {
|
||||
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
@@ -335,14 +385,6 @@ private:
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
if (!m_assertp
|
||||
&& (nodep->displayType() == AstDisplayType::DT_INFO
|
||||
|| nodep->displayType() == AstDisplayType::DT_WARNING
|
||||
|| nodep->displayType() == AstDisplayType::DT_ERROR
|
||||
|| nodep->displayType() == AstDisplayType::DT_FATAL)) {
|
||||
nodep->v3error(nodep->verilogKwd()+" only allowed under an assertion.");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstUdpTable* nodep, AstNUser*) {
|
||||
@@ -368,7 +410,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +437,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
LinkResolveVisitor(AstNetlist* rootp) {
|
||||
explicit LinkResolveVisitor(AstNetlist* rootp) {
|
||||
m_ftaskp = NULL;
|
||||
m_modp = NULL;
|
||||
m_assertp = NULL;
|
||||
@@ -447,7 +489,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
LinkBotupVisitor(AstNetlist* rootp) {
|
||||
explicit LinkBotupVisitor(AstNetlist* rootp) {
|
||||
m_modp = NULL;
|
||||
//
|
||||
rootp->accept(*this);
|
||||
|
||||
+2
-2
@@ -93,7 +93,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
LocalizeDehierVisitor(AstNetlist* nodep) {
|
||||
explicit LocalizeDehierVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~LocalizeDehierVisitor() {}
|
||||
@@ -233,7 +233,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
LocalizeVisitor(AstNetlist* nodep) {
|
||||
explicit LocalizeVisitor(AstNetlist* nodep) {
|
||||
m_cfuncp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
NameVisitor(AstNetlist* nodep) {
|
||||
explicit NameVisitor(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~NameVisitor() {}
|
||||
|
||||
+78
-17
@@ -396,12 +396,12 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
|
||||
if (binary) {
|
||||
out<<"b";
|
||||
out<<displayed("%0b");
|
||||
out<<displayed(m_fileline, "%0b");
|
||||
}
|
||||
else {
|
||||
if (prefixed) out<<"h";
|
||||
// Always deal with 4 bits at once. Note no 4-state, it's above.
|
||||
out<<displayed("%0h");
|
||||
out<<displayed(m_fileline, "%0h");
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
@@ -409,9 +409,8 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
string V3Number::quoteNameControls(const string& namein) {
|
||||
// Encode control chars into C style escapes
|
||||
// Reverse is V3Parse::deQuote
|
||||
const char* start = namein.c_str();
|
||||
string out;
|
||||
for (const char* pos = start; *pos; pos++) {
|
||||
for (string::const_iterator pos=namein.begin(); pos!=namein.end(); ++pos) {
|
||||
if (pos[0]=='\\' || pos[0]=='"') {
|
||||
out += string("\\")+pos[0];
|
||||
} else if (pos[0]=='\n') {
|
||||
@@ -424,7 +423,8 @@ string V3Number::quoteNameControls(const string& namein) {
|
||||
out += pos[0];
|
||||
} else {
|
||||
// This will also cover \a etc
|
||||
char octal[10]; sprintf(octal,"\\%03o",pos[0]);
|
||||
// Can't use %03o as messes up when signed
|
||||
char octal[10]; sprintf(octal,"\\%o%o%o",(pos[0]>>6)&3, (pos[0]>>3)&7, pos[0]&7);
|
||||
out += octal;
|
||||
}
|
||||
}
|
||||
@@ -442,16 +442,20 @@ bool V3Number::displayedFmtLegal(char format) {
|
||||
case 'g': return true;
|
||||
case 'h': return true;
|
||||
case 'o': return true;
|
||||
case 'p': return true; // Pattern
|
||||
case 's': return true;
|
||||
case 't': return true;
|
||||
case 'u': return true; // Packed 2-state
|
||||
case 'v': return true; // Strength
|
||||
case 'x': return true;
|
||||
case 'z': return true; // Packed 4-state
|
||||
case '@': return true; // Packed string
|
||||
case '~': return true; // Signed decimal
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
string V3Number::displayed(const string& vformat) const {
|
||||
string V3Number::displayed(FileLine*fl, const string& vformat) const {
|
||||
string::const_iterator pos = vformat.begin();
|
||||
UASSERT(pos != vformat.end() && pos[0]=='%', "$display-like function with non format argument "<<*this);
|
||||
++pos;
|
||||
@@ -496,14 +500,12 @@ string V3Number::displayed(const string& vformat) const {
|
||||
return str;
|
||||
}
|
||||
case 'c': {
|
||||
if (this->width()>8) m_fileline->v3error("$display-like format of char of > 8 bit value");
|
||||
int v = bitsValue(0, 8);
|
||||
str += (char)(v);
|
||||
if (this->width()>8) fl->v3warn(WIDTH,"$display-like format of %c format of > 8 bit value");
|
||||
unsigned int v = bitsValue(0, 8);
|
||||
char strc[2]; strc[0] = v&0xff; strc[1] = '\0';
|
||||
str = strc;
|
||||
return str;
|
||||
}
|
||||
case '@': { // Packed string
|
||||
return toString();
|
||||
}
|
||||
case 's': {
|
||||
// Spec says always drop leading zeros, this isn't quite right, we space pad.
|
||||
int bit=this->width()-1;
|
||||
@@ -532,7 +534,7 @@ string V3Number::displayed(const string& vformat) const {
|
||||
fmtsize = cvtToStr(int(dchars));
|
||||
}
|
||||
if (width() > 64) {
|
||||
m_fileline->v3error("Unsupported: $display-like format of decimal of > 64 bit results (use hex format instead)");
|
||||
fl->v3error("Unsupported: $display-like format of decimal of > 64 bit results (use hex format instead)");
|
||||
return "ERR";
|
||||
}
|
||||
if (issigned) {
|
||||
@@ -555,8 +557,45 @@ string V3Number::displayed(const string& vformat) const {
|
||||
sprintf(tmp, vformat.c_str(), toDouble());
|
||||
return tmp;
|
||||
}
|
||||
// 'l' // Library - converted to text by V3LinkResolve
|
||||
// 'p' // Packed - converted to another code by V3Width
|
||||
case 'u': { // Packed 2-state
|
||||
for (int i=0; i<words(); i++) {
|
||||
str += (char)((m_value[i] >> 0) & 0xff);
|
||||
str += (char)((m_value[i] >> 8) & 0xff);
|
||||
str += (char)((m_value[i] >> 16) & 0xff);
|
||||
str += (char)((m_value[i] >> 24) & 0xff);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case 'z': { // Packed 4-state
|
||||
for (int i=0; i<words(); i++) {
|
||||
str += (char)((m_value[i] >> 0) & 0xff);
|
||||
str += (char)((m_value[i] >> 8) & 0xff);
|
||||
str += (char)((m_value[i] >> 16) & 0xff);
|
||||
str += (char)((m_value[i] >> 24) & 0xff);
|
||||
str += (char)((m_valueX[i] >> 0) & 0xff);
|
||||
str += (char)((m_valueX[i] >> 8) & 0xff);
|
||||
str += (char)((m_valueX[i] >> 16) & 0xff);
|
||||
str += (char)((m_valueX[i] >> 24) & 0xff);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case 'v': { // Strength
|
||||
int bit = width()-1;
|
||||
for (; bit>=0; bit--) {
|
||||
if (bitIs0(bit)) str+="St0 "; // Yes, always a space even for bit 0
|
||||
else if (bitIs1(bit)) str+="St1 ";
|
||||
else if (bitIsZ(bit)) str+="StZ ";
|
||||
else str+="StX";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case '@': { // Packed string
|
||||
return toString();
|
||||
}
|
||||
default:
|
||||
m_fileline->v3fatalSrc("Unknown $display-like format code for number: %"<<pos[0]);
|
||||
fl->v3fatalSrc("Unknown $display-like format code for number: %"<<pos[0]);
|
||||
return "ERR";
|
||||
}
|
||||
}
|
||||
@@ -939,7 +978,7 @@ V3Number& V3Number::opRepl (const V3Number& lhs, const V3Number& rhs) { // rhs i
|
||||
V3Number& V3Number::opRepl (const V3Number& lhs, uint32_t rhsval) { // rhs is # of times to replicate
|
||||
// i op repl, L(i)*value(rhs) bit return
|
||||
setZero();
|
||||
if (rhsval>8192) m_fileline->v3fatal("More than a 8k bit replication is probably wrong: "<<rhsval);
|
||||
if (rhsval>8192) m_fileline->v3warn(WIDTHCONCAT,"More than a 8k bit replication is probably wrong: "<<rhsval);
|
||||
int obit = 0;
|
||||
for (unsigned times=0; times<rhsval; times++) {
|
||||
for(int bit=0; bit<lhs.width(); bit++) {
|
||||
@@ -1569,6 +1608,24 @@ V3Number& V3Number::opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opSelInto (const V3Number& lhs, const V3Number& lsb, int width) {
|
||||
return opSelInto(lhs, lsb.toSInt(), width);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opSelInto (const V3Number& lhs, int lsbval, int width) {
|
||||
// this[lsbval+width-1 : lsbval] = lhs; Other bits of this are not affected
|
||||
int ibit=0;
|
||||
for(int bit=lsbval; bit<lsbval+width; bit++) {
|
||||
if (ibit>=0 && ibit<lhs.width()) {
|
||||
setBit(bit,lhs.bitIs(ibit));
|
||||
} else {
|
||||
setBit(bit,'x');
|
||||
}
|
||||
ibit++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s) {
|
||||
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
|
||||
if (lhstrue.bitIs0(0)) {
|
||||
@@ -1609,14 +1666,18 @@ V3Number& V3Number::opRealToBits (const V3Number& lhs) {
|
||||
if (lhs.width()!=64 || this->width()!=64) {
|
||||
m_fileline->v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
return opAssign(lhs);
|
||||
opAssign(lhs);
|
||||
m_double = false;
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::opBitsToRealD (const V3Number& lhs) {
|
||||
// Conveniently our internal format is identical so we can copy bits...
|
||||
if (lhs.width()!=64 || this->width()!=64) {
|
||||
m_fileline->v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
return opAssign(lhs);
|
||||
opAssign(lhs);
|
||||
m_double = true;
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::opNegateD (const V3Number& lhs) {
|
||||
return setDouble(- lhs.toDouble());
|
||||
|
||||
+18
-6
@@ -56,10 +56,19 @@ public:
|
||||
V3Number& setDouble(double value);
|
||||
void setBit (int bit, char value) { // Note must be pre-zeroed!
|
||||
if (bit>=m_width) return;
|
||||
if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31));
|
||||
else {
|
||||
if (value=='1'||value=='x'||value==1||value==3) m_value [bit/32] |= (1UL<<(bit&31));
|
||||
if (value=='z'||value=='x'||value==2||value==3) m_valueX[bit/32] |= (1UL<<(bit&31));
|
||||
uint32_t mask = (1UL<<(bit&31));
|
||||
if (value=='0' || value==0) {
|
||||
m_value [bit/32] &= ~mask;
|
||||
m_valueX[bit/32] &= ~mask;
|
||||
} else if (value=='1'|| value==1) {
|
||||
m_value [bit/32] |= mask;
|
||||
m_valueX[bit/32] &= ~mask;
|
||||
} else if (value=='z'|| value==2) {
|
||||
m_value [bit/32] &= ~mask;
|
||||
m_valueX[bit/32] |= mask;
|
||||
} else { // X
|
||||
m_value [bit/32] |= mask;
|
||||
m_valueX[bit/32] |= mask;
|
||||
}
|
||||
}
|
||||
private:
|
||||
@@ -120,7 +129,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
V3Number(FileLine* fileline) { init(fileline, 1); }
|
||||
explicit V3Number(FileLine* fileline) { init(fileline, 1); }
|
||||
V3Number(FileLine* fileline, int width) { init(fileline, width); } // 0=unsized
|
||||
V3Number(FileLine* fileline, int width, uint32_t value) { init(fileline, width); m_value[0]=value; opCleanThis(); }
|
||||
V3Number(FileLine* fileline, const char* source); // Create from a verilog 32'hxxxx number.
|
||||
@@ -162,7 +171,7 @@ public:
|
||||
// ACCESSORS
|
||||
string ascii(bool prefixed=true, bool cleanVerilog=false) const;
|
||||
static string quoteNameControls(const string& namein); // Add backslash quotes to strings
|
||||
string displayed(const string& format) const;
|
||||
string displayed(FileLine* fl, const string& format) const;
|
||||
static bool displayedFmtLegal(char format); // Is this a valid format letter?
|
||||
int width() const { return m_width; }
|
||||
int widthMin() const; // Minimum width that can represent this number (~== log2(num)+1)
|
||||
@@ -196,6 +205,7 @@ public:
|
||||
double toDouble() const;
|
||||
uint32_t toHash() const;
|
||||
uint32_t dataWord(int word) const;
|
||||
uint8_t dataByte(int byte) const { return (dataWord(byte/4) >> (8*(byte&3))) & 0xff; }
|
||||
uint32_t countOnes() const;
|
||||
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
|
||||
|
||||
@@ -235,6 +245,8 @@ public:
|
||||
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opSel (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opSel (const V3Number& lhs, uint32_t rhs, uint32_t ths);
|
||||
V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width);
|
||||
V3Number& opSelInto (const V3Number& lhs, int lsb, int width);
|
||||
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
|
||||
+22
-12
@@ -563,9 +563,9 @@ bool V3Options::onoff(const char* sw, const char* arg, bool& flag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool V3Options::suffixed(const char* sw, const char* arg) {
|
||||
if (strlen(arg) > strlen(sw)) return false;
|
||||
return (0==strcmp(sw+strlen(sw)-strlen(arg), arg));
|
||||
bool V3Options::suffixed(const string& sw, const char* arg) {
|
||||
if (strlen(arg) > sw.length()) return false;
|
||||
return (0==strcmp(sw.c_str()+sw.length()-strlen(arg), arg));
|
||||
}
|
||||
|
||||
void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv) {
|
||||
@@ -672,6 +672,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( onoff (sw, "-trace-structs", flag/*ref*/) ) { m_traceStructs = flag; }
|
||||
else if ( onoff (sw, "-trace-underscore", flag/*ref*/) ) { m_traceUnderscore = flag; }
|
||||
else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2
|
||||
else if ( onoff (sw, "-vpi", flag/*ref*/) ) { m_vpi = flag; }
|
||||
else if ( onoff (sw, "-x-initial-edge", flag/*ref*/) ) { m_xInitialEdge = flag; }
|
||||
else if ( onoff (sw, "-xml-only", flag/*ref*/) ) { m_xmlOnly = flag; } // Undocumented, still experimental
|
||||
// Optimization
|
||||
@@ -711,6 +712,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
addCFlags(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-comp-limits-syms") && (i+1)<argc ) { // Undocumented
|
||||
shift;
|
||||
VName::maxLength(atoi(argv[i]));
|
||||
}
|
||||
else if ( !strcmp (sw, "-converge-limit") && (i+1)<argc ) {
|
||||
shift;
|
||||
m_convergeLimit = atoi(argv[i]);
|
||||
@@ -957,15 +962,16 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else {
|
||||
// Filename
|
||||
string filename = parseFileArg(optdir,argv[i]);
|
||||
if (suffixed(filename.c_str(), ".cpp")
|
||||
|| suffixed(filename.c_str(), ".cxx")
|
||||
|| suffixed(filename.c_str(), ".cc")
|
||||
|| suffixed(filename.c_str(), ".sp")) {
|
||||
if (suffixed(filename, ".cpp")
|
||||
|| suffixed(filename, ".cxx")
|
||||
|| suffixed(filename, ".cc")
|
||||
|| suffixed(filename, ".c")
|
||||
|| suffixed(filename, ".sp")) {
|
||||
V3Options::addCppFile(filename);
|
||||
}
|
||||
else if (suffixed(filename.c_str(), ".a")
|
||||
|| suffixed(filename.c_str(), ".o")
|
||||
|| suffixed(filename.c_str(), ".so")) {
|
||||
else if (suffixed(filename, ".a")
|
||||
|| suffixed(filename, ".o")
|
||||
|| suffixed(filename, ".so")) {
|
||||
V3Options::addLdLibs(filename);
|
||||
}
|
||||
else {
|
||||
@@ -983,7 +989,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
|
||||
// Read the specified -f filename and process as arguments
|
||||
UINFO(1,"Reading Options File "<<filename<<endl);
|
||||
|
||||
const auto_ptr<ifstream> ifp (V3File::new_ifstream(filename));
|
||||
const VL_UNIQUE_PTR<ifstream> ifp (V3File::new_ifstream(filename));
|
||||
if (ifp->fail()) {
|
||||
fl->v3error("Cannot open -f command file: "+filename);
|
||||
return;
|
||||
@@ -996,6 +1002,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
|
||||
getline(*ifp, line);
|
||||
// Strip simple comments
|
||||
string oline;
|
||||
// cppcheck-suppress StlMissingComparison
|
||||
for (string::const_iterator pos = line.begin(); pos != line.end(); ++pos) {
|
||||
if (inCmt) {
|
||||
if (*pos=='*' && *(pos+1)=='/') {
|
||||
@@ -1149,6 +1156,7 @@ V3Options::V3Options() {
|
||||
m_preprocOnly = false;
|
||||
m_preprocNoLine = false;
|
||||
m_public = false;
|
||||
m_reportUnoptflat = false;
|
||||
m_savable = false;
|
||||
m_skipIdentical = true;
|
||||
m_stats = false;
|
||||
@@ -1161,7 +1169,7 @@ V3Options::V3Options() {
|
||||
m_traceStructs = false;
|
||||
m_traceUnderscore = false;
|
||||
m_underlineZero = false;
|
||||
m_reportUnoptflat = false;
|
||||
m_vpi = false;
|
||||
m_xInitialEdge = false;
|
||||
m_xmlOnly = false;
|
||||
|
||||
@@ -1189,6 +1197,8 @@ V3Options::V3Options() {
|
||||
|
||||
m_defaultLanguage = V3LangCode::mostRecent();
|
||||
|
||||
VName::maxLength(128); // Linux filename limits 256; leave half for prefix
|
||||
|
||||
optimize(true);
|
||||
// Default +libext+
|
||||
addLibExtV(""); // So include "filename.v" will find the same file
|
||||
|
||||
+6
-2
@@ -85,6 +85,7 @@ class V3Options {
|
||||
bool m_pinsUint8; // main switch: --pins-uint8
|
||||
bool m_profileCFuncs;// main switch: --profile-cfuncs
|
||||
bool m_public; // main switch: --public
|
||||
bool m_reportUnoptflat; // main switch: --report-unoptflat
|
||||
bool m_savable; // main switch: --savable
|
||||
bool m_systemC; // main switch: --sc: System C instead of simple C++
|
||||
bool m_skipIdentical;// main switch: --skip-identical
|
||||
@@ -97,7 +98,7 @@ class V3Options {
|
||||
bool m_traceStructs; // main switch: --trace-structs
|
||||
bool m_traceUnderscore;// main switch: --trace-underscore
|
||||
bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2
|
||||
bool m_reportUnoptflat; // main switch: --report-unoptflat
|
||||
bool m_vpi; // main switch: --vpi
|
||||
bool m_xInitialEdge; // main switch: --x-initial-edge
|
||||
bool m_xmlOnly; // main switch: --xml-netlist
|
||||
|
||||
@@ -167,13 +168,15 @@ class V3Options {
|
||||
void showVersion(bool verbose);
|
||||
void coverage(bool flag) { m_coverageLine = m_coverageToggle = m_coverageUser = flag; }
|
||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||
bool suffixed(const char* sw, const char* arg);
|
||||
bool suffixed(const string& sw, const char* arg);
|
||||
string parseFileArg(const string& optdir, const string& relfilename);
|
||||
bool parseLangExt(const char* swp, const char* langswp, const V3LangCode& lc);
|
||||
string filePathCheckOneDir(const string& modname, const string& dirname);
|
||||
|
||||
static string getenvSYSTEMPERLGuts();
|
||||
|
||||
V3Options(const V3Options&); ///< N/A, no copy constructor
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
V3Options();
|
||||
@@ -239,6 +242,7 @@ class V3Options {
|
||||
bool ignc() const { return m_ignc; }
|
||||
bool inhibitSim() const { return m_inhibitSim; }
|
||||
bool reportUnoptflat() const { return m_reportUnoptflat; }
|
||||
bool vpi() const { return m_vpi; }
|
||||
bool xInitialEdge() const { return m_xInitialEdge; }
|
||||
bool xmlOnly() const { return m_xmlOnly; }
|
||||
|
||||
|
||||
+6
-6
@@ -363,7 +363,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
OrderClkMarkVisitor(AstNode* nodep) {
|
||||
explicit OrderClkMarkVisitor(AstNode* nodep) {
|
||||
m_hasClk = false;
|
||||
m_inClocked = false;
|
||||
m_inAss = false;
|
||||
@@ -410,7 +410,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
OrderClkAssVisitor(AstNode* nodep) {
|
||||
explicit OrderClkAssVisitor(AstNode* nodep) {
|
||||
m_clkAss = false;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -1265,7 +1265,7 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) {
|
||||
domainp->dumpTree(cout);
|
||||
cout<<endl;
|
||||
}
|
||||
newtreep->deleteTree(); newtreep=NULL;
|
||||
newtreep->deleteTree(); VL_DANGLING(newtreep);
|
||||
}
|
||||
}
|
||||
} // next input edgep
|
||||
@@ -1476,7 +1476,7 @@ void OrderVisitor::processMoveDoneOne(OrderMoveVertex* vertexp) {
|
||||
UINFO(9," Clear to "<<(toVertexp->inEmpty()?"[EMP] ":" ")
|
||||
<<toVertexp<<endl);
|
||||
// Delete this edge
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
edgep->unlinkDelete(); VL_DANGLING(edgep);
|
||||
if (toVertexp->inEmpty()) {
|
||||
// If destination node now has all inputs resolved; recurse to move that vertex
|
||||
// This is thus depth first (before width) which keeps the resulting executable's d-cache happy.
|
||||
@@ -1530,7 +1530,7 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
|
||||
nodep->unlinkFrBack();
|
||||
if (domainp == m_deleteDomainp) {
|
||||
UINFO(4," Ordering deleting pre-settled "<<nodep<<endl);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
} else {
|
||||
m_pomNewFuncp->addStmtsp(nodep);
|
||||
if (v3Global.opt.outputSplitCFuncs()) {
|
||||
@@ -1646,7 +1646,7 @@ void OrderVisitor::process() {
|
||||
m_graph.dumpDotFilePrefixed("orderg_done");
|
||||
if (0 && debug()) {
|
||||
string dfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_INT_order.tree";
|
||||
const auto_ptr<ofstream> logp (V3File::new_ofstream(dfilename));
|
||||
const VL_UNIQUE_PTR<ofstream> logp (V3File::new_ofstream(dfilename));
|
||||
if (logp->fail()) v3fatalSrc("Can't write "<<dfilename);
|
||||
m_graph.dump(*logp);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ struct OrderVEdgeType {
|
||||
}
|
||||
enum en m_e;
|
||||
inline OrderVEdgeType () : m_e(VERTEX_UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline OrderVEdgeType (en _e) : m_e(_e) {}
|
||||
explicit inline OrderVEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ void V3Os::setenvStr(const string& envvar, const string& value, const string& wh
|
||||
} else {
|
||||
UINFO(1,"export "<<envvar<<"="<<value<<endl);
|
||||
}
|
||||
#if defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
|
||||
#if !defined(__MINGW32__) && (defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L))
|
||||
setenv(envvar.c_str(),value.c_str(),true);
|
||||
#else
|
||||
//setenv() replaced by putenv() in MinGW/Solaris environment. Prototype is different
|
||||
|
||||
+96
-20
@@ -88,7 +88,7 @@ private:
|
||||
struct ModInfo {
|
||||
AstNodeModule* m_modp; // Module with specified name
|
||||
VarCloneMap m_cloneMap; // Map of old-varp -> new cloned varp
|
||||
ModInfo(AstNodeModule* modp) { m_modp=modp; }
|
||||
explicit ModInfo(AstNodeModule* modp) { m_modp=modp; }
|
||||
};
|
||||
typedef map<string,ModInfo> ModNameMap;
|
||||
ModNameMap m_modNameMap; // Hash of created module flavors by name
|
||||
@@ -108,6 +108,8 @@ private:
|
||||
typedef deque<AstCell*> CellList;
|
||||
CellList m_cellps; // Cells left to process (in this module)
|
||||
|
||||
string m_unlinkedTxt; // Text for AstUnlinkedRef
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
@@ -137,7 +139,7 @@ private:
|
||||
char ch = varp->user4()&255;
|
||||
string st = cvtToStr(ch);
|
||||
while (index) {
|
||||
st += cvtToStr(char((index%26)+'A'));
|
||||
st += cvtToStr(char((index%25)+'A'));
|
||||
index /= 26;
|
||||
}
|
||||
return st;
|
||||
@@ -146,7 +148,7 @@ private:
|
||||
// Given a compilcated object create a number to use for param module assignment
|
||||
// Ideally would be relatively stable if design changes (not use pointer value),
|
||||
// and must return same value given same input node
|
||||
// Return must presently be numberic so doesn't collide with 'small' alphanumeric parameter names
|
||||
// Return must presently be numeric so doesn't collide with 'small' alphanumeric parameter names
|
||||
ValueMap::iterator it = m_valueMap.find(nodep);
|
||||
if (it != m_valueMap.end()) {
|
||||
return cvtToStr(it->second);
|
||||
@@ -160,7 +162,8 @@ private:
|
||||
else { m_nextValueMap.insert(make_pair(bucket, offset + 1)); }
|
||||
int num = bucket + offset * BUCKETS;
|
||||
m_valueMap.insert(make_pair(nodep, num));
|
||||
return cvtToStr(num);
|
||||
// 'z' just to make sure we don't collide with a normal non-hashed number
|
||||
return (string)"z"+cvtToStr(num);
|
||||
}
|
||||
}
|
||||
void relinkPins(VarCloneMap* clonemapp, AstPin* startpinp) {
|
||||
@@ -248,6 +251,47 @@ private:
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (nodep->varp()) nodep->varp()->iterate(*this);
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
||||
nodep->varp(NULL); // Needs relink, as may remove pointed-to var
|
||||
}
|
||||
|
||||
virtual void visit(AstUnlinkedRef* nodep, AstNUser*) {
|
||||
AstVarXRef* varxrefp = nodep->op1p()->castVarXRef();
|
||||
AstNodeFTaskRef* taskrefp = nodep->op1p()->castNodeFTaskRef();
|
||||
if (varxrefp) {
|
||||
m_unlinkedTxt = varxrefp->dotted();
|
||||
} else if (taskrefp) {
|
||||
m_unlinkedTxt = taskrefp->dotted();
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unexpected AstUnlinkedRef node");
|
||||
return;
|
||||
}
|
||||
nodep->cellrefp()->iterate(*this);
|
||||
|
||||
if (varxrefp) {
|
||||
varxrefp->dotted(m_unlinkedTxt);
|
||||
} else {
|
||||
taskrefp->dotted(m_unlinkedTxt);
|
||||
}
|
||||
nodep->replaceWith(nodep->op1p()->unlinkFrBack());
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstCellArrayRef* nodep, AstNUser*) {
|
||||
V3Const::constifyParamsEdit(nodep->selp());
|
||||
if (AstConst* constp = nodep->selp()->castConst()) {
|
||||
string index = AstNode::encodeNumber(constp->toSInt());
|
||||
string replacestr = nodep->name() + "__BRA__??__KET__";
|
||||
size_t pos = m_unlinkedTxt.find(replacestr);
|
||||
if (pos == string::npos) {
|
||||
nodep->v3error("Could not find array index in unlinked text: '" << m_unlinkedTxt << "' for node: " << nodep);
|
||||
return;
|
||||
}
|
||||
m_unlinkedTxt.replace(pos, replacestr.length(), nodep->name() + "__BRA__"+index+"__KET__");
|
||||
} else {
|
||||
nodep->v3error("Could not expand constant selection inside dotted reference: "<<nodep->selp()->prettyName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate Statements
|
||||
virtual void visit(AstGenerate* nodep, AstNUser*) {
|
||||
@@ -262,7 +306,7 @@ private:
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstGenIf* nodep, AstNUser*) {
|
||||
UINFO(9," GENIF "<<nodep<<endl);
|
||||
@@ -283,7 +327,7 @@ private:
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
// Normal edit rules will now recurse the replacement
|
||||
} else {
|
||||
nodep->condp()->v3error("Generate If condition must evaluate to constant");
|
||||
@@ -310,7 +354,7 @@ private:
|
||||
string beginName = nodep->name();
|
||||
// Leave the original Begin, as need a container for the (possible) GENVAR
|
||||
// Note V3Unroll will replace some AstVarRef's to the loop variable with constants
|
||||
V3Unroll::unrollGen(forp, beginName); forp=NULL;
|
||||
V3Unroll::unrollGen(forp, beginName); VL_DANGLING(forp);
|
||||
// Blocks were constructed under the special begin, move them up
|
||||
// Note forp is null, so grab statements again
|
||||
if (AstNode* stmtsp = nodep->genforp()) {
|
||||
@@ -339,8 +383,7 @@ private:
|
||||
for (AstNode* ep = itemp->condsp(); ep; ) {
|
||||
AstNode* nextp = ep->nextp(); //May edit list
|
||||
ep->iterateAndNext(*this);
|
||||
V3Const::constifyParamsEdit(ep); ep=NULL; // ep may change
|
||||
// cppcheck-suppress redundantAssignment
|
||||
V3Const::constifyParamsEdit(ep); VL_DANGLING(ep); // ep may change
|
||||
ep = nextp;
|
||||
}
|
||||
}
|
||||
@@ -372,7 +415,7 @@ private:
|
||||
nodep->replaceWith(keepp);
|
||||
}
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
// Default: Just iterate
|
||||
@@ -382,7 +425,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ParamVisitor(AstNetlist* nodep) {
|
||||
explicit ParamVisitor(AstNetlist* nodep) {
|
||||
m_longId = 0;
|
||||
//
|
||||
nodep->accept(*this);
|
||||
@@ -431,9 +474,13 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
// Setting parameter to its default value. Just ignore it.
|
||||
// This prevents making additional modules, and makes coverage more
|
||||
// obvious as it won't show up under a unique module page name.
|
||||
} else {
|
||||
} else if (!constp->num().isDouble() && !constp->num().isString()
|
||||
&& !constp->num().isFourState() && !constp->num().isNegative()) {
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+constp->num().ascii(false);
|
||||
any_overrides = true;
|
||||
} else {
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+paramValueNumber(constp);
|
||||
any_overrides = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -442,16 +489,44 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
AstVar* modvarp = pinp->modVarp();
|
||||
if (modvarp->isIfaceRef()) {
|
||||
AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType();
|
||||
//UINFO(9," portIfaceRef "<<portIrefp<<endl);
|
||||
if (!pinp->exprp()
|
||||
|| !pinp->exprp()->castVarRef()
|
||||
|| !pinp->exprp()->castVarRef()->varp()
|
||||
|| !pinp->exprp()->castVarRef()->varp()->subDTypep()
|
||||
|| !pinp->exprp()->castVarRef()->varp()->subDTypep()->castIfaceRefDType()) {
|
||||
if (!portIrefp) {
|
||||
portIrefp = modvarp->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
}
|
||||
|
||||
AstIfaceRefDType* pinIrefp = NULL;
|
||||
AstNode* exprp = pinp->exprp();
|
||||
if (exprp
|
||||
&& exprp->castVarRef()
|
||||
&& exprp->castVarRef()->varp()
|
||||
&& exprp->castVarRef()->varp()->subDTypep()
|
||||
&& exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType())
|
||||
pinIrefp = exprp->castVarRef()->varp()->subDTypep()->castIfaceRefDType();
|
||||
else if (exprp
|
||||
&& exprp->op1p()
|
||||
&& exprp->op1p()->castVarRef()
|
||||
&& exprp->op1p()->castVarRef()->varp()
|
||||
&& exprp->op1p()->castVarRef()->varp()->subDTypep()
|
||||
&& exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()
|
||||
&& exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()
|
||||
&& exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType())
|
||||
pinIrefp = exprp->op1p()->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
else if (exprp
|
||||
&& exprp->castVarRef()
|
||||
&& exprp->castVarRef()->varp()
|
||||
&& exprp->castVarRef()->varp()->subDTypep()
|
||||
&& exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()
|
||||
&& exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()
|
||||
&& exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType())
|
||||
pinIrefp = exprp->castVarRef()->varp()->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
|
||||
UINFO(9," portIfaceRef "<<portIrefp<<endl);
|
||||
|
||||
if (!portIrefp) {
|
||||
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not an interface" << modvarp);
|
||||
} else if (!pinIrefp) {
|
||||
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not connected to interface/modport pin expression");
|
||||
} else {
|
||||
AstIfaceRefDType* pinIrefp = pinp->exprp()->castVarRef()->varp()->subDTypep()->castIfaceRefDType();
|
||||
//UINFO(9," pinIfaceRef "<<pinIrefp<<endl);
|
||||
UINFO(9," pinIfaceRef "<<pinIrefp<<endl);
|
||||
if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) {
|
||||
UINFO(9," IfaceRefDType needs reconnect "<<pinIrefp<<endl);
|
||||
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+paramValueNumber(pinIrefp);
|
||||
@@ -467,6 +542,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
} else {
|
||||
// If the name is very long, we don't want to overwhelm the filename limit
|
||||
// We don't do this always, as it aids debugability to have intuitive naming.
|
||||
// TODO can use new V3Name hash replacement instead of this
|
||||
string newname = longname;
|
||||
if (longname.length()>30) {
|
||||
LongMap::iterator iter = m_longMap.find(longname);
|
||||
|
||||
@@ -36,6 +36,7 @@ class V3Parse {
|
||||
private:
|
||||
V3ParseImp* m_impp;
|
||||
|
||||
V3Parse(const V3Parse&); ///< N/A, no copy constructor
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
// We must allow reading multiple files into one parser
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||
}
|
||||
if (ofp) {
|
||||
ofp->close();
|
||||
delete ofp; ofp = NULL;
|
||||
delete ofp; VL_DANGLING(ofp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ public:
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
V3ParseSym(AstNetlist* rootp)
|
||||
explicit V3ParseSym(AstNetlist* rootp)
|
||||
: m_syms(rootp) {
|
||||
s_anonNum = 0; // Number of next anonymous object
|
||||
pushScope(findNewTable(rootp));
|
||||
|
||||
+20
-9
@@ -58,6 +58,7 @@ static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l);
|
||||
%x DEFFORM
|
||||
%x DEFVAL
|
||||
%x DEFCMT
|
||||
%x STRIFY
|
||||
%x ARGMODE
|
||||
%x INCMODE
|
||||
%x PRTMODE
|
||||
@@ -80,8 +81,8 @@ drop [\032]
|
||||
/**************************************************************/
|
||||
%%
|
||||
|
||||
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext);
|
||||
return(VP_LINE); }
|
||||
<INITIAL,STRIFY>^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext);
|
||||
return(VP_LINE); }
|
||||
|
||||
/* Special directives we recognize */
|
||||
<INITIAL>"`define" { return(VP_DEFINE); }
|
||||
@@ -93,17 +94,15 @@ drop [\032]
|
||||
<INITIAL>"`include" { return(VP_INCLUDE); }
|
||||
<INITIAL>"`undef" { return(VP_UNDEF); }
|
||||
<INITIAL>"`undefineall" { return(VP_UNDEFINEALL); }
|
||||
|
||||
/* Optional directives we recognize */
|
||||
<INITIAL>"`__FILE__" { static string rtnfile;
|
||||
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
|
||||
<INITIAL,STRIFY>"`__FILE__" { static string rtnfile;
|
||||
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename();
|
||||
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
|
||||
return (VP_STRING); }
|
||||
<INITIAL>"`__LINE__" { static char buf[10];
|
||||
<INITIAL,STRIFY>"`__LINE__" { static char buf[10];
|
||||
sprintf(buf, "%d",LEXP->curFilelinep()->lineno());
|
||||
yytext = buf; yyleng = strlen(yytext);
|
||||
return (VP_TEXT); }
|
||||
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
|
||||
|
||||
/* Pass-through strings */
|
||||
<INITIAL>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
@@ -118,8 +117,20 @@ drop [\032]
|
||||
else return (VP_STRING); }
|
||||
|
||||
/* Stringification */
|
||||
<INITIAL>{tickquote} { return VP_STRIFY; }
|
||||
<INITIAL>"`\\`\"" { return VP_BACKQUOTE; }
|
||||
<INITIAL>{tickquote} { yy_push_state(STRIFY); return VP_STRIFY; }
|
||||
<STRIFY><<EOF>> { linenoInc(); yyerrorf("EOF in unterminated '\""); yyleng=0; yyterminate(); }
|
||||
<STRIFY>"`\\`\"" { return VP_BACKQUOTE; }
|
||||
<STRIFY>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
<STRIFY>{tickquote} { yy_pop_state(); return VP_STRIFY; }
|
||||
<STRIFY>{symbdef} { return (VP_SYMBOL); }
|
||||
<STRIFY>{symbdef}`` { yyleng-=2; return (VP_SYMBOL_JOIN); }
|
||||
<STRIFY>"`"{symbdef} { return (VP_DEFREF); }
|
||||
<STRIFY>"`"{symbdef}`` { yyleng-=2; return (VP_DEFREF_JOIN); }
|
||||
<STRIFY>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
||||
<STRIFY>{wsn}+ { return (VP_WHITE); }
|
||||
<STRIFY>{drop} { }
|
||||
<STRIFY>[\r] { }
|
||||
<STRIFY>. { return (VP_TEXT); }
|
||||
|
||||
/* Protected blocks */
|
||||
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
|
||||
|
||||
+1
-1
@@ -1074,7 +1074,7 @@ int V3PreProcImp::getStateToken() {
|
||||
out = defineSubst(refp);
|
||||
//NOP: out = m_preprocp->defSubstitute(out);
|
||||
}
|
||||
m_defRefs.pop(); refp=NULL;
|
||||
m_defRefs.pop(); VL_DANGLING(refp);
|
||||
if (m_defRefs.empty()) {
|
||||
statePop();
|
||||
if (!m_off) unputDefrefString(out);
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
PremitAssignVisitor(AstNodeAssign* nodep) {
|
||||
explicit PremitAssignVisitor(AstNodeAssign* nodep) {
|
||||
UINFO(4," PremitAssignVisitor on "<<nodep<<endl);
|
||||
m_noopt = false;
|
||||
nodep->accept(*this);
|
||||
@@ -383,7 +383,7 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
PremitVisitor(AstNetlist* nodep) {
|
||||
explicit PremitVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_funcp = NULL;
|
||||
m_stmtp = NULL;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user