Compare commits

...
97 Commits
Author SHA1 Message Date
Wilson Snyder 379177d2f4 Version bump 2017-09-23 10:04:52 -04:00
Wilson Snyder fb193d6172 Internals: Ignore gmon.out 2017-09-23 09:52:06 -04:00
Wilson Snyder 16234bb713 Tests: Call driver's run instead of private _run. 2017-09-23 08:50:39 -04:00
Wilson Snyder 3f14e649b5 Internals: Use singleton in place of global 2017-09-23 07:44:52 -04:00
Wilson Snyder c2e8062f84 Verilated headers no longer "use namespace std;" 2017-09-23 07:32:37 -04:00
Wilson Snyder 5d3fef21b0 Cleanup misc spacing and unneeded stuff in emitted headers. 2017-09-22 22:27:03 -04:00
Wilson Snyder b64e1b4a49 Fix inverted sync/async message. 2017-09-22 18:57:53 -04:00
Wilson Snyder 89f414b185 Less verbosity for IEEE warnings in earlier commit this rev. 2017-09-21 22:07:49 -04:00
Wilson Snyder 47e13cfdf4 Optimize concat/replicate+replicate. 2017-09-21 21:05:42 -04:00
Wilson Snyder 48d3ce46d8 Commenary 2017-09-21 18:39:23 -04:00
Wilson Snyder 89c8449ec0 Support package export, bug1217. 2017-09-20 21:04:59 -04:00
Xavier Delacour 331fcb633e Update .gitconfig 2017-09-20 07:57:09 -04:00
Wilson Snyder bffc2233a0 Commentary about IMPERFECTSCH. Add test. 2017-09-19 21:01:03 -04:00
Wilson Snyder 393b5d48b2 Better optimize Shift-And constructs. 2017-09-19 20:56:17 -04:00
Wilson Snyder 6006cdff2c Fix wide array indices causing compile error. 2017-09-19 20:04:45 -04:00
Wilson Snyder d6b10465f3 Improve more errors to note IEEE 2017-09-18 23:06:31 -04:00
Wilson Snyder b3cf5c4f5f Improve error to note common :: package errors 2017-09-18 22:54:54 -04:00
Wilson Snyder 3862f2f022 Note IEEE in 32 bit decimal oversized 2017-09-18 22:50:26 -04:00
Wilson Snyder 38ab22bf1d Simplify VL_CONST_W macro generation for faster compiles. 2017-09-18 21:36:18 -04:00
Wilson Snyder ce16f7689d Fix clang 3.8 warnings 2017-09-18 20:05:56 -04:00
Wilson Snyder b06a329466 Fix GCC 4.4 false warning 2017-09-18 08:30:04 -04:00
Wilson Snyder c5b24f3850 Internals: Remove dead code, bug1215. 2017-09-18 07:13:58 -04:00
Wilson Snyder 103b956581 Default to -O2 for Verilator itself, for 20%+ 2017-09-17 23:25:20 -04:00
Wilson Snyder 63361fc56e Add performance information to --stats file. 2017-09-17 22:52:57 -04:00
Wilson Snyder 1e9e334929 Internals: Name cleanup. No functional change. 2017-09-16 11:06:35 -04:00
Wilson Snyder f30d71b0c5 Internals: Better prefetching for ~5%. 2017-09-16 07:55:48 -04:00
Wilson Snyder fee4aba9ec Internals: Fix GCC constant warnings. 2017-09-15 18:26:09 -04:00
Wilson Snyder f1960273a0 Internals: Fix over-aggressive debug 2017-09-15 18:25:52 -04:00
Wilson Snyder 778564e63b Compling: Turn on -Wextra when using --enable-ccwarn 2017-09-14 23:28:02 -04:00
Wilson Snyder cf6a69da27 Internals: Fix some cast and fallthrough warnings. No functional change 2017-09-14 23:27:06 -04:00
Wilson Snyder 960b2ed023 Internals: Fix some shadow and other warnings. No functional change 2017-09-14 23:26:23 -04:00
Mike Popoloski 74420550e6 Fix .name connections on interfaces, bug1214.
Signed-off-by: Wilson Snyder <[email protected]>
2017-09-14 21:24:13 -04:00
Mike Popoloski cb5887b376 Support module port parameters without defaults, bug 1213.
Signed-off-by: Wilson Snyder <[email protected]>
2017-09-14 21:20:20 -04:00
Wilson Snyder 41b40157d8 Fix non-colon array of interface modports, bug1212. 2017-09-14 21:15:56 -04:00
Wilson Snyder b11b693c08 Fix constant function default parameters, bug1211. 2017-09-13 19:47:11 -04:00
Wilson Snyder 256eb4bba0 Support or/and/xor array intrinsic methods, bug1210. 2017-09-13 19:37:47 -04:00
Wilson Snyder 77804b4d38 Fix GCC noreturn compile error, bug1209. 2017-09-13 19:27:59 -04:00
Wilson Snyder 8c9ca7a1b3 Fix LITENDIAN warning on arrayed cells, bug1202. 2017-09-13 19:09:49 -04:00
Wilson Snyder 9d055f8c13 Fix ordering of arrayed cell wide connections, bug1202 partial. 2017-09-12 19:34:10 -04:00
Wilson Snyder 3dacd87dfb Fix enum ranges without colons, bug1204. 2017-09-12 18:53:57 -04:00
Wilson Snyder 691fbb0c42 Tests: Support newer VCS. 2017-09-12 18:42:58 -04:00
Wilson Snyder c28a6eef3b Fix whitespace issues, bug1203. 2017-09-11 19:18:58 -04:00
Wilson Snyder 17fed3fedd devel release 2017-09-07 21:15:48 -04:00
Wilson Snyder 1448cc56fc Version bump 2017-09-07 21:10:22 -04:00
Wilson Snyder 074689b5de SystemPerl mode (-sp-deprecated) has been removed. 2017-09-07 21:08:49 -04:00
Wilson Snyder 8dd612a0a0 Commentary, bug1198. 2017-09-06 20:45:21 -04:00
Wilson Snyder 22fdbba0b5 Update keywords for C++11 etc, msg2325 2017-09-02 21:01:50 -04:00
Wilson Snyder 39b787670b Update keywords for C++11 etc, msg2325 2017-09-02 20:59:03 -04:00
Wilson Snyder a221278c05 Commentary 2017-08-31 19:45:53 -04:00
Wilson Snyder 5f26b9ec66 Internals: Remove dead putAlign, bug1093. 2017-08-28 23:01:19 -04:00
Wilson Snyder 48778d0a77 devel release 2017-08-28 22:51:53 -04:00
Wilson Snyder 42d2cbad41 Version bump 2017-08-28 22:46:43 -04:00
Wilson Snyder cb82c42e35 Test for bug1191. 2017-08-28 22:41:38 -04:00
Wilson Snyder f13fb330ed Reenable -Wchar-subscripts and sort flag list 2017-08-14 20:15:24 -04:00
Wilson Snyder d4bae48ca2 Fix GCC7.1 warning on new alignment 2017-08-14 19:59:21 -04:00
Wilson Snyder 590ad964b1 Add assertion on bad formed lvalues, used to debug bug1187. 2017-08-13 18:08:44 -04:00
Wilson Snyder d4595df8a4 Fix internal error on unconnected inouts, bug1187. 2017-08-13 18:08:24 -04:00
Wilson Snyder 7b642bcbb4 Support packed struct DPI imports, bug1190. 2017-08-11 19:07:47 -04:00
Wilson Snyder ca26596695 Fix undefined VL_POW_WWI. 2017-07-12 20:08:32 -04:00
Wilson Snyder 88cf5e5d98 Fix realloc leak on out-of-memory 2017-07-12 18:54:27 -04:00
Wilson Snyder 13f790360d Fix compile error on unused VL_VALUEPLUSARGS_IW, bug1181. 2017-07-07 07:50:45 -04:00
Wilson Snyder 70daadf987 Fix cpp-check warnings; support XML format 2 2017-07-06 20:25:59 -04:00
Wilson Snyder 9d5004db1c Fix GCC 7 warnings. 2017-07-06 19:49:34 -04:00
Wilson Snyder ea82bfcced Fix GCC 6 warnings. 2017-07-06 19:07:23 -04:00
Wilson Snyder 00a502942e Fix valueplus exceeding array bounds. 2017-07-06 19:01:35 -04:00
Wilson Snyder 2031bc7fc4 Commentary 2017-07-05 19:06:22 -04:00
Wilson Snyder 3adb22e971 Support x in , 2017-07-05 18:51:06 -04:00
Wilson Snyder 331ea5116f devel release 2017-06-22 18:36:29 -04:00
Wilson Snyder 1da5a33f88 Version bump 2017-06-22 18:31:22 -04:00
Wilson Snyder 6c87724af8 Support set_time_unit/set_time_precision in C traces, msg2261. 2017-06-20 19:33:58 -04:00
Wilson Snyder c7a5ff5e82 Tests: Fix broken vgen test, commentary. 2017-06-20 19:10:18 -04:00
Wilson Snyder abf2fcf820 Fix .* on interface pins, bug1176. 2017-06-20 18:40:18 -04:00
Wilson Snyder 644c22b08f Fix extract of packed array with non-zero LSB, bug1172. 2017-06-06 20:06:23 -04:00
Wilson Snyder c54024a5e6 Fix constant shifts by more than 32-bit numbers, bug1174 continued. 2017-06-05 21:15:31 -04:00
Wilson Snyder 97093fdf81 Fix power operator on wide constants, bug761. 2017-06-05 20:30:01 -04:00
Wilson Snyder 50c4f60c68 Internals: Favor preincrement. No functional change. 2017-06-05 20:16:51 -04:00
Wilson Snyder f0fb3b78d1 Internals: New VL_ZERO_W for faster inline. Prefer WData for wide. No functional change intended. 2017-06-05 20:04:09 -04:00
Wilson Snyder 9b06178f35 Fix shifts by more than 32-bit numbers, bug1174. 2017-06-05 07:56:59 -04:00
Wilson Snyder a01c96140b devel release 2017-05-30 22:04:58 -04:00
Wilson Snyder 02530172e7 Version bump 2017-05-30 22:01:21 -04:00
Wilson Snyder 447d803800 Fix internal clang warnings. 2017-05-24 23:51:15 -04:00
Wilson Snyder 6b04901c4d Fix testplusargs false width warning, bug1165. 2017-05-19 07:20:41 -04:00
Wilson Snyder 7fb29621c3 Fix interface functions returning wrong parameters, bug996. 2017-05-18 22:49:17 -04:00
Wilson Snyder b032fce962 Support $value$plusargs with variables, bug1165. 2017-05-18 22:41:43 -04:00
Wilson Snyder ce879122bb Fix --assert with complex case statements, bug1164. 2017-05-17 20:15:40 -04:00
Todd Strader 2fa16708b7 Fix non-arrayed cells with interface arrays, bug1153.
Signed-off-by: Wilson Snyder <[email protected]>
2017-05-10 19:05:42 -04:00
Todd Strader 54bc8608e3 Add stack trace when can't optimize function, bug1158.
Signed-off-by: Wilson Snyder <[email protected]>
2017-05-09 18:54:15 -04:00
Todd Strader 706a7802cc Fix non-cutable ordering loops on clock arrays, bug1009.
Signed-off-by: Wilson Snyder <[email protected]>
2017-05-09 08:05:21 -04:00
Wilson Snyder 9dc01cf540 Support arrayed parameter overrides, bug1153. 2017-05-02 19:16:54 -04:00
Wilson Snyder 8943ad5966 internals: Remove extra newlines on v3fatalSrc. No functional change. 2017-04-28 20:09:27 -04:00
Wilson Snyder deb7a1c9c0 Fix non-arrayed cells with interface arrays, bug1153. 2017-04-28 20:03:38 -04:00
Wilson Snyder 96a5445d44 Support ports of array of reals, bug1154. 2017-04-28 06:10:14 -04:00
Wilson Snyder d693065afb Fix backwards array interface error message 2017-04-27 06:36:14 -04:00
Wilson Snyder bdeee35669 Add warning on mis-sized literal, bug1156. 2017-04-26 18:34:01 -04:00
Wilson Snyder 62b3deb90d Tests: Improve vams to attach wire. 2017-04-04 19:15:15 -04:00
Wilson Snyder 9df9ff59e0 Commentary 2017-04-03 20:02:19 -04:00
Wilson Snyder 23a3271c06 devel release 2017-04-02 08:49:31 -04:00
328 changed files with 6933 additions and 2131 deletions
+4
View File
@@ -1,3 +1,5 @@
\#*
.#*
*~
*.old
*.gz
@@ -20,8 +22,10 @@ configure
dddrun*
doxygen-doc
gdbrun*
gmon.out
internals.txt
verilator.txt
verilator_bin*
verilator_coverage_bin*
verilator.pc
**/obj_dir/*
+91
View File
@@ -2,6 +2,97 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 3.912 2017-09-23
** Verilated headers no longer "use namespace std;"
User's code without "std::" prefixes may need "use namespace std;" to compile.
*** Support or/and/xor array intrinsic methods, bug1210. [Mike Popoloski]
*** Support package export, bug1217. [Usuario Eda]
*** Fix ordering of arrayed cell wide connections, bug1202 partial. [Mike Popoloski]
**** Support module port parameters without defaults, bug 1213. [Mike Popoloski]
**** Add performance information to --stats file.
**** Simplify VL_CONST_W macro generation for faster compiles.
**** Fix LITENDIAN warning on arrayed cells, bug1202. [Mike Popoloski]
**** Fix enum ranges without colons, bug1204. [Mike Popoloski]
**** Fix GCC noreturn compile error, bug1209. [Mike Popoloski]
**** Fix constant function default parameters, bug1211. [Mike Popoloski]
**** Fix non-colon array of interface modports, bug1212. [Mike Popoloski]
**** Fix .name connections on interfaces, bug1214. [Mike Popoloski]
**** Fix wide array indices causing compile error.
**** Better optimize Shift-And, and replication constructs.
* Verilator 3.910 2017-09-07
*** SystemPerl mode (-sp-deprecated) has been removed.
**** Update keyword warnings to include C++11 and others.
* Verilator 3.908 2017-08-28
**** Support x in $readmem, bug1180. [Arthur Kahlich]
**** Support packed struct DPI imports, bug1190. [Rob Stoddard]
**** Fix GCC 6 warnings.
**** Fix compile error on unused VL_VALUEPLUSARGS_IW, bug1181. [Thomas J Whatson]
**** Fix undefined VL_POW_WWI. [Clifford Wolf]
**** Fix internal error on unconnected inouts, bug1187. [Rob Stoddard]
* Verilator 3.906 2017-06-22
*** Support set_time_unit/set_time_precision in C traces, msg2261.
*** Fix extract of packed array with non-zero LSB, bug1172. [James Pallister]
*** Fix shifts by more than 32-bit numbers, bug1174. [Clifford Wolf]
*** Fix power operator on wide constants, bug761. [Clifford Wolf]
*** Fix .* on interface pins, bug1176. [Maciej Piechotka]
* Verilator 3.904 2017-05-30
*** Fix non-cutable ordering loops on clock arrays, bug1009. [Todd Strader]
*** Support ports of array of reals, bug1154. [J Briquet]
*** Support arrayed parameter overrides, bug1153. [John Stevenson]
*** Support $value$plusargs with variables, bug1165. [Wesley Terpstra]
**** Support modport access to un-modport objects, bug1161. [Todd Strader]
**** Add stack trace when can't optimize function, bug1158. [Todd Strader]
**** Add warning on mis-sized literal, bug1156. [Todd Strader]
**** Fix interface functions returning wrong parameters, bug996. [Todd Strader]
**** Fix non-arrayed cells with interface arrays, bug1153. [John Stevenson]
**** Fix --assert with complex case statements, bug1164. [Enzo Chi]
* Verilator 3.902 2017-04-02
+1 -1
View File
@@ -51,7 +51,7 @@ output (not Verilator itself) compiles under MSVC++ 2008 and newer.
=head1 INSTALLATION
For more details see
For more details see
L<http://www.veripool.org/projects/verilator/wiki/Installing>.
If you will be modifying Verilator, you should use the "git" method as it
+1 -1
View File
@@ -41,7 +41,7 @@ Testing:
* // verilator debug in code so can see only tree affecting those nodes
Usability:
* Detect and pre-remove most UNOPTFLATs (4.000)
* Detect and pre-remove most UNOPTFLATs (4.000)
* Better reporting of unopt problems, including what lines of code
* Report more errors (all of them?) before exiting [Eugene Weber]
* Auto-create scons config files
+71 -41
View File
@@ -182,7 +182,9 @@ sub run {
warn "%Error: $command\n";
}
if ($status & 127) {
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
if (($status & 127) == 4 # SIGILL
|| ($status & 127) == 8 # SIGFPA
|| ($status & 127) == 11) { # SIGSEGV
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
} elsif (($status & 127) == 6) { # SIGABRT
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
@@ -349,7 +351,8 @@ descriptions in the next sections for more information.
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
--vpi Enable VPI compiles
-Werror-<message> Convert warning to error
-Wall Enable all style warnings
-Werror-<message> Convert warnings to errors
-Wfuture-<message> Disable unknown message warnings
-Wno-<message> Disable warning
-Wno-lint Disable all lint warnings
@@ -483,7 +486,7 @@ interest in adding more traditional CDC checks, please contact the authors.
Sometimes it is quite difficult for Verilator to distinguish clock signals from
other data signals. Occasionally the clock signals can end up in the checking
list of signals which determines if further evaluation is needed. This will
heavily degrade the performance of verilated model.
heavily degrade the performance of a Verilated model.
With --clk <signal-name>, user can specified root clock into the model, then
Verilator will mark the signal as clocker and propagate the clocker attribute
@@ -495,6 +498,10 @@ If the signal is the input to top-module, the directly the signal name. If you
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
RTL file to mark the signal directly.
If clock signals are assigned to vectors and then later used individually,
Verilator will attempt to decompose the vector and connect the single-bit
clock signals directly. This should be transparent to the user.
=item --compiler I<compiler-name>
Enables tunings and workarounds for the specified C++ compiler.
@@ -509,7 +516,7 @@ breaking deep structures as for msvc as described below.
=item gcc
Tune for Gnu C++, although generated code should work on almost any
Tune for GNU C++, although generated code should work on almost any
compliant C++ compiler. Currently the default.
=item msvc
@@ -907,7 +914,7 @@ developers.
=item --output-split I<bytes>
Enables splitting the output .cpp/.sp files into multiple outputs. When a
Enables splitting the output .cpp files into multiple outputs. When a
C++ file exceeds the specified number of operations, a new file will be
created at the next function boundary. In addition, any slow routines will
be placed into __Slow files. This accelerates compilation by as
@@ -919,7 +926,7 @@ one-minute-compile chunks.
=item --output-split-cfuncs I<statements>
Enables splitting functions in the output .cpp/.sp files into multiple
Enables splitting functions in the output .cpp files into multiple
functions. When a generated function exceeds the specified number of
operations, a new function will be created. With --output-split, this will
enable GCC to compile faster, at a small loss in performance that gets
@@ -929,7 +936,7 @@ function.
=item --output-split-ctrace I<statements>
Enables splitting trace functions in the output .cpp/.sp files into
Enables splitting trace functions in the output .cpp files into
multiple functions. Defaults to same setting as --output-split-cfuncs.
=item -P
@@ -1194,8 +1201,9 @@ Enable use of VPI and linking against the verilated_vpi.cpp files.
=item -Wall
Enable all warnings, including code style warnings that are normally
disabled by default.
Enable all code style warnings, including code style warnings that are
normally disabled by default. Equivelent to "-Wwarn-lint -Wwarn-style".
Excludes some specialty warnings, i.e. IMPERFECTSCH.
=item -Werror-I<message>
@@ -1426,8 +1434,8 @@ This is an example similar to the above, but using SystemC.
Verilated::commandArgs(argc, argv);
sc_clock clk ("clk",10, 0.5, 3, true);
Vour* top;
top = new Vour("top"); // SP_CELL (top, Vour);
top->clk(clk); // SP_PIN (top, clk, clk);
top = new Vour("top");
top->clk(clk);
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
delete top;
exit(0);
@@ -1506,7 +1514,7 @@ OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
the compiler or linker. Or, just for one run, pass them on the command
line to make:
make OPT_FAST="-O2" -f Vour.mk Vour__ALL.a
make OPT_FAST="-O2 -fno-stack-protector" -f Vour.mk Vour__ALL.a
OPT_FAST specifies optimizations for those programs that are part of the
fast path, mostly code that is executed every cycle. OPT_SLOW specifies
@@ -1913,54 +1921,71 @@ documented below.
Verilator has an important difference from an event based simulator; signal
values that are changed by the VPI will not immediately propagate their
values, instead the top level header file's eval() method must be called.
Normally this would be part of the normal evaluation (IE the next clock
Normally this would be part of the normal evaluation (i.e. the next clock
edge), not as part of the value change. This makes the performance of VPI
routines extremely fast compared to event based simulators, but can confuse
some test-benches that expect immediate propagation.
Note the VPI by it's specified implementation will always be much slower
Note the VPI by its specified implementation will always be much slower
than accessing the Verilator values by direct reference
(structure->module->signame), as the VPI accessors perform lookup in
functions at runtime requiring at best hundreds of instructions, while the
direct references are evaluated by the compiler and result in only a couple
of instructions.
For signal callbacks to work the main loop of the program must call
VerilatedVpi::callValueCbs().
=head2 VPI Example
In the below example, we have readme marked read-only, and writeme which if
written from outside the model will have the same semantics as if it
changed on the specified clock edge.
module t;
reg readme /*verilator public_flat_rd*/;
reg writeme /*verilator public_flat_rw @(posedge clk) */;
endmodule
cat <<EOF >our.v
module our (input clk);
reg readme /*verilator public_flat_rd*/;
reg writeme /*verilator public_flat_rw @(posedge clk) */;
initial $finish;
endmodule
EOF
There are many online tutorials and books on the VPI, but an example that
accesses the above would be:
accesses the above signal "readme" would be:
void read_and_check() {
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
if (!vh1) { error... }
const char* name = vpi_get_str(vpiName, vh1);
printf("Module name: %s\n"); // Prints "readme"
cat <<EOF >sim_main.cpp
#include "Vour.h"
#include "verilated.h"
#include "verilated_vpi.h" // Required to get definitions
s_vpi_value v;
v.format = vpiIntVal;
vpi_get_value(vh1, &v);
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
}
vluint64_t main_time = 0; // See comments in first example
double sc_time_stamp () { return main_time; }
For signal callbacks to work the main loop of the program must call
VerilatedVpi::callValueCbs().
void read_and_check() {
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"TOP.our.readme", NULL);
if (!vh1) { vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found"); }
const char* name = vpi_get_str(vpiName, vh1);
printf("Module name: %s\n", name); // Prints "readme"
#include "verilated_vpi.h" // Required to get definitions
...
while (time passes) {
...
topp->eval();
VerilatedVpi::callValueCbs();
}
s_vpi_value v;
v.format = vpiIntVal;
vpi_get_value(vh1, &v);
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
}
int main(int argc, char **argv, char **env) {
Verilated::commandArgs(argc, argv);
Vour* top = new Vour;
Verilated::internalsDump(); // See scopes to help debug
while (!Verilated::gotFinish()) {
top->eval();
VerilatedVpi::callValueCbs(); // For signal callbacks
read_and_check();
}
delete top;
exit(0);
}
EOF
=head1 CROSS COMPILATION
@@ -3133,8 +3158,8 @@ correctly.
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.
to off, is not part of -Wall, and must be turned on explicitly before the
top module statement is processed.
=item IMPLICIT
@@ -3184,6 +3209,11 @@ Warns that a packed vector is declared with little endian bit numbering
and little numbering is now thus often due to simple oversight instead of
intent.
Also warns that a cell is declared with little endian range (i.e. [0:7] or
[7]) and is connected to a N-wide signal. Based on IEEE the bits will
likely be backwards from what you expect (i.e. cell [0] will connect to
signal bit [N-1] not bit [0]).
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
@@ -3857,7 +3887,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->our->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
+22 -12
View File
@@ -6,8 +6,9 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.902 2017-04-02])
AC_INIT([Verilator],[3.912 2017-09-23])
# When releasing, also update header of Changes file
# and commit using "devel release" or "Version bump" message
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc)
@@ -139,35 +140,44 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
])# _MY_CXX_CHECK_OPT
# Flags for compiling Verilator internals including parser
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
# Flags for compiling Verilator internals including parser, and Verilated files
# These turn on extra warnings and are only used with 'configure --enable-ccwarn'
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wextra)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wlogical-op)
AC_SUBST(CFG_CXXFLAGS_WEXTRA)
# Flags for compiling Verilator internals including parser always
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-faligned-new)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow)
AC_SUBST(CFG_CXXFLAGS_SRC)
# Flags for compiling Verilator parser
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-unused)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-parentheses-equality)
# Flags for compiling Verilator parser always (in addition to above CFG_CXXFLAGS_SRC)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-null-conversion)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-parentheses-equality)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-unused)
AC_SUBST(CFG_CXXFLAGS_PARSER)
# Flags for Verilated makefile
# For example, -Wno-div-by-zero isn't in 4.1.2
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-char-subscripts)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-parentheses-equality)
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
# without this flag, even though there's a conditional to prevent the divide.
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-faligned-new)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-fbracket-depth=4096)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Qunused-arguments)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-parentheses-equality)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-sign-compare)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-but-set-variable)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-variable)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-fbracket-depth=4096)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Qunused-arguments)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-shadow)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
# Checks for library functions.
+226 -105
View File
@@ -115,7 +115,7 @@ QData VL_RANDOM_Q(int obits) {
}
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) {
for (int i=0; i<VL_WORDS_I(obits); ++i) {
if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = VL_RAND32();
} else {
@@ -146,7 +146,7 @@ QData VL_RAND_RESET_Q(int obits) {
}
WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) {
for (int i=0; i<VL_WORDS_I(obits); ++i) {
if (i<(VL_WORDS_I(obits)-1)) {
outwp[i] = VL_RAND_RESET_I(32);
} else {
@@ -157,7 +157,7 @@ WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) {
}
WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
for (int i=0; i<VL_WORDS_I(obits); i++) outwp[i] = 0;
for (int i=0; i<VL_WORDS_I(obits); ++i) outwp[i] = 0;
return outwp;
}
@@ -166,7 +166,7 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
VL_PRINTF(" Data: w%d: ", lbits);
for (int i=VL_WORDS_I(lbits)-1; i>=0; i--) { VL_PRINTF("%08x ",iwp[i]); }
for (int i=VL_WORDS_I(lbits)-1; i>=0; --i) { VL_PRINTF("%08x ",iwp[i]); }
VL_PRINTF("\n");
}
@@ -179,7 +179,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// for debug see V3Number version
// Requires clean input
int words = VL_WORDS_I(lbits);
for (int i=0; i<words; i++) owp[i]=0;
for (int i=0; i<words; ++i) owp[i]=0;
// Find MSB and check for zero.
int umsbp1 = VL_MOSTSETBITP1_W(words,lwp); // dividend
int vmsbp1 = VL_MOSTSETBITP1_W(words,rwp); // divisor
@@ -193,14 +193,14 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
if (vw == 1) { // Single divisor word breaks rest of algorithm
vluint64_t k = 0;
for (int j = uw-1; j >= 0; j--) {
for (int j = uw-1; j >= 0; --j) {
vluint64_t unw64 = ((k<<VL_ULL(32)) + (vluint64_t)(lwp[j]));
owp[j] = unw64 / (vluint64_t)(rwp[0]);
k = unw64 - (vluint64_t)(owp[j])*(vluint64_t)(rwp[0]);
}
if (is_modulus) {
owp[0] = k;
for (int i=1; i<words; i++) owp[i]=0;
for (int i=1; i<words; ++i) owp[i]=0;
}
return owp;
}
@@ -211,13 +211,13 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// Zero for ease of debugging and to save having to zero for shifts
// Note +1 as loop will use extra word
for (int i=0; i<words+1; i++) { un[i]=vn[i]=0; }
for (int i=0; i<words+1; ++i) { un[i]=vn[i]=0; }
// Algorithm requires divisor MSB to be set
// Copy and shift to normalize divisor so MSB of vn[vw-1] is set
int s = 31-VL_BITBIT_I(vmsbp1-1); // shift amount (0...31)
vluint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value
for (int i = vw-1; i>0; i--) {
for (int i = vw-1; i>0; --i) {
vn[i] = (rwp[i] << s) | (shift_mask & (rwp[i-1] >> (32-s)));
}
vn[0] = rwp[0] << s;
@@ -225,13 +225,13 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// Copy and shift dividend by same amount; may set new upper word
if (s) un[uw] = lwp[uw-1] >> (32-s);
else un[uw] = 0;
for (int i=uw-1; i>0; i--) {
for (int i=uw-1; i>0; --i) {
un[i] = (lwp[i] << s) | (shift_mask & (lwp[i-1] >> (32-s)));
}
un[0] = lwp[0] << s;
// Main loop
for (int j = uw - vw; j >= 0; j--) {
for (int j = uw - vw; j >= 0; --j) {
// Estimate
vluint64_t unw64 = ((vluint64_t)(un[j+vw])<<VL_ULL(32) | (vluint64_t)(un[j+vw-1]));
vluint64_t qhat = unw64 / (vluint64_t)(vn[vw-1]);
@@ -247,7 +247,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
vlsint64_t t = 0; // Must be signed
vluint64_t k = 0;
for (int i=0; i<vw; i++) {
for (int i=0; i<vw; ++i) {
vluint64_t p = qhat*vn[i]; // Multiply by estimate
t = un[i+j] - k - (p & VL_ULL(0xFFFFFFFF)); // Subtract
un[i+j] = t;
@@ -261,7 +261,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
// Over subtracted; correct by adding back
owp[j]--;
k = 0;
for (int i=0; i<vw; i++) {
for (int i=0; i<vw; ++i) {
t = (vluint64_t)(un[i+j]) + (vluint64_t)(vn[i]) + k;
un[i+j] = t;
k = t >> VL_ULL(32);
@@ -272,23 +272,99 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
if (is_modulus) { // modulus
// Need to reverse normalization on copy to output
for (int i=0; i<vw; i++) {
for (int i=0; i<vw; ++i) {
owp[i] = (un[i] >> s) | (shift_mask & (un[i+1] << (32-s)));
}
for (int i=vw; i<words; i++) owp[i] = 0;
for (int i=vw; i<words; ++i) owp[i] = 0;
return owp;
} else { // division
return owp;
}
}
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) {
// obits==lbits, rbits can be different
owp[0] = 1;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
// cppcheck-suppress variableScope
WData powstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
WData lastpowstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
WData lastoutstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
VL_ASSIGN_W(obits, powstore, lwp);
for (int bit=0; bit<rbits; bit++) {
if (bit>0) { // power = power*power
VL_ASSIGN_W(obits, lastpowstore, powstore);
VL_MUL_W(VL_WORDS_I(obits), powstore, lastpowstore, lastpowstore);
}
if (VL_BITISSET_W(rwp,bit)) { // out *= power
VL_ASSIGN_W(obits, lastoutstore, owp);
VL_MUL_W(VL_WORDS_I(obits), owp, lastoutstore, powstore);
}
}
return owp;
}
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs) {
WData rhsw[2]; VL_SET_WQ(rhsw, rhs);
return VL_POW_WWW(obits,lbits,rbits,owp,lwp,rhsw);
}
QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) {
// Skip check for rhs == 0, as short-circuit doesn't save time
if (VL_UNLIKELY(lhs==0)) return 0;
QData power = lhs;
QData out = VL_ULL(1);
for (int bit=0; bit<rbits; ++bit) {
if (bit>0) power = power*power;
if (VL_BITISSET_W(rwp,bit)) out *= power;
}
return out;
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) {
// obits==lbits, rbits can be different
if (rsign && VL_SIGN_W(rbits, rwp)) {
int words = VL_WORDS_I(obits);
VL_ZERO_W(obits, owp);
IData lor = 0; // 0=all zeros, ~0=all ones, else mix
for (int i=1; i < (words-1); ++i) {
lor |= lwp[i];
}
lor |= ( (lwp[words-1] == VL_MASK_I(rbits)) ? ~VL_UL(0) : 0);
if (lor==0 && lwp[0]==0) { return owp; } // "X" so return 0
else if (lor==0 && lwp[0]==1) { owp[0] = 1; return owp; } // 1
else if (lsign && lor == ~VL_UL(0) && lwp[0]==~VL_UL(0)) { // -1
if (rwp[0] & 1) { return VL_ALLONES_W(obits, owp); } // -1^odd=-1
else { owp[0] = 1; return owp; } // -1^even=1
}
return 0;
}
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
}
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) {
WData rhsw[2]; VL_SET_WQ(rhsw, rhs);
return VL_POWSS_WWW(obits,lbits,rbits,owp,lwp,rhsw,lsign,rsign);
}
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign) {
// Skip check for rhs == 0, as short-circuit doesn't save time
if (rsign && VL_SIGN_W(rbits, rwp)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { // -1
if (rwp[0] & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_QQW(obits, rbits, rbits, lhs, rwp);
}
//===========================================================================
// Formatting
// 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))
void _vl_vsformat(string& output, const char* formatp, va_list ap) {
void _vl_vsformat(std::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
@@ -302,8 +378,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
bool inPct = false;
bool widthSet = false;
int width = 0;
const char* pos = formatp;
for (; *pos; ++pos) {
for (const char* pos = formatp; *pos; ++pos) {
if (!inPct && pos[0]=='%') {
pctp = pos;
inPct = true;
@@ -345,7 +420,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
}
case '@': { // Verilog/C++ string
va_arg(ap, int); // # bits is ignored
const string* cstrp = va_arg(ap, const string*);
const std::string* cstrp = va_arg(ap, const std::string*);
output += *cstrp;
break;
}
@@ -377,7 +452,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
if (fmt == 'd' || fmt == '#') fmt = 'x'; // Not supported, but show something
}
int lsb=lbits-1;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) --lsb;
switch (fmt) {
case 'c': {
IData charval = ld & 0xff;
@@ -385,7 +460,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
break;
}
case 's':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
output += (charval==0)?' ':charval;
@@ -434,13 +509,13 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
break;
}
case 'b':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
}
break;
break;
case 'o':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 3) * 3; // Next digit
// Octal numbers may span more than one wide word,
// so we need to grab each bit separately and check for overrun
@@ -453,35 +528,38 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
break;
case 'u': // Packed 2-state
output.reserve(output.size() + 4*VL_WORDS_I(lbits));
for (int i=0; i<VL_WORDS_I(lbits); i++) {
output += (char)((lwp[i] >> 0) & 0xff);
for (int i=0; i<VL_WORDS_I(lbits); ++i) {
output += (char)((lwp[i] ) & 0xff);
output += (char)((lwp[i] >> 8) & 0xff);
output += (char)((lwp[i] >> 16) & 0xff);
output += (char)((lwp[i] >> 24) & 0xff);
}
break;
case 'z': // Packed 4-state
output.reserve(output.size() + 8*VL_WORDS_I(lbits));
for (int i=0; i<VL_WORDS_I(lbits); i++) {
output += (char)((lwp[i] >> 0) & 0xff);
for (int i=0; i<VL_WORDS_I(lbits); ++i) {
output += (char)((lwp[i] ) & 0xff);
output += (char)((lwp[i] >> 8) & 0xff);
output += (char)((lwp[i] >> 16) & 0xff);
output += (char)((lwp[i] >> 24) & 0xff);
output += "\0\0\0\0"; // No tristate
}
break;
case 'v': // Strength; assume always strong
for (lsb=lbits-1; lsb>=0; lsb--) {
for (lsb=lbits-1; lsb>=0; --lsb) {
if ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) output += "St1 ";
else output += "St0 ";
}
break;
case 'x':
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
output += "0123456789abcdef"[charval];
}
break;
default:
string msg = string("Unknown _vl_vsformat code: ")+pos[0];
std::string msg = std::string("Unknown _vl_vsformat code: ")+pos[0];
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
break;
} // switch
@@ -499,7 +577,7 @@ 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, const string& fstr) {
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr) {
// Get a character without advancing
if (fp) {
int data = fgetc(fp);
@@ -516,14 +594,14 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const stri
}
}
}
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, const string& fstr) {
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr) {
while (1) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c==EOF || !isspace(c)) return;
_vl_vsss_advance(fp, floc);
}
}
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const string& fstr,
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr,
char* tmpp, const char* acceptp) {
// Read into tmp, consisting of characters from acceptp list
char* cp = tmpp;
@@ -547,7 +625,7 @@ static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, int posstart, int posend) {
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
int lsb = 0;
for (int i=0, pos=posend-1; i<obits && pos>=posstart; pos--) {
for (int i=0, pos=posend-1; i<obits && pos>=posstart; --pos) {
switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb += baseLog2; break;
@@ -573,7 +651,7 @@ static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const
IData _vl_vsscanf(FILE* fp, // If a fscanf
int fbits, WDataInP fromp, // Else if a sscanf
const string& fstr, // if a sscanf to string
const std::string& fstr, // if a sscanf to string
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
@@ -610,12 +688,12 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
// Deal with all read-and-scan somethings
// Note LSBs are preserved if there's an overflow
const int obits = va_arg(ap, int);
WData qowp[2];
WData qowp[2] = {0, 0};
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;
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,fstr);
@@ -628,10 +706,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, NULL);
if (!tmp[0]) goto done;
int pos = ((int)strlen(tmp))-1;
int lpos = ((int)strlen(tmp))-1;
int lsb = 0;
for (int i=0; i<obits && pos>=0; pos--) {
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
for (int i=0; i<obits && lpos>=0; --lpos) {
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[lpos]); lsb+=8;
}
break;
}
@@ -688,7 +766,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break;
}
default:
string msg = string("Unknown _vl_vsscanf code: ")+pos[0];
std::string msg = std::string("Unknown _vl_vsscanf code: ")+pos[0];
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
break;
} // switch
@@ -724,7 +802,7 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
int lsb=obits-1;
bool start=true;
char* destp = destoutp;
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (sourcep[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
if (!start || charval) {
@@ -742,8 +820,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
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; }
for (i=0; i<srclen; ++i) { *op++ = srcp[srclen-1-i]; }
for (; i<bytes; ++i) { *op++ = 0; }
}
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
@@ -774,13 +852,13 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
return got;
}
IData VL_FOPEN_NI(const string& filename, IData mode) {
IData VL_FOPEN_NI(const std::string& filename, IData mode) {
char modez[5];
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
return VL_FOPEN_S(filename.c_str(), modez);
}
IData VL_FOPEN_QI(QData filename, IData mode) {
IData fnw[2]; VL_SET_WQ(fnw, filename);
WData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode);
}
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
@@ -802,7 +880,7 @@ void VL_FCLOSE_I(IData fdi) {
}
void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -813,7 +891,7 @@ void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) {
}
void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -824,7 +902,7 @@ void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) {
}
void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -835,7 +913,7 @@ void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) {
}
void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -846,7 +924,7 @@ void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) {
}
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -856,7 +934,7 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
_VL_STRING_TO_VINT(obits, destp, (int)output.length(), output.c_str());
}
void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...) {
if (obits_ignored) {}
output = "";
va_list ap;
@@ -865,8 +943,8 @@ void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
va_end(ap);
}
string VL_SFORMATF_NX(const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
std::string VL_SFORMATF_NX(const char* formatp, ...) {
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -877,7 +955,7 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
}
void VL_WRITEF(const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
va_list ap;
va_start(ap,formatp);
@@ -889,7 +967,7 @@ void VL_WRITEF(const char* formatp, ...) {
}
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
VL_STATIC_OR_THREAD string output; // static only for speed
VL_STATIC_OR_THREAD std::string output; // static only for speed
output = "";
FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return;
@@ -914,7 +992,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
}
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
IData fnw[2]; VL_SET_WI(fnw, ld);
WData fnw[2]; VL_SET_WI(fnw, ld);
va_list ap;
va_start(ap,formatp);
@@ -923,7 +1001,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
return got;
}
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
IData fnw[2]; VL_SET_WQ(fnw, ld);
WData fnw[2]; VL_SET_WQ(fnw, ld);
va_list ap;
va_start(ap,formatp);
@@ -938,7 +1016,7 @@ IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
va_end(ap);
return got;
}
IData VL_SSCANF_INX(int, const string& ld, const char* formatp, ...) {
IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) {
va_list ap;
va_start(ap,formatp);
IData got = _vl_vsscanf(NULL, ld.length()*8, NULL, ld, formatp, ap);
@@ -948,7 +1026,7 @@ IData VL_SSCANF_INX(int, const string& ld, const char* formatp, ...) {
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);
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
}
@@ -956,12 +1034,12 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilenamep, void* memp, IData start, IData end) {
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
string ofilenames(ofilenamez);
std::string ofilenames(ofilenamez);
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
}
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const string& ofilenamep, void* memp, IData start, IData end) {
const std::string& ofilenamep, void* memp, IData start, IData end) {
if (fnwords) {}
FILE* fp = fopen(ofilenamep.c_str(), "r");
if (VL_UNLIKELY(!fp)) {
@@ -997,9 +1075,9 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
else if (c=='_') {}
else if (c=='@') { reading_addr = true; innum=false; needinc=false; }
// Check for hex or binary digits as file format requests
else if (isxdigit(c)) {
else if (isxdigit(c) || (!reading_addr && (c=='x' || c=='X'))) {
c = tolower(c);
int value = (c >= 'a' ? (c-'a'+10) : (c-'0'));
int value = (c >= 'a' ? (c=='x' ? VL_RAND_RESET_I(4) : (c-'a'+10)) : (c-'0'));
if (!innum) { // Prep for next number
if (needinc) { addr++; needinc=false; }
}
@@ -1051,7 +1129,7 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
}
lastc = c;
}
if (needinc) { addr++; needinc=false; }
if (needinc) { addr++; }
// Final checks
fclose(fp);
@@ -1061,7 +1139,7 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
}
IData VL_SYSTEM_IQ(QData lhs) {
IData lhsw[2]; VL_SET_WQ(lhsw, lhs);
WData lhsw[2]; VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(2, lhsw);
}
IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
@@ -1072,31 +1150,45 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
}
IData VL_TESTPLUSARGS_I(const char* formatp) {
const string& match = VerilatedImp::argPlusMatch(formatp);
const std::string& match = VerilatedImp::argPlusMatch(formatp);
if (match == "") return 0;
else return 1;
}
IData VL_VALUEPLUSARGS_IN(int, const char* prefixp, char, string& ldr) {
const string& match = VerilatedImp::argPlusMatch(prefixp);
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
if (match == "") return 0;
ldr = string(dp);
return 1;
}
IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) {
std::string prefix;
bool inPct = false;
bool done = false;
char fmt = ' ';
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
if (!inPct && posp[0]=='%') {
inPct = true;
} else if (!inPct) { // Normal text
prefix += *posp;
} else { // Format character
switch (tolower(*posp)) {
case '%':
prefix += *posp;
inPct = false;
break;
default:
fmt = *posp;
done = true;
break;
}
}
}
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
const string& match = VerilatedImp::argPlusMatch(prefixp);
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
const std::string& match = VerilatedImp::argPlusMatch(prefix.c_str());
const char* dp = match.c_str() + 1 /*leading + */ + prefix.length();
if (match == "") return 0;
VL_ZERO_RESET_W(rbits, rwp);
switch (tolower(fmt)) {
case '%':
break;
case 'd':
vlsint64_t ld;
sscanf(dp,"%30" VL_PRI64 "d",&ld);
VL_SET_WQ(rwp,ld);
vlsint64_t lld;
sscanf(dp,"%30" VL_PRI64 "d",&lld);
VL_SET_WQ(rwp,lld);
break;
case 'b':
_vl_vsss_based(rwp,rbits, 1, dp, 0, (int)strlen(dp));
@@ -1108,21 +1200,50 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
case 'x':
_vl_vsss_based(rwp,rbits, 4, dp, 0, (int)strlen(dp));
break;
case 's':
for (int i=0, lsb=0, pos=((int)strlen(dp))-1; i<rbits && pos>=0; pos--) {
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[pos]); lsb+=8;
case 's': // string/no conversion
for (int i=0, lsb=0, posp=((int)strlen(dp))-1; i<rbits && posp>=0; --posp) {
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8;
}
break;
default: // Compile time should have found all errors before this
vl_fatal (__FILE__, __LINE__, "", "$value$plusargs format error");
break;
case 'e': //FALLTHRU - Unsupported
case 'f': //FALLTHRU - Unsupported
case 'g': //FALLTHRU - Unsupported
default: // Other simulators simply return 0 in these cases and don't error out
return 0;
}
_VL_CLEAN_INPLACE_W(rbits,rwp);
return 1;
}
IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) {
std::string prefix;
bool inPct = false;
bool done = false;
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
if (!inPct && posp[0]=='%') {
inPct = true;
} else if (!inPct) { // Normal text
prefix += *posp;
} else { // Format character
switch (tolower(*posp)) {
case '%':
prefix += *posp;
inPct = false;
break;
default:
done = true;
break;
}
}
}
const std::string& match = VerilatedImp::argPlusMatch(prefix.c_str());
const char* dp = match.c_str() + 1 /*leading + */ + prefix.length();
if (match == "") return 0;
rdr = std::string(dp);
return 1;
}
const char* vl_mc_scan_plusargs(const char* prefixp) {
const string& match = VerilatedImp::argPlusMatch(prefixp);
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match == "") return NULL;
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
@@ -1134,7 +1255,7 @@ const char* vl_mc_scan_plusargs(const char* prefixp) {
//===========================================================================
// Heavy functions
string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
// See also _VL_VINT_TO_STRING
char destout[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
int obits = lwords * VL_WORDSIZE;
@@ -1142,7 +1263,7 @@ string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
bool start=true;
char* destp = destout;
int len = 0;
for (; lsb>=0; lsb--) {
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
if (!start || charval) {
@@ -1151,7 +1272,7 @@ string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
start = false; // Drop leading 0s
}
}
return string(destout, len);
return std::string(destout, len);
}
//===========================================================================
@@ -1163,7 +1284,7 @@ const char* Verilated::catName(const char* n1, const char* n2) {
static char* strp = NULL;
static size_t len = 0;
size_t newlen = strlen(n1)+strlen(n2)+2;
if (newlen > len) {
if (!strp || newlen > len) {
if (strp) delete [] strp;
strp = new char[newlen];
len = newlen;
@@ -1190,7 +1311,7 @@ void Verilated::commandArgs(int argc, const char** argv) {
}
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
const string& match = VerilatedImp::argPlusMatch(prefixp);
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match == "") return "";
strncpy(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH);
@@ -1321,19 +1442,19 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
} else {
// We could have a linked list of ranges, but really this whole thing needs
// to be generalized to support structs and unions, etc.
vl_fatal(__FILE__,__LINE__,"",(string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
vl_fatal(__FILE__,__LINE__,"",(std::string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
}
}
va_end(ap);
m_varsp->insert(make_pair(namep,var));
m_varsp->insert(std::make_pair(namep,var));
}
// cppcheck-suppress unusedFunction // Used by applications
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
if (VL_LIKELY(m_varsp)) {
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
if (VL_LIKELY(it != m_varsp->end())) {
if (VL_LIKELY(it != m_varsp->end())) {
return &(it->second);
}
}
@@ -1342,26 +1463,26 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const {
void* VerilatedScope::exportFindNullError(int funcnum) {
// Slowpath - Called only when find has failed
string msg = (string("Testbench C called '")
+VerilatedImp::exportName(funcnum)
+"' but scope wasn't set, perhaps due to dpi import call without 'context'");
std::string msg = (std::string("Testbench C called '")
+VerilatedImp::exportName(funcnum)
+"' but scope wasn't set, perhaps due to dpi import call without 'context'");
vl_fatal("unknown",0,"", msg.c_str());
return NULL;
}
void* VerilatedScope::exportFindError(int funcnum) const {
// Slowpath - Called only when find has failed
string msg = (string("Testbench C called '")
+VerilatedImp::exportName(funcnum)
+"' but this DPI export function exists only in other scopes, not scope '"
+name()+"'");
std::string msg = (std::string("Testbench C called '")
+VerilatedImp::exportName(funcnum)
+"' but this DPI export function exists only in other scopes, not scope '"
+name()+"'");
vl_fatal("unknown",0,"", msg.c_str());
return NULL;
}
void VerilatedScope::scopeDump() const {
VL_PRINTF(" SCOPE %p: %s\n", this, name());
for (int i=0; i<m_funcnumMax; i++) {
for (int i=0; i<m_funcnumMax; ++i) {
if (m_callbacksp && m_callbacksp[i]) {
VL_PRINTF(" DPI-EXPORT %p: %s\n",
m_callbacksp[i], VerilatedImp::exportName(i));
+249 -141
View File
@@ -40,13 +40,12 @@
// <iostream> avoided to reduce compile time
// <map> avoided and instead in verilated_heavy.h to reduce compile time
// <string> avoided and instead in verilated_heavy.h to reduce compile time
using namespace std;
//=============================================================================
// Switches
#if VM_TRACE // Verilator tracing requested
# define WAVES 1 // Set backward compatibility flag as in systemperl.h
# define WAVES 1 // Set backward compatibility flag
#endif
//=========================================================================
@@ -349,7 +348,7 @@ extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signa
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
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal (slow - else use VL_ZERO_W)
/// Math
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
@@ -392,19 +391,19 @@ extern IData VL_SYSTEM_IQ(QData lhs);
inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); }
extern IData VL_TESTPLUSARGS_I(const char* formatp);
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
//=========================================================================
// Base macros
/// Return true if data[bit] set
/// Return true if data[bit] set; not 0/1 return, but 0/non-zero return.
#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
/// WData is always at least 2 words; does not clean upper bits
#define VL_SET_WQ(owp,data) { owp[0]=(IData)(data); owp[1]=(IData)((data)>>VL_WORDSIZE); }
#define VL_SET_WI(owp,data) { owp[0]=(IData)(data); owp[1]=0; }
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
@@ -433,6 +432,7 @@ static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUN
// (Requires clean input)
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1)))
#define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1)))
#define VL_SIGN_W(nbits,rwp) ((rwp)[VL_BITWORD_I((nbits)-VL_UL(1))] >> VL_BITBIT_I((nbits)-VL_UL(1)))
#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits,lhs)))
// Sign bit extended up to MSB, doesn't include unsigned portion
@@ -504,17 +504,28 @@ static inline WDataOutP _VL_CLEAN_INPLACE_W(int obits, WDataOutP owp) {
}
static inline WDataOutP VL_CLEAN_WW(int obits, int, WDataOutP owp, WDataInP lwp){
int words = VL_WORDS_I(obits);
for (int i=0; (i < (words-1)); i++) owp[i] = lwp[i];
for (int i=0; (i < (words-1)); ++i) owp[i] = lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
return(owp);
}
static inline WDataOutP VL_ZERO_W(int obits, WDataOutP owp) {
int words = VL_WORDS_I(obits);
for (int i=0; i < words; ++i) owp[i] = 0;
return owp;
}
static inline WDataOutP VL_ALLONES_W(int obits, WDataOutP owp) {
int words = VL_WORDS_I(obits);
for (int i=0; (i < (words-1)); ++i) owp[i] = ~VL_UL(0);
owp[words-1] = VL_MASK_I(obits);
return owp;
}
// EMIT_RULE: VL_ASSIGN: oclean=rclean; obits==lbits;
// For now, we always have a clean rhs.
// Note: If a ASSIGN isn't clean, use VL_ASSIGNCLEAN instead to do the same thing.
static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp,WDataInP lwp){
static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp, WDataInP lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i < words; i++) owp[i] = lwp[i];
for (int i=0; i < words; ++i) owp[i] = lwp[i];
return(owp);
}
@@ -575,7 +586,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
}
#define VL_ASSIGN_WSW(obits,owp,svar) { \
int words = VL_WORDS_I(obits); \
for (int i=0; i < words; i++) owp[i] = svar.read().get_word(i); \
for (int i=0; i < words; ++i) owp[i] = svar.read().get_word(i); \
owp[words-1] &= VL_MASK_I(obits); \
}
@@ -584,7 +595,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
#define VL_ASSIGN_WSB(obits,owp,svar) { \
int words = VL_WORDS_I(obits); \
sc_biguint<obits> _butemp = (svar).read(); \
for (int i=0; i < words; i++) { \
for (int i=0; i < words; ++i) { \
int msb = ((i+1)*VL_WORDSIZE) - 1; \
msb = (msb >= obits) ? (obits-1) : msb; \
owp[i] = _butemp.range(msb,i*VL_WORDSIZE).to_uint(); \
@@ -611,7 +622,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
}
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
sc_bv<obits> _bvtemp; \
for (int i=0; i < VL_WORDS_I(obits); i++) _bvtemp.set_word(i,rwp[i]); \
for (int i=0; i < VL_WORDS_I(obits); ++i) _bvtemp.set_word(i,rwp[i]); \
svar.write(_bvtemp); \
}
@@ -621,7 +632,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
#define VL_ASSIGN_SBQ(obits,svar,rd) { (svar).write(rd); }
#define VL_ASSIGN_SBW(obits,svar,rwp) { \
sc_biguint<obits> _butemp; \
for (int i=0; i < VL_WORDS_I(obits); i++) { \
for (int i=0; i < VL_WORDS_I(obits); ++i) { \
int msb = ((i+1)*VL_WORDSIZE) - 1; \
msb = (msb >= obits) ? (obits-1) : msb; \
_butemp.range(msb,i*VL_WORDSIZE) = rwp[i]; \
@@ -643,17 +654,17 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) {
// Note for extracts that obits != lbits
owp[0] = ld;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return(owp);
}
static inline WDataOutP VL_EXTEND_WQ(int obits, int, WDataOutP owp, QData ld) {
VL_SET_WQ(owp,ld);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return(owp);
}
static inline WDataOutP VL_EXTEND_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) {
for (int i=0; i < VL_WORDS_I(lbits); i++) owp[i] = lwp[i];
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
return(owp);
}
@@ -672,22 +683,22 @@ static inline QData VL_EXTENDS_QQ(int, int lbits, QData lhs) {
static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) {
IData sign = VL_SIGNONES_I(lbits,ld);
owp[0] = ld | (sign & ~VL_MASK_I(lbits));
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return(owp);
}
static inline WDataOutP VL_EXTENDS_WQ(int obits, int lbits, WDataOutP owp, QData ld) {
VL_SET_WQ(owp,ld);
IData sign = VL_SIGNONES_I(lbits,owp[1]);
owp[1] |= sign & ~VL_MASK_I(lbits);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return(owp);
}
static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WDataInP lwp) {
for (int i=0; i < VL_WORDS_I(lbits)-1; i++) owp[i] = lwp[i];
for (int i=0; i < VL_WORDS_I(lbits)-1; ++i) owp[i] = lwp[i];
int lmsw=VL_WORDS_I(lbits)-1;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_I(lbits));
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); ++i) owp[i] = sign;
return(owp);
}
@@ -700,7 +711,7 @@ static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WData
static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) {
int words = VL_WORDS_I(lbits);
IData combine=lwp[0];
for (int i=1; i < words-1; i++) combine &= lwp[i];
for (int i=1; i < words-1; ++i) combine &= lwp[i];
combine &= ~VL_MASK_I(lbits) | lwp[words-1];
return ((~combine)==0);
}
@@ -710,7 +721,7 @@ static inline IData VL_REDAND_IW(int, int lbits, WDataInP lwp) {
#define VL_REDOR_Q(lhs) (lhs!=0)
static inline IData VL_REDOR_W(int words, WDataInP lwp) {
IData equal=0;
for (int i=0; i < words; i++) equal |= lwp[i];
for (int i=0; i < words; ++i) equal |= lwp[i];
return(equal!=0);
}
@@ -762,7 +773,7 @@ static inline IData VL_REDXOR_64(QData r) {
}
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
IData r = lwp[0];
for (int i=1; i < words; i++) r ^= lwp[i];
for (int i=1; i < words; ++i) r ^= lwp[i];
return VL_REDXOR_32(r);
}
@@ -780,7 +791,7 @@ static inline IData VL_COUNTONES_Q(QData lhs) {
}
static inline IData VL_COUNTONES_W(int words, WDataInP lwp) {
IData r = 0;
for (int i=0; (i < words); i++) r+=VL_COUNTONES_I(lwp[i]);
for (int i=0; (i < words); ++i) r+=VL_COUNTONES_I(lwp[i]);
return r;
}
@@ -792,7 +803,7 @@ static inline IData VL_ONEHOT_Q(QData lhs) {
}
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) {
IData one=0;
for (int i=0; (i < words); i++) {
for (int i=0; (i < words); ++i) {
if (lwp[i]) {
if (one) return 0;
one = 1;
@@ -810,7 +821,7 @@ static inline IData VL_ONEHOT0_Q(QData lhs) {
}
static inline IData VL_ONEHOT0_W(int words, WDataInP lwp) {
bool one=false;
for (int i=0; (i < words); i++) {
for (int i=0; (i < words); ++i) {
if (lwp[i]) {
if (one) return 0;
one = true;
@@ -825,21 +836,21 @@ static inline IData VL_CLOG2_I(IData lhs) {
if (VL_UNLIKELY(!lhs)) return 0;
lhs--;
int shifts=0;
for (; lhs!=0; shifts++) lhs = lhs >> 1;
for (; lhs!=0; ++shifts) lhs = lhs >> 1;
return shifts;
}
static inline IData VL_CLOG2_Q(QData lhs) {
if (VL_UNLIKELY(!lhs)) return 0;
lhs--;
int shifts=0;
for (; lhs!=0; shifts++) lhs = lhs >> VL_ULL(1);
for (; lhs!=0; ++shifts) lhs = lhs >> VL_ULL(1);
return shifts;
}
static inline IData VL_CLOG2_W(int words, WDataInP lwp) {
IData adjust = (VL_COUNTONES_W(words,lwp)==1) ? 0 : 1;
for (int i=words-1; i>=0; i--) {
for (int i=words-1; i>=0; --i) {
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
for (int bit=31; bit>=0; bit--) {
for (int bit=31; bit>=0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) {
return i*VL_WORDSIZE + bit + adjust;
}
@@ -852,9 +863,9 @@ static inline IData VL_CLOG2_W(int words, WDataInP lwp) {
static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) {
// MSB set bit plus one; similar to FLS. 0=value is zero
for (int i=words-1; i>=0; i--) {
for (int i=words-1; i>=0; --i) {
if (VL_UNLIKELY(lwp[i])) { // Shorter worst case if predict not taken
for (int bit=31; bit>=0; bit--) {
for (int bit=31; bit>=0; --bit) {
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) {
return i*VL_WORDSIZE + bit + 1;
}
@@ -870,33 +881,33 @@ static inline IData VL_MOSTSETBITP1_W(int words, WDataInP lwp) {
// EMIT_RULE: VL_AND: oclean=lclean||rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_AND_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] & rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] & rwp[i]);
return(owp);
}
// EMIT_RULE: VL_OR: oclean=lclean&&rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_OR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] | rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] | rwp[i]);
return(owp);
}
// EMIT_RULE: VL_CHANGEXOR: oclean=1; obits=32; lbits==rbits;
static inline IData VL_CHANGEXOR_W(int words, WDataInP lwp,WDataInP rwp){
IData od = 0;
for (int i=0; (i < words); i++) od |= (lwp[i] ^ rwp[i]);
for (int i=0; (i < words); ++i) od |= (lwp[i] ^ rwp[i]);
return(od);
}
// EMIT_RULE: VL_XOR: oclean=lclean&&rclean; obits=lbits; lbits==rbits;
static inline WDataOutP VL_XOR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] ^ rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ rwp[i]);
return(owp);
}
// EMIT_RULE: VL_XNOR: oclean=dirty; obits=lbits; lbits==rbits;
static inline WDataOutP VL_XNOR_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; (i < words); i++) owp[i] = (lwp[i] ^ ~rwp[i]);
for (int i=0; (i < words); ++i) owp[i] = (lwp[i] ^ ~rwp[i]);
return(owp);
}
// EMIT_RULE: VL_NOT: oclean=dirty; obits=lbits;
static inline WDataOutP VL_NOT_W(int words, WDataOutP owp,WDataInP lwp) {
for (int i=0; i < words; i++) owp[i] = ~(lwp[i]);
for (int i=0; i < words; ++i) owp[i] = ~(lwp[i]);
return(owp);
}
@@ -918,7 +929,7 @@ static inline WDataOutP VL_NOT_W(int words, WDataOutP owp,WDataInP lwp) {
// Output clean, <lhs> AND <rhs> MUST BE CLEAN
static inline IData VL_EQ_W(int words, WDataInP lwp, WDataInP rwp) {
int nequal=0;
for (int i=0; (i < words); i++) nequal |= (lwp[i] ^ rwp[i]);
for (int i=0; (i < words); ++i) nequal |= (lwp[i] ^ rwp[i]);
return(nequal==0);
}
@@ -1012,7 +1023,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) {
static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(lwp[i]) + (QData)(rwp[i]);
owp[i] = (carry & VL_ULL(0xffffffff));
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
@@ -1022,7 +1033,7 @@ static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(lwp[i]) + (QData)(IData)(~rwp[i]);
if (i==0) carry++; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff));
@@ -1039,7 +1050,7 @@ static inline QData VL_NEGATE_Q(QData data) { return -data; }
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(IData)(~lwp[i]);
if (i==0) carry++; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff));
@@ -1049,11 +1060,11 @@ static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
}
static inline WDataOutP VL_MUL_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
for (int i=0; i<words; i++) owp[i] = 0;
for (int lword=0; lword<words; lword++) {
for (int rword=0; rword<words; rword++) {
for (int i=0; i<words; ++i) owp[i] = 0;
for (int lword=0; lword<words; ++lword) {
for (int rword=0; rword<words; ++rword) {
QData mul = (QData)(lwp[lword]) * (QData)(rwp[rword]);
for (int qword=lword+rword; qword<words; qword++) {
for (int qword=lword+rword; qword<words; ++qword) {
mul += (QData)(owp[qword]);
owp[qword] = (mul & VL_ULL(0xffffffff));
mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff);
@@ -1077,8 +1088,10 @@ static inline QData VL_MULS_QQQ(int,int lbits,int, QData lhs,QData rhs) {
static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lwp,WDataInP rwp){
int words = VL_WORDS_I(lbits);
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
IData rwstore[VL_MULS_MAX_WORDS];
// cppcheck-suppress variableScope
WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP lwusp = lwp;
WDataInP rwusp = rwp;
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
@@ -1097,7 +1110,7 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0;
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
carry = carry + (QData)(IData)(~owp[i]);
if (i==0) carry++; // Negation of temp2
owp[i] = (carry & VL_ULL(0xffffffff));
@@ -1139,9 +1152,9 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[words-1]);
// cppcheck-suppress variableScope
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
IData rwstore[VL_MULS_MAX_WORDS];
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
@@ -1160,15 +1173,15 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
IData lsign = VL_SIGN_I(lbits,lwp[words-1]);
IData rsign = VL_SIGN_I(lbits,rwp[words-1]);
// cppcheck-suppress variableScope
IData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
WData lwstore[VL_MULS_MAX_WORDS]; // Fixed size, as MSVC++ doesn't allow [words] here
// cppcheck-suppress variableScope
IData rwstore[VL_MULS_MAX_WORDS];
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if (lsign) { // Only dividend sign matters for modulus
IData qNoSign[VL_MULS_MAX_WORDS];
WData qNoSign[VL_MULS_MAX_WORDS];
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp;
@@ -1177,14 +1190,17 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
}
}
#define VL_POW_IIQ(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
#define VL_POW_IIW(obits,lbits,rbits,lhs,rwp) VL_POW_QQW(obits,lbits,rbits,lhs,rwp)
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
#define VL_POW_WWI(obits,lbits,rbits,owp,lwp,rhs) VL_POW_WWQ(obits,lbits,rbits,owp,lwp,rhs)
static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (VL_UNLIKELY(lhs==0)) return 0;
IData power = lhs;
IData out = 1;
for (int i=0; i<rbits; i++) {
for (int i=0; i<rbits; ++i) {
if (i>0) power = power*power;
if (rhs & (VL_ULL(1)<<i)) out *= power;
}
@@ -1195,42 +1211,51 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
if (VL_UNLIKELY(lhs==0)) return 0;
QData power = lhs;
QData out = VL_ULL(1);
for (int i=0; i<rbits; i++) {
for (int i=0; i<rbits; ++i) {
if (i>0) power = power*power;
if (rhs & (VL_ULL(1)<<i)) out *= power;
}
return out;
}
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp);
WDataOutP VL_POW_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs);
QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp);
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
else if (lsign && lhs==VL_MASK_I(obits)) { // -1
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_III(obits, obits, rbits, lhs, rhs);
return VL_POW_III(obits, rbits, rbits, lhs, rhs);
}
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) {
if (VL_UNLIKELY(rhs==0)) return 1;
if (rsign && VL_SIGN_I(rbits, rhs)) {
if (lhs==0) return 0; // "X"
else if (lhs==1) return 1;
else if (lsign && lhs==VL_MASK_I(obits)) { //-1
else if (lsign && lhs==VL_MASK_I(obits)) { // -1
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
return 0;
}
return VL_POW_QQQ(obits, obits, rbits, lhs, rhs);
return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs);
}
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign);
//===================================================================
// Concat/replication
@@ -1285,13 +1310,13 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
int words = VL_WORDS_I(hbit-lbit+1);
if (hoffset==VL_SIZEBITS_I && loffset==0) {
// Fast and common case, word based insertion
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[lword+i] = lwp[i];
}
}
else if (loffset==0) {
// Non-32bit, but nicely aligned, so stuff all but the last word
for (int i=0; i<(words-1); i++) {
for (int i=0; i<(words-1); ++i) {
owp[lword+i] = lwp[i];
}
IData hinsmask = (VL_MASK_I(hoffset-0+1)); // Know it's not a full word as above fast case handled it
@@ -1303,7 +1328,7 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int hword = VL_BITWORD_I(hbit);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
{ // Lower word
int oword = lword+i;
IData d = lwp[i]<<loffset;
@@ -1336,7 +1361,7 @@ static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, i
static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) {
IData returndata = ld;
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
returndata = returndata << lbits;
returndata |= ld;
}
@@ -1344,7 +1369,7 @@ static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) {
}
static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) {
QData returndata = ld;
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
returndata = returndata << lbits;
returndata |= (QData)ld;
}
@@ -1352,21 +1377,21 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) {
}
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld, IData rep) {
owp[0] = ld;
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WI(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld, IData rep) {
VL_SET_WQ(owp,ld);
for (unsigned i=1; i < rep; i++){
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WQ(obits,owp,ld,i*lbits+lbits-1,i*lbits);
}
return(owp);
}
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp, IData rep) {
for (int i=0; i < VL_WORDS_I(lbits); i++) owp[i] = lwp[i];
for (unsigned i=1; i < rep; i++){
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
for (unsigned i=1; i < rep; ++i){
_VL_INSERT_WW(obits,owp,lwp,i*lbits+lbits-1,i*lbits);
}
return(owp);
@@ -1470,13 +1495,13 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) {
}
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp, IData rd) {
VL_ZERO_RESET_W(lbits, owp);
VL_ZERO_W(lbits, owp);
// Slice size should never exceed the lhs width
int ssize = (rd < (IData)lbits) ? rd : ((IData)lbits);
for (int istart=0; istart<lbits; istart+=rd) {
int ostart=lbits-rd-istart;
ostart = ostart > 0 ? ostart : 0;
for (int sbit=0; sbit<ssize && sbit<lbits-istart; sbit++) {
for (int sbit=0; sbit<ssize && sbit<lbits-istart; ++sbit) {
// Extract a single bit from lwp and shift it to the correct
// location for owp.
WData bit= ((lwp[VL_BITWORD_I(istart+sbit)] >> VL_BITBIT_I(istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
@@ -1498,55 +1523,55 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
static inline WDataOutP VL_CONCAT_WII(int obits,int lbits,int rbits,WDataOutP owp,IData ld,IData rd) {
owp[0] = rd;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWI(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, IData rd) {
owp[0] = rd;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WIW(int obits,int lbits,int rbits,WDataOutP owp,IData ld, WDataInP rwp) {
for (int i=0; i < VL_WORDS_I(rbits); i++) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WIQ(int obits,int lbits,int rbits,WDataOutP owp,IData ld,QData rd) {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQI(int obits,int lbits,int rbits,WDataOutP owp,QData ld,IData rd) {
owp[0] = rd;
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQQ(int obits,int lbits,int rbits,WDataOutP owp,QData ld,QData rd) {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWQ(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, QData rd) {
VL_SET_WQ(owp,rd);
for (int i=2; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WQW(int obits,int lbits,int rbits,WDataOutP owp,QData ld, WDataInP rwp) {
for (int i=0; i < VL_WORDS_I(rbits); i++) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
return(owp);
}
static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=0; i < VL_WORDS_I(rbits); i++) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
return(owp);
}
@@ -1559,7 +1584,7 @@ static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP ow
static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or 4*/) {
int words = VL_WORDS_I(obits);
IData linsmask = VL_MASK_I(rd);
for (int i=words-1; i>=1; i--) {
for (int i=words-1; i>=1; --i) {
iowp[i] = ((iowp[i]<<rd) & ~linsmask) | ((iowp[i-1] >> (32-rd)) & linsmask);
}
iowp[0] = ((iowp[0]<<rd) & ~linsmask);
@@ -1573,16 +1598,32 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
int word_shift = VL_BITWORD_I(rd);
int bit_shift = VL_BITBIT_I(rd);
if (rd >= (IData)obits) { // rd may be huge with MSB set
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
} else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
for (int i=0; i < word_shift; i++) owp[i] = 0;
for (int i=word_shift; i < VL_WORDS_I(obits); i++) owp[i] = lwp[i-word_shift];
for (int i=0; i < word_shift; ++i) owp[i] = 0;
for (int i=word_shift; i < VL_WORDS_I(obits); ++i) owp[i] = lwp[i-word_shift];
} else {
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
_VL_INSERT_WW(obits,owp,lwp,obits-1,rd);
}
return(owp);
}
static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
}
}
return VL_SHIFTL_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs<<rwp[0]);
}
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
// Important: Unlike most other funcs, the shift might well be a computed
@@ -1591,27 +1632,43 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
int word_shift = VL_BITWORD_I(rd); // Maybe 0
int bit_shift = VL_BITBIT_I(rd);
if (rd >= (IData)obits) { // rd may be huge with MSB set
for (int i=0; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift);
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = 0;
for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
} else {
int loffset = rd & VL_SIZEBITS_I;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(obits-rd);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[i] = lwp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
if (upperword < VL_WORDS_I(obits)) {
owp[i] |= lwp[upperword]<< nbitsonright;
}
}
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i]=0;
for (int i=words; i<VL_WORDS_I(obits); ++i) owp[i]=0;
}
return(owp);
}
static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_W(obits, owp);
}
}
return VL_SHIFTR_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTR_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs>>rwp[0]);
}
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData rhs) {
@@ -1637,20 +1694,20 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
if (rd >= (IData)obits) { // Shifting past end, sign in all of lbits
for (int i=0; i <= lmsw; i++) owp[i] = sign;
for (int i=0; i <= lmsw; ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
int copy_words = (VL_WORDS_I(obits)-word_shift);
for (int i=0; i < copy_words; i++) owp[i] = lwp[i+word_shift];
for (int i=0; i < copy_words; ++i) owp[i] = lwp[i+word_shift];
if (copy_words>=0) owp[copy_words-1] |= ~VL_MASK_I(obits) & sign;
for (int i=copy_words; i < VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=copy_words; i < VL_WORDS_I(obits); ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
} else {
int loffset = rd & VL_SIZEBITS_I;
int nbitsonright = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(obits-rd);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[i] = lwp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
if (upperword < VL_WORDS_I(obits)) {
@@ -1658,11 +1715,49 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
}
}
if (words) owp[words-1] |= sign & ~VL_MASK_I(obits-loffset);
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i] = sign;
for (int i=words; i<VL_WORDS_I(obits); ++i) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
}
return(owp);
}
static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
for (int j=0; j <= lmsw; ++j) owp[j] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
return owp;
}
}
return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
return VL_CLEAN_II(obits,obits,sign);
}
}
return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]);
}
static inline QData VL_SHIFTRS_QQW(int obits,int lbits,int rbits,QData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
return VL_CLEAN_QQ(obits,obits,sign);
}
}
return VL_SHIFTRS_QQI(obits,lbits,32,lhs,rwp[0]);
}
static inline IData VL_SHIFTRS_IIQ(int obits,int lbits,int rbits,IData lhs, QData rhs) {
WData rwp[2]; VL_SET_WQ(rwp,rhs);
return VL_SHIFTRS_IIW(obits,lbits,rbits,lhs,rwp);
}
static inline QData VL_SHIFTRS_QQQ(int obits,int lbits,int rbits,QData lhs, QData rhs) {
WData rwp[2]; VL_SET_WQ(rwp,rhs);
return VL_SHIFTRS_QQW(obits,lbits,rbits,lhs,rwp);
}
//===================================================================
// Bit selection
@@ -1728,25 +1823,25 @@ static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WD
int msb = lsb+width-1;
int word_shift = VL_BITWORD_I(lsb);
if (VL_UNLIKELY(msb>lbits)) { // Outside bounds,
for (int i=0; i<VL_WORDS_I(obits)-1; i++) owp[i] = ~0;
for (int i=0; i<VL_WORDS_I(obits)-1; ++i) owp[i] = ~0;
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits);
} else if (VL_BITBIT_I(lsb)==0) {
// Just a word extract
for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = lwp[i+word_shift];
for (int i=0; i<VL_WORDS_I(obits); ++i) owp[i] = lwp[i+word_shift];
} else {
// Not a _VL_INSERT because the bits come from any bit number and goto bit 0
int loffset = lsb & VL_SIZEBITS_I;
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
// Middle words
int words = VL_WORDS_I(msb-lsb+1);
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
owp[i] = lwp[i+word_shift]>>loffset;
int upperword = i+word_shift+1;
if (upperword <= (int)VL_BITWORD_I(msb)) {
owp[i] |= lwp[upperword]<< nbitsfromlow;
}
}
for (int i=words; i<VL_WORDS_I(obits); i++) owp[i]=0;
for (int i=words; i<VL_WORDS_I(obits); ++i) owp[i]=0;
}
return owp;
}
@@ -1791,92 +1886,105 @@ static inline void VL_ASSIGNSEL_WIIW(int obits, int lsb, WDataOutP owp, WDataInP
static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
WDataOutP owp, int cond, WDataInP w1p, WDataInP w2p) {
int words = VL_WORDS_I(obits);
for (int i=0; i < words; i++) owp[i] = cond ? w1p[i] : w2p[i];
for (int i=0; i < words; ++i) owp[i] = cond ? w1p[i] : w2p[i];
return(owp);
}
//======================================================================
// System Functions
inline IData VL_VALUEPLUSARGS_IQ(int rbits, const char* prefixp, char fmt, QData& ldr) {
WData wd[2]; IData v=VL_VALUEPLUSARGS_IW(rbits,prefixp,fmt,wd); if (v) ldr=VL_SET_QW(wd);
return v;
}
inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, CData& ldr) {
QData qd; IData v=VL_VALUEPLUSARGS_IQ(rbits,prefixp,fmt,qd); if (v) ldr=(CData)qd;
return v;
}
inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, SData& ldr) {
QData qd; IData v=VL_VALUEPLUSARGS_IQ(rbits,prefixp,fmt,qd); if (v) ldr=(SData)qd;
return v;
}
inline IData VL_VALUEPLUSARGS_II(int rbits, const char* prefixp, char fmt, IData& ldr) {
QData qd; IData v=VL_VALUEPLUSARGS_IQ(rbits,prefixp,fmt,qd); if (v) ldr=(IData)qd;
return v;
}
//======================================================================
// Constification
// VL_CONST_W_#X(int obits, WDataOutP owp, IData data0, .... IData data(#-1))
// Sets wide vector words to specified constant words, zeros upper data.
// Sets wide vector words to specified constant words.
// These macros are used when o might represent more words then are given as constants,
// hence all upper words must be zeroed.
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
#define _END(obits,wordsSet) \
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
for(int i=(wordsSet);i<VL_WORDS_I(obits);++i) o[i] = (IData)0x0; \
return o
#define VL_HAVE_CONST_W_1X
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
IData d0) {
o[0]=d0;
_END(obits,1); }
#define VL_HAVE_CONST_W_2X
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
IData d1,IData d0) {
o[0]=d0; o[1]=d1;
_END(obits,2); }
#define VL_HAVE_CONST_W_3X
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
IData d2,IData d1,IData d0) {
o[0]=d0; o[1]=d1; o[2]=d2;
_END(obits,3); }
#define VL_HAVE_CONST_W_4X
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
IData d3,IData d2,IData d1,IData d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
_END(obits,4); }
#define VL_HAVE_CONST_W_5X
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
IData d4,IData d3,IData d2,IData d1,IData d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
_END(obits,5); }
#define VL_HAVE_CONST_W_6X
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
_END(obits,6); }
#define VL_HAVE_CONST_W_7X
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
_END(obits,7); }
#define VL_HAVE_CONST_W_8X
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
_END(obits,8); }
#define VL_HAVE_CONST_W_9X
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
IData d8,
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
//
static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0;
_END(obits,1); }
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1;
_END(obits,2); }
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
IData d2,IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2;
_END(obits,3); }
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
IData d3,IData d2,IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
_END(obits,4); }
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
IData d4,IData d3,IData d2,IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
_END(obits,5); }
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
_END(obits,6); }
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
_END(obits,7); }
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
o[8]=d8;
_END(obits,9); }
_END(obits,8); }
#undef _END
// Partial constant, lower words of vector wider than 8*32, starting at bit number lsb
static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
IData d7, IData d6, IData d5, IData d4, IData d3, IData d2, IData d1, IData d0) {
WDataOutP o = obase + VL_WORDS_I(lsb);
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; }
//======================================================================
#endif /*_VERILATED_H_*/
+7 -21
View File
@@ -18,11 +18,12 @@ CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
# Compiler flags that turn on extra warnings
CFG_CXXFLAGS_WEXTRA = @CFG_CXXFLAGS_WEXTRA@
######################################################################
# Programs
SP_PREPROC = sp_preproc
SP_INCLUDER = $(VERILATOR_INCLUDER)
VERILATOR_COVERAGE = $(PERL) $(VERILATOR_ROOT)/bin/verilator_coverage
VERILATOR_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
@@ -49,8 +50,7 @@ VK_CPPFLAGS_ALWAYS += \
$(CFG_CXXFLAGS_NO_UNUSED) \
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
VK_CPPFLAGS_WALL += -Wall \
-Werror
VK_CPPFLAGS_WALL += -Wall $(CFG_CXXFLAGS_WEXTRA) -Werror
endif
CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
@@ -93,9 +93,9 @@ VM_CLASSES += $(VM_CLASSES_FAST) $(VM_CLASSES_SLOW)
VM_SUPPORT += $(VM_SUPPORT_FAST) $(VM_SUPPORT_SLOW)
#######################################################################
##### SystemC or SystemPerl builds
##### SystemC builds
ifeq ($(VM_SP_OR_SC),1)
ifeq ($(VM_SC),1)
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
SC_LIBS = -lsystemc
@@ -106,23 +106,9 @@ ifeq ($(VM_SP_OR_SC),1)
endif
#######################################################################
##### SystemPerl builds
##### Stub
ifeq ($(VM_SP),1)
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE) -DSYSTEMPERL
VPATH += $(SYSTEMPERL_INCLUDE)
LIBS += -lm -lstdc++
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
# This rule is called manually by the upper level makefile
preproc:
@echo " SP Preprocess" $(basename $(VM_CLASSES)) ...
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
--preproc $(VK_CLASSES_SP)
else
preproc:
endif
preproc:
#######################################################################
##### C/H builds
+51 -50
View File
@@ -50,7 +50,7 @@ public: // But only local to this file
// CONSTRUCTORS
// Derived classes should call zero() in their constructor
VerilatedCovImpItem() {
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
m_keys[i]=KEY_UNDEF;
m_vals[i]=0;
}
@@ -72,6 +72,7 @@ private:
T* m_countp; ///< Count value
public:
// METHODS
// cppcheck-suppress truncLongCastReturn
virtual vluint64_t count() const { return *m_countp; }
virtual void zero() const { *m_countp = 0; }
// CONSTRUCTORS
@@ -89,9 +90,9 @@ public:
class VerilatedCovImp : VerilatedCovImpBase {
private:
// TYPES
typedef map<string,int> ValueIndexMap;
typedef map<int,string> IndexValueMap;
typedef deque<VerilatedCovImpItem*> ItemList;
typedef std::map<std::string,int> ValueIndexMap;
typedef std::map<int,std::string> IndexValueMap;
typedef std::deque<VerilatedCovImpItem*> ItemList;
private:
// MEMBERS
@@ -118,19 +119,19 @@ public:
private:
// PRIVATE METHODS
int valueIndex(const string& value) {
int valueIndex(const std::string& value) {
static int nextIndex = KEY_UNDEF+1;
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
if (iter != m_valueIndexes.end()) return iter->second;
nextIndex++; assert(nextIndex>0);
m_valueIndexes.insert(make_pair(value, nextIndex));
m_indexValues.insert(make_pair(nextIndex, value));
m_valueIndexes.insert(std::make_pair(value, nextIndex));
m_indexValues.insert(std::make_pair(nextIndex, value));
return nextIndex;
}
string dequote(const string& text) {
std::string dequote(const std::string& text) {
// Quote any special characters
string rtn;
for (const char* pos = text.c_str(); *pos; pos++) {
std::string rtn;
for (const char* pos = text.c_str(); *pos; ++pos) {
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
char hex[10]; sprintf(hex,"%%%02X",pos[0]);
rtn += hex;
@@ -140,7 +141,7 @@ private:
}
return rtn;
}
bool legalKey(const string& key) {
bool legalKey(const std::string& key) {
// Because we compress long keys to a single letter, and
// don't want applications to either get confused if they use
// a letter differently, nor want them to rely on our compression...
@@ -149,17 +150,17 @@ private:
if (key.length()==2 && isdigit(key[1])) return false;
return true;
}
string keyValueFormatter (const string& key, const string& value) {
string name;
std::string keyValueFormatter (const std::string& key, const std::string& value) {
std::string name;
if (key.length()==1 && isalpha(key[0])) {
name += string("\001")+key;
name += std::string("\001")+key;
} else {
name += string("\001")+dequote(key);
name += std::string("\001")+dequote(key);
}
name += string("\002")+dequote(value);
name += std::string("\002")+dequote(value);
return name;
}
string combineHier (const string& old, const string& add) {
std::string combineHier (const std::string& old, const std::string& add) {
// (foo.a.x, foo.b.x) => foo.*.x
// (foo.a.x, foo.b.y) => foo.*
// (foo.a.x, foo.b) => foo.*
@@ -177,7 +178,7 @@ private:
// We used to backup and split on only .'s but it seems better to be verbose
// and not assume . is the separator
string prefix = string(a,apre-a);
std::string prefix = std::string(a,apre-a);
// Scan backward to last mismatch
const char* apost = a+strlen(a)-1;
@@ -186,19 +187,19 @@ private:
&& apost>apre && bpost>bpre) { apost--; bpost--; }
// Forward to . so we have a whole word
string suffix = *bpost ? string(bpost+1) : "";
std::string suffix = *bpost ? std::string(bpost+1) : "";
string out = prefix+"*"+suffix;
std::string out = prefix+"*"+suffix;
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
return out;
}
bool itemMatchesString(VerilatedCovImpItem* itemp, const string& match) {
for (int i=0; i<MAX_KEYS; i++) {
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) {
for (int i=0; i<MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
// We don't compare keys, only values
string val = m_indexValues[itemp->m_vals[i]];
if (string::npos != val.find(match)) { // Found
std::string val = m_indexValues[itemp->m_vals[i]];
if (std::string::npos != val.find(match)) { // Found
return true;
}
}
@@ -262,27 +263,27 @@ public:
assert(m_insertp);
// First two key/vals are filename
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
string linestr = vlCovCvtToStr(m_insertLineno);
std::string linestr = vlCovCvtToStr(m_insertLineno);
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
// Default page if not specified
const char* fnstartp = m_insertFilenamep;
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1;
const char* fnendp = fnstartp;
while (*fnendp && *fnendp!='.') fnendp++;
string page_default = "sp_user/"+string(fnstartp,fnendp-fnstartp);
std::string page_default = "sp_user/"+std::string(fnstartp,fnendp-fnstartp);
ckeyps[2]="page"; valps[2]=page_default.c_str();
// Keys -> strings
string keys[MAX_KEYS];
for (int i=0; i<MAX_KEYS; i++) {
std::string keys[MAX_KEYS];
for (int i=0; i<MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) {
keys[i] = ckeyps[i];
}
}
// Ignore empty keys
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
if (keys[i]!="") {
for (int j=i+1; j<MAX_KEYS; j++) {
for (int j=i+1; j<MAX_KEYS; ++j) {
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
keys[i] = "";
break;
@@ -292,16 +293,16 @@ public:
}
// Insert the values
int addKeynum=0;
for (int i=0; i<MAX_KEYS; i++) {
const string key = keys[i];
for (int i=0; i<MAX_KEYS; ++i) {
const std::string key = keys[i];
if (keys[i]!="") {
const string val = valps[i];
const std::string val = valps[i];
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
m_insertp->m_keys[addKeynum] = valueIndex(key);
m_insertp->m_vals[addKeynum] = valueIndex(val);
addKeynum++;
if (!legalKey(key)) {
string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
vl_fatal("",0,"",msg.c_str());
}
}
@@ -317,27 +318,27 @@ public:
#endif
selftest();
ofstream os (filename);
std::ofstream os (filename);
if (os.fail()) {
string msg = (string)"%Error: Can't write '"+filename+"'";
std::string msg = (std::string)"%Error: Can't write '"+filename+"'";
vl_fatal("",0,"",msg.c_str());
return;
}
os << "# SystemC::Coverage-3\n";
// Build list of events; totalize if collapsing hierarchy
typedef map<string,pair<string,vluint64_t> > EventMap;
EventMap eventCounts;
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
EventMap eventCounts;
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
string name;
string hier;
std::string name;
std::string hier;
bool per_instance = false;
for (int i=0; i<MAX_KEYS; i++) {
for (int i=0; i<MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
string val = m_indexValues[itemp->m_vals[i]];
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
std::string val = m_indexValues[itemp->m_vals[i]];
if (key == VL_CIK_PER_INSTANCE) {
if (val != "0") per_instance = true;
}
@@ -362,21 +363,21 @@ public:
// Find or insert the named event
EventMap::iterator cit = eventCounts.find(name);
if (cit != eventCounts.end()) {
const string& oldhier = cit->second.first;
const std::string& oldhier = cit->second.first;
cit->second.second += itemp->count();
cit->second.first = combineHier(oldhier, hier);
} else {
eventCounts.insert(make_pair(name, make_pair(hier,itemp->count())));
eventCounts.insert(std::make_pair(name, make_pair(hier,itemp->count())));
}
}
// Output body
for (EventMap::iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
os<<"C '"<<dec;
os<<"C '"<<std::dec;
os<<it->first;
if (it->second.first != "") os<<keyValueFormatter(VL_CIK_HIER,it->second.first);
os<<"' "<<it->second.second;
os<<endl;
os<<std::endl;
}
}
};
@@ -440,9 +441,9 @@ void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
}
// Backward compatibility for Verilator
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
K(4),const string& val4, A(5),A(6)) {
string val2str = vlCovCvtToStr(val2);
string val3str = vlCovCvtToStr(val3);
K(4),const std::string& val4, A(5),A(6)) {
std::string val2str = vlCovCvtToStr(val2);
std::string val3str = vlCovCvtToStr(val3);
_insertp(C(0),C(1),
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
C(5),C(6),N(7),N(8),N(9),
+4 -5
View File
@@ -27,7 +27,6 @@
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
//=============================================================================
/// Conditionally compile coverage code
@@ -60,9 +59,9 @@ using namespace std;
///
/// vluint32_t m_cases[10];
/// constructor {
/// for (int i=0; i<10; i++) { m_cases[i]=0; }
/// for (int i=0; i<10; ++i) { m_cases[i]=0; }
/// }
/// for (int i=0; i<10; i++) {
/// for (int i=0; i<10; ++i) {
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
/// }
@@ -75,7 +74,7 @@ using namespace std;
/// Convert VL_COVER_INSERT value arguments to strings
template< class T> std::string vlCovCvtToStr (const T& t) {
ostringstream os; os<<t; return os.str();
std::ostringstream os; os<<t; return os.str();
}
//=============================================================================
@@ -115,7 +114,7 @@ public:
,A(20),D(21),D(22),D(23),D(24),D(25),D(26),D(27),D(28),D(29));
// Backward compatibility for Verilator
static void _insertp (A(0), A(1), K(2),int val2, K(3),int val3,
K(4),const string& val4, A(5),A(6));
K(4),const std::string& val4, A(5),A(6));
#undef K
#undef A
+1 -2
View File
@@ -25,7 +25,6 @@
#include "verilatedos.h"
#include <string>
using namespace std;
//=============================================================================
// Data used to edit below file, using vlcovgen
@@ -105,7 +104,7 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
class VerilatedCovKey {
public:
static string shortKey(const string& key) {
static std::string shortKey(const std::string& key) {
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
if (key == "col0") return VL_CIK_COL0;
if (key == "col0_name") return VL_CIK_COL0_NAME;
+11 -11
View File
@@ -40,7 +40,7 @@
// Not supported yet
#define _VL_SVDPI_UNIMP() \
vl_fatal(__FILE__,__LINE__,"",(string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
vl_fatal(__FILE__,__LINE__,"",(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
// Function requires a "context" in the import declaration
#define _VL_SVDPI_CONTEXT_WARN() \
@@ -58,31 +58,31 @@ const char* svDpiVersion() {
//======================================================================
// Bit-select utility functions.
svBit svGetBitselBit(const svBitVecVal* s, int i) {
_VL_SVDPI_UNIMP(); return 0;
svBit svGetBitselBit(const svBitVecVal* sp, int bit) {
return VL_BITISSET_W(sp,bit);
}
svLogic svGetBitselLogic(const svLogicVecVal* s, int i) {
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
_VL_SVDPI_UNIMP(); return 0;
}
void svPutBitselBit(svBitVecVal* d, int i, svBit s) {
_VL_SVDPI_UNIMP();
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
VL_ASSIGNBIT_WI(32, bit, dp, s);
}
void svPutBitselLogic(svLogicVecVal* d, int i, svLogic s) {
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
_VL_SVDPI_UNIMP();
}
void svGetPartselBit(svBitVecVal* d, const svBitVecVal* s, int i, int w) {
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int i, int w) {
_VL_SVDPI_UNIMP();
}
void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w) {
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int i, int w) {
_VL_SVDPI_UNIMP();
}
void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w) {
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int i, int w) {
_VL_SVDPI_UNIMP();
}
void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w) {
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int i, int w) {
_VL_SVDPI_UNIMP();
}
+5 -5
View File
@@ -37,25 +37,25 @@
/// Return svBitVecVal from WData
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
for (int i=0; i<words-1; ++i) owp[i]=lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
}
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
for (int i=0; i<words-1; ++i) owp[i]=lwp[i];
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
}
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
// Note we ignore X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
for (int i=0; i<words-1; ++i) owp[i]=lwp[i].aval;
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
}
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
// Note we don't create X/Z in svLogicVecVal
int words = VL_WORDS_I(obits);
for (int i=0; i<words; i++) owp[i].bval=0;
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
for (int i=0; i<words; ++i) owp[i].bval=0;
for (int i=0; i<words-1; ++i) owp[i].aval=lwp[i];
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
}
+30 -17
View File
@@ -36,36 +36,49 @@
//======================================================================
// Conversion functions
extern string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
inline string VL_CVT_PACK_STR_NQ(QData lhs) {
IData lw[2]; VL_SET_WQ(lw, lhs);
extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) {
WData lw[2]; VL_SET_WQ(lw, lhs);
return VL_CVT_PACK_STR_NW(2, lw);
}
inline string VL_CVT_PACK_STR_NN(const string& lhs) {
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) {
return lhs;
}
inline string VL_CVT_PACK_STR_NI(IData lhs) {
IData lw[1]; lw[0] = lhs;
inline std::string VL_CVT_PACK_STR_NI(IData lhs) {
WData lw[1]; lw[0] = lhs;
return VL_CVT_PACK_STR_NW(1, lw);
}
inline string VL_CONCATN_NNN(const string& lhs, const string& rhs) {
inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) {
return lhs+rhs;
}
inline string VL_REPLICATEN_NNQ(int,int,int, const string& lhs, IData rep) {
string out; out.reserve(lhs.length() * rep);
for (unsigned times=0; times<rep; times++) out += lhs;
inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData rep) {
std::string out; out.reserve(lhs.length() * rep);
for (unsigned times=0; times<rep; ++times) out += lhs;
return out;
}
inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs, IData rep) {
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const std::string& lhs, IData rep) {
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
}
extern IData VL_FOPEN_NI(const string& filename, IData mode);
extern IData VL_FOPEN_NI(const std::string& filename, IData mode);
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
const string& ofilename, void* memp, IData start, IData end);
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
extern string VL_SFORMATF_NX(const char* formatp, ...);
extern IData VL_VALUEPLUSARGS_IN(int rbits, const char* prefixp, char fmt, string& ldr);
const std::string& ofilename, void* memp, IData start, IData end);
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...);
extern std::string VL_SFORMATF_NX(const char* formatp, ...);
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rdp);
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) {
WData rwp[2]; // WData must always be at least 2
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = rwp[0];
return got;
}
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr) {
WData rwp[2];
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
if (got) rdr = VL_SET_QW(rwp);
return got;
}
extern IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr);
#endif // Guard
+15 -15
View File
@@ -47,9 +47,9 @@ class VerilatedImp {
// Whole class is internal use only - Global information shared between verilated*.cpp files.
// TYPES
typedef vector<string> ArgVec;
typedef map<pair<const void*,void*>,void*> UserMap;
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
typedef std::vector<std::string> ArgVec;
typedef std::map<std::pair<const void*,void*>,void*> UserMap;
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
// MEMBERS
static VerilatedImp s_s; ///< Static Singleton; One and only static this
@@ -65,8 +65,8 @@ class VerilatedImp {
int m_exportNext; ///< Next export funcnum
// File I/O
vector<FILE*> m_fdps; ///< File descriptors
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
std::vector<FILE*> m_fdps; ///< File descriptors
std::deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
public: // But only for verilated*.cpp
// CONSTRUCTORS
@@ -97,10 +97,10 @@ public: // But only for verilated*.cpp
}
static void commandArgsAdd(int argc, const char** argv) {
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
for (int i=0; i<argc; i++) s_s.m_argVec.push_back(argv[i]);
for (int i=0; i<argc; ++i) s_s.m_argVec.push_back(argv[i]);
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
}
static string argPlusMatch(const char* prefixp) {
static std::string argPlusMatch(const char* prefixp) {
// Note prefixp does not include the leading "+"
size_t len = strlen(prefixp);
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
@@ -122,13 +122,13 @@ public: // But only for verilated*.cpp
// There's often many more scopes than userdata's and thus having a ~48byte
// per map overhead * N scopes would take much more space and cache thrashing.
static inline void userInsert(const void* scopep, void* userKey, void* userData) {
UserMap::iterator it=s_s.m_userMap.find(make_pair(scopep,userKey));
UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
if (it != s_s.m_userMap.end()) it->second = userData;
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
else s_s.m_userMap.insert(it, make_pair(make_pair(scopep,userKey),userData));
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep,userKey),userData));
}
static inline void* userFind(const void* scopep, void* userKey) {
UserMap::iterator it=s_s.m_userMap.find(make_pair(scopep,userKey));
UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
else return NULL;
}
@@ -159,7 +159,7 @@ public: // But only for verilated*.cpp
// Slow ok - called once/scope at construction
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
if (it == s_s.m_nameMap.end()) {
s_s.m_nameMap.insert(it, make_pair(scopep->name(),scopep));
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(),scopep));
}
}
static inline const VerilatedScope* scopeFind(const char* namep) {
@@ -198,7 +198,7 @@ public: // But only for verilated*.cpp
// Slow ok - called once/function at creation
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
if (it == s_s.m_exportMap.end()) {
s_s.m_exportMap.insert(it, make_pair(namep, s_s.m_exportNext++));
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
return s_s.m_exportNext++;
} else {
return it->second;
@@ -207,8 +207,8 @@ public: // But only for verilated*.cpp
static int exportFind(const char* namep) {
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
string msg = (string("%Error: Testbench C called ")+namep
+" but no such DPI export function name exists in ANY model");
std::string msg = (std::string("%Error: Testbench C called ")+namep
+" but no such DPI export function name exists in ANY model");
vl_fatal("unknown",0,"", msg.c_str());
return -1;
}
@@ -238,7 +238,7 @@ public: // But only for verilated*.cpp
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start*2);
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
for (size_t i=start; i<start*2; ++i) s_s.m_fdFree.push_back((IData)i);
}
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
s_s.m_fdps[idx] = fp;
+9 -9
View File
@@ -60,8 +60,8 @@ bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t siz
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
if (VL_UNLIKELY(readDiffers(datap,size))) {
string fn = filename();
string msg = (string)"Can't deserialize save-restore file as was made from different model";
std::string fn = filename();
std::string msg = (std::string)"Can't deserialize save-restore file as was made from different model";
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
@@ -81,8 +81,8 @@ void VerilatedSerialize::header() {
void VerilatedDeserialize::header() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
string fn = filename();
string msg = (string)"Can't deserialize; file has wrong header signature";
std::string fn = filename();
std::string msg = (std::string)"Can't deserialize; file has wrong header signature";
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
@@ -98,8 +98,8 @@ void VerilatedSerialize::trailer() {
void VerilatedDeserialize::trailer() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
string fn = filename();
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
std::string fn = filename();
std::string msg = (std::string)"Can't deserialize; file has wrong end-of-file signature";
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
@@ -187,7 +187,7 @@ void VerilatedSave::flush() {
} else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space)
string msg = string(__FUNCTION__)+": "+strerror(errno);
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
vl_fatal("",0,"",msg.c_str());
close();
break;
@@ -204,7 +204,7 @@ void VerilatedRestore::fill() {
for (vluint8_t* sp=m_cp; sp < m_endp;) *rp++ = *sp++; // Overlaps
m_endp = m_bufp + (m_endp - m_cp);
m_cp = m_bufp; // Reset buffer
// Read into buffer starting at m_endp
// Read into buffer starting at m_endp
while (1) {
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
if (remaining==0) break;
@@ -215,7 +215,7 @@ void VerilatedRestore::fill() {
} else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space)
string msg = string(__FUNCTION__)+": "+strerror(errno);
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
vl_fatal("",0,"",msg.c_str());
close();
break;
+6 -7
View File
@@ -25,7 +25,6 @@
#include "verilatedos.h"
#include <string>
using namespace std;
//=============================================================================
// VerilatedSerialBase - internal base class for common code between VerilatedSerialize and VerilatedDeserialize
@@ -37,7 +36,7 @@ protected:
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
vluint8_t* m_bufp; ///< Output buffer
bool m_isOpen; ///< True indicates open file/stream
string m_filename;
std::string m_filename;
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
inline static size_t bufferInsertSize() { return 16*1024; }
@@ -58,7 +57,7 @@ public:
}
// METHODS
bool isOpen() const { return m_isOpen; }
string filename() const { return m_filename; }
std::string filename() const { return m_filename; }
virtual void close() { flush(); }
virtual void flush() {}
};
@@ -150,7 +149,7 @@ public:
virtual ~VerilatedSave() { close(); }
// METHODS
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
void open(const string& filename) { open(filename.c_str()); }
void open(const std::string& filename) { open(filename.c_str()); }
virtual void close();
virtual void flush();
};
@@ -169,7 +168,7 @@ public:
// METHODS
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
void open(const string& filename) { open(filename.c_str()); }
void open(const std::string& filename) { open(filename.c_str()); }
virtual void close();
virtual void flush() {}
virtual void fill();
@@ -219,12 +218,12 @@ inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, std::string& rhs) {
vluint32_t len=rhs.length();
os<<len;
return os.write(rhs.data(), len);
}
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& rhs) {
vluint32_t len=0;
os>>len;
rhs.resize(len);
+4 -3
View File
@@ -36,7 +36,7 @@
/// Verilator range
// See also V3Ast::VNumRange
class VerilatedRange {
class VerilatedRange {
int m_left;
int m_right;
protected:
@@ -91,13 +91,14 @@ struct VerilatedCStrCmp {
};
class VerilatedScopeNameMap
: public map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
public:
VerilatedScopeNameMap() {}
~VerilatedScopeNameMap() {}
};
class VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
class VerilatedVarNameMap
: public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
public:
VerilatedVarNameMap() {}
~VerilatedVarNameMap() {}
+28 -31
View File
@@ -46,11 +46,6 @@
# define O_NONBLOCK 0
#endif
//=============================================================================
// Global
vector<VerilatedVcd*> VerilatedVcd::s_vcdVecp; ///< List of all created traces
//=============================================================================
// VerilatedVcdCallInfo
/// Internal callback routines for each module being traced.
@@ -79,7 +74,7 @@ protected:
//=============================================================================
// VerilatedVcdFile
bool VerilatedVcdFile::open(const string& name) {
bool VerilatedVcdFile::open(const std::string& name) {
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK, 0666);
return (m_fd>=0);
}
@@ -121,7 +116,7 @@ void VerilatedVcd::open (const char* filename) {
// Set member variables
m_filename = filename;
s_vcdVecp.push_back(this);
singleton().s_vcdVecp.push_back(this);
// SPDIFF_OFF
// Set callback so an early exit will flush us
@@ -150,7 +145,7 @@ void VerilatedVcd::openNext (bool incFilename) {
closePrev(); // Close existing
if (incFilename) {
// Find _0000.{ext} in filename
string name = m_filename;
std::string name = m_filename;
size_t pos=name.rfind(".");
if (pos>8 && 0==strncmp("_cat",name.c_str()+pos-8,4)
&& isdigit(name.c_str()[pos-4])
@@ -205,18 +200,18 @@ void VerilatedVcd::makeNameMap() {
// This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const string& hiername = it->first;
const std::string& hiername = it->first;
if (hiername.size() >= 1 && hiername[0] == '\t') nullScope=true;
}
if (nullScope) {
NameMap* newmapp = new NameMap;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const string& hiername = it->first;
const string& decl = it->second;
string newname = string("top");
const std::string& hiername = it->first;
const std::string& decl = it->second;
std::string newname = std::string("top");
if (hiername[0] != '\t') newname += ' ';
newname += hiername;
newmapp->insert(make_pair(newname,decl));
newmapp->insert(std::make_pair(newname,decl));
}
deleteNameMap();
m_namemapp = newmapp;
@@ -234,8 +229,8 @@ VerilatedVcd::~VerilatedVcd() {
deleteNameMap();
if (m_filep && m_fileNewed) { delete m_filep; m_filep = NULL; }
// Remove from list of traces
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
VcdVec::iterator pos = find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), this);
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
}
void VerilatedVcd::closePrev () {
@@ -326,7 +321,7 @@ void VerilatedVcd::bufferFlush () {
} else if (got < 0) {
if (errno != EAGAIN && errno != EINTR) {
// write failed, presume error (perhaps out of disk space)
string msg = (string)"VerilatedVcd::bufferFlush: "+strerror(errno);
std::string msg = (std::string)"VerilatedVcd::bufferFlush: "+strerror(errno);
vl_fatal("",0,"",msg.c_str());
closeErr();
break;
@@ -369,7 +364,7 @@ double VerilatedVcd::timescaleToDouble (const char* unitp) {
return value;
}
string VerilatedVcd::doubleToTimescale (double value) {
std::string VerilatedVcd::doubleToTimescale (double value) {
const char* suffixp = "s";
if (value>=1e0) { suffixp="s"; value *= 1e0; }
else if (value>=1e-3 ) { suffixp="ms"; value *= 1e3; }
@@ -398,7 +393,7 @@ void VerilatedVcd::dumpHeader () {
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
printStr("$timescale ");
const string& timeResStr = doubleToTimescale(m_timeRes);
const std::string& timeResStr = doubleToTimescale(m_timeRes);
printStr(timeResStr.c_str());
printStr(" $end\n");
@@ -412,13 +407,13 @@ void VerilatedVcd::dumpHeader () {
// We detect the spaces in module names to determine hierarchy. This
// allows signals to be declared without fixed ordering, which is
// required as Verilog signals might be separately declared from
// "SP_TRACE" signals.
// SC module signals.
// Print the signal names
const char* lastName = "";
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const string& hiernamestr = it->first;
const string& decl = it->second;
const std::string& hiernamestr = it->first;
const std::string& decl = it->second;
// Determine difference between the old and new names
const char* hiername = hiernamestr.c_str();
@@ -472,7 +467,7 @@ void VerilatedVcd::dumpHeader () {
deleteNameMap();
}
void VerilatedVcd::module (const string& name) {
void VerilatedVcd::module (const std::string& name) {
m_modName = name;
}
@@ -485,7 +480,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
if (tri) codesNeeded *= 2; // Space in change array for __en signals
// Make sure array is large enough
m_nextCode = max(nextCode(), code+codesNeeded);
m_nextCode = std::max(nextCode(), code+codesNeeded);
if (m_sigs.capacity() <= m_nextCode) {
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
}
@@ -503,10 +498,10 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
// Tab separates final scope from signal name
// Tab sorts before spaces, so signals nicely will print before scopes
// Note the hiername may be nothing, if so we'll add "\t{name}"
string nameasstr = name;
std::string nameasstr = name;
if (m_modName!="") { nameasstr = m_modName+m_scopeEscape+nameasstr; } // Optional ->module prefix
string hiername;
string basename;
std::string hiername;
std::string basename;
for (const char* cp=nameasstr.c_str(); *cp; cp++) {
if (isScopeEscape(*cp)) {
// Ahh, we've just read a scope, not a basename
@@ -520,7 +515,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
hiername += "\t"+basename;
// Print reference
string decl = "$var ";
std::string decl = "$var ";
if (m_evcd) decl += "port"; else decl += wirep; // usually "wire"
char buf [1000];
sprintf(buf, " %2d ", bits);
@@ -543,7 +538,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
decl += buf;
}
decl += " $end\n";
m_namemapp->insert(make_pair(hiername,decl));
m_namemapp->insert(std::make_pair(hiername,decl));
}
void VerilatedVcd::declBit (vluint32_t code, const char* name, int arraynum)
@@ -570,6 +565,7 @@ void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum
//=============================================================================
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
// cppcheck-suppress invalidPointerCast
(*((double*)&m_sigs_oldvalp[code])) = newval;
// Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", newval);
@@ -578,6 +574,7 @@ void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
bufferCheck();
}
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
// cppcheck-suppress invalidPointerCast
(*((float*)&m_sigs_oldvalp[code])) = newval;
// Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", (double)newval);
@@ -594,7 +591,7 @@ void VerilatedVcd::addCallback (
void* userthis)
{
if (VL_UNLIKELY(isOpen())) {
string msg = (string)"Internal: "+__FILE__+"::"+__FUNCTION__+" called with already open file";
std::string msg = (std::string)"Internal: "+__FILE__+"::"+__FUNCTION__+" called with already open file";
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
}
VerilatedVcdCallInfo* vci = new VerilatedVcdCallInfo(initcb, fullcb, changecb, userthis, nextCode());
@@ -645,8 +642,8 @@ void VerilatedVcd::dumpDone () {
// Static members
void VerilatedVcd::flush_all() {
for (vluint32_t ent = 0; ent< s_vcdVecp.size(); ent++) {
VerilatedVcd* vcdp = s_vcdVecp[ent];
for (vluint32_t ent = 0; ent< singleton().s_vcdVecp.size(); ent++) {
VerilatedVcd* vcdp = singleton().s_vcdVecp[ent];
vcdp->flush();
}
}
+30 -15
View File
@@ -28,7 +28,6 @@
#include <string>
#include <vector>
#include <map>
using namespace std;
class VerilatedVcd;
class VerilatedVcdCallInfo;
@@ -45,7 +44,7 @@ public:
// METHODS
VerilatedVcdFile() : m_fd(0) {}
virtual ~VerilatedVcdFile() {}
virtual bool open(const string& name);
virtual bool open(const std::string& name);
virtual void close();
virtual ssize_t write(const char* bufp, ssize_t len);
};
@@ -80,13 +79,13 @@ private:
bool m_fileNewed; ///< m_filep needs destruction
bool m_isOpen; ///< True indicates open file
bool m_evcd; ///< True for evcd format
string m_filename; ///< Filename we're writing to (if open)
std::string m_filename; ///< Filename we're writing to (if open)
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
char m_scopeEscape; ///< Character to separate scope components
int m_modDepth; ///< Depth of module hierarchy
bool m_fullDump; ///< True indicates dump ignoring if changed
vluint32_t m_nextCode; ///< Next code number to assign
string m_modName; ///< Module name being traced now
std::string m_modName; ///< Module name being traced now
double m_timeRes; ///< Time resolution (ns/ms etc)
double m_timeUnit; ///< Time units (ns/ms etc)
vluint64_t m_timeLastDump; ///< Last time we did a dump
@@ -98,11 +97,16 @@ private:
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
vector<VerilatedVcdSig> m_sigs; ///< Pointer to signal information
vector<VerilatedVcdCallInfo*> m_callbacks; ///< Routines to perform dumping
typedef map<string,string> NameMap;
NameMap* m_namemapp; ///< List of names for the header
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
std::vector<VerilatedVcdSig> m_sigs; ///< Pointer to signal information
std::vector<VerilatedVcdCallInfo*> m_callbacks; ///< Routines to perform dumping
typedef std::map<std::string,std::string> NameMap;
NameMap* m_namemapp; ///< List of names for the header
typedef std::vector<VerilatedVcd*> VcdVec;
struct Singleton {
VcdVec s_vcdVecp; ///< List of all created traces
};
static Singleton& singleton() { static Singleton s; return s; }
void bufferResize(vluint64_t minsize);
void bufferFlush();
@@ -136,8 +140,8 @@ private:
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
*m_writep++ = ((char)((code)%94+33));
}
static string stringCode (vluint32_t code) {
string out;
static std::string stringCode (vluint32_t code) {
std::string out;
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
if (code>=(94)) out += ((char)((code/94)%94+33));
@@ -175,13 +179,13 @@ public:
void close (); ///< Close the file
void set_time_unit (const char* unit); ///< Set time units (s/ms, defaults to ns)
void set_time_unit (const string& unit) { set_time_unit(unit.c_str()); }
void set_time_unit (const std::string& unit) { set_time_unit(unit.c_str()); }
void set_time_resolution (const char* unit); ///< Set time resolution (s/ms, defaults to ns)
void set_time_resolution (const string& unit) { set_time_resolution(unit.c_str()); }
void set_time_resolution (const std::string& unit) { set_time_resolution(unit.c_str()); }
double timescaleToDouble (const char* unitp);
string doubleToTimescale (double value);
std::string doubleToTimescale (double value);
/// Inside dumping routines, called each cycle to make the dump
void dump (vluint64_t timeui);
@@ -194,7 +198,7 @@ public:
void* userthis);
/// Inside dumping routines, declare a module
void module (const string& name);
void module (const std::string& name);
/// Inside dumping routines, declare a signal
void declBit (vluint32_t code, const char* name, int arraynum);
void declBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
@@ -382,11 +386,13 @@ public:
}
}
inline void chgDouble (vluint32_t code, const double newval) {
// cppcheck-suppress invalidPointerCast
if (VL_UNLIKELY((*((double*)&m_sigs_oldvalp[code])) != newval)) {
fullDouble (code, newval);
}
}
inline void chgFloat (vluint32_t code, const float newval) {
// cppcheck-suppress invalidPointerCast
if (VL_UNLIKELY((*((float*)&m_sigs_oldvalp[code])) != newval)) {
fullFloat (code, newval);
}
@@ -428,6 +434,15 @@ public:
void dump (double timestamp) { dump((vluint64_t)timestamp); }
void dump (vluint32_t timestamp) { dump((vluint64_t)timestamp); }
void dump (int timestamp) { dump((vluint64_t)timestamp); }
/// Set time units (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
void set_time_unit (const char* unit) { m_sptrace.set_time_unit(unit); }
void set_time_unit (const std::string& unit) { set_time_unit(unit.c_str()); }
/// Set time resolution (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
void set_time_resolution (const char* unit) { m_sptrace.set_time_resolution(unit); }
void set_time_resolution (const std::string& unit) { set_time_resolution(unit.c_str()); }
/// Internal class access
inline VerilatedVcd* spTrace () { return &m_sptrace; };
};
+20 -21
View File
@@ -386,7 +386,7 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) {
#define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got),(exp))) { \
string msg = string("%Error: ") \
std::string msg = std::string("%Error: ") \
+ "GOT = '"+((got)?(got):"<null>")+"'" \
+ " EXP = '"+((exp)?(exp):"<null>")+"'"; \
vl_fatal(__FILE__,__LINE__,"",msg.c_str()); \
@@ -502,9 +502,9 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
const VerilatedVar* varp;
const VerilatedScope* scopep;
string scopeAndName = namep;
std::string scopeAndName = namep;
if (voScopep) {
scopeAndName = string(voScopep->fullname()) + "." + namep;
scopeAndName = std::string(voScopep->fullname()) + "." + namep;
namep = (PLI_BYTE8*)scopeAndName.c_str();
}
{
@@ -514,11 +514,11 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
return (new VerilatedVpioScope(scopep))->castVpiHandle();
}
const char* baseNamep = scopeAndName.c_str();
string scopename;
std::string scopename;
const char* dotp = strrchr(namep, '.');
if (VL_LIKELY(dotp)) {
baseNamep = dotp+1;
scopename = string(namep,dotp-namep);
scopename = std::string(namep,dotp-namep);
}
scopep = Verilated::scopeFind(scopename.c_str());
if (!scopep) return NULL;
@@ -754,7 +754,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
}
WDataInP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
out[i].aval = datap[i];
out[i].bval = 0;
}
@@ -791,7 +791,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
}
for (i=0; i<bits; i++) {
for (i=0; i<bits; ++i) {
char val = (datap[i>>3]>>(i&7))&1;
outStr[bits-i-1] = val?'1':'0';
}
@@ -821,7 +821,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
}
for (i=0; i<chars; i++) {
for (i=0; i<chars; ++i) {
div_t idx = div(i*3, 8);
int val = datap[idx.quot];
if ((idx.quot+1)<bytes) {
@@ -882,7 +882,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
chars = outStrSz;
}
for (i=0; i<chars; i++) {
for (i=0; i<chars; ++i) {
char val = (datap[i>>1]>>((i&1)<<2))&15;
static char hex[] = "0123456789abcdef";
if (i==(chars-1)) {
@@ -922,7 +922,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes);
bytes = outStrSz;
}
for (i=0; i<bytes; i++) {
for (i=0; i<bytes; ++i) {
char val = datap[bytes-i-1];
// other simulators replace [leading?] zero chars with spaces, replicate here.
outStr[i] = val?val:' ';
@@ -946,11 +946,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
value_p->value.integer = *((IData*)(vop->varDatap()));
return;
case VLVT_WDATA:
case VLVT_UINT64:
// Not legal
value_p->value.integer = 0;
case VLVT_WDATA: // FALLTHRU
case VLVT_UINT64: // FALLTHRU
default:
value_p->value.integer = 0;
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return;
@@ -1007,7 +1006,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_WDATA: {
int words = VL_WORDS_I(vop->varp()->range().elements());
WDataOutP datap = ((IData*)(vop->varDatap()));
for (int i=0; i<words; i++) {
for (int i=0; i<words; ++i) {
datap[i] = value_p->value.vector[i].aval;
if (i==(words-1)) {
datap[i] &= vop->mask();
@@ -1037,7 +1036,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
int bits = vop->varp()->range().elements();
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
for (int i=0; i<bits; i++) {
for (int i=0; i<bits; ++i) {
char set = (i < len)?(value_p->value.str[len-i-1]=='1'):0;
// zero bits 7:1 of byte when assigning to bit 0, else
// or in 1 if bit set
@@ -1067,7 +1066,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
CData* datap = ((CData*)(vop->varDatap()));
div_t idx;
datap[0] = 0; // reset zero'th byte
for (int i=0; i<chars; i++) {
for (int i=0; i<chars; ++i) {
union {
char byte[2];
short half;
@@ -1105,7 +1104,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
datap[idx.quot+1] &= vop->mask_byte(idx.quot+1);
}
// zero off remaining top bytes
for (int i=idx.quot+2; i<bytes; i++) {
for (int i=idx.quot+2; i<bytes; ++i) {
datap[i] = 0;
}
return object;
@@ -1155,7 +1154,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
val += 2;
}
int len = strlen(val);
for (int i=0; i<chars; i++) {
for (int i=0; i<chars; ++i) {
char hex;
// compute hex digit value
if (i < len) {
@@ -1197,7 +1196,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
int bytes = VL_BYTES_I(vop->varp()->range().elements());
int len = strlen(value_p->value.str);
CData* datap = ((CData*)(vop->varDatap()));
for (int i=0; i<bytes; i++) {
for (int i=0; i<bytes; ++i) {
datap[i] = (i < len)?value_p->value.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes
}
return object;
@@ -1255,7 +1254,7 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
}
if (time_p->type == vpiSimTime) {
QData qtime = VL_TIME_Q();
IData itime[2];
WData itime[2];
VL_SET_WQ(itime, qtime);
time_p->low = itime[0];
time_p->high = itime[1];
+29 -28
View File
@@ -99,8 +99,8 @@ public:
virtual const char* name() { return "<null>"; }
virtual const char* fullname() { return "<null>"; }
virtual const char* defname() { return "<null>"; }
virtual const vluint32_t type() { return 0; }
virtual const vluint32_t size() const { return 0; }
virtual vluint32_t type() { return 0; }
virtual vluint32_t size() const { return 0; }
virtual const VerilatedRange* rangep() const { return NULL; }
virtual vpiHandle dovpi_scan() { return 0; }
};
@@ -120,7 +120,7 @@ public:
}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiCallback; }
virtual vluint32_t type() { return vpiCallback; }
vluint32_t reason() const { return m_cbData.reason; }
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
t_cb_data* cb_datap() { return &(m_cbData); }
@@ -133,7 +133,7 @@ public:
explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
virtual ~VerilatedVpioConst() {}
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiUndefined; }
virtual vluint32_t type() { return vpiUndefined; }
vlsint32_t num() const { return m_num; }
};
@@ -144,8 +144,8 @@ public:
explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
virtual ~VerilatedVpioRange() {}
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiRange; }
virtual const vluint32_t size() const { return m_range->elements(); }
virtual vluint32_t type() { return vpiRange; }
virtual vluint32_t size() const { return m_range->elements(); }
virtual const VerilatedRange* rangep() const { return m_range; }
int iteration() const { return m_iteration; }
void iterationInc() { ++m_iteration; }
@@ -167,7 +167,7 @@ public:
: m_scopep(scopep) {}
virtual ~VerilatedVpioScope() {}
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiScope; }
virtual vluint32_t type() { return vpiScope; }
const VerilatedScope* scopep() const { return m_scopep; }
virtual const char* name() { return m_scopep->name(); }
virtual const char* fullname() { return m_scopep->name(); }
@@ -206,17 +206,17 @@ public:
vluint32_t mask() const { return m_mask.u32; }
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
vluint32_t entSize() const { return m_entSize; }
const vluint32_t index() { return m_index; }
virtual const vluint32_t type() {
vluint32_t index() { return m_index; }
virtual vluint32_t type() {
if (varp()->vldir() != vpiNoDirection) return vpiPort;
return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
}
virtual const vluint32_t size() const { return get_range().elements(); }
virtual vluint32_t size() const { return get_range().elements(); }
virtual const VerilatedRange* rangep() const { return &get_range(); }
virtual const char* name() { return m_varp->name(); }
virtual const char* fullname() {
VL_STATIC_OR_THREAD string out;
out = string(m_scopep->name())+"."+name();
VL_STATIC_OR_THREAD std::string out;
out = std::string(m_scopep->name())+"."+name();
return out.c_str();
}
void* prevDatap() const { return m_prevDatap; }
@@ -239,13 +239,13 @@ public:
}
virtual ~VerilatedVpioMemoryWord() {}
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiMemoryWord; }
virtual const vluint32_t size() const { return varp()->range().elements(); }
virtual vluint32_t type() { return vpiMemoryWord; }
virtual vluint32_t size() const { return varp()->range().elements(); }
virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
virtual const char* fullname() {
VL_STATIC_OR_THREAD string out;
VL_STATIC_OR_THREAD std::string out;
char num[20]; sprintf(num,"%d",m_index);
out = string(scopep()->name())+"."+name()+"["+num+"]";
out = std::string(scopep()->name())+"."+name()+"["+num+"]";
return out.c_str();
}
};
@@ -259,7 +259,7 @@ public:
: m_scopep(scopep), m_started(false) { }
virtual ~VerilatedVpioVarIter() {}
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiIterator; }
virtual vluint32_t type() { return vpiIterator; }
virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) {
VerilatedVarNameMap* varsp = m_scopep->varsp();
@@ -286,7 +286,7 @@ public:
: m_handle(handle), m_varp(varp), m_iteration(varp->array().right()), m_direction(VL_LIKELY(varp->array().left()>varp->array().right())?1:-1), m_done(false) { }
virtual ~VerilatedVpioMemoryWordIter() {}
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
virtual const vluint32_t type() { return vpiIterator; }
virtual vluint32_t type() { return vpiIterator; }
void iterationInc() { if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction; }
virtual vpiHandle dovpi_scan() {
vpiHandle result;
@@ -301,8 +301,8 @@ public:
struct VerilatedVpiTimedCbsCmp {
/// Ordering sets keyed by time, then callback descriptor
bool operator() (const pair<QData,VerilatedVpioCb*>& a,
const pair<QData,VerilatedVpioCb*>& b) const {
bool operator() (const std::pair<QData,VerilatedVpioCb*>& a,
const std::pair<QData,VerilatedVpioCb*>& b) const {
if (a.first < b.first) return 1;
if (a.first > b.first) return 0;
return a.second < b.second;
@@ -313,8 +313,8 @@ class VerilatedVpiError;
class VerilatedVpi {
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
typedef list<VerilatedVpioCb*> VpioCbList;
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
typedef std::list<VerilatedVpioCb*> VpioCbList;
typedef std::set<std::pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
struct product_info {
PLI_BYTE8* product;
@@ -339,7 +339,7 @@ public:
s_s.m_cbObjLists[vop->reason()].push_back(vop);
}
static void cbTimedAdd(VerilatedVpioCb* vop) {
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
s_s.m_timedCbs.insert(std::make_pair(vop->time(), vop));
}
static void cbReasonRemove(VerilatedVpioCb* cbp) {
VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
@@ -350,7 +350,7 @@ public:
}
}
static void cbTimedRemove(VerilatedVpioCb* cbp) {
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(std::make_pair(cbp->time(),cbp));
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
s_s.m_timedCbs.erase(it);
}
@@ -389,7 +389,8 @@ public:
}
static void callValueCbs() {
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
set<VerilatedVpioVar*> update; // set of objects to update after callbacks
typedef std::set<VerilatedVpioVar*> VpioVarSet;
VpioVarSet update; // set of objects to update after callbacks
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
it = cbObjList.erase(it);
@@ -411,7 +412,7 @@ public:
}
}
}
for (set<VerilatedVpioVar*>::iterator it=update.begin(); it!=update.end(); ++it) {
for (VpioVarSet::iterator it=update.begin(); it!=update.end(); ++it) {
memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
}
}
@@ -462,8 +463,8 @@ public:
m_errorInfo.level = level;
return this;
}
void setMessage(string file, PLI_INT32 line, string message, ...) {
static VL_THREAD string filehold;
void setMessage(std::string file, PLI_INT32 line, std::string message, ...) {
static VL_THREAD std::string filehold;
_VL_VPI_ERROR_SET;
m_errorInfo.state = vpiPLI;
filehold = file;
+4 -1
View File
@@ -46,6 +46,7 @@
# define VL_FUNC __func__
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
# define VL_UNREACHABLE __builtin_unreachable();
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
#elif defined(_MSC_VER)
@@ -57,6 +58,7 @@
# define VL_FUNC __FUNCTION__
# define VL_LIKELY(x) (!!(x))
# define VL_UNLIKELY(x) (!!(x))
# define VL_UNREACHABLE
# define VL_PREFETCH_RD(p)
# define VL_PREFETCH_RW(p)
#else
@@ -68,6 +70,7 @@
# define VL_FUNC "__func__" ///< Name of current function for error macros
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
# define VL_UNREACHABLE ///< Point that may never be reached
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
#endif
@@ -95,7 +98,7 @@
// This is not necessarily the same as #UL, depending on what the IData typedef is.
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
#ifdef VL_CPPCHECK
#if defined(VL_CPPCHECK) || defined(__clang_analyzer__)
# define VL_DANGLING(v)
#else
# define VL_DANGLING(v) do { (v) = NULL; } while(0) ///< After e.g. delete, set variable to NULL to indicate must not use later
+7 -7
View File
@@ -124,7 +124,7 @@ if [ x"$dir_arg" != x ]; then
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
@@ -134,7 +134,7 @@ else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
@@ -162,7 +162,7 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
@@ -201,17 +201,17 @@ else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
@@ -242,7 +242,7 @@ else
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
+1 -1
View File
@@ -709,7 +709,7 @@ Start GDB, then C<start> with the remaining arguments.
Temporary breakpoint 1, main (argc=13, argv=0xbfffefa4, env=0xbfffefdc)
at ../Verilator.cpp:615
615 ios::sync_with_stdio();
(gdb)
(gdb)
You can then continue execution with breakpoints as required.
+1 -1
View File
@@ -8,7 +8,7 @@ use strict;
#======================================================================
# main
eval `modulecmd perl add synopsys-vcs_mx`;
eval `modulecmd perl add synopsys-sim`;
exec('vcs',@ARGV);
#######################################################################
+4 -10
View File
@@ -64,6 +64,8 @@ LDFLAGS += @LDFLAGS@
EXEEXT = @EXEEXT@
CFG_CXXFLAGS_SRC = @CFG_CXXFLAGS_SRC@
CFG_CXXFLAGS_PARSER = @CFG_CXXFLAGS_PARSER@
# Compiler flags that turn on extra warnings
CFG_CXXFLAGS_WEXTRA = @CFG_CXXFLAGS_WEXTRA@
#### End of system configuration section. ####
@@ -73,7 +75,7 @@ TGT = ../../verilator_bin
#################
ifeq ($(VL_DEBUG),)
# Optimize
COPT = -O
COPT = -O2
else
# Debug
COPT = -ggdb -DVL_DEBUG
@@ -97,7 +99,7 @@ CPPFLAGS += -DYYDEBUG # Required to get nice error messages
CPPFLAGS += $(COPT)
CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_WEXTRA) $(CFG_CXXFLAGS_SRC) -Werror
#CPPFLAGS += -pedantic-errors
else
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
@@ -105,12 +107,6 @@ endif
CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
#else if set, leave as-is.
#else if SYSTEMPERL="" don't set _INCLUDE so source will figure it out
endif
# Allow RPM builds to specify hardcoded data directories
# To do this:
ifeq ($(CFG_WITH_DEFENV),yes)
@@ -118,8 +114,6 @@ ifeq ($(CFG_WITH_DEFENV),yes)
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
CPPFLAGS += -DDEFENV_SYSTEMC_INCLUDE=\"$(SYSTEMC_INCLUDE)\"
CPPFLAGS += -DDEFENV_SYSTEMC_LIBDIR=\"$(SYSTEMC_LIBDIR)\"
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(pkgdatadir)\"
else
+3 -3
View File
@@ -176,7 +176,7 @@ private:
if (m_check == CT_INITIAL) {
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
} else if (m_check == CT_LATCH) {
// Suppress. Shouldn't matter that the interior of the latch races
// Suppress. Shouldn't matter that the interior of the latch races
} else {
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
}
@@ -323,7 +323,7 @@ private:
// Read sensitivitues
m_itemCombo = false;
m_itemSequent = false;
oldsensesp->iterateAndNext(*this);
if (oldsensesp) oldsensesp->iterateAndNext(*this);
bool combo = m_itemCombo;
bool sequent = m_itemSequent;
@@ -438,5 +438,5 @@ public:
void V3Active::activeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("active.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -2
View File
@@ -108,7 +108,7 @@ private:
// Move the active's contents to the other active
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
if (nodep->sensesStorep()) {
if (sensesp != nodep->sensesStorep()) nodep->v3fatalSrc("sensesStore should have been deleted earlier if different\n");
if (sensesp != nodep->sensesStorep()) nodep->v3fatalSrc("sensesStore should have been deleted earlier if different");
sensesp->unlinkFrBack();
// There may be other references to same sense tree,
// we'll be removing all references when we get to them,
@@ -160,5 +160,5 @@ public:
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ActiveTopVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("activetop.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+11 -21
View File
@@ -119,7 +119,7 @@ private:
} else {
nodep->v3fatalSrc("Unknown node type");
}
if (stmtsp) bodysp = bodysp->addNext(stmtsp);
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
bodysp = ifp;
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
@@ -162,7 +162,7 @@ private:
// Bye
pushDeletep(nodep); VL_DANGLING(nodep);
}
virtual void visit(AstIf* nodep) {
if (nodep->user1SetOnce()) return;
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
@@ -177,12 +177,12 @@ private:
// Recurse into the true case.
ifp->ifsp()->iterateAndNext(*this);
// If the last else is not an else if, recurse into that too.
if (ifp->elsesp() && !nextifp) {
ifp->elsesp()->iterateAndNext(*this);
}
// Build a bitmask of the true predicates
AstNode* predp = ifp->condp()->cloneTree(false);
if (propp) {
@@ -195,13 +195,13 @@ private:
if (ifp->elsesp() && !nextifp) {
hasDefaultElse = true;
}
ifp = nextifp;
} while (ifp);
AstNode *newifp = nodep->cloneTree(false);
bool allow_none = nodep->unique0Pragma();
// Note: if this ends with an 'else', then we don't need to validate that one of the
// predicates evaluates to true.
AstNode* ohot = ((allow_none || hasDefaultElse)
@@ -246,20 +246,10 @@ private:
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
AstNode* onep;
AstConst* iconstp = icondp->castConst();
if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
AstNode* and1p = new AstAnd(itemp->fileline(), nodep->exprp()->cloneTree(false),
new AstConst(itemp->fileline(), nummask));
AstNode* and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
onep = AstEq::newTyped(itemp->fileline(), and1p, and2p);
if (nodep->casex() || nodep->casez() || nodep->caseInside()) {
onep = AstEqWild::newTyped(itemp->fileline(),
nodep->exprp()->cloneTree(false),
icondp->cloneTree(false));
} else {
onep = AstEq::newTyped(icondp->fileline(),
nodep->exprp()->cloneTree(false),
@@ -354,5 +344,5 @@ public:
void V3Assert::assertAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("assert.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -137,5 +137,5 @@ public:
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
AssertPreVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("assertpre.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+9 -3
View File
@@ -716,6 +716,7 @@ void AstNode::deleteTree() {
#ifdef VL_LEAK_CHECKS
void* AstNode::operator new(size_t size) {
// Optimization note: Aligning to cache line is a loss, due to lost packing
AstNode* objp = static_cast<AstNode*>(::operator new(size));
V3Broken::addNewed(objp);
return objp;
@@ -734,6 +735,7 @@ void AstNode::operator delete(void* objp, size_t size) {
void AstNode::iterateChildren(AstNVisitor& v) {
// This is a very hot function
// Optimization note: Grabbing m_op#p->m_nextp is a net loss
ASTNODE_PREFETCH(m_op1p);
ASTNODE_PREFETCH(m_op2p);
ASTNODE_PREFETCH(m_op3p);
@@ -766,11 +768,13 @@ void AstNode::iterateAndNext(AstNVisitor& v) {
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
#endif
if (nodep) ASTNODE_PREFETCH(nodep->m_nextp);
while (nodep) { // effectively: if (!this) return; // Callers rely on this
if (nodep->m_nextp) ASTNODE_PREFETCH(nodep->m_nextp->m_nextp);
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
ASTNODE_PREFETCH(nodep->m_nextp);
// Desirable check, but many places where multiple iterations are OK
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
// Optimization note: Doing PREFETCH_RW on m_iterpp is a net even
// cppcheck-suppress nullPointer
niterp->m_iterpp = &niterp;
niterp->accept(v);
@@ -902,7 +906,7 @@ bool AstNode::sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool
//======================================================================
// Static utilities
ostream& operator<<(ostream& os, V3Hash rhs) {
ostream& operator<<(ostream& os, const V3Hash& rhs) {
return os<<hex<<setw(2)<<setfill('0')<<rhs.depth()
<<"_"<<setw(6)<<setfill('0')<<rhs.hshval();
}
@@ -975,7 +979,7 @@ void AstNode::dumpTreeGdb() { // For GDB only
dumpTree(cout);
}
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree",98);
string filename = filenamep ? filenamep : v3Global.debugFilename("debug",98);
v3Global.rootp()->dumpTreeFile(filename);
}
@@ -1057,6 +1061,8 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
editCountSetLast();
}
void AstNode::v3errorEndFatal(ostringstream& str) const { v3errorEnd(str); assert(0); }
void AstNode::v3errorEnd(ostringstream& str) const {
if (!dynamic_cast<const AstNode*>(this)) {
// No known cases cause this, but better than a core dump
+30 -14
View File
@@ -61,7 +61,7 @@ public:
inline bool operator== (AstType lhs, AstType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstType lhs, AstType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstType::en lhs, AstType rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstType rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const AstType& rhs) { return os<<rhs.ascii(); }
//######################################################################
@@ -107,7 +107,7 @@ public:
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const AstNumeric& rhs) { return os<<rhs.ascii(); }
//######################################################################
@@ -396,7 +396,7 @@ public:
return (m_e==LOGIC || m_e==BIT);
}
bool isDpiUnsupported() const {
return (m_e==LOGIC || m_e==TIME);
return (m_e==TIME);
}
bool isDpiUnsignable() const { // Can add "unsigned" to DPI
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
@@ -464,7 +464,7 @@ public:
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstVarType::en lhs, AstVarType rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstVarType rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const AstVarType& rhs) { return os<<rhs.ascii(); }
//######################################################################
@@ -496,7 +496,7 @@ public:
inline bool operator== (AstBranchPred lhs, AstBranchPred rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstBranchPred lhs, AstBranchPred::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstBranchPred::en lhs, AstBranchPred rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstBranchPred rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const AstBranchPred& rhs) { return os<<rhs.ascii(); }
//######################################################################
@@ -529,7 +529,7 @@ public:
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstVarAttrClocker::en lhs, AstVarAttrClocker rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstVarAttrClocker rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const AstVarAttrClocker& rhs) { return os<<rhs.ascii(); }
//######################################################################
@@ -628,7 +628,7 @@ public:
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstParseRefExp lhs, AstParseRefExp::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstParseRefExp::en lhs, AstParseRefExp rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstParseRefExp rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const AstParseRefExp& rhs) { return os<<rhs.ascii(); }
//######################################################################
// VNumRange - Structure containing numberic range information
@@ -680,7 +680,7 @@ struct VNumRange {
{ return (!m_ranged || (m_lo==0 && m_hi>=1 && !m_littleEndian)); }
void dump(ostream& str) const { if (ranged()) str<<"["<<left()<<":"<<right()<<"]"; else str<<"[norg]"; }
};
inline ostream& operator<<(ostream& os, VNumRange rhs) { rhs.dump(os); return os; }
inline ostream& operator<<(ostream& os, const VNumRange& rhs) { rhs.dump(os); return os; }
//######################################################################
@@ -709,7 +709,7 @@ struct VBasicTypeKey {
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
return false; }
VBasicTypeKey(int width, int widthMin, AstNumeric numeric, AstBasicDTypeKwd kwd,
VNumRange nrange)
const VNumRange& nrange)
: m_width(width), m_widthMin(widthMin), m_numeric(numeric),
m_keyword(kwd), m_nrange(nrange) {}
~VBasicTypeKey() {}
@@ -733,8 +733,9 @@ class VNUser {
} m_u;
public:
VNUser() {}
// non-explicit:
VNUser(int i) { m_u.up = 0; m_u.ui = i; }
VNUser(void* p) { m_u.up = p; }
explicit VNUser(void* p) { m_u.up = p; }
~VNUser() {}
// Casters
WidthVP* c() { return ((WidthVP*)m_u.up); }
@@ -891,7 +892,7 @@ public:
AstNode* oldp() const { return m_oldp; }
void dump(ostream& str=cout) const;
};
inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;}
inline ostream& operator<<(ostream& os, const AstNRelinker& rhs) { rhs.dump(os); return os;}
//######################################################################
// V3Hash -- Node hashing for V3Combine
@@ -903,7 +904,8 @@ class V3Hash {
uint32_t m_both;
static const uint32_t M24 = ((1<<24)-1);
void setBoth(uint32_t depth, uint32_t hshval) {
if (depth==0) depth=1; if (depth>255) depth=255;
if (depth==0) depth=1;
if (depth>255) depth=255;
m_both = (depth<<24) | (hshval & M24);
}
public:
@@ -940,7 +942,7 @@ public:
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3, V3Hash h4) {
setBoth(1,((h1.hshval()*31+h2.hshval())*31+h3.hshval())*31+h4.hshval()); }
};
ostream& operator<<(ostream& os, V3Hash rhs);
ostream& operator<<(ostream& os, const V3Hash& rhs);
//######################################################################
// AstNode -- Base type of all Ast types
@@ -1230,6 +1232,7 @@ public:
// METHODS - dump and error
void v3errorEnd(ostringstream& str) const;
void v3errorEndFatal(ostringstream& str) const VL_ATTR_NORETURN;
string warnMore() const;
virtual void dump(ostream& str=cout);
void dumpGdb(); // For GDB only
@@ -1509,6 +1512,7 @@ public:
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; }
virtual string verilogKwd() const { return "="; }
virtual bool brokeLhsMustBeLvalue() const = 0;
};
class AstNodeFor : public AstNodeStmt {
@@ -1675,6 +1679,7 @@ public:
virtual bool maybePointedTo() const { return true; }
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
//
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
@@ -1724,6 +1729,9 @@ public:
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
// op1 = members
virtual bool similarDType(AstNodeDType* samep) const {
return this==samep; // We don't compare members, require exact equivalence
}
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
bool packed() const { return m_packed; }
@@ -1754,7 +1762,7 @@ public:
virtual void dump(ostream& str);
virtual void dumpSmall(ostream& str);
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|| (!m_refDTypep && childDTypep()))); return NULL; }
|| (!m_refDTypep && childDTypep()))); return NULL; }
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
m_refDTypep = m_refDTypep->clonep();
}}
@@ -1763,6 +1771,14 @@ public:
return (msb()==sp->msb()
&& subDTypep()==sp->subDTypep()
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
virtual bool similarDType(AstNodeDType* samep) const {
AstNodeArrayDType* sp = samep->castNodeArrayDType();
return (sp
&& type() == samep->type()
&& msb() == sp->msb()
&& rangenp()->sameTree(sp->rangenp())
&& subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()));
}
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
+12 -1
View File
@@ -140,6 +140,13 @@ AstNodeBiop* AstLte::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
}
}
AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
if (lhsp->isDouble() && rhsp->isDouble()) {
return new AstEqD(fl, lhsp, rhsp);
} else {
return new AstEqWild(fl, lhsp, rhsp);
}
}
bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
@@ -219,7 +226,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
arg += "float";
} else if (strtype) {
if (isInOnly()) arg += "const ";
arg += "string";
arg += "std::string";
} else if (widthMin() <= 8) {
arg += "CData";
} else if (widthMin() <= 16) {
@@ -884,6 +891,10 @@ void AstNodeModule::dump(ostream& str) {
if (inLibrary()) str<<" [LIB]";
if (dead()) str<<" [DEAD]";
}
void AstPackageExport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
}
void AstPackageImport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
+79 -31
View File
@@ -121,21 +121,24 @@ public:
m_littleEndian = false;
setOp2p(new AstConst(fl,msb)); setOp3p(new AstConst(fl,lsb));
}
AstRange(FileLine* fl, VNumRange range)
AstRange(FileLine* fl, const VNumRange& range)
:AstNode(fl) {
m_littleEndian = range.littleEndian();
setOp2p(new AstConst(fl,range.hi())); setOp3p(new AstConst(fl,range.lo()));
}
ASTNODE_NODE_FUNCS(Range)
AstNode* msbp() const { return op2p(); } // op2 = Msb expression
AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression
AstNode* msbp() const { return op2p(); } // op2 = Msb expression
AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression
AstNode* leftp() const { return littleEndian()?lsbp():msbp(); } // How to show a declaration
AstNode* rightp() const { return littleEndian()?msbp():lsbp(); }
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()) ? msbConst()-lsbConst()+1 : lsbConst()-msbConst()+1; }
bool littleEndian() const { return m_littleEndian; }
void littleEndian(bool flag) { m_littleEndian=flag; }
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()) ? msbConst()-lsbConst()+1 : lsbConst()-msbConst()+1; }
int leftConst() const { AstConst* constp=leftp()->castConst(); return (constp?constp->toSInt():0); }
int rightConst() const { AstConst* constp=rightp()->castConst(); return (constp?constp->toSInt():0); }
int leftToRightInc() const { return littleEndian()?1:-1; }
bool littleEndian() const { return m_littleEndian; }
void littleEndian(bool flag) { m_littleEndian=flag; }
virtual void dump(ostream& str);
virtual string emitC() { V3ERROR_NA; return ""; }
virtual V3Hash sameHash() const { return V3Hash(); }
@@ -180,6 +183,10 @@ public:
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
virtual bool similarDType(AstNodeDType* samep) const {
AstParamTypeDType* sp = samep->castParamTypeDType();
return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()));
}
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
// METHODS
@@ -251,6 +258,8 @@ public:
}
ASTNODE_NODE_FUNCS(DefImplicitDType)
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; }
virtual bool similarDType(AstNodeDType* samep) const {
return type()==samep->type() && same(samep); }
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
@@ -392,14 +401,16 @@ public:
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); }
virtual bool same(AstNode* samep) const { // width/widthMin/numeric compared elsewhere
return samep->castBasicDType()->m == m; }
virtual bool similarDType(AstNodeDType* samep) const {
return type()==samep->type() && same(samep); }
virtual string name() const { return m.m_keyword.ascii(); }
virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; }
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
void rangep(AstRange* nodep) { setNOp1p(nodep); }
void setSignedState(VSignedState signst) {
// Note NOSIGN does NOT change the state; this is required by the parser
if (signst==signedst_UNSIGNED) numeric(VSignedState(signst));
else if (signst==signedst_SIGNED) numeric(VSignedState(signst));
if (signst==signedst_UNSIGNED) numeric(signst);
else if (signst==signedst_SIGNED) numeric(signst);
}
// METHODS
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
@@ -456,6 +467,8 @@ public:
}}
virtual bool same(AstNode* samep) const {
return (m_refDTypep==samep->castConstDType()->m_refDTypep); }
virtual bool similarDType(AstNodeDType* samep) const {
return skipRefp()->similarDType(samep->skipRefp()); }
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } // node's type() included elsewhere
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
@@ -499,6 +512,7 @@ public:
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
virtual int widthAlignBytes() const { return 1; }
virtual int widthTotalBytes() const { return 1; }
string cellName() const { return m_cellName; }
@@ -540,6 +554,8 @@ public:
return (m_refDTypep==samep->castRefDType()->m_refDTypep
&& m_name==samep->castRefDType()->m_name
&& m_packagep==samep->castRefDType()->m_packagep); }
virtual bool similarDType(AstNodeDType* samep) const {
return skipRefp()->similarDType(samep->skipRefp()); }
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(m_packagep)); }
virtual void dump(ostream& str=cout);
virtual string name() const { return m_name; }
@@ -623,6 +639,7 @@ public:
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
//
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
@@ -704,6 +721,7 @@ public:
m_refDTypep = m_refDTypep->clonep();
}}
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castEnumDType()->m_uniqueNum; }
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Data type
@@ -728,11 +746,12 @@ class AstParseTypeDType : public AstNodeDType {
// During parsing, this indicates the type of a parameter is a "parameter type"
// e.g. the data type is a container of any data type
public:
AstParseTypeDType(FileLine* fl)
explicit AstParseTypeDType(FileLine* fl)
: AstNodeDType(fl) {}
ASTNODE_NODE_FUNCS(ParseTypeDType)
AstNodeDType* dtypep() const { return NULL; }
// METHODS
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
virtual AstBasicDType* basicp() const { return NULL; }
virtual AstNodeDType* skipRefp() const { return NULL; }
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
@@ -1489,6 +1508,31 @@ public:
virtual string verilogKwd() const { return "primitive"; }
};
class AstPackageExportStarStar : public AstNode {
// A package export *::* declaration
public:
AstPackageExportStarStar(FileLine* fl)
: AstNode (fl) {}
ASTNODE_NODE_FUNCS(PackageExportStarStar)
};
class AstPackageExport : public AstNode {
private:
// A package export declaration
string m_name;
AstPackage* m_packagep; // Package hierarchy
public:
AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
: AstNode (fl), m_name(name), m_packagep(packagep) {}
ASTNODE_NODE_FUNCS(PackageExport)
virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; }
virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); }
virtual void dump(ostream& str);
virtual string name() const { return m_name; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
};
class AstPackageImport : public AstNode {
private:
// A package import declaration
@@ -1639,7 +1683,7 @@ private:
string m_name; // Cell name
public:
AstCellRef(FileLine* fl,
string name, AstNode* cellp, AstNode* exprp)
const string& name, AstNode* cellp, AstNode* exprp)
: AstNode(fl)
, m_name(name) {
addNOp1p(cellp); addNOp2p(exprp); }
@@ -1656,7 +1700,7 @@ private:
string m_name; // Array name
public:
AstCellArrayRef(FileLine* fl,
string name, AstNode* selectExprp)
const string& name, AstNode* selectExprp)
: AstNode(fl)
, m_name(name) {
addNOp1p(selectExprp); }
@@ -1672,7 +1716,7 @@ private:
string m_name; // Var name
public:
AstUnlinkedRef(FileLine* fl,
AstNode* refp, string name, AstNode* crp)
AstNode* refp, const string& name, AstNode* crp)
: AstNode(fl)
, m_name(name) {
addNOp1p(refp); addNOp2p(crp); }
@@ -1778,7 +1822,7 @@ public:
}}
virtual bool same(AstNode* samep) const {
return (m_packagep==samep->castPackageRef()->m_packagep); }
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_packagep)); }
virtual V3Hash sameHash() const { return V3Hash(m_packagep); }
virtual void dump(ostream& str=cout);
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
@@ -1900,7 +1944,7 @@ public:
}
ASTNODE_NODE_FUNCS(SenItem)
virtual void dump(ostream& str);
virtual V3Hash sameHash() const { return V3Hash(V3Hash(edgeType())); }
virtual V3Hash sameHash() const { return V3Hash(edgeType()); }
virtual bool same(AstNode* samep) const {
return edgeType()==samep->castSenItem()->edgeType(); }
AstEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge
@@ -2023,6 +2067,7 @@ public:
}
ASTNODE_NODE_FUNCS(Assign)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssign(this->fileline(), lhsp, rhsp); }
virtual bool brokeLhsMustBeLvalue() const { return true; }
};
class AstAssignAlias : public AstNodeAssign {
@@ -2033,6 +2078,7 @@ public:
: AstNodeAssign(fileline, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignAlias)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { V3ERROR_NA; return NULL; }
virtual bool brokeLhsMustBeLvalue() const { return false; }
};
class AstAssignDly : public AstNodeAssign {
@@ -2043,6 +2089,7 @@ public:
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignDly(this->fileline(), lhsp, rhsp); }
virtual bool isGateOptimizable() const { return false; }
virtual string verilogKwd() const { return "<="; }
virtual bool brokeLhsMustBeLvalue() const { return true; }
};
class AstAssignW : public AstNodeAssign {
@@ -2052,6 +2099,7 @@ public:
: AstNodeAssign(fileline, lhsp, rhsp) { }
ASTNODE_NODE_FUNCS(AssignW)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignW(this->fileline(), lhsp, rhsp); }
virtual bool brokeLhsMustBeLvalue() const { return true; }
AstAlways* convertToAlways() {
AstNode* lhs1p = lhsp()->unlinkFrBack();
AstNode* rhs1p = rhsp()->unlinkFrBack();
@@ -2071,6 +2119,7 @@ public:
}
ASTNODE_NODE_FUNCS(AssignVarScope)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignVarScope(this->fileline(), lhsp, rhsp); }
virtual bool brokeLhsMustBeLvalue() const { return false; }
};
class AstPull : public AstNode {
@@ -2097,6 +2146,7 @@ public:
: AstNodeAssign(fileline, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignPre)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignPre(this->fileline(), lhsp, rhsp); }
virtual bool brokeLhsMustBeLvalue() const { return true; }
};
class AstAssignPost : public AstNodeAssign {
@@ -2106,6 +2156,7 @@ public:
: AstNodeAssign(fileline, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignPost)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignPost(this->fileline(), lhsp, rhsp); }
virtual bool brokeLhsMustBeLvalue() const { return true; }
};
class AstComment : public AstNodeStmt {
@@ -2642,28 +2693,24 @@ public:
class AstValuePlusArgs : public AstNodeMath {
// Parents: expr
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
private:
string m_text;
public:
AstValuePlusArgs(FileLine* fileline, const string& text, AstNode* exprsp)
: AstNodeMath (fileline), m_text(text) {
setOp1p(exprsp);
AstValuePlusArgs(FileLine* fileline, AstNode* searchp, AstNode* outp)
: AstNodeMath (fileline) {
setOp1p(searchp); setOp2p(outp);
}
ASTNODE_NODE_FUNCS(ValuePlusArgs)
virtual string name() const { return m_text; }
virtual string verilogKwd() const { return "$value$plusargs"; }
virtual string emitVerilog() { return verilogKwd(); }
virtual string emitC() { return "VL_VALUEPLUSARGS_%nq(%lw, %P, NULL)"; }
virtual string emitVerilog() { return "%f$value$plusargs(%l, %k%r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool cleanOut() { return true; }
virtual V3Hash sameHash() const { return V3Hash(text()); }
virtual bool same(AstNode* samep) const {
return text()==samep->castValuePlusArgs()->text(); }
AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output
void exprsp(AstNode* nodep) { setOp1p(nodep); } // op1 = Expressions to output
string text() const { return m_text; } // * = Text to display
void text(const string& text) { m_text=text; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstNode* searchp() const { return op1p(); } // op1 = Search expression
void searchp(AstNode* nodep) { setOp1p(nodep); }
AstNode* outp() const { return op2p(); } // op2 = Expressions to output
void outp(AstNode* nodep) { setOp2p(nodep); }
};
class AstTestPlusArgs : public AstNodeMath {
@@ -4657,6 +4704,7 @@ public:
dtypeSetLogicBool(); }
ASTNODE_NODE_FUNCS(EqWild)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); }
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEqWild/AstEqD
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f==? %r)"; }
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
+1 -1
View File
@@ -296,5 +296,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
if (state.anyFuncInBegin()) {
BeginRelinkVisitor brvisitor (nodep,&state);
}
V3Global::dumpCheckGlobalTree("begin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+18 -5
View File
@@ -62,16 +62,20 @@ public:
if (debug()>=9) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted");
}
if (iter!=s_nodes.end()) s_nodes.erase(iter);
}
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
// GCC 4.4.* compiler warning bug, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39390
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
static void addNewed(const AstNode* nodep) {
// Called by operator new on any node - only if VL_LEAK_CHECKS
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
nodep->v3fatalSrc("Newing AstNode object that is already allocated");
}
if (iter == s_nodes.end()) {
int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2
@@ -94,16 +98,16 @@ public:
NodeMap::iterator iter = s_nodes.find(nodep);
if (iter == s_nodes.end()) {
#ifdef VL_LEAK_CHECKS
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
nodep->v3fatalSrc("AstNode is in tree, but not allocated");
#endif
} else {
if (!(iter->second & FLAG_ALLOCATED)) {
#ifdef VL_LEAK_CHECKS
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
nodep->v3fatalSrc("AstNode is in tree, but not allocated");
#endif
}
if (iter->second & FLAG_IN_TREE) {
nodep->v3fatalSrc("AstNode is already in tree at another location\n");
nodep->v3fatalSrc("AstNode is already in tree at another location");
}
}
int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0);
@@ -236,6 +240,15 @@ private:
nodep->iterateChildrenConst(*this);
BrokenTable::setUnder(nodep,false);
}
virtual void visit(AstNodeAssign* nodep) {
processAndIterate(nodep);
if (v3Global.assertDTypesResolved()
&& nodep->brokeLhsMustBeLvalue()
&& nodep->lhsp()->castNodeVarRef()
&& !nodep->lhsp()->castNodeVarRef()->lvalue()) {
nodep->v3fatalSrc("Assignment LHS is not an lvalue");
}
}
virtual void visit(AstNode* nodep) {
processAndIterate(nodep);
}
+8 -2
View File
@@ -75,7 +75,8 @@ public:
m_numStmts += 1;
}
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="") {
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="",
const string& stmt="") {
m_basename = basename;
m_argsp = argsp;
m_callargsp = callargsp;
@@ -87,9 +88,13 @@ public:
m_tlFuncp->isStatic(false);
m_tlFuncp->slow(true);
m_tlFuncp->argTypes(m_argsp);
if (stmt != "") {
m_tlFuncp->addStmtsp(new AstCStmt(nodep->fileline(), stmt));
}
m_funcp = m_tlFuncp;
m_modp->addStmtp(m_tlFuncp);
}
~V3CCtorsVisitor() {}
};
//######################################################################
@@ -100,7 +105,8 @@ void V3CCtors::cctorsAll() {
// Process each module in turn
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
V3CCtorsVisitor configure_coverage (modp, "_configure_coverage",
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first");
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first",
"if (0 && vlSymsp && first) {} // Prevent unused\n");
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
AstVar* varp = np->castVar();
+3 -3
View File
@@ -174,7 +174,7 @@ private:
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
//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 (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this");
if (neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
} else {
@@ -423,7 +423,7 @@ private:
// Handle any assertions
replaceCaseParallel(nodep, false);
// Replace the CASE... with IF...
if (debug()>=9) grouprootp->dumpTree(cout," _new: ");
if (debug()>=9 && grouprootp) grouprootp->dumpTree(cout," _new: ");
if (grouprootp) nodep->replaceWith(grouprootp);
else nodep->unlinkFrBack();
nodep->deleteTree(); VL_DANGLING(nodep);
@@ -489,7 +489,7 @@ public:
void V3Case::caseAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CaseVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("case.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Case::caseLint(AstNodeCase* nodep) {
UINFO(4,__FUNCTION__<<": "<<endl);
+1 -1
View File
@@ -188,5 +188,5 @@ public:
void V3Cast::castAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CastVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("cast.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+4 -4
View File
@@ -591,14 +591,14 @@ private:
vertexp->dstDomainp(senoutp);
if (debug()>=9) {
UINFO(9,spaces(level)+" Tracedst "<<vertexp);
if (senoutp) V3EmitV::verilogForTree(senoutp, cout); cout<<endl;
if (senoutp) { V3EmitV::verilogForTree(senoutp, cout); cout<<endl; }
}
} else {
vertexp->srcDomainSet(true); // Note it's set - domainp may be null, so can't use that
vertexp->srcDomainp(senoutp);
if (debug()>=9) {
UINFO(9,spaces(level)+" Tracesrc "<<vertexp);
if (senoutp) V3EmitV::verilogForTree(senoutp, cout); cout<<endl;
if (senoutp) { V3EmitV::verilogForTree(senoutp, cout); cout<<endl; }
}
}
}
@@ -629,9 +629,9 @@ private:
}
virtual void visit(AstNodeVarRef* nodep) {
if (m_scopep) {
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block");
AstVarScope* varscp = nodep->varScopep();
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
CdcVarVertex* varvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
// We use weight of one for normal edges,
+5 -5
View File
@@ -111,8 +111,8 @@ private:
AstVarScope* m_vscp; // Original (non-change) variable we're change-detecting
AstVarScope* m_newvscp; // New (change detect) variable we're change-detecting
AstNode* m_varEqnp; // Original var's equation to get var value
AstNode* m_newLvEqnp; // New var's equation to read value
AstNode* m_newRvEqnp; // New var's equation to set value
AstNode* m_newLvEqnp; // New var's equation to read value
AstNode* m_newRvEqnp; // New var's equation to set value
uint32_t m_detects; // # detects created
// CONSTANTS
@@ -253,7 +253,7 @@ private:
AstNode::user1ClearTree();
// Create the change detection function
AstScope* scopep = nodep->scopep();
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
m_statep->m_scopetopp = scopep;
// Create a wrapper change detection function that calls each change detection function
@@ -278,7 +278,7 @@ private:
}
}
virtual void visit(AstNodeMath* nodep) {
// Short-circuit
// Short-circuit
}
//--------------------
// Default: Just iterate
@@ -302,5 +302,5 @@ void V3Changed::changedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ChangedState state;
ChangedVisitor visitor (nodep, &state);
V3Global::dumpCheckGlobalTree("changed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -297,5 +297,5 @@ public:
void V3Clean::cleanAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CleanVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clean.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+5 -4
View File
@@ -559,7 +559,7 @@ class GaterVisitor : public GaterBaseVisitor {
if (!vVxp->inBeginp()) {
// At this point, any variable not linked is an error
// (It should have at least landed under the Head node)
vVxp->nodep()->v3fatalSrc("Variable became stranded in clk gate detection\n");
vVxp->nodep()->v3fatalSrc("Variable became stranded in clk gate detection");
}
if (!lastVxp || vVxp->sortCmp(lastVxp)) {
// Different sources for this new node
@@ -611,7 +611,8 @@ class GaterVisitor : public GaterBaseVisitor {
// Edges from IFs represent a real IF branch in the equation tree
//UINFO(9," ifver "<<(void*)(edgep)<<" cc"<<edgep->dotColor()<<endl);
eqnp = cVxp->nodep()->condp()->cloneTree(true);
if (eqnp && cedgep->ifelseFalse()) {
if (!eqnp) cVxp->nodep()->v3fatalSrc("null condition");
if (cedgep->ifelseFalse()) {
eqnp = new AstNot(eqnp->fileline(),eqnp);
}
// We need to AND this term onto whatever was found below it
@@ -878,7 +879,7 @@ class GaterVisitor : public GaterBaseVisitor {
public:
// CONSTUCTORS
explicit GaterVisitor(AstNode* nodep) {
explicit GaterVisitor(AstNetlist* nodep) {
// AstAlways visitor does the real work, so most zeroing needs to be in clear()
clear();
nodep->accept(*this);
@@ -914,5 +915,5 @@ void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
// While the gater does well at some modules, it seems to slow down many others
UINFO(5,"ClkGater is disabled due to performance issues\n");
//GaterVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clkgater.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("clkgater", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -2
View File
@@ -192,7 +192,7 @@ private:
UINFO(4," TOPSCOPE "<<nodep<<endl);
m_topScopep=nodep;
m_scopep = nodep->scopep();
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
//VV***** We reset all user1p()
AstNode::user1ClearTree();
// Make top functions
@@ -413,5 +413,5 @@ public:
void V3Clock::clockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ClockVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("clock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -2
View File
@@ -239,7 +239,7 @@ private:
V3Hash hashval = it->first;
AstNode* node1p = it->second;
if (!node1p->castCFunc()) continue;
if (hashval.isIllegal()) node1p->v3fatalSrc("Illegal (unhashed) nodes\n");
if (hashval.isIllegal()) node1p->v3fatalSrc("Illegal (unhashed) nodes");
for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) {
AstNode* node2p = eqit->second;
if (!(eqit->first == hashval)) break;
@@ -474,5 +474,5 @@ public:
void V3Combine::combineAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
CombineVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("combine.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -104,7 +104,7 @@ class V3ConfigIgnores {
public:
inline static V3ConfigIgnores& singleton() { return s_singleton; }
void addIgnore(V3ErrorCode code, string wildname, int lineno, bool on) {
void addIgnore(V3ErrorCode code, const string& wildname, int lineno, bool on) {
// Insert
IgnLines* linesp = findWilds(wildname);
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
+98 -15
View File
@@ -305,8 +305,7 @@ private:
return (nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
&& nodep->lsbConst()==0
&& (int)nodep->widthConst()==nodep->fromp()->width()
&& 1);
&& (int)nodep->widthConst()==nodep->fromp()->width());
}
bool operandSelExtend(AstSel* nodep) {
// A pattern created by []'s after offsets have been removed
@@ -342,6 +341,33 @@ private:
replaceWChild(nodep, bip); VL_DANGLING(nodep);
return true;
}
bool operandSelShiftLower(AstSel* nodep) {
// AND({a}, SHIFTR({b}, {c})) is often shorthand in C for Verilog {b}[{c} :+ {a}]
// becomes thought other optimizations
// SEL(SHIFTR({a},{b}),{lsb},{width}) -> SEL({a},{lsb+b},{width})
AstShiftR* shiftp = nodep->fromp()->castShiftR();
if (!(m_doV
&& shiftp
&& shiftp->rhsp()->castConst()
&& nodep->lsbp()->castConst()
&& nodep->widthp()->castConst()
)) return false;
AstNode* ap = shiftp->lhsp();
AstConst* bp = shiftp->rhsp()->castConst();
AstConst* lp = nodep->lsbp()->castConst();
if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative()
|| lp->isWide() || lp->num().isFourState() || lp->num().isNegative()) return false;
int newLsb = lp->toSInt() + bp->toSInt();
if (newLsb + nodep->widthConst() > ap->width()) return false;
//
UINFO(9, "SEL(SHIFTR(a,b),l,w) -> SEL(a,l+b,w)\n");
if (debug()>=9) nodep->dumpTree(cout,"SEL(SH)-in:");
AstSel* newp = new AstSel(nodep->fileline(), ap->unlinkFrBack(), newLsb, nodep->widthConst());
newp->dtypeFrom(nodep);
if (debug()>=9) newp->dumpTree(cout,"SEL(SH)-ou:");
nodep->replaceWith(newp); VL_DANGLING(nodep);
return true;
}
bool operandBiExtendConst(AstNodeBiop* nodep) {
// Loop unrolling favors standalone compares
@@ -555,7 +581,7 @@ private:
// Replace oldp node with a constant set to specified value
UASSERT (oldp, "Null old\n");
if (oldp->castConst() && !oldp->castConst()->num().isFourState()) {
oldp->v3fatalSrc("Already constant??\n");
oldp->v3fatalSrc("Already constant??");
}
AstNode* newp = new AstConst(oldp->fileline(), num);
newp->dtypeFrom(oldp);
@@ -1367,21 +1393,67 @@ private:
}
nodep->deleteTree(); VL_DANGLING(nodep);
}
void replaceSelReplicate(AstSel* nodep) {
// SEL(REPLICATE(a,b),1,bit) => SEL(a,1,bit)
bool operandSelReplicate(AstSel* nodep) {
// SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long as SEL's width <= b's width
AstReplicate* repp = nodep->fromp()->castReplicate();
AstNode* fromp = repp->lhsp()->unlinkFrBack();
AstConst* lsbp = nodep->lsbp()->castConst();
AstNode* widthp = nodep->widthp()->unlinkFrBack();
AstNode* fromp = repp->lhsp();
AstConst* lsbp = nodep->lsbp()->castConst(); if (!lsbp) return false;
AstNode* widthp = nodep->widthp(); if (!widthp->castConst()) return false;
if (!fromp->width()) nodep->v3fatalSrc("Not widthed");
if ((lsbp->toUInt() / fromp->width())
!= ((lsbp->toUInt()+nodep->width()-1) / fromp->width())) return false;
//
fromp->unlinkFrBack();
widthp->unlinkFrBack();
AstSel* newp = new AstSel(nodep->fileline(),
fromp,
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
widthp);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
return true;
}
bool operandRepRep(AstReplicate* nodep) {
// REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2))
AstReplicate* rep2p = nodep->lhsp()->castReplicate();
AstNode* from2p = rep2p->lhsp();
AstConst* cnt1p = nodep->rhsp()->castConst(); if (!cnt1p) return false;
AstConst* cnt2p = rep2p->rhsp()->castConst(); if (!cnt2p) return false;
//
from2p->unlinkFrBack();
cnt1p->unlinkFrBack();
cnt2p->unlinkFrBack();
AstReplicate* newp = new AstReplicate(nodep->fileline(),
from2p, cnt1p->toUInt()*cnt2p->toUInt());
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
return true;
}
bool operandConcatSame(AstConcat* nodep) {
// CONCAT(fromp,fromp) -> REPLICATE(fromp,1+1)
// CONCAT(REP(fromp,cnt1),fromp) -> REPLICATE(fromp,cnt1+1)
// CONCAT(fromp,REP(fromp,cnt1)) -> REPLICATE(fromp,1+cnt1)
// CONCAT(REP(fromp,cnt1),REP(fromp,cnt2)) -> REPLICATE(fromp,cnt1+cnt2)
AstNode* from1p = nodep->lhsp(); uint32_t cnt1 = 1;
AstNode* from2p = nodep->rhsp(); uint32_t cnt2 = 1;
if (from1p->castReplicate()) {
AstConst* cnt1p = from1p->castReplicate()->rhsp()->castConst(); if (!cnt1p) return false;
from1p = from1p->castReplicate()->lhsp();
cnt1 = cnt1p->toUInt();
}
if (from2p->castReplicate()) {
AstConst* cnt2p = from2p->castReplicate()->rhsp()->castConst(); if (!cnt2p) return false;
from2p = from2p->castReplicate()->lhsp();
cnt2 = cnt2p->toUInt();
}
if (!operandsSame(from1p,from2p)) return false;
//
from1p->unlinkFrBack();
AstReplicate* newp = new AstReplicate(nodep->fileline(), from1p, cnt1+cnt2);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
return true;
}
void replaceSelIntoBiop(AstSel* nodep) {
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
@@ -1491,6 +1563,14 @@ private:
did=true;
}
}
else if (m_params && valuep->castInitArray() && nodep->backp()->castPin()) {
// Allow parameters to pass arrays
// Earlier recursion of InitArray made sure each array value is constant
// This exception is fairly fragile, i.e. doesn't support arrays of arrays or other stuff
AstNode* newp = valuep->cloneTree(false);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
did = true;
}
}
}
if (!did && m_required) {
@@ -2233,6 +2313,8 @@ private:
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())");
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
TREEOPV("AstReplicateN{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
TREEOPV("AstReplicate{$lhsp.castReplicate, operandRepRep(nodep)}", "DONE"); // {2{3{lhs}}}->{6{lhs}}
TREEOPV("AstConcat{operandConcatSame(nodep)}", "DONE"); // {a,a}->{2{a}}, {a,2{a}}->{3{a}, etc
// Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy.
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
@@ -2244,9 +2326,10 @@ private:
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
TREEOPV("AstSel{$fromp.castShiftR, operandSelShiftLower(nodep)}", "DONE");
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.castConst, operandSelReplicate(nodep) }", "DONE");
// V3Tristate requires selects below BufIf1.
// Also do additional operators that are bit-independent, but only definite
// win if bit select is a constant (otherwise we may need to compute bit index several times)
@@ -2400,14 +2483,14 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Const::constifyCpp(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_CPP);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const_cpp.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("const_cpp", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
AstNode* V3Const::constifyEdit(AstNode* nodep) {
@@ -2423,7 +2506,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Const::constifyAll(AstNetlist* nodep) {
@@ -2431,7 +2514,7 @@ void V3Const::constifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
(void)visitor.mainAcceptEdit(nodep);
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
+1 -1
View File
@@ -395,5 +395,5 @@ public:
void V3Coverage::coverage(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
CoverageVisitor visitor (rootp);
V3Global::dumpCheckGlobalTree("coverage.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -135,5 +135,5 @@ public:
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
CoverageJoinVisitor visitor (rootp);
V3Global::dumpCheckGlobalTree("coveragejoin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+7 -7
View File
@@ -338,8 +338,8 @@ private:
if (vscp->user1() == 0) {
UINFO(4," Dead "<<vscp<<endl);
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
AstNodeAssign* assp = it->second;
for (AssignMap::iterator itr = eqrange.first; itr != eqrange.second; ++itr) {
AstNodeAssign* assp = itr->second;
UINFO(4," Dead assign "<<assp<<endl);
assp->dtypep()->user1Inc(-1);
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
@@ -422,29 +422,29 @@ public:
void V3Dead::deadifyModules(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, false, false, false);
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("deadModules", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true, false, false);
V3Global::dumpCheckGlobalTree("deadDtypes.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("deadDtypes", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, false, true, true, false);
V3Global::dumpCheckGlobalTree("deadDtypesScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true, false, true);
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("deadAll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DeadVisitor visitor (nodep, true, true, true, true);
V3Global::dumpCheckGlobalTree("deadAllScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+6 -6
View File
@@ -158,7 +158,7 @@ private:
if (oldactivep->sensesp() != m_activep->sensesp()) {
if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN)
&& !varrefp->varp()->user2()) {
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks: "<<varrefp->varp()->prettyName()<<endl
varrefp->varp()->v3warn(MULTIDRIVEN,"Signal has multiple driving blocks with different clocking: "<<varrefp->varp()->prettyName()<<endl
<<varrefp->warnMore()<<"... Location of first driving block"<<endl
<<oldactivep->warnMore()<<"... Location of other driving block");
varrefp->varp()->user2(true);
@@ -207,8 +207,8 @@ private:
dimvalp.push_front(valp);
}
AstVarRef* varrefp = dimselp->castVarRef();
if (!varrefp) nodep->v3fatalSrc("No var underneath arraysels\n");
if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
if (!varrefp) nodep->v3fatalSrc("No var underneath arraysels");
if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
varrefp->unlinkFrBack();
AstVar* oldvarp = varrefp->varp();
int modVecNum = oldvarp->user4(); oldvarp->user4(modVecNum+1);
@@ -393,7 +393,7 @@ private:
if (!m_activep) nodep->v3fatalSrc("<= not under sensitivity block");
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
AstVarScope* oldvscp = nodep->varScopep();
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
AstVarScope* dlyvscp = oldvscp->user1p()->castVarScope();
if (dlyvscp) { // Multiple use of delayed variable
AstActive* oldactivep = dlyvscp->user2p()->castActive();
@@ -433,7 +433,7 @@ private:
}
virtual void visit(AstNodeFor* nodep) {
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin");
}
virtual void visit(AstWhile* nodep) {
bool oldloop = m_inLoop;
@@ -471,5 +471,5 @@ public:
void V3Delayed::delayedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DelayedVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("delayed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("delayed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -175,5 +175,5 @@ public:
void V3Depth::depthAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DepthVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("depth.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+1 -1
View File
@@ -140,5 +140,5 @@ public:
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DepthBlockVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("deepblock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+4 -3
View File
@@ -138,8 +138,9 @@ private:
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = stmtp->castVar()) {
if (portp->isIO() && !portp->isFuncReturn()) {
argsp = argsp->addNextNull(new AstVarRef(portp->fileline(), portp,
portp->isOutput()));
AstNode* newp = new AstVarRef(portp->fileline(), portp, portp->isOutput());
if (argsp) argsp = argsp->addNextNull(newp);
else argsp = newp;
}
}
}
@@ -262,5 +263,5 @@ public:
void V3Descope::descopeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
DescopeVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("descope.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+159 -174
View File
@@ -36,6 +36,8 @@
#define VL_VALUE_STRING_MAX_WIDTH 8192 // We use a static char array in VL_VALUE_STRING
#define EMITC_NUM_CONSTW 8 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_8X is last)
//######################################################################
// Emit statements and math operators
@@ -69,7 +71,7 @@ public:
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);
const string& vfmt, char fmtLetter);
void emitVarDecl(AstVar* nodep, const string& prefixIfImp);
typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_PAR, EVL_ALL} EisWhich;
@@ -217,7 +219,7 @@ public:
}
virtual void visit(AstNodeCase* nodep) {
// In V3Case...
nodep->v3fatalSrc("Case statements should have been reduced out\n");
nodep->v3fatalSrc("Case statements should have been reduced out");
}
virtual void visit(AstComment* nodep) {
putsDecoration((string)"// "+nodep->name()+" at "+nodep->fileline()->ascii()+"\n");
@@ -277,54 +279,15 @@ public:
displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true);
}
virtual void visit(AstValuePlusArgs* nodep) {
string prefix;
char format = '?';
bool pct=false;
int got=0;
string txt = nodep->text();
for (string::const_iterator it=txt.begin(); it!=txt.end(); ++it) {
char ch = *it;
if (pct) {
pct = false;
switch (tolower(ch)) {
case '%':
prefix += ch;
break;
case 'd': // FALLTHRU
case 'o': // FALLTHRU
case 'h': // FALLTHRU
case 'x': // FALLTHRU
case 'b': // FALLTHRU
case 'v': // FALLTHRU
case 's':
got++; format = tolower(ch);
break;
case 'e': // FALLTHRU
case 'f': // FALLTHRU
case 'g':
got++; format = tolower(ch);
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
break;
default:
got++;
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
break;
}
}
else if (ch == '%') pct = true;
else prefix += ch;
}
if (got!=1) nodep->v3error("Missing or extra $value$plusargs format qualifier: '"<<nodep->text()<<"'"<<endl);
puts("VL_VALUEPLUSARGS_I");
emitIQW(nodep->exprsp());
puts("VL_VALUEPLUSARGS_IN");
emitIQW(nodep->outp());
puts("(");
puts(cvtToStr(nodep->exprsp()->widthMin())); // Note argument width, not node width (which is always 32)
putbs(",");
putsQuoted(prefix);
putbs(",");
puts("'"); puts(cvtToStr(format)); puts("'");
puts(cvtToStr(nodep->outp()->widthMin()));
puts(",");
nodep->exprsp()->iterateAndNext(*this);
emitCvtPackStr(nodep->searchp());
puts(",");
putbs("");
nodep->outp()->iterateAndNext(*this);
puts(")");
}
virtual void visit(AstTestPlusArgs* nodep) {
@@ -548,6 +511,30 @@ public:
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPow* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowSS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowSU* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstPowUS* nodep) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Unsupported: Power of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h");
}
visit(nodep->castNodeBiop());
}
virtual void visit(AstCCast* nodep) {
// Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) {
@@ -618,33 +605,90 @@ public:
puts(nodep->hiername());
puts(nodep->varp()->name());
}
void emitCvtPackStr(AstNode* nodep) {
if (AstConst* constp = nodep->castConst()) {
putbs("std::string(");
putsQuoted(constp->num().toString());
puts(")");
} else {
putbs("VL_CVT_PACK_STR_N");
emitIQW(nodep);
puts("(");
if (nodep->isWide()) {
puts(cvtToStr(nodep->widthWords())); // Note argument width, not node width (which is always 32)
puts(",");
}
nodep->iterateAndNext(*this);
puts(")");
}
}
void emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
// Put out constant set to the specified variable, or given variable in a string
if (nodep->num().isFourState()) {
nodep->v3error("Unsupported: 4-state numbers in this context");
} else if (nodep->num().isString()) {
putbs("string(");
putbs("std::string(");
putsQuoted(nodep->num().toString());
puts(")");
} else if (nodep->isWide()) {
putbs("VL_CONST_W_");
puts(cvtToStr(VL_WORDS_I(nodep->num().widthMin())));
puts("X(");
puts(cvtToStr(nodep->widthMin()));
puts(",");
if (!assigntop) {
puts(assignString);
} else if (assigntop->castVarRef()) {
puts(assigntop->hiername());
puts(assigntop->varp()->name());
} else {
assigntop->iterateAndNext(*this);
int upWidth = nodep->num().widthMin();
int chunks = 0;
if (upWidth > EMITC_NUM_CONSTW*VL_WORDSIZE) {
// Output e.g. 8 words in groups of e.g. 8
chunks = (upWidth-1) / (EMITC_NUM_CONSTW*VL_WORDSIZE);
upWidth %= (EMITC_NUM_CONSTW*VL_WORDSIZE);
if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW*VL_WORDSIZE);
}
for (int word=VL_WORDS_I(nodep->num().widthMin())-1; word>0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
{ // Upper e.g. 8 words
if (chunks) {
putbs("VL_CONSTHI_W_");
puts(cvtToStr(VL_WORDS_I(upWidth)));
puts("X(");
puts(cvtToStr(nodep->widthMin()));
puts(",");
puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE));
} else {
putbs("VL_CONST_W_");
puts(cvtToStr(VL_WORDS_I(upWidth)));
puts("X(");
puts(cvtToStr(nodep->widthMin()));
}
puts(",");
if (!assigntop) {
puts(assignString);
} else if (assigntop->castVarRef()) {
puts(assigntop->hiername());
puts(assigntop->varp()->name());
} else {
assigntop->iterateAndNext(*this);
}
for (int word=VL_WORDS_I(upWidth)-1; word>=0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word+chunks*EMITC_NUM_CONSTW)));
}
puts(")");
}
for (chunks--; chunks >= 0; chunks--) {
puts(";\n");
putbs("VL_CONSTLO_W_");
puts(cvtToStr(EMITC_NUM_CONSTW));
puts("X(");
puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE));
puts(",");
if (!assigntop) {
puts(assignString);
} else if (assigntop->castVarRef()) {
puts(assigntop->hiername());
puts(assigntop->varp()->name());
} else {
assigntop->iterateAndNext(*this);
}
for (int word=EMITC_NUM_CONSTW-1; word>=0; word--) {
// Only 32 bits - llx + long long here just to appease CPP format warning
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word+chunks*EMITC_NUM_CONSTW)));
}
puts(")");
}
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
} else if (nodep->isDouble()) {
if (int(nodep->num().toDouble()) == nodep->num().toDouble()
&& nodep->num().toDouble() < 1000
@@ -780,12 +824,7 @@ class EmitCImp : EmitCStmts {
// We should move them to a different stage.
string filename = VL_DEV_NULL;
newCFile(filename, slow, source);
ofp = new V3OutSpFile (filename);
}
else if (optSystemPerl()) {
string filename = filenameNoExt+".sp";
newCFile(filename, slow, source);
ofp = new V3OutSpFile (filename);
ofp = new V3OutCFile (filename);
}
else if (optSystemC()) {
string filename = filenameNoExt+(source?".cpp":".h");
@@ -845,16 +884,13 @@ class EmitCImp : EmitCStmts {
if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n");
if (nodep->initsp()) putsDecoration("// Variables\n");
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
if (AstVar* varp=subnodep->castVar()) {
if (varp->isFuncReturn()) emitVarDecl(varp, "");
}
}
emitVarList(nodep->initsp(), EVL_ALL, "");
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
emitVarList(nodep->stmtsp(), EVL_ALL, "");
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
nodep->initsp()->iterateAndNext(*this);
@@ -962,7 +998,6 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->isIO()) {
if (nodep->isSc()) {
m_ctorVarsVec.push_back(nodep);
ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment
if (nodep->attrScClocked() && nodep->isInput()) {
puts("sc_in_clk\t");
} else {
@@ -983,8 +1018,6 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
emitDeclArrayBrackets(nodep);
puts(";\n");
} else { // C++ signals
ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(),
nodep->dtypeSkipRefp()->widthTotalBytes());
if (nodep->isInout()) puts("VL_INOUT");
else if (nodep->isInput()) puts("VL_IN");
else if (nodep->isOutput()) puts("VL_OUT");
@@ -1011,8 +1044,6 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
} else {
// Arrays need a small alignment, but may need different padding after.
// For example three VL_SIG8's needs alignment 1 but size 3.
ofp()->putAlign(nodep->isStatic(), nodep->dtypeSkipRefp()->widthAlignBytes(),
nodep->dtypeSkipRefp()->widthTotalBytes());
if (nodep->isStatic() && prefixIfImp=="") puts("static ");
if (nodep->isStatic()) puts("VL_ST_"); else puts("VL_");
if (nodep->widthMin() <= 8) {
@@ -1235,7 +1266,6 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
if (dispp) {}
puts("VL_SFORMATF_NX(");
} else {
isStmt = true;
nodep->v3fatalSrc("Unknown displayEmit node type");
}
ofp()->putsQuoted(emitDispState.m_format);
@@ -1267,7 +1297,7 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
}
void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
string vfmt, char fmtLetter) {
const string& vfmt, char fmtLetter) {
// Print display argument, edits elistp
AstNode* argp = *elistp;
if (!argp) {
@@ -1482,9 +1512,7 @@ void EmitCImp::emitCoverageDecl(AstNodeModule* modp) {
void EmitCImp::emitCtorImp(AstNodeModule* modp) {
puts("\n");
if (optSystemPerl() && modp->isTop()) {
puts("SP_CTOR_IMP("+modClassName(modp)+")");
} else if (optSystemC() && modp->isTop()) {
if (optSystemC() && modp->isTop()) {
puts("VL_SC_CTOR_IMP("+modClassName(modp)+")");
} else {
puts("VL_CTOR_IMP("+modClassName(modp)+")");
@@ -1502,7 +1530,6 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) {
putsDecoration("// Reset structure values\n");
puts("_ctor_var_reset();\n");
emitTextSection(AstType::atScCtor);
if (optSystemPerl()) puts("SP_AUTO_CTOR;\n");
puts("}\n");
}
@@ -1521,9 +1548,7 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
if (v3Global.opt.coverage() ) {
puts("\n// Coverage\n");
// Rather than putting out VL_COVER_INSERT calls directly, we do it via this function
// This gets around gcc slowness constructing all of the template arguments
// SystemPerl 1.301 is much faster, but it's nice to remain back
// compatible, and have a common wrapper.
// This gets around gcc slowness constructing all of the template arguments.
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
puts( "const char* hierp, const char* pagep, const char* commentp) {\n");
puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant
@@ -1533,8 +1558,8 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
puts( " \"filename\",filenamep,");
puts( " \"lineno\",lineno,");
puts( " \"column\",column,\n");
//puts( "\"hier\",string(__VlSymsp->name())+hierp,"); // Need to move hier into scopes and back out if do this
puts( "\"hier\",string(name())+hierp,");
//puts( "\"hier\",std::string(__VlSymsp->name())+hierp,"); // Need to move hier into scopes and back out if do this
puts( "\"hier\",std::string(name())+hierp,");
puts( " \"page\",pagep,");
puts( " \"comment\",commentp);\n");
puts("}\n");
@@ -1703,7 +1728,7 @@ void EmitCImp::emitSensitives() {
void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts("\nvoid "+modClassName(modp)+"::eval() {\n");
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symTopAssign()+"\n");
putsDecoration("// Initialize\n");
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);\n");
@@ -1713,14 +1738,16 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
putsDecoration("// Evaluate till stable\n");
puts("VL_DEBUG_IF(VL_PRINTF(\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
puts("int __VclockLoop = 0;\n");
puts("QData __Vchange=1;\n");
puts("QData __Vchange = 1;\n");
puts("while (VL_LIKELY(__Vchange)) {\n");
puts( "VL_DEBUG_IF(VL_PRINTF(\" Clock loop\\n\"););\n");
puts( "vlSymsp->__Vm_activity = true;\n");
if (v3Global.opt.trace()) {
puts("vlSymsp->__Vm_activity = true;\n");
}
puts( "_eval(vlSymsp);\n");
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+")) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts("}\n");
puts("}\n");
splitSizeInc(10);
@@ -1729,15 +1756,17 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
puts("vlSymsp->__Vm_didInit = true;\n");
puts("_eval_initial(vlSymsp);\n");
puts( "vlSymsp->__Vm_activity = true;\n");
if (v3Global.opt.trace()) {
puts("vlSymsp->__Vm_activity = true;\n");
}
puts( "int __VclockLoop = 0;\n");
puts( "QData __Vchange=1;\n");
puts( "QData __Vchange = 1;\n");
puts( "while (VL_LIKELY(__Vchange)) {\n");
puts( "_eval_settle(vlSymsp);\n");
puts( "_eval(vlSymsp);\n");
puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+")) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "}\n");
puts("}\n");
splitSizeInc(10);
@@ -1787,7 +1816,6 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
}
}
}
ofp()->putAlign(isstatic, 4, 0, prefixIfImp);
}
}
@@ -1815,7 +1843,7 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
if (!funcp->dpiImport()) { // DPI is prototyped in __Dpi.h
ofp()->putsPrivate(funcp->declPrivate());
if (funcp->isStatic()) puts("static ");
puts(funcp->rtnTypeVoid()); puts("\t");
puts(funcp->rtnTypeVoid()); puts(" ");
puts(funcp->name()); puts("("+cFuncArgs(funcp)+");\n");
}
}
@@ -1823,11 +1851,9 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
void EmitCImp::emitInt(AstNodeModule* modp) {
// Always have this first; gcc has short circuiting if #ifdef is first in a file
if (!optSystemPerl()) { // else done for us automatically
puts("#ifndef _"+modClassName(modp)+"_H_\n");
puts("#define _"+modClassName(modp)+"_H_\n");
puts("\n");
}
puts("#ifndef _"+modClassName(modp)+"_H_\n");
puts("#define _"+modClassName(modp)+"_H_\n");
puts("\n");
ofp()->putsIntTopInclude();
if (v3Global.needHeavy()) {
@@ -1849,8 +1875,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
// do this before including our main .h file so that any references to
// types defined in svdpi.h are available
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
puts("\n");
}
puts("\n");
// Declare foreign instances up front to make C++ happy
puts("class "+symClassName()+";\n");
@@ -1871,19 +1897,18 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
} else {
puts("VL_MODULE("+modClassName(modp)+") {\n");
}
if (optSystemPerl()) puts("/*AUTOATTR(verilated)*/\n\n");
ofp()->resetPrivate();
ofp()->putsPrivate(false); // public:
// Instantiated modules
if (optSystemPerl()) {
puts("/*AUTOSUBCELLS*/\n\n");
} else {
putsDecoration("// CELLS\n");
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
{ // Instantiated cells
bool did = false;
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstCell* cellp=nodep->castCell()) {
if (!did++) {
putsDecoration("// CELLS\n");
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
}
ofp()->putsCellDecl(modClassName(cellp->modp()), cellp->name());
}
}
@@ -1907,18 +1932,14 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
puts("\n// INTERNAL VARIABLES\n");
if (modp->isTop()) puts("// Internals; generally not touched by application code\n");
ofp()->putsPrivate(!modp->isTop()); // private: unless top
ofp()->putAlign(V3OutFile::AL_AUTO, 8);
puts(symClassName()+"*\t__VlSymsp;\t\t// Symbol table\n");
puts(symClassName()+"* __VlSymsp; // Symbol table\n");
ofp()->putsPrivate(false); // public:
if (modp->isTop()) {
if (v3Global.opt.inhibitSim()) {
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_inhibitSim;\t///< Set true to disable evaluation of module\n");
puts("bool __Vm_inhibitSim; ///< Set true to disable evaluation of module\n");
}
}
ofp()->putAlign(V3OutFile::AL_AUTO, 8);
emitCoverageDecl(modp); // may flip public/private
ofp()->putAlign(V3OutFile::AL_AUTO, 8);
puts("\n// PARAMETERS\n");
if (modp->isTop()) puts("// Parameters marked /*verilator public*/ for use by application code\n");
@@ -1950,8 +1971,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
ofp()->resetPrivate();
// We don't need a private copy constructor, as VerilatedModule has one for us.
ofp()->putsPrivate(true);
puts(modClassName(modp)+"& operator= (const "+modClassName(modp)+"&);\t///< Copying not allowed\n");
puts(modClassName(modp)+"(const "+modClassName(modp)+"&);\t///< Copying not allowed\n");
puts(modClassName(modp)+"& operator= (const "+modClassName(modp)+"&); ///< Copying not allowed\n");
puts(modClassName(modp)+"(const "+modClassName(modp)+"&); ///< Copying not allowed\n");
ofp()->putsPrivate(false); // public:
if (optSystemC() && modp->isTop()) {
@@ -1970,7 +1991,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (modp->isTop()) puts("/// Destroy the model; called (often implicitly) by application code\n");
puts("~"+modClassName(modp)+"();\n");
}
if (v3Global.opt.trace() && !optSystemPerl()) {
if (v3Global.opt.trace()) {
if (modp->isTop()) puts("/// Trace signals in the model; called by application code\n");
puts("void trace (VerilatedVcdC* tfp, int levels, int options=0);\n");
if (modp->isTop() && optSystemC()) {
@@ -1979,8 +2000,6 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
}
}
puts("\n// USER METHODS\n");
if (optSystemPerl()) puts("/*AUTOMETHODS*/\n");
emitTextSection(AstType::atScInt);
puts("\n// API METHODS\n");
@@ -1992,7 +2011,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
if (!optSystemC()) puts("/// Simulation complete, run final blocks. Application must call on completion.\n");
puts("void final();\n");
if (v3Global.opt.inhibitSim()) {
puts("void inhibitSim(bool flag) { __Vm_inhibitSim=flag; }\t///< Set true to disable evaluation of module\n");
puts("void inhibitSim(bool flag) { __Vm_inhibitSim=flag; } ///< Set true to disable evaluation of module\n");
}
}
@@ -2007,7 +2026,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
emitIntFuncDecls(modp);
if (!optSystemPerl() && v3Global.opt.trace()) {
if (v3Global.opt.trace()) {
ofp()->putsPrivate(false); // public:
puts("static void traceInit ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
puts("static void traceFull ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
@@ -2025,24 +2044,18 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
// Save/restore
if (v3Global.opt.savable() && modp->isTop()) {
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vserialize(os); return os;}\n");
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vdeserialize(os); return os;}\n");
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) { rhs.__Vserialize(os); return os; }\n");
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) { rhs.__Vdeserialize(os); return os; }\n");
puts("\n");
}
// finish up h-file
if (!optSystemPerl()) {
puts("#endif /*guard*/\n");
}
puts("#endif // guard\n");
}
//----------------------------------------------------------------------
void EmitCImp::emitImp(AstNodeModule* modp) {
if (optSystemPerl()) {
puts("//############################################################\n");
puts("#sp implementation\n");
}
ofp()->printf("#include \"%-20s // For This\n",
(modClassName(modp)+".h\"").c_str());
@@ -2053,11 +2066,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
puts("\n");
puts("#include \"verilated_dpi.h\"\n");
}
if (optSystemPerl() && (splitFilenum() || !m_fast)) {
puts("\n");
puts("SP_MODULE_CONTINUED("+modClassName(modp)+");\n");
}
puts("\n");
emitTextSection(AstType::atScImpHdr);
@@ -2090,13 +2099,6 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
}
}
if (m_fast && splitFilenum()==0) {
if (v3Global.opt.trace() && optSystemPerl() && m_modp->isTop()) {
puts("\n");
puts("\n/*AUTOTRACE(__MODULE__,recurse,activity,exists)*/\n\n");
}
}
// Blocks
puts("\n//--------------------\n");
puts("// Internal Methods\n");
@@ -2114,15 +2116,7 @@ void EmitCImp::main(AstNodeModule* modp, bool slow, bool fast) {
UINFO(0," Emitting "<<modClassName(modp)<<endl);
}
if (optSystemPerl()) {
m_ofp = newOutCFile(modp, !m_fast, true);
if (m_fast) {
puts("#sp interface\n");
emitInt (modp);
}
}
else if (optSystemC()) {
if (optSystemC()) {
if (m_fast) {
m_ofp = newOutCFile (modp, !m_fast, false/*source*/);
emitInt (modp);
@@ -2187,11 +2181,7 @@ class EmitCTrace : EmitCStmts {
void emitTraceHeader() {
// Includes
if (optSystemPerl()) {
puts("#include \"SpTraceVcd.h\"\n");
} else {
puts("#include \"verilated_vcd_c.h\"\n");
}
puts("#include \"verilated_vcd_c.h\"\n");
puts("#include \""+ symClassName() +".h\"\n");
puts("\n");
}
@@ -2200,11 +2190,7 @@ class EmitCTrace : EmitCStmts {
puts("\n//======================\n\n");
puts("void "+topClassName()+"::trace (");
if (optSystemPerl()) {
puts("SpTraceFile* tfp, int, int) {\n");
} else {
puts("VerilatedVcdC* tfp, int, int) {\n");
}
puts("VerilatedVcdC* tfp, int, int) {\n");
puts( "tfp->spTrace()->addCallback ("
"&"+topClassName()+"::traceInit"
+", &"+topClassName()+"::traceFull"
@@ -2216,12 +2202,12 @@ class EmitCTrace : EmitCStmts {
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
putsDecoration("// Callback from vcd->open()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
puts("vcdp->scopeEscape(' ');\n");
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
puts("vcdp->scopeEscape('.');\n"); // Restore so SystemPerl traced files won't break
puts("vcdp->scopeEscape('.');\n"); // Restore so later traced files won't break
puts("}\n");
splitSizeInc(10);
@@ -2229,7 +2215,7 @@ class EmitCTrace : EmitCStmts {
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
putsDecoration("// Callback from vcd->dump()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("t->traceFullThis (vlSymsp, vcdp, code);\n");
puts("}\n");
splitSizeInc(10);
@@ -2244,7 +2230,7 @@ class EmitCTrace : EmitCStmts {
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
putsDecoration("// Callback from vcd->dump()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("if (vlSymsp->getClearActivity()) {\n");
puts("t->traceChgThis (vlSymsp, vcdp, code);\n");
puts("}\n");
@@ -2388,7 +2374,7 @@ class EmitCTrace : EmitCStmts {
puts("int c=code;\n");
puts("if (0 && vcdp && c) {} // Prevent unused\n");
if (nodep->funcType() == AstCFuncType::TRACE_INIT) {
puts("vcdp->module(vlSymsp->name()); // Setup signal names\n");
puts("vcdp->module(vlSymsp->name()); // Setup signal names\n");
} else if (nodep->funcType() == AstCFuncType::TRACE_INIT_SUB) {
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL) {
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL_SUB) {
@@ -2399,7 +2385,6 @@ class EmitCTrace : EmitCStmts {
if (nodep->initsp()) putsDecoration("// Variables\n");
emitVarList(nodep->initsp(), EVL_ALL, "");
nodep->initsp()->iterateAndNext(*this);
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
putsDecoration("// Body\n");
puts("{\n");
-1
View File
@@ -46,7 +46,6 @@ public:
void putsDecoration(const string& str) { if (v3Global.opt.decoration()) puts(str); }
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
bool optSystemC() { return v3Global.opt.systemC(); }
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
static string symTopAssign() { return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
+2 -40
View File
@@ -32,30 +32,15 @@
#include "V3EmitCBase.h"
#include "V3Stats.h"
#define EMITCINLINES_NUM_CONSTW 10 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_9X is last)
//######################################################################
class EmitCInlines : EmitCBaseVisitor {
// STATE
vector<V3Double0> m_wordWidths; // What sizes are used?
// METHODS
void emitInt();
// VISITORS
virtual void visit(AstVar* nodep) {
// All wide constants load into variables, so we can just hunt for them
nodep->iterateChildren(*this);
int words = nodep->widthWords();
if (words >= EMITCINLINES_NUM_CONSTW ) {
if (int(m_wordWidths.size()) <= words) {
m_wordWidths.resize(words+5);
}
++ m_wordWidths.at(words);
v3Global.needHInlines(true);
}
}
virtual void visit(AstBasicDType* nodep) {
if (nodep->keyword() == AstBasicDTypeKwd::STRING) {
v3Global.needHeavy(true); // #include <string> via verilated_heavy.h when we create symbol file
@@ -94,33 +79,10 @@ void EmitCInlines::emitInt() {
puts("\n//======================\n\n");
for (unsigned words=0; words<m_wordWidths.size(); words++) {
if (m_wordWidths.at(words)) {
puts("#ifndef VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
puts("# define VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
puts("static inline WDataOutP VL_CONST_W_"+cvtToStr(words)+"X(int obits, WDataOutP o\n");
puts("\t");
for (int i=words-1; i>=0; --i) {
puts(",IData d"+cvtToStr(i));
if (i && (i % 8 == 0)) puts("\n\t");
}
puts(") {\n");
puts(" ");
for (int i=words-1; i>=0; --i) {
puts(" o["+cvtToStr(i)+"]=d"+cvtToStr(i)+";");
if (i && (i % 8 == 0)) puts("\n ");
}
puts("\n");
puts(" for(int i="+cvtToStr(words)+";i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0;\n");
puts(" return o;\n");
puts("}\n");
puts("#endif\n");
puts("\n");
}
}
// Placeholder - v3Global.needHInlines(true) currently not used
puts("//======================\n\n");
puts("#endif /*guard*/\n");
puts("#endif // guard\n");
}
//######################################################################
+36 -28
View File
@@ -112,8 +112,8 @@ class EmitCSyms : EmitCBaseVisitor {
// We didn'e have all m_scopes loaded when we encountered variables, so expand them now
// It would be less code if each module inserted its own variables.
// Someday. For now public isn't common.
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* smodp = it->second;
for (vector<ScopeModPair>::iterator itsc = m_scopes.begin(); itsc != m_scopes.end(); ++itsc) {
AstScope* scopep = itsc->first; AstNodeModule* smodp = itsc->second;
for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
AstNodeModule* modp = it->first;
AstVar* varp = it->second;
@@ -124,10 +124,10 @@ class EmitCSyms : EmitCBaseVisitor {
string scpName;
string varBase;
if (whole.substr(0,10) == "__DOT__TOP") whole.replace(0,10,"");
string::size_type pos = whole.rfind("__DOT__");
if (pos != string::npos) {
scpName = whole.substr(0,pos);
varBase = whole.substr(pos+strlen("__DOT__"));
string::size_type dpos = whole.rfind("__DOT__");
if (dpos != string::npos) {
scpName = whole.substr(0,dpos);
varBase = whole.substr(dpos+strlen("__DOT__"));
} else {
varBase = whole;
}
@@ -238,7 +238,6 @@ class EmitCSyms : EmitCBaseVisitor {
virtual void visit(AstConst*) {}
// Default
virtual void visit(AstNode* nodep) {
nameCheck(nodep);
nodep->iterateChildren(*this);
}
//---------------------------------------
@@ -303,14 +302,12 @@ void EmitCSyms::emitSymHdr() {
ofp()->putsPrivate(false); // public:
puts("\n// LOCAL STATE\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(vluint64_t));
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_didInit;\n");
if (v3Global.opt.trace()) {
puts("bool __Vm_activity; ///< Used by trace routines to determine change occurred\n");
}
puts("bool __Vm_didInit;\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(vluint64_t));
puts("\n// SUBCELL STATE\n");
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
@@ -324,15 +321,17 @@ void EmitCSyms::emitSymHdr() {
}
}
puts("\n// COVERAGE\n");
if (m_coverBins) {
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint32_t));
puts("uint32_t\t__Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
puts("\n// COVERAGE\n");
puts("uint32_t __Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
}
puts("\n// SCOPE NAMES\n");
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
puts("VerilatedScope __Vscope_"+it->second.m_symName+";\n");
{ // Scope names
bool did = false;
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
if (!did++) puts("\n// SCOPE NAMES\n");
puts("VerilatedScope __Vscope_"+it->second.m_symName+";\n");
}
}
puts("\n// CREATORS\n");
@@ -341,7 +340,9 @@ void EmitCSyms::emitSymHdr() {
puts("\n// METHODS\n");
puts("inline const char* name() { return __Vm_namep; }\n");
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
if (v3Global.opt.trace()) {
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r; }\n");
}
if (v3Global.opt.savable() ) {
puts("void __Vserialize(VerilatedSerialize& os);\n");
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
@@ -349,7 +350,7 @@ void EmitCSyms::emitSymHdr() {
puts("\n");
puts("} VL_ATTR_ALIGNED(64);\n");
puts("\n");
puts("#endif /*guard*/\n");
puts("#endif // guard\n");
}
void EmitCSyms::emitSymImp() {
@@ -375,7 +376,9 @@ void EmitCSyms::emitSymImp() {
puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n");
puts("\t// Setup locals\n");
puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
puts("\t, __Vm_activity(false)\n");
if (v3Global.opt.trace()) {
puts("\t, __Vm_activity(false)\n");
}
puts("\t, __Vm_didInit(false)\n");
puts("\t// Setup submodule names\n");
char comma=',';
@@ -426,11 +429,14 @@ void EmitCSyms::emitSymImp() {
}
}
puts("// Setup scope names\n");
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
putsQuoted(it->second.m_prettyName);
puts(");\n");
{ // Setup scope names
bool did = false;
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
if (!did++) puts("// Setup scope names\n");
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
putsQuoted(it->second.m_prettyName);
puts(");\n");
}
}
if (v3Global.dpi()) {
@@ -518,7 +524,9 @@ void EmitCSyms::emitSymImp() {
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
puts( "// LOCAL STATE\n");
// __Vm_namep presumably already correct
puts( "os"+op+"__Vm_activity;\n");
if (v3Global.opt.trace()) {
puts( "os"+op+"__Vm_activity;\n");
}
puts( "os"+op+"__Vm_didInit;\n");
puts( "// SUBCELL STATE\n");
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
+8 -19
View File
@@ -90,15 +90,10 @@ public:
if (v3Global.opt.coverage()) {
putMakeClassEntry(of, "verilated_cov.cpp");
}
if (v3Global.opt.systemPerl()) {
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
}
else {
if (v3Global.opt.trace()) {
putMakeClassEntry(of, "verilated_vcd_c.cpp");
if (v3Global.opt.systemC()) {
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
}
if (v3Global.opt.trace()) {
putMakeClassEntry(of, "verilated_vcd_c.cpp");
if (v3Global.opt.systemC()) {
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
}
}
}
@@ -106,7 +101,7 @@ public:
}
else {
for (AstCFile* nodep = v3Global.rootp()->filesp(); nodep; nodep=nodep->nextp()->castCFile()) {
if (nodep->source() && nodep->slow()==slow && nodep->support()==support) {
if (nodep->source() && nodep->slow()==(slow!=0) && nodep->support()==(support!=0)) {
putMakeClassEntry(of, nodep->name());
}
}
@@ -139,22 +134,16 @@ public:
of.puts("PERL = "+V3Options::getenvPERL()+"\n");
of.puts("# Path to Verilator kit (from $VERILATOR_ROOT)\n");
of.puts("VERILATOR_ROOT = "+V3Options::getenvVERILATOR_ROOT()+"\n");
of.puts("# Path to SystemPerl kit top (from $SYSTEMPERL)\n");
of.puts("SYSTEMPERL = "+V3Options::getenvSYSTEMPERL()+"\n");
of.puts("# Path to SystemPerl kit includes (from $SYSTEMPERL_INCLUDE)\n");
of.puts("SYSTEMPERL_INCLUDE = "+V3Options::getenvSYSTEMPERL_INCLUDE()+"\n");
of.puts("# SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE)\n");
of.puts(string("SYSTEMC_INCLUDE ?= ")+V3Options::getenvSYSTEMC_INCLUDE()+"\n");
of.puts("# SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR)\n");
of.puts(string("SYSTEMC_LIBDIR ?= ")+V3Options::getenvSYSTEMC_LIBDIR()+"\n");
of.puts("\n### Switches...\n");
of.puts("# SystemPerl output mode? 0/1 (from --sp)\n");
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
of.puts("# SystemC output mode? 0/1 (from --sc)\n");
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
of.puts("# SystemPerl or SystemC output mode? 0/1 (from --sp/--sc)\n");
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
of.puts(string("VM_SC = ")+((v3Global.opt.systemC())?"1":"0")+"\n");
of.puts("# Legacy or SystemC output mode? 0/1 (from --sc)\n");
of.puts(string("VM_SP_OR_SC = $(VM_SC)\n"));
of.puts("# Deprecated\n");
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
of.puts("# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)\n");
-4
View File
@@ -238,10 +238,6 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
virtual void visit(AstSFormatF* nodep) {
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
}
virtual void visit(AstValuePlusArgs* nodep) {
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
}
virtual void visit(AstFOpen* nodep) {
putfs(nodep,nodep->verilogKwd());
putbs(" (");
+1 -1
View File
@@ -215,7 +215,7 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
}
#ifndef _V3ERROR_NO_GLOBAL_
if (debug()) {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",990));
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final",990));
if (s_errorExitCb) s_errorExitCb();
V3Stats::statsFinalAll(v3Global.rootp());
V3Stats::statsReport();
+8 -5
View File
@@ -29,6 +29,7 @@
#include <map>
#include <set>
#include <deque>
#include <cassert>
//######################################################################
@@ -253,18 +254,20 @@ class V3Error {
// Global versions, so that if the class doesn't define a operator, we get the functions anyways.
inline int debug() { return V3Error::debugDefault(); }
inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
inline void v3errorEndFatal(ostringstream& sstr) { V3Error::v3errorEnd(sstr); assert(0); VL_UNREACHABLE }
// Theses allow errors using << operators: v3error("foo"<<"bar");
// Careful, you can't put () around msg, as you would in most macro definitions
// Note the commas are the comma operator, not separating arguments. These are needed to insure
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
#define v3warnCode(code,msg) v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
#define v3warn(code,msg) v3warnCode(V3ErrorCode::code,msg)
#define v3info(msg) v3warn(EC_INFO,msg)
#define v3fatal(msg) v3warn(EC_FATAL,msg)
#define v3error(msg) v3warn(EC_ERROR,msg)
#define v3warnCodeFatal(code,msg) v3errorEndFatal((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
#define v3warn(code,msg) v3warnCode(V3ErrorCode::code, msg)
#define v3info(msg) v3warnCode(V3ErrorCode::EC_INFO, msg)
#define v3error(msg) v3warnCode(V3ErrorCode::EC_ERROR, msg)
#define v3fatal(msg) v3warnCodeFatal(V3ErrorCode::EC_FATAL, msg)
// Use this instead of fatal() to mention the source code line.
#define v3fatalSrc(msg) v3warn(EC_FATALSRC,__FILE__<<":"<<dec<<__LINE__<<": "<<msg)
#define v3fatalSrc(msg) v3warnCodeFatal(V3ErrorCode::EC_FATALSRC, __FILE__<<":"<<dec<<__LINE__<<": "<<msg)
#define UINFO(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
#define UINFONL(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<stmsg; } }
+1 -1
View File
@@ -937,5 +937,5 @@ public:
void V3Expand::expandAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
ExpandVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("expand.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("expand", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+15 -33
View File
@@ -553,8 +553,7 @@ bool V3InFilter::readWholefile(const string& filename, V3InFilter::StrList& outl
V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang)
: m_filename(filename), m_lang(lang)
, m_lineno(1), m_column(0)
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0) {
m_blockIndent = v3Global.opt.decoration() ? 4 : 1;
m_commaWidth = v3Global.opt.decoration() ? 50 : 150;
}
@@ -609,21 +608,22 @@ bool V3OutFormatter::tokenEnd(const char* cp) {
int V3OutFormatter::endLevels (const char *strg) {
int levels=m_indentLevel;
const char* cp=strg;
while (isspace(*cp)) cp++;
switch (*cp) {
case '\n': // Newlines.. No need for whitespace before it
return (0);
case '#': // Preproc directive
return (0);
}
{
// label/public/private: Deindent by 2 spaces
const char* mp=cp;
for (; isalnum(*mp); mp++) ;
if (mp[0]==':' && mp[1]!=':') return (levels-m_blockIndent/2);
const char* cp=strg;
while (isspace(*cp)) cp++;
switch (*cp) {
case '\n': // Newlines.. No need for whitespace before it
return (0);
case '#': // Preproc directive
return (0);
}
{
// label/public/private: Deindent by 2 spaces
const char* mp=cp;
for (; isalnum(*mp); mp++) ;
if (mp[0]==':' && mp[1]!=':') return (levels-m_blockIndent/2);
}
}
// We want "} else {" to be one level to the left of normal
for (const char* cp=strg; *cp; cp++) {
switch (*cp) {
@@ -797,24 +797,6 @@ void V3OutFormatter::putcNoTracking (char chr) {
putcOutput (chr);
}
void V3OutFormatter::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const string& prefix) {
if (size==0) size=align;
int alignSize = size; if (alignSize>8) alignSize=8;
int& alignr = isStatic ? m_declSAlign : m_declNSAlign;
int padsize = alignSize - (alignr % alignSize);
if (padsize && padsize!=alignSize) {
// Modern versions of GCC no longer need this, they'll pad for us, so
// we'll save the work and danger of getting it wrong.
puts("//char\t");
puts(prefix);
puts("__VpadToAlign"+cvtToStr(alignr)
+"["+cvtToStr(padsize)+"];\n");
alignr += padsize;
m_declPadNum++;
}
alignr += size;
}
//----------------------------------------------------------------------
// Simple wrappers
-16
View File
@@ -120,9 +120,6 @@ private:
int m_nobreak; // Basic operator or begin paren, don't break next
bool m_prependIndent;
int m_indentLevel; // Current {} indentation
int m_declSAlign; // Byte alignment of next declaration, statics
int m_declNSAlign; // Byte alignment of next declaration, nonstatics
int m_declPadNum; // Pad variable number
stack<int> m_parenVec; // Stack of columns where last ( was
int endLevels(const char* strg);
@@ -144,7 +141,6 @@ public:
void putsQuoted(const string& strg);
void putBreak(); // Print linebreak if line is too wide
void putBreakExpr(); // Print linebreak in expression if line is too wide
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const string& prefix=""); // Declare a variable, with natural alignment
void putbs(const char* strg) { putBreakExpr(); puts(strg); }
void putbs(const string& strg) { putBreakExpr(); puts(strg); }
bool exceededWidth() const { return m_column > m_commaWidth; }
@@ -222,18 +218,6 @@ public:
}
};
class V3OutSpFile : public V3OutCFile {
public:
explicit V3OutSpFile(const string& filename) : V3OutCFile(filename) {}
virtual ~V3OutSpFile() {}
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
virtual void putsIntTopInclude() {
putsForceIncs();
puts("#include \"systemperl.h\"\n");
puts("#include \"verilated_sc.h\"\n");
}
};
class V3OutVFile : public V3OutFile {
public:
explicit V3OutVFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_VERILOG) {}
+1 -1
View File
@@ -270,7 +270,7 @@ void FileLine::operator delete(void* objp, size_t size) {
if (it != fileLineLeakChecks.end()) {
fileLineLeakChecks.erase(it);
} else {
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
flp->v3fatalSrc("Deleting FileLine object that was never tracked");
}
::operator delete(objp);
}
+5
View File
@@ -161,11 +161,16 @@ public:
// OPERATORS
void v3errorEnd(ostringstream& str);
void v3errorEndFatal(ostringstream& str);
string warnMore() const;
inline bool operator==(FileLine rhs) const {
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
}
private:
void v3errorEndFatalGuts(ostringstream& str);
};
ostream& operator<<(ostream& os, FileLine* fileline);
inline void FileLine::v3errorEndFatal(ostringstream& str) { v3errorEnd(str); assert(0); }
#endif // Guard
+222 -10
View File
@@ -113,6 +113,20 @@ public:
}
return ret;
}
// Returns only the result from the LAST vertex iterated over
// Note: This behaves differently than iterateInEdges() in that it will traverse
// all edges that exist when it is initially called, whereas
// iterateInEdges() will stop traversing edges if one is deleted
VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu=VNUser(0)) {
VNUser ret = VNUser(0);
V3GraphEdge* next_edgep = NULL;
for (V3GraphEdge* edgep = outBeginp(); edgep; edgep = next_edgep) {
// Need to find the next edge before visiting in case the edge is deleted
next_edgep = edgep->outNextp();
ret = dynamic_cast<GateEitherVertex*>(edgep->top())->accept(v, vu);
}
return ret;
}
};
class GateVarVertex : public GateEitherVertex {
@@ -291,6 +305,7 @@ private:
// {statement}Node::user1p -> GateLogicVertex* for this statement
// AstVarScope::user2 -> bool: Signal used in SenItem in *this* always statement
// AstVar::user2 -> bool: Warned about SYNCASYNCNET
// AstVarNodeRef::user2 -> bool: ConcatOffset visited
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
@@ -358,6 +373,7 @@ private:
void replaceAssigns();
void dedupe();
void mergeAssigns();
void decomposeClkVectors();
// VISITORS
virtual void visit(AstNetlist* nodep) {
@@ -365,6 +381,8 @@ private:
//if (debug()>6) m_graph.dump();
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
warnSignals(); // Before loss of sync/async pointers
// Decompose clock vectors -- need to do this before removing redundant edges
decomposeClkVectors();
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
m_graph.dumpDotFilePrefixed("gate_simp");
// Find gate interconnect and optimize
@@ -409,9 +427,9 @@ private:
}
virtual void visit(AstNodeVarRef* nodep) {
if (m_scopep) {
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block");
AstVarScope* varscp = nodep->varScopep();
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
GateVarVertex* vvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
if (m_inSenItem) vvertexp->setIsClock();
@@ -419,9 +437,9 @@ private:
if (m_inSenItem) varscp->user2(true);
else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) {
if (varscp->user2()) {
if (!vvertexp->rstSyncNodep()) vvertexp->rstSyncNodep(nodep);
} else {
if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep);
} else {
if (!vvertexp->rstSyncNodep()) vvertexp->rstSyncNodep(nodep);
}
}
// We use weight of one; if we ref the var more than once, when we simplify,
@@ -484,7 +502,7 @@ private:
}
virtual void visit(AstConcat* nodep) {
if (nodep->backp()->castNodeAssign() && nodep->backp()->castNodeAssign()->lhsp()==nodep) {
nodep->v3fatalSrc("Concat on LHS of assignment; V3Const should have deleted it\n");
nodep->v3fatalSrc("Concat on LHS of assignment; V3Const should have deleted it");
}
nodep->iterateChildren(*this);
}
@@ -704,7 +722,7 @@ void GateVisitor::replaceAssigns() {
if (!vscp->valuep()->castNodeMath()
|| vscp->valuep()->nextp()) {
vscp->dumpTree(cerr, "vscStrange: ");
vscp->v3fatalSrc("Value of varscope not mathematical\n");
vscp->v3fatalSrc("Value of varscope not mathematical");
}
}
}
@@ -1115,7 +1133,7 @@ void GateVisitor::dedupe() {
//######################################################################
// Recurse through the graph, try to merge assigns
// Recurse through the graph, try to merge assigns
class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor {
private:
@@ -1127,7 +1145,7 @@ private:
V3Double0 m_numMergedAssigns; // Statistic tracking
// assemble two Sel into one if possible
// assemble two Sel into one if possible
AstSel* merge(AstSel* pre, AstSel* cur) {
AstVarRef* preVarRefp = pre->fromp()->castVarRef();
AstVarRef* curVarRefp = cur->fromp()->castVarRef();
@@ -1183,7 +1201,7 @@ private:
// update the graph
{
// delete all inedges to lvertexp
if (!lvertexp->inEmpty()) {
if (!lvertexp->inEmpty()) {
for (V3GraphEdge* ledgep = lvertexp->inBeginp(); ledgep; ) {
V3GraphEdge* oedgep = ledgep;
ledgep = ledgep->inNextp();
@@ -1238,6 +1256,200 @@ void GateVisitor::mergeAssigns() {
m_statAssignMerged += merger.numMergedAssigns();
}
//######################################################################
// Find a var's offset in a concatenation
class GateConcatVisitor : public GateBaseVisitor {
private:
// STATE
AstVarScope* m_vscp; // Varscope we're trying to find
int m_offset; // Current offset of varscope
int m_found_offset; // Found offset of varscope
bool m_found; // Offset found
// VISITORS
virtual void visit(AstNodeVarRef* nodep) {
UINFO(9,"CLK DECOMP Concat search var (off = "<<m_offset<<") - "<<nodep<<endl);
if (nodep->varScopep() == m_vscp && !nodep->user2() && !m_found) {
// A concatenation may use the same var multiple times
// But the graph will initially have an edge per instance
nodep->user2(true);
m_found_offset = m_offset;
m_found = true;
UINFO(9,"CLK DECOMP Concat found var (off = "<<m_offset<<") - "<<nodep<<endl);
}
m_offset += nodep->dtypep()->width();
}
virtual void visit(AstConcat* nodep) {
UINFO(9,"CLK DECOMP Concat search (off = "<<m_offset<<") - "<<nodep<<endl);
nodep->rhsp()->iterate(*this);
nodep->lhsp()->iterate(*this);
}
//--------------------
// Default
virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
GateConcatVisitor() {
m_vscp = NULL;
m_offset = 0;
m_found_offset = 0;
m_found = false;
}
virtual ~GateConcatVisitor() {}
// PUBLIC METHODS
bool concatOffset(AstConcat* concatp, AstVarScope* vscp, int& offsetr) {
m_vscp = vscp;
m_offset = 0;
m_found = false;
// Iterate
concatp->accept(*this);
UINFO(9,"CLK DECOMP Concat Offset (found = "<<m_found<<") ("<<m_found_offset<<") - "<<concatp<<" : "<<vscp<<endl);
offsetr = m_found_offset;
return m_found;
}
};
//######################################################################
// Recurse through the graph, looking for clock vectors to bypass
class GateClkDecompState {
public:
int m_offset;
AstVarScope* m_last_vsp;
GateClkDecompState(int offset, AstVarScope* vsp) {
m_offset = offset;
m_last_vsp = vsp;
}
virtual ~GateClkDecompState() {}
};
class GateClkDecompGraphVisitor : public GateGraphBaseVisitor {
private:
// NODE STATE
// AstVarScope::user2p -> bool: already visited
V3Graph* m_graphp;
int m_seen_clk_vectors;
AstVarScope* m_clk_vsp;
GateVarVertex* m_clk_vvertexp;
GateConcatVisitor m_concat_visitor;
int m_total_seen_clk_vectors;
int m_total_decomposed_clk_vectors;
virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) {
// Check that we haven't been here before
AstVarScope* vsp = vvertexp->varScp();
if (vsp->user2SetOnce()) return VNUser(0);
UINFO(9,"CLK DECOMP Var - "<<vvertexp<<" : "<<vsp<<endl);
if (vsp->varp()->width() > 1) {
m_seen_clk_vectors++;
m_total_seen_clk_vectors++;
}
GateClkDecompState* currState = (GateClkDecompState*) vu.c();
GateClkDecompState nextState(currState->m_offset, vsp);
vvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState));
if (vsp->varp()->width() > 1) {
m_seen_clk_vectors--;
}
vsp->user2(false);
return VNUser(0);
}
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) {
GateClkDecompState* currState = (GateClkDecompState*) vu.c();
int clk_offset = currState->m_offset;
if (AstAssignW* assignp = lvertexp->nodep()->castAssignW()) {
UINFO(9,"CLK DECOMP Logic (off = "<<clk_offset<<") - "<<lvertexp<<" : "<<m_clk_vsp<<endl);
if (AstSel* rselp = assignp->rhsp()->castSel()) {
if (rselp->lsbp()->castConst() && rselp->widthp()->castConst()) {
if (clk_offset < rselp->lsbConst() || clk_offset > rselp->msbConst()) {
UINFO(9,"CLK DECOMP Sel [ "<<rselp->msbConst()<<" : "<<rselp->lsbConst()<<" ] dropped clock ("<<clk_offset<<")"<<endl);
return VNUser(0);
}
clk_offset -= rselp->lsbConst();
} else {
return VNUser(0);
}
} else if (AstConcat* catp = assignp->rhsp()->castConcat()) {
UINFO(9,"CLK DECOMP Concat searching - "<<assignp->lhsp()<<endl);
int concat_offset;
if (!m_concat_visitor.concatOffset(catp, currState->m_last_vsp, concat_offset)) {
return VNUser(0);
}
clk_offset += concat_offset;
}
if (AstSel* lselp = assignp->lhsp()->castSel()) {
if (lselp->lsbp()->castConst() && lselp->widthp()->castConst()) {
clk_offset += lselp->lsbConst();
} else {
return VNUser(0);
}
} else if (AstVarRef* vrp = assignp->lhsp()->castVarRef()) {
if (vrp->dtypep()->width() == 1 && m_seen_clk_vectors) {
if (clk_offset != 0) {
UINFO(9,"Should only make it here with clk_offset = 0"<<endl);
return VNUser(0);
}
UINFO(9,"CLK DECOMP Connecting - "<<assignp->lhsp()<<" <-> "<<m_clk_vsp<<endl);
AstNode* rhsp = assignp->rhsp();
rhsp->replaceWith(new AstVarRef(rhsp->fileline(), m_clk_vsp, false));
for (V3GraphEdge* edgep = lvertexp->inBeginp(); edgep; ) {
edgep->unlinkDelete(); VL_DANGLING(edgep);
}
new V3GraphEdge(m_graphp, m_clk_vvertexp, lvertexp, 1);
m_total_decomposed_clk_vectors++;
}
}
GateClkDecompState nextState(clk_offset, currState->m_last_vsp);
return lvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState));
}
return VNUser(0);
}
public:
explicit GateClkDecompGraphVisitor(V3Graph* graphp) {
m_graphp = graphp;
m_seen_clk_vectors = 0;
m_clk_vsp = NULL;
m_clk_vvertexp = NULL;
m_total_seen_clk_vectors = 0;
m_total_decomposed_clk_vectors = 0;
}
virtual ~GateClkDecompGraphVisitor() {
V3Stats::addStat("Optimizations, Clocker seen vectors", m_total_seen_clk_vectors);
V3Stats::addStat("Optimizations, Clocker decomposed vectors", m_total_decomposed_clk_vectors);
}
void clkDecomp(GateVarVertex* vvertexp) {
UINFO(9,"CLK DECOMP Starting Var - "<<vvertexp<<endl);
m_seen_clk_vectors = 0;
m_clk_vsp = vvertexp->varScp();
m_clk_vvertexp = vvertexp;
GateClkDecompState nextState(0, m_clk_vsp);
vvertexp->accept(*this, VNUser(&nextState));
}
};
void GateVisitor::decomposeClkVectors() {
UINFO(9,"Starting clock decomposition"<<endl);
AstNode::user2ClearTree();
GateClkDecompGraphVisitor decomposer(&m_graph);
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (GateVarVertex* vertp = dynamic_cast<GateVarVertex*>(itp)) {
AstVarScope* vsp = vertp->varScp();
if (vsp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
if (vsp->varp()->width() > 1) {
UINFO(9,"Clocker > 1 bit, not decomposing: "<<vsp<<endl);
} else {
UINFO(9,"CLK DECOMP - "<<vertp<<" : "<<vsp<<endl);
decomposer.clkDecomp(vertp);
}
}
}
}
}
//######################################################################
// Convert VARSCOPE(ASSIGN(default, VARREF)) to just VARSCOPE(default)
@@ -1276,5 +1488,5 @@ void V3Gate::gateAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
GateVisitor visitor (nodep);
GateDeassignVisitor deassign (nodep);
V3Global::dumpCheckGlobalTree("gate.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("gate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -228,5 +228,5 @@ public:
void V3GenClk::genClkAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
GenClkReadVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("genclk.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("genclk", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -97,7 +97,7 @@ public:
// METHODS
void readFiles();
void checkTree();
static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
static void dumpCheckGlobalTree(const string& stagename, int newNumber=0, bool doDump=true);
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
bool constRemoveXs() const { return m_constRemoveXs; }
+1 -1
View File
@@ -529,7 +529,7 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) {
// Compute fanouts of each node
// If forward edge, don't double count that fanout
if (vertexp->user() == 2) return vertexp->fanout(); // Already processed it
if (vertexp->user() == 1) v3fatalSrc("Loop found, backward edges should be dead\n");
if (vertexp->user() == 1) v3fatalSrc("Loop found, backward edges should be dead");
vertexp->user(1);
double fanout = 0;
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
+6 -6
View File
@@ -44,7 +44,7 @@ DfaVertex* DfaGraph::findStart() {
startp = vvertexp;
}
} else {
v3fatalSrc("Non DfaVertex in DfaGraph\n");
v3fatalSrc("Non DfaVertex in DfaGraph");
}
}
if (!startp) v3fatalSrc("No start point in NFA graph");
@@ -257,11 +257,11 @@ private:
// Find epsilon closure of this nfa node, and destinations to work list
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
DfaVertex* nfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
DfaVertex* ecNfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
//UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
if (cNfaEdgep->epsilon()
&& unseenNfaThisStep(nfaStatep)) { // Not processed?
workps.push_back(nfaStatep);
&& unseenNfaThisStep(ecNfaStatep)) { // Not processed?
workps.push_back(ecNfaStatep);
}
}
}
@@ -453,7 +453,7 @@ private:
DfaVertex* fromvertexp = static_cast<DfaVertex*>(edgep->fromp());
if (fromvertexp != vertexp
&& !fromvertexp->user()) {
workps.push(static_cast<DfaVertex*>(fromvertexp));
workps.push(fromvertexp);
fromvertexp->user(1);
}
}
@@ -520,7 +520,7 @@ private:
}
}
}
if (!acceptp) v3fatalSrc("No accepting vertex in DFA\n");
if (!acceptp) v3fatalSrc("No accepting vertex in DFA");
// Remap edges
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
+1 -1
View File
@@ -124,7 +124,7 @@ public:
static DfaInput EPSILON() { return VNUser::fromInt(0); }
static DfaInput NA() { return VNUser::fromInt(1); } // as in not-applicable
// CONSTRUCTORS
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, DfaInput input)
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaInput& input)
: V3GraphEdge(graphp, fromp, top, 1)
, m_input(input), m_complement(false) {}
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
+4 -4
View File
@@ -72,7 +72,7 @@ public:
class V3GraphTestVertex : public V3GraphVertex {
string m_name;
public:
V3GraphTestVertex(V3Graph* graphp, string name) : V3GraphVertex(graphp), m_name(name) {}
V3GraphTestVertex(V3Graph* graphp, const string& name) : V3GraphVertex(graphp), m_name(name) {}
virtual ~V3GraphTestVertex() {}
// Accessors
virtual string name() const { return m_name; }
@@ -80,7 +80,7 @@ public:
class V3GraphTestVarVertex : public V3GraphTestVertex {
public:
V3GraphTestVarVertex(V3Graph* graphp, string name) : V3GraphTestVertex(graphp, name) {}
V3GraphTestVarVertex(V3Graph* graphp, const string& name) : V3GraphTestVertex(graphp, name) {}
virtual ~V3GraphTestVarVertex() {}
// Accessors
virtual string dotColor() const { return "blue"; }
@@ -251,7 +251,7 @@ public:
// Outbound are cutable, as we may need to evaluate multiple times
{
V3GraphTestVertex* n = new V3GraphTestVertex(gp,"c=a|b|i");
n = new V3GraphTestVertex(gp,"c=a|b|i");
new V3GraphEdge(gp, n, c, 1, true);
new V3GraphEdge(gp, a, n, 1, false);
new V3GraphEdge(gp, b, n, 1, false);
@@ -270,7 +270,7 @@ public:
class DfaTestVertex : public DfaVertex {
string m_name;
public:
DfaTestVertex(DfaGraph* graphp, string name) : DfaVertex(graphp), m_name(name) {}
DfaTestVertex(DfaGraph* graphp, const string& name) : DfaVertex(graphp), m_name(name) {}
virtual ~DfaTestVertex() {}
// Accessors
virtual string name() const { return m_name; }
+4 -4
View File
@@ -277,7 +277,7 @@ private:
AstVarRef* exprvarrefp = nodep->user2p()->castVarRef();
UINFO(8,"connectto: "<<nodep->user2p()<<endl);
if (!exprconstp && !exprvarrefp) {
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
}
if (exprconstp) {
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
@@ -362,7 +362,7 @@ private:
nodep->varp( exprvarrefp->varp() );
}
else {
nodep->v3fatalSrc("Null connection?\n");
nodep->v3fatalSrc("Null connection?");
}
}
nodep->name(nodep->varp()->name());
@@ -514,7 +514,7 @@ private:
AstNode* connectRefp = pinp->exprp();
if (!connectRefp->castConst() && !connectRefp->castVarRef()) {
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
}
if (pinNewVarp->isOutOnly() && connectRefp->castConst()) {
pinp->v3error("Output port is connected to a constant pin, electrical short");
@@ -587,5 +587,5 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
}
}
V3Global::dumpCheckGlobalTree("inline.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("inline", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+126 -65
View File
@@ -90,7 +90,7 @@ private:
// Make a ASSIGNW (expr, pin)
AstNode* exprp = nodep->exprp()->cloneTree(false);
if (exprp->width() != nodep->modVarp()->width())
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
if (nodep->modVarp()->isInout()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isOutput()) {
@@ -154,14 +154,10 @@ public:
//######################################################################
class InstDeVisitor : public AstNVisitor {
// Find all cells with arrays, and convert to non-arrayed
class InstDeModVarVisitor : public AstNVisitor {
// Expand all module variables, and save names for later reference
private:
// STATE
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
int m_instNum; // Current instantiation number
int m_instLsb; // Current instantiation number
typedef map<string,AstVar*> VarNameMap;
VarNameMap m_modVarNameMap; // Per module, name of cloned variables
@@ -172,15 +168,108 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstVar* nodep) {
if (nodep->dtypep()->castIfaceRefDType()) {
UINFO(8," dm-1-VAR "<<nodep<<endl);
insert(nodep);
}
nodep->iterateChildren(*this);
}
// Save some time
virtual void visit(AstNodeMath*) {}
// Default: Just iterate
virtual void visit(AstNode* nodep) {
nodep->iterateChildren(*this);
}
public:
// METHODS
void insert(AstVar* nodep) {
UINFO(8," dmINSERT "<<nodep<<endl);
m_modVarNameMap.insert(make_pair(nodep->name(), nodep));
}
AstVar* find(const string& name) {
VarNameMap::iterator it = m_modVarNameMap.find(name);
if (it != m_modVarNameMap.end()) {
return it->second;
} else {
return NULL;
}
}
void dump() {
for (VarNameMap::iterator it=m_modVarNameMap.begin(); it!=m_modVarNameMap.end(); ++it) {
cout<<"-namemap: "<<it->first<<" -> "<<it->second<<endl;
}
}
public:
// CONSTUCTORS
explicit InstDeModVarVisitor() {}
void main(AstNodeModule* nodep) {
UINFO(8," dmMODULE "<<nodep<<endl);
m_modVarNameMap.clear();
nodep->accept(*this);
}
virtual ~InstDeModVarVisitor() {}
};
//######################################################################
class InstDeVisitor : public AstNVisitor {
// Find all cells with arrays, and convert to non-arrayed
private:
// STATE
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
int m_instSelNum; // Current instantiation count 0..N-1
InstDeModVarVisitor m_deModVars; // State of variables for current cell module
typedef map<string,AstVar*> VarNameMap;
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
// VISITORS
virtual void visit(AstVar* nodep) {
if (nodep->dtypep()->castUnpackArrayDType()
&& nodep->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType()) {
UINFO(8," dv-vec-VAR "<<nodep<<endl);
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
AstNode* prevp = NULL;
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
UINFO(8,"VAR name insert "<<varNewName<<" "<<nodep<<endl);
if (!m_deModVars.find(varNewName)) {
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
arrdtype->addNextHere(ifaceRefp);
ifaceRefp->cellp(NULL);
AstVar* varNewp = nodep->cloneTree(false);
varNewp->name(varNewName);
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
varNewp->dtypep(ifaceRefp);
m_deModVars.insert(varNewp);
if (!prevp) {
prevp = varNewp;
} else {
prevp->addNextHere(varNewp);
}
}
}
if (prevp) nodep->addNextHere(prevp);
if (prevp && debug()==9) { prevp->dumpTree(cout, "newintf: "); cout << endl; }
}
nodep->iterateChildren(*this);
}
virtual void visit(AstCell* nodep) {
UINFO(4," CELL "<<nodep<<endl);
// Find submodule vars
if (!nodep->modp()) nodep->v3fatalSrc("Unlinked");
m_deModVars.main(nodep->modp());
//
if (nodep->rangep()) {
m_cellRangep = nodep->rangep();
UINFO(4," CELL "<<nodep<<endl);
AstVar* ifaceVarp = nodep->nextp()->castVar();
bool isIface = ifaceVarp
@@ -188,8 +277,10 @@ private:
&& ifaceVarp->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
// Make all of the required clones
m_instLsb = m_cellRangep->lsbConst();
for (m_instNum = m_instLsb; m_instNum<=m_cellRangep->msbConst(); m_instNum++) {
for (int i = 0; i < m_cellRangep->elementsConst(); i++) {
m_instSelNum = m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i;
int instNum = m_cellRangep->lsbConst() + i;
AstCell* newp = nodep->cloneTree(false);
nodep->addNextHere(newp);
// Remove ranging and fix name
@@ -197,11 +288,12 @@ private:
// Somewhat illogically, we need to rename the orignal name of the cell too.
// as that is the name users expect for dotting
// The spec says we add [x], but that won't work in C...
newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
newp->name(newp->name()+"__BRA__"+cvtToStr(instNum)+"__KET__");
newp->origName(newp->origName()+"__BRA__"+cvtToStr(instNum)+"__KET__");
UINFO(8," CELL loop "<<newp<<endl);
// If this AstCell is actually an interface instantiation, let's ensure we also clone
// the IfaceRef.
// If this AstCell is actually an interface instantiation, also clone the IfaceRef
// within the same parent module as the cell
if (isIface) {
AstUnpackArrayDType* arrdtype = ifaceVarp->dtypep()->castUnpackArrayDType();
AstIfaceRefDType* origIfaceRefp = arrdtype->subDTypep()->castIfaceRefDType();
@@ -211,8 +303,8 @@ private:
arrdtype->addNextHere(ifaceRefp);
ifaceRefp->cellp(newp);
ifaceRefp->cellName(newp->name());
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(instNum) + "__KET__");
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(instNum) + "__KET__");
varNewp->dtypep(ifaceRefp);
newp->addNextHere(varNewp);
if (debug()==9) { varNewp->dumpTree(cout, "newintf: "); cout << endl; }
@@ -229,42 +321,11 @@ private:
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
} else {
m_cellRangep = NULL;
nodep->iterateChildren(*this);
}
}
virtual void visit(AstVar* nodep) {
bool isIface = nodep->dtypep()->castUnpackArrayDType()
&& nodep->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
if (isIface) {
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
AstNode* prev = NULL;
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
arrdtype->addNextHere(ifaceRefp);
ifaceRefp->cellp(NULL);
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
if (it == m_modVarNameMap.end()) {
AstVar* varNewp = nodep->cloneTree(false);
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
varNewp->name(varNewName);
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
varNewp->dtypep(ifaceRefp);
if (!prev) {
prev = varNewp;
} else {
prev->addNextHere(varNewp);
}
}
}
if (prev) nodep->addNextHere(prev);
if (prev && debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; }
}
nodep->iterateChildren(*this);
}
virtual void visit(AstPin* nodep) {
// Any non-direct pins need reconnection with a part-select
if (!nodep->exprp()) return; // No-connect
@@ -283,12 +344,16 @@ private:
// Connection to array, where array dimensions match the instant dimension
AstNode* exprp = nodep->exprp()->unlinkFrBack();
exprp = new AstArraySel (exprp->fileline(), exprp,
(m_instNum-m_instLsb));
m_instSelNum);
nodep->exprp(exprp);
} else if (expwidth == pinwidth) {
// NOP: Arrayed instants: widths match so connect to each instance
} else if (expwidth == pinwidth*m_cellRangep->elementsConst()) {
// Arrayed instants: one bit for each of the instants (each assign is 1 pinwidth wide)
if (m_cellRangep->littleEndian()) {
nodep->v3warn(LITENDIAN,"Little endian cell range connecting to vector: MSB < LSB of cell range: "
<<m_cellRangep->lsbConst()<<":"<<m_cellRangep->msbConst());
}
AstNode* exprp = nodep->exprp()->unlinkFrBack();
bool inputPin = nodep->modVarp()->isInput();
if (!inputPin && !exprp->castVarRef()
@@ -298,7 +363,7 @@ private:
// Note spec allows more complicated matches such as slices and such
}
exprp = new AstSel (exprp->fileline(), exprp,
pinwidth*(m_instNum-m_instLsb),
pinwidth*m_instSelNum,
pinwidth);
nodep->exprp(exprp);
} else {
@@ -334,30 +399,28 @@ private:
// Clone pin varp:
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) {
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
AstVar* varNewp = NULL;
// Only clone the var once for each module
// Only clone the var once for all usages of a given child module
if (!pinVarp->backp()) {
if (it != m_modVarNameMap.end()) {
varNewp = it->second;
}
varNewp = m_deModVars.find(varNewName);
} else {
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
ifaceRefp->cellp(NULL);
varNewp = pinVarp->cloneTree(false);
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
varNewp->name(varNewName);
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
varNewp->dtypep(ifaceRefp);
m_deModVars.insert(varNewp);
if (!prevp) {
prevp = varNewp;
} else {
prevp->addNextHere(varNewp);
}
}
if (varNewp == NULL) {
nodep->v3fatalSrc("Module dearray failed\n");
if (!varNewp) {
if (debug()>=9) m_deModVars.dump();
nodep->v3fatalSrc("Module dearray failed for "<<AstNode::prettyName(varNewName));
}
// But clone the pin for each module instance
@@ -399,8 +462,7 @@ public:
// CONSTUCTORS
explicit InstDeVisitor(AstNetlist* nodep) {
m_cellRangep=NULL;
m_instNum=0;
m_instLsb=0;
m_instSelNum=0;
//
nodep->accept(*this);
}
@@ -468,8 +530,7 @@ public:
&& connBasicp->width() == pinBasicp->width()
&& connBasicp->lsb() == pinBasicp->lsb()
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
&& connBasicp->width() == pinVarp->width()
&& 1) {
&& connBasicp->width() == pinVarp->width()) {
// Done. One to one interconnect won't need a temporary variable.
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
// Done. Constant.
@@ -522,11 +583,11 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
void V3Inst::instAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
InstVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("inst.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("inst", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3Inst::dearrayAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
InstDeVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("dearray.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("dearray", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+104 -43
View File
@@ -45,70 +45,132 @@ class V3LanguageWords {
public:
V3LanguageWords() {
// C++ keywords
addKwd("asm", "C++ reserved word");
addKwd("auto", "C++ reserved word");
addKwd("catch", "C++ reserved word");
addKwd("cdecl", "C++ reserved word");
addKwd("char", "C++ reserved word");
addKwd("const_cast", "C++ reserved word");
addKwd("delete", "C++ reserved word");
addKwd("double", "C++ reserved word");
addKwd("dynamic_cast", "C++ reserved word");
addKwd("explicit", "C++ reserved word");
addKwd("far", "C++ reserved word");
addKwd("float", "C++ reserved word");
addKwd("friend", "C++ reserved word");
addKwd("goto", "C++ reserved word");
addKwd("huge", "C++ reserved word");
addKwd("inline", "C++ reserved word");
addKwd("interrupt", "C++ reserved word");
addKwd("long", "C++ reserved word");
addKwd("mutable", "C++ reserved word");
addKwd("near", "C++ reserved word");
addKwd("operator", "C++ reserved word");
addKwd("pascal", "C++ reserved word");
addKwd("private", "C++ reserved word");
addKwd("public", "C++ reserved word");
addKwd("register", "C++ reserved word");
addKwd("reinterpret_cast ", "C++ reserved word");
addKwd("restrict", "C++ reserved word");
addKwd("short", "C++ reserved word");
addKwd("sizeof", "C++ reserved word");
addKwd("static_cast", "C++ reserved word");
addKwd("switch", "C++ reserved word");
addKwd("template", "C++ reserved word");
addKwd("throw", "C++ reserved word");
addKwd("try", "C++ reserved word");
addKwd("typeid", "C++ reserved word");
addKwd("typename", "C++ reserved word");
addKwd("unsigned", "C++ reserved word");
addKwd("using", "C++ reserved word");
addKwd("volatile", "C++ reserved word");
// C++
addKwd("NULL", "C++ common word");
addKwd("abort", "C++ common word");
addKwd("alignas", "C++11 keyword");
addKwd("alignof", "C++11 keyword");
addKwd("and", "C++11 keyword");
addKwd("and_eq", "C++11 keyword");
addKwd("asm", "C++ common word");
addKwd("atomic_cancel", "C++ TM TS keyword");
addKwd("atomic_commit", "C++ TM TS keyword");
addKwd("atomic_noexcept", "C++ TM TS keyword");
addKwd("auto", "C++ keyword");
addKwd("bit_vector", "C++ common word");
addKwd("bool", "C++ common word");
addKwd("bitand", "C++ keyword");
addKwd("bitor", "C++ keyword");
addKwd("bool", "C++ keyword");
addKwd("break", "C++ keyword");
addKwd("case", "C++ keyword");
addKwd("catch", "C++ keyword");
addKwd("cdecl", "C++ common word");
addKwd("char", "C++ keyword");
addKwd("char16_t", "C++11 keyword");
addKwd("char32_t", "C++11 keyword");
addKwd("class", "C++11 keyword");
addKwd("compl", "C++11 keyword");
addKwd("complex", "C++ common word");
addKwd("concept", "C++20 keyword");
addKwd("const", "C++ keyword");
addKwd("const_cast", "C++ common word");
addKwd("const_iterator", "C++ common word");
addKwd("const_reference ", "C++ common word");
addKwd("constexpr", "C++11 keyword");
addKwd("continue", "C++ keyword");
addKwd("decltype", "C++11 keyword");
addKwd("default", "C++ keyword");
addKwd("delete", "C++ keyword");
addKwd("deque", "C++ common word");
addKwd("false", "C++ common word");
addKwd("do", "C++ keyword");
addKwd("double", "C++ keyword");
addKwd("dynamic_cast", "C++ keyword");
addKwd("else", "C++ keyword");
addKwd("enum", "C++ keyword");
addKwd("explicit", "C++ keyword");
addKwd("export", "C++ keyword");
addKwd("extern", "C++ keyword");
addKwd("false", "C++ keyword");
addKwd("far", "C++ common word");
addKwd("float", "C++ keyword");
addKwd("for", "C++ keyword");
addKwd("friend", "C++ keyword");
addKwd("goto", "C++ keyword");
addKwd("huge", "C++ keyword");
addKwd("if", "C++ keyword");
addKwd("import", "C++ modules TS keyword");
addKwd("inline", "C++ keyword");
addKwd("int", "C++ keyword");
addKwd("interrupt", "C++ common word");
addKwd("iterator", "C++ common word");
addKwd("list", "C++ common word");
addKwd("long", "C++ keyword");
addKwd("map", "C++ common word");
addKwd("module", "C++ modules TS keyword");
addKwd("multimap", "C++ common word");
addKwd("multiset", "C++ common word");
addKwd("mutable", "C++ keyword");
addKwd("namespace", "C++ keyword");
addKwd("near", "C++ common word");
addKwd("new", "C++ keyword");
addKwd("noexcept", "C++11 keyword");
addKwd("not", "C++ keyword");
addKwd("not_eq", "C++ keyword");
addKwd("nullptr", "C++11 keyword");
addKwd("operator", "C++ keyword");
addKwd("or", "C++ keyword");
addKwd("or_eq", "C++ keyword");
addKwd("override", "C++ common word");
addKwd("pascal", "C++ keyword");
addKwd("private", "C++ keyword");
addKwd("protected", "C++ keyword");
addKwd("public", "C++ keyword");
addKwd("queue", "C++ common word");
addKwd("reference", "C++ common word");
addKwd("register", "C++ keyword");
addKwd("reinterpret_cast ", "C++ keyword");
addKwd("requires", "C++20 keyword");
addKwd("restrict", "C++ keyword");
addKwd("return", "C++ keyword");
addKwd("set", "C++ common word");
addKwd("short", "C++ keyword");
addKwd("signed", "C++ keyword");
addKwd("sizeof", "C++ keyword");
addKwd("stack", "C++ common word");
addKwd("true", "C++ common word");
addKwd("static", "C++ keyword");
addKwd("static_assert", "C++11 keyword");
addKwd("static_cast", "C++ keyword");
addKwd("struct", "C++ keyword");
addKwd("switch", "C++ keyword");
addKwd("synchronized", "C++ TM TS keyword");
addKwd("template", "C++ keyword");
addKwd("this", "C++ keyword");
addKwd("thread_local", "C++11 keyword");
addKwd("throw", "C++ keyword");
addKwd("transaction_safe", "C++ common word");
addKwd("transaction_safe_dynamic", "C++ common word");
addKwd("true", "C++ keyword");
addKwd("try", "C++ keyword");
addKwd("type_info", "C++ common word");
addKwd("typedef", "C++ keyword");
addKwd("typeid", "C++ keyword");
addKwd("typename", "C++ keyword");
addKwd("uint16_t", "C++ common word");
addKwd("uint32_t", "C++ common word");
addKwd("uint8_t", "C++ common word");
addKwd("union", "C++ keyword");
addKwd("unsigned", "C++ keyword");
addKwd("using", "C++ keyword");
addKwd("vector", "C++ common word");
addKwd("virtual", "C++ keyword");
addKwd("void", "C++ keyword");
addKwd("volatile", "C++ keyword");
addKwd("wchar_t", "C++ keyword");
addKwd("while", "C++ keyword");
addKwd("xor", "C++ keyword");
addKwd("xor_eq", "C++ keyword");
// This conflicts with header functions, so is ignored
//dKwd("final", "C++11 keyword"); // Member function or class head, otherwise not reserved
// SystemC
addKwd("sc_clock", "SystemC common word");
addKwd("sc_in", "SystemC common word");
@@ -123,4 +185,3 @@ class V3LanguageWords {
#endif // Guard
+1 -1
View File
@@ -515,5 +515,5 @@ void V3Life::lifeAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
LifeState state;
LifeTopVisitor visitor (nodep, &state);
V3Global::dumpCheckGlobalTree("life.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("life", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+1 -1
View File
@@ -193,5 +193,5 @@ void V3LifePost::lifepostAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
// Mark redundant AssignPost
LifePostDlyVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("life_post.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("life_post", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+2 -1
View File
@@ -335,7 +335,8 @@ private:
UINFO(9," need .* PORT "<<portp<<endl);
// Create any not already connected
AstPin* newp = new AstPin(nodep->fileline(),0,portp->name(),
new AstVarRef(nodep->fileline(),portp->name(),false));
new AstParseRef(nodep->fileline(),
AstParseRefExp::PX_TEXT, portp->name(), NULL, NULL));
newp->svImplicit(true);
nodep->addPinsp(newp);
} else { // warn on the CELL that needs it, not the port
+43 -11
View File
@@ -161,7 +161,7 @@ public:
if (!diddump && v3Global.opt.dumpTree()) {
diddump = true;
dump("linkdot-preerr",true);
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("linkdot-preerr.tree"));
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("linkdot-preerr"));
}
}
@@ -445,6 +445,10 @@ public:
<<") <- se"<<srcp<<" "<<srcp->nodep()<<endl);
// srcp should be an interface reference pointing to the interface we want to import
lhsp->importFromIface(symsp(), srcp);
// Allow access to objects not permissible to be listed in a modport
if (srcp->nodep()->castModport()) {
lhsp->importFromIface(symsp(), srcp->parentp(), true);
}
}
//m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file
}
@@ -839,7 +843,7 @@ class LinkDotFindVisitor : public AstNVisitor {
virtual void visit(AstNodeFTask* nodep) {
// NodeTask: Remember its name for later resolution
UINFO(5," "<<nodep<<endl);
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Function/Task not under module??\n");
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Function/Task not under module?");
// Remember the existing symbol table scope
VSymEnt* oldCurSymp = m_curSymp;
{
@@ -873,7 +877,7 @@ class LinkDotFindVisitor : public AstNVisitor {
}
virtual void visit(AstVar* nodep) {
// Var: Remember its name for later resolution
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Var not under module??\n");
if (!m_curSymp || !m_modSymp) nodep->v3fatalSrc("Var not under module?");
nodep->iterateChildren(*this);
if (!m_statep->forScopeCreation()) {
// Find under either a task or the module's vars
@@ -957,12 +961,12 @@ class LinkDotFindVisitor : public AstNVisitor {
}
virtual void visit(AstTypedef* nodep) {
// Remember its name for later resolution
if (!m_curSymp) nodep->v3fatalSrc("Typedef not under module??\n");
if (!m_curSymp) nodep->v3fatalSrc("Typedef not under module?");
nodep->iterateChildren(*this);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
}
virtual void visit(AstParamTypeDType* nodep) {
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module??\n");
if (!m_curSymp) nodep->v3fatalSrc("Parameter type not under module?");
nodep->iterateChildren(*this);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
}
@@ -1013,6 +1017,24 @@ class LinkDotFindVisitor : public AstNVisitor {
UINFO(9," Link Done: "<<nodep<<endl);
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstPackageExport* nodep) {
UINFO(9," Link: "<<nodep<<endl);
VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep());
if (nodep->name()!="*") {
VSymEnt* impp = srcp->findIdFlat(nodep->name());
if (!impp) {
nodep->v3error("Export object not found: "<<nodep->packagep()->prettyName()<<"::"<<nodep->prettyName());
}
}
m_curSymp->exportFromPackage(m_statep->symsp(), srcp, nodep->name());
UINFO(9," Link Done: "<<nodep<<endl);
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstPackageExportStarStar* nodep) {
UINFO(2," Link: "<<nodep<<endl);
m_curSymp->exportStarStar(m_statep->symsp());
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstNode* nodep) {
// Default: Just iterate
@@ -1593,7 +1615,7 @@ private:
checkNoDot(nodep);
nodep->iterateChildren(*this);
if (!nodep->modVarp()) {
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?\n");
if (!m_pinSymp) nodep->v3fatalSrc("Pin not under cell?");
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
const char* whatp = nodep->param() ? "parameter pin" : "pin";
if (!foundp) {
@@ -1861,7 +1883,7 @@ private:
}
//
if (!ok) {
//Cells/interfaces can't be implicit
// Cells/interfaces can't be implicit
bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false;
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell);
bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name()));
@@ -2212,6 +2234,16 @@ private:
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstPackageExport* nodep) {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstPackageExportStarStar* nodep) {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstCellRef* nodep) {
UINFO(5," AstCellRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
nodep->iterateChildren(*this);
@@ -2254,21 +2286,21 @@ public:
int V3LinkDot::debug() { return LinkDotState::debug(); }
void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) {
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree"));
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot"));
LinkDotState state (rootp, step);
LinkDotFindVisitor visitor(rootp,&state);
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree"));
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find"));
if (step == LDS_PRIMARY || step == LDS_PARAMED) {
// Initial link stage, resolve parameters
LinkDotParamVisitor visitors(rootp,&state);
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree"));
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param"));
}
else if (step == LDS_ARRAYED) {}
else if (step == LDS_SCOPED) {
// Well after the initial link when we're ready to operate on the flat design,
// process AstScope's. This needs to be separate pass after whole hierarchy graph created.
LinkDotScopeVisitor visitors(rootp,&state);
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree"));
if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped"));
}
else v3fatalSrc("Bad case");
state.dump();
+4 -4
View File
@@ -36,19 +36,19 @@ private:
public:
static void linkDotPrimary(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PRIMARY);
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
static void linkDotParamed(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PARAMED);
V3Global::dumpCheckGlobalTree("paramlink.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("paramlink", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
static void linkDotArrayed(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_ARRAYED);
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
static void linkDotScope(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_SCOPED);
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
};
+1 -1
View File
@@ -263,5 +263,5 @@ public:
void V3LinkJump::linkJump(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
LinkJumpVisitor bvisitor (nodep);
V3Global::dumpCheckGlobalTree("link.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("link", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+4 -2
View File
@@ -174,8 +174,10 @@ private:
virtual void visit(AstValuePlusArgs* nodep) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = false;
nodep->searchp()->iterateAndNext(*this);
m_setRefLvalue = true;
nodep->exprsp()->iterateAndNext(*this);
nodep->outp()->iterateAndNext(*this);
}
m_setRefLvalue = last_setRefLvalue;
}
@@ -277,7 +279,7 @@ public:
void V3LinkLValue::linkLValue(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkLValueVisitor visitor(rootp, false);
V3Global::dumpCheckGlobalTree("linklvalue.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
void V3LinkLValue::linkLValueSet(AstNode* nodep) {
// Called by later link functions when it is known a node needs
+1 -1
View File
@@ -80,7 +80,7 @@ void V3LinkLevel::modSortByLevel() {
v3Global.rootp()->addModulep(nodep);
}
UINFO(9,"modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666
V3Global::dumpCheckGlobalTree("cells.tree", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
//######################################################################
+4 -2
View File
@@ -131,7 +131,9 @@ private:
AstNode* valuep = NULL;
if (nodep->valuep()) valuep = new AstAdd(nodep->fileline(), nodep->valuep()->cloneTree(true),
new AstConst(nodep->fileline(), AstConst::Unsized32(), offset_from_init));
addp = addp->addNextNull(new AstEnumItem(nodep->fileline(), name, NULL, valuep));
AstNode* newp = new AstEnumItem(nodep->fileline(), name, NULL, valuep);
if (addp) addp = addp->addNextNull(newp);
else addp = newp;
}
nodep->replaceWith(addp);
nodep->deleteTree();
@@ -429,5 +431,5 @@ public:
void V3LinkParse::linkParse(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkParseVisitor visitor(rootp);
V3Global::dumpCheckGlobalTree("linkparse.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("linkparse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+3 -3
View File
@@ -236,12 +236,12 @@ private:
virtual void visit(AstPragma* nodep) {
if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) {
if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module\n");
if (!m_modp) nodep->v3fatalSrc("PUBLIC_MODULE not under a module");
m_modp->modPublic(true);
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
}
else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) {
if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task\n");
if (!m_ftaskp) nodep->v3fatalSrc("PUBLIC_TASK not under a task");
m_ftaskp->taskPublic(true);
m_modp->modPublic(true); // Need to get to the task...
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
@@ -516,5 +516,5 @@ void V3LinkResolve::linkResolve(AstNetlist* rootp) {
UINFO(4,__FUNCTION__<<": "<<endl);
LinkResolveVisitor visitor(rootp);
LinkBotupVisitor visitorb(rootp);
V3Global::dumpCheckGlobalTree("linkresolve.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("linkresolve", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+1 -1
View File
@@ -250,5 +250,5 @@ void V3Localize::localizeAll(AstNetlist* nodep) {
LocalizeVisitor visitor (nodep);
// Fix up hiernames
LocalizeDehierVisitor dvisitor (nodep);
V3Global::dumpCheckGlobalTree("localize.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+1 -1
View File
@@ -149,5 +149,5 @@ public:
void V3Name::nameAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
NameVisitor visitor (nodep);
V3Global::dumpCheckGlobalTree("name.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}
+34 -11
View File
@@ -48,7 +48,7 @@ V3Number::V3Number(VerilogStringLiteral, FileLine* fileline, const string& str)
}
}
}
opCleanThis();
opCleanThis(true);
}
V3Number::V3Number (FileLine* fileline, const char* sourcep) {
@@ -71,7 +71,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
if (*cp != '_') *wp++ = *cp;
}
*wp++ = '\0';
while (*cp && *cp == '_') cp++;
while (*cp == '_') cp++;
if (*cp && tolower(*cp)=='s') {
cp++; isSigned(true);
}
@@ -139,6 +139,12 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
this->opAdd(product,addend);
if (product.bitsValue(width(), 4)) { // Overflowed
m_fileline->v3error("Too many digits for "<<width()<<" bit number: "<<sourcep);
if (!m_sized) {
static int warned = false;
if (!warned++) {
m_fileline->v3error("As that number was unsized ('d...) it is limited to 32 bits (IEEE 2012 5.7.1)");
}
}
while (*(cp+1)) cp++; // Skip ahead so don't get multiple warnings
}
}
@@ -254,7 +260,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
setBit(obit, bitIs(obit-1));
obit++;
}
opCleanThis();
opCleanThis(true);
//printf("Dump \"%s\" CP \"%s\" B '%c' %d W %d\n", sourcep, value_startp, base, width(), m_value[0]);
}
@@ -446,7 +452,7 @@ bool V3Number::displayedFmtLegal(char format) {
case 's': return true;
case 't': return true;
case 'u': return true; // Packed 2-state
case 'v': return true; // Strength
case 'v': return true; // Strength
case 'x': return true;
case 'z': return true; // Packed 4-state
case '@': return true; // Packed string
@@ -1217,6 +1223,9 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
if (rhs.bitIs1(bit)) return *this; // shift of over 2^32 must be zero
}
uint32_t rhsval = rhs.toUInt();
if (rhsval < (uint32_t)lhs.width()) {
for (int bit=0; bit<this->width(); bit++) {
@@ -1232,6 +1241,13 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_
// We presume it is signed; as that's V3Width's job to convert to opShiftR
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs(lbits-1)); // 0/1/X/Z
}
if (rhs.bitIs1(lbits-1)) setAllBits1(); // -1 else 0
return *this; // shift of over 2^32 must be -1/0
}
uint32_t rhsval = rhs.toUInt();
if (rhsval < (uint32_t)lhs.width()) {
for (int bit=0; bit<this->width(); bit++) {
@@ -1239,7 +1255,7 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_
}
} else {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs(lbits-1));
setBit(bit,lhs.bitIs(lbits-1)); // 0/1/X/Z
}
}
return *this;
@@ -1249,6 +1265,9 @@ V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
if (rhs.bitIs1(bit)) return *this; // shift of over 2^32 must be zero
}
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) {
@@ -1518,8 +1537,6 @@ V3Number& V3Number::opPow (const V3Number& lhs, const V3Number& rhs, bool lsign,
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setQuad(1); // Overrides lhs 0 -> return 0
// We may want to special case when the lhs is 2, so we can get larger outputs
if (lhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
if (rhs.width()>64) m_fileline->v3fatalSrc("Unsupported: Large >64bit ** power operator not implemented yet: "<<*this);
if (rsign && rhs.isNegative()) {
if (lhs.isEqZero()) return setAllBitsXRemoved();
else if (lhs.isEqOne()) return setQuad(1);
@@ -1587,10 +1604,16 @@ V3Number& V3Number::opClean (const V3Number& lhs, uint32_t bits) {
return opSel(lhs, bits-1, 0);
}
void V3Number::opCleanThis() {
// Clean in place number
m_value[words()-1] &= hiWordMask();
m_valueX[words()-1] &= hiWordMask();
void V3Number::opCleanThis(bool warnOnTruncation) {
// Clean MSB of number
uint32_t newValueMsb = m_value[words()-1] & hiWordMask();
uint32_t newValueXMsb = m_valueX[words()-1] & hiWordMask();
if (warnOnTruncation && (newValueMsb != m_value[words()-1] || newValueXMsb != m_valueX[words()-1])) {
// Displaying in decimal avoids hiWordMask truncation
m_fileline->v3warn(WIDTH,"Value too large for "<<width()<<" bit number: "<<displayed(m_fileline, "%d"));
}
m_value[words()-1] = newValueMsb;
m_valueX[words()-1] = newValueXMsb;
}
V3Number& V3Number::opSel (const V3Number& lhs, const V3Number& msb, const V3Number& lsb) {
+2 -2
View File
@@ -45,7 +45,7 @@ class V3Number {
// METHODS
V3Number& setSingleBits(char value);
V3Number& setString(const string& str) { m_isString=true; m_stringVal=str; return *this; }
void opCleanThis();
void opCleanThis(bool warnOnTruncation = false);
public:
FileLine* fileline() const { return m_fileline; }
void fileline(FileLine* fl) { m_fileline=fl; }
@@ -327,6 +327,6 @@ public:
V3Number& opLtN (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteN (const V3Number& lhs, const V3Number& rhs);
};
inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); }
inline ostream& operator<<(ostream& os, const V3Number& rhs) { return os<<rhs.ascii(); }
#endif // Guard
+2 -2
View File
@@ -32,7 +32,7 @@
#include <algorithm>
#include "V3Number.h"
void test(string lhss, string op, string rhss, string exps) {
void test(const string& lhss, const string& op, const string& rhss, const string& exps) {
char* l1 = strdup(lhss.c_str());
char* r1 = strdup(rhss.c_str());
char* e1 = strdup(exps.c_str());
@@ -84,7 +84,7 @@ void test(string lhss, string op, string rhss, string exps) {
V3Number ok (new FileLine("ck",__LINE__), 1);
ok.opCaseEq(expnum,gotnum);
if (ok.toUInt()!=1) {
v3fatalSrc("%Error:Test FAILED\n");
v3fatalSrc("%Error:Test FAILED");
}
}
+7 -58
View File
@@ -491,52 +491,6 @@ string V3Options::getenvSYSTEMC_LIBDIR() {
return var;
}
string V3Options::getenvSYSTEMPERL() {
// Must be careful to set SYSTEMPERL_INCLUDE first else we'd setenv
// SYSTEMPERL which would override a DEFENVed SYSTEMPERL_INCLUDE.
V3Options::getenvSYSTEMPERL_INCLUDE();
return V3Options::getenvSYSTEMPERLGuts();
}
string V3Options::getenvSYSTEMPERLGuts() {
// Get SYSTEMPERL when SYSTEMPERL_INCLUDE has already been tested
string var = V3Os::getenvStr("SYSTEMPERL","");
if (var == "" && string(DEFENV_SYSTEMPERL) != "") {
var = DEFENV_SYSTEMPERL;
V3Os::setenvStr("SYSTEMPERL", var, "Hardcoded at build time");
}
return var;
}
string V3Options::getenvSYSTEMPERL_INCLUDE() {
string var = V3Os::getenvStr("SYSTEMPERL_INCLUDE","");
if (var == "") {
string sp_src = V3Options::getenvSYSTEMPERLGuts()+"/src";
if (V3Options::fileStatNormal(sp_src+"/systemperl.h")) {
var = sp_src;
V3Os::setenvStr ("SYSTEMPERL_INCLUDE", var, "From $SYSTEMPERL/src");
} else if (string(DEFENV_SYSTEMPERL_INCLUDE) != "") {
// Note if SYSTEMPERL is DEFENVed, then SYSTEMPERL_INCLUDE is also DEFENVed
// So we don't need to sweat testing DEFENV_SYSTEMPERL also
var = DEFENV_SYSTEMPERL_INCLUDE;
V3Os::setenvStr("SYSTEMPERL_INCLUDE", var, "Hardcoded at build time");
}
}
// Only correct or check it if we really need the value
if (v3Global.opt.usingSystemPerlLibs()) {
// We warn about $SYSTEMPERL instead of _INCLUDE since that's more likely
// what users will want to set.
if (var == "") {
v3fatal("Need $SYSTEMPERL and $SYSTEMPERL_INCLUDE in environment for --sp or --coverage\n"
"Probably System-Perl isn't installed, see http://www.veripool.org/systemperl\n");
}
else if (var != "" && !V3Options::fileStatNormal(var+"/systemperl.h")) {
v3fatal("Neither $SYSTEMPERL nor $SYSTEMPERL_INCLUDE environment vars to point to System-Perl kit: "<<var<<endl);
}
}
return var;
}
string V3Options::getenvVERILATOR_ROOT() {
string var = V3Os::getenvStr("VERILATOR_ROOT","");
if (var == "" && string(DEFENV_VERILATOR_ROOT) != "") {
@@ -559,8 +513,9 @@ string V3Options::version() {
}
void V3Options::throwSigsegv() {
// cppcheck-suppress nullPointer
char* zp=NULL; *zp=0;
#if !(defined(VL_CPPCHECK) || defined(__clang_analyzer__))
char* zp=NULL; *zp=0; // Intentional core dump, ignore warnings here
#endif
}
//######################################################################
@@ -607,7 +562,7 @@ bool V3Options::onoff(const char* sw, const char* arg, bool& flag) {
// if sw=="-no-arg", then return true (found it), and flag=false
// if sw=="-noarg", then return true (found it), and flag=false
// else return false
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash.\n");
if (arg[0]!='-') v3fatalSrc("OnOff switches must have leading dash");
if (0==strcmp(sw,arg)) { flag=true; return true; }
else if (0==strncmp(sw,"-no",3) && (0==strcmp(sw+3,arg+1))) { flag=false; return true; }
else if (0==strncmp(sw,"-no-",4) && (0==strcmp(sw+4,arg+1))) { flag=false; return true; }
@@ -682,7 +637,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-autoflush", flag/*ref*/) ) { m_autoflush = flag; }
else if ( onoff (sw, "-bbox-sys", flag/*ref*/) ) { m_bboxSys = flag; }
else if ( onoff (sw, "-bbox-unsup", flag/*ref*/) ) { m_bboxUnsup = flag; }
else if ( !strcmp (sw, "-cc") ) { m_outFormatOk = true; m_systemC = false; m_systemPerl = false; }
else if ( !strcmp (sw, "-cc") ) { m_outFormatOk = true; m_systemC = false; }
else if ( onoff (sw, "-cdc", flag/*ref*/) ) { m_cdc = flag; }
else if ( onoff (sw, "-coverage", flag/*ref*/) ) { coverage(flag); }
else if ( onoff (sw, "-coverage-line", flag/*ref*/) ){ m_coverageLine = flag; }
@@ -713,9 +668,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-report-unoptflat", flag/*ref*/) ) { m_reportUnoptflat = flag; }
else if ( onoff (sw, "-relative-includes", flag/*ref*/) ) { m_relativeIncludes = flag; }
else if ( onoff (sw, "-savable", flag/*ref*/) ) { m_savable = flag; }
else if ( !strcmp (sw, "-sc") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = false; }
else if ( !strcmp (sw, "-sc") ) { m_outFormatOk = true; m_systemC = true; }
else if ( onoff (sw, "-skip-identical", flag/*ref*/) ) { m_skipIdentical = flag; }
else if ( !strcmp (sw, "-sp-deprecated") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = true; } // Undocumented, old
else if ( onoff (sw, "-stats", flag/*ref*/) ) { m_stats = flag; }
else if ( onoff (sw, "-stats-vars", flag/*ref*/) ) { m_statsVars = flag; m_stats |= flag; }
else if ( !strcmp (sw, "-sv") ) { m_defaultLanguage = V3LangCode::L1800_2005; }
@@ -845,7 +799,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
}
else if ( !strcmp (sw, "-Mdir") && (i+1)<argc ) {
shift; m_makeDir = argv[i];
addIncDirFallback (string (m_makeDir)); // Need to find generated files there too
addIncDirFallback (m_makeDir); // Need to find generated files there too
}
else if ( !strcmp (sw, "-o") && (i+1)<argc ) {
shift; m_exeName = argv[i];
@@ -1178,8 +1132,6 @@ void V3Options::showVersion(bool verbose) {
cout << " SYSTEMC_ARCH = " << DEFENV_SYSTEMC_ARCH<<endl;
cout << " SYSTEMC_INCLUDE = " << DEFENV_SYSTEMC_INCLUDE<<endl;
cout << " SYSTEMC_LIBDIR = " << DEFENV_SYSTEMC_LIBDIR<<endl;
cout << " SYSTEMPERL = " << DEFENV_SYSTEMPERL<<endl;
cout << " SYSTEMPERL_INCLUDE = " << DEFENV_SYSTEMPERL_INCLUDE<<endl;
cout << " VERILATOR_ROOT = " << DEFENV_VERILATOR_ROOT<<endl;
cout <<endl;
@@ -1189,8 +1141,6 @@ void V3Options::showVersion(bool verbose) {
cout << " SYSTEMC_ARCH = " << V3Os::getenvStr("SYSTEMC_ARCH","")<<endl;
cout << " SYSTEMC_INCLUDE = " << V3Os::getenvStr("SYSTEMC_INCLUDE","")<<endl;
cout << " SYSTEMC_LIBDIR = " << V3Os::getenvStr("SYSTEMC_LIBDIR","")<<endl;
cout << " SYSTEMPERL = " << V3Os::getenvStr("SYSTEMPERL","")<<endl;
cout << " SYSTEMPERL_INCLUDE = " << V3Os::getenvStr("SYSTEMPERL_INCLUDE","")<<endl;
cout << " VERILATOR_ROOT = " << V3Os::getenvStr("VERILATOR_ROOT","")<<endl;
cout << " VERILATOR_BIN = " << V3Os::getenvStr("VERILATOR_BIN","")<<endl; // wrapper uses this
}
@@ -1234,7 +1184,6 @@ V3Options::V3Options() {
m_stats = false;
m_statsVars = false;
m_systemC = false;
m_systemPerl = false;
m_trace = false;
m_traceDups = false;
m_traceParams = true;
+3 -10
View File
@@ -93,7 +93,6 @@ class V3Options {
bool m_savable; // main switch: --savable
bool m_systemC; // main switch: --sc: System C instead of simple C++
bool m_skipIdentical;// main switch: --skip-identical
bool m_systemPerl; // main switch: --sp: System Perl instead of SystemC (m_systemC also set)
bool m_stats; // main switch: --stats
bool m_statsVars; // main switch: --stats-vars
bool m_trace; // main switch: --trace
@@ -146,7 +145,7 @@ class V3Options {
bool m_oCombine; // main switch: -Ob: common icode packing
bool m_oConst; // main switch: -Oc: constant folding
bool m_oDedupe; // main switch: -Od: logic deduplication
bool m_oAssemble; // main switch: -Om: assign assemble
bool m_oAssemble; // main switch: -Om: assign assemble
bool m_oExpand; // main switch: -Ox: expansion of C macros
bool m_oFlopGater; // main switch: -Of: flop gater detection
bool m_oGate; // main switch: -Og: gate wire elimination
@@ -179,8 +178,6 @@ class V3Options {
bool parseLangExt(const char* swp, const char* langswp, const V3LangCode& lc);
string filePathCheckOneDir(const string& modname, const string& dirname);
static string getenvSYSTEMPERLGuts();
V3Options(const V3Options&); ///< N/A, no copy constructor
public:
@@ -212,9 +209,7 @@ class V3Options {
string bin() const { return m_bin; }
string flags() const { return m_flags; }
bool systemC() const { return m_systemC; }
bool systemPerl() const { return m_systemPerl; }
bool usingSystemCLibs() const { return !lintOnly() && (systemPerl() || systemC()); }
bool usingSystemPerlLibs() const { return !lintOnly() && systemPerl(); }
bool usingSystemCLibs() const { return !lintOnly() && systemC(); }
bool savable() const { return m_savable; }
bool skipIdentical() const { return m_skipIdentical; }
bool stats() const { return m_stats; }
@@ -319,7 +314,7 @@ class V3Options {
bool oTable() const { return m_oTable; }
// METHODS (uses above)
string traceClassBase() const { return systemPerl() ? "SpTraceVcd" : "VerilatedVcd"; }
string traceClassBase() const { return "VerilatedVcd"; }
// METHODS (from main)
static string version();
@@ -339,8 +334,6 @@ class V3Options {
static string getenvSYSTEMC_ARCH();
static string getenvSYSTEMC_INCLUDE();
static string getenvSYSTEMC_LIBDIR();
static string getenvSYSTEMPERL();
static string getenvSYSTEMPERL_INCLUDE();
static string getenvVERILATOR_ROOT();
// METHODS (file utilities using these options)
+10 -52
View File
@@ -194,7 +194,7 @@ public:
// METHODS
OrderVarVertex* newVarUserVertex(V3Graph* graphp, AstScope* scopep,
AstVarScope* varscp, WhichVertex type, bool* createdp=NULL) {
if (type>=WV_MAX) varscp->v3fatalSrc("Bad Case\n");
if (type>=WV_MAX) varscp->v3fatalSrc("Bad case");
OrderVarVertex* vertexp = m_vertexp[type];
if (!vertexp) {
UINFO(6,"New vertex "<<varscp<<endl);
@@ -205,7 +205,7 @@ public:
case WV_PORD: vertexp = new OrderVarPordVertex (graphp, scopep, varscp); break;
case WV_POST: vertexp = new OrderVarPostVertex (graphp, scopep, varscp); break;
case WV_SETL: vertexp = new OrderVarSettleVertex(graphp, scopep, varscp); break;
default: varscp->v3fatalSrc("Bad Case\n");
default: varscp->v3fatalSrc("Bad case");
}
m_vertexp[type] = vertexp;
} else {
@@ -242,7 +242,7 @@ struct OrderVarFanoutCmp {
};
//######################################################################
// The class is used for propagating the clocker attribute for further
// The class is used for propagating the clocker attribute for further
// avoiding marking clock signals as circular.
// Transformation:
// while (newClockerMarked)
@@ -251,7 +251,7 @@ struct OrderVarFanoutCmp {
// mark LHS as clocker as well.
// newClockerMarked = true;
//
// In addition it also check whether clock and data signals are mixed, and
// In addition it also check whether clock and data signals are mixed, and
// produce a CLKDATA warning if so.
//
class OrderClkMarkVisitor : public AstNVisitor {
@@ -465,9 +465,6 @@ private:
OrderLogicVertex* m_activeSenVxp; // Sensitivity vertex
deque<OrderUser*> m_orderUserps; // All created OrderUser's for later deletion.
// STATE... for inside process
OrderLoopId m_loopIdMax; // Maximum BeginLoop id number assigned
vector<OrderLoopEndVertex*> m_pmlLoopEndps; // processInsLoop: End vertex for each color
vector<OrderLoopBeginVertex*> m_pomLoopMoveps;// processMoveLoop: Loops next nodes are under
AstCFunc* m_pomNewFuncp; // Current function being created
int m_pomNewStmts; // Statements in function being created
V3Graph m_pomGraph; // Graph of logic elements to move
@@ -565,10 +562,6 @@ private:
void processMoveReadyOne(OrderMoveVertex* vertexp);
void processMoveDoneOne(OrderMoveVertex* vertexp);
void processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* domScopep, int level);
void processMoveLoopPush(OrderLoopBeginVertex* beginp);
void processMoveLoopPop(OrderLoopBeginVertex* beginp);
void processMoveLoopStmt(AstNode* newSubnodep);
OrderLoopId processMoveLoopCurrent();
string cfuncName(AstNodeModule* modp, AstSenTree* domainp, AstScope* scopep, AstNode* forWhatp) {
modp->user3Inc();
@@ -806,15 +799,15 @@ private:
virtual void visit(AstNodeVarRef* nodep) {
if (m_scopep) {
AstVarScope* varscp = nodep->varScopep();
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
if (m_inSenTree) {
// Add CLOCK dependency... This is a root of the tree we'll trace
if (nodep->lvalue()) nodep->v3fatalSrc("How can a sensitivity be setting a var?\n");
if (nodep->lvalue()) nodep->v3fatalSrc("How can a sensitivity be setting a var?");
OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_STD);
varVxp->isClock(true);
new OrderEdge(&m_graph, varVxp, m_activeSenVxp, WEIGHT_MEDIUM);
} else {
if (!m_logicVxp) nodep->v3fatalSrc("Var ref not under a logic block\n");
if (!m_logicVxp) nodep->v3fatalSrc("Var ref not under a logic block");
// What new directions is this used
// We don't want to add extra edges if the logic block has many usages of same var
bool gen = false;
@@ -1016,7 +1009,6 @@ public:
m_activeSenVxp = NULL;
m_logicVxp = NULL;
m_pomNewFuncp = NULL;
m_loopIdMax = LOOPID_FIRST;
m_pomNewStmts = 0;
if (debug()) m_graph.debug(5); // 3 is default if global debug; we want acyc debugging
}
@@ -1518,7 +1510,7 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
scopep->addActivep(m_pomNewFuncp);
// Where will we be adding the call?
AstActive* callunderp = new AstActive(nodep->fileline(), name, domainp);
processMoveLoopStmt(callunderp);
m_scopetopp->addActivep(callunderp);
// Add a top call to it
AstCCall* callp = new AstCCall(nodep->fileline(), m_pomNewFuncp);
callp->argTypes("vlSymsp");
@@ -1543,40 +1535,6 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
processMoveDoneOne (vertexp);
}
inline void OrderVisitor::processMoveLoopPush(OrderLoopBeginVertex* beginp) {
UINFO(6," LoopPush "<<beginp<<endl);
m_pomLoopMoveps.push_back(beginp);
}
inline void OrderVisitor::processMoveLoopPop(OrderLoopBeginVertex* beginp) {
UINFO(6," LoopPop "<<beginp<<endl);
if (m_pomLoopMoveps.empty()) beginp->nodep()->v3fatalSrc("processMoveLoopPop with no push'ed loops");
OrderLoopBeginVertex* topBeginp = m_pomLoopMoveps.back();
if (topBeginp != beginp) beginp->nodep()->v3fatalSrc("processMoveLoopPop had different vertex then one expected, got="<<topBeginp<<" exp="<<beginp<<endl);
m_pomLoopMoveps.pop_back();
}
inline void OrderVisitor::processMoveLoopStmt(AstNode* newSubnodep) {
if (m_pomLoopMoveps.empty()) {
// Not in any loops, statements go into main body
m_scopetopp->addActivep(newSubnodep);
} else {
// In a loop, put statements under appropriate loop body
OrderLoopBeginVertex* topBeginp = m_pomLoopMoveps.back();
topBeginp->untilp()->addBodysp(newSubnodep);
}
}
inline OrderLoopId OrderVisitor::processMoveLoopCurrent() {
// Return loopID we're currently processing
if (m_pomLoopMoveps.empty()) {
return LOOPID_NOTLOOPED;
} else {
OrderLoopBeginVertex* topBeginp = m_pomLoopMoveps.back();
return topBeginp->loopId(); // Not inLoop, the begin is in the upper subloop.
}
}
inline void OrderMoveDomScope::ready(OrderVisitor* ovp) { // Check the domScope is on ready list, add if not
if (!m_onReadyList) {
m_onReadyList = true;
@@ -1645,7 +1603,7 @@ void OrderVisitor::process() {
// Dump data
m_graph.dumpDotFilePrefixed("orderg_done");
if (0 && debug()) {
string dfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_INT_order.tree";
string dfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_INT_order";
const VL_UNIQUE_PTR<ofstream> logp (V3File::new_ofstream(dfilename));
if (logp->fail()) v3fatalSrc("Can't write "<<dfilename);
m_graph.dump(*logp);
@@ -1660,5 +1618,5 @@ void V3Order::orderAll(AstNetlist* nodep) {
OrderClkMarkVisitor markVisitor(nodep);
OrderVisitor visitor;
visitor.main(nodep);
V3Global::dumpCheckGlobalTree("order.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
V3Global::dumpCheckGlobalTree("order", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
+35 -1
View File
@@ -22,6 +22,7 @@
#include "verilatedos.h"
#include <cstdarg>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
@@ -68,7 +69,7 @@ void V3Os::setenvStr(const string& envvar, const string& value, const string& wh
}
//######################################################################
// Generic filename utilities
// Generic filename utilities
string V3Os::filenameFromDirBase (const string& dir, const string& basename) {
// Don't return ./{filename} because if filename was absolute, that makes it relative
@@ -186,3 +187,36 @@ void V3Os::unlinkRegexp(const string& dir, const string& regexp) {
closedir(dirp);
}
}
//######################################################################
// METHODS (performance)
uint64_t V3Os::timeUsecs() {
#if defined(_WIN32) || defined(__MINGW32__)
return 0;
#else
timeval tv;
if (gettimeofday(&tv, NULL) < 0) return 0;
return static_cast<uint64_t>(tv.tv_sec)*1000000 + tv.tv_usec;
#endif
}
uint64_t V3Os::memUsageBytes() {
#if defined(_WIN32) || defined(__MINGW32__)
return 0;
#else
// Highly unportable. Sorry
const char* statmFilename = "/proc/self/statm";
FILE* fp = fopen(statmFilename,"r");
if (!fp) {
return 0;
}
uint64_t size, resident, share, text, lib, data, dt; // All in pages
if (7 != fscanf(fp, "%" VL_PRI64 "d %" VL_PRI64 "d %" VL_PRI64 "d %"
VL_PRI64 "d %" VL_PRI64 "d %" VL_PRI64 "d %" VL_PRI64 "d",
&size, &resident, &share, &text, &lib, &data, &dt)) {
return 0;
}
return (text + data) * getpagesize();
#endif
}
+4
View File
@@ -47,6 +47,10 @@ public:
// METHODS (directory utilities)
static void createDir(const string& dirname);
static void unlinkRegexp(const string& dir, const string& regexp);
// METHODS (performance)
static uint64_t timeUsecs(); ///< Return wall time since epoch in microseconds, or 0 if not implemented
static uint64_t memUsageBytes(); ///< Return memory usage in bytes, or 0 if not implemented
};
#endif // Guard
+63 -5
View File
@@ -204,7 +204,7 @@ private:
pinp->modPTypep(cloneiter->second->castParamTypeDType());
}
else {
pinp->v3fatalSrc("Not linked?\n");
pinp->v3fatalSrc("Not linked?");
}
}
}
@@ -283,7 +283,59 @@ private:
virtual void visit(AstVarRef* nodep) {
if (nodep->varp()) nodep->varp()->iterate(*this);
}
bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) {
for (; candp; candp = candp->nextp()) {
if (nodep->name() == candp->name()) {
if (AstVar* varp = candp->castVar()) {
UINFO(9,"Found interface parameter: "<<varp<<endl);
nodep->varp(varp);
return true;
} else if (AstPin* pinp = candp->castPin()) {
UINFO(9,"Found interface parameter: "<<pinp<<endl);
if (!pinp->exprp()) pinp->v3fatalSrc("Interface parameter pin missing expression");
nodep->replaceWith(pinp->exprp()->cloneTree(false)); VL_DANGLING(nodep);
return true;
}
}
}
return false;
}
virtual void visit(AstVarXRef* nodep) {
// Check to see if the scope is just an interface because interfaces are special
string dotted = nodep->dotted();
if (!dotted.empty() && nodep->varp() && nodep->varp()->isParam()) {
AstNode* backp = nodep;
while ((backp = backp->backp())) {
if (backp->castNodeModule()) {
UINFO(9,"Hit module boundary, done looking for interface"<<endl);
break;
}
if (backp->castVar()
&& backp->castVar()->isIfaceRef()
&& backp->castVar()->childDTypep()
&& backp->castVar()->childDTypep()->castIfaceRefDType()) {
AstIfaceRefDType* ifacerefp = backp->castVar()->childDTypep()->castIfaceRefDType();
// Interfaces passed in on the port map have ifaces
if (AstIface* ifacep = ifacerefp->ifacep()) {
if (dotted == backp->name()) {
UINFO(9,"Iface matching scope: "<<ifacep<<endl);
if (ifaceParamReplace(nodep, ifacep->stmtsp())) {
return;
}
}
}
// Interfaces declared in this module have cells
else if (AstCell* cellp = ifacerefp->cellp()) {
if (dotted == cellp->name()) {
UINFO(9,"Iface matching scope: "<<cellp<<endl);
if (ifaceParamReplace(nodep, cellp->paramsp())) {
return;
}
}
}
}
}
}
nodep->varp(NULL); // Needs relink, as may remove pointed-to var
}
@@ -493,6 +545,12 @@ void ParamVisitor::visitCell(AstCell* nodep) {
if (AstVar* modvarp = pinp->modVarp()) {
if (!modvarp->isGParam()) {
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->prettyName()<<" of "<<nodep->prettyName());
} else if (pinp->exprp()->castInitArray()
&& modvarp->subDTypep()->castUnpackArrayDType()) {
// Array assigned to array
AstNode* exprp = pinp->exprp();
longname += "_" + paramSmallName(nodep->modp(),modvarp)+paramValueNumber(exprp);
any_overrides = true;
} else {
AstConst* exprp = pinp->exprp()->castConst();
AstConst* origp = modvarp->valuep()->castConst();
@@ -651,11 +709,11 @@ void ParamVisitor::visitCell(AstCell* nodep) {
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (pinp->exprp()) {
if (AstVar* modvarp = pinp->modVarp()) {
AstConst* constp = pinp->exprp()->castConst();
AstNode* newp = pinp->exprp(); // Const or InitArray
// Remove any existing parameter
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
// Set this parameter to value requested by cell
modvarp->valuep(constp->cloneTree(false));
modvarp->valuep(newp->cloneTree(false));
}
else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
AstNodeDType* dtypep = pinp->exprp()->castNodeDType();
@@ -686,7 +744,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
// Delete the parameters from the cell; they're not relevant any longer.
if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
UINFO(8," Done with "<<nodep<<endl);
//if (debug()>=10) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
//if (debug()>=10) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out"));
}
// Now remember to process the child module at the end of the module
@@ -699,5 +757,5 @@ void ParamVisitor::visitCell(AstCell* nodep) {
void V3Param::param(AstNetlist* rootp) {
UINFO(2,__FUNCTION__<<": "<<endl);
ParamVisitor visitor (rootp);
V3Global::dumpCheckGlobalTree("param.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
V3Global::dumpCheckGlobalTree("param", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
}

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