Compare commits

..
32 Commits
Author SHA1 Message Date
Wilson Snyder 2685037ca2 Version bump 2018-12-01 14:52:21 -05:00
Wilson Snyder 940dc98c66 Add CONTASSREG error on continuous assignments to regs, bug1369. 2018-12-01 10:12:10 -05:00
Wilson Snyder 49353784fd Fix __Slow files getting compiled with OPT_FAST, bug1370. 2018-11-29 20:35:21 -05:00
Wilson Snyder 2e5919549c Tests: Separate make_main flag from verilator_make_gcc flag. 2018-11-29 19:50:09 -05:00
Wilson Snyder 8170391573 Internals: Fix spacing of comments. No functional change. 2018-11-28 19:59:10 -05:00
Wilson Snyder 61e4b0a472 Add IMPORTSTAR warning on import::* inside scope. 2018-11-28 18:25:34 -05:00
Wilson Snyder 15af706286 Fix crash due to cygwin bug in getline, bug1349. 2018-11-26 19:09:08 -05:00
Wilson Snyder 2a43410fa6 Tests: Fix buggy size test. 2018-11-26 18:22:20 -05:00
Wilson Snyder 5cc11839b5 Add PROCASSWIRE error on behavioral assignments to wires, msg2737. 2018-11-26 17:58:18 -05:00
Wilson Snyder d1bfeae026 Tests: Ignore obj_vcs 2018-11-25 21:08:16 -05:00
Wilson Snyder e0b2c46664 Internals: Function return values act as vars, not wires. 2018-11-25 19:50:53 -05:00
Wilson Snyder ea61559ab5 Internals: Cleaner name for var. No functional change. 2018-11-25 19:10:18 -05:00
Wilson Snyder 6a5a2a56d7 Internals: Favor AstNetlist for global thread errors, and allow 0 line number error suppression. 2018-11-16 20:49:17 -05:00
Wilson Snyder 5cbf80918f Tests: Favor golden files over long regexps. No functional change. 2018-11-03 14:59:04 -04:00
Wilson Snyder 196e3a9712 Tests: Reduce timeout when single-threaded testing. 2018-11-03 09:07:28 -04:00
Wilson Snyder 3798b80091 Tests: Fix test instability. 2018-11-03 09:07:11 -04:00
Wilson Snyder 689e4cf1d3 Tests: Have files_identical fail on error 2018-11-01 21:58:39 -04:00
Wilson Snyder 64f11251b6 Fix verilator_coverage not sorting output 2018-11-01 21:39:37 -04:00
Wilson Snyder 6cd2bd2972 Tests: Add golden_filename. 2018-11-01 21:04:19 -04:00
Wilson Snyder d396c55e34 In --xml-only show module_files and cells ala Verilog-Perl vhier, msg2716. 2018-11-01 19:53:26 -04:00
Wilson Snyder 45c9939a5e Fix hang on bad pattern keys, bug1364. 2018-11-01 19:03:52 -04:00
Wilson Snyder ad2929dff0 Support "ref" and "const ref" pins and functions, bug1360. 2018-10-30 20:50:09 -04:00
Wilson Snyder d3e1dfd3f5 Tests: Add VERILATOR_MAKE override variable. 2018-10-30 20:28:39 -04:00
Wilson Snyder 14b48140bd In --xml-only show the original unmodified names, msg2716. 2018-10-30 18:17:37 -04:00
Wilson Snyder 7be1678fb0 Fix --trace-lxt2 compile error on MinGW, msg2711. 2018-10-30 07:35:30 -04:00
Wilson Snyder d464ce1477 Fix unneeded emit comment. No functional change. 2018-10-29 20:48:50 -04:00
Wilson Snyder 0a04f79576 Commentary 2018-10-28 08:16:19 -04:00
Wilson Snyder b8098098d8 Internals: Refactor input/output to new class in prep for ref support. 2018-10-27 17:29:00 -04:00
Wilson Snyder dc26815b1c Tests: Report wide line numbers. 2018-10-27 17:21:07 -04:00
Wilson Snyder f2028b60af Internals: Expand git_untabify lines touched. 2018-10-27 16:48:42 -04:00
Wilson Snyder 06c7d8ce3b Internals: Fix whitespace issues. No functional change, use -b to diff 2018-10-27 10:03:28 -04:00
Wilson Snyder 160505c5a4 devel release 2018-10-27 08:48:12 -04:00
322 changed files with 3037 additions and 2134 deletions
+22
View File
@@ -3,6 +3,28 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.008 2018-12-01
*** Support "ref" and "const ref" pins and functions, bug1360. [Jake Longo]
*** In --xml-only show the original unmodified names, and add module_files
and cells similar to Verilog-Perl, msg2719. [Kanad Kanhere]
**** Add CONTASSREG error on continuous assignments to regs, bug1369. [Peter Gerst]
**** Add PROCASSWIRE error on behavioral assignments to wires, msg2737. [Neil Turton]
**** Add IMPORTSTAR warning on import::* inside $unit scope.
**** Fix --trace-lxt2 compile error on MinGW, msg2711. [HyungKi Jeong]
**** Fix hang on bad pattern keys, bug1364. [Matt Myers]
**** Fix crash due to cygwin bug in getline, bug1349. [Affe Mao]
**** Fix __Slow files getting compiled with OPT_FAST, bug1370. [Thomas Watts]
* Verilator 4.006 2018-10-27
** Add --pp-comments, msg2700. [Robert Henry]
+2
View File
@@ -15,7 +15,9 @@
.*\.1
/obj_dir/
/obj_dbg/
/obj_nc/
/obj_opt/
/obj_vcs/
/obj_vlt/
/obj_vltmt/
/obj_dist/
+57 -21
View File
@@ -30,7 +30,7 @@ use IO::File;
use Pod::Usage;
use strict;
use vars qw ($Debug @Opt_Verilator_Sw);
use vars qw($Debug @Opt_Verilator_Sw);
#######################################################################
#######################################################################
@@ -57,7 +57,7 @@ foreach my $sw (@ARGV) {
push @Opt_Verilator_Sw, $sw;
}
Getopt::Long::config ("no_auto_abbrev","pass_through");
Getopt::Long::config("no_auto_abbrev","pass_through");
if (! GetOptions (
# Major operating modes
"help" => \&usage,
@@ -108,7 +108,7 @@ if ($opt_gdb) {
." -ex 'bt'");
} else {
# Normal, non gdb
run (verilator_bin()." ".join(' ',@quoted_sw));
run(verilator_bin()." ".join(' ',@quoted_sw));
}
#----------------------------------------------------------------------
@@ -226,7 +226,7 @@ Verilator - Convert Verilog code to C++/SystemC
verilator --version
verilator --cc [options] [source_files.v]... [opt_c_files.cpp/c/cc/a/o/so]
verilator --sc [options] [source_files.v]... [opt_c_files.cpp/c/cc/a/o/so]
verilator --lint-only [source_files.v]...
verilator --lint-only -Wall [source_files.v]...
=head1 DESCRIPTION
@@ -388,6 +388,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--x-assign <mode> Assign non-initial Xs to this value
--x-initial <mode> Assign initial Xs to this value
--x-initial-edge Enable initial X->0 and X->1 edge triggers
--xml-only Create XML parser output
-y <dir> Directory to search for modules
This is a short summary of the arguments to run-time Verilated arguments.
@@ -1413,8 +1414,8 @@ received from third parties.
Disable all code style related warning messages (note by default they are
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-PINCONNECTEMPTY -Wno-PINNOCONNECT -Wno-SYNCASYNCNET
-Wno-UNDRIVEN -Wno-UNUSED -Wno-VARHIDDEN".
-Wno-IMPORTSTAR -Wno-INCABSPATH -Wno-PINCONNECTEMPTY -Wno-PINNOCONNECT
-Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED -Wno-VARHIDDEN".
=item -Wno-fatal
@@ -1524,6 +1525,14 @@ convergence, and that it may be necessary to use --converge-limit to
increase the number of convergence iterations. This may be another
indication of problems with the modelled design that should be addressed.
=item --xml-only
Create XML output only, do not create any other output.
The XML format is intended to be used to leverage Verilator's parser and
elaboration to feed to other downstream tools. Be aware that the XML format
is still evolving; there will be some changes in future versions.
=item -y I<dir>
Add the directory to the list of directories that should be searched for
@@ -3446,15 +3455,6 @@ instead intended is to use a casez with C<?>.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item COLONPLUS
Warns that a :+ is seen. Likely the intent was to use +: to select a range
of bits. If the intent was a range that is explicitly positive, suggest
adding a space, e.g. use ": +".
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item CDCRSTLOGIC
With --cdc only, warns that asynchronous flop reset terms come from other
@@ -3479,6 +3479,15 @@ For example "X > 1" will always be true when X is a single bit wide.
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item COLONPLUS
Warns that a :+ is seen. Likely the intent was to use +: to select a range
of bits. If the intent was a range that is explicitly positive, suggest
adding a space, e.g. use ": +".
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item COMBDLY
Warns that you have a delayed assignment inside of a combinatorial block.
@@ -3491,6 +3500,18 @@ L<http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf>
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item CONTASSREG
Error that a continuous assignment is setting a reg. According to IEEE
Verilog, but not SystemVerilog, a wire must be used as the target of
continuous assignments.
This error is only reported when "--language 1364-1995", "--language
1364-2001", or "--language 1364-2005" is used.
Ignoring this error will only suppress the lint check, it will simulate
correctly.
=item DECLFILENAME
Warns that a module or other declaration's name doesn't match the filename
@@ -3570,6 +3591,16 @@ Emacs, available from L<http://www.veripool.org/>
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item IMPORTSTAR
Warns that an "import I<package>::*" statement is in $unit scope. This
causes the imported symbols to polute the global namespace, defeating much
of the purpose of having a package. Generally "import ::*" should only be
used inside a lower scope such as a package or module.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item IMPURE
Warns that a task or function that has been marked with /*verilator
@@ -3684,6 +3715,11 @@ signal.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item PROCASSWIRE
Error that a procedural assignment is setting a wire. According to IEEE, a
var/reg must be used as the target of procedural assignments.
=item REALCVT
Warns that a real number is being implicitly rounded to an integer, with
@@ -3760,7 +3796,7 @@ expression as the next statement. For example:
task foo; output sig; ... endtask
always @* begin
foo(bus_we_select_from[2]); // Will get TASKNSVAR error
foo(bus_we_select_from[2]); // Will get TASKNSVAR error
end
Change this to:
@@ -4128,12 +4164,12 @@ trace file if you want all data to land in the same output file.
...
Verilated::traceEverOn(true);
VerilatedVcdC* tfp = new VerilatedVcdC;
topp->trace (tfp, 99);
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
topp->trace(tfp, 99);
tfp->open("obj_dir/t_trace_ena_cc/simx.vcd");
...
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += #;
tfp->dump (main_time);
tfp->dump(main_time);
}
tfp->close();
}
@@ -4164,8 +4200,8 @@ trace file if you want all data to land in the same output file.
...
Verilated::traceEverOn(true);
VerilatedVcdSc* tfp = new VerilatedVcdSc;
topp->trace (tfp, 99);
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
topp->trace(tfp, 99);
tfp->open("obj_dir/t_trace_ena_cc/simx.vcd");
...
sc_start(1);
...
+4 -4
View File
@@ -31,7 +31,7 @@ use Pod::Usage;
use Cwd qw(abs_path getcwd);
use strict;
use vars qw ($Debug @Opt_Verilator_Sw);
use vars qw($Debug @Opt_Verilator_Sw);
#######################################################################
#######################################################################
@@ -54,7 +54,7 @@ foreach my $sw (@ARGV) {
push @Opt_Verilator_Sw, $sw;
}
Getopt::Long::config ("no_auto_abbrev","pass_through");
Getopt::Long::config("no_auto_abbrev","pass_through");
if (! GetOptions (
# Major operating modes
"help" => \&usage,
@@ -67,8 +67,8 @@ if (! GetOptions (
}
# Normal, non gdb
run (verilator_coverage_bin()
." ".join(' ',@Opt_Verilator_Sw));
run(verilator_coverage_bin()
." ".join(' ',@Opt_Verilator_Sw));
#----------------------------------------------------------------------
+9 -9
View File
@@ -10,7 +10,7 @@ use Getopt::Long;
use IO::File;
use Pod::Usage;
use strict;
use vars qw ($Debug);
use vars qw($Debug);
#======================================================================
@@ -37,7 +37,7 @@ my $Opt_B;
my $Opt_Lineno = 1;
autoflush STDOUT 1;
autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
Getopt::Long::config("no_auto_abbrev");
if (! GetOptions (
"help" => \&usage,
"debug" => \&debug,
@@ -54,9 +54,9 @@ defined $Opt_B or die "%Error: No new diff filename\n";
-e $Opt_B or die "%Error: No new diff filename found: $Opt_B\n";
if (-d $Opt_A && -d $Opt_B) {
diff_dir ($Opt_A, $Opt_B);
diff_dir($Opt_A, $Opt_B);
} elsif (-f $Opt_A && -f $Opt_B) {
diff_file ($Opt_A, $Opt_B);
diff_file($Opt_A, $Opt_B);
} else {
die "%Error: Mix of files and dirs\n";
}
@@ -85,8 +85,8 @@ sub diff_dir {
diff_file($a,$b);
$any = 1;
}
$any or warn ("%Warning: No .tree files found that have similar base names:\n "
.join("\n ", sort keys %files),"\n");
$any or warn("%Warning: No .tree files found that have similar base names:\n "
.join("\n ", sort keys %files),"\n");
}
sub diff_file {
@@ -103,8 +103,8 @@ sub diff_file {
my $verCvt = (($vera < 0x3900 && $verb >= 0x3900)
|| ($vera >= 0x3900 && $verb < 0x3900));
filter ($a, $tmp_a, $verCvt);
filter ($b, $tmp_b, $verCvt);
filter($a, $tmp_a, $verCvt);
filter($b, $tmp_b, $verCvt);
system("diff -u $tmp_a $tmp_b");
unlink $tmp_a;
unlink $tmp_b;
@@ -169,7 +169,7 @@ sub filter {
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1);
exit(1);
}
sub debug {
+2 -2
View File
@@ -9,7 +9,7 @@ use warnings;
use Getopt::Long;
use IO::File;
use Pod::Usage;
use vars qw ($Debug);
use vars qw($Debug);
$Debug = 0;
my $Opt_File;
@@ -44,7 +44,7 @@ exit(0);
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1);
exit(1);
}
sub parameter {
+3 -3
View File
@@ -11,7 +11,7 @@ use IO::File;
use Pod::Usage;
eval { use Data::Dumper; $Data::Dumper::Indent = 1; }; # Debug, ok if missing
use strict;
use vars qw ($Debug);
use vars qw($Debug);
#======================================================================
@@ -23,7 +23,7 @@ $Debug = 0;
my $Opt_File;
autoflush STDOUT 1;
autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
Getopt::Long::config("no_auto_abbrev");
if (! GetOptions (
"help" => \&usage,
"debug" => \&debug,
@@ -40,7 +40,7 @@ profcfunc($Opt_File);
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1);
exit(1);
}
sub debug {
+1 -1
View File
@@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[4.006 2018-10-27],
AC_INIT([Verilator],[4.008 2018-12-01],
[https://www.veripool.org/verilator],
[verilator],[https://www.veripool.org/verilator])
# When releasing, also update header of Changes file
-3
View File
@@ -2,9 +2,6 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
#if !defined(__MINGW32__)
+193 -193
View File
@@ -37,7 +37,7 @@
# include <direct.h> // mkdir
#endif
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
//===========================================================================
// Global variables
@@ -58,7 +58,7 @@ VerilatedImp VerilatedImp::s_s;
//===========================================================================
// User definable functions
#ifndef VL_USER_FINISH // Define this to override this function
#ifndef VL_USER_FINISH ///< Define this to override this function
void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
if (0 && hier) {}
VL_PRINTF("- %s:%d: Verilog $finish\n", filename, linenum); // Not VL_PRINTF_MT, already on main thread
@@ -71,7 +71,7 @@ void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE
}
#endif
#ifndef VL_USER_STOP // Define this to override this function
#ifndef VL_USER_STOP ///< Define this to override this function
void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
Verilated::gotFinish(true);
Verilated::flushCall();
@@ -79,7 +79,7 @@ void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
}
#endif
#ifndef VL_USER_FATAL // Define this to override this function
#ifndef VL_USER_FATAL ///< Define this to override this function
void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
if (0 && hier) {}
Verilated::gotFinish(true);
@@ -158,7 +158,7 @@ vluint64_t _vl_dbg_sequence_number() VL_MT_SAFE {
vluint32_t VL_THREAD_ID() VL_MT_SAFE {
#ifdef VL_THREADED
// Alternative is to use std::this_thread::get_id, but that returns a hard-to-read number and is very slow
static std::atomic<vluint32_t> s_nextId (0);
static std::atomic<vluint32_t> s_nextId(0);
static VL_THREAD_LOCAL vluint32_t t_myId = ++s_nextId;
return t_myId;
#else
@@ -202,7 +202,7 @@ Verilated::Serialized::Serialized() {
s_calcUnusedSigs = false;
s_gotFinish = false;
s_assertOn = true;
s_fatalOnVpiError = true; // retains old default behaviour
s_fatalOnVpiError = true; // retains old default behaviour
}
Verilated::NonSerialized::NonSerialized() {
@@ -277,8 +277,8 @@ WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
if (Verilated::randReset()==0) return 0;
IData data = ~0;
if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RANDOM_I(obits);
if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RANDOM_I(obits);
}
if (obits<32) data &= VL_MASK_I(obits);
return data;
@@ -286,8 +286,8 @@ IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
if (Verilated::randReset()==0) return 0;
QData data = VL_ULL(~0);
if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RANDOM_Q(obits);
if (Verilated::randReset()!=1) { // if 2, randomize
data = VL_RANDOM_Q(obits);
}
if (obits<64) data &= VL_MASK_Q(obits);
return data;
@@ -328,10 +328,10 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
int words = VL_WORDS_I(lbits);
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
int umsbp1 = VL_MOSTSETBITP1_W(words,lwp); // dividend
int vmsbp1 = VL_MOSTSETBITP1_W(words,rwp); // divisor
if (VL_UNLIKELY(vmsbp1==0) // rwp==0 so division by zero. Return 0.
|| VL_UNLIKELY(umsbp1==0)) { // 0/x so short circuit and return 0
|| VL_UNLIKELY(umsbp1==0)) { // 0/x so short circuit and return 0
return owp;
}
@@ -353,8 +353,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
}
// +1 word as we may shift during normalization
vluint32_t un[VL_MULS_MAX_WORDS+1]; // Fixed size, as MSVC++ doesn't allow [words] here
vluint32_t vn[VL_MULS_MAX_WORDS+1]; // v normalized
vluint32_t un[VL_MULS_MAX_WORDS+1]; // Fixed size, as MSVC++ doesn't allow [words] here
vluint32_t vn[VL_MULS_MAX_WORDS+1]; // v normalized
// Zero for ease of debugging and to save having to zero for shifts
// Note +1 as loop will use extra word
@@ -401,8 +401,8 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
k = (p >> VL_ULL(32)) - (t >> VL_ULL(32));
}
t = un[j+vw] - k;
un[j+vw] = t;
owp[j] = qhat; // Save quotient digit
un[j+vw] = t;
owp[j] = qhat; // Save quotient digit
if (t < 0) {
// Over subtracted; correct by adding back
@@ -417,14 +417,14 @@ 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) {
owp[i] = (un[i] >> s) | (shift_mask & (un[i+1] << (32-s)));
}
for (int i=vw; i<words; ++i) owp[i] = 0;
return owp;
} else { // division
if (is_modulus) { // modulus
// Need to reverse normalization on copy to output
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;
return owp;
} else { // division
return owp;
}
}
@@ -434,9 +434,9 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDa
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
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++) {
@@ -473,17 +473,17 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
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
}
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);
@@ -497,12 +497,12 @@ WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits,
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
// 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
}
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);
@@ -541,7 +541,7 @@ std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
}
std::string output;
int lsb = (maxdecwidth-1) & ~3;
for (; lsb>0; lsb-=4) { // Skip leading zeros
for (; lsb>0; lsb-=4) { // Skip leading zeros
if (VL_BITRSHIFT_W(bcd, lsb) & 0xf) break;
}
for (; lsb>=0; lsb-=4) {
@@ -572,17 +572,17 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
pctp = pos;
inPct = true;
widthSet = false;
width = 0;
} else if (!inPct) { // Normal text
// Fast-forward to next escape and add to output
const char *ep = pos;
while (ep[0] && ep[0]!='%') ep++;
if (ep != pos) {
output.append(pos, ep-pos);
pos += ep-pos-1;
}
} else { // Format character
inPct = false;
width = 0;
} else if (!inPct) { // Normal text
// Fast-forward to next escape and add to output
const char *ep = pos;
while (ep[0] && ep[0]!='%') ep++;
if (ep != pos) {
output.append(pos, ep-pos);
pos += ep-pos-1;
}
} else { // Format character
inPct = false;
char fmt = pos[0];
switch (fmt) {
case '0': case '1': case '2': case '3': case '4':
@@ -597,17 +597,17 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case '%':
output += '%';
break;
case 'N': { // "C" string with name of module, add . if needed
const char* cstrp = va_arg(ap, const char*);
if (VL_LIKELY(*cstrp)) { output += cstrp; output += '.'; }
break;
}
case 'S': { // "C" string
const char* cstrp = va_arg(ap, const char*);
output += cstrp;
break;
}
case '@': { // Verilog/C++ string
case 'N': { // "C" string with name of module, add . if needed
const char* cstrp = va_arg(ap, const char*);
if (VL_LIKELY(*cstrp)) { output += cstrp; output += '.'; }
break;
}
case 'S': { // "C" string
const char* cstrp = va_arg(ap, const char*);
output += cstrp;
break;
}
case '@': { // Verilog/C++ string
va_arg(ap, int); // # bits is ignored
const std::string* cstrp = va_arg(ap, const std::string*);
output += *cstrp;
@@ -649,12 +649,12 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
case 's':
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
output += (charval==0)?' ':charval;
}
break;
case 'd': { // Signed decimal
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
output += (charval==0)?' ':charval;
}
break;
case 'd': { // Signed decimal
int digits;
std::string append;
if (lbits <= VL_QUADSIZE) {
@@ -673,16 +673,16 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
int needmore = width-digits;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += append;
break;
}
case '#': { // Unsigned decimal
if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero
} else {
output.append(needmore, ' '); // Pre-pad spaces
}
}
output += append;
break;
}
case '#': { // Unsigned decimal
int digits;
std::string append;
if (lbits <= VL_QUADSIZE) {
@@ -694,16 +694,16 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
int needmore = width-digits;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += append;
break;
}
case 't': { // Time
if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero
} else {
output.append(needmore, ' '); // Pre-pad spaces
}
}
output += append;
break;
}
case 't': { // Time
int digits;
if (VL_TIME_MULTIPLIER==1) {
digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
@@ -714,9 +714,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
} else {
VL_FATAL_MT(__FILE__,__LINE__,"","Unsupported VL_TIME_MULTIPLIER");
}
int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
output += tmp;
int needmore = width-digits;
if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces
output += tmp;
break;
}
case 'b':
@@ -725,9 +725,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
}
break;
case 'o':
for (; lsb>=0; --lsb) {
lsb = (lsb / 3) * 3; // Next digit
// Octal numbers may span more than one wide word,
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
// Octal is rare, so we'll do it a slow simple way
output += ('0'
@@ -752,19 +752,19 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
output += static_cast<char>((lwp[i] >> 8) & 0xff);
output += static_cast<char>((lwp[i] >> 16) & 0xff);
output += static_cast<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) {
output += "\0\0\0\0"; // No tristate
}
break;
case 'v': // Strength; assume always strong
for (lsb=lbits-1; lsb>=0; --lsb) {
if (VL_BITRSHIFT_W(lwp, lsb) & 1) output += "St1 ";
else output += "St0 ";
}
break;
case 'x':
for (; lsb>=0; --lsb) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
}
break;
case 'x':
for (; lsb>=0; --lsb) {
lsb = (lsb / 4) * 4; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
output += "0123456789abcdef"[charval];
}
break;
@@ -772,10 +772,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
std::string msg = std::string("Unknown _vl_vsformat code: ")+pos[0];
VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str());
break;
} // switch
}
} // switch
}
} // switch
}
} // switch
}
}
}
@@ -795,9 +795,9 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const std:
ungetc(data,fp);
return data;
} else {
if (floc < 0) return EOF;
floc = floc & ~7; // Align to closest character
if (fromp == NULL) {
if (floc < 0) return EOF;
floc = floc & ~7; // Align to closest character
if (fromp == NULL) {
return fstr[fstr.length()-1 - (floc>>3)];
} else {
return VL_BITRSHIFT_W(fromp, floc) & 0xff;
@@ -818,9 +818,9 @@ static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std:
while (1) {
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
if (c==EOF || isspace(c)) break;
if (acceptp!=NULL // String - allow anything
&& NULL==strchr(acceptp, c)) break;
if (acceptp!=NULL) c = tolower(c); // Non-strings we'll simplify
if (acceptp // String - allow anything
&& NULL==strchr(acceptp, c)) break;
if (acceptp) c = tolower(c); // Non-strings we'll simplify
*cp++ = c;
_vl_vsss_advance(fp, floc);
}
@@ -837,9 +837,9 @@ static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2,
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
int lsb = 0;
for (int i=0, pos=static_cast<int>(posend)-1; i<obits && pos>=static_cast<int>(posstart); --pos) {
switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': //FALLTHRU
case '0': lsb += baseLog2; break;
switch (tolower (strp[pos])) {
case 'x': case 'z': case '?': // FALLTHRU
case '0': lsb += baseLog2; break;
case '1': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 1); lsb+=baseLog2; break;
case '2': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 2); lsb+=baseLog2; break;
case '3': _vl_vsss_setbit(owp,obits,lsb, baseLog2, 3); lsb+=baseLog2; break;
@@ -876,15 +876,15 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
//VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp,floc,fromp,fstr)<<"'"<<endl);
if (!inPct && pos[0]=='%') {
inPct = true;
} else if (!inPct && isspace(pos[0])) { // Format spaces
while (isspace(pos[1])) pos++;
_vl_vsss_skipspace(fp,floc,fromp,fstr);
} else if (!inPct) { // Expected Format
_vl_vsss_skipspace(fp,floc,fromp,fstr);
int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c != pos[0]) goto done;
else _vl_vsss_advance(fp,floc);
} else { // Format character
} else if (!inPct && isspace(pos[0])) { // Format spaces
while (isspace(pos[1])) pos++;
_vl_vsss_skipspace(fp,floc,fromp,fstr);
} else if (!inPct) { // Expected Format
_vl_vsss_skipspace(fp,floc,fromp,fstr);
int c = _vl_vsss_peek(fp,floc,fromp,fstr);
if (c != pos[0]) goto done;
else _vl_vsss_advance(fp,floc);
} else { // Format character
// Skip loading spaces
inPct = false;
char fmt = pos[0];
@@ -923,9 +923,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[lpos]); lsb+=8;
}
break;
}
case 'd': { // Signed decimal
_vl_vsss_skipspace(fp,floc,fromp,fstr);
}
case 'd': { // Signed decimal
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
vlsint64_t ld;
@@ -934,9 +934,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
break;
}
case 'f':
case 'e':
case 'g': { // Real number
_vl_vsss_skipspace(fp,floc,fromp,fstr);
case 'e':
case 'g': { // Real number
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done;
// cppcheck-suppress unusedStructMember // It's used
@@ -945,9 +945,9 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
VL_SET_WQ(owp,u.ld);
break;
}
case 't': // FALLTHRU // Time
case '#': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp,fstr);
case 't': // FALLTHRU // Time
case '#': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp,fstr);
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789+-xXzZ?_");
if (!tmp[0]) goto done;
QData ld;
@@ -979,8 +979,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
default:
std::string msg = std::string("Unknown _vl_vsscanf code: ")+pos[0];
VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str());
break;
} // switch
break;
} // switch
got++;
// Reload data if non-wide (if wide, we put it in the right place directly)
@@ -994,8 +994,8 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
QData* p = va_arg(ap,QData*); *p = VL_SET_QW(owp);
}
}
} // switch
}
} // switch
}
}
done:
return got;
@@ -1014,14 +1014,14 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE
bool start=true;
char* destp = destoutp;
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
if (!start || charval) {
*destp++ = (charval==0)?' ':charval;
start = false; // Drop leading 0s
}
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
if (!start || charval) {
*destp++ = (charval==0)?' ':charval;
start = false; // Drop leading 0s
}
}
*destp = '\0'; // Terminate
*destp = '\0'; // Terminate
// Drop trailing spaces
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0';
}
@@ -1277,15 +1277,15 @@ const char* memhFormat(int nBits) {
}
void VL_WRITEMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& filename, // Output file name
const void* memp, // Array state
IData start, // First array row address to write
IData end // Last address to write
IData start, // First array row address to write
IData end // Last address to write
) VL_MT_SAFE {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(filename.c_str(), 0, "",
@@ -1381,15 +1381,15 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
}
void VL_READMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& filename, // Input file name
void* memp, // Array state
IData start, // First array row address to read
IData end // Last row address to read
void* memp, // Array state
IData start, // First array row address to read
IData end // Last row address to read
) VL_MT_SAFE {
FILE* fp = fopen(filename.c_str(), "r");
if (VL_UNLIKELY(!fp)) {
@@ -1519,9 +1519,9 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
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
} else if (!inPct) { // Normal text
prefix += *posp;
} else { // Format character
switch (tolower(*posp)) {
case '%':
prefix += *posp;
@@ -1552,18 +1552,18 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
case 'o':
_vl_vsss_based(rwp,rbits, 3, dp, 0, strlen(dp));
break;
case 'h': //FALLTHRU
case 'h': // FALLTHRU
case 'x':
_vl_vsss_based(rwp,rbits, 4, dp, 0, strlen(dp));
break;
case 's': // string/no conversion
for (int i=0, lsb=0, posp=static_cast<int>(strlen(dp))-1; i<rbits && posp>=0; --posp) {
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8;
}
break;
case 'e': //FALLTHRU - Unsupported
case 'f': //FALLTHRU - Unsupported
case 'g': //FALLTHRU - Unsupported
_vl_vsss_based(rwp,rbits, 4, dp, 0, strlen(dp));
break;
case 's': // string/no conversion
for (int i=0, lsb=0, posp=static_cast<int>(strlen(dp))-1; i<rbits && posp>=0; --posp) {
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8;
}
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;
}
@@ -1577,9 +1577,9 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
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
} else if (!inPct) { // Normal text
prefix += *posp;
} else { // Format character
switch (tolower(*posp)) {
case '%':
prefix += *posp;
@@ -1602,8 +1602,8 @@ const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
if (match.empty()) return NULL;
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
VL_VALUE_STRING_MAX_WIDTH);
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
VL_VALUE_STRING_MAX_WIDTH);
outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
return outstr;
}
@@ -1620,13 +1620,13 @@ std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
char* destp = destout;
int len = 0;
for (; lsb>=0; --lsb) {
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
if (!start || charval) {
*destp++ = (charval==0)?' ':charval;
len++;
start = false; // Drop leading 0s
}
lsb = (lsb / 8) * 8; // Next digit
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
if (!start || charval) {
*destp++ = (charval==0)?' ':charval;
len++;
start = false; // Drop leading 0s
}
}
return std::string(destout, len);
}
@@ -2001,9 +2001,9 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_
} else {
if (VL_UNLIKELY(funcnum >= m_funcnumMax)) {
VL_FATAL_MT(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum");
}
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
m_callbacksp = new void* [m_funcnumMax];
}
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
m_callbacksp = new void* [m_funcnumMax];
memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
}
m_callbacksp[funcnum] = cb;
+114 -110
View File
@@ -26,7 +26,7 @@
#ifndef _VERILATED_H_
#define _VERILATED_H_ 1 ///< Header Guard
#define _VERILATED_H_ 1 ///< Header Guard
#include "verilatedos.h"
@@ -48,8 +48,8 @@
//=============================================================================
// Switches
#if VM_TRACE // Verilator tracing requested
# define WAVES 1 // Set backward compatibility flag
#if VM_TRACE // Verilator tracing requested
# define WAVES 1 // Set backward compatibility flag
#endif
//=========================================================================
@@ -158,7 +158,7 @@ class VL_SCOPED_CAPABILITY VerilatedLockGuard {
}
};
#else // !VL_THREADED
#else // !VL_THREADED
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
class VerilatedMutex {
@@ -175,7 +175,7 @@ public:
~VerilatedLockGuard() {}
};
#endif // VL_THREADED
#endif // VL_THREADED
/// Remember the calling thread at construction time, and make sure later calls use same thread
class VerilatedAssertOneThread {
@@ -196,7 +196,7 @@ public:
}
}
static void fatal_different() VL_MT_SAFE;
#else // !VL_THREADED || !VL_DEBUG
#else // !VL_THREADED || !VL_DEBUG
public:
void check() {}
#endif
@@ -208,11 +208,11 @@ public:
class VerilatedModule {
VL_UNCOPYABLE(VerilatedModule);
private:
const char* m_namep; ///< Module name
const char* m_namep; ///< Module name
public:
explicit VerilatedModule(const char* namep); ///< Create module with given hierarchy name
explicit VerilatedModule(const char* namep); ///< Create module with given hierarchy name
~VerilatedModule();
const char* name() const { return m_namep; } ///< Return name of module
const char* name() const { return m_namep; } ///< Return name of module
};
//=========================================================================
@@ -336,9 +336,9 @@ class Verilated {
static VerilatedVoidCb s_flushCb; ///< Flush callback function
static struct Serialized { // All these members serialized/deserialized
// Fast path
int s_debug; ///< See accessors... only when VL_DEBUG set
static struct Serialized { // All these members serialized/deserialized
// Fast path
int s_debug; ///< See accessors... only when VL_DEBUG set
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
bool s_gotFinish; ///< A $finish statement executed
bool s_assertOn; ///< Assertions are enabled
@@ -470,7 +470,7 @@ public:
public:
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
// Internal: Create a new module name by concatenating two strings
static const char* catName(const char* n1, const char* n2); // Returns static data
static const char* catName(const char* n1, const char* n2); // Returns static data
// Internal: Throw signal assertion
static void overWidthError(const char* signame) VL_MT_SAFE;
@@ -491,7 +491,7 @@ public:
static int exportFuncNum(const char* namep) VL_MT_SAFE;
static size_t serializedSize() VL_PURE { return sizeof(s_s); }
static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
#ifdef VL_THREADED
/// Set the mtaskId, called when an mtask starts
static void mtaskId(vluint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
@@ -562,15 +562,15 @@ extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
/// Print a debug message from internals with standard prefix, with printf style format
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
/// Init time only, so slow is fine
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal (slow - else use VL_ZERO_W)
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 (slow - else use VL_ZERO_W)
#if VL_THREADED
/// Return high-precision counter for profiling, or 0x0 if not available
@@ -1191,7 +1191,7 @@ static inline int _VL_CMP_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
if (lwp[i] > rwp[i]) return 1;
if (lwp[i] < rwp[i]) return -1;
}
return(0); // ==
return(0); // ==
}
#define VL_LTS_IWW(obits,lbits,rbbits,lwp,rwp) (_VL_CMPS_W(lbits,lwp,rwp)<0)
@@ -1202,8 +1202,8 @@ static inline int _VL_CMP_W(int words, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
static inline IData VL_GTS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
// For lbits==32, this becomes just a single instruction, otherwise ~5.
// GCC 3.3.4 sign extension bugs on AMD64 architecture force us to use quad logic
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); //Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); //Q for gcc
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
return lhs_signed > rhs_signed;
}
static inline IData VL_GTS_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
@@ -1213,8 +1213,8 @@ static inline IData VL_GTS_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PUR
}
static inline IData VL_GTES_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); //Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); //Q for gcc
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
return lhs_signed >= rhs_signed;
}
static inline IData VL_GTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
@@ -1224,8 +1224,8 @@ static inline IData VL_GTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PU
}
static inline IData VL_LTS_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); //Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); //Q for gcc
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
return lhs_signed < rhs_signed;
}
static inline IData VL_LTS_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
@@ -1235,8 +1235,8 @@ static inline IData VL_LTS_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PUR
}
static inline IData VL_LTES_III(int, int lbits, int, IData lhs, IData rhs) VL_PURE {
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); //Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); //Q for gcc
vlsint64_t lhs_signed = VL_EXTENDS_QQ(64, lbits, lhs); // Q for gcc
vlsint64_t rhs_signed = VL_EXTENDS_QQ(64, lbits, rhs); // Q for gcc
return lhs_signed <= rhs_signed;
}
static inline IData VL_LTES_IQQ(int, int lbits, int, QData lhs, QData rhs) VL_PURE {
@@ -1251,13 +1251,13 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
// We need to flip sense if negative comparison
IData lsign = VL_SIGN_I(lbits,lwp[i]);
IData rsign = VL_SIGN_I(lbits,rwp[i]);
if (!lsign && rsign) return 1; // + > -
if (lsign && !rsign) return -1; // - < +
if (!lsign && rsign) return 1; // + > -
if (lsign && !rsign) return -1; // - < +
for (; i>=0; --i) {
if (lwp[i] > rwp[i]) return 1;
if (lwp[i] < rwp[i]) return -1;
if (lwp[i] > rwp[i]) return 1;
if (lwp[i] < rwp[i]) return -1;
}
return(0); // ==
return(0); // ==
}
//=========================================================================
@@ -1341,26 +1341,26 @@ static inline QData VL_MULS_QQQ(int,int lbits,int, QData lhs,QData rhs) VL_PURE
static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lwp,WDataInP rwp) VL_MT_SAFE {
int words = VL_WORDS_I(lbits);
// cppcheck-suppress variableScope
WData 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
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP lwusp = lwp;
WDataInP rwusp = rwp;
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
if (lneg) { // Negate lhs
lwusp = lwstore;
VL_NEGATE_W(words, lwstore, lwp);
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
if (lneg) { // Negate lhs
lwusp = lwstore;
VL_NEGATE_W(words, lwstore, lwp);
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
}
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
if (rneg) { // Negate rhs
rwusp = rwstore;
VL_NEGATE_W(words, rwstore, rwp);
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
if (rneg) { // Negate rhs
rwusp = rwstore;
VL_NEGATE_W(words, rwstore, rwp);
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
}
VL_MUL_W(words,owp,lwusp,rwusp);
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)
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0;
for (int i=0; i<words; ++i) {
carry = carry + static_cast<QData>(static_cast<IData>(~owp[i]));
@@ -1404,7 +1404,7 @@ 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
WData 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
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
@@ -1425,7 +1425,7 @@ 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
WData 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
WData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
@@ -1488,12 +1488,12 @@ static inline IData VL_POWSS_III(int obits, int, int rbits,
IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
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
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
if (lhs==0) return 0; // "X"
else if (lhs==1) return 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, rbits, rbits, lhs, rhs);
@@ -1502,12 +1502,12 @@ static inline QData VL_POWSS_QQQ(int obits, int, int rbits,
QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
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
if (rhs & 1) return VL_MASK_I(obits); // -1^odd=-1
else return 1; // -1^even=1
}
if (lhs==0) return 0; // "X"
else if (lhs==1) return 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, rbits, rbits, lhs, rhs);
@@ -1549,9 +1549,9 @@ static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbi
}
else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
owp[lword] = (owp[lword] & ~insmask) | ((ld<<loffset) & insmask);
} else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
@@ -1580,9 +1580,9 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
// Non-32bit, but nicely aligned, so stuff all but the last word
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
owp[lword+words-1] = (owp[words+lword-1] & ~hinsmask) | (lwp[words-1] & hinsmask);
}
IData hinsmask = (VL_MASK_I(hoffset-0+1)); // Know it's not a full word as above fast case handled it
owp[lword+words-1] = (owp[words+lword-1] & ~hinsmask) | (lwp[words-1] & hinsmask);
}
else {
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
@@ -1688,20 +1688,24 @@ static inline IData VL_STREAML_FAST_III(int, int lbits, int, IData ld, IData rd_
// ret = 10324---
IData ret = ld;
if (rd_log2) {
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2); // max multiple of rd <= lbits
vluint32_t lbitsRem = lbits - lbitsFloor; // number of bits in most-sig slice (MSS)
IData msbMask = VL_MASK_I(lbitsRem) << lbitsFloor; // mask to sel only bits in MSS
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_UL(1) << rd_log2) - lbitsRem));
vluint32_t lbitsFloor = lbits & ~VL_MASK_I(rd_log2); // max multiple of rd <= lbits
vluint32_t lbitsRem = lbits - lbitsFloor; // number of bits in most-sig slice (MSS)
IData msbMask = VL_MASK_I(lbitsRem) << lbitsFloor; // mask to sel only bits in MSS
ret = (ret & ~msbMask) | ((ret & msbMask) << ((VL_UL(1) << rd_log2) - lbitsRem));
}
switch (rd_log2) {
case 0:
ret = ((ret >> 1) & VL_UL(0x55555555)) | ((ret & VL_UL(0x55555555)) << 1); // FALLTHRU
case 1:
ret = ((ret >> 2) & VL_UL(0x33333333)) | ((ret & VL_UL(0x33333333)) << 2); // FALLTHRU
case 2:
ret = ((ret >> 4) & VL_UL(0x0f0f0f0f)) | ((ret & VL_UL(0x0f0f0f0f)) << 4); // FALLTHRU
case 3:
ret = ((ret >> 8) & VL_UL(0x00ff00ff)) | ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
case 0:
ret = ((ret >> 1) & VL_UL(0x55555555))
| ((ret & VL_UL(0x55555555)) << 1); // FALLTHRU
case 1:
ret = ((ret >> 2) & VL_UL(0x33333333))
| ((ret & VL_UL(0x33333333)) << 2); // FALLTHRU
case 2:
ret = ((ret >> 4) & VL_UL(0x0f0f0f0f))
| ((ret & VL_UL(0x0f0f0f0f)) << 4); // FALLTHRU
case 3:
ret = ((ret >> 8) & VL_UL(0x00ff00ff))
| ((ret & VL_UL(0x00ff00ff)) << 8); // FALLTHRU
case 4:
ret = ((ret >> 16) | (ret << 16));
}
@@ -1895,17 +1899,17 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
static inline WDataOutP VL_SHIFTL_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
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);
}
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) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs<<rwp[0]);
}
@@ -1942,17 +1946,17 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int,
static inline WDataOutP VL_SHIFTR_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
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);
}
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) VL_MT_SAFE {
for (int i=1; i < VL_WORDS_I(rbits); ++i) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs>>rwp[0]);
}
@@ -1963,8 +1967,8 @@ static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData r
// IEEE says signed if output signed, but bit position from lbits;
// must use lbits for sign; lbits might != obits,
// an EXTEND(SHIFTRS(...)) can became a SHIFTRS(...) within same 32/64 bit word length
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past"
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
IData signext = ~(VL_MASK_I(lbits) >> rhs); // One with bits where we've shifted "past"
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
}
static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData rhs) VL_PURE {
@@ -2012,9 +2016,9 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
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]);
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;
@@ -2025,20 +2029,20 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits, int lbits, int rbits,
static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits,
IData lhs, WDataInP rwp) VL_MT_SAFE {
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);
}
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) VL_MT_SAFE {
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);
}
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]);
}
@@ -2063,8 +2067,8 @@ static inline QData VL_SHIFTRS_QQQ(int obits,int lbits,int rbits,QData lhs, QDat
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) VL_MT_SAFE {
int word = VL_BITWORD_I(rd);
if (VL_UNLIKELY(rd > static_cast<IData>(lbits))) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
// We return all 1's as that's more likely to find bugs (?) than 0's.
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
// We return all 1's as that's more likely to find bugs (?) than 0's.
} else {
return (lwp[word]>>VL_BITBIT_I(rd));
}
@@ -2080,7 +2084,7 @@ static inline IData VL_SEL_IWII(int, int lbits, int, int,
WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
int msb = lsb+width-1;
if (VL_UNLIKELY(msb>lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
return VL_BITRSHIFT_W(lwp, lsb);
} else {
@@ -2095,7 +2099,7 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int,
WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
int msb = lsb+width-1;
if (VL_UNLIKELY(msb>lbits)) {
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
return VL_BITRSHIFT_W(lwp, lsb);
} else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I(static_cast<int>(lsb))) {
@@ -2117,9 +2121,9 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, int, int,
WDataOutP owp, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
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;
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits);
if (VL_UNLIKELY(msb>lbits)) { // Outside bounds,
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];
@@ -2287,4 +2291,4 @@ static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
//======================================================================
#endif /*_VERILATED_H_*/
#endif // Guard
+10 -5
View File
@@ -167,17 +167,19 @@ $(VM_PREFIX)__ALL.a: $(VK_OBJS)
### Compile rules
ifneq ($(VM_DEFAULT_RULES),0)
$(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
$(VM_PREFIX)__ALLcls.o: $(VM_PREFIX)__ALLcls.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
$(VM_PREFIX)%__Slow.o: $(VM_PREFIX)%__Slow.cpp
$(VM_PREFIX)__ALLsup.o: $(VM_PREFIX)__ALLsup.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
$(VM_PREFIX)%.o: $(VM_PREFIX)%.cpp
# VM_GLOBAL_FAST files including verilated.o use this rule
%.o: %.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<
%__Slow.o: %__Slow.cpp
$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
endif
#Default rule embedded in make:
@@ -189,7 +191,10 @@ endif
debug-make::
@echo
@echo CXXFLAGS: $(CXXFLAGS)
@echo CPPFLAGS: $(CPPFLAGS)
@echo OPT_FAST: $(OPT_FAST)
@echo OPT_SLOW: $(OPT_SLOW)
@echo VM_PREFIX: $(VM_PREFIX)
@echo VM_PARALLEL_BUILDS: $(VM_PARALLEL_BUILDS)
@echo VM_CLASSES_FAST: $(VM_CLASSES_FAST)
+1 -1
View File
@@ -29,4 +29,4 @@
// Hide file descriptor difference - deprecated - for older versions
`define verilator_file_descriptor integer
`endif // guard
`endif // guard
+10 -10
View File
@@ -34,8 +34,8 @@
struct VerilatedCovImpBase {
// TYPES
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
};
//=============================================================================
@@ -45,8 +45,8 @@ struct VerilatedCovImpBase {
class VerilatedCovImpItem : VerilatedCovImpBase {
public: // But only local to this file
// MEMBERS
int m_keys[MAX_KEYS]; ///< Key
int m_vals[MAX_KEYS]; ///< Value for specified key
int m_keys[MAX_KEYS]; ///< Key
int m_vals[MAX_KEYS]; ///< Value for specified key
// CONSTRUCTORS
// Derived classes should call zero() in their constructor
VerilatedCovImpItem() {
@@ -69,7 +69,7 @@ public: // But only local to this file
template <class T> class VerilatedCoverItemSpec : public VerilatedCovImpItem {
private:
// MEMBERS
T* m_countp; ///< Count value
T* m_countp; ///< Count value
public:
// METHODS
// cppcheck-suppress truncLongCastReturn
@@ -431,12 +431,12 @@ void VerilatedCov::_insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19),
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) VL_MT_SAFE {
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
= {NULL,NULL,NULL, // filename,lineno,page
key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,
key10,key11,key12,key13,key14,key15,key16,key17,key18,key19,
key20,key21,key22,key23,key24,key25,key26,key27,key28,key29};
= {NULL,NULL,NULL, // filename,lineno,page
key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,
key10,key11,key12,key13,key14,key15,key16,key17,key18,key19,
key20,key21,key22,key23,key24,key25,key26,key27,key28,key29};
const char* valps[VerilatedCovImpBase::MAX_KEYS]
= {NULL,NULL,NULL, // filename,lineno,page
= {NULL,NULL,NULL, // filename,lineno,page
valp0,valp1,valp2,valp3,valp4,valp5,valp6,valp7,valp8,valp9,
valp10,valp11,valp12,valp13,valp14,valp15,valp16,valp17,valp18,valp19,
valp20,valp21,valp22,valp23,valp24,valp25,valp26,valp27,valp28,valp29};
+3 -3
View File
@@ -106,8 +106,8 @@ public:
// much slower (nearly 2x) than having smaller versions also. However
// there's not much more gain in having a version for each number of args.
#define K(n) const char* key ## n
#define A(n) const char* key ## n, const char* valp ## n // Argument list
#define D(n) const char* key ## n = NULL, const char* valp ## n = NULL // Argument list
#define A(n) const char* key ## n, const char* valp ## n // Argument list
#define D(n) const char* key ## n = NULL, const char* valp ## n = NULL // Argument list
static void _insertp(D(0),D(1),D(2),D(3),D(4),D(5),D(6),D(7),D(8),D(9));
static void _insertp(A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)
,A(10),D(11),D(12),D(13),D(14),D(15),D(16),D(17),D(18),D(19));
@@ -129,4 +129,4 @@ public:
static void zero() VL_MT_SAFE;
};
#endif // guard
#endif // Guard
+1 -1
View File
@@ -140,4 +140,4 @@ public:
}
};
#endif // guard
#endif // guard
+12 -12
View File
@@ -147,7 +147,7 @@ void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width)
else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
} else {
@@ -172,7 +172,7 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w
else {
int hword = VL_BITWORD_I(hbit);
int lword = VL_BITWORD_I(lbit);
if (hword==lword) { // know < 32 bits because above checks it
if (hword==lword) { // know < 32 bits because above checks it
IData insmask = (VL_MASK_I(hoffset-loffset+1))<<loffset;
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
@@ -474,7 +474,7 @@ void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3); break; }
default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break; // Will error
default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
return datap;
@@ -500,7 +500,7 @@ void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
@@ -527,7 +527,7 @@ void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
@@ -558,7 +558,7 @@ void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
@@ -585,7 +585,7 @@ void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0); break; }
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3); break; }
default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break; // Will error
}
va_end(ap);
}
@@ -615,7 +615,7 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
return out;
@@ -643,7 +643,7 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); break; }
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
return out;
@@ -673,7 +673,7 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
}
@@ -699,7 +699,7 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...)
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; }
case 4: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int); int indx4=va_arg(ap,int);
_vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); break; }
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error
}
va_end(ap);
}
@@ -763,7 +763,7 @@ int svGetCallerInfo(const char** fileNamepp, int *lineNumberp) {
// Disables
int svIsDisabledState() {
return 0; // Disables not implemented
return 0; // Disables not implemented
}
void svAckDisabledState() {
+2 -2
View File
@@ -26,7 +26,7 @@
#ifndef _VERILATED_DPI_H_
#define _VERILATED_DPI_H_ 1 ///< Header Guard
#define _VERILATED_DPI_H_ 1 ///< Header Guard
#include "verilatedos.h"
#include "verilated.h" // Also presumably included by caller
@@ -80,4 +80,4 @@ static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, QData ld) VL_MT_SAFE {
//======================================================================
#endif // _VERILATED_DPI_H_
#endif // Guard
+2 -2
View File
@@ -27,7 +27,7 @@
#ifndef _VERILATED_HEAVY_H_
#define _VERILATED_HEAVY_H_ 1 ///< Header Guard
#define _VERILATED_HEAVY_H_ 1 ///< Header Guard
#include "verilated.h"
@@ -88,4 +88,4 @@ inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr)
}
extern IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE;
#endif // Guard
#endif // Guard
+12 -12
View File
@@ -22,7 +22,7 @@
#ifndef _VERILATED_IMP_H_
#define _VERILATED_IMP_H_ 1 ///< Header Guard
#define _VERILATED_IMP_H_ 1 ///< Header Guard
#if !defined(_VERILATED_CPP_) && !defined(_VERILATED_DPI_CPP_)
# error "verilated_imp.h only to be included by verilated*.cpp internals"
@@ -57,8 +57,8 @@ public:
};
private:
// MEMBERS
vluint32_t m_mtaskId; ///< MTask that did enqueue
std::function<void()> m_cb; ///< Lambda to execute when message received
vluint32_t m_mtaskId; ///< MTask that did enqueue
std::function<void()> m_cb; ///< Lambda to execute when message received
public:
// CONSTRUCTORS
VerilatedMsg(const std::function<void()>& cb)
@@ -103,9 +103,9 @@ public:
while (m_depth) {
// Wait for a message to be added to the queue
// We don't use unique_lock as want to unlock with the message copy still in scope
m_mutex.lock();
assert(!m_queue.empty()); // Otherwise m_depth is wrong
// Unfortunately to release the lock we need to copy the message
m_mutex.lock();
assert(!m_queue.empty()); // Otherwise m_depth is wrong
// Unfortunately to release the lock we need to copy the message
// (Or have the message be a pointer, but then new/delete cost on each message)
// We assume messages are small, so copy
auto it = m_queue.begin();
@@ -160,7 +160,7 @@ public:
}
}
};
#endif // VL_THREADED
#endif // VL_THREADED
//======================================================================
// VerilatedImp
@@ -174,7 +174,7 @@ class VerilatedImp {
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
// MEMBERS
static VerilatedImp s_s; ///< Static Singleton; One and only static this
static VerilatedImp s_s; ///< Static Singleton; One and only static this
// Nothing here is save-restored; users expected to re-register appropriately
@@ -197,7 +197,7 @@ class VerilatedImp {
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex); ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
public: // But only for verilated*.cpp
public: // But only for verilated*.cpp
// CONSTRUCTORS
VerilatedImp()
: m_argVecLoaded(false), m_exportNext(0) {
@@ -282,7 +282,7 @@ private:
}
}
public: // But only for verilated*.cpp
public: // But only for verilated*.cpp
// METHODS - scope name
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at construction
@@ -319,7 +319,7 @@ public: // But only for verilated*.cpp
return &s_s.m_nameMap;
}
public: // But only for verilated*.cpp
public: // But only for verilated*.cpp
// METHODS - export names
// Each function prototype is converted to a function number which we
@@ -367,7 +367,7 @@ public: // But only for verilated*.cpp
// We don't free up m_exportMap until the end, because we can't be sure
// what other models are using the assigned funcnum's.
public: // But only for verilated*.cpp
public: // But only for verilated*.cpp
// METHODS - file IO
static IData fdNew(FILE* fp) VL_MT_SAFE {
if (VL_UNLIKELY(!fp)) return 0;
+3 -3
View File
@@ -51,9 +51,9 @@ protected:
void* m_userthis; ///< Fake "this" for caller
vluint32_t m_code; ///< Starting code number
// CONSTRUCTORS
VerilatedLxt2CallInfo (VerilatedLxt2Callback_t icb, VerilatedLxt2Callback_t fcb,
VerilatedLxt2Callback_t changecb,
void* ut, vluint32_t code)
VerilatedLxt2CallInfo(VerilatedLxt2Callback_t icb, VerilatedLxt2Callback_t fcb,
VerilatedLxt2Callback_t changecb,
void* ut, vluint32_t code)
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {};
~VerilatedLxt2CallInfo() {}
};
+4 -4
View File
@@ -139,10 +139,10 @@ public:
void fullQuad(vluint32_t code, const vluint64_t newval, int bits) { chgQuad(code, newval, bits); }
void fullArray(vluint32_t code, const vluint32_t* newval, int bits) { chgArray(code, newval, bits); }
void declTriBit (vluint32_t code, const char* name, int arraynum);
void declTriBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
void declTriQuad (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
void declTriArray (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
void declTriBit(vluint32_t code, const char* name, int arraynum);
void declTriBus(vluint32_t code, const char* name, int arraynum, int msb, int lsb);
void declTriQuad(vluint32_t code, const char* name, int arraynum, int msb, int lsb);
void declTriArray(vluint32_t code, const char* name, int arraynum, int msb, int lsb);
void fullTriBit(vluint32_t code, const vluint32_t newval, const vluint32_t newtri);
void fullTriBus(vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits);
void fullTriQuad(vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits);
+11 -10
View File
@@ -32,7 +32,7 @@
# include <unistd.h>
#endif
#ifndef O_LARGEFILE // For example on WIN32
#ifndef O_LARGEFILE // For example on WIN32
# define O_LARGEFILE 0
#endif
#ifndef O_NONBLOCK
@@ -43,8 +43,8 @@
#endif
// CONSTANTS
static const char* const VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
static const char* const VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
//=============================================================================
//=============================================================================
@@ -119,7 +119,7 @@ void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n",filenamep););
if (filenamep[0]=='|') {
assert(0); // Not supported yet.
assert(0); // Not supported yet.
} else {
// cppcheck-suppress duplicateExpression
m_fd = ::open(filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC
@@ -142,7 +142,7 @@ void VerilatedRestore::open(const char* filenamep) VL_MT_UNSAFE_ONE {
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n",filenamep););
if (filenamep[0]=='|') {
assert(0); // Not supported yet.
assert(0); // Not supported yet.
} else {
// cppcheck-suppress duplicateExpression
m_fd = ::open(filenamep, O_CREAT|O_RDONLY|O_LARGEFILE|O_CLOEXEC
@@ -200,7 +200,7 @@ void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
}
}
}
m_cp = m_bufp; // Reset buffer
m_cp = m_bufp; // Reset buffer
}
void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
@@ -210,7 +210,7 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
vluint8_t* rp = m_bufp;
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
m_cp = m_bufp; // Reset buffer
// Read into buffer starting at m_endp
while (1) {
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
@@ -226,9 +226,10 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
VL_FATAL_MT("",0,"",msg.c_str());
close();
break;
}
} else { // got==0, EOF
// Fill buffer from here to end with NULLs so reader's don't need to check eof each character.
}
} else { // got==0, EOF
// Fill buffer from here to end with NULLs so reader's don't
// need to check eof each character.
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
break;
}
+1 -1
View File
@@ -248,4 +248,4 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& r
return os.read((void*)rhs.data(), len);
}
#endif // guard
#endif // Guard
+2 -2
View File
@@ -25,7 +25,7 @@
#ifndef _VERILATED_SC_H_
#define _VERILATED_SC_H_ 1 ///< Header Guard
#define _VERILATED_SC_H_ 1 ///< Header Guard
#include "verilatedos.h"
@@ -50,4 +50,4 @@ public:
//=========================================================================
#endif // guard
#endif // Guard
+2 -2
View File
@@ -30,7 +30,7 @@
#ifndef _VERILATED_SYM_PROPS_H_
#define _VERILATED_SYM_PROPS_H_ 1 ///< Header Guard
#define _VERILATED_SYM_PROPS_H_ 1 ///< Header Guard
#include "verilatedos.h"
@@ -223,4 +223,4 @@ public:
const char* name() const { return m_namep; }
};
#endif // Guard
#endif // Guard
+2 -2
View File
@@ -29,7 +29,7 @@
#ifndef _VERILATED_SYMS_H_
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
#include "verilatedos.h"
#include "verilated_heavy.h"
@@ -63,4 +63,4 @@ public:
~VerilatedVarNameMap() {}
};
#endif // Guard
#endif // Guard
+4 -4
View File
@@ -122,9 +122,9 @@ public:
class iterator {
protected:
// MEMBERS
size_t m_bucketIdx; // Bucket this iterator points into.
typename Bucket::iterator m_bit; // Bucket-local iterator.
const vl_unordered_set* m_setp; // The containing set.
size_t m_bucketIdx; // Bucket this iterator points into
typename Bucket::iterator m_bit; // Bucket-local iterator
const vl_unordered_set* m_setp; // The containing set
public:
// CONSTRUCTORS
@@ -469,7 +469,7 @@ private:
// MEMBERS
typedef vl_unordered_set<KeyValPair, KeyHash, KeyEqual> MapSet;
MapSet m_set; // Wrap this vl_unordered_set which holds all state.
MapSet m_set; // Wrap this vl_unordered_set which holds all state.
public:
// CONSTRUCTORS
+1 -1
View File
@@ -40,7 +40,7 @@ class VerilatedVcdCallInfo;
class VerilatedVcdFile {
private:
int m_fd; ///< File descriptor we're writing to
int m_fd; ///< File descriptor we're writing to
public:
// METHODS
VerilatedVcdFile() : m_fd(0) {}
+57 -55
View File
@@ -921,7 +921,7 @@ void VerilatedVpiError::selfTest() VL_MT_UNSAFE_ONE {
vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
// cppcheck-suppress nullPointer
if (VL_UNLIKELY(!cb_data_p)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s : callback data pointer is null", VL_FUNC);
@@ -963,7 +963,7 @@ PLI_INT32 vpi_remove_cb(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n",object););
VerilatedVpiImp::assertOneCheck();
VerilatedVpioCb* vop = VerilatedVpioCb::castp(object);
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!vop)) return 0;
if (vop->cb_datap()->reason == cbAfterDelay) {
VerilatedVpiImp::cbTimedRemove(vop);
@@ -987,7 +987,7 @@ void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) {
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!namep)) return NULL;
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_name %s %p\n",namep,scope););
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
@@ -1024,7 +1024,7 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_index %p %d\n",object, indx););
VerilatedVpiImp::assertOneCheck();
VerilatedVpioVar* varop = VerilatedVpioVar::castp(object);
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_LIKELY(varop)) {
if (varop->varp()->dims()<2) return 0;
if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) {
@@ -1049,7 +1049,7 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle %d %p\n",type,object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
switch (type) {
case vpiLeftRange: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
@@ -1092,7 +1092,7 @@ vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHa
vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_iterate %d %p\n",type,object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
switch (type) {
case vpiMemoryWord: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
@@ -1130,7 +1130,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
vpiHandle vpi_scan(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_scan %p\n",object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return NULL;
return vop->dovpi_scan();
@@ -1142,7 +1142,7 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
// Leave this in the header file - in many cases the compiler can constant propagate "object"
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get %d %p\n",property,object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
switch (property) {
case vpiTimePrecision: {
return VL_TIME_PRECISION;
@@ -1185,7 +1185,7 @@ PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_str %d %p\n",property,object););
VerilatedVpiImp::assertOneCheck();
VerilatedVpio* vop = VerilatedVpio::castp(object);
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!vop)) return NULL;
switch (property) {
case vpiName: {
@@ -1224,7 +1224,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1;
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n",object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!value_p)) return;
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
// We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
@@ -1295,10 +1295,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
for (i=0; i<bits; ++i) {
char val = (datap[i>>3]>>(i&7))&1;
outStr[bits-i-1] = val?'1':'0';
}
outStr[i]=0; // NULL terminate
return;
}
}
outStr[i] = '\0';
return;
}
default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
@@ -1345,10 +1345,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
}
}
outStr[chars-i-1] = '0' + (val&7);
}
outStr[i]=0; // NULL terminate
return;
}
}
outStr[i] = '\0';
return;
}
default:
strcpy(outStr, "0");
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
@@ -1404,10 +1404,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
}
}
outStr[chars-i-1] = "0123456789abcdef"[static_cast<int>(val)];
}
outStr[i]=0; // NULL terminate
return;
}
}
outStr[i] = '\0';
return;
}
default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
@@ -1436,10 +1436,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
char val = datap[bytes-i-1];
// other simulators replace [leading?] zero chars with spaces, replicate here.
outStr[i] = val?val:' ';
}
outStr[i]=0; // NULL terminate
return;
}
}
outStr[i] = '\0';
return;
}
default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
@@ -1456,9 +1456,9 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
case VLVT_UINT32:
value_p->value.integer = *(reinterpret_cast<IData*>(vop->varDatap()));
return;
case VLVT_WDATA: // FALLTHRU
case VLVT_UINT64: // FALLTHRU
default:
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());
@@ -1488,7 +1488,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
p_vpi_time time_p, PLI_INT32 flags) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value %p %p\n",object, value_p););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!value_p)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value with NULL value pointer");
return 0;
@@ -1578,8 +1578,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
int len = strlen(value_p->value.str);
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
div_t idx;
datap[0] = 0; // reset zero'th byte
for (int i=0; i<chars; ++i) {
datap[0] = 0; // reset zero'th byte
for (int i=0; i<chars; ++i) {
union {
char byte[2];
short half;
@@ -1605,11 +1605,12 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
// signifcant byte of the aligned value is the most significant
// byte of the destination.
val.half <<= idx.rem;
datap[idx.quot] |= val.byte[0]; // or in value
datap[idx.quot] |= val.byte[0]; // or in value
if ((idx.quot+1) < bytes) {
datap[idx.quot+1] = val.byte[1]; // this also resets all bits to 0 prior to or'ing above
}
}
datap[idx.quot+1] = val.byte[1]; // this also resets
// all bits to 0 prior to or'ing above
}
}
// mask off non existant bits in the most significant byte
if (idx.quot == (bytes-1)) {
datap[idx.quot] &= vop->mask_byte(idx.quot);
@@ -1692,9 +1693,10 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
if (i&1) {
datap[i>>1] |= hex<<4;
} else {
datap[i>>1] = hex; // this also resets all bits to 0 prior to or'ing above of the msb
}
}
datap[i>>1] = hex; // this also resets all
// bits to 0 prior to or'ing above of the msb
}
}
// apply bit mask to most significant byte
datap[(chars-1)>>1] &= vop->mask_byte((chars-1)>>1);
return object;
@@ -1736,9 +1738,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
case VLVT_UINT32:
*(reinterpret_cast<IData*>(vop->varDatap())) = vop->mask() & value_p->value.integer;
return object;
case VLVT_WDATA: // FALLTHRU
case VLVT_UINT64: // FALLTHRU
default:
case VLVT_WDATA: // FALLTHRU
case VLVT_UINT64: // FALLTHRU
default:
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
return 0;
@@ -1789,13 +1791,13 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
return VL_FOPEN_S(filenamep,"wb");
}
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
VL_FCLOSE_I(mcd); return 0;
}
@@ -1805,7 +1807,7 @@ PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
va_list ap;
va_start(ap,formatp);
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
@@ -1815,7 +1817,7 @@ PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
va_list ap;
va_start(ap,formatp);
int chars = vpi_vprintf(formatp, ap);
@@ -1825,14 +1827,14 @@ PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
return VL_VPRINTF(formatp, ap);
}
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
VerilatedVpiImp::assertOneCheck();
FILE* fp = VL_CVT_I_FP(mcd);
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
// cppcheck-suppress nullPointer
if (VL_UNLIKELY(!fp)) return 0;
int chars = vfprintf(fp, format, ap);
@@ -1841,7 +1843,7 @@ PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
PLI_INT32 vpi_flush(void) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
Verilated::flushCall();
return 0;
}
@@ -1849,7 +1851,7 @@ PLI_INT32 vpi_flush(void) {
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
VerilatedVpiImp::assertOneCheck();
FILE* fp = VL_CVT_I_FP(mcd);
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!fp)) return 1;
fflush(fp);
return 0;
@@ -1868,13 +1870,13 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
if (error_info_p && _error_info_p) {
*error_info_p = *_error_info_p;
}
if (!_error_info_p) return 0; // no error occured
if (!_error_info_p) return 0; // no error occured
return _error_info_p->level; // return error severity level
};
PLI_INT32 vpi_free_object(vpiHandle object) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
return vpi_release_handle(object); // Deprecated
}
@@ -1882,7 +1884,7 @@ PLI_INT32 vpi_release_handle(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_release_handle %p\n",object););
VerilatedVpiImp::assertOneCheck();
VerilatedVpio* vop = VerilatedVpio::castp(object);
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!vop)) return 0;
vpi_remove_cb(object); // May not be a callback, but that's ok
delete vop;
@@ -1891,7 +1893,7 @@ PLI_INT32 vpi_release_handle(vpiHandle object) {
PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) VL_MT_SAFE {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
vlog_info_p->argc = Verilated::getCommandArgs()->argc;
vlog_info_p->argv = (PLI_BYTE8**)Verilated::getCommandArgs()->argv;
vlog_info_p->product = (PLI_BYTE8*)Verilated::productName();
@@ -1917,7 +1919,7 @@ PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) {
PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_control %d\n",operation););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET(); // reset vpi error status
_VL_VPI_ERROR_RESET();
switch (operation) {
case vpiFinish: {
VL_FINISH_MT(__FILE__,__LINE__,"*VPI*");
+2 -3
View File
@@ -24,7 +24,7 @@
//=========================================================================
#ifndef _VERILATED_VPI_H_
#define _VERILATED_VPI_H_ 1 ///< Header Guard
#define _VERILATED_VPI_H_ 1 ///< Header Guard
#include "verilatedos.h"
#include "verilated.h"
@@ -49,5 +49,4 @@ public:
static void selfTest() VL_MT_UNSAFE_ONE;
};
#endif // Guard
#endif // Guard
+20 -20
View File
@@ -28,7 +28,7 @@
#ifndef _VERILATEDOS_H_
#define _VERILATEDOS_H_ 1 ///< Header Guard
#define _VERILATEDOS_H_ 1 ///< Header Guard
//=========================================================================
// Compiler pragma abstraction
@@ -188,14 +188,14 @@
#ifndef VL_WARNINGS
# ifdef _MSC_VER
# pragma warning(disable:4099) // C4099: type name first seen using 'class' now seen using 'struct' (V3AstNode)
# pragma warning(disable:4100) // C4100: unreferenced formal parameter (L4)
# pragma warning(disable:4127) // C4127: conditional expression is constant (L4)
# pragma warning(disable:4146) // C4146: unary minus operator applied to unsigned type, result still unsigned
# pragma warning(disable:4189) // C4189: local variable is initialized but not referenced (L4)
# pragma warning(disable:4244) // C4244: conversion from 'uint64_t' to 'uint_32_t', possible loss of data
# pragma warning(disable:4245) // C4245: conversion from 'int' to 'unsigned', signed/unsigned mismatch
# pragma warning(disable:4996) // C4996: sscanf/fopen/etc may be unsafe
# pragma warning(disable:4099) // C4099: type name first seen using 'class' now seen using 'struct' (V3AstNode)
# pragma warning(disable:4100) // C4100: unreferenced formal parameter (L4)
# pragma warning(disable:4127) // C4127: conditional expression is constant (L4)
# pragma warning(disable:4146) // C4146: unary minus operator applied to unsigned type, result still unsigned
# pragma warning(disable:4189) // C4189: local variable is initialized but not referenced (L4)
# pragma warning(disable:4244) // C4244: conversion from 'uint64_t' to 'uint_32_t', possible loss of data
# pragma warning(disable:4245) // C4245: conversion from 'int' to 'unsigned', signed/unsigned mismatch
# pragma warning(disable:4996) // C4996: sscanf/fopen/etc may be unsafe
# endif
#endif
@@ -211,10 +211,10 @@ typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward comp
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
typedef int32_t vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
# else // Older Cygwin has long==uint32_t
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
typedef int32_t vlsint32_t; ///< 32-bit signed type
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
# else // Older Cygwin has long==uint32_t
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
typedef long vlsint32_t; ///< 32-bit signed type
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
@@ -247,9 +247,9 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
# endif
# endif
#else // Linux or compliant Unix flavors, -m64
#else // Linux or compliant Unix flavors, -m64
# include <inttypes.h> // Solaris
# include <inttypes.h> // Solaris
# include <stdint.h> // Linux and most flavors
# include <sys/types.h> // __WORDSIZE
# include <unistd.h> // ssize_t
@@ -272,7 +272,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#ifdef _WIN32
# define VL_PRI64 "I64"
#else // Linux or compliant Unix flavors
#else // Linux or compliant Unix flavors
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
# define VL_PRI64 "l"
# else
@@ -297,7 +297,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#ifdef _WIN32
# define VL_DEV_NULL "nul"
#else // Linux or compliant Unix flavors
#else // Linux or compliant Unix flavors
# define VL_DEV_NULL "/dev/null"
#endif
@@ -341,9 +341,9 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
/// Mask for quads with 1's where relevant bits are (0=all bits)
#define VL_MASK_Q(nbits) (((nbits) & VL_SIZEBITS_Q) \
? ((VL_ULL(1) << ((nbits) & VL_SIZEBITS_Q) )-VL_ULL(1)) : VL_ULL(~0))
#define VL_BITWORD_I(bit) ((bit)/VL_WORDSIZE) ///< Word number for a wide quantity
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
#define VL_BITWORD_I(bit) ((bit)/VL_WORDSIZE) ///< Word number for a wide quantity
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
//=========================================================================
// Floating point
+3 -3
View File
@@ -8,7 +8,7 @@ use IO::File;
use Pod::Usage;
use Data::Dumper; $Data::Dumper::Indent=1;
use strict;
use vars qw ($Debug);
use vars qw($Debug);
#======================================================================
@@ -32,14 +32,14 @@ if (! GetOptions (
usage();
}
dotread ($opt_filename);
dotread($opt_filename);
cwrite("graph_export.cpp");
#----------------------------------------------------------------------
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1);
exit(1);
}
sub debug {
+3 -3
View File
@@ -8,7 +8,7 @@ use IO::File;
use Pod::Usage;
use Data::Dumper; $Data::Dumper::Indent=1;
use strict;
use vars qw ($Debug);
use vars qw($Debug);
#======================================================================
@@ -35,7 +35,7 @@ if (! GetOptions (
usage();
}
dotread ($opt_filename);
dotread($opt_filename);
circle($opt_circle) if $opt_circle;
simplify();
dotwrite();
@@ -44,7 +44,7 @@ dotwrite();
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1);
exit(1);
}
sub debug {
+6 -6
View File
@@ -47,12 +47,12 @@ sub prep {
my @lines;
while (defined(my $line = $fh->getline)) {
# Productions
#$line =~ s/[ \t]{[^}]*?}/\t{}/g;
$line =~ s/StashPrefix;//g;
$line =~ s/VALTEXT;//g;
$line =~ s/CALLBACK\([^)]*\);//g;
push @lines, $line;
# Productions
#$line =~ s/[ \t]{[^}]*?}/\t{}/g;
$line =~ s/StashPrefix;//g;
$line =~ s/VALTEXT;//g;
$line =~ s/CALLBACK\([^)]*\);//g;
push @lines, $line;
}
#@lines = sort @lines;
+15 -3
View File
@@ -8,7 +8,7 @@ use IO::File;
use IO::Dir;
use Pod::Usage;
use strict;
use vars qw ($Debug);
use vars qw($Debug);
our $VERSION = '0.001';
our $Opt_Widen = 1;
@@ -18,7 +18,7 @@ our $Opt_Widen = 1;
autoflush STDOUT 1;
autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
Getopt::Long::config("no_auto_abbrev");
if (! GetOptions (
"debug" => sub { $Debug = 1; },
"help" => sub { print "Version $VERSION\n";
@@ -87,6 +87,18 @@ sub find_edits {
my $hunk = $editlines->{$lineno}{hunk};
$hunk_lastlines{$hunk} ||= $lineno if $editlines->{$lineno}{user_edit};
}
# Expand to include }'s that finish basic block
foreach my $hunk (keys %hunk_lastlines) {
while (my $lineno = $hunk_lastlines{$hunk}) {
++$lineno;
if (($editlines->{$lineno}{line} || "")
=~ /^[+ ]\s+}[ \t};]*$/) {
$hunk_lastlines{$hunk} = $lineno;
} else {
last;
}
}
}
# Expand to always untabify at least 3 lines (so that future diff will
# have non-tabs within a edit hunk distance
foreach my $hunk (keys %hunk_firstlines) {
@@ -100,7 +112,7 @@ sub find_edits {
}
foreach my $lineno (sort {$a <=> $b} keys %$editlines) {
if ($editlines->{$lineno}{line} =~ /\t/) {
if (($editlines->{$lineno}{line}||"") =~ /\t/) {
my $hunk = $editlines->{$lineno}{hunk};
if ($hunk_firstlines{$hunk} <= $lineno && $hunk_lastlines{$hunk} >= $lineno) {
$editlines->{$lineno}{editit} = 1;
+2 -2
View File
@@ -7,7 +7,7 @@ use Cwd;
use IO::File;
use Pod::Usage;
use strict;
use vars qw ($Debug);
use vars qw($Debug);
#======================================================================
# main
@@ -17,7 +17,7 @@ our $Opt_Jobs = calc_jobs();
autoflush STDOUT 1;
autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev");
Getopt::Long::config("no_auto_abbrev");
if (! GetOptions (
"debug" => sub { $Debug = 1; },
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
+3 -3
View File
@@ -8,7 +8,7 @@ use IO::File;
use Pod::Usage;
use Data::Dumper; $Data::Dumper::Indent=1;
use strict;
use vars qw ($Debug);
use vars qw($Debug);
#======================================================================
@@ -31,7 +31,7 @@ if (! GetOptions (
usage();
}
vread ($opt_filename);
vread($opt_filename);
#print Dumper($Tree);
vwrite();
@@ -41,7 +41,7 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
sub usage {
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1);
exit(1);
}
sub debug {
+81 -23
View File
@@ -464,18 +464,61 @@ public:
//######################################################################
class VDirection {
public:
enum en {
NONE,
INPUT,
OUTPUT,
INOUT,
REF,
CONSTREF
};
enum en m_e;
inline VDirection() : m_e(NONE) {}
// cppcheck-suppress noExplicitConstructor
inline VDirection(en _e) : m_e(_e) {}
explicit inline VDirection(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[] = {
"NONE", "INPUT", "OUTPUT", "INOUT", "REF", "CONSTREF"};
return names[m_e]; }
string verilogKwd() const {
static const char* const names[] = {
"", "input", "output", "inout", "ref", "const ref"};
return names[m_e]; }
string xmlKwd() const { // For historical reasons no "put" suffix
static const char* const names[] = {
"", "in", "out", "inout", "ref", "const ref"};
return names[m_e]; }
string prettyName() const { return verilogKwd(); }
bool isAny() const { return m_e != NONE; }
// Looks like inout - "ish" because not identical to being an INOUT
bool isInoutish() const { return m_e == INOUT; }
bool isNonOutput() const { return m_e == INPUT || m_e == INOUT
|| m_e == REF || m_e == CONSTREF; }
bool isReadOnly() const { return m_e == INPUT || m_e == CONSTREF; }
bool isWritable() const { return m_e == OUTPUT || m_e == INOUT
|| m_e == REF; }
bool isRefOrConstRef() const { return m_e == REF || m_e == CONSTREF; }
};
inline bool operator== (VDirection lhs, VDirection rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (VDirection lhs, VDirection::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (VDirection::en lhs, VDirection rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { return os<<rhs.ascii(); }
//######################################################################
class AstVarType {
public:
enum en {
UNKNOWN,
GPARAM,
LPARAM,
GENVAR,
VAR, // Reg, integer, logic, etc
INPUT,
OUTPUT,
INOUT,
SUPPLY0,
UNKNOWN,
GPARAM,
LPARAM,
GENVAR,
VAR, // Reg, integer, logic, etc
SUPPLY0,
SUPPLY1,
WIRE,
WREAL,
@@ -497,20 +540,35 @@ public:
explicit inline AstVarType(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[] = {
"?","GPARAM","LPARAM","GENVAR",
"VAR","INPUT","OUTPUT","INOUT",
"SUPPLY0","SUPPLY1","WIRE","WREAL","IMPLICITWIRE",
"TRIWIRE","TRI0","TRI1",
"PORT",
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
"IFACEREF"};
return names[m_e]; }
bool isSignal() const { return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|| m_e==TRIWIRE
|| m_e==TRI0 || m_e==TRI1
|| m_e==SUPPLY0 || m_e==SUPPLY1
|| m_e==VAR); }
static const char* const names[] = {
"?", "GPARAM", "LPARAM", "GENVAR", "VAR",
"SUPPLY0", "SUPPLY1", "WIRE", "WREAL", "IMPLICITWIRE",
"TRIWIRE", "TRI0", "TRI1",
"PORT",
"BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP",
"IFACEREF"};
return names[m_e]; }
bool isSignal() const {
return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|| m_e==TRIWIRE
|| m_e==TRI0 || m_e==TRI1 || m_e==PORT
|| m_e==SUPPLY0 || m_e==SUPPLY1
|| m_e==VAR);
}
bool isContAssignable() const { // In Verilog, always ok in SystemVerilog
return (m_e==SUPPLY0 || m_e==SUPPLY1
|| m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|| m_e==TRIWIRE || m_e==TRI0 || m_e==TRI1 || m_e==PORT
|| m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP
|| m_e==XTEMP || m_e==IFACEREF);
}
bool isProcAssignable() const {
return (m_e==GPARAM || m_e==LPARAM || m_e==GENVAR
|| m_e==VAR
|| m_e==TRIWIRE || m_e==TRI0 || m_e==TRI1 || m_e==PORT
|| m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP
|| m_e==XTEMP || m_e==IFACEREF);
}
};
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); }
+76 -70
View File
@@ -178,89 +178,98 @@ void AstVar::combineType(AstVarType type) {
// These flags get combined with the existing settings of the flags.
// We don't test varType for certain types, instead set flags since
// when we combine wires cross-hierarchy we need a union of all characteristics.
m_varType=type; // For debugging prints only
m_varType = type;
// These flags get combined with the existing settings of the flags.
if (type==AstVarType::INPUT || type==AstVarType::INOUT) {
m_input = true;
m_declInput = true;
if (type==AstVarType::TRIWIRE || type==AstVarType::TRI0 || type==AstVarType::TRI1) {
m_tristate = true;
}
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
m_output = true;
m_declOutput = true;
if (type==AstVarType::TRI0) {
m_isPulldown = true;
}
if (type==AstVarType::TRI1) {
m_isPullup = true;
}
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE
|| type==AstVarType::TRI0 || type==AstVarType::TRI1)
m_tristate = true;
if (type==AstVarType::TRI0)
m_isPulldown = true;
if (type==AstVarType::TRI1)
m_isPullup = true;
}
string AstVar::verilogKwd() const {
if (isInout()) {
return "inout";
} else if (isInput()) {
return "input";
} else if (isOutput()) {
return "output";
if (isIO()) {
return direction().verilogKwd();
} else if (isTristate()) {
return "tri";
return "tri";
} else if (varType()==AstVarType::WIRE) {
return "wire";
return "wire";
} else if (varType()==AstVarType::WREAL) {
return "wreal";
return "wreal";
} else {
return dtypep()->name();
return dtypep()->name();
}
}
string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
if (forReturn) named=false;
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
string arg;
if (isWide() && isInOnly()) arg += "const ";
string otype;
AstBasicDType* bdtypep = basicp();
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
arg += "const char*";
otype += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
arg += "const VerilatedScope*";
otype += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
arg += "double";
if (forFunc && isReadOnly()) otype += "const ";
otype += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
arg += "float";
if (forFunc && isReadOnly()) otype += "const ";
otype += "float";
} else if (strtype) {
if (isInOnly()) arg += "const ";
arg += "std::string";
if (forFunc && isReadOnly()) otype += "const ";
otype += "std::string";
} else if (widthMin() <= 8) {
arg += "CData";
if (forFunc && isReadOnly()) otype += "const ";
otype += "CData";
} else if (widthMin() <= 16) {
arg += "SData";
if (forFunc && isReadOnly()) otype += "const ";
otype += "SData";
} else if (widthMin() <= VL_WORDSIZE) {
arg += "IData";
if (forFunc && isReadOnly()) otype += "const ";
otype += "IData";
} else if (isQuad()) {
arg += "QData";
if (forFunc && isReadOnly()) otype += "const ";
otype += "QData";
} else if (isWide()) {
arg += "WData"; // []'s added later
if (forFunc && isReadOnly()) otype += "const ";
otype += "WData"; // []'s added later
}
if (isDpiOpenArray() || (isWide() && !strtype)) {
arg += " (& "+name()+")";
bool mayparen = false; // Need paren, to handle building "(& name)[2]"
string oname;
if (isDpiOpenArray()
|| (isWide() && !strtype)
|| (forFunc && (isWritable()
|| direction()==VDirection::REF
|| direction()==VDirection::CONSTREF
|| (strtype && isNonOutput())))) {
oname += "&";
mayparen = true;
}
if (named) oname += " "+name();
string oarray;
if (isDpiOpenArray() || direction().isRefOrConstRef()) {
for (AstNodeDType* dtp=dtypep(); dtp; ) {
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
if (AstUnpackArrayDType* adtypep = VN_CAST(dtp, UnpackArrayDType)) {
arg += "["+cvtToStr(adtypep->declRange().elements())+"]";
if (mayparen) { oname = " ("+oname+")"; mayparen = false; }
oarray += "["+cvtToStr(adtypep->declRange().elements())+"]";
dtp = adtypep->subDTypep();
} else break;
}
if (isWide() && !strtype) {
arg += "["+cvtToStr(widthWords())+"]";
}
} else {
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
if (named) arg += " "+name();
}
return arg;
if (isWide() && !strtype) {
if (mayparen) { oname = " ("+oname+")"; mayparen = false; }
oarray += "["+cvtToStr(widthWords())+"]";
}
return otype+oname+oarray;
}
string AstVar::vlEnumType() const {
@@ -290,12 +299,12 @@ string AstVar::vlEnumType() const {
string AstVar::vlEnumDir() const {
string out;
if (isInout()) {
if (isInoutish()) {
out = "VLVD_INOUT";
} else if (isInOnly()) {
out = "VLVD_IN";
} else if (isOutOnly()) {
} else if (isWritable()) {
out = "VLVD_OUT";
} else if (isNonOutput()) {
out = "VLVD_IN";
} else {
out = "VLVD_NODIR";
}
@@ -336,7 +345,7 @@ string AstVar::vlPropInit() const {
string AstVar::cPubArgType(bool named, bool forReturn) const {
if (forReturn) named=false;
string arg;
if (isWide() && isInOnly()) arg += "const ";
if (isWide() && isReadOnly()) arg += "const ";
if (widthMin() == 1) {
arg += "bool";
} else if (widthMin() <= VL_WORDSIZE) {
@@ -351,8 +360,9 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
arg += " (& "+name();
arg += ")["+cvtToStr(widthWords())+"]";
} else {
if (isOutput() && !forReturn) arg += "&";
if (named) arg += " "+name();
if (!forReturn && (isWritable()
|| direction().isRefOrConstRef())) arg += "&";
if (named) arg += " "+name();
}
return arg;
}
@@ -367,11 +377,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
} else if (basicp()->keyword().isDpiBitVal()) {
if (widthMin() == 1) {
arg = "unsigned char";
if (!forReturn && isOutput()) arg += "*";
} else {
if (forReturn) {
arg = "svBitVecVal";
} else if (isInOnly()) {
if (!forReturn && isWritable()) arg += "*";
} else {
if (forReturn) {
arg = "svBitVecVal";
} else if (isReadOnly()) {
arg = "const svBitVecVal*";
} else {
arg = "svBitVecVal*";
@@ -380,11 +390,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
} else if (basicp()->keyword().isDpiLogicVal()) {
if (widthMin() == 1) {
arg = "unsigned char";
if (!forReturn && isOutput()) arg += "*";
if (!forReturn && isWritable()) arg += "*";
} else {
if (forReturn) {
arg = "svLogicVecVal";
} else if (isInOnly()) {
} else if (isReadOnly()) {
arg = "const svLogicVecVal*";
} else {
arg = "svLogicVecVal*";
@@ -394,8 +404,8 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
arg = basicp()->keyword().dpiType();
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
arg = "unsigned "+arg;
}
if (!forReturn && isOutput()) arg += "*";
}
if (!forReturn && isWritable()) arg += "*";
}
if (named) arg += " "+name();
return arg;
@@ -898,7 +908,7 @@ void AstModportFTaskRef::dump(std::ostream& str) {
}
void AstModportVarRef::dump(std::ostream& str) {
this->AstNode::dump(str);
str<<" "<<varType();
if (direction().isAny()) str<<" "<<direction();
if (varp()) { str<<" -> "; varp()->dump(str); }
else { str<<" -> UNLINKED"; }
}
@@ -1061,12 +1071,8 @@ void AstVarRef::dump(std::ostream& str) {
void AstVar::dump(std::ostream& str) {
this->AstNode::dump(str);
if (isSc()) str<<" [SC]";
if (isPrimaryIO()) str<<(isInout()?" [PIO]":(isInput()?" [PI]":" [PO]"));
else {
if (isInout()) str<<" [IO]";
else if (isInput()) str<<" [I]";
else if (isOutput()) str<<" [O]";
}
if (isPrimaryIO()) str<<(isInoutish()?" [PIO]":(isWritable()?" [PO]":" [PI]"));
if (isIO()) str<<" "<<direction().ascii();
if (isConst()) str<<" [CONST]";
if (isPullup()) str<<" [PULLUP]";
if (isPulldown()) str<<" [PULLDOWN]";
+51 -52
View File
@@ -1096,12 +1096,10 @@ private:
string m_origName; // Original name before dot addition
string m_tag; // Holds the string of the verilator tag -- used in XML output.
AstVarType m_varType; // Type of variable
VDirection m_direction; // Direction input/output etc
VDirection m_declDirection; // Declared direction input/output etc
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
bool m_input:1; // Input or inout
bool m_output:1; // Output or inout
bool m_tristate:1; // Inout or triwire or trireg
bool m_declInput:1; // Inout or input before tristate and inline resolution
bool m_declOutput:1; // Inout or output before tristate and inline resolution
bool m_primaryIO:1; // In/out to top level (or directly assigned from same)
bool m_sc:1; // SystemC variable
bool m_scClocked:1; // SystemC sc_clk<> needed
@@ -1132,10 +1130,9 @@ private:
AstVarAttrClocker m_attrClocker;
MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var
void init() {
m_input=false; m_output=false; m_tristate=false; m_declInput=false; m_declOutput=false;
m_primaryIO=false;
m_sc=false; m_scClocked=false; m_scSensitive=false;
void init() {
m_tristate=false; m_primaryIO=false;
m_sc=false; m_scClocked=false; m_scSensitive=false;
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
m_funcLocal=false; m_funcReturn=false;
@@ -1201,9 +1198,16 @@ public:
string origName() const { return m_origName; } // * = Original name
void origName(const string& name) { m_origName = name; }
AstVarType varType() const { return m_varType; } // * = Type of variable
void direction(const VDirection& flag) {
m_direction = flag;
if (m_direction == VDirection::INOUT) m_tristate = true; }
VDirection direction() const { return m_direction; }
bool isIO() const { return m_direction != VDirection::NONE; }
void declDirection(const VDirection& flag) { m_declDirection = flag; }
VDirection declDirection() const { return m_declDirection; }
void varType(AstVarType type) { m_varType = type; }
void varType2Out() { m_tristate=0; m_input=0; m_output=1; }
void varType2In() { m_tristate=0; m_input=1; m_output=0; }
void varType2Out() { m_tristate=0; m_direction=VDirection::OUTPUT; }
void varType2In() { m_tristate=0; m_direction=VDirection::INPUT; }
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
@@ -1258,19 +1262,13 @@ public:
virtual void name(const string& name) { m_name = name; }
virtual void tag(const string& text) { m_tag = text;}
virtual string tag() const { return m_tag; }
virtual string directionName() const { return (isInout() ? "inout" : isInput() ? "input"
: isOutput() ? "output" : varType().ascii()); }
bool isInput() const { return m_input; }
bool isOutput() const { return m_output; }
bool isInOnly() const { return m_input && !m_output; }
bool isOutOnly() const { return m_output && !m_input; }
bool isInout() const { return m_input && m_output; }
bool isInoutish() const { return m_direction.isInoutish(); }
bool isNonOutput() const { return m_direction.isNonOutput(); }
bool isReadOnly() const { return m_direction.isReadOnly(); }
bool isWritable() const { return m_direction.isWritable(); }
bool isTristate() const { return m_tristate; }
bool isDeclInput() const { return m_declInput; }
bool isDeclOutput() const { return m_declOutput; }
bool isPrimaryIO() const { return m_primaryIO; }
bool isPrimaryIn() const { return isPrimaryIO() && isInput(); }
bool isIO() const { return (m_input||m_output); }
bool isPrimaryIO() const { return m_primaryIO; }
bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); }
bool isIfaceRef() const { return (varType()==AstVarType::IFACEREF); }
bool isIfaceParent() const { return m_isIfaceParent; }
bool isSignal() const { return varType().isSignal(); }
@@ -1326,8 +1324,9 @@ public:
// Ok to gate optimize; must return false if propagateAttrFrom would do anything
return (!attrClockEn() && !isUsedClock());
}
void combineType(AstVar* typevarp) {
// This is same as typevarp (for combining input & reg decls)
void combineType(AstVar* typevarp) {
// This is same as typevarp (for combining input & reg decls)
// "this" is the input var. typevarp is the reg var.
propagateAttrFrom(typevarp);
combineType(typevarp->varType());
if (typevarp->isSigPublic()) sigPublic(true);
@@ -1337,9 +1336,11 @@ public:
if (typevarp->attrScClocked()) attrScClocked(true);
}
void inlineAttrReset(const string& name) {
m_input=m_output=false; m_name = name;
if (varType()==AstVarType::INOUT) m_varType = AstVarType::TRIWIRE;
if (varType()==AstVarType::INPUT || varType()==AstVarType::OUTPUT) m_varType = AstVarType::WIRE;
if (direction()==VDirection::INOUT && varType()==AstVarType::WIRE) {
m_varType = AstVarType::TRIWIRE;
}
m_direction = VDirection::NONE;
m_name = name;
}
static AstVar* scVarRecurse(AstNode* nodep);
void addProducingMTaskId(int id) { m_mtaskIds.insert(id); }
@@ -1577,10 +1578,13 @@ public:
return NULL; }
virtual string name() const { return m_name; } // * = Pin name, ""=go by number
virtual void name(const string& name) { m_name = name; }
virtual string prettyOperatorName() const { return modVarp()
? (modVarp()->directionName()+" port connection '"+modVarp()->prettyName()+"'")
: "port connection"; }
bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked
virtual string prettyOperatorName() const {
return modVarp() ? ((modVarp()->direction().isAny()
? modVarp()->direction().prettyName()+" "
: "")
+"port connection '"+modVarp()->prettyName()+"'")
: "port connection"; }
bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked
int pinNum() const { return m_pinNum; }
void exprp(AstNode* nodep) { addOp1p(nodep); }
AstNode* exprp() const { return op1p(); } // op1 = Expression connected to pin, NULL if unconnected
@@ -1730,19 +1734,18 @@ class AstModportVarRef : public AstNode {
// PARENT: AstModport
private:
string m_name; // Name of the variable referenced
AstVarType m_type; // Type of the variable (in/out)
AstVar* m_varp; // Link to the actual Var
VDirection m_direction; // Direction of the variable (in/out)
AstVar* m_varp; // Link to the actual Var
public:
AstModportVarRef(FileLine* fl, const string& name, AstVarType::en type)
: AstNode(fl), m_name(name), m_type(type), m_varp(NULL) { }
AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction)
: AstNode(fl), m_name(name), m_direction(direction), m_varp(NULL) { }
ASTNODE_NODE_FUNCS(ModportVarRef)
virtual const char* broken() const { BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; }
virtual void dump(std::ostream& str);
virtual void cloneRelink() { if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); }
virtual string name() const { return m_name; }
AstVarType varType() const { return m_type; } // * = Type of variable
bool isInput() const { return (varType()==AstVarType::INPUT || varType()==AstVarType::INOUT); }
bool isOutput() const { return (varType()==AstVarType::OUTPUT || varType()==AstVarType::INOUT); }
void direction(const VDirection& flag) { m_direction = flag; }
VDirection direction() const { return m_direction; }
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
void varp(AstVar* varp) { m_varp=varp; }
};
@@ -3367,8 +3370,7 @@ private:
uint32_t m_codeInc; // Code increment
AstVarType m_varType; // Type of variable (for localparam vs. param)
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
bool m_declInput:1; // Input or inout
bool m_declOutput:1; // Output or inout
VDirection m_declDirection; // Declared direction input/output etc
public:
AstTraceDecl(FileLine* fl, const string& showname,
AstVar* varp, // For input/output state etc
@@ -3382,8 +3384,7 @@ public:
* valuep->dtypep()->widthWords());
m_varType = varp->varType();
m_declKwd = varp->declKwd();
m_declInput = varp->isDeclInput();
m_declOutput = varp->isDeclOutput();
m_declDirection = varp->declDirection();
}
virtual int instrCount() const { return 100; } // Large...
ASTNODE_NODE_FUNCS(TraceDecl)
@@ -3400,9 +3401,7 @@ public:
const VNumRange& arrayRange() const { return m_arrayRange; }
AstVarType varType() const { return m_varType; }
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
bool declInput() const { return m_declInput; }
bool declOutput() const { return m_declOutput; }
bool declInout() const { return m_declInput && m_declOutput; }
VDirection declDirection() const { return m_declDirection; }
};
class AstTraceInc : public AstNodeStmt {
@@ -5853,15 +5852,15 @@ class AstNetlist : public AstNode {
// Parents: none
// Children: MODULEs & CFILEs
private:
AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup
AstPackage* m_dollarUnitPkgp;
AstCFunc* m_evalp; // The '_eval' function
AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup
AstPackage* m_dollarUnitPkgp; // $unit
AstCFunc* m_evalp; // The '_eval' function
AstExecGraph* m_execGraphp; // Execution MTask graph for threads>1 mode
public:
AstNetlist()
: AstNode(new FileLine("AstRoot",0))
, m_typeTablep(NULL)
, m_dollarUnitPkgp(NULL)
: AstNode(new FileLine("AstRoot", 0))
, m_typeTablep(NULL)
, m_dollarUnitPkgp(NULL)
, m_evalp(NULL)
, m_execGraphp(NULL) { }
ASTNODE_NODE_FUNCS(Netlist)
@@ -5877,7 +5876,7 @@ public:
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
AstCFile* filesp() const { return VN_CAST(op2p(), CFile);} // op2 = List of files
void addFilesp(AstCFile* filep) { addOp2p(filep); }
AstNode* miscsp() const { return op3p();} // op3 = List of dtypes etc
AstNode* miscsp() const { return op3p(); } // op3 = List of dtypes etc
void addMiscsp(AstNode* nodep) { addOp3p(nodep); }
AstTypeTable* typeTablep() { return m_typeTablep; }
void addTypeTablep(AstTypeTable* nodep) { m_typeTablep = nodep; addMiscsp(nodep); }
+1 -1
View File
@@ -114,7 +114,7 @@ void V3CCtors::evalAsserts() {
modp->addStmtp(funcp);
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
if (AstVar* varp = VN_CAST(np, Var)) {
if (varp->isPrimaryIn() && !varp->isSc()) {
if (varp->isPrimaryInish() && !varp->isSc()) {
if (AstBasicDType* basicp = VN_CAST(varp->dtypeSkipRefp(), BasicDType)) {
int storedWidth = basicp->widthAlignBytes() * 8;
int lastWordWidth = varp->width() % storedWidth;
+19 -17
View File
@@ -258,13 +258,13 @@ private:
// Create IO vertex - note it's relative to the pointed to var, not where we are now
// This allows reporting to easily print the input statement
CdcLogicVertex* ioVertexp = new CdcLogicVertex(&m_graph, varscp->scopep(), varscp->varp(), NULL);
if (varscp->varp()->isInput()) {
new V3GraphEdge(&m_graph, ioVertexp, vertexp, 1);
} else {
new V3GraphEdge(&m_graph, vertexp, ioVertexp, 1);
}
}
}
if (varscp->varp()->isWritable()) {
new V3GraphEdge(&m_graph, vertexp, ioVertexp, 1);
} else {
new V3GraphEdge(&m_graph, ioVertexp, vertexp, 1);
}
}
}
if (m_inSenItem) {
varscp->user2(true); // It's like a clock...
// TODO: In the future we could mark it here and do normal clock tree glitch checks also
@@ -372,9 +372,9 @@ private:
}
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
if (mark) vvertexp->asyncPath(true);
// If primary I/O, it's ok here back
if (vvertexp->varScp()->varp()->isPrimaryIn()) {
// Show the source "input" statement if it exists
// If primary I/O, it's ok here back
if (vvertexp->varScp()->varp()->isPrimaryInish()) {
// Show the source "input" statement if it exists
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
CdcEitherVertex* eFromVertexp = static_cast<CdcEitherVertex*>(edgep->fromp());
eFromVertexp->asyncPath(true);
@@ -501,8 +501,8 @@ private:
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
AstVar* varp = vvertexp->varScp()->varp();
if (1) { // varp->isPrimaryIO()
const char* whatp = "wire";
if (varp->isPrimaryIO()) whatp = (varp->isInout()?"inout":varp->isInput()?"input":"output");
string what = "wire";
if (varp->isPrimaryIO()) what = varp->direction().prettyName();
std::ostringstream os;
os.setf(std::ios::left);
@@ -510,7 +510,7 @@ private:
// so we assume the modulename matches the filebasename
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
os<<" "<<std::setw(20)<<fname;
os<<" "<<std::setw(8)<<whatp;
os<<" "<<std::setw(8)<<what;
os<<" "<<std::setw(40)<<vvertexp->varScp()->prettyName();
os<<" SRC=";
if (vvertexp->srcDomainp()) V3EmitV::verilogForTree(vvertexp->srcDomainp(), os);
@@ -545,10 +545,12 @@ private:
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
// If primary I/O, give it domain of the input
AstVar* varp = vvertexp->varScp()->varp();
if (varp->isPrimaryIO() && varp->isInput() && !traceDests) {
senouts.insert(new AstSenTree(varp->fileline(), new AstSenItem(varp->fileline(), AstSenItem::Combo())));
}
}
if (varp->isPrimaryIO() && varp->isNonOutput() && !traceDests) {
senouts.insert(
new AstSenTree(varp->fileline(),
new AstSenItem(varp->fileline(), AstSenItem::Combo())));
}
}
// Now combine domains of sources/dests
if (traceDests) {
+4 -3
View File
@@ -1538,9 +1538,10 @@ private:
&& ((!m_params // Can reduce constant wires into equations
&& m_doNConst
&& v3Global.opt.oConst()
&& !(nodep->varp()->isFuncLocal() // Default value, not a "known" constant for this usage
&& nodep->varp()->isInput())
&& !nodep->varp()->noSubst()
// Default value, not a "known" constant for this usage
&& !(nodep->varp()->isFuncLocal()
&& nodep->varp()->isNonOutput())
&& !nodep->varp()->noSubst()
&& !nodep->varp()->isSigPublic())
|| nodep->varp()->isParam())) {
if (operandConst(valuep)) {
+8 -7
View File
@@ -183,13 +183,14 @@ private:
AstNode* argsp = NULL;
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && !portp->isFuncReturn()) {
AstNode* newp = new AstVarRef(portp->fileline(), portp, portp->isOutput());
if (argsp) argsp = argsp->addNextNull(newp);
else argsp = newp;
}
}
}
if (portp->isIO() && !portp->isFuncReturn()) {
AstNode* newp = new AstVarRef(portp->fileline(),
portp, portp->isWritable());
if (argsp) argsp = argsp->addNextNull(newp);
else argsp = newp;
}
}
}
AstNode* returnp = new AstCReturn(funcp->fileline(),
new AstCCall(funcp->fileline(),
+29 -29
View File
@@ -1086,8 +1086,8 @@ class EmitCImp : EmitCStmts {
}
}
if (gotOne) {
puts(");\n");
//puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );");
puts(");\n");
//puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );");
for (std::vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
it != m_blkChangeDetVec.end(); ++it) {
AstChangeDet* nodep = *it;
@@ -1211,13 +1211,13 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
if (nodep->isIO()) {
if (nodep->isSc()) {
m_ctorVarsVec.push_back(nodep);
if (nodep->attrScClocked() && nodep->isInput()) {
puts("sc_in_clk ");
} else {
if (nodep->isInout()) puts("sc_inout<");
else if (nodep->isInput()) puts("sc_in<");
else if (nodep->isOutput()) puts("sc_out<");
else nodep->v3fatalSrc("Unknown type");
if (nodep->attrScClocked() && nodep->isReadOnly()) {
puts("sc_in_clk ");
} else {
if (nodep->isInoutish()) puts("sc_inout<");
else if (nodep->isWritable()) puts("sc_out<");
else if (nodep->isNonOutput()) puts("sc_in<");
else nodep->v3fatalSrc("Unknown type");
puts(nodep->scType());
puts("> ");
@@ -1230,11 +1230,11 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
puts(nodep->vlArgType(true,false,false));
emitDeclArrayBrackets(nodep);
puts(";\n");
} else { // C++ signals
if (nodep->isInout()) puts("VL_INOUT");
else if (nodep->isInput()) puts("VL_IN");
else if (nodep->isOutput()) puts("VL_OUT");
else nodep->v3fatalSrc("Unknown type");
} else { // C++ signals
if (nodep->isInoutish()) puts("VL_INOUT");
else if (nodep->isWritable()) puts("VL_OUT");
else if (nodep->isNonOutput()) puts("VL_IN");
else nodep->v3fatalSrc("Unknown type");
if (nodep->isQuad()) puts("64");
else if (nodep->widthMin() <= 8) puts("8");
@@ -1990,9 +1990,10 @@ void EmitCImp::emitSensitives() {
puts("SC_METHOD(eval);\n");
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstVar* varp = VN_CAST(nodep, Var)) {
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
int vects = 0;
// This isn't very robust and may need cleanup for other data types
if (varp->isNonOutput() && (varp->isScSensitive()
|| varp->isUsedClock())) {
int vects = 0;
// This isn't very robust and may need cleanup for other data types
for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType);
arrayp;
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
@@ -2608,11 +2609,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
//----------------------------------------------------------------------
void EmitCImp::emitImp(AstNodeModule* modp) {
ofp()->printf("#include \"%-20s // For This\n",
(modClassName(modp)+".h\"").c_str());
// Us
puts("#include \""+ symClassName() +".h\"\n");
puts("#include \""+modClassName(modp)+".h\"\n");
puts("#include \""+symClassName()+".h\"\n");
if (v3Global.dpi()) {
puts("\n");
@@ -2732,10 +2730,11 @@ class EmitCTrace : EmitCStmts {
// METHODS
void newOutCFile(int filenum) {
string filename = (v3Global.opt.makeDir()+"/"+ topClassName()
+ (m_slow?"__Trace__Slow":"__Trace"));
if (filenum) filename += "__"+cvtToStr(filenum);
filename += ".cpp";
string filename = (v3Global.opt.makeDir()+"/"+ topClassName()
+"__Trace");
if (filenum) filename += "__"+cvtToStr(filenum);
filename += (m_slow ? "__Slow":"");
filename += ".cpp";
AstCFile* cfilep = newCFile(filename, m_slow, true/*source*/);
cfilep->support(true);
@@ -2852,9 +2851,9 @@ class EmitCTrace : EmitCStmts {
if (v3Global.opt.traceFormat() == TraceFormat::FST) {
puts(","+cvtToStr(enumNum));
// fstVarDir
if (nodep->declInout()) puts(",FST_VD_INOUT");
else if (nodep->declInput()) puts(",FST_VD_INPUT");
else if (nodep->declOutput()) puts(",FST_VD_OUTPUT");
if (nodep->declDirection().isInoutish()) puts(",FST_VD_INOUT");
else if (nodep->declDirection().isWritable()) puts(",FST_VD_OUTPUT");
else if (nodep->declDirection().isNonOutput()) puts(",FST_VD_INPUT");
else puts(",FST_VD_IMPLICIT");
//
// fstVarType
@@ -2875,6 +2874,7 @@ class EmitCTrace : EmitCStmts {
else if (vartype == AstVarType::TRI1) fstvt = "FST_VT_VCD_TRI1";
else if (vartype == AstVarType::TRIWIRE) fstvt = "FST_VT_VCD_TRI";
else if (vartype == AstVarType::WIRE) fstvt = "FST_VT_VCD_WIRE";
else if (vartype == AstVarType::PORT) fstvt = "FST_VT_VCD_WIRE";
//
else if (kwd == AstBasicDTypeKwd::INTEGER) fstvt = "FST_VT_VCD_INTEGER";
else if (kwd == AstBasicDTypeKwd::BIT) fstvt = "FST_VT_SV_BIT";
+7 -6
View File
@@ -41,9 +41,10 @@ class EmitCInlines : EmitCBaseVisitor {
// VISITORS
virtual void visit(AstBasicDType* nodep) {
if (nodep->keyword() == AstBasicDTypeKwd::STRING) {
v3Global.needHeavy(true); // #include <string> via verilated_heavy.h when we create symbol file
}
if (nodep->keyword() == AstBasicDTypeKwd::STRING) {
// Request #include <string> via verilated_heavy.h when we create symbol file
v3Global.needHeavy(true);
}
}
// NOPs
@@ -57,9 +58,9 @@ class EmitCInlines : EmitCBaseVisitor {
public:
explicit EmitCInlines(AstNetlist* nodep) {
iterate(nodep);
if (v3Global.needHInlines()) {
emitInt();
}
if (v3Global.needHInlines()) {
emitInt();
}
}
};
+141 -10
View File
@@ -99,6 +99,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
virtual void visit(AstCell* nodep) {
outputTag(nodep, "instance"); // IEEE: vpiInstance
puts(" defName="); putsQuoted(nodep->modName()); // IEEE vpiDefName
puts(" origName="); putsQuoted(nodep->origName());
outputChildrenEnd(nodep, "instance");
}
virtual void visit(AstNetlist* nodep) {
@@ -108,21 +109,25 @@ class EmitXmlFileVisitor : public AstNVisitor {
}
virtual void visit(AstNodeModule* nodep) {
outputTag(nodep, "");
puts(" origName="); putsQuoted(nodep->origName());
if (nodep->level()==1 || nodep->level()==2) // ==2 because we don't add wrapper when in XML mode
puts(" topModule=\"1\""); // IEEE vpiTopModule
outputChildrenEnd(nodep, "");
}
virtual void visit(AstVar* nodep) {
outputTag(nodep, "");
puts(" origName="); putsQuoted(nodep->origName());
outputChildrenEnd(nodep, "");
}
virtual void visit(AstPin* nodep) {
// What we call a pin in verilator is a port in the IEEE spec.
outputTag(nodep, "port"); // IEEE: vpiPort
if (nodep->modVarp()->isInOnly()) {
puts(" direction=\"in\"");
} else if (nodep->modVarp()->isOutOnly()) {
puts(" direction=\"out\"");
} else puts(" direction=\"inout\"");
puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
outputChildrenEnd(nodep, "port");
// What we call a pin in verilator is a port in the IEEE spec.
outputTag(nodep, "port"); // IEEE: vpiPort
if (nodep->modVarp()->isIO()) {
puts(" direction=\""+nodep->modVarp()->direction().xmlKwd()+"\"");
}
puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
outputChildrenEnd(nodep, "port");
}
virtual void visit(AstSenItem* nodep) {
outputTag(nodep, "");
@@ -154,6 +159,126 @@ public:
virtual ~EmitXmlFileVisitor() {}
};
//######################################################################
// List of module files xml visitor
class ModuleFilesXmlVisitor : public AstNVisitor {
private:
// MEMBERS
std::ostream& m_os;
std::set<std::string> m_modulesCovered;
std::deque<FileLine*> m_nodeModules;
// METHODS
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNetlist* nodep) {
// Children are iterated backwards to ensure correct compilation order
iterateChildrenBackwards(nodep);
}
virtual void visit(AstNodeModule* nodep) {
// Only list modules and interfaces
// Assumes modules and interfaces list is already sorted level wise
if (!nodep->dead()
&& (VN_IS(nodep, Module) || VN_IS(nodep, Iface))
&& m_modulesCovered.insert(nodep->fileline()->filename()).second) {
m_nodeModules.push_front(nodep->fileline());
}
}
//-----
virtual void visit(AstNode* nodep) {
// All modules are present at root so no need to iterate on children
}
public:
// CONSTRUCTORS
ModuleFilesXmlVisitor(AstNetlist* nodep, std::ostream& os)
: m_os(os), m_modulesCovered(), m_nodeModules() {
// Operate on whole netlist
nodep->accept(*this);
// Xml output
m_os<<"<module_files>\n";
for (std::deque<FileLine*>::iterator it = m_nodeModules.begin();
it != m_nodeModules.end(); it++) {
m_os<<"<file id=\""<<(*it)->filenameLetters()
<<"\" filename=\""<<(*it)->filename()
<<"\" language=\""<<(*it)->language().ascii()<<"\"/>\n";
}
m_os<<"</module_files>\n";
}
virtual ~ModuleFilesXmlVisitor() {}
};
//######################################################################
// Hierarchy of Cells visitor
class HierCellsXmlVisitor : public AstNVisitor {
private:
// MEMBERS
std::ostream& m_os;
std::string m_hier;
bool m_hasChildren;
// METHODS
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNodeModule* nodep) {
if (nodep->level() >= 0
&& nodep->level() <=2 ) { // ==2 because we don't add wrapper when in XML mode
m_os<<"<cells>\n";
m_os<<"<cell "<<nodep->fileline()->xml()
<<" name=\""<<nodep->name()<<"\""
<<" submodname=\""<<nodep->name()<<"\""
<<" hier=\""<<nodep->name()<<"\"";
m_hier = nodep->name() + ".";
m_hasChildren = false;
iterateChildren(nodep);
if (m_hasChildren) {
m_os<<"</cell>\n";
} else {
m_os<<"/>\n";
}
m_os<<"</cells>\n";
}
}
virtual void visit(AstCell* nodep) {
if (nodep->modp()->dead()) {
return;
}
if (!m_hasChildren) m_os<<">\n";
m_os<<"<cell "<<nodep->fileline()->xml()
<<" name=\""<<nodep->name()<<"\""
<<" submodname=\""<<nodep->modName()<<"\""
<<" hier=\""<<m_hier+nodep->name()<<"\"";
std::string hier = m_hier;
m_hier += nodep->name() + ".";
m_hasChildren = false;
iterateChildren(nodep->modp());
if (m_hasChildren) {
m_os<<"</cell>\n";
} else {
m_os<<"/>\n";
}
m_hier = hier;
m_hasChildren = true;
}
//-----
virtual void visit(AstNode* nodep) {
iterateChildren(nodep);
}
public:
// CONSTRUCTORS
HierCellsXmlVisitor(AstNetlist* nodep, std::ostream& os)
: m_os(os), m_hier(""), m_hasChildren(false) {
// Operate on whole netlist
nodep->accept(*this);
}
virtual ~HierCellsXmlVisitor() {}
};
//######################################################################
// EmitXml class functions
@@ -169,6 +294,12 @@ void V3EmitXml::emitxml() {
FileLine::fileNameNumMapDumpXml(sstr);
of.puts(sstr.str());
}
{
std::stringstream sstr;
ModuleFilesXmlVisitor moduleFilesVisitor (v3Global.rootp(), sstr);
HierCellsXmlVisitor cellsVisitor (v3Global.rootp(), sstr);
of.puts(sstr.str());
}
EmitXmlFileVisitor visitor (v3Global.rootp(), &of);
of.puts("</verilator_xml>\n");
}
+26 -19
View File
@@ -70,15 +70,17 @@ public:
CLKDATA, // Clock used as data
CMPCONST, // Comparison is constant due to limited range
COLONPLUS, // :+ instead of +:
COMBDLY, // Combinatorial delayed assignment
DEFPARAM, // Style: Defparam
DECLFILENAME, // Declaration doesn't match filename
COMBDLY, // Combinatorial delayed assignment
CONTASSREG, // Continuous assignment on reg
DEFPARAM, // Style: Defparam
DECLFILENAME, // Declaration doesn't match filename
ENDLABEL, // End lable name mismatch
GENCLK, // Generated Clock
IFDEPTH, // If statements too deep
IMPERFECTSCH, // Imperfect schedule (disabled by default)
IMPLICIT, // Implicit wire
IMPURE, // Impure function not being inlined
IMPLICIT, // Implicit wire
IMPORTSTAR, // Import::* in $unit
IMPURE, // Impure function not being inlined
INCABSPATH, // Include has absolute path
INFINITELOOP, // Infinite loop
INITIALDLY, // Initial delayed statement
@@ -87,8 +89,9 @@ public:
MULTIDRIVEN, // Driven from multiple blocks
PINMISSING, // Cell pin not specified
PINNOCONNECT, // Cell pin not connected
PINCONNECTEMPTY,// Cell pin connected by name with empty reference: ".name()" (can be used to mark unused pins)
REALCVT, // Real conversion
PINCONNECTEMPTY,// Cell pin connected by name with empty reference
PROCASSWIRE, // Procedural assignment on wire
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro
SELRANGE, // Selection index out of range
STMTDLY, // Delayed statement
@@ -131,14 +134,15 @@ public:
" EC_FIRST_WARN",
"ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN",
"BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CLKDATA",
"CMPCONST", "COLONPLUS", "COMBDLY", "DEFPARAM", "DECLFILENAME",
"ENDLABEL", "GENCLK",
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CLKDATA",
"CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG",
"DEFPARAM", "DECLFILENAME",
"ENDLABEL", "GENCLK",
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
"INCABSPATH", "INFINITELOOP", "INITIALDLY",
"LITENDIAN", "MODDUP",
"MULTIDRIVEN",
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY",
"LITENDIAN", "MODDUP",
"MULTIDRIVEN",
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
"REALCVT", "REDEFMACRO",
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT",
@@ -157,8 +161,10 @@ public:
// Warnings we'll present to the user as errors
// Later -Werror- options may make more of these.
bool pretendError() const { return ( m_e==ASSIGNIN || m_e==BLKANDNBLK
|| m_e==BLKLOOPINIT
|| m_e==IMPURE); }
|| m_e==BLKLOOPINIT
|| m_e==CONTASSREG
|| m_e==IMPURE
|| m_e==PROCASSWIRE); }
// Warnings to mention manual
bool mentionManual() const { return ( m_e==EC_FATALSRC || m_e==SYMRSVDWORD
|| pretendError() ); }
@@ -182,9 +188,10 @@ public:
|| m_e==BLKSEQ
|| m_e==DEFPARAM
|| m_e==DECLFILENAME
|| m_e==INCABSPATH
|| m_e==PINCONNECTEMPTY
|| m_e==PINNOCONNECT
|| m_e==IMPORTSTAR
|| m_e==INCABSPATH
|| m_e==PINCONNECTEMPTY
|| m_e==PINNOCONNECT
|| m_e==SYNCASYNCNET
|| m_e==UNDRIVEN
|| m_e==UNUSED
+6 -6
View File
@@ -206,12 +206,12 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm
return false;
}
{
string ignore; getline(*ifp, ignore);
string ignore = V3Os::getline(*ifp);
}
{
char chkDir; *ifp>>chkDir;
char quote; *ifp>>quote;
string chkCmdline; getline(*ifp, chkCmdline, '"');
char chkDir; *ifp>>chkDir;
char quote; *ifp>>quote;
string chkCmdline = V3Os::getline(*ifp, '"');
string cmdline = stripQuotes(cmdlineIn);
if (cmdline != chkCmdline) {
UINFO(2," --check-times failed: different command line\n");
@@ -228,8 +228,8 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm
time_t chkCnstime; *ifp>>chkCnstime;
time_t chkMstime; *ifp>>chkMstime;
time_t chkMnstime; *ifp>>chkMnstime;
char quote; *ifp>>quote;
string chkFilename; getline(*ifp, chkFilename, '"');
char quote; *ifp>>quote;
string chkFilename = V3Os::getline(*ifp, '"');
V3Options::fileNfsFlush(chkFilename);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
+5 -8
View File
@@ -235,14 +235,11 @@ void FileLine::modifyStateInherit(const FileLine* fromp) {
}
void FileLine::v3errorEnd(std::ostringstream& str) {
if (m_lineno) {
std::ostringstream nsstr;
nsstr<<this<<str.str();
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
V3Error::v3errorEnd(nsstr);
} else {
V3Error::v3errorEnd(str);
}
std::ostringstream nsstr;
if (m_lineno) nsstr<<this;
nsstr<<str.str();
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
V3Error::v3errorEnd(nsstr);
}
string FileLine::warnMore() const {
+5 -5
View File
@@ -1131,11 +1131,11 @@ void GateVisitor::dedupe() {
}
// Traverse starting from each of the outputs
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
if (vvertexp->isTop() && vvertexp->varScp()->varp()->isOutput()) {
deduper.dedupeTree(vvertexp);
}
}
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
if (vvertexp->isTop() && vvertexp->varScp()->varp()->isWritable()) {
deduper.dedupeTree(vvertexp);
}
}
}
m_statDedupLogic += deduper.numDeduped();
}
+33 -27
View File
@@ -317,23 +317,26 @@ private:
// Public variable at the lower module end - we need to make sure we propagate
// the logic changes up and down; if we aliased, we might remove the change detection
// on the output variable.
UINFO(9,"public pin assign: "<<exprvarrefp<<endl);
if (nodep->isInput()) nodep->v3fatalSrc("Outputs only - inputs use AssignAlias");
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true),
new AstVarRef(nodep->fileline(), nodep, false)));
} else if (nodep->isIfaceRef()) {
m_modp->addStmtp(new AstAssignVarScope(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
AstNode* nodebp=exprvarrefp->varp();
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
} else {
// Do to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below
m_modp->addStmtp(new AstAssignAlias(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
UINFO(9,"public pin assign: "<<exprvarrefp<<endl);
if (nodep->isNonOutput()) nodep->v3fatalSrc("Outputs only - inputs use AssignAlias");
m_modp->addStmtp(
new AstAssignW(nodep->fileline(),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true),
new AstVarRef(nodep->fileline(), nodep, false)));
} else if (nodep->isIfaceRef()) {
m_modp->addStmtp(
new AstAssignVarScope(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
AstNode* nodebp=exprvarrefp->varp();
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
} else {
// Do to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below
m_modp->addStmtp(
new AstAssignAlias(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
AstNode* nodebp=exprvarrefp->varp();
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
@@ -549,11 +552,12 @@ private:
AstNode* connectRefp = pinp->exprp();
if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) {
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
}
if (pinNewVarp->isOutOnly() && VN_IS(connectRefp, Const)) {
pinp->v3error("Output port is connected to a constant pin, electrical short");
}
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
}
if (pinNewVarp->direction() == VDirection::OUTPUT
&& VN_IS(connectRefp, Const)) {
pinp->v3error("Output port is connected to a constant pin, electrical short");
}
// Propagate any attributes across the interconnect
pinNewVarp->propagateAttrFrom(pinOldVarp);
@@ -567,11 +571,13 @@ private:
UINFO(6,"One-to-one "<<connectRefp<<endl);
UINFO(6," -to "<<pinNewVarp<<endl);
pinNewVarp->user2p(connectRefp);
// Public output inside the cell must go via an assign rather than alias
// Else the public logic will set the alias, losing the value to be propagated up
// (InOnly isn't a problem as the AssignAlias will create the assignment for us)
pinNewVarp->user3(pinNewVarp->isSigUserRWPublic() && pinNewVarp->isOutOnly());
}
// Public output inside the cell must go via an assign rather
// than alias. Else the public logic will set the alias, losing
// the value to be propagated up (InOnly isn't a problem as the
// AssignAlias will create the assignment for us)
pinNewVarp->user3(pinNewVarp->isSigUserRWPublic()
&& pinNewVarp->direction()==VDirection::OUTPUT);
}
// Cleanup var names, etc, to not conflict
{ InlineRelinkVisitor(newmodp, m_modp, nodep); }
// Move statements to top module
+38 -31
View File
@@ -63,28 +63,31 @@ private:
m_cellp = NULL;
}
virtual void visit(AstPin* nodep) {
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
UINFO(4," PIN "<<nodep<<endl);
if (!nodep->exprp()) return; // No-connect
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
if (nodep->modVarp()->isOutOnly() && VN_IS(nodep->exprp(), Const))
nodep->v3error("Output port is connected to a constant pin, electrical short");
// Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1SetOnce()) {
// Simplify it
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
UINFO(4," PIN "<<nodep<<endl);
if (!nodep->exprp()) return; // No-connect
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
if (nodep->modVarp()->direction() == VDirection::OUTPUT
&& VN_IS(nodep->exprp(), Const)) {
nodep->v3error("Output port is connected to a constant pin, electrical short");
}
// Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1SetOnce()) {
// Simplify it
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
// Make an 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");
if (nodep->modVarp()->isInout()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isOutput()) {
if (exprp->width() != nodep->modVarp()->width()) {
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
}
if (nodep->modVarp()->isInoutish()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isWritable()) {
AstNode* rhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
AstAssignW* assp = new AstAssignW(exprp->fileline(), exprp, rhsp);
m_cellp->addNextHere(assp);
} else if (nodep->modVarp()->isInput()) {
} else if (nodep->modVarp()->isNonOutput()) {
// Don't bother moving constants now,
// we'll be pushing the const down to the cell soon enough.
AstNode* assp = new AstAssignW
@@ -332,8 +335,8 @@ private:
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();
AstNode* exprp = nodep->exprp()->unlinkFrBack();
bool inputPin = nodep->modVarp()->isNonOutput();
if (!inputPin && !VN_IS(exprp, VarRef)
&& !VN_IS(exprp, Concat) // V3Const will collapse the SEL with the one we're about to make
&& !VN_IS(exprp, Sel)) { // V3Const will collapse the SEL with the one we're about to make
@@ -512,25 +515,29 @@ public:
// Make a new temp wire
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
string newvarname = (string(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
+(forTristate?"t":"") // Prevent name conflict if both tri & non-tri add signals
+"__"+cellp->name()+"__"+pinp->name());
AstVar* newvarp = new AstVar(pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
// Important to add statement next to cell, in case there is a generate with same named cell
cellp->addNextHere(newvarp);
if (pinVarp->isInout()) {
string newvarname = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp")
// Prevent name conflict if both tri & non-tri add signals
+(forTristate?"t":"")
+"__"+cellp->name()+"__"+pinp->name());
AstVar* newvarp = new AstVar(pinVarp->fileline(),
AstVarType::MODULETEMP, newvarname, pinVarp);
// Important to add statement next to cell, in case there is a
// generate with same named cell
cellp->addNextHere(newvarp);
if (pinVarp->isInoutish()) {
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be"
" direct one-to-one connection (without any expression)");
} else if (pinVarp->isOutput()) {
// See also V3Inst
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
} else if (pinVarp->isWritable()) {
// See also V3Inst
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "
<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
pinp->exprp(new AstVarRef(newvarp->fileline(), newvarp, true));
AstNode* rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
assignp = new AstAssignW(pinp->fileline(), pinexprp, rhsSelp);
} else {
// V3 width should have range/extended to make the widths correct
} else {
// V3 width should have range/extended to make the widths correct
assignp = new AstAssignW(pinp->fileline(),
new AstVarRef(pinp->fileline(), newvarp, true),
pinexprp);
+14 -9
View File
@@ -867,12 +867,13 @@ class LinkDotFindVisitor : public AstNVisitor {
if (nodep->fvarp()
&& !VN_IS(nodep->fvarp(), Var)) {
AstNodeDType* dtypep = VN_CAST(nodep->fvarp(), NodeDType);
// If unspecified, function returns one bit; however when we support NEW() it could
// also return the class reference.
if (dtypep) dtypep->unlinkFrBack();
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(),
VFlagChildDType(), dtypep); // Not dtype resolved yet
// If unspecified, function returns one bit; however when we support NEW() it could
// also return the class reference.
if (dtypep) dtypep->unlinkFrBack();
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::VAR, nodep->name(),
VFlagChildDType(), dtypep); // Not dtype resolved yet
newvarp->direction(VDirection::OUTPUT);
newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
@@ -1019,7 +1020,11 @@ class LinkDotFindVisitor : public AstNVisitor {
virtual void visit(AstPackageImport* nodep) {
UINFO(4," Link: "<<nodep<<endl);
VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep());
if (nodep->name()!="*") {
if (nodep->name()=="*") {
if (m_curSymp == m_statep->dunitEntp()) {
nodep->v3warn(IMPORTSTAR,"Import::* in $unit scope may pollute global namespace");
}
} else {
VSymEnt* impp = srcp->findIdFlat(nodep->name());
if (!impp) {
nodep->v3error("Import object not found: "<<nodep->packagep()->prettyName()<<"::"<<nodep->prettyName());
@@ -1537,10 +1542,10 @@ private:
} else if (VN_IS(symp->nodep(), ModportVarRef)) {
AstModportVarRef* snodep = VN_CAST(symp->nodep(), ModportVarRef);
AstVar* varp = snodep->varp();
if (lvalue && snodep->isInput()) {
if (lvalue && snodep->direction().isReadOnly()) {
nodep->v3error("Attempt to drive input-only modport: "<<nodep->prettyName());
} // else other simulators don't warn about reading, and IEEE doesn't say illegal
return varp;
return varp;
} else {
return NULL;
}
+16 -16
View File
@@ -56,21 +56,21 @@ private:
nodep->lvalue(true);
}
if (nodep->varp()) {
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
if (!m_ftaskp) {
nodep->v3warn(ASSIGNIN,"Assigning to input variable: "<<nodep->prettyName());
}
}
}
if (nodep->lvalue() && !m_ftaskp
&& nodep->varp()->isReadOnly()) {
nodep->v3warn(ASSIGNIN,"Assigning to input/const variable: "
<<nodep->prettyName());
}
}
iterateChildren(nodep);
}
// Nodes that start propagating down lvalues
virtual void visit(AstPin* nodep) {
if (nodep->modVarp() && nodep->modVarp()->isOutput()) {
// When the varref's were created, we didn't know the I/O state
// Now that we do, and it's from a output, we know it's a lvalue
m_setRefLvalue = true;
if (nodep->modVarp() && nodep->modVarp()->isWritable()) {
// When the varref's were created, we didn't know the I/O state
// Now that we do, and it's from a output, we know it's a lvalue
m_setRefLvalue = true;
iterateChildren(nodep);
m_setRefLvalue = false;
} else {
@@ -238,14 +238,14 @@ private:
if (!taskp) return;
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO()) {
if (portp->isInput()) {
if (portp->isIO()) {
if (portp->isWritable()) {
m_setRefLvalue = true;
iterate(pinp);
} else { // Output or Inout
m_setRefLvalue = true;
m_setRefLvalue = false;
} else {
iterate(pinp);
m_setRefLvalue = false;
}
}
// Advance pin
pinp = pinp->nextp();
}
+11 -7
View File
@@ -126,10 +126,14 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
AstVar* varp = oldvarp->cloneTree(false);
newmodp->addStmtp(varp);
varp->sigPublic(true); // User needs to be able to get to it...
if (oldvarp->isIO()) {
oldvarp->primaryIO(true);
varp->primaryIO(true);
}
if (oldvarp->isIO()) {
oldvarp->primaryIO(false);
varp->primaryIO(true);
}
if (varp->direction().isRefOrConstRef()) {
varp->v3error("Unsupported: ref/const ref as primary input/output: "
<<varp->prettyName());
}
if (varp->isIO() && v3Global.opt.systemC()) {
varp->sc(true);
// User can see trace one level down from the wrapper
@@ -138,9 +142,9 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
}
AstPin* pinp = new AstPin(oldvarp->fileline(),0,oldvarp->name(),
new AstVarRef(varp->fileline(),
varp, oldvarp->isOutput()));
// Skip length and width comp; we know it's a direct assignment
new AstVarRef(varp->fileline(),
varp, oldvarp->isWritable()));
// Skip length and width comp; we know it's a direct assignment
pinp->modVarp(oldvarp);
cellp->addPinsp(pinp);
}
+15 -12
View File
@@ -198,20 +198,23 @@ private:
// A variable with an = value can be three things:
FileLine* fl = nodep->valuep()->fileline();
// 1. Parameters and function inputs: It's a default to use if not overridden
if (nodep->isParam() || (m_ftaskp && nodep->isInOnly())) {
}
else if (!m_ftaskp && nodep->isInOnly()) {
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
}
else if (!m_ftaskp && nodep->isNonOutput()) {
nodep->v3error("Unsupported: Default value on module input: "<<nodep->prettyName());
nodep->valuep()->unlinkFrBack()->deleteTree();
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
else if (m_valueModp) {
nodep->addNextHere
(new AstInitial
(fl, new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
nodep->valuep()->unlinkFrBack())));
} // 3. Under blocks, it's an initial value to be under an assign
else {
nodep->addNextHere
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
else if (m_valueModp) {
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
FileLine* newfl = new FileLine (fl);
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
nodep->addNextHere
(new AstInitial
(newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true),
nodep->valuep()->unlinkFrBack())));
} // 3. Under blocks, it's an initial value to be under an assign
else {
nodep->addNextHere
(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
nodep->valuep()->unlinkFrBack()));
}
+11 -8
View File
@@ -405,14 +405,17 @@ private:
AstVar* varoutp = NULL;
for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* varp = VN_CAST(stmtp, Var)) {
if (varp->isInput()) {
} else if (varp->isOutput()) {
if (varoutp) { varp->v3error("Multiple outputs not allowed in udp modules"); }
varoutp = varp;
// Tie off
m_modp->addStmtp(new AstAssignW(varp->fileline(),
new AstVarRef(varp->fileline(), varp, true),
new AstConst(varp->fileline(), AstConst::LogicFalse())));
if (varp->isReadOnly()) {
} else if (varp->isWritable()) {
if (varoutp) {
varp->v3error("Multiple outputs not allowed in udp modules");
}
varoutp = varp;
// Tie off
m_modp->addStmtp(new AstAssignW(
varp->fileline(),
new AstVarRef(varp->fileline(), varp, true),
new AstConst(varp->fileline(), AstConst::LogicFalse())));
} else {
varp->v3error("Only inputs and outputs are allowed in udp modules");
}
+3 -4
View File
@@ -1113,10 +1113,9 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
string whole_file;
bool inCmt = false;
while (!ifp->eof()) {
string line;
getline(*ifp, line);
// Strip simple comments
string oline;
string line = V3Os::getline(*ifp);
// Strip simple comments
string oline;
// cppcheck-suppress StlMissingComparison
for (string::const_iterator pos = line.begin(); pos != line.end(); ++pos) {
if (inCmt) {
+9 -9
View File
@@ -1017,9 +1017,9 @@ private:
m_inClocked = false;
}
virtual void visit(AstVarScope* nodep) {
// Create links to all input signals
if (m_modp->isTop() && nodep->varp()->isInput()) {
OrderVarVertex* varVxp = newVarUserVertex(nodep, WV_STD);
// Create links to all input signals
if (m_modp->isTop() && nodep->varp()->isNonOutput()) {
OrderVarVertex* varVxp = newVarUserVertex(nodep, WV_STD);
new OrderEdge(&m_graph, m_inputsVxp, varVxp, WEIGHT_INPUT);
}
}
@@ -1463,9 +1463,9 @@ void OrderVisitor::processSensitive() {
// Sc sensitives are required on all inputs that go to a combo
// block. (Not inputs that go only to clocked blocks.)
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
if (vvertexp->varScp()->varp()->isInput()) {
//UINFO(0," scsen "<<vvertexp<<endl);
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
if (vvertexp->varScp()->varp()->isNonOutput()) {
//UINFO(0," scsen "<<vvertexp<<endl);
for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
if (OrderEitherVertex* toVertexp = dynamic_cast<OrderEitherVertex*>(edgep->top())) {
if (edgep->weight() && toVertexp->domainp()) {
@@ -1501,8 +1501,8 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) {
OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp);
AstSenTree* domainp = NULL;
UASSERT(m_comboDomainp, "not preset");
if (vvertexp && vvertexp->varScp()->varp()->isInput()) {
domainp = m_comboDomainp;
if (vvertexp && vvertexp->varScp()->varp()->isNonOutput()) {
domainp = m_comboDomainp;
}
if (vvertexp && vvertexp->varScp()->isCircular()) {
domainp = m_comboDomainp;
@@ -1910,7 +1910,7 @@ void OrderVisitor::processMTasks() {
// Create the AstExecGraph node which represents the execution
// of the MTask graph.
FileLine* rootFlp = new FileLine("AstRoot", 0);
FileLine* rootFlp = v3Global.rootp()->fileline();
AstExecGraph* execGraphp = new AstExecGraph(rootFlp);
m_scopetopp->addActivep(execGraphp);
v3Global.rootp()->execGraphp(execGraphp);
+15
View File
@@ -165,6 +165,21 @@ bool V3Os::filenameIsRel(const string& filename) {
return (filename.length()>0 && filename[0] != '/');
}
//######################################################################
// File utilities
string V3Os::getline(std::istream& is, char delim) {
string line;
#if defined(__CYGWIN__) // Work around buggy implementation of getline
char buf[65536];
is.getline(buf, 65535, delim);
line = buf;
#else
std::getline(is, line, delim);
#endif
return line;
}
//######################################################################
// Directory utilities
+3
View File
@@ -46,6 +46,9 @@ public:
static string filenameRealPath(const string& filename); ///< Return realpath of filename
static bool filenameIsRel(const string& filename); ///< True if relative
// METHODS (file utilities)
static string getline(std::istream& is, char delim='\n');
// METHODS (directory utilities)
static void createDir(const string& dirname);
static void unlinkRegexp(const string& dir, const string& regexp);
+3 -3
View File
@@ -36,7 +36,7 @@ class V3ParseSym;
class V3Parse {
private:
V3ParseImp* m_impp;
V3ParseImp* m_impp;
// CONSTRUCTORS
VL_UNCOPYABLE(V3Parse);
@@ -48,10 +48,10 @@ public:
// METHODS
// Preprocess and read the Verilog file specified into the netlist database
void parseFile(FileLine* fileline, const string& modname, bool inLibrary,
const string& errmsg);
const string& errmsg);
// Push preprocessed text to the lexer
static void ppPushText(V3ParseImp* impp, const string& text);
};
#endif // Guard
#endif // Guard
+2 -1
View File
@@ -18,7 +18,8 @@
//
//*************************************************************************
#include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict
#include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict
//======================================================================
// The guts came from bison
+2 -5
View File
@@ -1248,11 +1248,8 @@ public:
if (mtaskCount > maxMTasks) {
uint32_t oldLimit = m_scoreLimit;
m_scoreLimit = (m_scoreLimit * 120) / 100;
// Line must be >0 otherwise FileLine doesn't check
// if the warning is suppressed with -Wno-UNOPTTHREADS
FileLine dummyFl("AstRoot", 1);
dummyFl.v3warn(UNOPTTHREADS, "Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads.");
v3Global.rootp()->fileline()->v3warn(
UNOPTTHREADS, "Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads.");
UINFO(1,"Critical path limit was="<<oldLimit
<<" now="<<m_scoreLimit<<endl);
continue;
+5 -5
View File
@@ -785,11 +785,11 @@ private:
AstVar* portp = it->first;
AstNode* pinp = it->second->exprp();
if (pinp) { // Else too few arguments in function call - ignore it
if (portp->isOutput()) {
clearOptimizable(portp,"Language violation: Outputs not allowed in constant functions");
return;
}
// Evaluate pin value
if (portp->isWritable()) {
clearOptimizable(portp, "Language violation: Outputs/refs not allowed in constant functions");
return;
}
// Evaluate pin value
iterate(pinp);
}
}
+46 -35
View File
@@ -332,9 +332,9 @@ private:
AstVarScope* createInputVar(AstCFunc* funcp, const string& name, AstBasicDTypeKwd kwd) {
AstVar* newvarp = new AstVar(funcp->fileline(), AstVarType::BLOCKTEMP, name,
funcp->findBasicDType(kwd));
newvarp->funcLocal(true);
newvarp->combineType(AstVarType::INPUT);
funcp->addArgsp(newvarp);
newvarp->funcLocal(true);
newvarp->direction(VDirection::INPUT);
funcp->addArgsp(newvarp);
AstVarScope* newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp);
m_scopep->addVarp(newvscp);
return newvscp;
@@ -378,10 +378,13 @@ private:
pinp->unlinkFrBack(); // Relinked to assignment below
argp->unlinkFrBack()->deleteTree(); // Args no longer needed
//
if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) {
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
}
else if (portp->isInout()) {
if (portp->isWritable() && VN_IS(pinp, Const)) {
pinp->v3error("Function/task "
+portp->direction().prettyName() // e.g. "output"
+" connected to constant instead of variable: "
+portp->prettyName());
}
else if (portp->isInoutish()) {
// Correct lvalue; see comments below
V3LinkLValue::linkLValueSet(pinp);
@@ -393,9 +396,9 @@ private:
} else {
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
}
}
else if (portp->isOutput()) {
// Make output variables
}
else if (portp->isWritable()) {
// Make output variables
// Correct lvalue; we didn't know when we linked
// This is slightly scary; are we sure no decisions were made
// before here based on this not being a lvalue?
@@ -412,9 +415,9 @@ private:
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
// Put assignment BEHIND of all other statements
beginp->addNext(assp);
}
else if (portp->isInput()) {
// Make input variable
}
else if (portp->isNonOutput()) {
// Make input variable
AstVarScope* inVscp = createVarScope(portp, namePrefix+"__"+portp->shortName());
portp->user2p(inVscp);
AstAssign* assp = new AstAssign(pinp->fileline(),
@@ -483,10 +486,13 @@ private:
} else {
UINFO(9, " Port "<<portp<<endl);
UINFO(9, " pin "<<pinp<<endl);
if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) {
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
}
else if (portp->isInout()) {
if (portp->isWritable() && VN_IS(pinp, Const)) {
pinp->v3error("Function/task "
+portp->direction().prettyName() // e.g. "output"
+" connected to constant instead of variable: "
+portp->prettyName());
}
else if (portp->isInoutish()) {
// Correct lvalue; see comments below
V3LinkLValue::linkLValueSet(pinp);
@@ -495,9 +501,9 @@ private:
} else {
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
}
}
else if (portp->isOutput()) {
// Make output variables
}
else if (portp->isWritable()) {
// Make output variables
// Correct lvalue; we didn't know when we linked
// This is slightly scary; are we sure no decisions were made
// before here based on this not being a lvalue?
@@ -718,12 +724,17 @@ private:
// No createDpiTemp; we make a real internal variable instead
// SAME CODE BELOW
args+= ", ";
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
if (args != "") {
argnodesp = argnodesp->addNext(
new AstText(portp->fileline(), args, true));
args="";
}
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isOutput());
argnodesp = argnodesp->addNextNull(refp);
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp,
portp->isWritable());
argnodesp = argnodesp->addNextNull(refp);
if (portp->isInput()) {
if (portp->isNonOutput()) {
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
}
}
@@ -736,9 +747,9 @@ private:
args+= ", ";
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isOutput());
argnodesp = argnodesp->addNextNull(refp);
}
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable());
argnodesp = argnodesp->addNextNull(refp);
}
{// Call the user function
// Add the variables referenced as VarRef's so that lifetime analysis
@@ -755,11 +766,11 @@ private:
// Convert output/inout arguments back to internal type
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && portp->isOutput() && !portp->isFuncReturn()) {
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
}
}
}
if (portp->isIO() && portp->isWritable() && !portp->isFuncReturn()) {
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
}
}
}
if (rtnvarp) {
dpip->addStmtsp(createDpiTemp(rtnvarp,""));
@@ -867,14 +878,14 @@ private:
else {
if (bitvec) {}
else if (logicvec) {}
else if (portp->isOutput()) args += "&";
else if (portp->isWritable()) args += "&";
else if (portp->basicp() && portp->basicp()->keyword().isDpiBitVal()
&& portp->width() != 1) args += "&"; // it's a svBitVecVal (2-32 bits wide)
args += portp->name()+"__Vcvt";
cfuncp->addStmtsp(createDpiTemp(portp,"__Vcvt"));
if (portp->isInput()) {
if (portp->isNonOutput()) {
cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,false,"","__Vcvt"));
}
}
@@ -900,7 +911,7 @@ private:
// Convert output/inout arguments back to internal type
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())
if (portp->isIO() && (portp->isWritable() || portp->isFuncReturn())
&& !portp->isDpiOpenArray()) {
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));
+5 -5
View File
@@ -699,11 +699,11 @@ private:
}
V3GraphVertex* traceVtxp = m_tracep->user1u().toGraphVertex();
new V3GraphEdge(&m_graph, varVtxp, traceVtxp, 1);
if (nodep->varp()->isPrimaryIn() // Always need to trace primary inputs
|| nodep->varp()->isSigPublic()) { // Or ones user can change
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1);
}
}
if (nodep->varp()->isPrimaryInish() // Always need to trace primary inputs
|| nodep->varp()->isSigPublic()) { // Or ones user can change
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1);
}
}
else if (m_funcp && m_finding && nodep->lvalue()) {
if (!nodep->varScopep()) nodep->v3fatalSrc("No var scope?");
V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp);
+23 -20
View File
@@ -27,9 +27,9 @@
// Over each module, from child to parent:
// Build a graph, connecting signals together so we can propagate tristates
// Variable becomes tristate with
// VAR->isInout
// VAR->isPullup/isPulldown (converted to AstPullup/AstPulldown
// BufIf0/1
// VAR->isInoutish
// VAR->isPullup/isPulldown (converted to AstPullup/AstPulldown
// BufIf0/1
// All variables on the LHS need to become tristate when there is:
// CONST-> with Z value on the RHS of an assignment
// AstPin with lower connection a tristate
@@ -1067,18 +1067,20 @@ class TristateVisitor : public TristateBaseVisitor {
UINFO(9,dbgState()<<nodep<<endl);
if (debug()>=9) nodep->dumpTree(cout,"-pin-pre: ");
// Empty/in-only; need Z to propagate
bool inDeclProcessing = (nodep->exprp()
&& nodep->modVarp()->isInOnly()
// Need to consider the original state instead of current state
// as we converted tristates to inputs, which do not want to have this.
&& !nodep->modVarp()->isDeclOutput());
if (!nodep->exprp()) { // No-connect; covert to empty connection
UINFO(5,"Unconnected pin terminate "<<nodep<<endl);
AstVar* ucVarp = getCreateUnconnVarp(nodep, nodep->modVarp()->dtypep());
nodep->exprp(new AstVarRef(nodep->fileline(), ucVarp,
// We converted, so use declaration output state
nodep->modVarp()->isDeclOutput()));
// Empty/in-only; need Z to propagate
bool inDeclProcessing = (nodep->exprp()
&& nodep->modVarp()->direction() == VDirection::INPUT
// Need to consider the original state
// instead of current state as we converted
// tristates to inputs, which do not want
// to have this.
&& !nodep->modVarp()->declDirection().isWritable());
if (!nodep->exprp()) { // No-connect; covert to empty connection
UINFO(5,"Unconnected pin terminate "<<nodep<<endl);
AstVar* ucVarp = getCreateUnconnVarp(nodep, nodep->modVarp()->dtypep());
nodep->exprp(new AstVarRef(nodep->fileline(), ucVarp,
// We converted, so use declaration output state
nodep->modVarp()->declDirection().isWritable()));
m_tgraph.setTristate(ucVarp);
// We don't need a driver on the wire; the lack of one will default to tristate
} else if (inDeclProcessing) { // Not an input that was a converted tristate
@@ -1245,11 +1247,12 @@ class TristateVisitor : public TristateBaseVisitor {
nodep->addNextHere(newp);
// We'll iterate on the new AstPull later
}
if (nodep->isInout()
//|| varp->isOutput()
// Note unconnected output only changes behavior vs. previous versions and causes outputs
// that don't come from anywhere to possibly create connection errors.
// One example of problems is this: "output z; task t; z <= {something}; endtask"
if (nodep->isInoutish()
//|| varp->isOutput()
// Note unconnected output only changes behavior vs. previous
// versions and causes outputs that don't come from anywhere to
// possibly create connection errors.
// One example of problems is this: "output z; task t; z <= {something}; endtask"
) {
UINFO(9," setTristate-inout "<<nodep<<endl);
m_tgraph.setTristate(nodep);
+79 -34
View File
@@ -232,9 +232,11 @@ private:
// STATE
std::vector<UndrivenVarEntry*> m_entryps[3]; // Nodes to delete when we are finished
bool m_inBBox; // In black box; mark as driven+used
AstNodeFTask* m_taskp; // Current task
AstAlways* m_alwaysp; // Current always if combo, otherwise NULL
bool m_inBBox; // In black box; mark as driven+used
bool m_inContAssign; // In continuous assignment
bool m_inProcAssign; // In procedual assignment
AstNodeFTask* m_taskp; // Current task
AstAlways* m_alwaysCombp; // Current always if combo, otherwise NULL
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@@ -268,16 +270,16 @@ private:
// VISITORS
virtual void visit(AstVar* nodep) {
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
// For assigns and non-combo always, do just usr==1, to look for module-wide undriven etc
// For non-combo always, run both usr==1 for above, and also usr==2 for always-only checks
for (int usr=1; usr<(m_alwaysCombp?3:2); ++usr) {
// For assigns and non-combo always, do just usr==1, to look for module-wide undriven etc
// For non-combo always, run both usr==1 for above, and also usr==2 for always-only checks
UndrivenVarEntry* entryp = getEntryp(nodep, usr);
if (nodep->isInput()
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->drivenWhole();
}
if (nodep->isOutput()
if (nodep->isNonOutput()
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->drivenWhole();
}
if (nodep->isWritable()
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|| nodep->isSigUserRdPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
@@ -299,12 +301,12 @@ private:
AstNodeVarRef* varrefp = VN_CAST(nodep->fromp(), NodeVarRef);
AstConst* constp = VN_CAST(nodep->lsbp(), Const);
if (varrefp && constp && !constp->num().isFourState()) {
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
for (int usr=1; usr<(m_alwaysCombp?3:2); ++usr) {
UndrivenVarEntry* entryp = getEntryp(varrefp->varp(), usr);
int lsb = constp->toUInt();
if (m_inBBox || varrefp->lvalue()) {
// Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine.
if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) {
int lsb = constp->toUInt();
if (m_inBBox || varrefp->lvalue()) {
// Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine.
if (usr==2 && m_alwaysCombp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) {
UINFO(9," Select. Entryp="<<cvtToHex(entryp)<<endl);
warnAlwCombOrder(varrefp);
}
@@ -319,11 +321,25 @@ private:
}
virtual void visit(AstNodeVarRef* nodep) {
// Any variable
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
if (nodep->lvalue()
&& !VN_IS(nodep, VarXRef)) { // Ignore interface variables and similar ugly items
if (m_inProcAssign && !nodep->varp()->varType().isProcAssignable()) {
nodep->v3warn(PROCASSWIRE, "Procedural assignment to wire, perhaps intended var"
" (IEEE 2017 6.5): "
+nodep->prettyName());
}
if (m_inContAssign && !nodep->varp()->varType().isContAssignable()
&& !nodep->fileline()->language().systemVerilog()) {
nodep->v3warn(CONTASSREG, "Continuous assignment to reg, perhaps intended wire"
" (IEEE 2005 6.1; Verilog only, legal in SV): "
+nodep->prettyName());
}
}
for (int usr=1; usr<(m_alwaysCombp?3:2); ++usr) {
UndrivenVarEntry* entryp = getEntryp(nodep->varp(), usr);
bool fdrv = nodep->lvalue() && nodep->varp()->attrFileDescr(); // FD's are also being read from
if (m_inBBox || nodep->lvalue()) {
if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenAny()) {
bool fdrv = nodep->lvalue() && nodep->varp()->attrFileDescr(); // FD's are also being read from
if (m_inBBox || nodep->lvalue()) {
if (usr==2 && m_alwaysCombp && entryp->isUsedNotDrivenAny()) {
UINFO(9," Full bus. Entryp="<<cvtToHex(entryp)<<endl);
warnAlwCombOrder(nodep);
}
@@ -341,17 +357,44 @@ private:
m_inBBox = prevMark;
}
virtual void visit(AstAlways* nodep) {
AstAlways* prevAlwp = m_alwaysp;
{
AstNode::user2ClearTree();
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," "<<nodep<<endl);
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) m_alwaysp = nodep;
else m_alwaysp = NULL;
virtual void visit(AstAssign* nodep) {
bool prevProc = m_inProcAssign;
{
m_inProcAssign = true;
iterateChildren(nodep);
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," Done "<<nodep<<endl);
}
m_alwaysp = prevAlwp;
m_inProcAssign = false;
}
m_inProcAssign = prevProc;
}
virtual void visit(AstAssignDly* nodep) {
bool prevProc = m_inProcAssign;
{
m_inProcAssign = true;
iterateChildren(nodep);
m_inProcAssign = false;
}
m_inProcAssign = prevProc;
}
virtual void visit(AstAssignW* nodep) {
bool prevCont = m_inProcAssign;
{
m_inContAssign = true;
iterateChildren(nodep);
m_inContAssign = false;
}
m_inProcAssign = prevCont;
}
virtual void visit(AstAlways* nodep) {
AstAlways* prevAlwp = m_alwaysCombp;
{
AstNode::user2ClearTree();
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," "<<nodep<<endl);
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) m_alwaysCombp = nodep;
else m_alwaysCombp = NULL;
iterateChildren(nodep);
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," Done "<<nodep<<endl);
}
m_alwaysCombp = prevAlwp;
}
virtual void visit(AstNodeFTask* nodep) {
@@ -379,9 +422,11 @@ private:
public:
// CONSTUCTORS
explicit UndrivenVisitor(AstNetlist* nodep) {
m_inBBox = false;
m_taskp = NULL;
m_alwaysp = NULL;
m_inBBox = false;
m_inContAssign = false;
m_inProcAssign = false;
m_taskp = NULL;
m_alwaysCombp = NULL;
iterate(nodep);
}
virtual ~UndrivenVisitor() {
+57 -33
View File
@@ -1287,7 +1287,10 @@ private:
if (!nodep->widthMin()) nodep->v3fatalSrc("LHS var should be size complete");
}
//if (debug()>=9) nodep->dumpTree(cout," VRout ");
if (nodep->lvalue() && nodep->varp()->isConst()
if (nodep->lvalue() && nodep->varp()->direction() == VDirection::CONSTREF) {
nodep->v3error("Assigning to const ref variable: "<<nodep->prettyName());
}
else if (nodep->lvalue() && nodep->varp()->isConst()
&& !m_paramsOnly
&& !m_initialp) { // Too loose, but need to allow our generated first assignment
// // Move this to a property of the AstInitial block
@@ -1753,32 +1756,39 @@ private:
AstMemberDType* memp = classp->membersp();
AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember);
for (; memp || patp; ) {
if (patp) {
if (patp->keyp()) {
if (AstText* textp = VN_CAST(patp->keyp(), Text)) {
memp = classp->findMember(textp->text());
if (!memp) {
patp->keyp()->v3error("Assignment pattern key '"<<textp->text()<<"' not found as member");
continue;
}
} else {
patp->keyp()->v3error("Assignment pattern key not"
" supported/understood: "<<patp->keyp()->prettyTypeName());
}
}
}
if (memp && !patp) {
// Missing init elements, warn below
memp=NULL; patp=NULL; break;
} else if (!memp && patp) { patp->v3error("Assignment pattern contains too many elements");
memp=NULL; patp=NULL; break;
} else {
std::pair<PatMap::iterator, bool> ret = patmap.insert(make_pair(memp, patp));
if (!ret.second) {
patp->v3error("Assignment pattern contains duplicate entry: "
<< VN_CAST(patp->keyp(), Text)->text());
}
}
do {
if (patp) {
if (patp->keyp()) {
if (AstText* textp = VN_CAST(patp->keyp(), Text)) {
memp = classp->findMember(textp->text());
if (!memp) {
patp->keyp()->v3error(
"Assignment pattern key '"
<<textp->text()<<"' not found as member");
break;
}
} else {
patp->keyp()->v3error(
"Assignment pattern key not supported/understood: "
<<patp->keyp()->prettyTypeName());
}
}
}
if (memp && !patp) {
// Missing init elements, warn below
memp=NULL; patp=NULL; break;
} else if (!memp && patp) {
patp->v3error("Assignment pattern contains too many elements");
memp=NULL; patp=NULL; break;
} else {
std::pair<PatMap::iterator, bool> ret
= patmap.insert(make_pair(memp, patp));
if (!ret.second) {
patp->v3error("Assignment pattern contains duplicate entry: "
<< VN_CAST(patp->keyp(), Text)->text());
}
}
} while(0);
// Next
if (memp) memp = VN_CAST(memp->nextp(), MemberDType);
if (patp) patp = VN_CAST(patp->nextp(), PatMember);
@@ -2319,7 +2329,13 @@ private:
}
userIterateAndNext(nodep->exprp(), WidthVP(subDTypep,FINAL).p());
} else {
if (nodep->modVarp()->isTristate()) {
if (nodep->modVarp()->direction() == VDirection::REF) {
nodep->v3error("Ref connection '"<<nodep->modVarp()->prettyName()<<"'"
<<" requires matching types;"
<<" ref requires "<<pinDTypep->prettyTypeName()
<<" but connection is "
<<conDTypep->prettyTypeName()<<"."<<endl);
} else if (nodep->modVarp()->isTristate()) {
if (pinwidth != conwidth) {
nodep->v3error("Unsupported: "<<ucfirst(nodep->prettyOperatorName())
<<" to inout signal requires "<<pinwidth
@@ -2557,9 +2573,16 @@ private:
AstArg* argp = it->second;
AstNode* pinp = argp->exprp();
if (!pinp) continue; // Argument error we'll find later
if ((portp->isOutput() || portp->isInout())
&& pinp->width() != portp->width()) {
pinp->v3error("Unsupported: Function output argument '"<<portp->prettyName()<<"'"
if (portp->direction() == VDirection::REF
&& !similarDTypeRecurse(portp->dtypep(), pinp->dtypep())) {
pinp->v3error("Ref argument requires matching types;"
<<" port '"<<portp->prettyName()<<"'"
<<" requires "<<portp->prettyTypeName()
<<" but connection is "<<pinp->prettyTypeName()<<".");
} else if (portp->isWritable()
&& pinp->width() != portp->width()) {
pinp->v3error("Unsupported: Function output argument '"
<<portp->prettyName()<<"'"
<<" requires "<<portp->width()
<<" bits, but connection's "<<pinp->prettyTypeName()
<<" generates "<<pinp->width()<<" bits.");
@@ -3344,8 +3367,9 @@ private:
AstNodeAssign* assignp = VN_CAST(nodep, NodeAssign);
AstPin* pinp = VN_CAST(nodep, Pin);
if (assignp && VN_IS(assignp->lhsp(), NodeStream)) {
} else if (pinp && !pinp->modVarp()->isInput()) { // V3Inst::pinReconnectSimple must deal
UINFO(5,"pinInSizeMismatch: "<<pinp);
} else if (pinp && pinp->modVarp()->direction() != VDirection::INPUT) {
// V3Inst::pinReconnectSimple must deal
UINFO(5,"pinInSizeMismatch: "<<pinp);
} else {
fixWidthExtend(underp, expDTypep, extendRule); VL_DANGLING(underp);//Changed
}
+3 -3
View File
@@ -100,10 +100,10 @@ public:
class VlcPoints {
private:
// MEMBERS
typedef vl_unordered_map<string,vluint64_t> NameMap;
NameMap m_nameMap; //< Name to point-number
typedef std::map<string,vluint64_t> NameMap; // Sorted by name (ordered)
NameMap m_nameMap; //< Name to point-number
std::vector<VlcPoint> m_points; //< List of all points
vluint64_t m_numPoints; //< Total unique points
vluint64_t m_numPoints; //< Total unique points
public:
// ITERATORS
+5 -7
View File
@@ -42,10 +42,9 @@ void VlcTop::readCoverage(const string& filename, bool nonfatal) {
VlcTest* testp = tests().newTest(filename, 0, 0);
while (!is.eof()) {
string line;
getline(is, line);
//UINFO(9," got "<<line<<endl);
if (line[0] == 'C') {
string line = V3Os::getline(is);
//UINFO(9," got "<<line<<endl);
if (line[0] == 'C') {
string::size_type secspace=3;
for (; secspace<line.length(); secspace++) {
if (line[secspace]=='\'' && line[secspace+1]==' ') break;
@@ -219,9 +218,8 @@ void VlcTop::annotateOutputFiles(const string& dirname) {
int lineno = 0;
while (!is.eof()) {
lineno++;
string line;
getline(is, line);
lineno++;
string line = V3Os::getline(is);
bool first = true;
+5 -5
View File
@@ -35,12 +35,12 @@
class VlcTop {
public:
// PUBLIC MEMBERS
VlcOptions opt; //< Runtime options
VlcOptions opt; //< Runtime options
private:
// MEMBERS
VlcTests m_tests; //< List of all tests (all coverage files)
VlcPoints m_points; //< List of all points
VlcSources m_sources; //< List of all source files to annotate
VlcTests m_tests; //< List of all tests (all coverage files)
VlcPoints m_points; //< List of all points
VlcSources m_sources; //< List of all source files to annotate
// METHODS
void createDir(const string& dirname);
@@ -68,4 +68,4 @@ public:
//######################################################################
#endif // guard
#endif // guard
+24 -18
View File
@@ -51,7 +51,7 @@ class V3ParseGrammar {
public:
bool m_impliedDecl; // Allow implied wire declarations
AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc)
AstVarType m_varIO; // Type for next signal declaration (input/output/etc)
VDirection m_varIO; // Direction for next signal declaration (reg/wire/etc)
AstVar* m_varAttrp; // Current variable for attribute adding
AstRange* m_gateRangep; // Current range for gate declarations
AstCase* m_caseAttrp; // Current case statement for attribute adding
@@ -68,7 +68,7 @@ public:
V3ParseGrammar() {
m_impliedDecl = false;
m_varDecl = AstVarType::UNKNOWN;
m_varIO = AstVarType::UNKNOWN;
m_varIO = VDirection::NONE;
m_varDTypep = NULL;
m_gateRangep = NULL;
m_memDTypep = NULL;
@@ -182,9 +182,9 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
#define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist
#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist
#define VARRESET() { VARDECL(UNKNOWN); VARIO(UNKNOWN); VARDTYPE(NULL); }
#define VARRESET() { VARDECL(UNKNOWN); VARIO(NONE); VARDTYPE(NULL); }
#define VARDECL(type) { GRAMMARP->m_varDecl = AstVarType::type; }
#define VARIO(type) { GRAMMARP->m_varIO = AstVarType::type; }
#define VARIO(type) { GRAMMARP->m_varIO = VDirection::type; }
#define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); }
#define VARDONEA(fl,name,array,attrs) GRAMMARP->createVariable((fl),(name),(array),(attrs))
@@ -899,11 +899,11 @@ port<nodep>: // ==IEEE: port
// // Expanded interface_port_header
// // We use instantCb here because the non-port form looks just like a module instantiation
portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE
{ $$ = $3; VARDECL(AstVarType::IFACEREF); VARIO(UNKNOWN);
{ $$ = $3; VARDECL(AstVarType::IFACEREF); VARIO(NONE);
VARDTYPE(new AstIfaceRefDType($<fl>2,"",*$2));
$$->addNextNull(VARDONEP($$,$4,$5)); }
| portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE
{ $$ = $5; VARDECL(AstVarType::IFACEREF); VARIO(UNKNOWN);
{ $$ = $5; VARDECL(AstVarType::IFACEREF); VARIO(NONE);
VARDTYPE(new AstIfaceRefDType($<fl>2,"",*$2,*$4));
$$->addNextNull(VARDONEP($$,$6,$7)); }
| portDirNetE yINTERFACE portSig rangeListE sigAttrListE
@@ -1301,8 +1301,8 @@ port_direction: // ==IEEE: port_direction + tf_port_direction
yINPUT { VARIO(INPUT); }
| yOUTPUT { VARIO(OUTPUT); }
| yINOUT { VARIO(INOUT); }
| yREF { $<fl>1->v3error("Unsupported: ref port"); VARIO(INOUT); }
| yCONST__REF yREF { $<fl>1->v3error("Unsupported: const ref port"); VARIO(INOUT); }
| yREF { VARIO(REF); }
| yCONST__REF yREF { VARIO(CONSTREF); }
;
port_directionReset: // IEEE: port_direction that starts a port_declaraiton
@@ -1310,8 +1310,8 @@ port_directionReset: // IEEE: port_direction that starts a port_declaraiton
yINPUT { VARRESET_NONLIST(UNKNOWN); VARIO(INPUT); }
| yOUTPUT { VARRESET_NONLIST(UNKNOWN); VARIO(OUTPUT); }
| yINOUT { VARRESET_NONLIST(UNKNOWN); VARIO(INOUT); }
| yREF { $<fl>1->v3error("Unsupported: ref port"); VARRESET_NONLIST(UNKNOWN); VARIO(INOUT); }
| yCONST__REF yREF { $<fl>1->v3error("Unsupported: const ref port"); VARRESET_NONLIST(UNKNOWN); VARIO(INOUT); }
| yREF { VARRESET_NONLIST(UNKNOWN); VARIO(REF); }
| yCONST__REF yREF { VARRESET_NONLIST(UNKNOWN); VARIO(CONSTREF); }
;
port_declaration<nodep>: // ==IEEE: port_declaration
@@ -3993,13 +3993,12 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nra
AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeRange* arrayp, AstNode* attrsp) {
AstNodeDType* dtypep = GRAMMARP->m_varDTypep;
UINFO(5," creVar "<<name<<" decl="<<GRAMMARP->m_varDecl<<" io="<<GRAMMARP->m_varIO<<" dt="<<(dtypep?"set":"")<<endl);
if (GRAMMARP->m_varIO == AstVarType::UNKNOWN
if (GRAMMARP->m_varIO == VDirection::NONE
&& GRAMMARP->m_varDecl == AstVarType::PORT) {
// Just a port list with variable name (not v2k format); AstPort already created
if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists");
return NULL;
}
AstVarType type = GRAMMARP->m_varIO;
if (GRAMMARP->m_varDecl == AstVarType::WREAL) {
// dtypep might not be null, might be implicit LOGIC before we knew better
dtypep = new AstBasicDType(fileline,AstBasicDTypeKwd::DOUBLE);
@@ -4010,21 +4009,28 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeR
dtypep = dtypep->cloneTree(false);
}
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<GRAMMARP->m_varDecl.ascii()<<" io="<<GRAMMARP->m_varIO.ascii()<<endl);
if (type == AstVarType::UNKNOWN
|| (type == AstVarType::PORT && GRAMMARP->m_varDecl != AstVarType::UNKNOWN))
type = GRAMMARP->m_varDecl;
if (type == AstVarType::UNKNOWN) fileline->v3fatalSrc("Unknown signal type declared");
AstVarType type = GRAMMARP->m_varDecl;
if (type == AstVarType::UNKNOWN) {
if (GRAMMARP->m_varIO.isAny()) {
type = AstVarType::PORT;
} else {
fileline->v3fatalSrc("Unknown signal type declared");
}
}
if (type == AstVarType::GENVAR) {
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
}
// Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE)
AstNodeDType* arrayDTypep = createArray(dtypep,arrayp,false);
AstNodeDType* arrayDTypep = createArray(dtypep, arrayp, false);
AstVar* nodep = new AstVar(fileline, type, name, VFlagChildDType(), arrayDTypep);
nodep->addAttrsp(attrsp);
if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl);
if (GRAMMARP->m_varIO != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varIO);
if (GRAMMARP->m_varIO != VDirection::NONE) {
nodep->declDirection(GRAMMARP->m_varIO);
nodep->direction(GRAMMARP->m_varIO);
}
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) {
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0));
+128 -66
View File
@@ -187,8 +187,9 @@ sub one_test {
} else {
$test->oprint("FAILED: ","*"x60,"\n");
my $j = ($opt_jobs>1?" -j":"");
push @fails, ("\t#".$test->soprint("%Error: $test->{errors}\n")
."\t\tmake$j && test_regress/"
my $makecmd = $ENV{VERILATOR_MAKE} || "make$j &&";
push @fails, ("\t#".$test->soprint("%Error: $test->{errors}\n")
."\t\t$makecmd test_regress/"
.$test->{pl_filename}
." ".join(' ', _args_scenario())
." --".$test->{scenario}."\n");
@@ -432,7 +433,8 @@ sub new {
$self->{run_log_filename} ||= "$self->{obj_dir}/vlt_sim.log";
$self->{coverage_filename} ||= "$self->{obj_dir}/coverage.dat";
$self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$//;
($self->{top_filename} ||= $self->{pl_filename}) =~ s/\.pl$//;
($self->{golden_filename} ||= $self->{pl_filename}) =~ s/\.pl$/.out/;
if (-e ($self->{top_filename}.".vhd")) { # If VHDL file exists
$self->{vhdl} = 1;
$self->{top_filename} .= ".vhd";
@@ -762,15 +764,15 @@ sub compile {
return 1;
}
if (!$param{fails} && $param{verilator_make_gcc}
&& $param{make_main}) {
$self->_make_main();
if (!$param{fails} && $param{make_main}) {
$self->_make_main();
}
$self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log",
fails=>$param{fails},
expect=>$param{expect},
cmd=>\@cmdargs) if $::Opt_Verilation;
expect=>$param{expect},
expect_filename=>$param{expect_filename},
cmd=>\@cmdargs) if $::Opt_Verilation;
return 1 if $self->errors || $self->skips || $self->unsupporteds;
if (!$param{fails} && $param{verilator_make_gcc}) {
@@ -824,8 +826,9 @@ sub execute {
@{$param{all_run_flags}},
],
%param,
expect=>$param{atsim_run_expect}, # non-verilator expect isn't the same
);
expect=>$param{atsim_run_expect}, # non-verilator expect isn't the same
expect_filename=>$param{atsim_run_expect_filename},
);
}
elsif ($param{ghdl}) {
$self->_run(logfile=>"$self->{obj_dir}/ghdl_sim.log",
@@ -835,8 +838,9 @@ sub execute {
@{$param{all_run_flags}},
],
%param,
expect=>$param{ghdl_run_expect}, # non-verilator expect isn't the same
);
expect=>$param{ghdl_run_expect}, # non-verilator expect isn't the same
expect_filename=>$param{ghdl_run_expect_filename},
);
}
elsif ($param{iv}) {
my @cmd = ($run_env."$self->{obj_dir}/simiv",
@@ -850,8 +854,9 @@ sub execute {
fails=>$param{fails},
cmd=> \@cmd,
%param,
expect=>$param{iv_run_expect}, # non-verilator expect isn't the same
);
expect=>$param{iv_run_expect}, # non-verilator expect isn't the same
expect_filename=>$param{iv_run_expect_filename},
);
}
elsif ($param{ms}) {
$self->_run(logfile=>"$self->{obj_dir}/ms_sim.log",
@@ -862,8 +867,9 @@ sub execute {
(" top")
],
%param,
expect=>$param{ms_run_expect}, # non-verilator expect isn't the same
);
expect=>$param{ms_run_expect}, # non-verilator expect isn't the same
expect_filename=>$param{ms_expect_filename},
);
}
elsif ($param{nc}) {
$self->_run(logfile=>"$self->{obj_dir}/nc_sim.log",
@@ -873,8 +879,9 @@ sub execute {
@{$param{all_run_flags}},
],
%param,
expect=>$param{nc_run_expect}, # non-verilator expect isn't the same
);
expect=>$param{nc_run_expect}, # non-verilator expect isn't the same
expect_filename=>$param{nc_run_expect_filename},
);
}
elsif ($param{vcs}) {
#my $fh = IO::File->new(">simv.key") or die "%Error: $! simv.key,";
@@ -885,8 +892,9 @@ sub execute {
@{$param{all_run_flags}},
],
%param,
expect=>$param{vcs_run_expect}, # non-verilator expect isn't the same
);
expect=>$param{vcs_run_expect}, # non-verilator expect isn't the same
expect_filename=>$param{vcs_run_expect_filename},
);
}
elsif ($param{vlt_all}
#&& (!$param{needs_v4} || -r "$ENV{VERILATOR_ROOT}/src/V3Gate.cpp")
@@ -901,8 +909,9 @@ sub execute {
($opt_gdbsim ? "'" : ""),
],
%param,
expect=>$param{expect}, # backward compatible name
);
expect=>$param{expect}, # backward compatible name
expect_filename=>$param{expect_filename}, # backward compatible name
);
}
else {
$self->error("No execute step for this simulator");
@@ -1102,8 +1111,9 @@ sub _run {
# Read the log file a couple of times to allow for NFS delays
if ($param{check_finished} || $param{expect}) {
for (my $try=7; $try>=0; $try--) {
sleep 1 if ($try!=7);
my $tries = $self->tries;
for (my $try=$tries-1; $try>=0; $try--) {
sleep 1 if ($try!=$tries-1);
my $moretry = $try!=0;
my $fh = IO::File->new("<$param{logfile}");
@@ -1112,17 +1122,18 @@ sub _run {
my $wholefile = <$fh>;
$fh->close();
# Strip debugging comments
$wholefile =~ s/^- [^\n]+\n//mig;
$wholefile =~ s/^- [a-z.0-9]+:\d+:[^\n]+\n//mig;
$wholefile =~ s/^dot [^\n]+\n//mig;
# Finished?
if ($param{check_finished} && $wholefile !~ /\*\-\* All Finished \*\-\*/) {
next if $moretry;
$self->error("Missing All Finished\n");
}
if ($param{expect}) {
# Strip debugging comments
# See also files_identical
$wholefile =~ s/^- [^\n]+\n//mig;
$wholefile =~ s/^- [a-z.0-9]+:\d+:[^\n]+\n//mig;
$wholefile =~ s/^dot [^\n]+\n//mig;
# Compare
my $quoted = quotemeta ($param{expect});
my $ok = ($wholefile eq $param{expect}
@@ -1144,6 +1155,9 @@ sub _run {
last;
}
}
if ($param{expect_filename}) {
files_identical($param{logfile}, $param{expect_filename}, 'logfile');
}
}
#######################################################################
@@ -1541,37 +1555,75 @@ sub verilator_version {
# File utilities
sub files_identical {
my $self = (ref $_[0]? shift : $Self);
my $fn1 = shift;
my $fn2 = shift;
my $f1 = IO::File->new("<$fn1"); if (!$f1) { warn "%Error: $! $fn1\n"; return 0; }
my $f2 = IO::File->new("<$fn2"); if (!$f2) { warn "%Error: $! $fn2\n"; return 0; }
my @l1 = $f1->getlines();
my @l2 = $f2->getlines();
my $nl = $#l1; $nl = $#l2 if ($#l2 > $nl);
for (my $l=0; $l<=$nl; $l++) {
if (($l1[$l]||"") ne ($l2[$l]||"")) {
warn ("%Warning: Line ".($l+1)." mismatches; $fn1 != $fn2\n"
."F1: ".($l1[$l]||"*EOF*\n")
."F2: ".($l2[$l]||"*EOF*\n"));
if ($ENV{HARNESS_UPDATE_GOLDEN}) { # Update golden files with current
warn "%Warning: HARNESS_UPDATE_GOLDEN set: cp $fn1 $fn2\n";
eval "use File::Copy;";
File::Copy::copy($fn1,$fn2);
} else {
warn "To update reference: HARNESS_UPDATE_GOLDEN=1 {command} or --golden\n";
}
return 0;
}
my $fn1_is_logfile = shift;
my $tries = $self->tries;
try:
for (my $try=$tries-1; $try>=0; $try--) {
sleep 1 if ($try!=$tries-1);
my $moretry = $try!=0;
my $f1 = IO::File->new("<$fn1");
my $f2 = IO::File->new("<$fn2");
if (!$f1) {
next try if $moretry;
$self->error("Files_identical file does not exist $fn1\n");
return 0;
}
if (!$f2 && !$ENV{HARNESS_UPDATE_GOLDEN}) {
next try if $moretry;
$self->error("Files_identical file does not exist $fn2\n");
return 0;
}
my @l1 = $f1 && $f1->getlines();
my @l2 = $f2 && $f2->getlines();
if ($fn1_is_logfile) {
@l1 = grep {
!/^- [^\n]+\n/
&& !/^- [a-z.0-9]+:\d+:[^\n]+\n/
&& !/^-node:/
&& !/^dot [^\n]+\n/
} @l1;
for (my $l=0; $l<=$#l1; ++$l) {
# Don't put control chars into our source repository
$l1[$l] =~ s/\r/<#013>/mig;
$l1[$l] =~ s/Command Failed[^\n]+/Command Failed/mig;
if ($l1[$l] =~ s/Exiting due to.*/Exiting due to/mig) {
splice @l1, $l+1; # Trunc rest
last;
}
}
}
my $nl = $#l1; $nl = $#l2 if ($#l2 > $nl);
for (my $l=0; $l<=$nl; ++$l) {
if (($l1[$l]||"") ne ($l2[$l]||"")) {
next try if $moretry;
$self->error("Line ".($l+1)." mismatches; $fn1 != $fn2");
warn("F1: ".($l1[$l]||"*EOF*\n")
."F2: ".($l2[$l]||"*EOF*\n"));
if ($ENV{HARNESS_UPDATE_GOLDEN}) { # Update golden files with current
warn "%Warning: HARNESS_UPDATE_GOLDEN set: cp $fn1 $fn2\n";
my $fhw = IO::File->new(">$fn2") or $self->error("Files_identical $! $fn2\n");
$fhw->print(join('',@l1));
} else {
warn "To update reference: HARNESS_UPDATE_GOLDEN=1 {command} or --golden\n";
}
return 0;
}
}
return 1;
}
return 1;
}
sub vcd_identical {
my $self = (ref $_[0]? shift : $Self);
my $fn1 = shift;
my $fn2 = shift;
if (!-r $fn1) { $self->error("File does not exist $fn1\n"); return 0; }
if (!-r $fn2) { $self->error("File does not exist $fn2\n"); return 0; }
if (!-r $fn1) { $self->error("Vcd_identical file does not exist $fn1\n"); return 0; }
if (!-r $fn2) { $self->error("Vcd_identical file does not exist $fn2\n"); return 0; }
{
# vcddiff to check transitions, if installed
my $cmd = qq{vcddiff --help};
@@ -1688,6 +1740,14 @@ sub cfg_with_threaded {
return ($_Cfg_With_Threaded =~ /yes/i) ? 1:0;
}
sub tries {
# Number of retries when reading logfiles, generally only need many
# retries when system is busy running a lot of tests
return 2 if !$::Fork->running;
return 7 if (scalar($::Fork->running)) > 1;
return 2;
}
sub file_grep_not {
my $self = (ref $_[0]? shift : $Self);
my $filename = shift;
@@ -1976,24 +2036,22 @@ Or in a hand-written C++ wrapper:
cout << "Read a = " << a << endl;
#endif
The C<expect> argument should not generally be used to decide if a test has
succeeded. However, in the case of tests that are designed to fail at
The C<expect_filename> specifies a filename that should be used to check
the output results. This should not generally be used to decide if a test
has succeeded. However, in the case of tests that are designed to fail at
compile time, it is the only option. For example:
compile (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
q{%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
%Error: t/t_gen_cond_bitrange_bad.v:\d+: Selection index out of range: 2:2 outside 1:0
%Error: Exiting due to .*},
);
compile(
v_flags2 => ["--lint-only"],
fails=>1,
expect_filename => $Self->{golden_filename},
);
The strings to match should be made general - for example the line numbers
in the Verilog should not be critical and the total number of errors should
not matter. This makes it easier to extend or modify the test in future.
Note expect_filename strips some debugging information from the logfile
when comparing.
The C<expect> argument specifies a regular expression which must match the
output.
=head1 DRIVER ARGUMENTS
@@ -2143,6 +2201,10 @@ Command to use to invoke GHDL.
Command to use to invoke Icarus Verilog.
=item VERILATOR_MAKE
Command to use to rebuild Verilator and run single test. Defaults to "make &&".
=item VERILATOR_MODELSIM
Command to use to invoke ModelSim.
+1 -1
View File
@@ -28,7 +28,7 @@ public:
operator vpiHandle() const { return m_handle; }
inline TestVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
TestVpiHandle& nofree() {
m_free = false;
m_free = false;
return *this;
}
};
@@ -0,0 +1,6 @@
%Error: t/t_array_backw_index_bad.v:13: Slice selection '[1:3]' has backward indexing versus data type's '[3:0]'
%Error: t/t_array_backw_index_bad.v:14: Slice selection '[3:1]' has backward indexing versus data type's '[0:3]'
%Error: t/t_array_backw_index_bad.v:16: Slice selection index '[4:3]' outside data type's '[3:0]'
%Error: t/t_array_backw_index_bad.v:17: Slice selection index '[1:-1]' outside data type's '[3:0]'
%Error: t/t_array_backw_index_bad.v:17: Assignment pattern missed initializing elements: -1
%Error: Exiting due to
+1 -6
View File
@@ -11,12 +11,7 @@ scenarios(simulator => 1);
compile(
fails => 1,
expect =>
q{%Error: t/t_array_backw_index_bad.v:\d+: Slice selection '\[1:3\]' has backward indexing versus data type's '\[3:0\]'
%Error: t/t_array_backw_index_bad.v:\d+: Slice selection '\[3:1\]' has backward indexing versus data type's '\[0:3\]'
%Error: t/t_array_backw_index_bad.v:\d+: Slice selection index '\[4:3\]' outside data type's '\[3:0\]'
%Error: t/t_array_backw_index_bad.v:\d+: Slice selection index '\[1:-1\]' outside data type's '\[3:0\]'
.*%Error: Exiting due to.*},
expect_filename => $Self->{golden_filename},
);
ok(1);
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
compile(
fails => 1,
expect =>
q{%Error: t/t_array_pattern_bad.v:23: Assignment pattern key 'valids' not found as member
.*%Error: Exiting due to.*},
);
ok(1);
1;
+25
View File
@@ -0,0 +1,25 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2018 by Wilson Snyder.
// bug1364
module t (/*AUTOARG*/
// Inputs
clk, res
);
input clk;
input res;
typedef struct packed {
logic [3:0] port_num;
} info_t;
info_t myinfo;
always_comb
myinfo = '{default: '0,
valids: '1};
endmodule
+1 -1
View File
@@ -12,7 +12,7 @@ module t (/*AUTOARG*/
logic [1:0] [3:0] [3:0] array_simp; // big endian array
logic [3:0] array_oned;
logic [3:0] array_oned;
initial begin
array_oned = '{2:1'b1, 0:1'b1, default:1'b0};
+3
View File
@@ -0,0 +1,3 @@
%Error: t/t_assert_dup_bad.v:16: Duplicate declaration of block: covlabel
%Error: t/t_assert_dup_bad.v:14: ... Location of original declaration
%Error: Exiting due to
+1 -4
View File
@@ -12,10 +12,7 @@ scenarios(simulator => 1);
compile(
v_flags2 => ["--lint-only"],
fails => 1,
expect =>
'%Error: t/t_assert_dup_bad.v:\d+: Duplicate declaration of block: covlabel
%Error: t/t_assert_dup_bad.v:\d+: ... Location of original declaration
%Error: Exiting due to.*',
expect_filename => $Self->{golden_filename},
);
ok(1);
+1 -1
View File
@@ -13,7 +13,7 @@ module t (/*AUTOARG*/
input clk;
input bit [3:0] sel;
input bit [3:0] a;
input bit c;
input bit c;
output bit dout;
localparam logic DC = 1'b?;
+3 -3
View File
@@ -9,8 +9,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
$Self->{golden_out} ||= "t/$Self->{name}.out";
compile(
verilator_flags2 => ["--stats --O3 -x-assign fast"],
);
@@ -19,5 +17,7 @@ execute(
check_finished => 1,
);
ok(files_identical("$Self->{obj_dir}/$Self->{name}_logger.log", $Self->{golden_out}));
files_identical("$Self->{obj_dir}/$Self->{name}_logger.log", $Self->{golden_filename});
ok(1);
1;
+2 -3
View File
@@ -9,8 +9,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
$Self->{golden_out} ||= "t/$Self->{name}.out";
compile(
verilator_flags2 => ["--stats --O3 -x-assign fast"],
);
@@ -19,6 +17,7 @@ execute(
check_finished => 1,
);
ok(files_identical("$Self->{obj_dir}/$Self->{name}_logger.log", $Self->{golden_out}));
files_identical("$Self->{obj_dir}/$Self->{name}_logger.log", $Self->{golden_filename});
ok(1);
1;
+6
View File
@@ -0,0 +1,6 @@
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:27: Logic in path that feeds async reset, via signal: t.rst2_bad_n
%Warning-CDCRSTLOGIC: Use "/* verilator lint_off CDCRSTLOGIC */" and lint_on around source to disable this message.
%Warning-CDCRSTLOGIC: See details in obj_vlt/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:52: Logic in path that feeds async reset, via signal: t.rst6a_bad_n
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:53: Logic in path that feeds async reset, via signal: t.rst6b_bad_n
%Error: Exiting due to
+3 -7
View File
@@ -12,14 +12,10 @@ scenarios(vlt => 1);
compile(
v_flags => ['--cdc'],
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
fails => 1,
expect =>
'%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst2_bad_n
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
%Warning-CDCRSTLOGIC: See details in obj_vlt/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst6a_bad_n
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: t.rst6b_bad_n
%Error: Exiting due to.*',
expect_filename => $Self->{golden_filename},
);
file_grep ("$Self->{obj_dir}/V$Self->{name}__cdc.txt", qr/CDC Report/);
+1 -1
View File
@@ -5,7 +5,7 @@
module t (/*AUTOARG*/);
wire [32767:0] a;
reg [32767:0] a;
initial begin
// verilator lint_off WIDTHCONCAT
+5
View File
@@ -0,0 +1,5 @@
%Error: t/t_const_overflow_bad.v:8: Too many digits for 94 bit number: 94'd123456789012345678901234567890
%Error: t/t_const_overflow_bad.v:10: Too many digits for 8 bit number: 8'habc
%Error: t/t_const_overflow_bad.v:11: Too many digits for 6 bit number: 6'o1234
%Error: t/t_const_overflow_bad.v:12: Too many digits for 3 bit number: 3'b1111
%Error: Exiting due to
+1 -6
View File
@@ -12,12 +12,7 @@ scenarios(simulator => 1);
compile(
v_flags2 => ["--lint-only"],
fails => 1,
expect =>
'%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 94 bit number: 94\'d123456789012345678901234567890
%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 8 bit number: 8\'habc
%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 6 bit number: 6\'o1234
%Error: t/t_const_overflow_bad.v:\d+: Too many digits for 3 bit number: 3\'b1111
%Error: Exiting due to.*',
expect_filename => $Self->{golden_filename},
);
ok(1);
+2 -1
View File
@@ -27,6 +27,7 @@ run(cmd => ["../bin/verilator_coverage",
"$Self->{obj_dir}/coverage.dat",
]);
ok(files_identical("$Self->{obj_dir}/annotated/t_cover_line.v", "t/t_cover_line.out"));
files_identical("$Self->{obj_dir}/annotated/t_cover_line.v", "t/t_cover_line.out");
ok(1);
1;
+1 -1
View File
@@ -16,7 +16,7 @@ module t (/*AUTOARG*/);
genvar the_genvar;
generate
for (the_genvar = 0; the_genvar < 4; the_genvar++) begin: foo_loop
foo foo_inst();
foo foo_inst();
end
endgenerate
+6
View File
@@ -0,0 +1,6 @@
%Warning-ASSIGNDLY: t/t_delay.v:19: Unsupported: Ignoring delay on this assignment/primitive.
%Warning-ASSIGNDLY: Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message.
%Warning-ASSIGNDLY: t/t_delay.v:24: Unsupported: Ignoring delay on this assignment/primitive.
%Warning-ASSIGNDLY: t/t_delay.v:27: Unsupported: Ignoring delay on this assignment/primitive.
%Warning-STMTDLY: t/t_delay.v:33: Unsupported: Ignoring delay on this delayed statement.
%Error: Exiting due to
+1 -7
View File
@@ -14,13 +14,7 @@ top_filename("t/t_delay.v");
compile(
verilator_flags2 => ['-Wall -Wno-DECLFILENAME'],
fails => 1,
expect =>
'%Warning-ASSIGNDLY: t/t_delay.v:\d+: Unsupported: Ignoring delay on this assignment/primitive.
%Warning-ASSIGNDLY: Use .*
%Warning-ASSIGNDLY: t/t_delay.v:\d+: Unsupported: Ignoring delay on this assignment/primitive.
%Warning-ASSIGNDLY: t/t_delay.v:\d+: Unsupported: Ignoring delay on this assignment/primitive.
%Warning-STMTDLY: t/t_delay.v:\d+: Unsupported: Ignoring delay on this delayed statement.
.*%Error: Exiting due to.*',
expect_filename => $Self->{golden_filename},
);
ok(1);
+52
View File
@@ -0,0 +1,52 @@
[0] In top.t: Hi
[0] In top.t.sub (sub)
[0] In top.t.sub.subblock (sub)
[0] In top.t.sub2 (sub2)
[0] In top.t.sub2.subblock2 (sub2)
[0] Back \ Quote "
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %d= 12 %0d=12 %d= 46099320012 %0d=46099320012 %d= 50692964483019020981880 %0d=50692964483019020981880
[0] %D= 12 %0D=12 %D= 46099320012 %0D=46099320012 %D= 50692964483019020981880 %0D=50692964483019020981880
[0] %h=00c %0h=c %h=00abbbbcccc %0h=abbbbcccc %h=00abc1234567812345678 %0h=abc1234567812345678
[0] %H=00c %0H=c %H=00abbbbcccc %0H=abbbbcccc %H=00abc1234567812345678 %0H=abc1234567812345678
[0] %o=014 %0o=14 %o=00527356746314 %0o=527356746314 %o=012570110642547402215053170 %0o=12570110642547402215053170
[0] %O=014 %0O=14 %O=00527356746314 %0O=527356746314 %O=012570110642547402215053170 %0O=12570110642547402215053170
[0] %x=00c %0x=c %x=00abbbbcccc %0x=abbbbcccc %x=00abc1234567812345678 %0x=abc1234567812345678
[0] %X=00c %0X=c %X=00abbbbcccc %0X=abbbbcccc %X=00abc1234567812345678 %0X=abc1234567812345678
[0] %d= 12 %0d=12 %d= -46099320012 %0d=-46099320012 %d= 50692964483019020981880 %0d=50692964483019020981880
[0] %D= 12 %0D=12 %D= -46099320012 %0D=-46099320012 %D= -50692964483019020981880 %0D=-50692964483019020981880
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %d= 12 %0d=12 %d= 46099320012 %0d=46099320012 %d= 50692964483019020981880 %0d=50692964483019020981880
[0] %D= 12 %0D=12 %D= 46099320012 %0D=46099320012 %D= 50692964483019020981880 %0D=50692964483019020981880
[0] %h=00c %0h=c %h=00abbbbcccc %0h=abbbbcccc %h=00abc1234567812345678 %0h=abc1234567812345678
[0] %H=00c %0H=c %H=00abbbbcccc %0H=abbbbcccc %H=00abc1234567812345678 %0H=abc1234567812345678
[0] %o=014 %0o=14 %o=00527356746314 %0o=527356746314 %o=012570110642547402215053170 %0o=12570110642547402215053170
[0] %O=014 %0O=14 %O=00527356746314 %0O=527356746314 %O=012570110642547402215053170 %0O=12570110642547402215053170
[0] %x=00c %0x=c %x=00abbbbcccc %0x=abbbbcccc %x=00abc1234567812345678 %0x=abc1234567812345678
[0] %X=00c %0X=c %X=00abbbbcccc %0X=abbbbcccc %X=00abc1234567812345678 %0X=abc1234567812345678
[0] %d= -12 %0d=-12 %d= -46099320012 %0d=-46099320012 %d= -50692964483019020981880 %0d=-50692964483019020981880
[0] %D= -12 %0D=-12 %D= -46099320012 %0D=-46099320012 %D= -50692964483019020981880 %0D=-50692964483019020981880
[0] %C=m %0C=m
[0] %c=m %0c=m
[0] %v=St0 St0 St0 St0 St0 St1 St1 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St1 St0 St0 %v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 <
[0] %V=St0 St0 St0 St0 St0 St1 St1 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St1 St0 St0 %V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 <
[0] %p='hc %0p='hc %p='habbbbcccc %0p='habbbbcccc %p='habc1234567812345678 %0p='habc1234567812345678
[0] %P='hc %0P='hc %P='habbbbcccc %0P='habbbbcccc %P='habc1234567812345678 %0P='habc1234567812345678
[0] %P="sv-str"
[0] %u=dcba %0u=dcba
[0] %U=dcba %0U=dcba
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
[0] %t= 0 %03t= 0 %0t=0
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
hello, from a concatenated string.
hello, from a concatenated format string [0].
extra argument: 0000000000000000
0000000000000000: pre argument
[0] Embedded <#013> return
[0] Embedded
multiline
*-* All Finished *-*
+2 -58
View File
@@ -14,65 +14,9 @@ compile(
execute(
check_finished => 1,
expect => dequote(
q{[0] In top.t: Hi
[0] In top.t.sub (sub)
[0] In top.t.sub.subblock (sub)
[0] In top.t.sub2 (sub2)
[0] In top.t.sub2.subblock2 (sub2)
[0] Back \ Quote "
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %d= 12 %0d=12 %d= 46099320012 %0d=46099320012 %d= 50692964483019020981880 %0d=50692964483019020981880
[0] %D= 12 %0D=12 %D= 46099320012 %0D=46099320012 %D= 50692964483019020981880 %0D=50692964483019020981880
[0] %h=00c %0h=c %h=00abbbbcccc %0h=abbbbcccc %h=00abc1234567812345678 %0h=abc1234567812345678
[0] %H=00c %0H=c %H=00abbbbcccc %0H=abbbbcccc %H=00abc1234567812345678 %0H=abc1234567812345678
[0] %o=014 %0o=14 %o=00527356746314 %0o=527356746314 %o=012570110642547402215053170 %0o=12570110642547402215053170
[0] %O=014 %0O=14 %O=00527356746314 %0O=527356746314 %O=012570110642547402215053170 %0O=12570110642547402215053170
[0] %x=00c %0x=c %x=00abbbbcccc %0x=abbbbcccc %x=00abc1234567812345678 %0x=abc1234567812345678
[0] %X=00c %0X=c %X=00abbbbcccc %0X=abbbbcccc %X=00abc1234567812345678 %0X=abc1234567812345678
[0] %d= 12 %0d=12 %d= -46099320012 %0d=-46099320012 %d= 50692964483019020981880 %0d=50692964483019020981880
[0] %D= 12 %0D=12 %D= -46099320012 %0D=-46099320012 %D= -50692964483019020981880 %0D=-50692964483019020981880
[0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %d= 12 %0d=12 %d= 46099320012 %0d=46099320012 %d= 50692964483019020981880 %0d=50692964483019020981880
[0] %D= 12 %0D=12 %D= 46099320012 %0D=46099320012 %D= 50692964483019020981880 %0D=50692964483019020981880
[0] %h=00c %0h=c %h=00abbbbcccc %0h=abbbbcccc %h=00abc1234567812345678 %0h=abc1234567812345678
[0] %H=00c %0H=c %H=00abbbbcccc %0H=abbbbcccc %H=00abc1234567812345678 %0H=abc1234567812345678
[0] %o=014 %0o=14 %o=00527356746314 %0o=527356746314 %o=012570110642547402215053170 %0o=12570110642547402215053170
[0] %O=014 %0O=14 %O=00527356746314 %0O=527356746314 %O=012570110642547402215053170 %0O=12570110642547402215053170
[0] %x=00c %0x=c %x=00abbbbcccc %0x=abbbbcccc %x=00abc1234567812345678 %0x=abc1234567812345678
[0] %X=00c %0X=c %X=00abbbbcccc %0X=abbbbcccc %X=00abc1234567812345678 %0X=abc1234567812345678
[0] %d= -12 %0d=-12 %d= -46099320012 %0d=-46099320012 %d= -50692964483019020981880 %0d=-50692964483019020981880
[0] %D= -12 %0D=-12 %D= -46099320012 %0D=-46099320012 %D= -50692964483019020981880 %0D=-50692964483019020981880
[0] %C=m %0C=m
[0] %c=m %0c=m
[0] %v=St0 St0 St0 St0 St0 St1 St1 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St1 St0 St0 %v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 %0v=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 <
[0] %V=St0 St0 St0 St0 St0 St1 St1 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St1 St0 St0 %V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St0 St1 St1 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 St1 St1 St0 St0 %V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 %0V=St0 St0 St0 St0 St0 St1 St0 St1 St0 St1 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 St0 St0 St0 St1 St0 St0 St1 St0 St0 St0 St1 St1 St0 St1 St0 St0 St0 St1 St0 St1 St0 St1 St1 St0 St0 St1 St1 St1 St1 St0 St0 St0 <
[0] %p='hc %0p='hc %p='habbbbcccc %0p='habbbbcccc %p='habc1234567812345678 %0p='habc1234567812345678
[0] %P='hc %0P='hc %P='habbbbcccc %0P='habbbbcccc %P='habc1234567812345678 %0P='habc1234567812345678
[0] %P="sv-str"
[0] %u=dcba %0u=dcba
[0] %U=dcba %0U=dcba
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
[0] %t= 0 %03t= 0 %0t=0
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
hello, from a concatenated string.
hello, from a concatenated format string [0].
extra argument: 0000000000000000
0000000000000000: pre argument
[0] Embedded <#013> return
[0] Embedded
multiline
*-* All Finished *-*
}),
);
expect_filename => $Self->{golden_filename},
);
ok(1);
# Don't put control chars into our source repository, pre-compress instead
sub dequote { my $s = shift; $s =~ s/<#013>/\r/g; $s; }
1;
+3
View File
@@ -0,0 +1,3 @@
%Error: t/t_display_bad.v:10: Missing arguments for $display-like format
%Error: t/t_display_bad.v:12: Unknown $display-like format code: %q
%Error: Exiting due to

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