Compare commits

...
57 Commits
Author SHA1 Message Date
Wilson Snyder bcc7045fc9 Version bump 2008-10-08 17:08:47 -04:00
Wilson Snyder 3b1929259a Support negative bit indexes.
Allow arbitrary characters in symbols (to make '-' work.)
Final merge from negative_lsb branch.
2008-10-06 09:59:22 -04:00
Wilson Snyder cdd6ea8e60 Fix genvars causing link error when using --public. 2008-09-30 08:58:07 -04:00
Wilson Snyder 4b8927af75 Expand environment variables in -f input files. 2008-09-29 15:51:45 -04:00
Wilson Snyder 0fba25c1b3 Commentary 2008-09-29 15:07:27 -04:00
Wilson Snyder f19ba9d54d Support negative bit indexes.
Tracing negative indexes requires latest Verilog-Perl and SystemPerl.
(Merged from negative_lsb branch.)
2008-09-24 07:43:08 -04:00
Wilson Snyder 8e9a0121ac Update test driver.pl: Allow -j auto determination, make logfile, don't require cd 2008-09-23 10:02:31 -04:00
Wilson Snyder bd6e8d808c Report error if port declaration is missing; bug32. 2008-09-23 09:35:00 -04:00
Wilson Snyder 11b9a631d4 Remove mis-committed debug print 2008-09-22 20:10:10 -04:00
Wilson Snyder f197dd29cb Suppress width warnings between constant strings and wider vectors. 2008-09-22 19:36:08 -04:00
Wilson Snyder daf7f42138 Version bump 2008-09-19 17:23:15 -04:00
Wilson Snyder dd487d4184 Fix t_psl_basic_cover test for new SystemPerl package 2008-09-19 08:00:02 -04:00
Wilson Snyder d90071637d SystemC uint64_t pins are now the default instead of sc_bv<64>.
Use --no-pins64 for backward compatibility.
2008-09-18 09:20:16 -04:00
Wilson Snyder d8efae2aba Rename t_bitsel_loop to t_select_loop to match other tests 2008-09-18 08:05:38 -04:00
Wilson Snyder 22543f3e19 Support arbitrary characters in identifiers and tracing. 2008-09-17 22:22:46 -04:00
Wilson Snyder 6aaef67e73 Fix test_verilated running under ncsim 2008-09-17 20:58:01 -04:00
Wilson Snyder 82a934d6fb Fix missing define to pass coverage down 2008-09-17 11:11:24 -04:00
Wilson Snyder eca6f2ca05 Increase bison max depth to prevent parse error 2008-09-17 11:11:09 -04:00
Wilson Snyder ef69f36403 More renames of asInt/toUInt where deemed correct 2008-09-04 11:03:46 -04:00
Wilson Snyder 99cf981c2f Support coverage under SystemPerl 1.285 and newer. 2008-09-04 09:43:53 -04:00
Wilson Snyder fc7a449f6d Rename asInt/asQuad to indicate signed/unsigned.
Internal code rename, no function change.
2008-09-03 17:40:01 -04:00
Wilson Snyder b7fafdafaa Fix never-true compiler warning [John Sanguinetti] 2008-08-22 17:32:29 -04:00
Wilson Snyder 8e180cfcde make install doesn't need source code 2008-08-20 16:05:24 -04:00
Wilson Snyder 4770fd39d2 Fix stack overflow on large ? : trees. 2008-08-20 15:59:10 -04:00
Wilson Snyder df107628c6 Fix default clocking syntax; covers go outside the block 2008-08-06 17:51:36 -04:00
Wilson Snyder 3463080a71 Fix extra evaluation of pure combo blocks in SystemC output. 2008-08-06 17:09:33 -04:00
Wilson Snyder 500dc2170f Support SystemVerilog "cover property" statements. 2008-08-06 12:52:39 -04:00
Wilson Snyder a76ae67a81 Add bisonpre for simplifing grammar and cleaning output 2008-08-06 12:35:34 -04:00
Wilson Snyder 1d091e49e1 Add VL_TIME_MULTIPLIER to allow sub-timeunit time printing 2008-08-05 14:45:20 -04:00
Wilson Snyder 2b63219cc6 Add IMPERFECTSCH warning, disabled by default. 2008-08-05 13:41:53 -04:00
Wilson Snyder f1b7762bef Add by-design and by-module subtotals to verilator_profcfunc. 2008-08-05 09:59:15 -04:00
Wilson Snyder 043ad86482 When warnings are disabled on signals that are flattened out, disable
the warnings on the signal(s) that replace it.
2008-08-01 15:30:17 -04:00
Wilson Snyder 74ca9578ed VERILATOR_BIN envvar should override adding _dbg to program name 2008-07-25 16:30:18 -04:00
Wilson Snyder d499161446 Fix typo in CASEWITHX 2008-07-23 08:58:48 -04:00
Wilson Snyder 34e8de56bc Version bump 2008-07-23 07:51:32 -04:00
Wilson Snyder 8a7864ebaa Add --Wfuture-, for improving forward compatibility. 2008-07-22 14:27:34 -04:00
Wilson Snyder 9e5fb5467f Add CASEZWITHX lint warning and if disabled fix handling of casez with Xs. 2008-07-22 13:07:19 -04:00
Wilson Snyder fb34bf7222 Fix lvalue errors with public functions; bug25. 2008-07-22 11:15:28 -04:00
Wilson Snyder 4591f35b7c Add --autoflush option 2008-07-16 14:06:08 -04:00
Wilson Snyder f0a06182ca Add --x-assign=fast, and make it the default. 2008-07-16 13:31:21 -04:00
Wilson Snyder d9e47a6293 Add WIDTH warning to etc file descriptors. 2008-07-14 17:15:26 -04:00
Wilson Snyder a555f87705 Fix missing verilator.1 during install. Bug#20. [Holger Wachtler] 2008-07-14 13:41:00 -04:00
Wilson Snyder 826b997166 Add . 2008-07-14 13:16:05 -04:00
Wilson Snyder d34bc6f304 Fix missing config_reg.h error when non-author .git repository 2008-07-14 10:48:57 -04:00
Wilson Snyder 5771ea48ef Fix IMPURE errors due to X-assignment temporary variables. 2008-07-14 10:42:58 -04:00
Wilson Snyder a4f3199427 Add informational warning when -Og is used 2008-07-02 06:48:50 -04:00
Wilson Snyder e6a43fc127 Fix verilator_includer not being installed into where verilated.mk.in expects 2008-07-01 16:10:09 -04:00
Wilson Snyder 701bd38d01 Add support for , . Bug14. 2008-07-01 14:15:10 -04:00
Wilson Snyder 1a8c8bec0d Rework $display/$write to go via new VL_WRITE function instead of
converting to pure C printf call.  This makes the resulting code smaller,
and allows sharing code with future $sprintf support.
2008-06-30 14:31:58 -04:00
Wilson Snyder 20aa21d4b6 Replace stdio.h and stdarg.h with C++ versions 2008-06-30 13:11:25 -04:00
Wilson Snyder 8c6adeb85a Internals: Convert to use common string convert routine 2008-06-30 07:10:23 -04:00
Wilson Snyder 09b7ba1317 Internal rework, no functionality change.
Rework V3EmitC to use a little template language for code to output,
similar to emitVerilog() functions.  Change all emitOperator() to
emitC(), elimate emitWordForm().
2008-06-29 20:02:24 -04:00
Wilson Snyder 0703843ac1 Support , . 2008-06-27 20:04:20 -04:00
Wilson Snyder d962dfe48c One or two digit octal escapes are legal 2008-06-27 17:52:45 -04:00
Wilson Snyder d6884db439 Support . 2008-06-27 11:36:25 -04:00
Wilson Snyder fdcbedef8f Add support 2008-06-27 08:45:05 -04:00
Wilson Snyder 8afd19648f Support 2008-06-26 08:52:02 -04:00
391 changed files with 5454 additions and 1638 deletions
+64 -1
View File
@@ -3,6 +3,69 @@ 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.680 2008/10/08
** Support negative bit indexes. [Stephane Laurent]
Tracing negative indexes requires latest Verilog-Perl and SystemPerl.
*** Suppress width warnings between constant strings and wider vectors.
[Rodney Sinclair]
**** Expand environment variables in -f input files. [Lawrence Butcher]
**** Report error if port declaration is missing; bug32. [Guy-Armand Kamendje]
**** Fix genvars causing link error when using --public. [Chris Candler]
* Verilator 3.671 2008/09/19
** SystemC uint64_t pins are now the default instead of sc_bv<64>.
Use --no-pins64 for backward compatibility.
*** Support SystemVerilog "cover property" statements.
*** When warnings are disabled on signals that are flattened out, disable
the warnings on the signal(s) that replace it.
*** Add by-design and by-module subtotals to verilator_profcfunc.
*** Fix extra evaluation of pure combo blocks in SystemC output.
**** Add IMPERFECTSCH warning, disabled by default.
**** Support coverage under SystemPerl 1.285 and newer.
**** Fix stack overflow on large ? : trees. [John Sanguinetti]
**** Support arbitrary characters in identifiers. [Stephane Laurent]
* Verilator 3.670 2008/07/23
** Add --x-assign=fast option, and make it the default.
This chooses performance over reset debugging. See the manual.
** Add --autoflush, for flushing streams after $display. [Steve Tong]
** Add CASEWITHX lint warning and if disabled fix handling of casez with Xs.
*** Add $feof, $fgetc, $fgets, $fflush, $fscanf, $sscanf. [Holger Waechtler]
*** Add $stime. [Holger Waechtler]
*** Add $random.
*** Add --Wfuture-, for improving forward compatibility.
**** Fix verilator_includer not being installed properly. [Holger Waechtler]
**** Fix IMPURE errors due to X-assignment temporary variables. [Steve Tong]
**** Fix "lvalue" errors with public functions; bug25. [CY Wang]
**** Add WIDTH warning to $fopen etc file descriptors.
**** Internal changes to how $displays get compiled and executed.
* Verilator 3.665 2008/06/25
**** Ignore "// verilator" comments alone on endif lines. [Rodney Sinclair]
@@ -17,7 +80,7 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix compile errors under Fedora 9, GCC 4.3.0. [by Jeremy Bennett]
**** Fix Makefile to find headers/libraries under prefix. [by Holger_Waechtler]
**** Fix Makefile to find headers/libraries under prefix. [by Holger Waechtler]
* Verilator 3.664 2008/05/08
+2
View File
@@ -15,6 +15,8 @@
/obj_dir/
/obj_dbg/
/obj_opt/
/INCA_libs/
/cov_work/
/logs/
Makefile
src/Makefile_obj
+10 -4
View File
@@ -110,13 +110,14 @@ DISTFILES_INC = $(INFOS) .gitignore COPYING *.in *.ac \
include/*.in \
include/.*ignore \
.*attributes */.*attributes */*/.*attributes \
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/*fix \
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
src/*.pl \
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
test_verilated/vgen*.pl \
test_regress/t/*.cpp \
test_regress/t/*.h \
test_regress/t/*.dat \
test_regress/t/*.mem \
test_regress/t/*.out \
test_regress/t/*.pl \
@@ -126,6 +127,7 @@ DISTFILES_INC = $(INFOS) .gitignore COPYING *.in *.ac \
INST_PROJ_FILES = \
bin/verilator \
bin/verilator_includer \
bin/verilator_profcfunc \
include/verilated.[chv]* \
include/verilated.mk \
include/verilatedos.[chv]* \
@@ -136,8 +138,10 @@ INST_PROJ_BIN_FILES = \
DISTFILES := $(DISTFILES_INC)
VL_INST_MAN_FILES = verilator.1
all: all_nomsg msg_test
all_nomsg: verilator_exe
all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
.PHONY:verilator_exe
verilator_exe verilator_bin verilator_bin_dbg:
@@ -221,6 +225,8 @@ README: readme.texi
# See uninstall also
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
verilator_includer verilator_profcfunc
# Some scripts go into both the search path and pkgdatadir,
# so they can be found by the user, and under $VERILATOR_ROOT.
installbin:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
( cd bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
@@ -228,8 +234,9 @@ installbin:
( cd bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
( cd bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
VL_INST_MAN_FILES = verilator.1
installman:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
for p in $(VL_INST_MAN_FILES) ; do \
@@ -239,7 +246,6 @@ installman:
installdata:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples
cp -r include $(DESTDIR)$(pkgdatadir)
cp -r src $(DESTDIR)$(pkgdatadir)
cp -r test_c $(DESTDIR)$(pkgdatadir)/examples
cp -r test_sc $(DESTDIR)$(pkgdatadir)/examples
cp -r test_sp $(DESTDIR)$(pkgdatadir)/examples
+152 -48
View File
@@ -100,8 +100,8 @@ sub verilator_bin {
my $bin = "";
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
$bin .= $ENV{VERILATOR_ROOT}."/" if defined($ENV{VERILATOR_ROOT});
$bin .= ($ENV{VERILATOR_BIN}||"verilator_bin");
if ($Debug) { $bin = "${bin}_dbg"; }
$bin .= ($ENV{VERILATOR_BIN}
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
return $bin;
}
@@ -177,6 +177,7 @@ descriptions in the next sections for more information.
{file.c/cc/cpp} Optional C++ files to link in
--assert Enable all assertions
--autoflush Flush streams after all $displays
--bin <filename> Override Verilator binary
--cc Create C++ output
--compiler <compiler-name> Tune for specified C++ compiler
@@ -201,13 +202,13 @@ descriptions in the next sections for more information.
--MP Create phony dependency targets
--Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes
--no-pins64 Don't use uint64_t's for 33-64 bit sigs
--no-skip-identical Disable skipping identical output
-O0 Disable optimizations
-O3 High performance optimizations
-O<optimization-letter> Selectable optimizations
--output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .ccp functions
--pins64 Use uint64_t's for 33-64 bit sigs
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--private Debugging; see docs
@@ -223,6 +224,7 @@ descriptions in the next sections for more information.
--underline-zero Zero signals with leading _'s
-v <filename> Verilog library
-Werror-<message> Convert warning to error
-Wfuture-<message> Disable unknown message warnings
-Wno-<message> Disable warning
-x-assign <mode> Initially assign Xs to this value
-y <dir> Directory to search for modules
@@ -252,6 +254,14 @@ linking with make rules you write yourself.
Enable all assertions, includes enabling the --psl flag. (If psl is not
desired, but other assertions are, use --assert --nopsl.)
See also --x-assign; setting "--x-assign unique" may be desirable.
=item --autoflush
After every $display or $fdisplay, flush the output stream. This insures
that messages will appear immediately but may reduce performance. Defaults
off, which will buffer output as provided by the normal C stdio calls.
=item --bin I<filename>
Rarely needed. Override the default filename for Verilator itself. When a
@@ -286,7 +296,7 @@ functions to avoid error C1061.
=item --coverage
Enables all forms of coverage, alias for --coverage-line, --coverage-user
Enables all forms of coverage, alias for --coverage-line, --coverage-user.
=item --coverage-line
@@ -298,10 +308,6 @@ Coverage. At each such branch a unique counter is incremented. At the end
of a test, the counters along with the filename and line number
corresponding to each counter are written into logs/coverage.pl.
After running multiple tests, the vcoverage utility (from the SystemPerl
package) is executed. Vcoverage reads the logs/coverage.pl file(s), and
creates an annotated source code listing showing code coverage details.
Verilator automatically disables coverage of branches that have a $stop in
them, as it is assumed $stop branches contain an error check that should
not occur. A /*verilator coverage_block_off*/ comment will perform a
@@ -311,10 +317,6 @@ Note Verilator may over-count combinatorial (non-clocked) blocks when those
blocks receive signals which have had the UNOPTFLAT warning disabled; for
most accurate results do not disable this warning when using coverage.
For an example, after running 'make test' in the Verilator distribution,
see the test_sp/logs/coverage_source directory. Grep for lines starting
with '%' to see what lines Verilator believes need more coverage.
=item --coverage-user
Enables user inserted functional coverage. Currently, all functional
@@ -411,6 +413,12 @@ be placed in this directory. If not specified, "obj_dir" is used.
Specifies the name to prepend to all lower level classes. Defaults to
the same as --prefix.
=item --no-pins64
Specifies SystemC outputs of 33-64 bits wide should use sc_bv's instead of
uint64_t's. Uint64's are faster, but sc_bvs were the default until
Verilator 3.671.
=item --no-skip-identical
Rarely needed. Disables skipping execution of Verilator if all source
@@ -452,11 +460,6 @@ operations, a new function will be created. With --output-split, this will
enable GCC to compile faster, at a small loss in performance that increases
with smaller statement values.
=item --pins64
Specifies SystemC outputs of 33-64 bits wide should use uint64_t instead of
the backward-compatible default of sc_bv's.
=item --prefix I<topname>
Specifies the name of the top level class and makefile. Defaults to V
@@ -547,6 +550,14 @@ Convert the specified warning message into a error message. This is
generally to discourage users from violating important site-wide rules, for
example C<-Werror-NOUNOPTFLAT>.
=item -Wfuture-I<message>
Suppress unknown Verilator comments or warning messages with the given
message code. This is used to allow code written with pragmas for a later
version of Verilator to run under a older version; add -Wfuture- arguments
for each message code or comment that the new version supports which the
older version does not support.
=item -Wno-I<message>
Disable the specified warning message.
@@ -554,26 +565,34 @@ Disable the specified warning message.
=item -Wno-lint
Disable all lint related warning messages. This is equivelent to
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CMPCONST
-Wno-IMPLICIT -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-VARHIDDEN
-Wno-WIDTH".
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEWITHX
-Wno-CMPCONST -Wno-IMPLICIT -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
-Wno-VARHIDDEN -Wno-WIDTH".
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
received from third parties.
=item -Wwarn-I<message>
Enables the specified warning message.
=item -x-assign 0
=item -x-assign 1
=item -x-assign unique (default)
=item -x-assign fast (default)
=item -x-assign unique
Controls the two-state value that is replaced when an assignment to X is
encountered. -x-assign=0 converts all Xs to 0s, this is the fastest.
-x-assign=1 converts all Xs to 1s, this is nearly as fast, but more likely
to find reset bugs as active high logic will fire. The default,
-x-assign=func will call a function to determine the value, this allows
randomization of all Xs and is the slowest, but safest.
encountered. -x-assign=fast, the default, converts all Xs to whatever is
best for performance. -x-assign=0 converts all Xs to 0s, and is also fast.
-x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
likely to find reset bugs as active high logic will fire. -x-assign=unique
will call a function to determine the value, this allows randomization of
all Xs to find reset bugs and is the slowest, but safest for finding reset
bugs in code.
=back
@@ -747,10 +766,10 @@ the test_sp directory in the distribution for an example.
=head1 BENCHMARKING & OPTIMIZATION
For best performance, run Verilator with the "-O3 -x-assign=0 --noassert"
flags. The -O3 flag will require longer compile times, and -x-assign=0 may
increase the risk of reset bugs in trade for performance; see the above
documentation for these flags.
For best performance, run Verilator with the "-O3 -x-assign=fast
--noassert" flags. The -O3 flag will require longer compile times, and
-x-assign=fast may increase the risk of reset bugs in trade for
performance; see the above documentation for these flags.
Minor Verilog code changes can also give big wins. You should not have any
UNOPTFLAT warnings from Verilator. Fixing these warnings can result in
@@ -955,11 +974,10 @@ Verilator will convert the top level module to a SC_MODULE. This module
will plug directly into a SystemC netlist.
The SC_MODULE gets the same pinout as the Verilog module, with the
following type conversions: Pins of a single bit become bool, unless they
are marked with `systemc_clock, in which case they become sc_clock's (for
SystemC 1.2, not needed in SystemC 2.0). Pins 2-32 bits wide become
uint32_t's. Pins 33-64 bits wide become sc_bv's or uint64_t's depending on
the -pins64 switch. Wider pins become sc_bv's.
following type conversions: Pins of a single bit become bool. Pins 2-32
bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or
uint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
(Uints simulate the fastest so are used where possible.)
Lower modules are not pure SystemC code. This is a feature, as using the
SystemC pin interconnect scheme everywhere would reduce performance by an
@@ -1024,7 +1042,8 @@ always_ff, always_latch, do-while, and final.
It also supports .name and .* interconnection.
Verilator partially supports assert.
Verilator partially supports concurrent assert and cover statements; see
the enclosed coverage tests for the syntax which is allowed.
=head1 SUGAR/PSL SUPPORT
@@ -1298,10 +1317,9 @@ Wide variables over 64 bits cannot be function returns, to avoid exposing
complexities. However, wide variables can be input/outputs; they will be
passed as references to an array of 32 bit numbers.
This feature is still somewhat experimental. Generally, only the values of
stored state (flops) should be written, as the model will NOT notice
changes made to variables in these functions. (Same as when a signal is
declared public.)
Generally, only the values of stored state (flops) should be written, as
the model will NOT notice changes made to variables in these functions.
(Same as when a signal is declared public.)
=item /*verilator public_flat*/ (variable)
@@ -1322,7 +1340,9 @@ using the --public switch.
=item /*verilator sc_clock*/
Used after a input declaration to indicate the signal should be declared in
SystemC as a sc_clock instead of a bool.
SystemC as a sc_clock instead of a bool. This was needed in SystemC 1.1
and 1.2 only; versions 2.0 and later do not require clock pins to be
sc_clocks and this is no longer needed.
=item /*verilator tracing_off*/
@@ -1535,8 +1555,8 @@ Verilator does not perform warning checking on uwires, it treats the uwire
keyword as if it were the normal wire keyword.
=item $bits, $countones, $error, $fatal, $finish, $info, $isunknown,
$onehot, $onehot0, $readmemb, $readmemh, $signed, $stop, $time, $unsigned,
$warning.
$onehot, $onehot0, $readmemb, $readmemh, $signed, $stime, $stop, $time,
$unsigned, $warning.
Generally supported.
@@ -1554,7 +1574,7 @@ them with a $write with the appropriate format specifier.
The rarely used optional parameter to $finish and $stop is ignored.
=item $fopen, $fclose, $fdisplay, $fwrite
=item $fopen, $fclose, $fdisplay, $feof, $fflush, $fgetc, $fgets, $fscanf, $fwrite
File descriptors passed to the file PLI calls must be file descriptors, not
MCDs, which includes the mode parameter to $fopen being mandatory.
@@ -1564,11 +1584,22 @@ are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a
reg [63:0] rather than an integer. The define `verilator_file_descriptor in
verilated.v can be used to hide this difference.
=item $fscanf, $sscanf
Only integer formats are supported; %e, %f, %m, %r, %v, and %z are not
supported.
=item $fullskew, $hold, $nochange, $period, $recovery, $recrem, $removal,
$setup, $setuphold, $skew, $timeskew, $width
All specify blocks and timing checks are ignored.
=item $random
$random does not support the optional argument to set the seed. Use the
srand function in C to accomplish this, and note there is only one random
number generator (not one per module).
=item $readmemb, $readmemh
Read memory commands should work properly. Note Verilator and the Verilog
@@ -1653,6 +1684,16 @@ L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item CASEWITHX
Warns that a case statement contains a constant with a C<x>. Verilator is
two-state so interpret such items as always false. Note a common error is
to use a C<X> in a case or casez statement item; often what the user
instead insteaded is to use a casez with C<?>.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item CMPCONST
Warns that you are comparing a value in a way that will always be constant.
@@ -1686,6 +1727,13 @@ additional ones.)
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item IMPERFECTSCH
Warns that the scheduling of the model is not absolutely perfect, and some
manual code edits may result in faster performance. This warning defaults
to off, and must be turned on explicitly before the top module statement is
processed.
=item IMPLICIT
Warns that a wire is being implicitly declared (it is a single bit wide
@@ -2049,6 +2097,24 @@ Verilator makes standard VCD (Value Change Dump) files. They are viewable
with the public domain Dinotrace or GtkWave programs, or any of the many
commercial offerings.
=item How do I do coverage analysis?
Verilator supports both block (line) coverage and user inserted functional
coverage. First, run verilator with the --coverage option. If you're
using your own makefile, compile the model with the GCC flag
-DSP_COVERAGE_ENABLE (if using Verilator's, it will do this for you.)
Run your tests in different directories. Each test will create a
logs/coverage.pl file.
After running all of your tests, the vcoverage utility (from the SystemPerl
package) is executed. Vcoverage reads the logs/coverage.pl file(s), and
creates an annotated source code listing showing code coverage details.
For an example, after running 'make test' in the Verilator distribution,
see the test_sp/logs/coverage_source directory. Grep for lines starting
with '%' to see what lines Verilator believes need more coverage.
=item Where is the translate_off command? (How do I ignore a construct?)
Translate on/off pragmas are generally a bad idea, as it's easy to have
@@ -2129,11 +2195,49 @@ uses one large symbol table, as that results in 2-3 less assembly
instructions for each signal access. This makes the execution time 10-15%
faster, but can result in more compilations when something changes.
=item How do I access functions/tasks in C?
Write a Verilog function or task with input/outputs that match what you
want to call in with C. Then mark that function public.
Verilog inputs of one bit become C++ bool inputs. Inputs 32 bits or
smaller become C uint32_t inputs, 64-32 bits become C uint64_t inputs, and
wider signals become arrays of 32 bits. Outputs are passed as references
to bool, uint32_t, uint64_t or uint32_t[] arrays.
Signals wider than 64 bits are passed as an array of 32-bit uint32_t's.
Thus to read bits 31:0, access signal[0], and for bits 63:32, access
signal[1]. Unused bits (for example bit numbers 65-96 of a 65 bit vector)
will always be zero. if you change the value you must make sure to pack
zeros in the unused bits or core-dumps may result. (Because Verilator
strips array bound checks where it believes them to be unnecessary.)
In the SYSTEMC example above, if you had in our.v:
task publicSetBool;
// verilator public
input in_bool;
var_bool = in_bool;
endtask
From the sc_main.cpp file, you'd then:
#include "Vour.h"
#include "Vour_our.h"
top->v->publicSetBool(value);
See additional notes under the /*verilator public*/ section.
=item How do I access signals in C?
First, declare the signals you will be accessing with a /*verilator
public*/ comment before the closing semicolon. Then scope into the C++
class to read the value of the signal, as you would any other member variable.
The best thing is to make a Verilator public task or function accessor that
can read or write that signal, as described in the previous FAQ. This will
allow Verilator to better optimize the model.
If you really want raw access to the signals, declare the signals you will
be accessing with a /*verilator public*/ comment before the closing
semicolon. Then scope into the C++ class to read the value of the signal,
as you would any other member variable.
Signals are the smallest of 8 bit chars, 16 bit shorts, 32 bit longs, or 64
bit long longs that fits the width of the signal. Generally, you can use
@@ -2155,7 +2259,7 @@ From the sc_main.cpp file, you'd then:
#include "Vour.h"
#include "Vour_our.h"
cout << "clock is " << top->v.clk << endl;
cout << "clock is " << top->v->clk << endl;
In this example, clk is a bool you can read or set as any other variable.
The value of normal signals may be set, though clocks shouldn't be changed
+41 -22
View File
@@ -1,18 +1,7 @@
: # -*-Mode: perl;-*- use perl, wherever it is
eval 'exec perl -wS $0 ${1+"$@"}'
if 0;
######################################################################
#
# Copyright 2007-2008 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
@@ -20,6 +9,7 @@ use warnings;
use Getopt::Long;
use IO::File;
use Pod::Usage;
eval { use Data::Dumper; $Data::Dumper::Indent = 1; }; # Debug, ok if missing
use strict;
use vars qw ($Debug);
@@ -76,7 +66,8 @@ sub profcfunc {
my %funcs;
while (defined (my $line=$fh->getline())) {
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+.*\s+(\S+)\s*$/) {
# %time cumesec selfsec calls {stuff} name
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
$funcs{$func}{pct} += $pct;
$funcs{$func}{sec} += $sec;
@@ -86,47 +77,75 @@ sub profcfunc {
$fh->close;
# Find modules
my %pointer_mods;
my %verilated_mods;
foreach my $func (keys %funcs) {
if ($func =~ /(.*)::_eval\(.*__Syms.*\)$/) {
if ($func =~ /(.*)::_eval\(([a-zA-Z_0-9]+__Syms).*\)$/) {
$verilated_mods{$1} = qr/^$1/;
$pointer_mods{$2} = $1;
}
}
#print Dumper(\%pointer_mods, \%verilated_mods);
# Resort by Verilog name
my %vfuncs;
my %groups;
foreach my $func (keys %funcs) {
my $pct = $funcs{$func}{pct};
my $vfunc = $func;
my $design;
if ($func =~ /\(([a-zA-Z_0-9]+__Syms)/) {
$design = $pointer_mods{$1};
}
foreach my $vde (keys %verilated_mods) {
last if $design;
if ($func =~ /$verilated_mods{$vde}/) {
$design=$vde;
last;
}
}
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) {
$vfunc = sprintf("VBlock %s:%d", $1, $2);
$groups{"Verilog Blocks under $design"} += $funcs{$func}{pct};
$groups{type}{"Verilog Blocks under $design"} += $pct;
$groups{design}{$design} += $pct;
$groups{module}{$1} += $pct;
} else {
if ($design) {
$vfunc = sprintf("VCommon %s", $func);
$groups{"Common code under $design"} += $funcs{$func}{pct};
$groups{type}{"Common code under $design"} += $pct;
$groups{design}{$design} += $pct;
$groups{module}{$design." common code"} += $pct;
} else {
$vfunc = sprintf("C++ %s", $func);
$groups{'C++'} += $funcs{$func}{pct};
$groups{type}{'C++'} += $pct;
$groups{design}{'C++'} += $pct;
$groups{module}{'C++'} += $pct;
}
}
$vfuncs{$vfunc} = $funcs{$func};
}
print("Overall summary:\n");
print(" % time\n");
foreach (sort (keys %groups)) {
printf(" %6.2f In all %s\n", $groups{$_}, $_);
foreach my $type qw(type design module) {
my $missing = 100;
foreach (sort (keys %{$groups{$type}})) {
$missing -= $groups{$type}{$_};
}
if ($missing) {
$groups{$type}{"\377Unaccounted for/rounding error"} = $missing;
}
print("Overall summary by $type:\n");
printf(" %-6s %s\n","% time",$type);
foreach my $what (sort (keys %{$groups{$type}})) {
(my $pwhat = $what) =~ s/^\377//; # Just used to establish sort order
printf(" %6.2f %s\n", $groups{$type}{$what}, $pwhat);
}
print("\n");
}
print("Verilog code profile:\n");
print(" These are split into three categories:\n");
+465 -77
View File
@@ -23,8 +23,7 @@
//=========================================================================
#include "verilated.h"
#include <string.h>
#include <ctype.h>
#include <cctype>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
@@ -80,23 +79,43 @@ IData VL_RAND32() {
#endif
}
IData VL_RAND_RESET_I(int outBits) {
IData VL_RANDOM_I(int obits) {
return VL_RAND32() & VL_MASK_I(obits);
}
QData VL_RANDOM_Q(int obits) {
QData data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
return data & VL_MASK_Q(obits);
}
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) {
if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = VL_RAND32();
} else {
outwp[i] = VL_RAND32() & VL_MASK_I(obits);
}
}
return outwp;
}
IData VL_RAND_RESET_I(int obits) {
if (Verilated::randReset()==0) return 0;
IData data = ~0;
if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RAND32();
data = VL_RANDOM_I(obits);
}
if (outBits<32) data &= VL_MASK_I(outBits);
if (obits<32) data &= VL_MASK_I(obits);
return data;
}
QData VL_RAND_RESET_Q(int outBits) {
QData VL_RAND_RESET_Q(int obits) {
if (Verilated::randReset()==0) return 0;
QData data = VL_ULL(~0);
if (Verilated::randReset()!=1) { // if 2, randomize
data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
data = VL_RANDOM_Q(obits);
}
if (outBits<64) data &= VL_MASK_Q(outBits);
if (obits<64) data &= VL_MASK_Q(obits);
return data;
}
@@ -119,94 +138,368 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
//===========================================================================
// Formatting
const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld) {
// Convert value into %b/%o/%x/%s/%u/%d formatted string
// Note uses a single buffer; presumes only one call per printf
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
char* strp = &str[0];
int lsb=obits-1;
if (drop0) while (lsb && !VL_BITISSET_Q(ld,lsb)) lsb--;
switch (fmt) {
case 'd':
sprintf(str,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(obits,obits,ld)));
return str;
case 'u':
sprintf(str,"%llu",ld);
return str;
case 's':
for (; lsb>=0; lsb--) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xff;
*strp++ = (charval==0)?' ':charval;
}
*strp++ = '\0';
return str;
case 'b':
for (; lsb>=0; lsb--) {
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 1) + '0';
}
*strp++ = '\0';
return str;
case 'o':
for (; lsb>=0; lsb--) {
lsb = (lsb / 3) * 3; // Next digit
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 7) + '0';
}
*strp++ = '\0';
return str;
default:
for (; lsb>=0; lsb--) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xf;
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
}
*strp++ = '\0';
return str;
}
*strp++ = '\0';
return str;
}
// Do a va_arg returning a quad, assuming input argument is anything less than wide
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp) {
// Convert value into %b/%o/%x/%s/%u/%d formatted string
// Note uses a single buffer; presumes only one call per printf
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
char* strp = &str[0];
int lsb=obits-1;
if (drop0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
void _vl_vsformat(string& output, const char* formatp, va_list ap) {
// Format a Verilog $write style format into the output list
// The format must be pre-processed (and lower cased) by Verilator
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
//
// Note uses a single buffer internally; presumes only one usage per printf
// Note also assumes variables < 64 are not wide, this assumption is
// sometimes not true in low-level routines written here in verilated.cpp
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
bool inPct = false;
bool widthSet = false;
int width = 0;
const char* pos = formatp;
for (; *pos; ++pos) {
if (!inPct && pos[0]=='%') {
inPct = true;
widthSet = false;
width = 0;
} else if (!inPct) { // Normal text
// Fast-forward to next escape and add to output
const char *ep = pos;
while (ep[0] && ep[0]!='%') ep++;
if (ep != pos) {
output += string(pos, ep-pos);
pos += ep-pos-1;
}
} else { // Format character
inPct = false;
char fmt = pos[0];
switch (fmt) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
inPct = true; // Get more digits
widthSet = true;
width = width*10 + (fmt - '0');
break;
case '%':
output += '%';
break;
case 'S': { // "C" string
const char* cstrp = va_arg(ap, const char*);
output += cstrp;
break;
}
default: {
// Deal with all read-and-print somethings
const int lbits = va_arg(ap, int);
QData ld = 0;
WDataInP lwp;
if (lbits <= VL_QUADSIZE) {
WData qlwp[2];
ld = _VL_VA_ARG_Q(ap, lbits);
VL_SET_WQ(qlwp,ld);
lwp = qlwp;
} else {
lwp = va_arg(ap,WDataInP);
ld = lwp[0];
if (fmt == 'u' || fmt == 'd') fmt = 'x'; // Not supported, but show something
}
int lsb=lbits-1;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
switch (fmt) {
case 'c': {
IData charval = ld & 0xff;
output += charval;
break;
}
case 's':
for (; lsb>=0; lsb--) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
*strp++ = (charval==0)?' ':charval;
output += (charval==0)?' ':charval;
}
break;
case 'd': { // Signed decimal
int digits=sprintf(tmp,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
output += tmp;
break;
}
case 'u': { // Unsigned decimal
int digits=sprintf(tmp,"%llu",ld);
int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
output += tmp;
break;
}
case 't': { // Time
int digits;
if (VL_TIME_MULTIPLIER==1) {
digits=sprintf(tmp,"%llu",ld);
} else if (VL_TIME_MULTIPLIER==1000) {
digits=sprintf(tmp,"%llu.%03llu",
(QData)(ld/VL_TIME_MULTIPLIER),
(QData)(ld%VL_TIME_MULTIPLIER));
} else {
vl_fatal(__FILE__,__LINE__,"","%%Error: Unsupported VL_TIME_MULTIPLIER");
}
int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
output += tmp;
break;
}
*strp++ = '\0';
return str;
case 'b':
for (; lsb>=0; lsb--) {
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
}
*strp++ = '\0';
return str;
break;
case 'o':
for (; lsb>=0; lsb--) {
lsb = (lsb / 3) * 3; // Next digit
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 7) + '0';
// Octal numbers may span more than one wide word,
// so we need to grab each bit separately and check for overrun
// Octal is rare, so we'll do it a slow simple way
output += ('0'
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0)
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+1)) ? 2 : 0)
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
}
*strp++ = '\0';
return str;
default:
break;
case 'x':
for (; lsb>=0; lsb--) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
output += "0123456789abcdef"[charval];
}
*strp++ = '\0';
return str;
break;
default:
string msg = string("%%Error: Unknown _vl_vsformat code: ")+pos[0]+"\n";
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
break;
} // switch
}
*strp++ = '\0';
return str;
} // switch
}
}
}
static inline bool _vl_vsss_eof(FILE* fp, int& floc) {
return fp ? feof(fp) : (floc<0);
}
static inline void _vl_vsss_advance(FILE* fp, int& floc) {
if (fp) fgetc(fp);
else floc -= 8;
}
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
// Get a character without advancing
if (fp) {
int data = fgetc(fp);
if (data == EOF) return EOF;
ungetc(data,fp);
return data;
} else {
if (floc < 0) return EOF;
floc = floc & ~7; // Align to closest character
int data = (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
return data;
}
}
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp) {
while (1) {
int c = _vl_vsss_peek(fp, floc, fromp);
if (c==EOF || !isspace(c)) return;
_vl_vsss_advance(fp, floc);
}
}
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp,
char* tmpp, const char* acceptp) {
// Read into tmp, consisting of characters from acceptp list
char* cp = tmpp;
while (1) {
int c = _vl_vsss_peek(fp, floc, fromp);
if (c==EOF || isspace(c)) break;
if (acceptp!=NULL // String - allow anything
&& NULL==strchr(acceptp, c)) break;
if (acceptp!=NULL) c = tolower(c); // Non-strings we'll simplify
*cp++ = c;
_vl_vsss_advance(fp, floc);
}
*cp++ = '\0';
//VL_PRINTF("\t_read got='%s'\n", tmpp);
}
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits, IData ld) {
for (; nbits && lsb<obits; nbits--, lsb++, ld>>=1) {
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
}
}
IData _vl_vsscanf(FILE* fp, // If a fscanf
int fbits, WDataInP fromp, // Else if a sscanf
const char* formatp, va_list ap) {
// Read a Verilog $sscanf/$fscanf style format into the output list
// The format must be pre-processed (and lower cased) by Verilator
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
int floc = fbits - 1;
IData got = 0;
bool inPct = false;
const char* pos = formatp;
for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) {
//VL_PRINTF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc, _vl_vsss_peek(fp,floc,fromp));
if (!inPct && pos[0]=='%') {
inPct = true;
} else if (!inPct && isspace(pos[0])) { // Format spaces
while (isspace(pos[1])) pos++;
_vl_vsss_skipspace(fp,floc,fromp);
} else if (!inPct) { // Expected Format
_vl_vsss_skipspace(fp,floc,fromp);
int c = _vl_vsss_peek(fp,floc,fromp);
if (c != pos[0]) goto done;
else _vl_vsss_advance(fp,floc);
} else { // Format character
// Skip loading spaces
inPct = false;
char fmt = pos[0];
switch (fmt) {
case '%': {
int c = _vl_vsss_peek(fp,floc,fromp);
if (c != '%') goto done;
else _vl_vsss_advance(fp,floc);
break;
}
default: {
// Deal with all read-and-scan somethings
// Note LSBs are preserved if there's an overflow
const int obits = va_arg(ap, int);
int lsb = 0;
WData qowp[2];
WDataOutP owp = qowp;
if (obits > VL_QUADSIZE) {
owp = va_arg(ap,WDataOutP);
}
for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = 0;
switch (fmt) {
case 'c': {
int c = _vl_vsss_peek(fp,floc,fromp);
if (c==EOF) goto done;
else _vl_vsss_advance(fp,floc);
owp[0] = c;
break;
}
case 's': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
}
break;
}
case 'd': { // Signed decimal
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
if (!tmp[0]) goto done;
vlsint64_t ld;
sscanf(tmp,"%lld",&ld);
VL_SET_WQ(owp,ld);
break;
}
case 't': // FALLTHRU // Time
case 'u': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
if (!tmp[0]) goto done;
QData ld;
sscanf(tmp,"%llu",&ld);
VL_SET_WQ(owp,ld);
break;
}
case 'b': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "01xz?_");
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
switch(tmp[pos]) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb++; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, 1, 1); lsb++; break;
case '_': break;
}
}
break;
}
case 'o': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xz?_");
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
switch(tmp[pos]) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb+=3; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, 3, 1); lsb+=3; break;
case '2': _vl_vsss_setbit(owp,obits,lsb, 3, 2); lsb+=3; break;
case '3': _vl_vsss_setbit(owp,obits,lsb, 3, 3); lsb+=3; break;
case '4': _vl_vsss_setbit(owp,obits,lsb, 3, 4); lsb+=3; break;
case '5': _vl_vsss_setbit(owp,obits,lsb, 3, 5); lsb+=3; break;
case '6': _vl_vsss_setbit(owp,obits,lsb, 3, 6); lsb+=3; break;
case '7': _vl_vsss_setbit(owp,obits,lsb, 3, 7); lsb+=3; break;
case '_': break;
}
}
break;
}
case 'x': {
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefxz?_");
if (!tmp[0]) goto done;
int pos = strlen(tmp)-1;
for (int i=0; i<obits && pos>=0; pos--) {
switch(tmp[pos]) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb+=4; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, 4, 1); lsb+=4; break;
case '2': _vl_vsss_setbit(owp,obits,lsb, 4, 2); lsb+=4; break;
case '3': _vl_vsss_setbit(owp,obits,lsb, 4, 3); lsb+=4; break;
case '4': _vl_vsss_setbit(owp,obits,lsb, 4, 4); lsb+=4; break;
case '5': _vl_vsss_setbit(owp,obits,lsb, 4, 5); lsb+=4; break;
case '6': _vl_vsss_setbit(owp,obits,lsb, 4, 6); lsb+=4; break;
case '7': _vl_vsss_setbit(owp,obits,lsb, 4, 7); lsb+=4; break;
case '8': _vl_vsss_setbit(owp,obits,lsb, 4, 8); lsb+=4; break;
case '9': _vl_vsss_setbit(owp,obits,lsb, 4, 9); lsb+=4; break;
case 'a': _vl_vsss_setbit(owp,obits,lsb, 4, 10); lsb+=4; break;
case 'b': _vl_vsss_setbit(owp,obits,lsb, 4, 11); lsb+=4; break;
case 'c': _vl_vsss_setbit(owp,obits,lsb, 4, 12); lsb+=4; break;
case 'd': _vl_vsss_setbit(owp,obits,lsb, 4, 13); lsb+=4; break;
case 'e': _vl_vsss_setbit(owp,obits,lsb, 4, 14); lsb+=4; break;
case 'f': _vl_vsss_setbit(owp,obits,lsb, 4, 15); lsb+=4; break;
case '_': break;
}
}
break;
}
default:
string msg = string("%%Error: Unknown _vl_vsscanf code: ")+pos[0]+"\n";
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
break;
} // switch
got++;
// Reload data if non-wide (if wide, we put it in the right place directly)
if (obits <= VL_BYTESIZE) {
CData* p = va_arg(ap,CData*); *p = owp[0];
} else if (obits <= VL_SHORTSIZE) {
SData* p = va_arg(ap,SData*); *p = owp[0];
} else if (obits <= VL_WORDSIZE) {
IData* p = va_arg(ap,IData*); *p = owp[0];
} else if (obits <= VL_QUADSIZE) {
QData* p = va_arg(ap,QData*); *p = VL_SET_QW(owp);
}
}
} // switch
}
}
done:
return got;
}
//===========================================================================
@@ -228,6 +521,40 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
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) {
// Convert C string to Verilog format
int bytes = VL_BYTES_I(obits);
char* op = ((char*)(destp));
if (srclen > bytes) srclen = bytes; // Don't overflow destination
int i;
for (i=0; i<srclen; i++) { *op++ = srcp[srclen-1-i]; }
for (; i<bytes; i++) { *op++ = 0; }
}
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
FILE* fp = VL_CVT_Q_FP(fpq);
if (VL_UNLIKELY(!fp)) return 0;
// The string needs to be padded with 0's in unused spaces in front of
// any read data. This means we can't know in what location the first
// character will finally live, so we need to copy. Yuk.
IData bytes = VL_BYTES_I(obits);
char buffer[bytes];
// We don't use fgets, as we must read \0s.
IData got = 0;
char* cp = buffer;
while (got < bytes) {
int c = getc(fp);
if (c==EOF) break;
*cp++ = c; got++;
if (c=='\n') break;
}
_VL_STRING_TO_VINT(obits, destp, got, buffer);
return got;
}
QData VL_FOPEN_QI(QData filename, IData mode) {
IData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode);
@@ -240,6 +567,67 @@ QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
return VL_CVT_FP_Q(fopen(filenamez,modez));
}
void VL_WRITEF(const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
string output;
_vl_vsformat(output, formatp, ap);
va_end(ap);
// Users can redefine VL_PRINTF if they wish.
VL_PRINTF("%s", output.c_str());
}
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq);
if (VL_UNLIKELY(!fp)) return;
va_list ap;
va_start(ap,formatp);
string output;
_vl_vsformat(output, formatp, ap);
va_end(ap);
fputs(output.c_str(), fp);
}
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq);
if (VL_UNLIKELY(!fp)) return 0;
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(fp, 0, NULL, formatp, ap);
va_end(ap);
return got;
}
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
IData fnw[2]; VL_SET_WI(fnw, ld);
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
va_end(ap);
return got;
}
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
IData fnw[2]; VL_SET_WQ(fnw, ld);
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
va_end(ap);
return got;
}
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, lbits, lwp, formatp, ap);
va_end(ap);
return got;
}
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData ofilename, void* memp, IData start, IData end) {
IData fnw[2]; VL_SET_WQ(fnw, ofilename);
+33 -18
View File
@@ -29,11 +29,11 @@
#include "verilatedos.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cassert>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
@@ -179,21 +179,21 @@ extern void vl_fatal (const char* filename, int linenum, const char* hier,
const char* msg);
//=========================================================================
// Extern functions -- Init time only, so slow is fine
// Extern functions -- Slow path
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
/// Init time only, so slow is fine
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
/// Return string with formated Verilog value
extern const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp);
extern const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld);
inline const char* VL_VALUE_FORMATTED_I(int obits, char fmt, bool drop0, IData ld) {
return VL_VALUE_FORMATTED_Q(obits,fmt,drop0,ld);
}
/// File I/O
extern IData VL_FGETS_IXQ(int sbits, void* strgp, QData fpq);
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
@@ -206,6 +206,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
IData ofilename, void* memp, IData start, IData end) {
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
//=========================================================================
// Base macros
@@ -213,9 +221,12 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
/// Create two 32-bit words from quadword
#define VL_SET_WQ(decl,data) { decl[0]=(data); decl[1]=((data)>>VL_WORDSIZE); }
#define VL_SET_WQ(owp,data) { owp[0]=(data); owp[1]=((data)>>VL_WORDSIZE); }
#define VL_SET_WI(owp,data) { owp[0]=(data); owp[1]=0; }
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
// Use a union to avoid cast-to-different-size warnings
/// Return FILE* from QData
@@ -244,13 +255,17 @@ static inline void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
//=========================================================================
// Pli macros
#ifndef VL_TIME_MULTIPLIER
# define VL_TIME_MULTIPLIER 1
#endif
/// Return current simulation time
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
# define VL_TIME_I(ign) ((IData)sc_time_stamp().to_default_time_units())
# define VL_TIME_Q(ign) ((QData)sc_time_stamp().to_default_time_units())
# define VL_TIME_I(ign) ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q(ign) ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
#else
# define VL_TIME_I(ign) ((IData)sc_time_stamp())
# define VL_TIME_Q(ign) ((QData)sc_time_stamp())
# define VL_TIME_I(ign) ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q(ign) ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
extern double sc_time_stamp();
#endif
+1
View File
@@ -28,6 +28,7 @@ VK_CPPFLAGS_ALWAYS += \
-I$(VERILATOR_ROOT)/include \
-DVL_PRINTF=printf \
-DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
VK_CPPFLAGS_WALL += -Wall \
+4
View File
@@ -110,10 +110,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
//=========================================================================
// Integer size macros
#define VL_BYTESIZE 8 ///< Bits in a byte
#define VL_SHORTSIZE 16 ///< Bits in a short
#define VL_WORDSIZE 32 ///< Bits in a word
#define VL_QUADSIZE 64 ///< Bits in a quadword
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
/// Bytes this number of bits needs (1 bit=1 byte)
#define VL_BYTES_I(nbits) (((nbits)+(VL_BYTESIZE-1))/VL_BYTESIZE)
/// Words this number of bits needs (1 bit=1 word)
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
+1 -12
View File
@@ -1,16 +1,5 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
+1 -12
View File
@@ -1,16 +1,5 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/perl -w
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
use strict;
#======================================================================
# main
delete $ENV{MODULE_VERSION};
_setup_modules();
module('add','cadence_verif');
exec('iccr',@ARGV);
#######################################################################
# Modules package
sub _setup_modules {
# Load the 'module' command into the environment
my $init = "/sicortex/$ENV{DIRPROJECT_ARCH}/lib/Modules/default/init/perl";
(-f $init) or die "%Error: Script not found: $init,";
require $init;
}
#######################################################################
__END__
=pod
=head1 NAME
invoke_iccr - Invoke tool under "modules" command
=head1 SYNOPSIS
invoke_iccr {ncv arguments}
=head1 DESCRIPTION
=head1 DISTRIBUTION
Copyright 2007-2008 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License or the Perl Artistic License.
=head1 AUTHORS
Wilson Snyder <[email protected]>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./invoke_iccr -help"
### End:
+1 -12
View File
@@ -1,16 +1,5 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2007-2008 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
+1 -12
View File
@@ -1,16 +1,5 @@
#!/usr/bin/perl -w
######################################################################
#
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
# program is free software; you can redistribute it and/or modify it under
# the terms of either the GNU Lesser General Public License or the Perl
# Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See copyright, etc in below POD section.
######################################################################
require 5.006_001;
+5 -1
View File
@@ -46,6 +46,10 @@ export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
export OBJCACHE := @objcache --read --write
endif
UNDER_GIT = $(wildcard ../.git)
#*********************************************************************
obj_opt:
mkdir $@
obj_dbg:
@@ -71,7 +75,7 @@ dbg: ../verilator_bin_dbg
prefiles::
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
prefiles:: config_rev.h
# This output goes into srcdir, as we need to distribute it as part of the kit.
config_rev.h: config_rev.pl ../.git/index
+3 -5
View File
@@ -31,7 +31,6 @@ LEX = @LEX@
LFLAGS = -d
PERL = @PERL@
YACC = @YACC@
YFLAGS = -y -d -v
prefix = @prefix@
@@ -98,6 +97,7 @@ endif
HEADERS = $(wildcard V*.h v*.h)
ASTGEN = $(srcdir)/astgen
BISONPRE = $(srcdir)/bisonpre
######################################################################
#### Top level
@@ -254,11 +254,9 @@ V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
y.tab.h: y.tab.c
# Have only one output file in this rule to prevent parallel make issues
y.tab.c: verilog.y $(HEADERS)
y.tab.c: verilog.y $(HEADERS) bisonpre
@echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer."
${YACC} ${YFLAGS} $<
mv y.tab.c y_pregen.tab.c && $(PERL) $(srcdir)/bisonfix < y_pregen.tab.c > y.tab.c
mv y.tab.h y_pregen.tab.h && $(PERL) $(srcdir)/bisonfix < y_pregen.tab.h > y.tab.h
$(PERL) $(BISONPRE) --yacc ${YACC} -d -v -o y.tab.c $<
V3Lexer_pregen.yy.cpp: verilog.l y.tab.h $(HEADERS)
${LEX} ${LFLAGS} -o$@ $<
+2 -2
View File
@@ -32,8 +32,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
+2 -2
View File
@@ -29,8 +29,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+23 -5
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
@@ -43,6 +43,7 @@ private:
// STATE
AstModule* m_modp; // Last module
AstBegin* m_beginp; // Last begin
V3Double0 m_statAsCover; // Statistic tracking
V3Double0 m_statAsPsl; // Statistic tracking
V3Double0 m_statAsFull; // Statistic tracking
@@ -100,9 +101,11 @@ private:
return bodysp;
}
void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) {
void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep,
AstNode* stmtsp, const string& message) {
propp->unlinkFrBack();
sentreep->unlinkFrBack();
if (stmtsp) stmtsp->unlinkFrBack();
//
AstNode* bodysp = NULL;
bool selfDestruct = false;
@@ -126,6 +129,7 @@ private:
} else {
nodep->v3fatalSrc("Unknown node type");
}
if (stmtsp) bodysp = bodysp->addNext(stmtsp);
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
@@ -232,12 +236,15 @@ private:
virtual void visit(AstPslCover* nodep, AstNUser*) {
nodep->iterateChildren(*this);
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
nodep->stmtsp(), nodep->name()); nodep=NULL;
m_statAsCover++;
}
virtual void visit(AstPslAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this);
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
NULL, nodep->name()); nodep=NULL;
m_statAsPsl++;
}
virtual void visit(AstVAssert* nodep, AstNUser*) {
@@ -253,6 +260,16 @@ private:
// Reset defaults
m_modp = NULL;
}
virtual void visit(AstBegin* nodep, AstNUser*) {
// This code is needed rather than a visitor in V3Begin,
// because V3Assert is called before V3Begin
AstBegin* lastp = m_beginp;
{
m_beginp = nodep;
nodep->iterateChildren(*this);
}
m_beginp = lastp;
}
// VISITORS //========== Temporal Layer
@@ -268,6 +285,7 @@ private:
public:
// CONSTRUCTORS
AssertVisitor(AstNetlist* nodep) {
m_beginp = NULL;
m_modp = NULL;
// Process
AstNode::userClearTree(); // userp() used on entire tree
+38 -12
View File
@@ -23,8 +23,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
@@ -56,10 +56,17 @@ private:
// Return NULL for always
AstSenTree* newp = NULL;
AstSenItem* senip = m_senip ? m_senip : m_seniDefaultp;
if (senip) newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
if (!senip) nodep->v3error("Unsupported: Unclocked assertion");
if (!senip) {
nodep->v3error("Unsupported: Unclocked assertion");
newp = new AstSenTree(nodep->fileline(), NULL);
} else {
newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
}
return newp;
}
void clearAssertInfo() {
m_senip = NULL;
}
// VISITORS //========== Statements
virtual void visit(AstPslDefClock* nodep, AstNUser*) {
@@ -70,28 +77,47 @@ private:
nodep->unlinkFrBack();
pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstClocking* nodep, AstNUser*) {
UINFO(8," CLOCKING"<<nodep<<endl);
// Store the new default clock, reset on new module
m_seniDefaultp = nodep->sensesp();
// Trash it, keeping children
if (nodep->bodysp()) {
nodep->replaceWith(nodep->bodysp()->unlinkFrBack());
} else {
nodep->unlinkFrBack();
}
pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstPslCover* nodep, AstNUser*) {
// Prep
m_senip = NULL;
if (nodep->sentreep()) return; // Already processed
clearAssertInfo();
nodep->iterateChildren(*this);
nodep->sentreep(newSenTree(nodep));
m_senip = NULL;
clearAssertInfo();
}
virtual void visit(AstPslAssert* nodep, AstNUser*) {
// Prep
m_senip = NULL;
if (nodep->sentreep()) return; // Already processed
clearAssertInfo();
nodep->iterateChildren(*this);
nodep->sentreep(newSenTree(nodep));
m_senip = NULL;
clearAssertInfo();
}
virtual void visit(AstPslClocked* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (m_senip) {
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion\n");
}
// Unlink and just keep a pointer to it, convert to sentree as needed
// Block is the new expression to evaluate
AstNode* blockp = nodep->propp()->unlinkFrBack();
if (nodep->disablep()) {
blockp = new AstAnd(nodep->disablep()->fileline(),
new AstNot(nodep->disablep()->fileline(),
nodep->disablep()->unlinkFrBack()),
blockp);
}
// Unlink and just keep a pointer to it, convert to sentree as needed
m_senip = nodep->sensesp();
nodep->replaceWith(blockp);
pushDeletep(nodep); nodep=NULL;
@@ -108,8 +134,8 @@ private:
public:
// CONSTRUCTORS
AssertPreVisitor(AstNetlist* nodep) {
m_senip = NULL;
m_seniDefaultp = NULL;
clearAssertInfo();
// Process
nodep->accept(*this);
}
+56 -15
View File
@@ -18,8 +18,8 @@
//
//*************************************************************************
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <fstream>
#include <iomanip>
#include <memory>
@@ -85,17 +85,40 @@ void AstNode::init() {
string AstNode::encodeName(const string& namein) {
string name2 = namein;
string out;
for (string::iterator pos = name2.begin(); pos != name2.end(); pos++) {
if (pos[0]=='_' && pos[1]=='_') {
out += "__ULUL_";
const char* start = name2.c_str();
for (const char* pos = start; *pos; pos++) {
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers
: isalnum(pos[0])) {
out += pos[0];
} else if (pos[0]=='_') {
if (pos[1]=='_') {
out += "_"; out += "__5F"; // hex(_) = 0x5F
pos++;
} else {
out += pos[0];
}
} else if (pos[0]=='.') {
out += "__DOT__";
} else if (pos[0]=='[') {
out += "__BRA__";
} else if (pos[0]==']') {
out += "__KET__";
} else {
char hex[10]; sprintf(hex,"%02X",pos[0]);
out += "__"; out += hex;
}
}
return out;
}
string AstNode::encodeNumber(vlsint64_t num) {
if (num < 0) {
return "__2D"+cvtToStr(-num); // 2D=-
} else {
return cvtToStr(num);
}
}
string AstNode::shortName() const {
string pretty = name();
string::size_type pos;
@@ -116,19 +139,37 @@ string AstNode::dedotName(const string& namein) {
}
string AstNode::prettyName(const string& namein) {
string pretty = namein;
string::size_type pos;
while ((pos=pretty.find("__BRA__")) != string::npos) {
pretty.replace(pos, 7, "[");
string pretty;
string name2 = namein;
pretty = "";
for (const char* pos = name2.c_str(); *pos; ) {
if (0==strncmp(pos,"__BRA__",7)) {
pretty += "[";
pos += 7;
}
while ((pos=pretty.find("__KET__")) != string::npos) {
pretty.replace(pos, 7, "]");
else if (0==strncmp(pos,"__KET__",7)) {
pretty += "]";
pos += 7;
}
while ((pos=pretty.find("__PVT__")) != string::npos) {
pretty.replace(pos, 7, "");
else if (0==strncmp(pos,"__DOT__",7)) {
pretty += ".";
pos += 7;
}
else if (0==strncmp(pos,"__PVT__",7)) {
pretty += "";
pos += 7;
}
else if (pos[0]=='_' && pos[1]=='_' && isxdigit(pos[2]) && isxdigit(pos[3])) {
char value = 0;
value += 16*(isdigit(pos[2]) ? (pos[2]-'0') : (tolower(pos[2])-'a'+10));
value += (isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
pretty += value;
pos += 4;
}
else {
pretty += pos[0];
pos++;
}
while ((pos=pretty.find("__ULUL_")) != string::npos) {
pretty.replace(pos, 7, "");
}
return AstNode::dedotName(pretty);
}
+25 -5
View File
@@ -197,7 +197,8 @@ public:
TRIWIRE,
BLOCKTEMP,
MODULETEMP,
STMTTEMP
STMTTEMP,
XTEMP
};
enum en m_e;
inline AstVarType () {};
@@ -209,7 +210,7 @@ public:
"?","GPARAM","LPARAM","GENVAR",
"INTEGER","INPUT","OUTPUT","INOUT",
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","REG","TRIWIRE",
"BLOCKTEMP","MODULETEMP","STMTTEMP"};
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
return names[m_e];};
};
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
@@ -250,6 +251,25 @@ public:
//######################################################################
class AstCaseType {
public:
enum en {
CASE,
CASEX,
CASEZ
};
enum en m_e;
inline AstCaseType () {};
inline AstCaseType (en _e) : m_e(_e) {};
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {};
operator en () const { return m_e; };
};
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); }
//######################################################################
class AstDisplayType {
public:
enum en {
@@ -559,6 +579,7 @@ public:
static string dedotName(const string& namein); // Name with dots removed
static string prettyName(const string& namein); // Name for printing out to the user
static string encodeName(const string& namein); // Encode user name into internal C representation
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
string prettyName() const { return prettyName(name()); }
FileLine* fileline() const { return m_fileline; }
int width() const { return m_width; }
@@ -651,7 +672,6 @@ public:
virtual bool same(AstNode* otherp) const { return true; }
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
virtual bool broken() const { return false; }
virtual bool emitWordForm() { return false; }
// INVOKERS
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
@@ -682,7 +702,7 @@ struct AstNodeMath : public AstNode {
virtual ~AstNodeMath() {}
// METHODS
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
virtual string emitOperator() = 0;
virtual string emitC() = 0;
virtual string emitSimpleOperator() { return ""; }
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
};
@@ -784,7 +804,7 @@ struct AstNodeCond : public AstNodeTriop {
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
virtual string emitVerilog() { return "%k(%l %k? %r %k: %t)"; }
virtual string emitOperator() { return "VL_COND"; }
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
virtual bool cleanLhs() { return true; }
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
+8 -4
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <fstream>
#include <iomanip>
#include <vector>
@@ -43,11 +43,11 @@ void AstNodeVarRef::cloneRelink() {
}
int AstNodeSel::bitConst() const {
AstConst* constp=bitp()->castConst(); return (constp?constp->asInt():0);
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
}
bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp()));
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
}
bool AstVar::isScQuad() const {
@@ -417,3 +417,7 @@ void AstCCall::dump(ostream& str) {
funcp()->dump(str);
}
}
void AstCFunc::dump(ostream& str) {
this->AstNode::dump(str);
if (slow()) str<<" [SLOW]";
}
+281 -134
View File
@@ -50,12 +50,13 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string name() const { return num().ascii(); } // * = Value
virtual const V3Number& num() const { return m_num; } // * = Value
uint32_t asInt() const { return num().asInt(); }
vluint64_t asQuad() const { return num().asQuad(); }
uint32_t toUInt() const { return num().toUInt(); }
vlsint32_t toSInt() const { return num().toSInt(); }
vluint64_t toUQuad() const { return num().toUQuad(); }
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { return true; }
virtual V3Hash sameHash() const { return V3Hash(num().asHash()); }
virtual V3Hash sameHash() const { return V3Hash(num().toHash()); }
virtual bool same(AstNode* samep) const {
return num().isCaseEq(samep->castConst()->num()); }
virtual int instrCount() const { return widthInstrs(); }
@@ -78,10 +79,10 @@ struct AstRange : public AstNode {
AstRange* cloneTree(bool cloneNextLink) { return AstNode::cloneTree(cloneNextLink)->castRange(); }
AstNode* msbp() const { return op2p()->castNode(); } // op2 = Msb expression
AstNode* lsbp() const { return op3p()->castNode(); } // op3 = Lsb expression
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->asInt():0); }
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->asInt():0); }
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->toSInt():0); }
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->toSInt():0); }
int elementsConst() const { return msbConst()-lsbConst()+1; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
};
@@ -100,7 +101,7 @@ struct AstArraySel : public AstNodeSel {
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
V3ERROR_NA; /* How can from be a const? */ }
virtual string emitVerilog() { return "%k(%l%k[%r])"; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { return "%li%k[%ri]"; }
virtual bool cleanOut() { return true; }
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -133,7 +134,7 @@ struct AstWordSel : public AstNodeSel {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k(%l[%r])"; } // Not %k, as usually it's a small constant rhsp
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp
virtual bool cleanOut() { return true; }
virtual bool cleanLhs() { return true; } virtual bool cleanRhs() { return true; }
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -192,7 +193,7 @@ struct AstSel : public AstNodeTriop {
// Children: varref|arraysel, math, constant math
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
:AstNodeTriop(fl, fromp, lsbp, widthp) {
if (widthp->castConst()) width(widthp->castConst()->asInt(), widthp->castConst()->asInt());
if (widthp->castConst()) width(widthp->castConst()->toUInt(), widthp->castConst()->toUInt());
}
AstSel(FileLine* fl, AstNode* fromp, int lsbp, int bitwidth)
:AstNodeTriop(fl, fromp,
@@ -204,9 +205,12 @@ struct AstSel : public AstNodeTriop {
virtual AstNode* clone() { return new AstSel(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) {
out.opRange(from, bit.asInt()+width.asInt()-1, bit.asInt()); }
out.opRange(from, bit.toUInt()+width.toUInt()-1, bit.toUInt()); }
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() {
return this->widthp()->isOne()
? "VL_BITSEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri)"
: "VL_SEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
virtual bool cleanOut() { return false; }
virtual bool cleanLhs() { return true;} virtual bool cleanRhs() {return true;}
virtual bool cleanThs() {return true;}
@@ -218,9 +222,9 @@ struct AstSel : public AstNodeTriop {
AstNode* fromp() const { return op1p()->castNode(); } // op1 = Extracting what (NULL=TBD during parsing)
AstNode* lsbp() const { return op2p()->castNode(); } // op2 = Msb selection expression
AstNode* widthp() const { return op3p()->castNode(); } // op3 = Width
uint32_t lsbConst() const { return lsbp()->castConst()->asInt(); }
uint32_t widthConst() const { return widthp()->castConst()->asInt(); }
uint32_t msbConst() const { return lsbConst()+widthConst()-1; }
int widthConst() const { return widthp()->castConst()->toSInt(); }
int lsbConst() const { return lsbp()->castConst()->toSInt(); }
int msbConst() const { return lsbConst()+widthConst()-1; }
};
struct AstVar : public AstNode {
@@ -332,9 +336,10 @@ public:
bool isSignal() const { return (varType()==AstVarType::WIRE || varType()==AstVarType::IMPLICIT
|| varType()==AstVarType::REG || varType()==AstVarType::INTEGER); }
bool isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
|| varType()==AstVarType::STMTTEMP); }
|| varType()==AstVarType::STMTTEMP || varType()==AstVarType::XTEMP); }
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
bool isPure() const { return (varType()==AstVarType::XTEMP); }
bool isParam() const { return (varType()==AstVarType::LPARAM || varType()==AstVarType::GPARAM); }
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
bool isGenVar() const { return (varType()==AstVarType::GENVAR); }
@@ -358,8 +363,9 @@ public:
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
int widthAlignBytes() const; // Structure alignment 1,2,4 or 8 bytes (arrays affect this)
int widthTotalBytes() const; // Width in bytes rounding up 1,2,4,8,12,...
uint32_t msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
uint32_t lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); }
int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
int lsb() const { if (!rangep()) return 0; return rangep()->lsbConst(); }
int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index
uint32_t arrayElements() const; // 1, or total multiplication of all dimensions
virtual string verilogKwd() const;
void propagateAttrFrom(AstVar* fromp) {
@@ -531,7 +537,7 @@ public:
&& varp()->name()==samep->castVarRef()->varp()->name()); }
virtual int instrCount() const { return widthInstrs()*(lvalue()?1:instrCountLd()); }
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { return true; }
};
@@ -559,7 +565,7 @@ public:
string inlinedDots() const { return m_inlinedDots; }
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { return true; }
virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()),V3Hash(dotted())); }
@@ -792,7 +798,7 @@ public:
virtual V3Hash sameHash() const { return V3Hash(m_expect); }
virtual bool same(AstNode* samep) const { return expect() == samep->castParseRef()->expect(); }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
AstParseRefExp expect() const { return m_expect; }
// op1 = Components
AstNode* lhsp() const { return op1p(); } // op1 = List of statements
@@ -808,7 +814,7 @@ struct AstDot : public AstNode {
virtual AstNode* clone() { return new AstDot(*this);}
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
AstNode* lhsp() const { return op1p(); }
AstNode* rhsp() const { return op2p(); }
};
@@ -1191,11 +1197,11 @@ struct AstCase : public AstNodeCase {
// exprp Children: MATHs
// casesp Children: CASEITEMs
private:
bool m_casex; // True if casex instead of normal case.
AstCaseType m_casex; // 0=case, 1=casex, 2=casez
bool m_fullPragma; // Synthesis full_case
bool m_parallelPragma; // Synthesis parallel_case
public:
AstCase(FileLine* fileline, bool casex, AstNode* exprp, AstNode* casesp)
AstCase(FileLine* fileline, AstCaseType casex, AstNode* exprp, AstNode* casesp)
: AstNodeCase(fileline, exprp, casesp) {
m_casex=casex;
m_fullPragma=false; m_parallelPragma=false;
@@ -1204,11 +1210,14 @@ public:
virtual AstType type() const { return AstType::CASE;}
virtual AstNode* clone() { return new AstCase(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string verilogKwd() const { return casex()?"casex":"case"; }
bool casex() const { return m_casex; }
virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; }
virtual bool same(AstNode* samep) const {
return m_casex==samep->castCase()->m_casex; }
bool casex() const { return m_casex==AstCaseType::CASEX; }
bool casez() const { return m_casex==AstCaseType::CASEZ; }
bool fullPragma() const { return m_fullPragma; }
bool parallelPragma() const { return m_parallelPragma; }
void fullPragma(bool flag) { m_fullPragma=flag; }
bool parallelPragma() const { return m_parallelPragma; }
void parallelPragma(bool flag) { m_parallelPragma=flag; }
};
@@ -1323,6 +1332,101 @@ struct AstFOpen : public AstNodeStmt {
AstNode* modep() const { return op3p(); }
};
struct AstFFlush : public AstNodeStmt {
// Parents: stmtlist
// Children: file which must be a varref
AstFFlush(FileLine* fileline, AstNode* filep)
: AstNodeStmt (fileline) {
setNOp2p(filep);
}
virtual ~AstFFlush() {}
virtual AstType type() const { return AstType::FFLUSH;}
virtual AstNode* clone() { return new AstFFlush(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string verilogKwd() const { return "$fflush"; };
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isSplittable() const { return false; }
virtual bool isOutputter() const { return true; }
virtual bool isUnlikely() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
};
struct AstFScanF : public AstNodeMath {
// Parents: expr
// Children: file which must be a varref
// Children: varrefs to load
private:
string m_text;
public:
AstFScanF(FileLine* fileline, const string& text, AstNode* filep, AstNode* exprsp)
: AstNodeMath (fileline), m_text(text) {
addNOp1p(exprsp);
setNOp2p(filep);
}
virtual ~AstFScanF() {}
virtual AstType type() const { return AstType::FSCANF;}
virtual AstNode* clone() { return new AstFScanF(*this); }
virtual string name() const { return m_text; }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string verilogKwd() const { return "$fscanf"; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isSplittable() const { return false; } // SPECIAL: has 'visual' ordering
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
virtual bool cleanOut() { return false; }
virtual V3Hash sameHash() const { return V3Hash(text()); }
virtual bool same(AstNode* samep) const {
return text()==samep->castFScanF()->text(); }
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
string text() const { return m_text; } // * = Text to display
void text(const string& text) { m_text=text; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
};
struct AstSScanF : public AstNodeMath {
// Parents: expr
// Children: file which must be a varref
// Children: varrefs to load
private:
string m_text;
public:
AstSScanF(FileLine* fileline, const string& text, AstNode* fromp, AstNode* exprsp)
: AstNodeMath (fileline), m_text(text) {
addNOp1p(exprsp);
setOp2p(fromp);
}
virtual ~AstSScanF() {}
virtual AstType type() const { return AstType::SSCANF;}
virtual AstNode* clone() { return new AstSScanF(*this); }
virtual string name() const { return m_text; }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string verilogKwd() const { return "$sscanf"; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isSplittable() const { return false; } // SPECIAL: has 'visual' ordering
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
virtual bool cleanOut() { return false; }
virtual V3Hash sameHash() const { return V3Hash(text()); }
virtual bool same(AstNode* samep) const {
return text()==samep->castSScanF()->text(); }
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
string text() const { return m_text; } // * = Text to display
void text(const string& text) { m_text=text; }
AstNode* fromp() const { return op2p(); }
void fromp(AstNode* nodep) { setOp2p(nodep); }
};
struct AstReadMem : public AstNodeStmt {
private:
bool m_isHex; // readmemh, not readmemb
@@ -1451,9 +1555,8 @@ struct AstChangeXor : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opChangeXor(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l ^ %r)"; }
virtual string emitOperator() { return "VL_CHANGEXOR"; }
virtual string emitC() { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "^"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;} // Lclean && Rclean
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -1592,8 +1695,8 @@ struct AstTraceDecl : public AstNodeStmt {
private:
string m_showname; // Name of variable
uint32_t m_code; // Trace identifier code; converted to ASCII by trace routines
uint32_t m_lsb; // Property of var the trace details
uint32_t m_msb; // Property of var the trace details
int m_lsb; // Property of var the trace details
int m_msb; // Property of var the trace details
uint32_t m_arrayLsb; // Property of var the trace details
uint32_t m_arrayMsb; // Property of var the trace details
uint32_t m_codeInc; // Code increment
@@ -1621,8 +1724,8 @@ public:
uint32_t code() const { return m_code; }
void code(uint32_t code) { m_code=code; }
uint32_t codeInc() const { return m_codeInc; }
uint32_t msb() const { return m_msb; }
uint32_t lsb() const { return m_lsb; }
int msb() const { return m_msb; }
int lsb() const { return m_lsb; }
uint32_t arrayMsb() const { return m_arrayMsb; }
uint32_t arrayLsb() const { return m_arrayLsb; }
uint32_t arrayWidth() const { if (!arrayMsb()) return 0; return arrayMsb()-arrayLsb()+1; }
@@ -1745,14 +1848,21 @@ struct AstScopeName : public AstNode {
struct AstRand : public AstNodeTermop {
// Return a random number, based upon width()
AstRand(FileLine* fl, int wwidth) : AstNodeTermop(fl) {
width(wwidth,wwidth); }
private:
bool m_reset; // Random reset, versus always random
public:
AstRand(FileLine* fl, int wwidth, bool reset) : AstNodeTermop(fl) {
width(wwidth,wwidth); m_reset=reset; }
AstRand(FileLine* fl) : AstNodeTermop(fl), m_reset(false) { }
virtual ~AstRand() {}
virtual AstType type() const { return AstType::RAND;}
virtual AstNode* clone() { return new AstRand(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string emitVerilog() { return "$random"; }
virtual string emitOperator() { return "VL_RAND_RESET"; }
virtual string emitC() {
return (m_reset ?
"VL_RAND_RESET_%nq(%nw, %P)"
:"VL_RANDOM_%nq(%nw, %P)"); }
virtual bool cleanOut() { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
@@ -1769,7 +1879,7 @@ struct AstTime : public AstNodeTermop {
virtual AstNode* clone() { return new AstTime(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string emitVerilog() { return "$time"; }
virtual string emitOperator() { return "VL_TIME"; }
virtual string emitC() { return "VL_TIME_%nq()"; }
virtual bool cleanOut() { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
@@ -1791,7 +1901,7 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual bool cleanOut() { return false; }
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
AstNode* bodysp() const { return op1p()->castNode(); } // op1= expressions to print
virtual bool isSplittable() const { return false; } // SPECIAL: User may order w/other sigs
virtual bool isOutputter() const { return true; }
@@ -1815,8 +1925,7 @@ struct AstUnaryMin : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); }
virtual string emitVerilog() { return "%k(- %l)"; }
virtual string emitOperator() { return "VL_UNARYMIN"; }
virtual bool emitWordForm() { return true; }
virtual string emitC() { return "VL_UNARYMIN_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return true;}
};
@@ -1829,7 +1938,7 @@ struct AstRedAnd : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
virtual string emitVerilog() { return "%k(& %l)"; }
virtual string emitOperator() { return "VL_REDAND"; }
virtual string emitC() { return "VL_REDAND_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
};
@@ -1842,8 +1951,7 @@ struct AstRedOr : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
virtual string emitVerilog() { return "%k(| %l)"; }
virtual string emitOperator() { return "VL_REDOR"; }
virtual bool emitWordForm() { return true; }
virtual string emitC() { return "VL_REDOR_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
};
@@ -1856,8 +1964,7 @@ struct AstRedXor : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
virtual string emitVerilog() { return "%k(^ %l)"; }
virtual string emitOperator() { return "VL_REDXOR"; }
virtual bool emitWordForm() { return true; }
virtual string emitC() { return "VL_REDXOR_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return (lhsp()->width()!=1 && lhsp()->width()!=2 && lhsp()->width()!=4
&& lhsp()->width()!=8 && lhsp()->width()!=16);}
@@ -1874,8 +1981,7 @@ struct AstRedXnor : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
virtual string emitVerilog() { return "%k(~^ %l)"; }
virtual string emitOperator() { v3fatalSrc("REDXNOR should have became REDXOR"); return ""; }
virtual bool emitWordForm() { return true; }
virtual string emitC() { v3fatalSrc("REDXNOR should have became REDXOR"); return ""; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
@@ -1890,7 +1996,7 @@ struct AstLogNot : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLogNot(lhs); }
virtual string emitVerilog() { return "%k(! %l)"; }
virtual string emitOperator() { return "VL_LOGNOT"; }
virtual string emitC() { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; }
virtual string emitSimpleOperator() { return "!"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
@@ -1904,9 +2010,8 @@ struct AstNot : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNot(lhs); }
virtual string emitVerilog() { return "%k(~ %l)"; }
virtual string emitOperator() { return "VL_NOT"; }
virtual string emitC() { return "VL_NOT_%lq(%lW, %P, %li)"; }
virtual string emitSimpleOperator() { return "~"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return true;}
};
@@ -1919,7 +2024,7 @@ struct AstExtend : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
virtual string emitVerilog() { return "%l"; }
virtual string emitOperator() { return "VL_EXTEND"; }
virtual string emitC() { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} // Because the EXTEND operator self-casts
virtual int instrCount() const { return 0; }
@@ -1933,7 +2038,7 @@ struct AstExtendS : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opExtendS(lhs); }
virtual string emitVerilog() { return "%l"; }
virtual string emitOperator() { return "VL_EXTENDS"; }
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} // Because the EXTEND operator self-casts
virtual int instrCount() const { return 0; }
@@ -1950,7 +2055,7 @@ struct AstSigned : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
virtual string emitVerilog() { return "%k$signed(%l)"; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
virtual int instrCount() const { return 0; }
@@ -1966,7 +2071,7 @@ struct AstUnsigned : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
virtual string emitVerilog() { return "%k$unsigned(%l)"; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
virtual int instrCount() const { return 0; }
@@ -1979,8 +2084,7 @@ struct AstCLog2 : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opCLog2(lhs); }
virtual string emitVerilog() { return "%k$clog2(%l)"; }
virtual bool emitWordForm() { return true; }
virtual string emitOperator() { return "VL_CLOG2"; }
virtual string emitC() { return "VL_CLOG2_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*16; }
@@ -1994,8 +2098,7 @@ struct AstCountOnes : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opCountOnes(lhs); }
virtual string emitVerilog() { return "%k$countones(%l)"; }
virtual bool emitWordForm() { return true; }
virtual string emitOperator() { return "VL_COUNTONES"; }
virtual string emitC() { return "VL_COUNTONES_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*16; }
@@ -2010,7 +2113,7 @@ struct AstIsUnknown : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIsUnknown(lhs); }
virtual string emitVerilog() { return "%k$isunknown(%l)"; }
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
};
@@ -2024,8 +2127,7 @@ struct AstOneHot : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot(lhs); }
virtual string emitVerilog() { return "%k$onehot(%l)"; }
virtual bool emitWordForm() { return true; }
virtual string emitOperator() { return "VL_ONEHOT"; }
virtual string emitC() { return "VL_ONEHOT_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*4; }
@@ -2040,8 +2142,7 @@ struct AstOneHot0 : public AstNodeUniop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot0(lhs); }
virtual string emitVerilog() { return "%k$onehot0(%l)"; }
virtual bool emitWordForm() { return true; }
virtual string emitOperator() { return "VL_ONEHOT0"; }
virtual string emitC() { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*3; }
@@ -2066,7 +2167,7 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
virtual string emitVerilog() { return "%k$_CAST(%l)"; }
virtual string emitOperator() { return "VL_CAST"; }
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
virtual V3Hash sameHash() const { return V3Hash(size()); }
@@ -2076,6 +2177,37 @@ public:
int size() const { return m_size; }
};
struct AstFEof : public AstNodeUniop {
AstFEof(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
virtual ~AstFEof() {}
virtual AstType type() const { return AstType::FEOF;}
virtual AstNode* clone() { return new AstFEof(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k$feof(%l)"; }
virtual string emitC() { return "(%li ? feof(VL_CVT_Q_FP(%li)) : true)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*16; }
AstNode* filep() const { return lhsp(); }
};
struct AstFGetC : public AstNodeUniop {
AstFGetC(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
virtual ~AstFGetC() {}
virtual AstType type() const { return AstType::FEOF;}
virtual AstNode* clone() { return new AstFGetC(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k$fgetc(%l)"; }
// Non-existant filehandle returns EOF
virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_FP(%li)) : -1)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*64; }
AstNode* filep() const { return lhsp(); }
};
//======================================================================
// Binary ops
@@ -2088,7 +2220,7 @@ struct AstLogOr : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogOr(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k|| %r)"; }
virtual string emitOperator() { return "VL_LOGOR"; }
virtual string emitC() { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "||"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
@@ -2104,7 +2236,7 @@ struct AstLogAnd : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogAnd(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k&& %r)"; }
virtual string emitOperator() { return "VL_LOGAND"; }
virtual string emitC() { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "&&"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
@@ -2120,7 +2252,7 @@ struct AstLogIf : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k(%l %k-> %r)"; }
virtual string emitOperator() { return "VL_LOGIF"; }
virtual string emitC() { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "->"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
@@ -2136,7 +2268,7 @@ struct AstLogIff : public AstNodeBiCom {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k(%l %k<-> %r)"; }
virtual string emitOperator() { return "VL_LOGIFF"; }
virtual string emitC() { return "VL_LOGIFF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "<->"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
@@ -2152,9 +2284,8 @@ struct AstOr : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opOr(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k| %r)"; }
virtual string emitOperator() { return "VL_OR"; }
virtual string emitC() { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "|"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean && Rclean
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2168,9 +2299,8 @@ struct AstAnd : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAnd(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k& %r)"; }
virtual string emitOperator() { return "VL_AND"; }
virtual string emitC() { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "&"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean || Rclean
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2184,9 +2314,8 @@ struct AstXor : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXor(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k^ %r)"; }
virtual string emitOperator() { return "VL_XOR"; }
virtual string emitC() { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "^"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;} // Lclean && Rclean
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2200,9 +2329,8 @@ struct AstXnor : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXnor(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k^ ~ %r)"; }
virtual string emitOperator() { return "VL_XNOR"; }
virtual string emitC() { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "^ ~"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2216,9 +2344,8 @@ struct AstEq : public AstNodeBiCom {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k== %r)"; }
virtual string emitOperator() { return "VL_EQ"; }
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2232,9 +2359,8 @@ struct AstNeq : public AstNodeBiCom {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k!= %r)"; }
virtual string emitOperator() { return "VL_NEQ"; }
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2248,9 +2374,8 @@ struct AstLt : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLt(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k< %r)"; }
virtual string emitOperator() { return "VL_LT"; }
virtual string emitC() { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "<"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2264,9 +2389,8 @@ struct AstLtS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k< %r)"; }
virtual string emitOperator() { return "VL_LTS"; }
virtual string emitC() { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
virtual bool emitWordForm() { return false; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2281,9 +2405,8 @@ struct AstGt : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGt(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k> %r)"; }
virtual string emitOperator() { return "VL_GT"; }
virtual string emitC() { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ">"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2297,9 +2420,8 @@ struct AstGtS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k> %r)"; }
virtual string emitOperator() { return "VL_GTS"; }
virtual string emitC() { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
virtual bool emitWordForm() { return false; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2314,9 +2436,8 @@ struct AstGte : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k>= %r)"; }
virtual string emitOperator() { return "VL_GTE"; }
virtual string emitC() { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ">="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2330,9 +2451,8 @@ struct AstGteS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k>= %r)"; }
virtual string emitOperator() { return "VL_GTES"; }
virtual string emitC() { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
virtual bool emitWordForm() { return false; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2347,9 +2467,8 @@ struct AstLte : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k<= %r)"; }
virtual string emitOperator() { return "VL_LTE"; }
virtual string emitC() { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "<="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2363,9 +2482,8 @@ struct AstLteS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k<= %r)"; }
virtual string emitOperator() { return "VL_LTES"; }
virtual string emitC() { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
virtual bool emitWordForm() { return false; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2382,7 +2500,7 @@ struct AstShiftL : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftL(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k<< %r)"; }
virtual string emitOperator() { return "VL_SHIFTL"; }
virtual string emitC() { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "<<"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return true;}
@@ -2399,7 +2517,7 @@ struct AstShiftR : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftR(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k>> %r)"; }
virtual string emitOperator() { return "VL_SHIFTR"; }
virtual string emitC() { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ">>"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
@@ -2416,7 +2534,7 @@ struct AstShiftRS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftRS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k>>> %r)"; }
virtual string emitOperator() { return "VL_SHIFTRS"; }
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
@@ -2432,9 +2550,8 @@ struct AstAdd : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAdd(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k+ %r)"; }
virtual string emitOperator() { return "VL_ADD"; }
virtual string emitC() { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "+"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2448,9 +2565,8 @@ struct AstSub : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSub(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k- %r)"; }
virtual string emitOperator() { return "VL_SUB"; }
virtual string emitC() { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2464,9 +2580,8 @@ struct AstMul : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMul(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k* %r)"; }
virtual string emitOperator() { return "VL_MUL"; }
virtual string emitC() { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "*"; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2481,9 +2596,8 @@ struct AstMulS : public AstNodeBiComAsv {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k* %r)"; }
virtual string emitOperator() { return "VL_MULS"; }
virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }
virtual bool emitWordForm() { return false; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2499,8 +2613,7 @@ struct AstDiv : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDiv(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k/ %r)"; }
virtual string emitOperator() { return "VL_DIV"; }
virtual bool emitWordForm() { return true; }
virtual string emitC() { return "VL_DIV_%lq(%lW, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2515,8 +2628,7 @@ struct AstDivS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k/ %r)"; }
virtual string emitOperator() { return "VL_DIVS"; }
virtual bool emitWordForm() { return false; }
virtual string emitC() { return "VL_DIVS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2532,8 +2644,7 @@ struct AstModDiv : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDiv(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k%% %r)"; }
virtual string emitOperator() { return "VL_MODDIV"; }
virtual bool emitWordForm() { return true; }
virtual string emitC() { return "VL_MODDIV_%lq(%lW, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2548,8 +2659,7 @@ struct AstModDivS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDivS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k%% %r)"; }
virtual string emitOperator() { return "VL_MODDIVS"; }
virtual bool emitWordForm() { return false; }
virtual string emitC() { return "VL_MODDIVS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
@@ -2565,8 +2675,7 @@ struct AstPow : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPow(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k** %r)"; }
virtual string emitOperator() { return "VL_POW"; }
virtual bool emitWordForm() { return false; }
virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
@@ -2581,8 +2690,7 @@ struct AstPowS : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowS(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k** %r)"; }
virtual string emitOperator() { return "VL_POWS"; }
virtual bool emitWordForm() { return false; }
virtual string emitC() { return "VL_POWS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
@@ -2598,9 +2706,8 @@ struct AstEqCase : public AstNodeBiCom {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k=== %r)"; }
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2614,9 +2721,8 @@ struct AstNeqCase : public AstNodeBiCom {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k!== %r)"; }
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2631,9 +2737,8 @@ struct AstEqWild : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k==? %r)"; }
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2647,9 +2752,8 @@ struct AstNeqWild : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k!=? %r)"; }
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2665,7 +2769,7 @@ struct AstConcat : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string emitVerilog() { return "%k{%l, %k%r}"; }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcat(lhs,rhs); }
virtual string emitOperator() { return "VL_CONCAT"; }
virtual string emitC() { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -2681,12 +2785,28 @@ struct AstReplicate : public AstNodeBiop {
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opRepl(lhs,rhs); }
virtual string emitVerilog() { return "%k{%l{%k%r}}"; }
virtual string emitOperator() { return "VL_REPLICATE"; }
virtual string emitC() { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*2; }
};
struct AstFGetS : public AstNodeBiop {
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
virtual ~AstFGetS() {}
virtual AstType type() const { return AstType::FEOF;}
virtual AstNode* clone() { return new AstFGetS(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%k$fgets(%l,%r)"; }
virtual string emitC() { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*64; }
AstNode* strgp() const { return lhsp(); }
AstNode* filep() const { return rhsp(); }
};
//======================================================================
// SysVerilog assertions
@@ -2712,6 +2832,27 @@ struct AstVAssert : public AstNodeStmt {
AstNode* failsp() const { return op3p(); } // op3 = if fails
};
//======================================================================
// Assertions
struct AstClocking : public AstNode {
// Set default clock region
// Parents: MODULE
// Children: Assertions
public:
AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp)
: AstNode(fl) {
addOp1p(sensesp);
addNOp2p(bodysp);
}
virtual ~AstClocking() {}
virtual AstType type() const { return AstType::CLOCKING;}
virtual AstNode* clone() { return new AstClocking(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list
AstNode* bodysp() const { return op2p(); } // op2 = Body
};
//======================================================================
// PSL
@@ -2736,17 +2877,19 @@ struct AstPslClocked : public AstNode {
// Parents: ASSERT|COVER (property)
// Children: SENITEM, Properties
public:
AstPslClocked(FileLine* fl, AstSenItem* sensesp, AstNode* propp)
AstPslClocked(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp)
: AstNode(fl) {
addNOp1p(sensesp);
addOp2p(propp);
addNOp2p(disablep);
addOp3p(propp);
}
virtual ~AstPslClocked() {}
virtual AstType type() const { return AstType::PSLCLOCKED;}
virtual AstNode* clone() { return new AstPslClocked(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list
AstNode* propp() const { return op2p(); } // op2 = property
AstNode* disablep() const { return op2p(); } // op2 = disable
AstNode* propp() const { return op3p(); } // op3 = property
};
struct AstPslAssert : public AstNodeStmt {
@@ -2780,10 +2923,11 @@ struct AstPslCover : public AstNodeStmt {
private:
string m_name; // Name to report
public:
AstPslCover(FileLine* fl, AstNode* propp, const string& name="")
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
: AstNodeStmt(fl)
, m_name(name) {
addOp1p(propp);
addNOp4p(stmtsp);
}
virtual ~AstPslCover() {}
virtual AstType type() const { return AstType::PSLCOVER;}
@@ -2792,11 +2936,13 @@ public:
virtual string name() const { return m_name; } // * = Var name
virtual V3Hash sameHash() const { return V3Hash(name()); }
virtual bool same(AstNode* samep) const { return samep->name() == name(); }
void name(const string& flag) { m_name = flag; }
AstNode* propp() const { return op1p(); } // op1 = property
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
AstNode* stmtsp() const { return op4p(); } // op4 = statements
};
//======================================================================
@@ -2999,6 +3145,7 @@ public:
virtual string name() const { return m_name; }
virtual bool broken() const { return ( (m_scopep && !m_scopep->brokeExists())); }
virtual bool maybePointedTo() const { return true; }
virtual void dump(ostream& str=cout);
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return ((funcType()==samep->castCFunc()->funcType())
&& (rtnTypeVoid()==samep->castCFunc()->rtnTypeVoid())
@@ -3155,7 +3302,7 @@ struct AstCMath : public AstNodeMath {
virtual bool isPredictOptimizable() const { return false; }
virtual bool cleanOut() { return true; }
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitOperator() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
};
+2 -2
View File
@@ -28,8 +28,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <cstring>
#include <algorithm>
+2 -2
View File
@@ -26,8 +26,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
+2 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <map>
+37 -8
View File
@@ -39,8 +39,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
@@ -73,7 +73,7 @@ private:
}
// Check for X/Z in non-casex statements
if (!nodep->castCase() || !nodep->castCase()->casex()) {
{
m_caseExprp = nodep;
nodep->exprp()->accept(*this);
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
@@ -83,11 +83,18 @@ private:
}
}
virtual void visit(AstConst* nodep, AstNUser*) {
// See also neverItem
if (m_caseExprp && nodep->num().isFourState()) {
if (m_caseExprp->castGenCase()) {
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
// Don't sweat it, we already complained about casex in general
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
if (nodep->num().isUnknown()) {
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
}
} else {
nodep->v3error("Use of x/? constant in case statement, (perhaps intended casex/casez)");
nodep->v3warn(CASEWITHX, "Use of x/? constant in case statement, (perhaps intended casex/casez)");
}
}
}
@@ -152,12 +159,15 @@ private:
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
AstConst* iconstp = icondp->castConst();
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
if (neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
} else {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
uint32_t mask = nummask.asInt();
uint32_t mask = nummask.toUInt();
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
uint32_t val = numval.asInt();
uint32_t val = numval.toUInt();
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if ((i & mask) == val) {
if (!m_valueItem[i]) {
@@ -170,6 +180,7 @@ private:
}
}
}
}
// Defaults were moved to last in the caseitem list by V3Link
if (itemp->isDefault()) { // Case statement's default... Fill the table
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
@@ -296,8 +307,15 @@ private:
AstNode* and1p;
AstNode* and2p;
AstConst* iconstp = icondp->castConst();
if (iconstp && iconstp->num().isFourState()
&& nodep->casex()) {
if (iconstp && neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
// For simplicity, make expression that is not equal, and let later
// optimizations remove it
and1p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,0));
and2p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,1));
} else if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez())) {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width());
@@ -394,6 +412,17 @@ private:
}
}
bool neverItem(AstCase* casep, AstConst* itemp) {
// Xs in case or casez are impossible due to two state simulations
if (casep->casex()) {
} else if (casep->casez()) {
if (itemp->num().isUnknown()) return true;
} else {
if (itemp->num().isFourState()) return true;
}
return false;
}
// VISITORS
virtual void visit(AstCase* nodep, AstNUser*) {
V3Case::caseLint(nodep);
+2 -2
View File
@@ -43,8 +43,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+3 -2
View File
@@ -32,8 +32,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <set>
@@ -63,6 +63,7 @@ private:
vscp->v3fatalSrc("Not applicable\n");
#endif
AstVar* varp = vscp->varp();
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
if (varp->arraysp()) {
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
} else {
+2 -2
View File
@@ -29,8 +29,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+2 -2
View File
@@ -33,8 +33,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+2 -2
View File
@@ -36,8 +36,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+23 -20
View File
@@ -26,8 +26,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
@@ -134,16 +134,16 @@ private:
}
bool operandHugeShiftL(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst()
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->width()));
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()));
}
bool operandHugeShiftR(AstNodeBiop* nodep) {
return (nodep->rhsp()->castConst()
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->lhsp()->width()));
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()));
}
bool operandIsTwo(AstNode* nodep) {
return (nodep->castConst()
&& nodep->width() <= VL_QUADSIZE
&& nodep->castConst()->asQuad()==2);
&& nodep->castConst()->toUQuad()==2);
}
bool operandIsTwostate(AstNode* nodep) {
return (nodep->castConst()
@@ -180,7 +180,7 @@ private:
return (nodep->rhsp()->castConst()
&& nodep->fromp()->castNodeVarRef()
&& !nodep->fromp()->castNodeVarRef()->lvalue()
&& ((int)(nodep->rhsp()->castConst()->asInt())
&& ((int)(nodep->rhsp()->castConst()->toUInt())
>= nodep->fromp()->castNodeVarRef()->varp()->widthWords()));
}
bool operandSelFull(AstSel* nodep) {
@@ -215,15 +215,18 @@ private:
bool warnSelect(AstSel* nodep) {
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
AstVar* varp = varrefp->varp();
if (m_warn
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& (!varrefp->varp()->rangep() || varrefp->varp()->msb()) // else it's non-resolvable parameterized
&& ( ( (nodep->msbConst() > varrefp->varp()->msb())
|| (nodep->lsbConst() > varrefp->varp()->msb())))) {
&& (!varp->rangep() || varp->msb()) // else it's non-resolvable parameterized
&& ( ( (nodep->msbConst() > varp->msbMaxSelect())
|| (nodep->lsbConst() > varp->msbMaxSelect())))) {
nodep->v3error("Selection index out of range: "
<<nodep->msbConst()<<":"<<nodep->lsbConst()
<<" outside "<<varrefp->varp()->msb()<<":0");
<<" outside "<<varp->msbMaxSelect()<<":0"
<<(varp->lsb()>=0 ? ""
:" (adjusted +"+cvtToStr(-varp->lsb())+" to account for negative lsb)"));
}
}
return false; // Not a transform, so NOP
@@ -432,8 +435,8 @@ private:
nodep->accept(*this); // Further reduce, either node may have more reductions.
} else {
// We know shift amounts are constant, but might be a mixed left/right shift
int shift1 = shift1p->castConst()->asInt(); if (lhsp->castShiftR()) shift1=-shift1;
int shift2 = shift2p->castConst()->asInt(); if (nodep->castShiftR()) shift2=-shift2;
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(); shift1p=NULL;
@@ -490,11 +493,11 @@ private:
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
// Swap?
if (( con1p->asInt() != con2p->asInt() + sel2p->width())
&&(con2p->asInt() != con1p->asInt() + sel1p->width())) return false;
bool lsbFirstAssign = (con1p->asInt() < con2p->asInt());
if (( con1p->toSInt() != con2p->toSInt() + sel2p->width())
&&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false;
bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt());
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
//if (VL_BITBIT_I(con1p->asInt()) == 0) return false;
//if (VL_BITBIT_I(con1p->toUInt()) == 0) return false;
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
UINFO(4," && "<<nextp<<endl);
//nodep->dumpTree(cout, "comb1: ");
@@ -517,7 +520,7 @@ private:
return true;
}
bool varNotReferenced(AstNode* nodep, AstVar* varp, bool level=0) {
bool varNotReferenced(AstNode* nodep, AstVar* varp, int level=0) {
// Return true if varp never referenced under node.
// Return false if referenced, or tree too deep to be worth it
if (!nodep) return true;
@@ -648,7 +651,7 @@ private:
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
if (!shiftp->rhsp()->castConst()) return false;
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->asInt()) return false;
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->toUInt()) return false;
return true;
}
void replaceBoolShift(AstNode* nodep) {
@@ -784,7 +787,7 @@ private:
AstNode* newlsbp;
if (lsb1p->castConst() && lsb2p->castConst()) {
newlsbp = new AstConst(lsb1p->fileline(),
lsb1p->castConst()->asInt() + lsb2p->castConst()->asInt());
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
lsb1p->deleteTree(); lsb1p=NULL;
lsb2p->deleteTree(); lsb2p=NULL;
} else {
@@ -851,7 +854,7 @@ private:
AstNode* widthp = nodep->widthp()->unlinkFrBack();
AstSel* newp = new AstSel(nodep->fileline(),
fromp,
new AstConst(lsbp->fileline(), lsbp->asInt() % fromp->width()),
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
widthp);
newp->widthSignedFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
+2 -2
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
+2 -2
View File
@@ -25,8 +25,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <vector>
#include <map>
+2 -2
View File
@@ -53,8 +53,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <map>
+2 -2
View File
@@ -29,8 +29,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+2 -2
View File
@@ -26,8 +26,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+2 -2
View File
@@ -28,8 +28,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
+237 -180
View File
@@ -20,10 +20,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
@@ -78,10 +78,10 @@ public:
//int debug() { return 9; }
// METHODS
void displayEmit(AstDisplay* nodep);
string displayFormat(AstNode* widthNode, string in,
char fmtLetter, bool padZero, bool reallyString);
void displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter);
void displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp, bool isScan);
void displayEmit(AstNode* nodep, bool isScan);
void displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
string vfmt, char fmtLetter);
void emitVarDecl(AstVar* nodep, const string& prefixIfImp);
typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_STATIC, EVL_ALL} EisWhich;
@@ -91,7 +91,8 @@ public:
void emitIQW(AstNode* nodep) {
puts (nodep->isWide()?"W":(nodep->isQuad()?"Q":"I"));
}
void emitOpName(AstNode* nodep, const string& name);
void emitOpName(AstNode* nodep, const string& format,
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
string cFuncArgs(AstCFunc* nodep) {
// Return argument list for given C function
@@ -230,7 +231,23 @@ public:
nodep->lhsp()->iterateAndNext(*this);
puts(");\n");
}
virtual void visit(AstDisplay* nodep, AstNUser*); // BELOW
virtual void visit(AstDisplay* nodep, AstNUser*) {
string text = nodep->text();
if (nodep->addNewline()) text += "\\n";
displayNode(nodep, text, nodep->exprsp(), false);
}
virtual void visit(AstFScanF* nodep, AstNUser*) {
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
}
virtual void visit(AstSScanF* nodep, AstNUser*) {
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
}
void checkMaxWords(AstNode* nodep) {
if (nodep->widthWords() > VL_TO_STRING_MAX_WORDS) {
nodep->v3error("String of "<<nodep->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
}
}
virtual void visit(AstFOpen* nodep, AstNUser*) {
nodep->filep()->iterateAndNext(*this);
puts(" = VL_FOPEN_");
@@ -242,9 +259,7 @@ public:
puts(cvtToStr(nodep->filenamep()->widthWords()));
putbs(", ");
}
if (nodep->filenamep()->widthWords() > VL_TO_STRING_MAX_WORDS) {
nodep->v3error("String of "<<nodep->filenamep()->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
}
checkMaxWords(nodep->filenamep());
nodep->filenamep()->iterateAndNext(*this);
putbs(", ");
nodep->modep()->iterateAndNext(*this);
@@ -271,9 +286,7 @@ public:
puts(cvtToStr(array_lsb));
putbs(",");
puts(cvtToStr(nodep->filenamep()->widthWords()));
if (nodep->filenamep()->widthWords() > VL_TO_STRING_MAX_WORDS) {
nodep->v3error("String of "<<nodep->filenamep()->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
}
checkMaxWords(nodep->filenamep());
putbs(", ");
nodep->filenamep()->iterateAndNext(*this);
putbs(", ");
@@ -292,6 +305,17 @@ public:
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
puts("=0; }\n");
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
if (!nodep->filep()) {
puts("fflush (stdout);\n");
} else {
puts("if (");
nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP(");
nodep->filep()->iterateAndNext(*this);
puts(")); }\n");
}
}
virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->precondsp()->iterateAndNext(*this);
puts("while (");
@@ -353,26 +377,24 @@ public:
// Operators
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
emitOpName(nodep,nodep->emitOperator());
puts(")");
emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL);
}
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
if (emitSimpleOk(nodep)) {
putbs("("); puts(nodep->emitSimpleOperator()); puts(" ");
} else {
emitOpName(nodep,nodep->emitOperator());
}
nodep->lhsp()->iterateAndNext(*this); puts(")");
} else {
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), NULL, NULL);
}
}
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
if (emitSimpleOk(nodep)) {
putbs("("); nodep->lhsp()->iterateAndNext(*this);
puts(" "); putbs(nodep->emitSimpleOperator()); puts(" ");
} else {
emitOpName(nodep,nodep->emitOperator());
nodep->lhsp()->iterateAndNext(*this); puts(", ");
}
nodep->rhsp()->iterateAndNext(*this); puts(")");
} else {
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
}
}
virtual void visit(AstRedXor* nodep, AstNUser* vup) {
if (nodep->lhsp()->isWide()) {
@@ -404,10 +426,7 @@ public:
virtual void visit(AstNodeCond* nodep, AstNUser*) {
// Widths match up already, so we'll just use C++'s operator w/o any temps.
if (nodep->expr1p()->isWide()) {
emitOpName(nodep,nodep->emitOperator());
nodep->condp()->iterateAndNext(*this); puts(", ");
nodep->expr1p()->iterateAndNext(*this); puts(", ");
nodep->expr2p()->iterateAndNext(*this); puts(")");
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p());
} else {
putbs("(");
nodep->condp()->iterateAndNext(*this); putbs(" ? ");
@@ -417,20 +436,11 @@ public:
}
virtual void visit(AstSel* nodep, AstNUser*) {
// Note ASSIGN checks for this on a LHS
if (nodep->widthp()->isOne()) {
emitOpName(nodep,"VL_BITSEL");
nodep->fromp()->iterateAndNext(*this); puts(", ");
nodep->lsbp()->iterateAndNext(*this); puts(")");
} else {
emitOpName(nodep,"VL_SEL");
nodep->fromp()->iterateAndNext(*this); puts(", ");
nodep->lsbp()->iterateAndNext(*this); puts(", ");
nodep->widthp()->iterateAndNext(*this); puts(")");
}
emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp());
}
virtual void visit(AstReplicate* nodep, AstNUser*) {
if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) {
if (((int)nodep->rhsp()->castConst()->asInt()
if (((int)nodep->rhsp()->castConst()->toUInt()
* nodep->lhsp()->widthMin()) != nodep->widthMin())
nodep->v3fatalSrc("Replicate non-constant or width miscomputed");
puts("VL_REPLICATE_");
@@ -440,19 +450,11 @@ public:
if (nodep->lhsp()) { puts(","+cvtToStr(nodep->lhsp()->widthMin())); }
if (nodep->rhsp()) { puts(","+cvtToStr(nodep->rhsp()->widthMin())); }
puts(",");
} else {
emitOpName(nodep,nodep->emitOperator());
}
nodep->lhsp()->iterateAndNext(*this); puts(", ");
nodep->rhsp()->iterateAndNext(*this); puts(")");
} else {
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
}
virtual void visit(AstArraySel* nodep, AstNUser*) {
nodep->fromp()->iterateAndNext(*this); putbs("[");
nodep->bitp()->iterateAndNext(*this); puts("]");
}
virtual void visit(AstWordSel* nodep, AstNUser*) {
nodep->fromp()->iterateAndNext(*this); puts("["); // Not putbs, as usually it's a small constant next
nodep->bitp()->iterateAndNext(*this); puts("]");
}
// Terminals
virtual void visit(AstVarRef* nodep, AstNUser*) {
@@ -482,11 +484,11 @@ public:
}
ofp()->printf(",0x%08x)", nodep->num().dataWord(0));
} else if (nodep->isQuad()) {
vluint64_t num = nodep->asQuad();
vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%lld)", (long long)num);
else ofp()->printf("VL_ULL(0x%llx)", (long long)num);
} else {
uint32_t num = nodep->asInt();
uint32_t num = nodep->toUInt();
if (num<10) puts(cvtToStr(num));
else ofp()->printf("0x%x", num);
//Unneeded-Causes %lx format warnings:
@@ -852,33 +854,95 @@ bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) {
return true;
}
void EmitCStmts::emitOpName(AstNode* nodep, const string& opname) {
putbs(opname+"_");
if (nodep->emitWordForm()) {
emitIQW(nodep->op1p());
puts("(");
if (nodep->op1p()->isWide()) {
puts(cvtToStr(nodep->op1p()->widthWords()));
puts(", ");
void EmitCStmts::emitOpName(AstNode* nodep, const string& format,
AstNode* lhsp, AstNode* rhsp, AstNode* thsp) {
// Look at emitOperator() format for term/uni/dual/triops,
// and write out appropriate text.
// %n* node
// %nq emitIQW on the [node]
// %nw width in bits
// %nW width in words
// %ni iterate
// %l* lhsp - if appropriate, then second char as above
// %r* rhsp - if appropriate, then second char as above
// %t* thsp - if appropriate, then second char as above
// %k Potential line break
// %P Wide temporary name
// , Commas suppressed if the previous field is suppressed
string nextComma;
bool needComma = false;
#define COMMA { if (nextComma!="") { puts(nextComma); nextComma=""; } }
putbs("");
for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) {
if (pos[0]==',') {
// Remember we need to add one, but don't do yet to avoid ",)"
if (needComma) {
if (pos[1]==' ') { nextComma=", "; }
else nextComma = ",";
needComma = false;
}
} else {
emitIQW(nodep);
if (nodep->op1p()) { emitIQW(nodep->op1p()); }
if (nodep->op2p()) { emitIQW(nodep->op2p()); }
if (nodep->op3p()) { emitIQW(nodep->op3p()); }
puts("(");
puts(cvtToStr(nodep->widthMin()));
if (nodep->op1p()) { puts(","+cvtToStr(nodep->op1p()->widthMin())); }
if (nodep->op2p()) { puts(","+cvtToStr(nodep->op2p()->widthMin())); }
if (nodep->op3p()) { puts(","+cvtToStr(nodep->op3p()->widthMin())); }
if (nodep->op1p() || nodep->isWide()) puts(", ");
if (pos[1]==' ') { ++pos; } // Must do even if no nextComma
}
else if (pos[0]=='%') {
++pos;
bool detail = false;
AstNode* detailp = NULL;
switch (pos[0]) {
case '%': puts("%"); break;
case 'k': putbs(""); break;
case 'n': detail = true; detailp = nodep; break;
case 'l': detail = true; detailp = lhsp; break;
case 'r': detail = true; detailp = rhsp; break;
case 't': detail = true; detailp = thsp; break;
case 'P':
if (nodep->isWide()) {
if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Op w/ no temp, perhaps missing op in V3EmitC?");
COMMA;
puts(m_wideTempRefp->hiername());
puts(m_wideTempRefp->varp()->name());
m_wideTempRefp = NULL;
if (nodep->op1p()) puts(", ");
needComma = true;
}
break;
default:
nodep->v3fatalSrc("Unknown emitOperator format code: %"<<pos[0]);
break;
}
if (detail) {
// Get next letter of %[nlrt]
++pos;
switch (pos[0]) {
case 'q': emitIQW(detailp); break;
case 'w':
COMMA;
puts(cvtToStr(detailp->widthMin()));
needComma = true;
break;
case 'W':
if (lhsp->isWide()) {
COMMA;
puts(cvtToStr(lhsp->widthWords()));
needComma = true;
}
break;
case 'i':
COMMA;
if (!detailp) { nodep->v3fatalSrc("emitOperator() references undef node"); }
else detailp->iterateAndNext(*this);
needComma = true;
break;
default:
nodep->v3fatalSrc("Unknown emitOperator format code: %[nlrt]"<<pos[0]);
break;
}
}
} else {
// Normal text
if (pos[0] == ')') nextComma="";
COMMA;
string s; s+=pos[0]; puts(s);
}
}
}
@@ -888,13 +952,11 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& opname) {
// We only do one display at once, so can just use static state
struct EmitDispState {
bool m_wide; // Put out a wide func that needs string buffer
string m_format; // "%s" and text from user
vector<AstNode*> m_argsp; // Each argument to be printed
vector<string> m_argsFunc; // Function before each argument to be printed
EmitDispState() { clear(); }
void clear() {
m_wide = false;
m_format = "";
m_argsp.clear();
m_argsFunc.clear();
@@ -906,18 +968,40 @@ struct EmitDispState {
}
} emitDispState;
void EmitCStmts::displayEmit(AstDisplay* nodep) {
if (emitDispState.m_format != "") {
// Format
if (nodep->filep()) {
puts("if (");
nodep->filep()->iterate(*this); // Check if closed, to avoid core dump
puts(") fprintf(VL_CVT_Q_FP(");
nodep->filep()->iterate(*this);
puts("),\"");
void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
if (emitDispState.m_format == ""
&& nodep->castDisplay()) { // not fscanf etc, as they need to return value
// NOP
} else {
puts("VL_PRINTF(\"");
// Format
bool isStmt;
if (AstFScanF* dispp = nodep->castFScanF()) {
isStmt = false;
puts("VL_FSCANF_IX(");
dispp->filep()->iterate(*this);
puts(",");
} else if (AstSScanF* dispp = nodep->castSScanF()) {
isStmt = false;
checkMaxWords(dispp->fromp());
puts("VL_SSCANF_I"); emitIQW(dispp->fromp()); puts("X(");
puts(cvtToStr(dispp->fromp()->widthMin()));
puts(",");
dispp->fromp()->iterate(*this);
puts(",");
} else if (AstDisplay* dispp = nodep->castDisplay()) {
isStmt = true;
if (dispp->filep()) {
puts("VL_FWRITEF(");
dispp->filep()->iterate(*this);
puts(",");
} else {
puts("VL_WRITEF(");
}
} else {
isStmt = true;
nodep->v3fatalSrc("Unknown displayEmit node type");
}
puts("\"");
ofp()->putsNoTracking(emitDispState.m_format);
puts("\"");
// Arguments
@@ -928,138 +1012,112 @@ void EmitCStmts::displayEmit(AstDisplay* nodep) {
ofp()->indentInc();
ofp()->putbs("");
if (func!="") puts(func);
if (argp) argp->iterate(*this);
if (func!="") puts(")");
if (argp) {
if (isScan) puts("&(");
argp->iterate(*this);
if (isScan) puts(")");
}
ofp()->indentDec();
}
// End
puts(");\n");
puts(")");
if (isStmt) puts(";\n");
else puts(" ");
// Prep for next
emitDispState.clear();
}
}
string EmitCStmts::displayFormat(AstNode* widthNodep, string in,
char fmtLetter, bool padZero, bool reallyString) {
if (fmtLetter=='s') padZero = false;
if (widthNodep && widthNodep->isWide()
void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
string vfmt, char fmtLetter) {
// Print display argument, edits elistp
AstNode* argp = *elistp;
if (!argp) {
// expectDisplay() checks this first, so internal error if found here
dispp->v3error("Internal: Missing arguments for $display format");
return;
}
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
dispp->v3error("Exceeded limit of 1024 bits for any display arguments");
}
if (argp && argp->isWide()
&& (fmtLetter=='d'||fmtLetter=='u')) {
widthNodep->v3error("Unsupported: $display of dec format of > 64 bit results (use hex format instead)");
argp->v3error("Unsupported: "<<dispp->verilogKwd()<<" of dec format of > 64 bit results (use hex format instead)");
}
if (widthNodep && widthNodep->widthMin()>8 && fmtLetter=='c') {
widthNodep->v3error("$display of char format of > 8 bit result");
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");
}
string fmt;
if (in == "") {
// Size naturally
if (widthNodep == NULL) fmt=""; // Out of args, will get error
if (fmtLetter=='u' || fmtLetter=='d') { // Decimal. Spec says leading spaces, not zeros
double mantissabits = widthNodep->widthMin() - ((fmtLetter=='d')?1:0);
//string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter;
string pfmt;
if ((fmtLetter=='u' || fmtLetter=='d' || fmtLetter=='t')
&& !isScan
&& vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros
double mantissabits = argp->widthMin() - ((fmtLetter=='d')?1:0);
double maxval = pow(2.0, mantissabits);
double dchars = log10(maxval)+1.0;
if (fmtLetter=='d') dchars++; // space for sign
int nchars = int(dchars);
fmt=cvtToStr(nchars);
} else if (fmtLetter!='s' && fmtLetter!='c') { // Strings/chars don't get padding
int bitsPerChar = (fmtLetter=='b'?1 : fmtLetter=='o'?3 : 4);
int nchars = (widthNodep->widthMin() + bitsPerChar-1)/bitsPerChar;
if (padZero) fmt=(string)("0")+cvtToStr(nchars);
else fmt=cvtToStr(nchars);
}
} else if (in == "0") {
fmt=""; // No width
pfmt = string("%") + cvtToStr(nchars) + fmtLetter;
} else {
fmt=in;
pfmt = string("%") + vfmt + fmtLetter;
}
return fmt;
}
void EmitCStmts::displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter) {
// Print display argument, edits elistp
if (!*elistp) {
dispp->v3error("Missing arguments for $display format");
return;
}
if ((*elistp)->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
dispp->v3error("Exceeded limit of 1024 bits for any display arguments");
}
if ((*elistp)->isWide() // Have to use our own function for wide,
|| fmtLetter=='s' // ... Verilog strings
|| fmtLetter=='b' // ... binary, no printf %b in C
|| fmtLetter=='d') { // ... Signed decimal
// We use a single static string, so must only have one call per VL_PRINT
if (emitDispState.m_wide) { displayEmit(dispp); }
emitDispState.m_wide = true;
string nfmt = displayFormat(*elistp, fmt, fmtLetter, false, true);
string pfmt = "%"+nfmt+"s";
string func = "VL_VALUE_FORMATTED_";
func += ((*elistp)->isWide()) ? "W(" : ((*elistp)->isQuad()) ? "Q(" : "I(";
func += (cvtToStr((*elistp)->widthMin())
+",'"+fmtLetter+"'"
+","+(fmt=="0"?"true":"false")+",");
emitDispState.pushFormat(pfmt);
emitDispState.pushArg(*elistp,func);
} else {
string func;
string nfmt = displayFormat(*elistp, fmt, fmtLetter, true, false);
// We don't need to check for fmtLetter=='d', as it is above.
if ((*elistp)->isQuad() && (fmtLetter=='u'||fmtLetter=='o'||fmtLetter=='x')) {
nfmt+="ll";
func="(unsigned long long)("; // Must match %ull to avoid warnings
}
string pfmt = "%"+nfmt+fmtLetter;
emitDispState.pushArg(NULL,cvtToStr(argp->widthMin()));
emitDispState.pushArg(argp,"");
emitDispState.pushFormat(pfmt);
emitDispState.pushArg(*elistp,func);
}
// Next parameter
*elistp = (*elistp)->nextp();
}
void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
string vformat = nodep->text();
AstNode* elistp = nodep->exprsp();
void EmitCStmts::displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp,
bool isScan) {
AstNode* elistp = exprsp;
// Convert Verilog display to C printf formats
// "%0t" becomes "%d"
emitDispState.clear();
string fmt = "";
string::iterator pos = vformat.begin();
string vfmt = "";
string::const_iterator pos = vformat.begin();
bool inPct = false;
for (; pos != vformat.end(); ++pos) {
if (inPct && pos[0]=='%') {
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
inPct = false;
} else if (pos[0]=='%') {
//UINFO(1,"Parse '"<<*pos<<"' IP"<<inPct<<" List "<<(void*)(elistp)<<endl);
if (!inPct && pos[0]=='%') {
inPct = true;
fmt = "";
vfmt = "";
} else if (!inPct) { // Normal text
//char text[2]; text[0]=*pos; text[1]='\0';
emitDispState.pushFormat(*pos);
} else { // Format character
if (isdigit(pos[0])) {
// Digits, like %5d, etc.
fmt += pos[0];
} else {
inPct = false;
switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
// Digits, like %5d, etc.
vfmt += pos[0];
inPct = true; // Get more digits
break;
case '%':
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
break;
// Special codes
case '~': displayArg(nodep,&elistp,fmt,'d'); break; // Signed decimal
case '~': displayArg(nodep,&elistp,isScan, vfmt,'d'); break; // Signed decimal
// Spec: h d o b c l
case 'b': displayArg(nodep,&elistp,fmt,'b'); break;
case 'c': displayArg(nodep,&elistp,fmt,'c'); break;
case 't':
case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal
case 'o': displayArg(nodep,&elistp,fmt,'o'); break;
case '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 'o': displayArg(nodep,&elistp,isScan, vfmt,'o'); break;
case 'h':
case 'x': displayArg(nodep,&elistp,fmt,'x'); break;
case 's': displayArg(nodep,&elistp,fmt,'s'); break;
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
case 'm': {
emitDispState.pushFormat("%s");
emitDispState.pushArg(NULL, "vlSymsp->name(");
if (!nodep->scopeNamep()) nodep->v3fatalSrc("Display with %m but no AstScopeName");
for (AstText* textp=nodep->scopeNamep()->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
emitDispState.pushFormat("%S");
emitDispState.pushArg(NULL, "vlSymsp->name()");
if (!nodep->castDisplay()) nodep->v3fatalSrc("Non-Display with %m");
AstScopeName* scopenamep = nodep->castDisplay()->scopeNamep();
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
for (AstText* textp=scopenamep->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
emitDispState.pushFormat(textp->text());
}
break;
@@ -1076,12 +1134,11 @@ void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
}
}
}
}
if (elistp != NULL) {
nodep->v3error("Extra arguments for $display format\n");
// expectFormat also checks this, and should have found it first, so internal
elistp->v3error("Internal: Extra arguments for $display format\n");
}
if (nodep->addNewline()) emitDispState.pushFormat("\\n");
displayEmit(nodep);
displayEmit(nodep, isScan);
}
//######################################################################
+3 -3
View File
@@ -24,10 +24,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include "V3Global.h"
#include "V3File.h"
+3 -3
View File
@@ -20,10 +20,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include <map>
#include <vector>
+3 -3
View File
@@ -20,10 +20,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include <map>
#include <set>
#include <vector>
+4 -3
View File
@@ -20,10 +20,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
@@ -46,6 +46,7 @@ public:
of.putsHeader();
of.puts("\n");
of.puts("VM_COVERAGE = "); of.puts(v3Global.opt.coverage()?"1":"0"); of.puts("\n");
of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n");
of.puts("\n");
+27 -10
View File
@@ -20,10 +20,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
@@ -163,19 +163,30 @@ public:
virtual void visit(AstCoverInc*, AstNUser*) {
// N/A
}
virtual void visit(AstDisplay* nodep, AstNUser*) {
void visitNodeDisplay(AstNode* nodep, AstNode* filep, const string& text, AstNode* exprsp) {
putbs(nodep->verilogKwd());
putbs(" (");
if (nodep->filep()) { nodep->filep()->iterateAndNext(*this); putbs(","); }
if (filep) { filep->iterateAndNext(*this); putbs(","); }
puts("\"");
ofp()->putsNoTracking(nodep->text());
ofp()->putsNoTracking(text);
puts("\"");
for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) {
for (AstNode* expp=exprsp; expp; expp = expp->nextp()) {
puts(",");
expp->iterateAndNext(*this);
}
puts(");\n");
}
virtual void visit(AstDisplay* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
}
virtual void visit(AstFScanF* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
}
virtual void visit(AstSScanF* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
}
virtual void visit(AstFOpen* nodep, AstNUser*) {
putbs(nodep->verilogKwd());
putbs(" (");
@@ -192,6 +203,12 @@ public:
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
puts(");\n");
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
putbs(nodep->verilogKwd());
putbs(" (");
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
puts(");\n");
}
virtual void visit(AstReadMem* nodep, AstNUser*) {
putbs(nodep->verilogKwd());
putbs(" (");
@@ -345,11 +362,11 @@ public:
if (nodep->widthp()->isOne()) {
nodep->lsbp()->iterateAndNext(*this);
} else {
puts(cvtToStr(nodep->lsbp()->castConst()->asInt()
+nodep->widthp()->castConst()->asInt()
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()
+nodep->widthp()->castConst()->toSInt()
-1));
puts(":");
nodep->lsbp()->iterateAndNext(*this);
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()));
}
} else {
nodep->lsbp()->iterateAndNext(*this); puts("+:");
+31 -5
View File
@@ -18,8 +18,8 @@
//
//*************************************************************************
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <cstring>
#include <set>
#include "V3Error.h"
@@ -65,6 +65,17 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
//######################################################################
// FileLine class functions
FileLine::FileLine(FileLine::EmptySecret) {
m_lineno=0;
m_filename="COMMAND_LINE";
m_warnOff=0;
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
V3ErrorCode code = (V3ErrorCode)codei;
if (code.defaultsOff()) warnOff(code, true);
}
}
void FileLine::lineDirective(const char* textp) {
// Handle `line directive
// Skip `line
@@ -153,13 +164,23 @@ ostream& operator<<(ostream& os, FileLine* fileline) {
return(os);
}
bool FileLine::warnIsOff(V3ErrorCode code) {
bool FileLine::warnIsOff(V3ErrorCode code) const {
if (m_warnOff.test(code)) return true;
// UNOPTFLAT implies UNOPT
if (code==V3ErrorCode::UNOPT && m_warnOff.test(V3ErrorCode::UNOPTFLAT)) return true;
return false;
}
void FileLine::warnStateInherit(const FileLine& from) {
// Any warnings that are off in "from", become off in "this".
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
V3ErrorCode code = (V3ErrorCode)codei;
if (from.warnIsOff(code)) {
this->warnOff(code, true);
}
}
}
void FileLine::v3errorEnd(ostringstream& str) {
if (this && m_lineno) {
ostringstream nsstr;
@@ -261,6 +282,7 @@ void V3Error::abortIfWarnings() {
bool V3Error::isError(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return false;
else if (code==V3ErrorCode::INFO) return false;
else if (code==V3ErrorCode::FATAL) return true;
else if (code==V3ErrorCode::ERROR) return true;
else if (code<V3ErrorCode::FIRST_WARN
@@ -270,6 +292,7 @@ bool V3Error::isError(V3ErrorCode code) {
string V3Error::msgPrefix(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
else if (code==V3ErrorCode::INFO) return "-Info: ";
else if (code==V3ErrorCode::FATAL) return "%Error: ";
else if (code==V3ErrorCode::ERROR) return "%Error: ";
else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
@@ -306,12 +329,15 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
#ifdef __COVERITY__
if (s_errorCode==V3ErrorCode::FATAL) __coverity_panic__(x);
#endif
if (s_errorCode!=V3ErrorCode::SUPPRESS || debug()) {
if (s_errorCode!=V3ErrorCode::SUPPRESS
// On debug, show only non default-off warning to prevent pages of warnings
|| (debug() && !s_errorCode.defaultsOff())) {
cerr<<msgPrefix()<<sstr.str();
if (sstr.str()[sstr.str().length()-1] != '\n') {
cerr<<endl;
}
if (s_errorCode!=V3ErrorCode::SUPPRESS) {
if (s_errorCode!=V3ErrorCode::SUPPRESS
&& s_errorCode!=V3ErrorCode::INFO) {
if (!s_describedEachWarn[s_errorCode]
&& !s_pretendError[s_errorCode]) {
s_describedEachWarn[s_errorCode] = true;
+14 -6
View File
@@ -34,6 +34,7 @@ class V3ErrorCode {
public:
enum en {
SUPPRESS, // Warning suppressed by user
INFO, // General information out
FATAL, // Kill the program
ERROR, // General error out, can't suppress
// Error codes:
@@ -45,11 +46,13 @@ public:
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
CASEINCOMPLETE, // Case statement has missing values
CASEOVERLAP, // Case statements overlap
CASEWITHX, // Case with X values
CASEX, // Casex
CMPCONST, // Comparison is constant due to limited range
COMBDLY, // Combinatorial delayed assignment
STMTDLY, // Delayed statement
GENCLK, // Generated Clock
IMPERFECTSCH, // Imperfect schedule (disabled by default)
IMPLICIT, // Implicit wire
IMPURE, // Impure function not being inlined
MULTIDRIVEN, // Driven from multiple blocks
@@ -74,12 +77,12 @@ public:
const char* ascii() const {
const char* names[] = {
// Leading spaces indicate it can't be disabled.
" SUPPRESS", " FATAL", " ERROR",
" SUPPRESS", " INFO", " FATAL", " ERROR",
"MULTITOP", "TASKNSVAR",
" FIRST_WARN",
"BLKANDNBLK",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
"COMBDLY", "STMTDLY", "GENCLK", "IMPLICIT", "IMPURE",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CMPCONST",
"COMBDLY", "STMTDLY", "GENCLK", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
"MULTIDRIVEN", "REDEFMACRO",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
@@ -87,6 +90,8 @@ public:
};
return names[m_e];
};
// Warnings that default to off
bool defaultsOff() const { return ( m_e==IMPERFECTSCH );};
// Warnings that warn about nasty side effects
bool dangerous() const { return ( m_e==COMBDLY );};
// Warnings we'll present to the user as errors
@@ -94,7 +99,8 @@ public:
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE); };
// Warnings that are lint only
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|| m_e==CASEX || m_e==CMPCONST
|| m_e==CASEWITHX || m_e==CASEX
|| m_e==CMPCONST
|| m_e==IMPLICIT
|| m_e==UNDRIVEN || m_e==UNSIGNED
|| m_e==UNUSED || m_e==VARHIDDEN
@@ -159,6 +165,7 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
// These allow errors using << operators: v3error("foo"<<"bar");
// Careful, you can't put () around msg, as you would in most macro definitions
#define v3info(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::INFO)<<msg),V3Error::v3errorStr()));
#define v3fatal(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::FATAL)<<msg),V3Error::v3errorStr()));
#define v3error(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::ERROR)<<msg),V3Error::v3errorStr()));
#define v3warn(code,msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::code)<<msg),V3Error::v3errorStr()));
@@ -203,7 +210,7 @@ protected:
public:
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff; }
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff; }
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; }
FileLine (EmptySecret);
~FileLine() { }
#ifdef VL_LEAK_CHECKS
static void* operator new(size_t size);
@@ -218,9 +225,10 @@ public:
const string profileFuncname() const;
void warnOff(V3ErrorCode code, bool flag) { m_warnOff.set(code,flag); } // Turn on/off warning messages on this line.
bool warnOff(const string& code, bool flag); // Returns 1 if ok
bool warnIsOff(V3ErrorCode code);
bool warnIsOff(V3ErrorCode code) const;
void warnLintOff(bool flag);
void warnStateFrom(const FileLine& from) { m_warnOff=from.m_warnOff; }
void warnStateInherit(const FileLine& from);
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
void v3errorEnd(ostringstream& str);
+6 -6
View File
@@ -31,8 +31,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
@@ -172,7 +172,7 @@ private:
// Return equation to get the VL_BITWORD of a constant or non-constant
if (lsbp->castConst()) {
return new AstConst (lsbp->fileline(),
wordAdder + VL_BITWORD_I(lsbp->castConst()->asInt()));
wordAdder + VL_BITWORD_I(lsbp->castConst()->toUInt()));
} else {
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
lsbp->cloneTree(true),
@@ -203,7 +203,7 @@ private:
// Return equation to get the VL_BITBIT of a constant or non-constant
if (lsbp->castConst()) {
return new AstConst (lsbp->fileline(),
VL_BITBIT_I(lsbp->castConst()->asInt()));
VL_BITBIT_I(lsbp->castConst()->toUInt()));
} else {
return new AstAnd (lsbp->fileline(),
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
@@ -688,7 +688,7 @@ private:
UINFO(8," REPLICATE "<<nodep<<endl);
AstConst* constp = nodep->rhsp()->castConst();
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
uint32_t times = constp->asInt();
uint32_t times = constp->toUInt();
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
newp = lhsp->cloneTree(true);
for (unsigned repnum=1; repnum<times; repnum++) {
@@ -713,7 +713,7 @@ private:
int lhswidth = lhsp->widthMin();
AstConst* constp = rhsp->rhsp()->castConst();
if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
uint32_t times = constp->asInt();
uint32_t times = constp->toUInt();
for (int w=0; w<rhsp->widthWords(); w++) {
AstNode* newp;
if (lhswidth==1) {
+3 -2
View File
@@ -20,7 +20,7 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdarg.h>
#include <cstdarg>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -244,7 +244,8 @@ void V3File::createMakeDir() {
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
V3OutFile::V3OutFile(const string& filename)
: m_lineno(1), m_column(0), m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
: m_filename(filename), m_lineno(1), m_column(0)
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
v3fatal("Cannot write "<<filename);
+5 -3
View File
@@ -24,7 +24,7 @@
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include <stdio.h>
#include <cstdio>
#include <stack>
#include <set>
#include <fstream>
@@ -87,6 +87,7 @@ public:
private:
// MEMBERS
FILE* m_fp;
string m_filename;
int m_lineno;
int m_column;
int m_nobreak; // Basic operator or begin paren, don't break next
@@ -120,8 +121,9 @@ public:
bool tokenStart(const char* cp, const char* cmp);
bool tokenEnd(const char* cp);
void indentInc() { m_indentLevel += INDBLK; };
void indentDec() { m_indentLevel -= INDBLK;
UASSERT(m_indentLevel>=0,"Underflow of indentation\n");
void indentDec() {
m_indentLevel -= INDBLK;
UASSERT(m_indentLevel>=0, ": "<<m_filename<<": Underflow of indentation\n");
}
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
+2 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <iomanip>
+2 -2
View File
@@ -25,8 +25,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include "V3Global.h"
+2 -2
View File
@@ -21,8 +21,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <stack>
#include <map>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include "V3Global.h"
+2 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+4 -2
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
@@ -172,6 +172,8 @@ private:
m_modp->addStmtp(new AstAssignAlias(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
nodep->fileline()->warnStateInherit(exprvarrefp->varp()->fileline());
exprvarrefp->varp()->fileline()->warnStateInherit(nodep->fileline());
}
}
// Variable under the inline cell, need to rename to avoid conflicts
+2 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+2 -2
View File
@@ -29,8 +29,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
+2 -2
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include "V3Global.h"
+15 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
@@ -50,6 +50,7 @@ private:
// AstNodeFTask::userp() // V3SymTable* Local Symbol table
// AstBegin::userp() // V3SymTable* Local Symbol table
// AstVar::userp() // V3SymTable* Table used to create this variable
// AstVar::user2p() // bool True if port set for this variable
// ENUMS
enum IdState { // Which loop through the tree
@@ -60,6 +61,7 @@ private:
// STATE
// Below state needs to be preserved between each module call.
AstModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task
IdState m_idState; // Id linking mode (find or resolve)
int m_paramNum; // Parameter number, for position based connection
V3SymTable* m_curVarsp; // Symbol table of variables and tasks under table we're inserting into
@@ -106,6 +108,7 @@ private:
// VISITs
virtual void visit(AstNetlist* nodep, AstNUser*) {
AstNode::userClearTree();
AstNode::user2ClearTree();
// Look at all modules, and store pointers to all module names
for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castModule()) {
V3SymTable* symp = new V3SymTable(NULL);
@@ -164,6 +167,7 @@ private:
if ((findvarp->isIO() && nodep->isSignal())
|| (findvarp->isSignal() && nodep->isIO())) {
findvarp->combineType(nodep);
findvarp->fileline()->warnStateInherit(nodep->fileline());
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} else {
nodep->v3error("Duplicate declaration of signal: "<<nodep->prettyName());
@@ -188,6 +192,11 @@ private:
}
}
}
if (m_idState==ID_RESOLVE) {
if (nodep->isIO() && !m_ftaskp && !nodep->user2()) {
nodep->v3error("Input/output/inout does not appear in port list: "<<nodep->prettyName());
}
}
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
// VarRef: Resolve its reference
@@ -235,7 +244,9 @@ private:
m_curVarsp->insert(newvarp->name(), newvarp);
}
}
m_ftaskp = nodep;
nodep->iterateChildren(*this);
m_ftaskp = NULL;
}
m_curVarsp = upperVarsp;
if (m_idState==ID_FIND) {
@@ -335,6 +346,7 @@ private:
nodep->v3error("Pin is not a in/out/inout: "<<nodep->prettyName());
} else {
m_curVarsp->insert("__pinNumber"+cvtToStr(nodep->pinNum()), refp);
refp->user2(true);
}
// Ports not needed any more
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
@@ -421,6 +433,7 @@ public:
m_curVarsp = NULL;
m_cellVarsp = NULL;
m_modp = NULL;
m_ftaskp = NULL;
m_paramNum = 0;
m_beginNum = 0;
//
+2 -2
View File
@@ -26,8 +26,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
+2 -2
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <cstring>
#include <unistd.h>
#include <map>
+65 -2
View File
@@ -24,8 +24,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
@@ -108,6 +108,48 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->filep()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFGetC* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->filep()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFGetS* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->filep()->iterateAndNext(*this);
nodep->strgp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFScanF* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->filep()->iterateAndNext(*this);
nodep->exprsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstSScanF* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
nodep->exprsp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstReadMem* nodep, AstNUser*) {
bool last_setRefLvalue = m_setRefLvalue;
{
@@ -157,6 +199,27 @@ private:
nodep->iterateChildren(*this);
m_ftaskp = NULL;
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
AstNode* pinp = nodep->pinsp();
AstNodeFTask* taskp = nodep->taskp();
// We'll deal with mismatching pins later
if (!taskp) return;
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
if (AstVar* portp = stmtp->castVar()) {
if (portp->isIO()) {
if (portp->isInput()) {
pinp->iterateAndNext(*this);
} else { // Output or Inout
m_setRefLvalue = true;
pinp->iterateAndNext(*this);
m_setRefLvalue = false;
}
// Advance pin
pinp = pinp->nextp();
}
}
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
+2 -2
View File
@@ -25,8 +25,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
+4 -3
View File
@@ -28,8 +28,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
@@ -160,7 +160,8 @@ private:
m_dotText = "";
nodep->lhsp()->iterateAndNext(*this);
if (AstConst* constp = nodep->rhsp()->castConst()) {
m_dotText = m_dotText+"__BRA__"+cvtToStr(constp->asInt())+"__KET__";
string index = AstNode::encodeNumber(constp->toSInt());
m_dotText = m_dotText+"__BRA__"+index+"__KET__";
} else {
nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference");
}
+70 -4
View File
@@ -29,8 +29,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
@@ -223,7 +223,7 @@ private:
AstNode* widthp;
if (msbp->castConst() && lsbp->castConst()) {
// Quite common, save V3Const some effort
V3Number widnum (msbp->fileline(),32,msbp->castConst()->asInt() +1-lsbp->castConst()->asInt());
V3Number widnum (msbp->fileline(),32,msbp->castConst()->toSInt() +1-lsbp->castConst()->toSInt());
widnum.width(32,false); // Unsized so width from user
widthp = new AstConst (msbp->fileline(), widnum);
pushDeletep(msbp);
@@ -312,10 +312,48 @@ private:
}
}
void expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
// Check display arguments
bool inPct = false;
for (const char* inp = format.c_str(); *inp; inp++) {
char ch = tolower(*inp); // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
} else if (inPct) {
inPct = false;
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
inPct = true;
break;
case '%': break; // %% - just output a %
case 'm': // %m - auto insert "name"
if (isScan) nodep->v3error("Unsupported: %m in $fscanf");
break;
default: // Most operators, just move to next argument
if (!V3Number::displayedFmtLegal(ch)) {
nodep->v3error("Unknown $display format code: %"<<ch);
} else {
if (!argp) {
nodep->v3error("Missing arguments for $display format");
} else {
argp = argp->nextp();
}
}
break;
} // switch
}
}
if (argp) {
argp->v3error("Extra arguments for $display format\n");
}
}
void expectDescriptor(AstNode* nodep, AstNodeVarRef* filep) {
if (!filep) nodep->v3error("Unsupported: $fopen/$fclose descriptor must be a simple variable");
if (!filep) nodep->v3error("Unsupported: $fopen/$fclose/$f* descriptor must be a simple variable");
if (filep && filep->varp()) filep->varp()->attrFileDescr(true);
}
virtual void visit(AstFOpen* nodep, AstNUser*) {
nodep->iterateChildren(*this);
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
@@ -324,9 +362,37 @@ private:
nodep->iterateChildren(*this);
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
}
virtual void visit(AstFEof* nodep, AstNUser*) {
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*) {
nodep->iterateChildren(*this);
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
}
virtual void visit(AstDisplay* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
expectFormat(nodep, nodep->text(), nodep->exprsp(), false);
if (!m_assertp
&& (nodep->displayType() == AstDisplayType::INFO
|| nodep->displayType() == AstDisplayType::WARNING
+2 -2
View File
@@ -28,8 +28,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <vector>
+2 -2
View File
@@ -25,8 +25,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
+65 -37
View File
@@ -20,9 +20,9 @@
#include <config_build.h>
#include "verilatedos.h"
#include <math.h>
#include <stdio.h>
#include <stdarg.h>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <cstring>
#include <algorithm>
#include "V3Number.h"
@@ -45,6 +45,7 @@ void V3Number::init (FileLine* fileline, int swidth) {
m_fileline = fileline;
m_signed = false;
m_autoExtend = false;
m_fromString = false;
width(swidth);
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
}
@@ -52,6 +53,7 @@ void V3Number::init (FileLine* fileline, int swidth) {
V3Number::V3Number(VerilogString, FileLine* fileline, const string& str) {
// Create a number using a verilog string as the value, thus 8 bits per character.
init(fileline, str.length()*8);
m_fromString = true;
for (unsigned pos=0; pos<str.length(); ++pos) {
int topos = str.length()-1-pos;
for (int bit=0; bit<8; ++bit) {
@@ -143,14 +145,14 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
olen++;
break;
}
case 'z': {
case 'z': case '?': {
if (olen) m_fileline->v3error("Multi-digit X/Z/? not legal in decimal constant: "<<*cp);
if (!m_sized) m_fileline->v3error("Unsized X/Z/? not legal in decimal constant: "<<*cp);
olen++;
setAllBitsZ();
break;
}
case 'x': case '?': {
case 'x': {
if (olen) m_fileline->v3error("Multi-digit X/Z/? not legal in decimal constant: "<<*cp);
if (!m_sized) m_fileline->v3error("Unsized X/Z/? not legal in decimal constant: "<<*cp);
olen++;
@@ -181,9 +183,8 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
switch(tolower(*cp)) {
case '0': setBit(obit++, 0); break;
case '1': setBit(obit++, 1); break;
case 'z': setBit(obit++, 'z'); break;
case 'x': case '?':
setBit(obit++, 'x'); break;
case 'z': case '?': setBit(obit++, 'z'); break;
case 'x': setBit(obit++, 'x'); break;
case '_': break;
default:
m_fileline->v3error("Illegal character in binary constant: "<<*cp);
@@ -202,8 +203,9 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
case '5': setBit(obit++, 1); setBit(obit++, 0); setBit(obit++, 1); break;
case '6': setBit(obit++, 0); setBit(obit++, 1); setBit(obit++, 1); break;
case '7': setBit(obit++, 1); setBit(obit++, 1); setBit(obit++, 1); break;
case 'z': setBit(obit++, 'z'); setBit(obit++, 'z'); setBit(obit++, 'z'); break;
case 'x': case '?':
case 'z': case '?':
setBit(obit++, 'z'); setBit(obit++, 'z'); setBit(obit++, 'z'); break;
case 'x':
setBit(obit++, 'x'); setBit(obit++, 'x'); setBit(obit++, 'x'); break;
case '_': break;
default:
@@ -230,8 +232,9 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
case 'd': setBit(obit++,1); setBit(obit++,0); setBit(obit++,1); setBit(obit++,1); break;
case 'e': setBit(obit++,0); setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); break;
case 'f': setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); break;
case 'z': setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); break;
case 'x': case '?':
case 'z': case '?':
setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); break;
case 'x':
setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); break;
case '_': break;
default:
@@ -345,6 +348,22 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
return out.str();
}
bool V3Number::displayedFmtLegal(char format) {
// Is this a valid format letter?
switch (tolower(format)) {
case 'b': return true;
case 'c': return true;
case 'd': return true; // Unsigned decimal
case 'h': return true;
case 'o': return true;
case 's': return true;
case 't': return true;
case 'x': return true;
case '~': return true; // Signed decimal
default: return false;
}
}
string V3Number::displayed(const string& vformat) const {
string::const_iterator pos = vformat.begin();
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
@@ -412,7 +431,7 @@ string V3Number::displayed(const string& vformat) const {
return str;
}
case '~': // Signed decimal
case 't':
case 't': // Time
case 'd': { // Unsigned decimal
bool issigned = (code == '~');
if (fmtsize == "") {
@@ -427,9 +446,9 @@ string V3Number::displayed(const string& vformat) const {
return "ERR";
}
if (issigned) {
str = cvtToStr(asSQuad());
str = cvtToStr(toSQuad());
} else {
str = cvtToStr(asQuad());
str = cvtToStr(toUQuad());
}
int intfmtsize = atoi(fmtsize.c_str());
while ((int)(str.length()) < intfmtsize) str = " "+str;
@@ -444,34 +463,40 @@ string V3Number::displayed(const string& vformat) const {
//======================================================================
// ACCESSORS - as numbers
uint32_t V3Number::asInt() const {
UASSERT(!isFourState(),"asInt with 4-state "<<*this);
uint32_t V3Number::toUInt() const {
UASSERT(!isFourState(),"toUInt with 4-state "<<*this);
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this);
return m_value[0];
}
vlsint32_t V3Number::asSInt() const {
uint32_t v = asInt();
vlsint32_t V3Number::toSInt() const {
if (isSigned()) {
uint32_t v = toUInt();
uint32_t signExtend = (-(v & (1UL<<(width()-1))));
uint32_t extended = v | signExtend;
return (vlsint32_t)(extended);
} else {
// Where we use this (widths, etc) and care about signedness,
// we can reasonably assume the MSB isn't set on unsigned numbers.
return (vlsint32_t)toUInt();
}
}
vluint64_t V3Number::asQuad() const {
UASSERT(!isFourState(),"asQuad with 4-state "<<*this);
vluint64_t V3Number::toUQuad() const {
UASSERT(!isFourState(),"toUQuad with 4-state "<<*this);
UASSERT(width()<65, "Value too wide "<<*this);
if (width()<=32) return ((vluint64_t)(asInt()));
if (width()<=32) return ((vluint64_t)(toUInt()));
return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]);
}
vlsint64_t V3Number::asSQuad() const {
vluint64_t v = asQuad();
vlsint64_t V3Number::toSQuad() const {
vluint64_t v = toUQuad();
vluint64_t signExtend = (-(v & (VL_ULL(1)<<(width()-1))));
vluint64_t extended = v | signExtend;
return (vlsint64_t)(extended);
}
uint32_t V3Number::asHash() const {
uint32_t V3Number::toHash() const {
return m_value[0];
}
@@ -506,6 +531,12 @@ bool V3Number::isEqAllOnes(int optwidth) const {
}
return true;
}
bool V3Number::isUnknown() const {
for(int bit=0; bit<width(); bit++) {
if (bitIsX(bit)) return true;
}
return false;
}
int V3Number::minWidth() const {
for(int bit=width()-1; bit>0; bit--) {
@@ -609,10 +640,7 @@ V3Number& V3Number::opCountOnes (const V3Number& lhs) {
return *this;
}
V3Number& V3Number::opIsUnknown (const V3Number& lhs) {
for(int bit=0; bit<lhs.width(); bit++) {
if (lhs.bitIsX(bit)) return setSingleBits(1);
}
return setSingleBits(0);
return setSingleBits(lhs.isUnknown());
}
V3Number& V3Number::opOneHot (const V3Number& lhs) {
if (lhs.isFourState()) return setAllBitsX();
@@ -731,7 +759,7 @@ V3Number& V3Number::opRepl (const V3Number& lhs, const V3Number& rhs) { // rhs i
// Hopefully the using routine has a error check too.
// See also error in V3Width
if (!lhs.sized()) m_fileline->v3warn(WIDTHCONCAT,"Unsized numbers/parameters not allowed in replications.");
return opRepl(lhs, rhs.asInt());
return opRepl(lhs, rhs.toUInt());
}
V3Number& V3Number::opRepl (const V3Number& lhs, uint32_t rhsval) { // rhs is # of times to replicate
@@ -917,7 +945,7 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.asInt();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs(bit + rhsval));
}
@@ -930,7 +958,7 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
// We presume it is signed; as that's V3Signed's job to convert to opShiftR
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.asInt();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIsExtend(bit + rhsval));
}
@@ -940,7 +968,7 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
uint32_t rhsval = rhs.asInt();
uint32_t rhsval = rhs.toUInt();
setZero();
for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) {
@@ -989,7 +1017,7 @@ V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
setZero();
if (width() <= 64) {
setQuad(lhs.asQuad() * rhs.asQuad());
setQuad(lhs.toUQuad() * rhs.toUQuad());
opCleanThis(); // Mult produces extra bits in result
} else {
for (int lword=0; lword<lhs.words(); lword++) {
@@ -1026,7 +1054,7 @@ V3Number& V3Number::opDiv (const V3Number& lhs, const V3Number& rhs) {
if (rhs.isEqZero()) return setAllBitsX();
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large / math not implemented yet: "<<*this);
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large / math not implemented yet: "<<*this);
setQuad(lhs.asQuad() / rhs.asQuad());
setQuad(lhs.toUQuad() / rhs.toUQuad());
return *this;
}
V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
@@ -1050,7 +1078,7 @@ V3Number& V3Number::opModDiv (const V3Number& lhs, const V3Number& rhs) {
if (rhs.isEqZero()) return setAllBitsX();
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large % math not implemented yet: "<<*this);
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large % math not implemented yet: "<<*this);
setQuad(lhs.asQuad() % rhs.asQuad());
setQuad(lhs.toUQuad() % rhs.toUQuad());
return *this;
}
V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
@@ -1131,7 +1159,7 @@ void V3Number::opCleanThis() {
V3Number& V3Number::opRange (const V3Number& lhs, const V3Number& msb, const V3Number& lsb) {
if (lsb.isFourState() || msb.isFourState()) return setAllBitsX();
return opRange(lhs, msb.asInt(), lsb.asInt());
return opRange(lhs, msb.toUInt(), lsb.toUInt());
}
V3Number& V3Number::opRange (const V3Number& lhs, uint32_t msbval, uint32_t lsbval) {
+9 -5
View File
@@ -34,6 +34,7 @@ class V3Number {
int m_width; // Width as specified/calculated.
bool m_sized:1; // True if the user specified the width, else we track it.
bool m_signed:1; // True if signed value
bool m_fromString:1; // True if from string
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
FileLine* m_fileline;
vector<uint32_t> m_value; // The Value, with bit 0 being in bit 0 of this vector (unless X/Z)
@@ -119,10 +120,12 @@ public:
// ACCESSORS
string ascii(bool prefixed=true, bool cleanVerilog=false) const;
string displayed(const string& format) const;
static bool displayedFmtLegal(char format); // Is this a valid format letter?
int width() const { return m_width; }
int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1)
bool sized() const { return m_sized; }
bool autoExtend() const { return m_autoExtend; }
bool isFromString() const { return m_fromString; }
bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isNegative() const { return bitIs1(width()-1); }
bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; }
@@ -133,11 +136,12 @@ public:
bool isCaseEq(const V3Number& rhsp) const; // operator==
void width(int width, bool sized=true);
void isSigned(bool ssigned) { m_signed=ssigned; }
uint32_t asInt() const;
vlsint32_t asSInt() const;
vluint64_t asQuad() const;
vlsint64_t asSQuad() const;
uint32_t asHash() const;
bool isUnknown() const;
uint32_t toUInt() const;
vlsint32_t toSInt() const;
vluint64_t toUQuad() const;
vlsint64_t toSQuad() const;
uint32_t toHash() const;
uint32_t dataWord(int word) const;
uint32_t countOnes() const;
uint32_t mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
+3 -3
View File
@@ -26,8 +26,8 @@
#include <config_build.h>
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <algorithm>
#include "V3Number.h"
@@ -82,7 +82,7 @@ void test(string lhss, string op, string rhss, string exps) {
V3Number ok (new FileLine("ck",__LINE__), 1);
ok.opCaseEq(expnum,gotnum);
if (ok.asInt()!=1) {
if (ok.toUInt()!=1) {
v3fatalSrc("%Error:Test FAILED\n");
}
}
+84 -30
View File
@@ -95,6 +95,15 @@ void V3Options::addCppFile(const string& filename) {
m_cppFiles.insert(filename);
}
}
void V3Options::addFuture(const string& flag) {
if (m_futures.find(flag) == m_futures.end()) {
m_futures.insert(flag);
}
}
bool V3Options::isFuture(const string& flag) const {
return m_futures.find(flag) != m_futures.end();
}
void V3Options::addLibraryFile(const string& filename) {
if (m_libraryFiles.find(filename) == m_libraryFiles.end()) {
m_libraryFiles.insert(filename);
@@ -123,7 +132,7 @@ string V3Options::allArgsString() {
V3LangCode::V3LangCode (const char* textp) {
// Return code for given string, or ERROR, which is a bad code
for (int codei=V3LangCode::ERROR; codei<V3LangCode::MAX; codei++) {
for (int codei=V3LangCode::ERROR; codei<V3LangCode::MAX; ++codei) {
V3LangCode code = (V3LangCode)codei;
if (0==strcasecmp(textp,code.ascii())) {
m_e = code; return;
@@ -168,6 +177,30 @@ string V3Options::filenameNonExt (const string& filename) {
return base;
}
string V3Options::filenameSubstitute (const string& filename) {
string out;
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
if (filename[pos] == '$') {
string::size_type endpos = pos+1;
while ((endpos+1) < filename.length()
&& (isalnum(filename[endpos+1]) || filename[endpos+1]=='_'))
++endpos;
string envvar = filename.substr(pos+1,endpos-pos);
const char* envvalue = NULL;
if (envvar != "") envvalue = getenv(envvar.c_str());
if (envvalue) {
out += envvalue;
pos = endpos;
} else {
out += filename[pos]; // *pos == '$'
}
} else {
out += filename[pos];
}
}
return out;
}
bool V3Options::fileStatDir(const string& filename) {
struct stat m_stat; // Stat information
int err = stat(filename.c_str(), &m_stat);
@@ -397,7 +430,7 @@ bool V3Options::wildmatch(const char* s, const char* p) {
string V3Options::downcase(const string& str) {
string out = str;
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
*pos = tolower(*pos);
}
return out;
@@ -421,7 +454,7 @@ string V3Options::version() {
string V3Options::argString (int argc, char** argv) {
// Return list of arguments as simple string
string opts;
for (int i=0; i<argc; i++) {
for (int i=0; i<argc; ++i) {
if (i!=0) opts += " ";
opts += string(argv[i]);
}
@@ -469,7 +502,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
// Parse parameters
// Note argc and argv DO NOT INCLUDE the filename in [0]!!!
// May be called recursively when there are -f files.
for (int i=0; i<argc; i++) {
for (int i=0; i<argc; ++i) {
addArg(argv[i]); // -f's really should be inserted in the middle, but this is for debug
}
#define shift { ++i; }
@@ -481,7 +514,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
addDefine (string (sw+strlen("+define+")));
}
else if ( !strncmp (sw, "+incdir+", 8)) {
addIncDir (string (sw+strlen("+incdir+")));
addIncDir (filenameSubstitute(string (sw+strlen("+incdir+"))));
}
else if ( !strncmp (sw, "+libext+", 8)) {
string exts = string(sw+strlen("+libext+"));
@@ -503,7 +536,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
char *sw = argv[i];
bool flag = true;
// Allow gnu -- switches
if (sw[0]=='-' && sw[1]=='-') sw++;
if (sw[0]=='-' && sw[1]=='-') ++sw;
// Switch tests
if ( !strcmp (sw, "-debug") ) {
setDebugMode(3);
@@ -551,7 +584,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
}
else if ( !strcmp (sw, "-v") ) {
shift;
V3Options::addLibraryFile(argv[i]);
V3Options::addLibraryFile(filenameSubstitute(argv[i]));
}
else if ( !strcmp (sw, "-version") ) {
cout <<version();
@@ -563,6 +596,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-MMD", flag/*ref*/) ) { m_makeDepend = flag; }
else if ( onoff (sw, "-MP", flag/*ref*/) ) { m_makePhony = flag; }
else if ( onoff (sw, "-assert", flag/*ref*/) ) { m_assert = flag; m_psl = flag; }
else if ( onoff (sw, "-autoflush", flag/*ref*/) ) { m_autoflush = flag; }
else if ( !strcmp (sw, "-cc") ) { m_outFormatOk = true; m_systemC = false; m_systemPerl = false; }
else if ( onoff (sw, "-coverage", flag/*ref*/) ) { coverage(flag); }
else if ( onoff (sw, "-coverage-line", flag/*ref*/) ){ m_coverageLine = flag; }
@@ -589,7 +623,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; }
// Optimization
else if ( !strncmp (sw, "-O", 2) ) {
for (char* cp=sw+strlen("-O"); *cp; cp++) {
for (char* cp=sw+strlen("-O"); *cp; ++cp) {
flag = isupper(*cp);
switch (tolower(*cp)) {
case '0': optimize(0); break; // 0=all off
@@ -630,6 +664,22 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else if ( !strncmp (sw, "-U", 2)) {
V3PreShell::undef (string (sw+strlen("-U")));
}
else if ( !strncmp (sw, "-Werror-",strlen("-Werror-")) ) {
string msg = sw+strlen("-Werror-");
V3ErrorCode code (msg.c_str());
if (code == V3ErrorCode::ERROR) {
if (!isFuture(msg)) {
fl->v3fatal("Unknown warning specified: "<<sw);
}
} else {
V3Error::pretendError(code, true);
}
}
else if ( !strncmp (sw, "-Wfuture-",strlen("-Wfuture-")) ) {
string msg = sw+strlen("-Wfuture-");
// Note it may not be a future option, but one that is currently implemented.
addFuture(msg);
}
else if ( !strncmp (sw, "-Wno-",5) ) {
if (!strcmp (sw, "-Wno-lint")) {
FileLine::defaultFileLine().warnLintOff(true);
@@ -637,17 +687,19 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
else {
string msg = sw+strlen("-Wno-");
if (!(FileLine::defaultFileLine().warnOff(msg, true))) {
fl->v3fatal("Unknown warning disabled: "<<sw);
}
}
}
else if ( !strncmp (sw, "-Werror-",strlen("-Werror-")) ) {
string msg = sw+strlen("-Werror-");
V3ErrorCode code (msg.c_str());
if (code == V3ErrorCode::ERROR) {
fl->v3fatal("Unknown warning specified: "<<sw);
} else {
V3Error::pretendError(code, true);
}
}
}
else if ( !strncmp (sw, "-Wwarn-",5) ) {
if (!strcmp (sw, "-Wwarn-lint")) {
FileLine::defaultFileLine().warnLintOff(false);
}
else {
string msg = sw+strlen("-Wwarn-");
if (!(FileLine::defaultFileLine().warnOff(msg, false))) {
fl->v3fatal("Unknown warning specified: "<<sw);
}
}
}
else if ( !strcmp (sw, "-bin") && (i+1)<argc ) {
@@ -666,7 +718,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
}
else if ( !strcmp (sw, "-f") && (i+1)<argc ) {
shift;
parseOptsFile(fl, argv[i]);
parseOptsFile(fl, filenameSubstitute(argv[i]));
}
else if ( !strcmp (sw, "-gdb") && (i+1)<argc ) {
shift; // Used only in perl shell
@@ -685,6 +737,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
shift;
if (!strcmp (argv[i], "0")) { m_xAssign="0"; }
else if (!strcmp (argv[i], "1")) { m_xAssign="1"; }
else if (!strcmp (argv[i], "fast")) { m_xAssign="fast"; }
else if (!strcmp (argv[i], "unique")) { m_xAssign="unique"; }
else {
fl->v3fatal("Unknown setting for --x-assign: "<<argv[i]);
@@ -700,14 +753,14 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
} // - options
else {
// Filename
string filename = argv[i];
string filename = filenameSubstitute(argv[i]);
if (filename.find(".cpp") != string::npos
|| filename.find(".cxx") != string::npos
|| filename.find(".cc") != string::npos
|| filename.find(".sp") != string::npos) {
V3Options::addCppFile(argv[i]);
V3Options::addCppFile(filename);
} else {
V3Options::addVFile(argv[i]);
V3Options::addVFile(filename);
}
shift;
}
@@ -735,17 +788,17 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename) {
getline(*ifp, line);
// Strip simple comments
string oline;
for (string::const_iterator pos = line.begin(); pos != line.end(); pos++) {
for (string::const_iterator pos = line.begin(); pos != line.end(); ++pos) {
if (inCmt) {
if (*pos=='*' && *(pos+1)=='/') {
inCmt = false;
pos++;
++pos;
}
} else if (*pos=='/' && *(pos+1)=='/') {
break; // Ignore to EOL
} else if (*pos=='/' && *(pos+1)=='*') {
inCmt = true;
pos++;
++pos;
} else {
oline += *pos;
}
@@ -768,9 +821,9 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename) {
vector<string> args;
string::size_type startpos = 0;
while (startpos < whole_file.length()) {
while (isspace(whole_file[startpos])) startpos++;
while (isspace(whole_file[startpos])) ++startpos;
string::size_type endpos = startpos;
while (endpos < whole_file.length() && !isspace(whole_file[endpos])) endpos++;
while (endpos < whole_file.length() && !isspace(whole_file[endpos])) ++endpos;
if (startpos != endpos) {
string arg (whole_file, startpos, endpos-startpos);
args.reserve(args.size()+1);
@@ -781,7 +834,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename) {
// Convert to argv style arg list and parse them
char* argv [args.size()+1];
for (unsigned i=0; i<args.size(); i++) {
for (unsigned i=0; i<args.size(); ++i) {
argv[i] = (char*)args[i].c_str();
}
parseOptsList(fl, args.size(), argv);
@@ -792,6 +845,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename) {
V3Options::V3Options() {
m_impp = new V3OptionsImp;
m_autoflush = false;
m_coverageLine = false;
m_coverageUser = false;
m_debugCheck = false;
@@ -803,7 +857,7 @@ V3Options::V3Options() {
m_makeDepend = true;
m_makePhony = false;
m_outFormatOk = false;
m_pins64 = false;
m_pins64 = true;
m_profileCFuncs = false;
m_preprocOnly = false;
m_psl = false;
@@ -830,7 +884,7 @@ V3Options::V3Options() {
m_makeDir = "obj_dir";
m_bin = "";
m_flags = "";
m_xAssign = "unique";
m_xAssign = "fast";
m_language = V3LangCode::mostRecent();
+9 -1
View File
@@ -79,6 +79,7 @@ class V3Options {
V3OptionsImp* m_impp; // Slow hidden options
V3StringSet m_cppFiles; // argument: C++ files to link against
V3StringSet m_futures; // argument: -Wfuture- list
V3StringSet m_libraryFiles; // argument: Verilog -v files
V3StringList m_vFiles; // argument: Verilog files to read
@@ -86,6 +87,7 @@ class V3Options {
bool m_makeDepend; // main switch: -MMD
bool m_makePhony; // main switch: -MP
bool m_assert; // main switch: --assert
bool m_autoflush; // main switch: --autoflush
bool m_coverageLine; // main switch: --coverage-block
bool m_coverageUser; // main switch: --coverage-func
bool m_debugCheck; // main switch: --debug-check
@@ -150,9 +152,10 @@ class V3Options {
private:
// METHODS
void addArg(const string& incdir);
void addDefine(const string& defline);
void addFuture(const string& flag);
void addIncDir(const string& incdir);
void addLibExt(const string& libext);
void addDefine(const string& defline);
void optimize(int level);
void coverage(bool flag) { m_coverageLine = m_coverageUser = flag; }
bool onoff(const char* sw, const char* arg, bool& flag);
@@ -182,6 +185,7 @@ class V3Options {
bool skipIdentical() const { return m_skipIdentical; }
bool stats() const { return m_stats; }
bool assertOn() const { return m_assert; } // assertOn as "assert" may be defined
bool autoflush() const { return m_autoflush; }
bool coverage() const { return m_coverageUser || m_coverageLine; }
bool coverageLine() const { return m_coverageLine; }
bool coverageUser() const { return m_coverageUser; }
@@ -217,11 +221,14 @@ class V3Options {
string modPrefix() const { return m_modPrefix; }
string topModule() const { return m_topModule; }
string xAssign() const { return m_xAssign; }
const V3StringSet& cppFiles() const { return m_cppFiles; }
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
const V3StringList& vFiles() const { return m_vFiles; }
const V3LangCode& language() const { return m_language; }
bool isFuture(const string& flag) const;
// ACCESSORS (optimization options)
bool oAcycSimp() const { return m_oAcycSimp; }
bool oCase() const { return m_oCase; }
@@ -259,6 +266,7 @@ class V3Options {
static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
static string filenameDir (const string& filename); ///< Return directory part of filename
static string filenameSubstitute (const string& filename); ///< Return filename with env vars removed
static void unlinkRegexp(const string& dir, const string& regexp);
// METHODS (environment)
+44 -4
View File
@@ -88,8 +88,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
@@ -256,7 +256,7 @@ private:
AstSenTree* m_deleteDomainp;// Delete this from tree
AstSenTree* m_settleDomainp;// Initial activation tree
OrderInputsVertex* m_inputsVxp; // Top level vertex all inputs point from
OrderSettleVertex* m_settleVxp; // Top level vertex all inputs point from
OrderSettleVertex* m_settleVxp; // Top level vertex all settlement vertexes point from
OrderLogicVertex* m_logicVxp; // Current statement being tracked, NULL=ignored
AstTopScope* m_topScopep; // Current top scope being processed
AstScope* m_scopetopp; // Scope under TOPSCOPE
@@ -341,6 +341,8 @@ private:
OrderVarVertex* processInsLoopNewVar(OrderVarVertex* oldVertexp, bool& createdr);
void processBrokeLoop();
void processCircular();
void processInputs();
void processInputsIterate(OrderEitherVertex* vertexp);
void processSensitive();
void processDomains();
void processDomainsIterate(OrderEitherVertex* vertexp);
@@ -927,6 +929,39 @@ void OrderVisitor::processBrokeLoop() {
}
}
//######################################################################
// Clock propagation
void OrderVisitor::processInputs() {
m_graph.userClearVertices(); // Vertex::user() // true if added as begin/end
processInputsIterate(m_inputsVxp);
}
void OrderVisitor::processInputsIterate(OrderEitherVertex* vertexp) {
// Propagate PrimaryIn through simple assignments
if (vertexp->user()) return; // Already processed
//UINFO(9," InIt "<<vertexp<<endl);
vertexp->user(true);
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(vertexp)) {
vvertexp->isFromInput(true);
}
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
OrderEitherVertex* toVertexp = (OrderEitherVertex*)edgep->top();
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(toVertexp)) {
processInputsIterate(vvertexp);
}
if (OrderLogicVertex* vvertexp = dynamic_cast<OrderLogicVertex*>(toVertexp)) {
if (AstNodeAssign* nodep = vvertexp->nodep()->castNodeAssign()) {
if (nodep->lhsp()->castVarRef()
&& nodep->rhsp()->castVarRef()) {
UINFO(9," Input reassignment: "<<vvertexp<<endl);
processInputsIterate(vvertexp);
}
}
}
}
}
//######################################################################
// Circular detection
@@ -936,7 +971,7 @@ void OrderVisitor::processCircular() {
// The change detect code will use this to force changedets
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
if (vvertexp->isClock() && !vvertexp->varScp()->varp()->isPrimaryIn()) {
if (vvertexp->isClock() && !vvertexp->isFromInput()) {
// If a clock is generated internally, we need to do another loop
// through the entire evaluation. This fixes races; see t_clk_dpulse test.
UINFO(5,"Circular Clock "<<vvertexp<<endl);
@@ -947,6 +982,7 @@ void OrderVisitor::processCircular() {
if (edgep->weight()==0) { // was cut
OrderEdge* oedgep = dynamic_cast<OrderEdge*>(edgep);
if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type");
UINFO(6," CutCircularO: "<<vvertexp->name()<<endl);
nodeMarkCircular(vvertexp, oedgep);
}
}
@@ -954,6 +990,7 @@ void OrderVisitor::processCircular() {
if (edgep->weight()==0) { // was cut
OrderEdge* oedgep = dynamic_cast<OrderEdge*>(edgep);
if (!oedgep) vvertexp->varScp()->v3fatalSrc("Cuttable edge not of proper type");
UINFO(6," CutCircularI: "<<vvertexp->name()<<endl);
nodeMarkCircular(vvertexp, oedgep);
}
}
@@ -1542,6 +1579,9 @@ void OrderVisitor::process() {
m_graph.order();
m_graph.dumpDotFilePrefixed("orderg_order");
UINFO(2," Process Clocks...\n");
processInputs(); // must be before processCircular
#ifndef NEW_ORDERING
UINFO(2," Process Circulars...\n");
processCircular(); // must be before processDomains
+31 -4
View File
@@ -18,6 +18,30 @@
// GNU General Public License for more details.
//
//*************************************************************************
// OrderGraph Class Hierarchy:
//
// V3GraphVertex
// OrderMoveVertex
// OrderEitherVertex
// OrderInputsVertex
// OrderSettleVertex
// OrderLogicVertex
// OrderLoopBeginVertex
// OrderLoopEndVertex
// OrderVarVertex
// OrderVarStdVertex
// OrderVarPreVertex
// OrderVarPostVertex
// OrderVarPordVertex
// OrderVarSettleVertex
//
// V3GraphEdge
// OrderEdge
// OrderChangeDetEdge
// OrderComboCutEdge
// OrderPostCutEdge
// OrderPreCutEdge
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
@@ -168,20 +192,23 @@ public:
class OrderVarVertex : public OrderEitherVertex {
AstVarScope* m_varScp;
bool m_isClock; // Used as clock
OrderVarVertex* m_pilNewVertexp; // for processInsLoopNewVar
bool m_isClock; // Used as clock
bool m_isFromInput; // From input, or derrived therefrom (conservatively false)
public:
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp), m_isClock(false)
, m_pilNewVertexp(NULL)
: OrderEitherVertex(graphp, scopep, NULL), m_varScp(varScp)
, m_pilNewVertexp(NULL), m_isClock(false), m_isFromInput(false)
{}
virtual ~OrderVarVertex() {}
virtual OrderVarVertex* clone (V3Graph* graphp) const = 0;
virtual OrderVEdgeType type() const = 0;
// Accessors
AstVarScope* varScp() const { return m_varScp; }
void isClock(bool clk) { m_isClock=clk; }
void isClock(bool flag) { m_isClock=flag; }
bool isClock() const { return m_isClock; }
void isFromInput(bool flag) { m_isFromInput=flag; }
bool isFromInput() const { return m_isFromInput; }
OrderVarVertex* pilNewVertexp() const { return m_pilNewVertexp; }
void pilNewVertexp (OrderVarVertex* vertexp) { m_pilNewVertexp = vertexp; }
};
+2 -2
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <vector>
+2 -2
View File
@@ -21,8 +21,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <fstream>
#include <stack>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <iostream>
#include <algorithm>
+25 -2
View File
@@ -23,12 +23,15 @@
// For each wide OP, make a a temporary variable with the wide value
// For each deep expression, assign expression to temporary.
//
// Each display (independant transformation; here as Premit is a good point)
// If autoflush, insert a flush
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <list>
@@ -264,6 +267,26 @@ private:
checkNode(nodep);
}
// Autoflush
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
startStatement(nodep);
nodep->iterateChildren(*this);
m_stmtp = NULL;
if (v3Global.opt.autoflush()) {
AstNode* searchp = nodep->nextp();
while (searchp && searchp->castComment()) searchp = searchp->nextp();
if (searchp
&& searchp->castDisplay()
&& nodep->filep()->sameTree(searchp->castDisplay()->filep())) {
// There's another display next; we can just wait to flush
} else {
UINFO(4,"Autoflush "<<nodep<<endl);
nodep->addNextHere(new AstFFlush(nodep->fileline(),
nodep->filep()->cloneTree(true)));
}
}
}
//--------------------
// Default: Just iterate
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
+5 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <fstream>
@@ -181,6 +181,9 @@ void V3Read::lexFile(const string& modname) {
bool V3Read::optPsl() {
return v3Global.opt.psl();
}
bool V3Read::optFuture(const string& flag) {
return v3Global.opt.isFuture(flag);
}
//======================================================================
// Lex internal functions
+1
View File
@@ -56,6 +56,7 @@ protected:
friend class V3PreShellImp;
int yylexThis();
static bool optPsl();
static bool optFuture(const string& flag);
static void ppline (const char* text);
static void incLineno() { s_readp->fileline()->incLineno(); }
static void verilatorCmtLint(const char* text, bool on);
+2 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <iomanip>
+2 -2
View File
@@ -36,8 +36,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <algorithm>
+11 -2
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
@@ -80,6 +80,11 @@ private:
virtual void visit(AstIsUnknown* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot0* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFEof* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetC* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstSScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
@@ -102,6 +107,10 @@ private:
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//========
// Signed: Output signed
virtual void visit(AstRand* nodep, AstNUser*) { signed_Os_Ix(nodep); }
//=======
// Signed: Output signed iff LHS signed; unary operator
virtual void visit(AstNot* nodep, AstNUser*) { signed_Olhs(nodep); }
+2 -2
View File
@@ -51,8 +51,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+2 -2
View File
@@ -27,8 +27,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
+2 -2
View File
@@ -20,8 +20,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
+4 -4
View File
@@ -28,8 +28,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
#include <vector>
@@ -276,7 +276,7 @@ private:
if (AstVarRef* varrefp = wordp->lhsp()->castVarRef()) {
if (wordp->rhsp()->castConst()
&& varrefp->varp()->isStatementTemp()) {
int word = wordp->rhsp()->castConst()->asInt();
int word = wordp->rhsp()->castConst()->toUInt();
SubstVarEntry* entryp = getEntryp(varrefp);
hit = true;
if (m_ops > SUBST_MAX_OPS_SUBST) {
@@ -313,7 +313,7 @@ private:
&& constp) {
// Nicely formed lvalues handled in NodeAssign
// Other lvalues handled as unknown mess in AstVarRef
int word = constp->asInt();
int word = constp->toUInt();
UINFO(8," USEword"<<word<<" "<<varrefp<<endl);
SubstVarEntry* entryp = getEntryp(varrefp);
if (AstNode* substp = entryp->substWord (nodep, word)) {
+2 -2
View File
@@ -23,8 +23,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
+3 -3
View File
@@ -27,10 +27,10 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <math.h>
#include <cmath>
#include <deque>
#include "V3Global.h"
+4 -3
View File
@@ -29,8 +29,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
@@ -208,7 +208,8 @@ private:
virtual void visit(AstVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->varp()->user4p() != m_curVxp) {
if (m_curVxp->pure()) {
if (m_curVxp->pure()
&& !nodep->varp()->isPure()) {
m_curVxp->impure(nodep);
}
}
+2 -2
View File
@@ -48,8 +48,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <set>
#include <map>
+2 -2
View File
@@ -26,8 +26,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include "V3Global.h"
+5 -4
View File
@@ -33,8 +33,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
@@ -191,10 +191,11 @@ private:
UINFO(4," -> "<<newp<<endl);
} else {
// Make a Vxrand variable
// We use the special XTEMP type so it doesn't break pure functions
string newvarname = ((string)"__Vxrand__"
+cvtToStr(m_modp->varNumGetInc()));
AstVar* newvarp
= new AstVar (nodep->fileline(), AstVarType::MODULETEMP, newvarname,
= new AstVar (nodep->fileline(), AstVarType::XTEMP, newvarname,
new AstRange(nodep->fileline(), nodep->width()-1, 0));
m_statUnkVars++;
AstNRelinker replaceHandle;
@@ -212,7 +213,7 @@ private:
new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(),numbx),
new AstRand(nodep->fileline(),
nodep->width())))));
nodep->width(), true)))));
// Add inits in front of other statement.
// In the future, we should stuff the initp into the module's constructor.
AstNode* afterp = m_modp->stmtsp()->unlinkFrBackWithNext();
+17 -11
View File
@@ -30,8 +30,8 @@
#include "config_build.h"
#include "verilatedos.h"
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <algorithm>
@@ -76,6 +76,11 @@ private:
return false;
}
int unrollCount() {
return m_generate ? v3Global.opt.unrollCount()*16
: v3Global.opt.unrollCount();
}
bool forUnrollCheck(AstNode* nodep,
AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp)
AstNode* precondsp, AstNode* condp,
@@ -158,16 +163,16 @@ private:
|| constStopp->width()>32 || constStopp->num().isFourState()
|| constIncp->width()>32 || constIncp->num().isFourState())
return cantUnroll(nodep, "init/final/increment too large or four state");
vlsint32_t valInit = constInitp->num().asInt(); // Extract as unsigned, then make signed
vlsint32_t valStop = constStopp->num().asInt(); // Extract as unsigned, then make signed
vlsint32_t valInit = constInitp->num().toSInt();
vlsint32_t valStop = constStopp->num().toSInt();
if (lte) valStop++; if (gte) valStop--;
vlsint32_t valInc = constIncp->num().asSInt();
vlsint32_t valInc = constIncp->num().toSInt();
if (subtract) valInc = -valInc;
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
//
if (!m_generate) {
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<v3Global.opt.unrollCount()<<endl);
if (((valStop - valInit)/valInc) > v3Global.opt.unrollCount())
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<unrollCount()<<endl);
if (((valStop - valInit)/valInc) > unrollCount())
return cantUnroll(nodep, "too many iterations");
// Less than 10 statements in the body?
@@ -253,8 +258,8 @@ private:
else newbodysp = oneloopp;
m_statIters++;
if (++times > v3Global.opt.unrollCount()*3) {
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop.");
if (++times > unrollCount()*3) {
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount());
break;
}
@@ -347,9 +352,10 @@ private:
) {
// Rename it, as otherwise we may get a conflict
// V3Begin sees these DOTs and makes CellInlines for us.
string nname = (string)"genfor"+cvtToStr(m_varValuep->asInt())+"__DOT__"+nodep->name();
string index = AstNode::encodeNumber(m_varValuep->toSInt());
string nname = (string)"genfor"+index+"__DOT__"+nodep->name();
// Verilog seems to drop the for loop name and tack on [#]
nname = nodep->name() + "__BRA__" + cvtToStr(m_varValuep->asInt()) + "__KET__";
nname = nodep->name() + "__BRA__" + index + "__KET__";
//UINFO(8," Rename begin "<<nname<<" "<<nodep<<endl);
nodep->name(nname);
}

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