mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 16:44:11 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2685037ca2 | ||
|
|
940dc98c66 | ||
|
|
49353784fd | ||
|
|
2e5919549c | ||
|
|
8170391573 | ||
|
|
61e4b0a472 | ||
|
|
15af706286 | ||
|
|
2a43410fa6 | ||
|
|
5cc11839b5 | ||
|
|
d1bfeae026 | ||
|
|
e0b2c46664 | ||
|
|
ea61559ab5 | ||
|
|
6a5a2a56d7 | ||
|
|
5cbf80918f | ||
|
|
196e3a9712 | ||
|
|
3798b80091 | ||
|
|
689e4cf1d3 | ||
|
|
64f11251b6 | ||
|
|
6cd2bd2972 | ||
|
|
d396c55e34 | ||
|
|
45c9939a5e | ||
|
|
ad2929dff0 | ||
|
|
d3e1dfd3f5 | ||
|
|
14b48140bd | ||
|
|
7be1678fb0 | ||
|
|
d464ce1477 | ||
|
|
0a04f79576 | ||
|
|
b8098098d8 | ||
|
|
dc26815b1c | ||
|
|
f2028b60af | ||
|
|
06c7d8ce3b | ||
|
|
160505c5a4 |
@@ -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]
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
.*\.1
|
||||
/obj_dir/
|
||||
/obj_dbg/
|
||||
/obj_nc/
|
||||
/obj_opt/
|
||||
/obj_vcs/
|
||||
/obj_vlt/
|
||||
/obj_vltmt/
|
||||
/obj_dist/
|
||||
|
||||
+57
-21
@@ -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);
|
||||
...
|
||||
|
||||
@@ -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));
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -29,4 +29,4 @@
|
||||
// Hide file descriptor difference - deprecated - for older versions
|
||||
`define verilator_file_descriptor integer
|
||||
|
||||
`endif // guard
|
||||
`endif // guard
|
||||
|
||||
+10
-10
@@ -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};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -140,4 +140,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
#endif // guard
|
||||
|
||||
+12
-12
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -248,4 +248,4 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& r
|
||||
return os.read((void*)rhs.data(), len);
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
#endif // Guard
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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*");
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"; },
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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";
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
Executable
+20
@@ -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;
|
||||
@@ -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
|
||||
@@ -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};
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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?;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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/);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
wire [32767:0] a;
|
||||
reg [32767:0] a;
|
||||
|
||||
initial begin
|
||||
// verilator lint_off WIDTHCONCAT
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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 *-*
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user