mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8e437c45c | ||
|
|
4627716aa4 | ||
|
|
847dbbbaf0 | ||
|
|
d90064eaee | ||
|
|
8e646bc55f | ||
|
|
3a777c2a37 | ||
|
|
237f4806bf | ||
|
|
dfe66a2b77 | ||
|
|
a0b09b6450 | ||
|
|
9e3a88c41d | ||
|
|
736bf75a50 | ||
|
|
129610821f | ||
|
|
4cd0310516 | ||
|
|
4f962bddd8 | ||
|
|
45eddfb335 | ||
|
|
d4b9b5aba6 | ||
|
|
b1bf742544 | ||
|
|
cdd70ff8fc | ||
|
|
2b56acb39a | ||
|
|
35a40b4930 | ||
|
|
ae33a1ceb1 | ||
|
|
d225e46e4a | ||
|
|
43d07235c9 | ||
|
|
047a08c999 | ||
|
|
1d74657bbb | ||
|
|
65bb93a6c5 | ||
|
|
6e7f28785e | ||
|
|
0eb1d0a84e | ||
|
|
5d26bca55c | ||
|
|
a15e6f68dd | ||
|
|
77e7e2bf1c | ||
|
|
1c5c9e2435 | ||
|
|
f0ed4346b2 | ||
|
|
94c8064798 | ||
|
|
cf0464c263 | ||
|
|
6268db643c | ||
|
|
fd98d231e4 | ||
|
|
92649ba494 | ||
|
|
0efe343494 | ||
|
|
84335b9580 | ||
|
|
e8b2c57610 | ||
|
|
5e22ca77ec | ||
|
|
b6e8133a4d | ||
|
|
02a22c12ea | ||
|
|
fe917ba7f4 | ||
|
|
2c568603f6 | ||
|
|
51422e3ee8 | ||
|
|
0ef3c10931 | ||
|
|
35be80f789 | ||
|
|
c29e7619eb | ||
|
|
a265417727 | ||
|
|
b69af164f7 | ||
|
|
ff61bb509c | ||
|
|
c8ba51581f | ||
|
|
29f1a9208e | ||
|
|
8b954dc381 | ||
|
|
767ac2547d | ||
|
|
a46aa2d62b | ||
|
|
9219ddaece | ||
|
|
c7c99d8553 | ||
|
|
e3354a0191 | ||
|
|
df3d1a4da9 | ||
|
|
3963fe4384 | ||
|
|
38261ac649 | ||
|
|
e49539fb4c | ||
|
|
3cd96cf558 | ||
|
|
1bcaaa0f0d | ||
|
|
7922a1de28 | ||
|
|
e897c862f2 | ||
|
|
f55040a38b | ||
|
|
2d580e6939 | ||
|
|
fc48008c1c | ||
|
|
4cf2e4024f | ||
|
|
57c7d77af3 | ||
|
|
c8cf2afb15 | ||
|
|
770045676f | ||
|
|
68cca0e114 | ||
|
|
0a1b775ed6 | ||
|
|
54a101acbe | ||
|
|
db1af07d72 | ||
|
|
ff82f75023 | ||
|
|
9ae54786e4 | ||
|
|
22ff760f0b | ||
|
|
86fe6ac3a8 | ||
|
|
9f52e23158 | ||
|
|
e1410775fb | ||
|
|
a7a790416e | ||
|
|
fe5c4df079 | ||
|
|
1376e5de92 | ||
|
|
7f5b1a402c | ||
|
|
22573d238b | ||
|
|
32859d9fc2 | ||
|
|
1b12800b8f | ||
|
|
13d11b037a | ||
|
|
0ca0854cac | ||
|
|
1726c71649 | ||
|
|
fd8c29f981 | ||
|
|
e07ee559a0 | ||
|
|
097107bd0b | ||
|
|
b40b152b87 | ||
|
|
3c7fef68c0 | ||
|
|
b2322ae873 | ||
|
|
e3f137875b | ||
|
|
71fcf45d73 | ||
|
|
652b68a5a0 | ||
|
|
3e0401de1c | ||
|
|
c164024f38 | ||
|
|
bd1f1e8699 | ||
|
|
7ee6efab74 | ||
|
|
3788e90644 | ||
|
|
8e65d93d6d | ||
|
|
4901668f13 | ||
|
|
f98940e40a | ||
|
|
49fe4d081c | ||
|
|
3054b36a8d | ||
|
|
b888158907 | ||
|
|
173f71dca6 | ||
|
|
37a931feb4 | ||
|
|
79f5c7fbda | ||
|
|
bf3f111ca4 | ||
|
|
9a2a5d3155 | ||
|
|
2a7c61cd6d | ||
|
|
51787d68b9 | ||
|
|
33eb0db6f8 | ||
|
|
a0b2727c59 | ||
|
|
d1b8f53711 | ||
|
|
27b5bfe9b1 | ||
|
|
ea91b10086 | ||
|
|
08da777b33 | ||
|
|
345657ab32 | ||
|
|
1b605ade94 | ||
|
|
b11fa372b1 | ||
|
|
662ebece71 | ||
|
|
6b6e8dc83e | ||
|
|
d215149c7c | ||
|
|
895fc0911a | ||
|
|
754527edfd | ||
|
|
f0217edef1 | ||
|
|
8f1798cc6f | ||
|
|
631bda395d | ||
|
|
791d02a753 | ||
|
|
54b3f92951 | ||
|
|
45de0599d7 | ||
|
|
331ecdc2e7 | ||
|
|
339a7640a8 |
@@ -23,6 +23,7 @@ dddrun*
|
||||
doxygen-doc
|
||||
gdbrun*
|
||||
gmon.out
|
||||
ncverilog.history
|
||||
internals.txt
|
||||
verilator.txt
|
||||
verilator_bin*
|
||||
|
||||
@@ -2,6 +2,113 @@ Revision history for Verilator
|
||||
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
* Verilator 3.926 2018-08-22
|
||||
|
||||
**** Add OBJCACHE envvar support to examples and generated Makefiles.
|
||||
|
||||
**** Change MODDUP errors to warnings, msg2588. [Marshal Qiao]
|
||||
|
||||
**** Fix define argument stringification (`"), broke since 3.914. [Joe DErrico]
|
||||
|
||||
**** Fix to ignore Unicode UTF-8 BOM sequences, msg2576. [HyungKi Jeong]
|
||||
|
||||
**** Fix std:: build error, bug1322.
|
||||
|
||||
**** Fix function inlining inside certain while loops, bug1330. [Julien Margetts]
|
||||
|
||||
|
||||
* Verilator 3.924 2018-06-12
|
||||
|
||||
*** Renamed --profile-cfuncs to --prof-cfuncs.
|
||||
|
||||
**** Report interface ports connected to wrong interface, bug1294. [Todd Strader]
|
||||
|
||||
**** When tracing, use scalars on single bit arrays to appease vcddiff.
|
||||
|
||||
**** Fix parsing "output signed" in V2K port list, msg2540. [James Jung]
|
||||
|
||||
**** Fix parsing error on bad missing #, bug1308. [Dan Kirkham]
|
||||
|
||||
**** Fix $clog2 to be in verilog 2005, bug1319. [James Hutchinson]
|
||||
|
||||
|
||||
* Verilator 3.922 2018-03-17
|
||||
|
||||
** Support IEEE 1800-2017 as default language.
|
||||
|
||||
*** Support trig functions ($sin() etc), bug1281. [Patrick Stewart]
|
||||
|
||||
*** Support calling system functions as tasks, bug1285. [Joel Holdsworth]
|
||||
|
||||
*** Support assert properties, bug785, bug1290. [John Coiner, et al]
|
||||
|
||||
*** Support $writememh. [John Coiner]
|
||||
|
||||
*** Add --no-debug-leak to reduce memory use under debug. [John Coiner]
|
||||
|
||||
**** Fix severe runtime performance bug in certain foreach loops. [John Coiner]
|
||||
|
||||
**** On convergence errors, show activity. [John Coiner]
|
||||
|
||||
**** Fix GCC 8.0 issues, bug1273.
|
||||
|
||||
**** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard]
|
||||
|
||||
**** Fix verilator_coverage --annotate-min, bug1284. [Tymoteusz Blazejczyk]
|
||||
|
||||
**** Fix quoting of quoted arguments. [John Coiner]
|
||||
|
||||
|
||||
* Verilator 3.920 2018-02-01
|
||||
|
||||
** Moving forward, use the git "stable" branch to track the latest release,
|
||||
and git "v#.###" tags for specific releases.
|
||||
|
||||
*** Support 'assume' similar to 'assert', bug1269. [Dan Gisselquist]
|
||||
|
||||
**** Fix tracing example file output, bug1268. [Enzo Chi]
|
||||
|
||||
**** Fix gate optimization out of memory, add --gate-stmts, bug1260. [Alex Solomatnikov]
|
||||
|
||||
**** Fix compile error on public real parameters by suppressing, bug1261. [Alex Solomatnikov]
|
||||
|
||||
**** Fix input-only tristate comparisons, bug1267. [Alexis G]
|
||||
|
||||
**** Fix missing edge type in xml output, msg2480. [Alexis G]
|
||||
|
||||
**** Fix compile error with --public and interface bind, bug1264. [Alexis G]
|
||||
|
||||
**** Remove c++filt, bug1265. [Stefan Wallentowitz]
|
||||
|
||||
|
||||
* Verilator 3.918 2018-01-02
|
||||
|
||||
*** Workaround GCC/clang bug with huge compile times, bug1248.
|
||||
|
||||
*** Support DPI open arrays, bug909, bug1245. [David Pierce, Victor Besyakov]
|
||||
|
||||
*** Add INFINITELOOP warning, bug1254. [Alex Solomatnikov]
|
||||
|
||||
**** Support > 64 bit decimal $display.
|
||||
|
||||
**** Support DPI time and svLogicVal. [Victor Besyakov]
|
||||
Note older version incorrectly assumed svBitVal even for logicals.
|
||||
|
||||
**** Support string len() method. [Victor Besyakov]
|
||||
|
||||
**** Add error if always_comb has sensitivity list. [Arjen Roodselaar]
|
||||
|
||||
**** Fix SystemC 2.3.2 compile error, bug1251. [Tymoteusz Blazejczyk]
|
||||
|
||||
**** Fix modport outputs being treated as inputs, bug1246. [Jeff Bush]
|
||||
|
||||
**** Fix false ALWCOMBORDER on interface references, bug1247. [Josh Redford]
|
||||
|
||||
**** Fix constant propagation across DPI imports of inout strings. [Victor Besyakov]
|
||||
|
||||
**** Fix resolving inline nested interface names, bug1250. [Arjen Roodselaar]
|
||||
|
||||
|
||||
* Verilator 3.916 2017-11-25
|
||||
|
||||
*** Support self-recursive modules, bug659. [Sean Moore, et al]
|
||||
@@ -2106,7 +2213,7 @@ Bug fixes:
|
||||
|
||||
* Verilator 3.501 2005/11/16 Stable
|
||||
|
||||
*** Add --profile-cfuncs for correlating profiles back to Verilog.
|
||||
*** Add --prof-cfuncs for correlating profiles back to Verilog.
|
||||
|
||||
**** Fixed functions where regs are declared before inputs. [Danny Ding]
|
||||
|
||||
@@ -2974,7 +3081,7 @@ of input ports exists for tracing.
|
||||
|
||||
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
||||
|
||||
Copyright 2001-2017 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2001-2018 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.
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
/obj_dir/
|
||||
/obj_dbg/
|
||||
/obj_opt/
|
||||
/obj_vlt/
|
||||
/obj_vltmt/
|
||||
/obj_dist/
|
||||
/INCA_libs/
|
||||
/cov_work/
|
||||
/logs/
|
||||
@@ -34,6 +37,7 @@ verilator.pc$
|
||||
verilator_bin.*
|
||||
verilator_coverage_bin.*
|
||||
.vcsmx_rebuild$
|
||||
ncverilog.history
|
||||
autom4te\.cache/
|
||||
nodist/
|
||||
/simv$
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ This is the Verilator package README file.
|
||||
|
||||
http://www.veripool.org/verilator
|
||||
|
||||
This package is Copyright 2003-2017 by Wilson Snyder. (Report bugs to
|
||||
This package is Copyright 2003-2018 by Wilson Snyder. (Report bugs to
|
||||
L<http://www.veripool.org/>.)
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it under
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// DESCRIPTION: Verilator: List of To Do issues.
|
||||
//
|
||||
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2018 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.
|
||||
@@ -27,12 +27,10 @@ Long-term Features
|
||||
* Multithreaded execution
|
||||
|
||||
Configure/Make/Install
|
||||
* Full MSVC++ compilation (does scons support this?) (4.000?)
|
||||
* Distribute with flex/bison already expanded?
|
||||
Flex library not needed. Probably too difficult to be worth it.
|
||||
|
||||
Testing:
|
||||
* Move test_c/sp/v/verilated into test_regress format (4.000?)
|
||||
* Capture all inputs into global "rerun it" file
|
||||
* Code to make wrapper that sets signals, so can do comparison checks
|
||||
* New random program generator
|
||||
@@ -48,20 +46,17 @@ Usability:
|
||||
* Print version/etc message at runtime. (4.000?)
|
||||
Include number of lines of code, percent comments, code complexity measurement
|
||||
<-80chars------------------------------------------------------------------->
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2013.
|
||||
Verilator 3.600 - The fast free open-sourced simulator. Copyright 2001-2013.
|
||||
Verilated #### modules, #### instances, ##### sigs,
|
||||
#### non-comment lines, ##### ops, ### KB model size
|
||||
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
|
||||
|
||||
Lint:
|
||||
* CDCRSTLOGIC should allow filtering with paths
|
||||
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
|
||||
|
||||
Internal Code:
|
||||
* Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
|
||||
and removing it will speed up and simplify all the other code.
|
||||
* A Visitor class that understands how to traverse data types
|
||||
* V3Graph should be templated container type, taking in Vertex + Edge types
|
||||
* Rename V3PreLex etc to match VerilogPerl filenames
|
||||
* Instead of string, have an VEncodedString/VIdString which contains __DOT__ish
|
||||
things, to reduce bugs. Also add _20 trailing space to \ encoded names. (4.000)
|
||||
|
||||
@@ -114,7 +109,6 @@ Performance:
|
||||
* Usually blocks/values
|
||||
Enable only after certain time, so VL_TIME_I(32) > 0x1e gets eliminated out
|
||||
* Better ordering of a<=b, b<=c, put all refs to 'b' next to each other to optimize caching
|
||||
* Allow Split of case statements without a $display/$stop
|
||||
* I-cache packing improvements (what/how?)
|
||||
* Data cache organization (order of vars in class)
|
||||
First have clocks,
|
||||
|
||||
+164
-98
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -54,18 +54,6 @@ push @ARGV, (split ' ',$ENV{VERILATOR_TEST_FLAGS}||"");
|
||||
# We sneak a look at the flags so we can do some pre-environment checks
|
||||
# All flags will hit verilator...
|
||||
foreach my $sw (@ARGV) {
|
||||
# Some special treatment for parameters to allow verilog literals for numbers
|
||||
if ((substr($sw, 0, 2) eq "-G") || (substr($sw, 0, 8) eq "-pvalue+")) {
|
||||
# If there is a single quote in the parameter put it double quotes ,
|
||||
# else just put it in double quotes
|
||||
if ($sw =~ m![\']!) {
|
||||
$sw = "\"$sw\"";
|
||||
} else {
|
||||
$sw = "'$sw'";
|
||||
}
|
||||
} else {
|
||||
$sw = "'$sw'" if $sw =~ m![^---a-zA-Z0-9_/\\:.+]!;
|
||||
}
|
||||
push @Opt_Verilator_Sw, $sw;
|
||||
}
|
||||
|
||||
@@ -84,16 +72,30 @@ if (! GetOptions (
|
||||
pod2usage(-exitstatus=>2, -verbose=>0);
|
||||
}
|
||||
|
||||
# Determine runtime flags and run
|
||||
if ($opt_gdbbt && !gdb_works()) {
|
||||
warn "-Info: --gdbbt ignored: gdb doesn't seem to be working\n" if $Debug;
|
||||
$opt_gdbbt = 0;
|
||||
}
|
||||
|
||||
# Determine runtime flags and run
|
||||
# Opt_Verilator_Sw is what we want verilator to see on its argc/argv.
|
||||
# Starting with that, escape all special chars for the shell;
|
||||
# The shell will undo the escapes and the verilator binary should
|
||||
# then see exactly the contents of @Opt_Verilator_Sw.
|
||||
my @quoted_sw = map {sh_escape($_)} @Opt_Verilator_Sw;
|
||||
if ($opt_gdb) {
|
||||
# Generic GDB interactive
|
||||
run (("gdb"||$ENV{VERILATOR_GDB})
|
||||
." ".verilator_bin()
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
# Note, uncomment to set breakpoints before running:
|
||||
# ." -ex 'break main'"
|
||||
|
||||
# Note, we must use double-quotes ("run <switches>")
|
||||
# and not single ('run <switches>') below. Bash swallows
|
||||
# escapes as you would expect in a double-quoted string.
|
||||
# That's not true for a single-quoted string, where \'
|
||||
# actually terminates the string -- not what we want!
|
||||
." -ex \"run ".join(' ', @quoted_sw)."\""
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
} elsif ($opt_gdbbt && $Debug) {
|
||||
@@ -101,13 +103,12 @@ if ($opt_gdb) {
|
||||
run ("gdb"
|
||||
." ".verilator_bin()
|
||||
." --batch --quiet --return-child-result"
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
." -ex \"run ".join(' ', @quoted_sw)."\""
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
} else {
|
||||
# Normal, non gdb
|
||||
run (verilator_bin()
|
||||
." ".join(' ',@Opt_Verilator_Sw));
|
||||
run (verilator_bin()." ".join(' ',@quoted_sw));
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
@@ -196,6 +197,16 @@ sub run {
|
||||
}
|
||||
}
|
||||
|
||||
sub sh_escape {
|
||||
my ($arg) = @_;
|
||||
|
||||
# This is similar to quotemeta() but less aggressive.
|
||||
# There's no need to escape hyphens, periods, or forward slashes
|
||||
# for the shell as these have no special meaning to the shell.
|
||||
$arg =~ s/([^0-9a-zA-Z_\-\.\/])/\\$1/g;
|
||||
return $arg;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
#######################################################################
|
||||
package main;
|
||||
@@ -217,8 +228,8 @@ Verilator - Convert Verilog code to C++/SystemC
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Verilator converts synthesizable (not behavioral) Verilog code, plus some
|
||||
Synthesis, SystemVerilog and a small subset of Verilog AMS assertions, into
|
||||
Verilator converts synthesizable (generally not behavioral) Verilog code,
|
||||
plus some Synthesis, SystemVerilog and a small subset of Verilog AMS into
|
||||
C++ or SystemC code. It is not a complete simulator, but a compiler.
|
||||
|
||||
Verilator is invoked with parameters similar to GCC, Cadence
|
||||
@@ -238,8 +249,8 @@ To get started, jump down to "EXAMPLE C++ EXECUTION".
|
||||
|
||||
=head1 ARGUMENT SUMMARY
|
||||
|
||||
This is a short summary of the arguments to Verilator. See the detailed
|
||||
descriptions in the next sections for more information.
|
||||
This is a short summary of the arguments to Verilator itself. See the
|
||||
detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
|
||||
|
||||
{file.v} Verilog package, module and top module filenames
|
||||
{file.c/cc/cpp} Optional C++ files to compile in
|
||||
@@ -251,6 +262,7 @@ descriptions in the next sections for more information.
|
||||
+1800-2005ext+<ext> Use SystemVerilog 2005 with file extension <ext>
|
||||
+1800-2009ext+<ext> Use SystemVerilog 2009 with file extension <ext>
|
||||
+1800-2012ext+<ext> Use SystemVerilog 2012 with file extension <ext>
|
||||
+1800-2017ext+<ext> Use SystemVerilog 2017 with file extension <ext>
|
||||
--assert Enable all assertions
|
||||
--autoflush Flush streams after all $displays
|
||||
--bbox-sys Blackbox unknown $system calls
|
||||
@@ -270,6 +282,7 @@ descriptions in the next sections for more information.
|
||||
-D<var>[=<value>] Set preprocessor define
|
||||
--debug Enable debugging
|
||||
--debug-check Enable debugging assertions
|
||||
--no-debug-leak Disable leaking memory in --debug mode
|
||||
--debugi <level> Enable debugging at a specified level
|
||||
--debugi-<srcfile> <level> Enable debugging a source file at a level
|
||||
--default-language <lang> Default language to parse
|
||||
@@ -289,6 +302,7 @@ descriptions in the next sections for more information.
|
||||
--getenv <var> Get environment variable with defaults
|
||||
--help Display this help
|
||||
-I<dir> Directory to search for includes
|
||||
--gate-stmts <value> Tune gate optimizer depth
|
||||
--if-depth <value> Tune IFDEPTH warning
|
||||
+incdir+<dir> Directory to search for includes
|
||||
--inhibit-sim Create function to turn off sim
|
||||
@@ -323,7 +337,7 @@ descriptions in the next sections for more information.
|
||||
--pins-uint8 Specify types for top level ports
|
||||
--pipe-filter <command> Filter all input through a script
|
||||
--prefix <topname> Name of top level class
|
||||
--profile-cfuncs Name functions for profiling
|
||||
--prof-cfuncs Name functions for profiling
|
||||
--private Debugging; see docs
|
||||
--public Debugging; see docs
|
||||
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||
@@ -335,7 +349,7 @@ descriptions in the next sections for more information.
|
||||
--stats Create statistics file
|
||||
--stats-vars Provide statistics on variables
|
||||
-sv Enable SystemVerilog parsing
|
||||
+systemverilogext+<ext> Synonym for +1800-2012ext+<ext>
|
||||
+systemverilogext+<ext> Synonym for +1800-2017ext+<ext>
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
@@ -352,6 +366,7 @@ descriptions in the next sections for more information.
|
||||
-v <filename> Verilog library
|
||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||
--version Displays program version and exits
|
||||
--vpi Enable VPI compiles
|
||||
-Wall Enable all style warnings
|
||||
-Werror-<message> Convert warnings to errors
|
||||
@@ -366,7 +381,9 @@ descriptions in the next sections for more information.
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
|
||||
=head1 ARGUMENTS
|
||||
=head1 VERILATION ARGUMENTS
|
||||
|
||||
The following are the arguments that may be passed to Verilator itself.
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -402,6 +419,8 @@ with the --exe option.
|
||||
|
||||
=item +1800-2012ext+I<ext>
|
||||
|
||||
=item +1800-2017ext+I<ext>
|
||||
|
||||
Specifies the language standard to be used with a specific filename
|
||||
extension, I<ext>.
|
||||
|
||||
@@ -433,7 +452,7 @@ Enable all assertions.
|
||||
|
||||
=item --autoflush
|
||||
|
||||
After every $display or $fdisplay, flush the output stream. This insures
|
||||
After every $display or $fdisplay, flush the output stream. This ensures
|
||||
that messages will appear immediately but may reduce performance; for best
|
||||
performance call "fflush(stdout)" occasionally in the main C loop.
|
||||
Defaults off, which will buffer output as provided by the normal C stdio
|
||||
@@ -529,7 +548,7 @@ functions to avoid error C1061.
|
||||
|
||||
=back
|
||||
|
||||
=item --converge-limit <loops>
|
||||
=item --converge-limit I<loops>
|
||||
|
||||
Rarely needed. Specifies the maximum number of runtime iterations before
|
||||
creating a model failed to converge error. Defaults to 100.
|
||||
@@ -626,9 +645,21 @@ to C<--dump-treei 3>).
|
||||
Rarely needed. Enable internal debugging assertion checks, without
|
||||
changing debug verbosity. Enabled automatically when --debug specified.
|
||||
|
||||
=item --debugi <level>
|
||||
=item --no-debug-leak
|
||||
|
||||
=item --debugi-<srcfile> <level>
|
||||
In --debug mode, by default Verilator intentionally leaks AstNode's
|
||||
instead of freeing them, so that each node pointer is unique in the
|
||||
resulting tree files and dot files.
|
||||
|
||||
This option disables the leak. This may avoid out-of-memory errors
|
||||
when Verilating large models in --debug mode.
|
||||
|
||||
Outside of --debug mode, AstNode's should never be leaked and this option
|
||||
has no effect.
|
||||
|
||||
=item --debugi I<level>
|
||||
|
||||
=item --debugi-I<srcfile> I<level>
|
||||
|
||||
Rarely needed - for developer use. Set internal debugging level globally
|
||||
to the specified debug level (1-10) or set the specified Verilator source
|
||||
@@ -639,7 +670,7 @@ produce more detailed messages.
|
||||
|
||||
Select the language to be used by default when first processing each
|
||||
Verilog file. The language value must be "1364-1995", "1364-2001",
|
||||
"1364-2005", "1800-2005", "1800-2009" or "1800-2012".
|
||||
"1364-2005", "1800-2005", "1800-2009", "1800-2012" or "1800-2017".
|
||||
|
||||
Any language associated with a particular file extension (see the various
|
||||
+I<lang>ext+ options) will be used in preference to the language specified
|
||||
@@ -652,7 +683,7 @@ legacy mixed language designs, the various +I<lang>ext+ options should be
|
||||
used.
|
||||
|
||||
If no language is specified, either by this flag or +I<lang>ext+ options,
|
||||
then the latest SystemVerilog language (IEEE 1800-2012) is used.
|
||||
then the latest SystemVerilog language (IEEE 1800-2017) is used.
|
||||
|
||||
=item +define+I<var>=I<value>
|
||||
|
||||
@@ -670,9 +701,9 @@ the Verilator Internals manual. --dump-tree is enabled automatically with
|
||||
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
|
||||
large and not desired.
|
||||
|
||||
=item --dump-treei <level>
|
||||
=item --dump-treei I<level>
|
||||
|
||||
=item --dump-treei-<srcfile> <level>
|
||||
=item --dump-treei-I<srcfile> I<level>
|
||||
|
||||
Rarely needed - for developer use. Set internal tree dumping level
|
||||
globally to a specific dumping level or set the specified Verilator source
|
||||
@@ -686,7 +717,7 @@ Preprocess the source code, but do not compile, as with 'gcc -E'. Output
|
||||
is written to standard out. Beware of enabling debugging messages, as they
|
||||
will also go to standard out.
|
||||
|
||||
=item --error-limit <value>
|
||||
=item --error-limit I<value>
|
||||
|
||||
After this number of errors or warnings are encountered, exit. Defaults to
|
||||
50.
|
||||
@@ -713,7 +744,7 @@ The file may contain // comments which are ignored to the end of the line.
|
||||
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
||||
variable.
|
||||
|
||||
=item -FI <file>
|
||||
=item -FI I<file>
|
||||
|
||||
Force include of the specified C++ header file. All generated C++ files
|
||||
will insert a #include of the specified file before any other includes. The
|
||||
@@ -745,11 +776,16 @@ Double literals must contain a dot (.) and/or an exponent (e).
|
||||
|
||||
=item Strings
|
||||
|
||||
String must in double quotes ("). On the command line it is required to escape
|
||||
String must in double quotes (""). On the command line it is required to escape
|
||||
them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
|
||||
|
||||
=back
|
||||
|
||||
=item --gate-stmts I<value>
|
||||
|
||||
Rarely needed. Set the maximum number of statements that may be present in
|
||||
an equation for the gate substitution optimization to inline that equation.
|
||||
|
||||
=item --gdb
|
||||
|
||||
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment
|
||||
@@ -866,7 +902,7 @@ otherwise manually create the Mdir before calling Verilator.
|
||||
Specifies the name to prepend to all lower level classes. Defaults to
|
||||
the same as --prefix.
|
||||
|
||||
=item --no-clk <signal-name>
|
||||
=item --no-clk I<signal-name>
|
||||
|
||||
Prevent the specified signal from being marked as clock. See C<--clk>.
|
||||
|
||||
@@ -925,7 +961,7 @@ disables an optimization, an upper case letter enables it. This is
|
||||
intended for debugging use only; see the source code for version-dependent
|
||||
mappings of optimizations to -O letters.
|
||||
|
||||
=item -o <executable>
|
||||
=item -o I<executable>
|
||||
|
||||
Specify the name for the final executable built if using --exe. Defaults
|
||||
to the --prefix if not specified.
|
||||
@@ -1024,7 +1060,7 @@ Specifies the name of the top level class and makefile. Defaults to V
|
||||
prepended to the name of the --top-module switch, or V prepended to the
|
||||
first Verilog filename passed on the command line.
|
||||
|
||||
=item --profile-cfuncs
|
||||
=item --prof-cfuncs
|
||||
|
||||
Modify the created C++ functions to support profiling. The functions will
|
||||
be minimized to contain one "basic" statement, generally a single always
|
||||
@@ -1032,7 +1068,7 @@ block or wire statement. (Note this will slow down the executable by ~5%.)
|
||||
Furthermore, the function name will be suffixed with the basename of the
|
||||
Verilog module and line number the statement came from. This allows gprof
|
||||
or oprofile reports to be correlated with the original Verilog source
|
||||
statements.
|
||||
statements. See also L<verilator_profcfunc>.
|
||||
|
||||
=item --private
|
||||
|
||||
@@ -1113,7 +1149,7 @@ Creates a dump file with statistics on the design in {prefix}__stats.txt.
|
||||
|
||||
=item --stats-vars
|
||||
|
||||
Creates more detailed statistics including a list of all the variables by
|
||||
Creates more detailed statistics, including a list of all the variables by
|
||||
size (plain --stats just gives a count). See --stats, which is implied by
|
||||
this.
|
||||
|
||||
@@ -1125,7 +1161,7 @@ compatibility with other simulators.
|
||||
|
||||
=item +systemverilogext+I<ext>
|
||||
|
||||
A synonym for C<+1800-2012ext+>I<ext>.
|
||||
A synonym for C<+1800-2017ext+>I<ext>.
|
||||
|
||||
=item --top-module I<topname>
|
||||
|
||||
@@ -1140,8 +1176,8 @@ Adds waveform tracing code to the model. Verilator will generate
|
||||
additional {prefix}__Trace*.cpp files that will need to be compiled. In
|
||||
addition verilated_vcd_sc.cpp (for SystemC traces) or verilated_vcd_c.cpp
|
||||
(for both) must be compiled and linked in. If using the Verilator
|
||||
generated Makefiles, these will be added as source targets for you. If
|
||||
you're not using the Verilator makefiles, you will need to add these to
|
||||
generated Makefiles, these files will be added as source targets for you.
|
||||
If you're not using the Verilator makefiles, you will need to add these to
|
||||
your Makefile manually.
|
||||
|
||||
Having tracing compiled in may result in some small performance losses,
|
||||
@@ -1219,6 +1255,10 @@ Note -v is fairly standard across Verilog tools.
|
||||
|
||||
Synonyms for C<+1364-1995ext+>I<ext> and C<+1364-2001ext+>I<ext> respectively
|
||||
|
||||
=item --version
|
||||
|
||||
Displays program version and exits.
|
||||
|
||||
=item --vpi
|
||||
|
||||
Enable use of VPI and linking against the verilated_vpi.cpp files.
|
||||
@@ -1245,8 +1285,9 @@ supports which the older version does not support.
|
||||
|
||||
=item -Wno-I<message>
|
||||
|
||||
Disable the specified warning message. This will override any lint_on
|
||||
directives in the source, i.e. the warning will still not be printed.
|
||||
Disable the specified warning message, or in some cases where noted here
|
||||
disable an error. This will override any lint_on directives in the source,
|
||||
i.e. the warning will still not be printed.
|
||||
|
||||
=item -Wno-lint
|
||||
|
||||
@@ -1337,7 +1378,7 @@ not otherwise initialized.
|
||||
|
||||
--x-initial=unique, the default, initializes variables using a function,
|
||||
which determines the value to use each initialization. This gives greatest
|
||||
flexibility and allows finding reset bugs. See L</"Unknown states">
|
||||
flexibility and allows finding reset bugs. See L</"Unknown states">.
|
||||
|
||||
--x-initial=fast, is best for performance, and initializes all variables to
|
||||
a state Verilator determines is optimal. This may allow further code
|
||||
@@ -1569,7 +1610,7 @@ fast path, mostly code that is executed every cycle. OPT_SLOW specifies
|
||||
optimizations for slow-path files (plus tracing), which execute only
|
||||
rarely, yet take a long time to compile with optimization on. OPT
|
||||
specifies overall optimization and affects all compiles, including those
|
||||
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
|
||||
OPT_FAST and OPT_SLOW control. For best results, use OPT="-O2", and link
|
||||
with "-static". Nearly the same results can be had with much better
|
||||
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
|
||||
such as "-O3" may help, but gcc compile times may be excessive under O3 on
|
||||
@@ -1598,7 +1639,7 @@ code with -DVL_INLINE_OPT=inline. This will inline functions, however this
|
||||
requires that all cpp files be compiled in a single compiler run.
|
||||
|
||||
You may uncover further tuning possibilities by profiling the Verilog code.
|
||||
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
|
||||
Use Verilator's --prof-cfuncs, then GCC's -g -pg. You can then run
|
||||
either oprofile or gprof to see where in the C++ code the time is spent.
|
||||
Run the gprof output through verilator_profcfunc and it will tell you what
|
||||
Verilog line numbers on which most of the time is being spent.
|
||||
@@ -1666,8 +1707,8 @@ needed at runtime.
|
||||
|
||||
Optionally specifies a caching or distribution program to place in front of
|
||||
all runs of the C++ Compiler. For example, "objcache --read --write", or
|
||||
"ccache". If using distcc, it would generally be run under either objcache
|
||||
or ccache; see the documentation for those programs.
|
||||
"ccache". If using distcc or icecc/icecream, they would generally be run
|
||||
under either objcache or ccache; see the documentation for those programs.
|
||||
|
||||
=item SYSTEMC
|
||||
|
||||
@@ -2188,6 +2229,11 @@ Verilator currently has some support for SystemVerilog synthesis
|
||||
constructs. As SystemVerilog features enter common usage they are added;
|
||||
please file a bug if a feature you need is missing.
|
||||
|
||||
=head2 SystemVerilog 2017 (IEEE 1800-2017) Support
|
||||
|
||||
Verilator supports the 2017 "for" loop constructs, and several minor
|
||||
cleanups made in 1800-2017.
|
||||
|
||||
=head2 Verilog AMS Support
|
||||
|
||||
Verilator implements a very small subset of Verilog AMS (Verilog Analog and
|
||||
@@ -3041,13 +3087,15 @@ Simply use a different register for the flop:
|
||||
always @* foo[0] = foo_flopped[0];
|
||||
always @* foo[1] = ...
|
||||
|
||||
It is also possible to disable this error when one of the assignments is
|
||||
inside a public task.
|
||||
|
||||
This is not illegal in SystemVerilog, but a violation of good coding
|
||||
practice. Verilator reports this as an error, because ignoring this warning
|
||||
may make Verilator simulations differ from other simulators.
|
||||
|
||||
It is generally safe to disable this error (with a "// verilator lint_off
|
||||
BLKANDNBLK" metacomment or the -Wno-BLKANDNBLK option) when one of the
|
||||
assignments is inside a public task, or when the blocked and non-blocking
|
||||
assignments have non-overlapping bits and structure members.
|
||||
|
||||
=item BLKSEQ
|
||||
|
||||
This indicates that a blocking assignment (=) is used in a sequential
|
||||
@@ -3275,6 +3323,18 @@ command line to specify the top include source directories.
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item INFINITELOOP
|
||||
|
||||
Warns that a while or for statement has a condition that is always true.
|
||||
and thus result in an infinite loop if the statement ever executes.
|
||||
|
||||
This might be unintended behavior if the loop body contains statements that
|
||||
in other statements that would make time pass, which Verilator is ignoring
|
||||
due to e.g. STMTDLY warnings being disabled.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly (i.e. hang due to the infinite loop).
|
||||
|
||||
=item INITIALDLY
|
||||
|
||||
Warns that you have a delayed assignment inside of an initial or final
|
||||
@@ -3301,10 +3361,14 @@ correctly.
|
||||
|
||||
=item MODDUP
|
||||
|
||||
Error that a module has multiple definitions. Generally this indicates a
|
||||
Warns that a module has multiple definitions. Generally this indicates a
|
||||
coding error, or a mistake in a library file and it's good practice to have
|
||||
one module per file to avoid these issues. For some gate level netlists
|
||||
duplicates are unavoidable, and this error may be disabled.
|
||||
one module per file (and only put each file once on the command line) to
|
||||
avoid these issues. For some gate level netlists duplicates are sometimes
|
||||
unavoidable, and MODDUP should be disabled.
|
||||
|
||||
Ignoring this warning will cause the more recent module definition to be
|
||||
discarded.
|
||||
|
||||
=item MULTIDRIVEN
|
||||
|
||||
@@ -3651,7 +3715,7 @@ For example:
|
||||
will toggle forever and thus the executable will give the didn't converge
|
||||
error to prevent an infinite loop.
|
||||
|
||||
To debug this, run Verilator with --profile-cfuncs. Run make on the
|
||||
To debug this, run Verilator with --prof-cfuncs. Run make on the
|
||||
generated files with "OPT=-DVL_DEBUG". Then call Verilated::debug(1) in
|
||||
your main.cpp.
|
||||
|
||||
@@ -4087,7 +4151,7 @@ When possible, please instead report bugs to L<http://www.veripool.org/>.
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
Major concepts by Paul Wasson, Duane Galbi and Jie Xu.
|
||||
Major concepts by Paul Wasson, Duane Galbi, John Coiner and Jie Xu.
|
||||
|
||||
|
||||
=head1 CONTRIBUTORS
|
||||
@@ -4111,50 +4175,52 @@ Some of the people who have provided ideas and feedback for Verilator
|
||||
include: Ahmed El-Mahmoudy, David Addison, Tariq B. Ahmad, Nikana
|
||||
Anastasiadis, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad
|
||||
Bagri, Andrew Bardsley, Matthew Barr, Geoff Barrett, Julius Baxter, Jeremy
|
||||
Bennett, Michael Berman, David Binderman, Johan Bjork, David Black, Daniel
|
||||
Bone, Gregg Bouchard, Christopher Boumenot, Nick Bowler, Byron Bradley,
|
||||
Bryan Brady, Charlie Brej, J Briquet, Lane Brooks, John Brownlee, Jeff
|
||||
Bush, Lawrence Butcher, Ted Campbell, Chris Candler, Lauren Carlson, Donal
|
||||
Casey, Terry Chen, Enzo Chi, Robert A. Clark, Allan Cochrane, John Coiner,
|
||||
Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, John Demme, Mike Denio,
|
||||
John Deroo, Philip Derrick, John Dickol, Ruben Diez, Danny Ding, Ivan
|
||||
Djordjevic, Jonathon Donaldson, Sebastian Dressler, Alex Duller, Jeff
|
||||
Dutton, Usuario Eda, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert
|
||||
Bennett, Michael Berman, Victor Besyakov, David Binderman, Johan Bjork,
|
||||
David Black, Tymoteusz Blazejczyk, Daniel Bone, Gregg Bouchard, Christopher
|
||||
Boumenot, Nick Bowler, Byron Bradley, Bryan Brady, Charlie Brej, J Briquet,
|
||||
Lane Brooks, John Brownlee, Jeff Bush, Lawrence Butcher, Ted Campbell,
|
||||
Chris Candler, Lauren Carlson, Donal Casey, Terry Chen, Enzo Chi, Robert
|
||||
A. Clark, Allan Cochrane, John Coiner, Laurens van Dam, Gunter Dannoritzer,
|
||||
Ashutosh Das, Bernard Deadman, John Demme, Mike Denio, John Deroo, Philip
|
||||
Derrick, Joe DErrico, John Dickol, Ruben Diez, Danny Ding, Ivan Djordjevic,
|
||||
Jonathon Donaldson, Sebastian Dressler, Alex Duller, Jeff Dutton, Usuario
|
||||
Eda, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Trevor Elbourne, Robert
|
||||
Farrell, Eugen Fekete, Fabrizio Ferrandi, Brian Flachs, Andrea Foletto, Bob
|
||||
Fredieu, Christian Gelinek, Glen Gibb, Shankar Giri, Dan Gisselquist, Sam
|
||||
Gladstone, Amir Gonnen, Chitlesh Goorah, Xuan Guo, Neil Hamilton, Jannis
|
||||
Harder, Junji Hashimoto, Thomas Hawkins, Robert Henry, David Hewson, Jamey
|
||||
Hicks, Hiroki Honda, Alex Hornung, David Horton, Jae Hossell, Alan Hunter,
|
||||
Jamie Iles, Ben Jackson, Shareef Jalloq, Krzysztof Jankowski, HyungKi
|
||||
Jeong, Iztok Jeras, James Johnson, Christophe Joly, Franck Jullien, Mike
|
||||
Kagen, Arthur Kahlich, Kaalia Kahn, Guy-Armand Kamendje, Vasu Kandadi,
|
||||
Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Olof
|
||||
Kindgren, Sobhan Klnv, Gernot Koch, Soon Koh, Steve Kolecki, Brett Koonce,
|
||||
Wojciech Koszek, Varun Koyyalagunta, David Kravitz, Roland Kruse, Sergey
|
||||
Kvachonok, Ed Lander, Steve Lang, Stephane Laurent, Walter Lavino,
|
||||
Christian Leber, Igor Lesik, John Li, Eivind Liland, Charlie Lind, Andrew
|
||||
Ling, Paul Liu, Derek Lockhart, Arthur Low, Stefan Ludwig, Dan Lussier,
|
||||
Fred Ma, Duraid Madina, Mark Marshall, Alfonso Martinez, Yves Mathieu,
|
||||
Patrick Maupin, Jason McMullan, Elliot Mednick, Wim Michiels, Miodrag
|
||||
Milanovic, Wai Sum Mong, Sean Moore, Dennis Muhlestein, John Murphy,
|
||||
Richard Myers, Dimitris Nalbantis, Bob Newgard, Cong Van Nguyen, Paul
|
||||
Nitza, Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, James
|
||||
Pallister, Brad Parker, Maciej Piechotka, David Pierce, Dominic Plunkett,
|
||||
David Poole, Mike Popoloski, Rich Porter, Niranjan Prabhu, Usha
|
||||
Priyadharshini, Mark Jackson Pulver, Prateek Puri, Chris Randall, Anton
|
||||
Rapp, Odd Magne Reitan, Frederic Requin, Alberto Del Rio, Oleg Rodionov,
|
||||
Paul Rolfe, Jan Egil Ruud, John Sanguinetti, Galen Seitz, Salman Sheikh,
|
||||
Hicks, Joel Holdsworth, Hiroki Honda, Alex Hornung, David Horton, Jae
|
||||
Hossell, Alan Hunter, James Hutchinson, Jamie Iles, Ben Jackson, Shareef
|
||||
Jalloq, Krzysztof Jankowski, HyungKi Jeong, Iztok Jeras, James Johnson,
|
||||
Christophe Joly, Franck Jullien, James Jung, Mike Kagen, Arthur Kahlich,
|
||||
Kaalia Kahn, Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf
|
||||
Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Olof Kindgren, Dan Kirkham,
|
||||
Sobhan Klnv, Gernot Koch, Soon Koh, Steve Kolecki, Brett Koonce, Wojciech
|
||||
Koszek, Varun Koyyalagunta, David Kravitz, Roland Kruse, Sergey Kvachonok,
|
||||
Ed Lander, Steve Lang, Stephane Laurent, Walter Lavino, Christian Leber,
|
||||
Igor Lesik, John Li, Eivind Liland, Charlie Lind, Andrew Ling, Paul Liu,
|
||||
Derek Lockhart, Arthur Low, Stefan Ludwig, Dan Lussier, Fred Ma, Duraid
|
||||
Madina, Mark Marshall, Alfonso Martinez, Yves Mathieu, Patrick Maupin,
|
||||
Jason McMullan, Elliot Mednick, Wim Michiels, Miodrag Milanovic, Wai Sum
|
||||
Mong, Sean Moore, Dennis Muhlestein, John Murphy, Richard Myers, Dimitris
|
||||
Nalbantis, Bob Newgard, Cong Van Nguyen, Paul Nitza, Pete Nixon, Lisa
|
||||
Noack, Mark Nodine, Andreas Olofsson, James Pallister, Brad Parker, Maciej
|
||||
Piechotka, David Pierce, Dominic Plunkett, David Poole, Mike Popoloski,
|
||||
Rich Porter, Niranjan Prabhu, Usha Priyadharshini, Mark Jackson Pulver,
|
||||
Prateek Puri, Chris Randall, Anton Rapp, Josh Redford, Odd Magne Reitan,
|
||||
Frederic Requin, Alberto Del Rio, Oleg Rodionov, Paul Rolfe, Arjen
|
||||
Roodselaar, Jan Egil Ruud, John Sanguinetti, Galen Seitz, Salman Sheikh,
|
||||
Mike Shinkarovsky, Rafael Shirakawa, Jeffrey Short, Rodney Sinclair, Steven
|
||||
Slatter, Brian Small, Alex Solomatnikov, Wei Song, Art Stamness, John
|
||||
Stevenson, Rob Stoddard, Todd Strader, John Stroebel, Sven Stucki, Emerson
|
||||
Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu Takatsukasa, Peter
|
||||
Tengstrand, Wesley Terpstra, Stefan Thiede, Gary Thomas, Kevin Thompson,
|
||||
Ian Thompson, Mike Thyer, Hans Tichelaar, Steve Tong, Michael Tresidder,
|
||||
Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters, Thomas
|
||||
Watts, Eugene Weber, David Welch, Thomas J Whatson, Leon Wildman, Gerald
|
||||
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Clifford Wolf, Johan
|
||||
Wouters, Ding Xiaoliang, Jie Xu, Mandy Xu, Luke Yang, and Amir
|
||||
Yazdanbakhsh.
|
||||
Stevenson, Patrick Stewart, Rob Stoddard, Todd Strader, John Stroebel, Sven
|
||||
Stucki, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu
|
||||
Takatsukasa, Peter Tengstrand, Wesley Terpstra, Rui Terra, Stefan Thiede,
|
||||
Gary Thomas, Kevin Thompson, Ian Thompson, Mike Thyer, Hans Tichelaar,
|
||||
Steve Tong, Michael Tresidder, Holger Waechtler, Stefan Wallentowitz, Shawn
|
||||
Wang, Greg Waters, Thomas Watts, Eugene Weber, David Welch, Thomas J
|
||||
Whatson, Leon Wildman, Gerald Williams, Trevor Williams, Jeff Winston,
|
||||
Joshua Wise, Clifford Wolf, Johan Wouters, Junyi Xi, Ding Xiaoliang, Jie
|
||||
Xu, Mandy Xu, Luke Yang, and Amir Yazdanbakhsh.
|
||||
|
||||
Thanks to them, and all those we've missed including above.
|
||||
|
||||
@@ -4163,7 +4229,7 @@ Thanks to them, and all those we've missed including above.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2003-2018 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify the Verilator internals under the terms of
|
||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||
License Version 2.0.
|
||||
|
||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -271,7 +271,7 @@ Specifies a module search directory.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2003-2018 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify the Verilator internals under the terms of
|
||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||
License Version 2.0.
|
||||
|
||||
@@ -85,7 +85,8 @@ sub diff_dir {
|
||||
diff_file($a,$b);
|
||||
$any = 1;
|
||||
}
|
||||
$any or warn "%Warning: No .tree files found\n";
|
||||
$any or warn ("%Warning: No .tree files found that have similar base names:\n "
|
||||
.join("\n ", sort keys %files),"\n");
|
||||
}
|
||||
|
||||
sub diff_file {
|
||||
@@ -235,7 +236,7 @@ Do not show differences in line numbering.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. This package is free software; you can
|
||||
Copyright 2005-2018 by Wilson Snyder. This package is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
# DESCRIPTION: Print include statements for each ARGV
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This package is free software; you can
|
||||
# Copyright 2003-2018 by Wilson Snyder. This package is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
######################################################################
|
||||
|
||||
+12
-4
@@ -73,6 +73,14 @@ sub profcfunc {
|
||||
$funcs{$func}{sec} += $sec;
|
||||
$funcs{$func}{calls} += $calls;
|
||||
}
|
||||
# Older gprofs have no call column for single-call functions
|
||||
# %time cumesec selfsec {stuff} name
|
||||
elsif ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
|
||||
my $pct=$1; my $sec=$2; my $calls=1; my $func=$3;
|
||||
$funcs{$func}{pct} += $pct;
|
||||
$funcs{$func}{sec} += $sec;
|
||||
$funcs{$func}{calls} += $calls;
|
||||
}
|
||||
}
|
||||
$fh->close;
|
||||
|
||||
@@ -191,11 +199,11 @@ __END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
verilator_profcfunc - Read gprof report created with --profile-cfuncs
|
||||
verilator_profcfunc - Read gprof report created with --prof-cfuncs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
verilator --profile-cfuncs ....
|
||||
verilator --prof-cfuncs ....
|
||||
gcc --ggdb -pg ....
|
||||
{run executable}
|
||||
gprof
|
||||
@@ -205,7 +213,7 @@ verilator_profcfunc - Read gprof report created with --profile-cfuncs
|
||||
|
||||
Verilator_profcfunc reads a profile report created by gprof. The names of
|
||||
the functions are then transformed, assuming the user used verilator's
|
||||
--profile-cfuncs, and a report printed showing the percentage of time, etc,
|
||||
--prof-cfuncs, and a report printed showing the percentage of time, etc,
|
||||
in each Verilog block.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
@@ -222,7 +230,7 @@ Displays this message and program version and exits.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2007-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2007-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+48
-2
@@ -1,12 +1,13 @@
|
||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
# Copyright 2003-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.916 2017-11-25])
|
||||
AC_INIT([Verilator],[3.926 2018-08-22],[https://www.veripool.org/verilator],
|
||||
[verilator],[https://www.veripool.org/verilator])
|
||||
# When releasing, also update header of Changes file
|
||||
# and commit using "devel release" or "Version bump" message
|
||||
|
||||
@@ -15,6 +16,14 @@ AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk incl
|
||||
|
||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
|
||||
# Ignore automake flags passed by Ubuntu builds
|
||||
AC_ARG_ENABLE([dependency-tracking],
|
||||
[AS_HELP_STRING([--disable-dependency-tracking], [ignored])])
|
||||
AC_ARG_ENABLE([maintainer-mode],
|
||||
[AS_HELP_STRING([--enable-maintainer-mode], [ignored])])
|
||||
AC_ARG_ENABLE([silent-rules],
|
||||
[AS_HELP_STRING([--disable-silent-rules], [ignored])])
|
||||
|
||||
# Special Substitutions - CFG_WITH_DEFENV
|
||||
AC_MSG_CHECKING(whether to use hardcoded paths)
|
||||
AC_ARG_ENABLE([defenv],
|
||||
@@ -65,6 +74,21 @@ AC_ARG_ENABLE([longtests],
|
||||
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||
|
||||
# CFG_WITH_PREC11
|
||||
AC_MSG_CHECKING(whether allow pre-C++11)
|
||||
AC_ARG_ENABLE([prec11],
|
||||
[AS_HELP_STRING([--enable-prec11],
|
||||
[enable pre-C++11 compilers])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_PREC11=yes ;;
|
||||
no) CFG_WITH_PREC11=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-prec11]) ;;
|
||||
esac],
|
||||
[CFG_WITH_PREC11=no;]
|
||||
)
|
||||
AC_SUBST(CFG_WITH_PREC11)
|
||||
AC_MSG_RESULT($CFG_WITH_PREC11)
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS=-I${includedir}
|
||||
CPPFLAGS=-I${includedir}
|
||||
@@ -77,6 +101,8 @@ AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
cxx_version=$($CXX --version | head -1)
|
||||
AC_MSG_RESULT([compiler is $CXX --version = $cxx_version])
|
||||
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([int main() { return 0; }])],
|
||||
@@ -167,9 +193,11 @@ AC_DEFUN([_MY_CXX_CHECK_OPT],
|
||||
# Macros work such that first option that passes is the one we take
|
||||
# gnu++14 is the newest that Verilator supports
|
||||
# std++03 is the oldest that Verilator supports
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++17)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++17)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++03)
|
||||
@@ -179,6 +207,7 @@ AC_SUBST(CFG_CXXFLAGS_STD_NEWEST)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++17)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++14)
|
||||
@@ -218,6 +247,7 @@ AC_SUBST(CFG_CXXFLAGS_PARSER)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-faligned-new)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-fbracket-depth=4096)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Qunused-arguments)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-bool-operation)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-parentheses-equality)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-sign-compare)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
|
||||
@@ -244,6 +274,22 @@ CFG_WITH_THREADED=$_my_result
|
||||
AC_SUBST(CFG_WITH_THREADED)
|
||||
AC_MSG_RESULT($CFG_WITH_THREADED)
|
||||
|
||||
# Check compiler flag
|
||||
if test "$CFG_WITH_THREADED" = "no" ; then
|
||||
if test "$CFG_WITH_PREC11" = "no" ; then
|
||||
AC_MSG_NOTICE([[]])
|
||||
AC_MSG_ERROR([[the $CXX compiler appears to not support C++11.
|
||||
|
||||
Verilator plans to require a C++11 or newer compiler in a future release,
|
||||
unless sufficient people report problems. Therefore, if you do not have a
|
||||
C++11 compiler, please post a message to
|
||||
https://www.veripool.org/boards/3/topics/2580-Verilator-Requiring-C-11-compiler
|
||||
indicating your OS and when you think C++11 might be ok, and then rerun
|
||||
configure with the --enable-prec11 argument. Thanks.]])
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_MEMBER([struct stat.st_mtim.tv_nsec],
|
||||
[AC_DEFINE([HAVE_STAT_NSEC],[1],[Defined if struct stat has st_mtim.tv_nsec])],
|
||||
|
||||
+1
-5
@@ -630,12 +630,8 @@ WARN_LOGFILE =
|
||||
# with spaces.
|
||||
|
||||
INPUT = doxygen-mainpage \
|
||||
include \
|
||||
include \
|
||||
src \
|
||||
test_c \
|
||||
test_regress \
|
||||
test_sc \
|
||||
test_v
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -23,7 +23,7 @@ endif
|
||||
# real project, it is better to start with a more complete example,
|
||||
# e.g. examples/tracing_c.
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -23,7 +23,7 @@ endif
|
||||
# real project, it is better to start with a more complete example,
|
||||
# e.g. examples/tracing_sc.
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -20,7 +20,7 @@ endif
|
||||
######################################################################
|
||||
# Set up variables
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# This is executed in the object directory, and called by ../Makefile
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -17,6 +17,9 @@ default: Vtop
|
||||
# Include the rules made by Verilator
|
||||
include Vtop.mk
|
||||
|
||||
# Use OBJCACHE (ccache) if using gmake and its installed
|
||||
COMPILE.cc = $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
|
||||
|
||||
#######################################################################
|
||||
# Compile flags
|
||||
|
||||
|
||||
@@ -90,6 +90,11 @@ int main(int argc, char** argv, char** env) {
|
||||
// Evaluate model
|
||||
top->eval();
|
||||
|
||||
#if VM_TRACE
|
||||
// Dump trace data for this cycle
|
||||
if (tfp) tfp->dump (main_time);
|
||||
#endif
|
||||
|
||||
// Read outputs
|
||||
VL_PRINTF ("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
|
||||
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
|
||||
@@ -102,7 +107,7 @@ int main(int argc, char** argv, char** env) {
|
||||
|
||||
// Close trace if opened
|
||||
#if VM_TRACE
|
||||
if (tfp) { tfp->close(); }
|
||||
if (tfp) { tfp->close(); tfp = NULL; }
|
||||
#endif
|
||||
|
||||
// Coverage analysis (since test passed)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -20,7 +20,7 @@ endif
|
||||
######################################################################
|
||||
# Set up variables
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# If $VERILATOR_ROOT isn't in the environment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# This is executed in the object directory, and called by ../Makefile
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
@@ -17,6 +17,9 @@ default: Vtop
|
||||
# Include the rules made by Verilator
|
||||
include Vtop.mk
|
||||
|
||||
# Use OBJCACHE (ccache) if using gmake and its installed
|
||||
COMPILE.cc = $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
|
||||
|
||||
#######################################################################
|
||||
# Compile flags
|
||||
|
||||
|
||||
@@ -94,10 +94,10 @@ int sc_main(int argc, char* argv[]) {
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0==strcmp(flag, "+trace")) {
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
VerilatedVcdSc* tfp = new VerilatedVcdSc;
|
||||
top->trace (tfp, 99);
|
||||
tfp = new VerilatedVcdSc;
|
||||
top->trace(tfp, 99);
|
||||
mkdir("logs", 0777);
|
||||
tfp->open ("logs/vlt_dump.vcd");
|
||||
tfp->open("logs/vlt_dump.vcd");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -107,13 +107,15 @@ int sc_main(int argc, char* argv[]) {
|
||||
// Flush the wave files each cycle so we can immediately see the output
|
||||
// Don't do this in "real" programs, do it in an abort() handler instead
|
||||
if (tfp) tfp->flush();
|
||||
#endif
|
||||
|
||||
// Apply inputs
|
||||
if (VL_TIME_Q() > 1 && VL_TIME_Q() < 10) {
|
||||
reset_l = !1; // Assert reset
|
||||
} else if (VL_TIME_Q() > 1) {
|
||||
reset_l = !0; // Deassert reset
|
||||
}
|
||||
#endif
|
||||
|
||||
// Simulate 1ns
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
@@ -122,20 +124,23 @@ int sc_main(int argc, char* argv[]) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close Waves
|
||||
#if VM_TRACE
|
||||
if (tfp) tfp->close();
|
||||
#endif
|
||||
|
||||
// Final model cleanup
|
||||
top->final();
|
||||
|
||||
// Close trace if opened
|
||||
#if VM_TRACE
|
||||
if (tfp) { tfp->close(); tfp = NULL; }
|
||||
#endif
|
||||
|
||||
// Coverage analysis (since test passed)
|
||||
#if VM_COVERAGE
|
||||
mkdir("logs", 0777);
|
||||
VerilatedCov::write("logs/coverage.dat");
|
||||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top; top = NULL;
|
||||
|
||||
// Fin
|
||||
return 0;
|
||||
}
|
||||
|
||||
+323
-62
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -40,9 +40,9 @@ VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||
Verilated::Serialized Verilated::s_s;
|
||||
VL_THREAD_LOCAL Verilated::ThreadLocal Verilated::t_s;
|
||||
|
||||
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
|
||||
Verilated::CommandArgValues Verilated::s_args;
|
||||
|
||||
VerilatedImp VerilatedImp::s_s;
|
||||
VerilatedImp VerilatedImp::s_s;
|
||||
|
||||
//===========================================================================
|
||||
// User definable functions
|
||||
@@ -122,10 +122,16 @@ std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
|
||||
va_list aq;
|
||||
va_copy(aq, ap);
|
||||
int len = VL_VSNPRINTF(NULL, 0, formatp, aq);
|
||||
if (VL_UNLIKELY(len < 1)) return "";
|
||||
va_end(aq);
|
||||
if (VL_UNLIKELY(len < 1)) {
|
||||
va_end(ap);
|
||||
return "";
|
||||
}
|
||||
|
||||
char* bufp = new char[len+1];
|
||||
VL_VSNPRINTF(bufp, len+1, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
std::string out = std::string(bufp, len);
|
||||
delete[] bufp;
|
||||
return out;
|
||||
@@ -159,7 +165,11 @@ void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
|
||||
std::string out = _vl_string_vprintf(formatp, ap);
|
||||
va_end(ap);
|
||||
// printf("-imm-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
|
||||
VL_PRINTF_MT("-V{t%d,%" VL_PRI64 "d}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
|
||||
|
||||
// Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF
|
||||
// from within the guts of the thread execution machinery (and it goes
|
||||
// to the screen and not into the queues we're debugging)
|
||||
VL_PRINTF("-V{t%d,%" VL_PRI64 "u}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), out.c_str());
|
||||
}
|
||||
|
||||
#ifdef VL_THREADED
|
||||
@@ -198,7 +208,7 @@ IData VL_RAND32() VL_MT_SAFE {
|
||||
t_seeded = true;
|
||||
long seedval;
|
||||
{
|
||||
VerilatedLockGuard guard(s_mutex);
|
||||
VerilatedLockGuard lock(s_mutex);
|
||||
seedval = lrand48()<<16 ^ lrand48();
|
||||
if (!seedval) seedval++;
|
||||
}
|
||||
@@ -430,7 +440,8 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) VL_MT_SAFE {
|
||||
return out;
|
||||
}
|
||||
|
||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
|
||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
|
||||
bool lsign, bool rsign) VL_MT_SAFE {
|
||||
// obits==lbits, rbits can be different
|
||||
if (rsign && VL_SIGN_W(rbits, rwp)) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
@@ -450,7 +461,9 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W
|
||||
}
|
||||
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
|
||||
}
|
||||
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
|
||||
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, QData rhs,
|
||||
bool lsign, bool rsign) VL_MT_SAFE {
|
||||
WData rhsw[2]; VL_SET_WQ(rhsw, rhs);
|
||||
return VL_POWSS_WWW(obits,lbits,rbits,owp,lwp,rhsw,lsign,rsign);
|
||||
}
|
||||
@@ -471,6 +484,45 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig
|
||||
//===========================================================================
|
||||
// Formatting
|
||||
|
||||
/// Output a string representation of a wide number
|
||||
std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
|
||||
int maxdecwidth = (width+3)*4/3;
|
||||
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
|
||||
WData bcd[VL_VALUE_STRING_MAX_WIDTH/4+2];
|
||||
VL_ZERO_RESET_W(maxdecwidth, bcd);
|
||||
WData tmp[VL_VALUE_STRING_MAX_WIDTH/4+2];
|
||||
WData tmp2[VL_VALUE_STRING_MAX_WIDTH/4+2];
|
||||
int from_bit = width-1;
|
||||
// Skip all leading zeros
|
||||
for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit);
|
||||
// Double-dabble algorithm
|
||||
for (; from_bit >= 0; --from_bit) {
|
||||
// Any digits >= 5 need an add 3 (via tmp)
|
||||
for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit+=4) {
|
||||
if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
|
||||
VL_ZERO_RESET_W(maxdecwidth, tmp2);
|
||||
tmp2[VL_BITWORD_I(nibble_bit)] |= 0x3 << VL_BITBIT_I(nibble_bit);
|
||||
VL_ASSIGN_W(maxdecwidth, tmp, bcd);
|
||||
VL_ADD_W(VL_WORDS_I(maxdecwidth), bcd, tmp, tmp2);
|
||||
}
|
||||
}
|
||||
// Shift; bcd = bcd << 1
|
||||
VL_ASSIGN_W(maxdecwidth, tmp, bcd);
|
||||
VL_SHIFTL_WWI(maxdecwidth, maxdecwidth, 32, bcd, tmp, 1);
|
||||
// bcd[0] = lwp[from_bit]
|
||||
if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
|
||||
}
|
||||
std::string output;
|
||||
int lsb = (maxdecwidth-1) & ~3;
|
||||
for (; lsb>0; lsb-=4) { // Skip leading zeros
|
||||
if (VL_BITRSHIFT_W(bcd, lsb) & 0xf) break;
|
||||
}
|
||||
for (; lsb>=0; lsb-=4) {
|
||||
output += ('0' + (VL_BITRSHIFT_W(bcd, lsb) & 0xf)); // 0..9
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Do a va_arg returning a quad, assuming input argument is anything less than wide
|
||||
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
|
||||
|
||||
@@ -559,7 +611,6 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
} else {
|
||||
lwp = va_arg(ap,WDataInP);
|
||||
ld = lwp[0];
|
||||
if (fmt == 'd' || fmt == '#') fmt = 'x'; // Not supported, but show something
|
||||
}
|
||||
int lsb=lbits-1;
|
||||
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) --lsb;
|
||||
@@ -572,13 +623,27 @@ 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 = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
|
||||
output += (charval==0)?' ':charval;
|
||||
}
|
||||
break;
|
||||
case 'd': { // Signed decimal
|
||||
int digits = sprintf(tmp,"%" VL_PRI64 "d",
|
||||
int digits;
|
||||
std::string append;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
digits = sprintf(tmp,"%" VL_PRI64 "d",
|
||||
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
append = tmp;
|
||||
} else {
|
||||
if (VL_SIGN_I(lbits, lwp[VL_WORDS_I(lbits)-1])) {
|
||||
WData neg[VL_VALUE_STRING_MAX_WIDTH/4+2];
|
||||
VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp);
|
||||
append = std::string("-") + VL_DECIMAL_NW(lbits, neg);
|
||||
} else {
|
||||
append = VL_DECIMAL_NW(lbits, lwp);
|
||||
}
|
||||
digits = append.length();
|
||||
}
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
@@ -587,11 +652,19 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
output += append;
|
||||
break;
|
||||
}
|
||||
case '#': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
int digits;
|
||||
std::string append;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
digits = sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
append = tmp;
|
||||
} else {
|
||||
append = VL_DECIMAL_NW(lbits, lwp);
|
||||
digits = append.length();
|
||||
}
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
@@ -600,7 +673,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
output += append;
|
||||
break;
|
||||
}
|
||||
case 't': { // Time
|
||||
@@ -621,10 +694,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
}
|
||||
case 'b':
|
||||
for (; lsb>=0; --lsb) {
|
||||
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
||||
output += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'o':
|
||||
for (; lsb>=0; --lsb) {
|
||||
lsb = (lsb / 3) * 3; // Next digit
|
||||
@@ -658,14 +730,14 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
||||
break;
|
||||
case 'v': // Strength; assume always strong
|
||||
for (lsb=lbits-1; lsb>=0; --lsb) {
|
||||
if ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) output += "St1 ";
|
||||
else output += "St0 ";
|
||||
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 = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
||||
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
|
||||
output += "0123456789abcdef"[charval];
|
||||
}
|
||||
break;
|
||||
@@ -701,7 +773,7 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const std:
|
||||
if (fromp == NULL) {
|
||||
return fstr[fstr.length()-1 - (floc>>3)];
|
||||
} else {
|
||||
return (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
|
||||
return VL_BITRSHIFT_W(fromp, floc) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -916,14 +988,15 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) VL_MT_SAFE
|
||||
char* destp = destoutp;
|
||||
for (; lsb>=0; --lsb) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = (sourcep[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||
IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
|
||||
if (!start || charval) {
|
||||
*destp++ = (charval==0)?' ':charval;
|
||||
start = false; // Drop leading 0s
|
||||
}
|
||||
}
|
||||
*destp = '\0'; // Terminate
|
||||
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||
// Drop trailing spaces
|
||||
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0';
|
||||
}
|
||||
|
||||
void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
|
||||
@@ -1142,10 +1215,134 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
|
||||
return got;
|
||||
}
|
||||
|
||||
void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||
QData ofilename, const void* memp, IData start,
|
||||
IData end) VL_MT_SAFE {
|
||||
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||
return VL_WRITEMEM_W(hex, width,depth,array_lsb,2,fnw,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilenamep, const void* memp, IData start,
|
||||
IData end) VL_MT_SAFE {
|
||||
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||
std::string ofilenames(ofilenamez);
|
||||
return VL_WRITEMEM_N(hex, width,depth,array_lsb,ofilenames,memp,start,end);
|
||||
}
|
||||
|
||||
const char* memhFormat(int nBits) {
|
||||
assert((nBits >= 1) && (nBits <= 32));
|
||||
|
||||
static char buf[32];
|
||||
switch ((nBits - 1) / 4) {
|
||||
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
|
||||
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
|
||||
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
|
||||
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
|
||||
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
|
||||
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
|
||||
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
|
||||
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void VL_WRITEMEM_N(
|
||||
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& ofilenamep, // Output file name
|
||||
const void* memp, // Array state
|
||||
IData start, // First array row address to write
|
||||
IData end // Last address to write
|
||||
) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(!hex)) {
|
||||
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
|
||||
"VL_WRITEMEM_N only supports hex format for now, sorry!");
|
||||
return;
|
||||
}
|
||||
FILE* fp = fopen(ofilenamep.c_str(), "w");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
VL_FATAL_MT(ofilenamep.c_str(), 0, "", "$writemem file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int row_addr = start; row_addr <= end; ++row_addr) {
|
||||
if ((row_addr < array_lsb)
|
||||
|| (row_addr > array_lsb + depth - 1)) {
|
||||
vluint32_t endmax = ~0;
|
||||
if (end != endmax) {
|
||||
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
|
||||
"$writemem specified address out-of-bounds");
|
||||
}
|
||||
// else, it's not an error to overflow due to end == endmax,
|
||||
// just return cleanly.
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Compute the offset into the memp array.
|
||||
int row_offset = row_addr - array_lsb;
|
||||
|
||||
if (width <= 8) {
|
||||
const CData* datap
|
||||
= &(reinterpret_cast<const CData*>(memp))[row_offset];
|
||||
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
|
||||
fprintf(fp, "\n");
|
||||
} else if (width <= 16) {
|
||||
const SData* datap
|
||||
= &(reinterpret_cast<const SData*>(memp))[row_offset];
|
||||
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
|
||||
fprintf(fp, "\n");
|
||||
} else if (width <= 32) {
|
||||
const IData* datap
|
||||
= &(reinterpret_cast<const IData*>(memp))[row_offset];
|
||||
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
|
||||
fprintf(fp, "\n");
|
||||
} else if (width <= 64) {
|
||||
const QData* datap
|
||||
= &(reinterpret_cast<const QData*>(memp))[row_offset];
|
||||
vluint64_t value = VL_MASK_Q(width) & *datap;
|
||||
vluint32_t lo = value & 0xffffffff;
|
||||
vluint32_t hi = value >> 32;
|
||||
fprintf(fp, memhFormat(width - 32), hi);
|
||||
fprintf(fp, "%08x\n", lo);
|
||||
} else {
|
||||
WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
|
||||
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)];
|
||||
// output as a sequence of VL_WORDSIZE'd words
|
||||
// from MSB to LSB. Mask off the MSB word which could
|
||||
// contain junk above the top of valid data.
|
||||
int word_idx = ((width - 1) / VL_WORDSIZE);
|
||||
bool first = true;
|
||||
while (word_idx >= 0) {
|
||||
IData data = datap[word_idx];
|
||||
if (first) {
|
||||
data &= VL_MASK_I(width);
|
||||
int top_word_nbits = ((width - 1) & 0x1f) + 1;
|
||||
fprintf(fp, memhFormat(top_word_nbits), data);
|
||||
} else {
|
||||
fprintf(fp, "%08x", data);
|
||||
}
|
||||
|
||||
word_idx--;
|
||||
first = false;
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||
QData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
|
||||
return VL_READMEM_W(hex,width,depth,array_lsb,2,fnw,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
@@ -1153,12 +1350,20 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||
std::string ofilenames(ofilenamez);
|
||||
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
|
||||
return VL_READMEM_N(hex,width,depth,array_lsb,ofilenames,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const std::string& ofilenamep, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
if (fnwords) {}
|
||||
void VL_READMEM_N(
|
||||
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& ofilenamep, // Input file name
|
||||
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(ofilenamep.c_str(), "r");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
// We don't report the Verilog source filename as it slow to have to pass it down
|
||||
@@ -1180,7 +1385,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
while (1) {
|
||||
int c = fgetc(fp);
|
||||
if (VL_UNLIKELY(c==EOF)) break;
|
||||
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
||||
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n",
|
||||
// linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
||||
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
|
||||
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
||||
// Skip // comments and detect /* comments
|
||||
@@ -1208,7 +1414,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
||||
if (VL_UNLIKELY(addr >= static_cast<IData>(depth+array_lsb)
|
||||
|| addr < static_cast<IData>(array_lsb))) {
|
||||
VL_FATAL_MT (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array");
|
||||
VL_FATAL_MT (ofilenamep.c_str(), linenum, "",
|
||||
"$readmem file address beyond bounds of array");
|
||||
} else {
|
||||
int entry = addr - array_lsb;
|
||||
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
|
||||
@@ -1237,7 +1444,8 @@ void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
datap[0] |= value;
|
||||
}
|
||||
if (VL_UNLIKELY(value>=(1<<shift))) {
|
||||
VL_FATAL_MT (ofilenamep.c_str(), linenum, "", "$readmemb (binary) file contains hex characters");
|
||||
VL_FATAL_MT (ofilenamep.c_str(), linenum, "",
|
||||
"$readmemb (binary) file contains hex characters");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1385,7 +1593,7 @@ std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
|
||||
int len = 0;
|
||||
for (; lsb>=0; --lsb) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
|
||||
if (!start || charval) {
|
||||
*destp++ = (charval==0)?' ':charval;
|
||||
len++;
|
||||
@@ -1401,7 +1609,8 @@ std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
|
||||
Verilated::ThreadLocal::ThreadLocal()
|
||||
:
|
||||
#ifdef VL_THREADED
|
||||
t_trainId(0),
|
||||
t_mtaskId(0),
|
||||
t_endOfEvalReqd(0),
|
||||
#endif
|
||||
t_dpiScopep(NULL), t_dpiFilename(0), t_dpiLineno(0) {
|
||||
}
|
||||
@@ -1409,7 +1618,7 @@ Verilated::ThreadLocal::~ThreadLocal() {
|
||||
}
|
||||
|
||||
void Verilated::debug(int val) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_debug = val;
|
||||
if (val) {
|
||||
#ifdef VL_DEBUG
|
||||
@@ -1420,23 +1629,23 @@ void Verilated::debug(int val) VL_MT_SAFE {
|
||||
}
|
||||
}
|
||||
void Verilated::randReset(int val) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_randReset = val;
|
||||
}
|
||||
void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_calcUnusedSigs = flag;
|
||||
}
|
||||
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_gotFinish = flag;
|
||||
}
|
||||
void Verilated::assertOn(bool flag) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_assertOn = flag;
|
||||
}
|
||||
void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_s.s_fatalOnVpiError = flag;
|
||||
}
|
||||
|
||||
@@ -1458,7 +1667,7 @@ const char* Verilated::catName(const char* n1, const char* n2) VL_MT_SAFE {
|
||||
}
|
||||
|
||||
void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (s_flushCb == cb) {} // Ok - don't duplicate
|
||||
else if (!s_flushCb) { s_flushCb=cb; }
|
||||
else {
|
||||
@@ -1468,12 +1677,14 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
|
||||
}
|
||||
|
||||
void Verilated::flushCall() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (s_flushCb) (*s_flushCb)();
|
||||
fflush(stderr);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Verilated::commandArgs(int argc, const char** argv) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
s_args.argc = argc;
|
||||
s_args.argv = argv;
|
||||
VerilatedImp::commandArgs(argc,argv);
|
||||
@@ -1511,16 +1722,6 @@ void Verilated::scopesDump() VL_MT_SAFE {
|
||||
VerilatedImp::scopesDump();
|
||||
}
|
||||
|
||||
void Verilated::numThreads(unsigned threads) VL_MT_SAFE {
|
||||
VerilatedImp::numThreads(threads);
|
||||
}
|
||||
unsigned Verilated::numThreads() VL_MT_SAFE {
|
||||
return VerilatedImp::numThreads();
|
||||
}
|
||||
void Verilated::spawnThreads() VL_MT_SAFE {
|
||||
VerilatedImp::spawnThreads();
|
||||
}
|
||||
|
||||
const VerilatedScope* Verilated::scopeFind(const char* namep) VL_MT_SAFE {
|
||||
return VerilatedImp::scopeFind(namep);
|
||||
}
|
||||
@@ -1534,8 +1735,8 @@ const VerilatedScopeNameMap* Verilated::scopeNameMap() VL_MT_SAFE {
|
||||
}
|
||||
|
||||
#ifdef VL_THREADED
|
||||
void Verilated::endOfThreadTrainGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("End of thread train\n"););
|
||||
void Verilated::endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("End of thread mtask\n"););
|
||||
VerilatedThreadMsgQueue::flush(evalMsgQp);
|
||||
}
|
||||
|
||||
@@ -1545,6 +1746,44 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// VerilatedImp:: Methods
|
||||
|
||||
void VerilatedImp::internalsDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
VL_PRINTF_MT("internalsDump:\n");
|
||||
versionDump();
|
||||
VL_PRINTF_MT(" Argv:");
|
||||
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF_MT(" %s",it->c_str());
|
||||
}
|
||||
VL_PRINTF_MT("\n");
|
||||
scopesDump();
|
||||
exportsDump();
|
||||
userDump();
|
||||
}
|
||||
void VerilatedImp::versionDump() VL_MT_SAFE {
|
||||
VL_PRINTF_MT(" Version: %s %s\n",
|
||||
Verilated::productName(), Verilated::productVersion());
|
||||
}
|
||||
|
||||
void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
s_s.m_argVec.clear(); // Always clear
|
||||
commandArgsAddGuts(argc, argv);
|
||||
}
|
||||
void VerilatedImp::commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
commandArgsAddGuts(argc, argv);
|
||||
}
|
||||
void VerilatedImp::commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex) {
|
||||
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||
for (int i=0; i<argc; ++i) {
|
||||
s_s.m_argVec.push_back(argv[i]);
|
||||
}
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// VerilatedSyms:: Methods
|
||||
|
||||
@@ -1575,7 +1814,7 @@ VerilatedModule::~VerilatedModule() {
|
||||
// VerilatedVar:: Methods
|
||||
|
||||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
vluint32_t VerilatedVar::entSize() const {
|
||||
vluint32_t VerilatedVarProps::entSize() const {
|
||||
vluint32_t size = 1;
|
||||
switch (vltype()) {
|
||||
case VLVT_PTR: size=sizeof(void*); break;
|
||||
@@ -1583,12 +1822,32 @@ vluint32_t VerilatedVar::entSize() const {
|
||||
case VLVT_UINT16: size=sizeof(SData); break;
|
||||
case VLVT_UINT32: size=sizeof(IData); break;
|
||||
case VLVT_UINT64: size=sizeof(QData); break;
|
||||
case VLVT_WDATA: size=VL_WORDS_I(range().elements())*sizeof(IData); break;
|
||||
case VLVT_WDATA: size=VL_WORDS_I(packed().elements())*sizeof(IData); break;
|
||||
default: size=0; break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t VerilatedVarProps::totalSize() const {
|
||||
size_t size = entSize();
|
||||
for (int dim=1; dim<=dims(); ++dim) {
|
||||
size *= m_unpacked[dim].elements();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const {
|
||||
if (VL_UNLIKELY(dim <=0 || dim > m_udims || dim > 3)) return NULL;
|
||||
if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return NULL;
|
||||
int indxAdj = indx - low(dim);
|
||||
vluint8_t* bytep = reinterpret_cast<vluint8_t*>(datap);
|
||||
// If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
|
||||
size_t slicesz = entSize();
|
||||
for (int d=dim+1; d<=m_udims; ++d) slicesz *= elements(d);
|
||||
bytep += indxAdj*slicesz;
|
||||
return bytep;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// VerilatedScope:: Methods
|
||||
|
||||
@@ -1656,15 +1915,17 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||
int msb = va_arg(ap,int);
|
||||
int lsb = va_arg(ap,int);
|
||||
if (i==0) {
|
||||
var.m_range.m_left = msb;
|
||||
var.m_range.m_right = lsb;
|
||||
} else if (i==1) {
|
||||
var.m_array.m_left = msb;
|
||||
var.m_array.m_right = lsb;
|
||||
var.m_packed.m_left = msb;
|
||||
var.m_packed.m_right = lsb;
|
||||
} else if (i>=1 && i<=3) {
|
||||
var.m_unpacked[i-1].m_left = msb;
|
||||
var.m_unpacked[i-1].m_right = lsb;
|
||||
} else {
|
||||
// We could have a linked list of ranges, but really this whole thing needs
|
||||
// to be generalized to support structs and unions, etc.
|
||||
VL_FATAL_MT(__FILE__,__LINE__,"",(std::string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
|
||||
VL_FATAL_MT(__FILE__,__LINE__,"",
|
||||
(std::string("Unsupported multi-dimensional public varInsert: ")
|
||||
+ namep).c_str());
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
@@ -1721,7 +1982,7 @@ void VerilatedScope::scopeDump() const {
|
||||
//===========================================================================
|
||||
// VerilatedOneThreaded:: Methods
|
||||
|
||||
#ifdef VL_THREADED
|
||||
#if defined(VL_THREADED) && defined(VL_DEBUG)
|
||||
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Routine called that is single threaded, but called from"
|
||||
" a different thread then the expected constructing thread");
|
||||
|
||||
+203
-107
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -99,7 +99,8 @@ enum VerilatedVarFlags {
|
||||
VLVF_MASK_DIR=7, // Bit mask for above directions
|
||||
// Flags
|
||||
VLVF_PUB_RD=(1<<8), // Public readable
|
||||
VLVF_PUB_RW=(1<<9) // Public writable
|
||||
VLVF_PUB_RW=(1<<9), // Public writable
|
||||
VLVF_DPI_CLAY=(1<<10) // DPI compatible C standard layout
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
@@ -110,6 +111,8 @@ extern vluint32_t VL_THREAD_ID() VL_MT_SAFE;
|
||||
|
||||
#if VL_THREADED
|
||||
|
||||
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before relaxing
|
||||
|
||||
/// Mutex, wrapped to allow -fthread_safety checks
|
||||
class VL_CAPABILITY("mutex") VerilatedMutex {
|
||||
private:
|
||||
@@ -118,9 +121,19 @@ class VL_CAPABILITY("mutex") VerilatedMutex {
|
||||
VerilatedMutex() {}
|
||||
~VerilatedMutex() {}
|
||||
/// Acquire/lock mutex
|
||||
void lock() VL_ACQUIRE() { m_mutex.lock(); }
|
||||
void lock() VL_ACQUIRE() {
|
||||
// Try to acquire the lock by spinning. If the wait is short,
|
||||
// avoids a trap to the OS plus OS scheduler overhead.
|
||||
if (VL_LIKELY(try_lock())) return; // Short circuit loop
|
||||
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
|
||||
if (VL_LIKELY(try_lock())) return;
|
||||
VL_CPU_RELAX();
|
||||
}
|
||||
// Spinning hasn't worked, pay the cost of blocking.
|
||||
m_mutex.lock();
|
||||
}
|
||||
/// Release/unlock mutex
|
||||
void unlock() VL_RELEASE() { m_mutex.unlock(); }
|
||||
void unlock() VL_RELEASE() { m_mutex.unlock(); }
|
||||
/// Try to acquire mutex. Returns true on success, and false on failure.
|
||||
bool try_lock() VL_TRY_ACQUIRE(true) { return m_mutex.try_lock(); }
|
||||
};
|
||||
@@ -142,14 +155,21 @@ class VL_SCOPED_CAPABILITY VerilatedLockGuard {
|
||||
|
||||
#else // !VL_THREADED
|
||||
|
||||
// Empty classes to avoid #ifdefs everywhere
|
||||
class VerilatedMutex {};
|
||||
/// Empty non-threaded mutex to avoid #ifdefs in consuming code
|
||||
class VerilatedMutex {
|
||||
public:
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
/// Empty non-threaded lock guard to avoid #ifdefs in consuming code
|
||||
class VerilatedLockGuard {
|
||||
VL_UNCOPYABLE(VerilatedLockGuard);
|
||||
public:
|
||||
explicit VerilatedLockGuard(VerilatedMutex&) {}
|
||||
~VerilatedLockGuard() {}
|
||||
};
|
||||
|
||||
#endif // VL_THREADED
|
||||
|
||||
/// Remember the calling thread at construction time, and make sure later calls use same thread
|
||||
@@ -166,9 +186,7 @@ public:
|
||||
// METHODS
|
||||
/// Check that the current thread ID is the same as the construction thread ID
|
||||
void check() VL_MT_UNSAFE_ONE {
|
||||
// Memoize results in local thread, to prevent slow get_id() call
|
||||
VL_THREAD_LOCAL bool t_okThread = (m_threadid == VL_THREAD_ID());
|
||||
if (!VL_LIKELY(t_okThread)) {
|
||||
if (!VL_LIKELY(m_threadid == VL_THREAD_ID())) {
|
||||
fatal_different();
|
||||
}
|
||||
}
|
||||
@@ -309,20 +327,21 @@ public: // But internals only - called from VerilatedModule's
|
||||
class Verilated {
|
||||
// MEMBERS
|
||||
// Slow path variables
|
||||
static VerilatedMutex m_mutex; ///< Mutex for all static members, when VL_THREADED
|
||||
static VerilatedMutex m_mutex; ///< Mutex for s_s/s_ns members, when VL_THREADED
|
||||
|
||||
static VerilatedVoidCb s_flushCb; ///< Flush callback function
|
||||
|
||||
static struct Serialized { // All these members serialized/deserialized
|
||||
// Slow path
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
// 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
|
||||
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
|
||||
Serialized();
|
||||
// Slow path
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
Serialized();
|
||||
~Serialized() {}
|
||||
} s_s;
|
||||
|
||||
// no need to be save-restored (serialized) the
|
||||
@@ -330,12 +349,14 @@ class Verilated {
|
||||
static struct CommandArgValues {
|
||||
int argc;
|
||||
const char** argv;
|
||||
CommandArgValues() : argc(0), argv(NULL) {}
|
||||
~CommandArgValues() {}
|
||||
} s_args;
|
||||
|
||||
// Not covered by mutex, as per-thread
|
||||
static VL_THREAD_LOCAL struct ThreadLocal {
|
||||
#ifdef VL_THREADED
|
||||
vluint32_t t_trainId; ///< Current train# executing on this thread
|
||||
vluint32_t t_mtaskId; ///< Current mtask# executing on this thread
|
||||
vluint32_t t_endOfEvalReqd; ///< Messages may be pending, thread needs endOf-eval calls
|
||||
#endif
|
||||
const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
@@ -372,7 +393,8 @@ public:
|
||||
#endif
|
||||
/// Enable calculation of unused signals
|
||||
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
|
||||
static bool calcUnusedSigs() VL_MT_SAFE { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
static bool calcUnusedSigs() VL_MT_SAFE { ///< Return calcUnusedSigs value
|
||||
return s_s.s_calcUnusedSigs; }
|
||||
/// Did the simulation $finish?
|
||||
static void gotFinish(bool flag) VL_MT_SAFE;
|
||||
static bool gotFinish() VL_MT_SAFE { return s_s.s_gotFinish; } ///< Return if got a $finish
|
||||
@@ -392,7 +414,8 @@ public:
|
||||
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv) VL_MT_SAFE;
|
||||
static void commandArgs(int argc, char** argv) VL_MT_SAFE { commandArgs(argc, const_cast<const char**>(argv)); }
|
||||
static void commandArgs(int argc, char** argv) VL_MT_SAFE {
|
||||
commandArgs(argc, const_cast<const char**>(argv)); }
|
||||
static void commandArgsAdd(int argc, const char** argv);
|
||||
static CommandArgValues* getCommandArgs() VL_MT_SAFE { return &s_args; }
|
||||
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
|
||||
@@ -416,17 +439,6 @@ public:
|
||||
/// releases - contact the authors before production use.
|
||||
static void scopesDump() VL_MT_SAFE;
|
||||
|
||||
/// Set the number of threads to execute on.
|
||||
/// 0x0 = use all available CPU threads, or 1 if no support compiled in
|
||||
/// Ignored after spawnThreads() has been called
|
||||
static void numThreads(unsigned threads) VL_MT_SAFE;
|
||||
static unsigned numThreads() VL_MT_SAFE;
|
||||
/// Spawn child threads, using numThreads() as # of threads
|
||||
/// Verilator calls this automatically on the first eval() call
|
||||
/// User code may call it earlier if desired
|
||||
/// Once called the first time, later calls are ignored
|
||||
static void spawnThreads() VL_MT_SAFE;
|
||||
|
||||
public:
|
||||
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
|
||||
// Internal: Create a new module name by concatenating two strings
|
||||
@@ -453,22 +465,29 @@ public:
|
||||
static size_t serializedSize() VL_PURE { return sizeof(s_s); }
|
||||
static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
|
||||
#ifdef VL_THREADED
|
||||
/// Set the trainId, called when a train starts
|
||||
static void trainId(vluint32_t id) VL_MT_SAFE { t_s.t_trainId = id; }
|
||||
static vluint32_t trainId() VL_MT_SAFE { return t_s.t_trainId; }
|
||||
/// Set the mtaskId, called when an mtask starts
|
||||
static void mtaskId(vluint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
|
||||
static vluint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; }
|
||||
static void endOfEvalReqdInc() VL_MT_SAFE { ++t_s.t_endOfEvalReqd; }
|
||||
static void endOfEvalReqdDec() VL_MT_SAFE { --t_s.t_endOfEvalReqd; }
|
||||
/// Called at end of each thread train, before finishing eval
|
||||
static void endOfThreadTrain(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) { endOfThreadTrainGuts(evalMsgQp); } }
|
||||
|
||||
/// Called at end of each thread mtask, before finishing eval
|
||||
static void endOfThreadMTask(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) { endOfThreadMTaskGuts(evalMsgQp); }
|
||||
}
|
||||
/// Called at end of eval loop
|
||||
static void endOfEval(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) { endOfEvalGuts(evalMsgQp); } }
|
||||
// It doesn't work to set endOfEvalReqd on the threadpool thread
|
||||
// and then check it on the eval thread since it's thread local.
|
||||
// It should be ok to call into endOfEvalGuts, it returns immediately
|
||||
// if there are no transactions.
|
||||
endOfEvalGuts(evalMsgQp);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef VL_THREADED
|
||||
static void endOfThreadTrainGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
|
||||
static void endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
|
||||
static void endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
|
||||
#endif
|
||||
};
|
||||
@@ -525,6 +544,11 @@ 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
|
||||
inline QData VL_RDTSC_Q() { vluint64_t val; VL_RDTSC(val); return val; }
|
||||
#endif
|
||||
|
||||
/// Math
|
||||
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
|
||||
|
||||
@@ -534,8 +558,8 @@ extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
|
||||
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) VL_MT_SAFE { return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) VL_MT_SAFE {
|
||||
return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
@@ -547,6 +571,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
IData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||
|
||||
extern void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilename, const void* memp, IData start, IData end);
|
||||
extern void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
QData ofilename, const void* memp, IData start, IData end);
|
||||
inline void VL_WRITEMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
IData ofilename, const void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
VL_WRITEMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||
|
||||
extern void VL_WRITEF(const char* formatp, ...);
|
||||
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||
|
||||
@@ -575,13 +607,20 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
|
||||
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
#define VL_BITISSETLIMIT_W(data,width,bit) \
|
||||
(((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
|
||||
/// Shift appropriate word by bit. Does not account for wrapping between two words
|
||||
#define VL_BITRSHIFT_W(data,bit) (data[VL_BITWORD_I(bit)] >> VL_BITBIT_I(bit))
|
||||
|
||||
/// Create two 32-bit words from quadword
|
||||
/// WData is always at least 2 words; does not clean upper bits
|
||||
#define VL_SET_WQ(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
|
||||
#define VL_SET_WQ(owp,data) { owp[0]=static_cast<IData>(data); \
|
||||
owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
|
||||
#define VL_SET_WI(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=0; }
|
||||
#define VL_SET_QW(lwp) ( (static_cast<QData>(lwp[0])) | (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
|
||||
#define VL_SET_QW(lwp) \
|
||||
( (static_cast<QData>(lwp[0])) \
|
||||
| (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
|
||||
#define _VL_SET_QII(ld,rd) ( (static_cast<QData>(ld)<<VL_ULL(32)) | static_cast<QData>(rd) )
|
||||
|
||||
/// Return FILE* from IData
|
||||
@@ -589,19 +628,26 @@ extern FILE* VL_CVT_I_FP(IData lhs);
|
||||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return void* from QData
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) VL_PURE {
|
||||
union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
static inline QData VL_CVT_VP_Q(void* fp) VL_PURE {
|
||||
union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return double from QData (bits, not numerically)
|
||||
static inline double VL_CVT_D_Q(QData lhs) VL_PURE { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
static inline double VL_CVT_D_Q(QData lhs) VL_PURE {
|
||||
union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
/// Return QData from double (bits, not numerically)
|
||||
static inline QData VL_CVT_Q_D(double lhs) VL_PURE { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
static inline QData VL_CVT_Q_D(double lhs) VL_PURE {
|
||||
union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) VL_PURE { return static_cast<double>(static_cast<vlsint32_t>(lhs)); }
|
||||
static inline double VL_ITOR_D_I(IData lhs) VL_PURE {
|
||||
return static_cast<double>(static_cast<vlsint32_t>(lhs)); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) VL_PURE { return static_cast<vlsint32_t>(VL_TRUNC(lhs)); }
|
||||
static inline IData VL_RTOI_I_D(double lhs) VL_PURE {
|
||||
return static_cast<vlsint32_t>(VL_TRUNC(lhs)); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE {
|
||||
return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
|
||||
|
||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||
// (Requires clean input)
|
||||
@@ -612,8 +658,10 @@ static inline IData VL_RTOIROUND_I_D(double lhs) VL_PURE { return static_cast<v
|
||||
|
||||
// Sign bit extended up to MSB, doesn't include unsigned portion
|
||||
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
|
||||
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
||||
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
|
||||
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) VL_PURE {
|
||||
return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
||||
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) VL_PURE {
|
||||
return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
|
||||
|
||||
// Debugging prints
|
||||
extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
@@ -1223,7 +1271,7 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
||||
static inline IData VL_NEGATE_I(IData data) VL_PURE { return -data; }
|
||||
static inline QData VL_NEGATE_Q(QData data) VL_PURE { return -data; }
|
||||
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE {
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; ++i) {
|
||||
carry = carry + static_cast<QData>(static_cast<IData>(~lwp[i]));
|
||||
@@ -1396,13 +1444,19 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDa
|
||||
WDataOutP VL_POW_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs);
|
||||
QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp);
|
||||
|
||||
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
|
||||
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
|
||||
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
|
||||
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||
#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
|
||||
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||
#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) \
|
||||
VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign)
|
||||
#define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) \
|
||||
VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign)
|
||||
#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) \
|
||||
VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign)
|
||||
|
||||
static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) VL_MT_SAFE {
|
||||
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"
|
||||
@@ -1415,7 +1469,8 @@ static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs
|
||||
}
|
||||
return VL_POW_III(obits, rbits, rbits, lhs, rhs);
|
||||
}
|
||||
static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
|
||||
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"
|
||||
@@ -1428,9 +1483,12 @@ static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs
|
||||
}
|
||||
return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs);
|
||||
}
|
||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
|
||||
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
|
||||
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign);
|
||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign);
|
||||
WDataOutP VL_POWSS_WWQ(int obits, int, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign);
|
||||
QData VL_POWSS_QQW(int obits, int, int rbits,
|
||||
QData lhs, WDataInP rwp, bool lsign, bool rsign);
|
||||
|
||||
//===================================================================
|
||||
// Concat/replication
|
||||
@@ -1550,21 +1608,24 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) V
|
||||
}
|
||||
return (returndata);
|
||||
}
|
||||
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int, WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_REPLICATE_WII(int obits, int lbits, int,
|
||||
WDataOutP owp, IData ld, IData rep) VL_MT_SAFE {
|
||||
owp[0] = ld;
|
||||
for (unsigned i=1; i < rep; ++i){
|
||||
_VL_INSERT_WI(obits,owp,ld,i*lbits+lbits-1,i*lbits);
|
||||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int, WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_REPLICATE_WQI(int obits, int lbits, int,
|
||||
WDataOutP owp, QData ld, IData rep) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp,ld);
|
||||
for (unsigned i=1; i < rep; ++i){
|
||||
_VL_INSERT_WQ(obits,owp,ld,i*lbits+lbits-1,i*lbits);
|
||||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int, WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_REPLICATE_WWI(int obits, int lbits, int,
|
||||
WDataOutP owp, WDataInP lwp, IData rep) VL_MT_SAFE {
|
||||
for (int i=0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
|
||||
for (unsigned i=1; i < rep; ++i){
|
||||
_VL_INSERT_WW(obits,owp,lwp,i*lbits+lbits-1,i*lbits);
|
||||
@@ -1629,15 +1690,20 @@ static inline QData VL_STREAML_FAST_QQI(int, int lbits, int, QData ld, IData rd_
|
||||
}
|
||||
switch (rd_log2) {
|
||||
case 0:
|
||||
ret = ((ret >> 1) & VL_ULL(0x5555555555555555)) | ((ret & VL_ULL(0x5555555555555555)) << 1); // FALLTHRU
|
||||
ret = (((ret >> 1) & VL_ULL(0x5555555555555555))
|
||||
| ((ret & VL_ULL(0x5555555555555555)) << 1)); // FALLTHRU
|
||||
case 1:
|
||||
ret = ((ret >> 2) & VL_ULL(0x3333333333333333)) | ((ret & VL_ULL(0x3333333333333333)) << 2); // FALLTHRU
|
||||
ret = (((ret >> 2) & VL_ULL(0x3333333333333333))
|
||||
| ((ret & VL_ULL(0x3333333333333333)) << 2)); // FALLTHRU
|
||||
case 2:
|
||||
ret = ((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f)) | ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4); // FALLTHRU
|
||||
ret = (((ret >> 4) & VL_ULL(0x0f0f0f0f0f0f0f0f))
|
||||
| ((ret & VL_ULL(0x0f0f0f0f0f0f0f0f)) << 4)); // FALLTHRU
|
||||
case 3:
|
||||
ret = ((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff)) | ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8); // FALLTHRU
|
||||
ret = (((ret >> 8) & VL_ULL(0x00ff00ff00ff00ff))
|
||||
| ((ret & VL_ULL(0x00ff00ff00ff00ff)) << 8)); // FALLTHRU
|
||||
case 4:
|
||||
ret = ((ret >> 16) & VL_ULL(0x0000ffff0000ffff)) | ((ret & VL_ULL(0x0000ffff0000ffff)) << 16); // FALLTHRU
|
||||
ret = (((ret >> 16) & VL_ULL(0x0000ffff0000ffff))
|
||||
| ((ret & VL_ULL(0x0000ffff0000ffff)) << 16)); // FALLTHRU
|
||||
case 5:
|
||||
ret = ((ret >> 32) | (ret << 32));
|
||||
}
|
||||
@@ -1679,7 +1745,7 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
|
||||
for (int sbit=0; sbit<ssize && sbit<lbits-istart; ++sbit) {
|
||||
// Extract a single bit from lwp and shift it to the correct
|
||||
// location for owp.
|
||||
WData bit= ((lwp[VL_BITWORD_I(istart+sbit)] >> VL_BITBIT_I(istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
|
||||
WData bit= (VL_BITRSHIFT_W(lwp, (istart+sbit)) & 1) << VL_BITBIT_I(ostart+sbit);
|
||||
owp[VL_BITWORD_I(ostart+sbit)] |= bit;
|
||||
}
|
||||
}
|
||||
@@ -1690,61 +1756,75 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
|
||||
// Thus we specify inputs must be clean, so we don't need to clean the output.
|
||||
// Note the bit shifts are always constants, so the adds in these constify out.
|
||||
// Casts required, as args may be 8 bit entities, and need to shift to appropriate output size
|
||||
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) (static_cast<IData>(ld)<<(rbits) | static_cast<IData>(rd))
|
||||
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) \
|
||||
(static_cast<IData>(ld)<<(rbits) | static_cast<IData>(rd))
|
||||
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) \
|
||||
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) \
|
||||
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) \
|
||||
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) \
|
||||
(static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
|
||||
static inline WDataOutP VL_CONCAT_WII(int obits,int lbits,int rbits,WDataOutP owp,IData ld,IData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WII(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, IData ld,IData rd) VL_MT_SAFE {
|
||||
owp[0] = rd;
|
||||
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WWI(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WWI(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
owp[0] = rd;
|
||||
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WIW(int obits,int lbits,int rbits,WDataOutP owp,IData ld, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WIW(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, IData ld, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
|
||||
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WIQ(int obits,int lbits,int rbits,WDataOutP owp,IData ld,QData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WIQ(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, IData ld, QData rd) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp,rd);
|
||||
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WI(obits,owp,ld,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WQI(int obits,int lbits,int rbits,WDataOutP owp,QData ld,IData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WQI(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, QData ld, IData rd) VL_MT_SAFE {
|
||||
owp[0] = rd;
|
||||
for (int i=1; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WQQ(int obits,int lbits,int rbits,WDataOutP owp,QData ld,QData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WQQ(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, QData ld, QData rd) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp,rd);
|
||||
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WWQ(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, QData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WWQ(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, QData rd) VL_MT_SAFE {
|
||||
VL_SET_WQ(owp,rd);
|
||||
for (int i=2; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WQW(int obits,int lbits,int rbits,WDataOutP owp,QData ld, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WQW(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, QData ld, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
|
||||
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WQ(obits,owp,ld,rbits+lbits-1,rbits);
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_CONCAT_WWW(int obits, int lbits, int rbits,
|
||||
WDataOutP owp, WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
for (int i=0; i < VL_WORDS_I(rbits); ++i) owp[i] = rwp[i];
|
||||
for (int i=VL_WORDS_I(rbits); i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
_VL_INSERT_WW(obits,owp,lwp,rbits+lbits-1,rbits);
|
||||
@@ -1783,7 +1863,8 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
||||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
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);
|
||||
@@ -1803,7 +1884,8 @@ static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rw
|
||||
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
|
||||
// Important: Unlike most other funcs, the shift might well be a computed
|
||||
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
|
||||
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SHIFTR_WWI(int obits, int, int,
|
||||
WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
int word_shift = VL_BITWORD_I(rd); // Maybe 0
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set
|
||||
@@ -1828,7 +1910,8 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
|
||||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
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);
|
||||
@@ -1860,10 +1943,12 @@ static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData r
|
||||
QData signext = ~(VL_MASK_Q(lbits) >> rhs);
|
||||
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
||||
}
|
||||
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) VL_PURE {
|
||||
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits,
|
||||
QData lhs, IData rhs) VL_PURE {
|
||||
return static_cast<IData>(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
static inline WDataOutP VL_SHIFTRS_WWI(int obits, int lbits, int,
|
||||
WDataOutP owp, WDataInP lwp, IData rd) VL_MT_SAFE {
|
||||
int word_shift = VL_BITWORD_I(rd);
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
int lmsw = VL_WORDS_I(obits)-1;
|
||||
@@ -1895,7 +1980,8 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
|
||||
}
|
||||
return(owp);
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) VL_MT_SAFE {
|
||||
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;
|
||||
@@ -1907,7 +1993,8 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP o
|
||||
}
|
||||
return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]);
|
||||
}
|
||||
static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) VL_MT_SAFE {
|
||||
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
|
||||
@@ -1916,7 +2003,8 @@ static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDat
|
||||
}
|
||||
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 {
|
||||
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
|
||||
@@ -1959,42 +2047,45 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
|
||||
#define VL_SEL_QQII(obits,lbits,rbits,tbits,lhs,lsb,width) ((lhs)>>(lsb))
|
||||
#define VL_SEL_IQII(obits,lbits,rbits,tbits,lhs,lsb,width) (static_cast<IData>((lhs)>>(lsb)))
|
||||
|
||||
static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
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.
|
||||
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
|
||||
return (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
return VL_BITRSHIFT_W(lwp, lsb);
|
||||
} else {
|
||||
// 32 bit extraction may span two words
|
||||
int nbitsfromlow = 32-VL_BITBIT_I(lsb); // bits that come from low word
|
||||
return ((lwp[VL_BITWORD_I(msb)]<<nbitsfromlow)
|
||||
|(lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)));
|
||||
| VL_BITRSHIFT_W(lwp, lsb));
|
||||
}
|
||||
}
|
||||
|
||||
static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
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.
|
||||
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
|
||||
return (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
return VL_BITRSHIFT_W(lwp, lsb);
|
||||
} else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I(static_cast<int>(lsb))) {
|
||||
int nbitsfromlow = 32-VL_BITBIT_I(lsb);
|
||||
QData hi = (lwp[VL_BITWORD_I(msb)]);
|
||||
QData lo = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
QData lo = VL_BITRSHIFT_W(lwp, lsb);
|
||||
return (hi<<nbitsfromlow) | lo;
|
||||
} else {
|
||||
// 64 bit extraction may span three words
|
||||
int nbitsfromlow = 32-VL_BITBIT_I(lsb);
|
||||
QData hi = (lwp[VL_BITWORD_I(msb)]);
|
||||
QData mid= (lwp[VL_BITWORD_I(lsb)+1]);
|
||||
QData lo = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
QData lo = VL_BITRSHIFT_W(lwp, lsb);
|
||||
return (hi<<(nbitsfromlow+32)) | (mid<<nbitsfromlow) | lo;
|
||||
}
|
||||
}
|
||||
|
||||
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) VL_MT_SAFE {
|
||||
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,
|
||||
@@ -2117,37 +2208,41 @@ static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
|
||||
o[0]=d0;
|
||||
_END(obits,1); }
|
||||
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
|
||||
IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1;
|
||||
_END(obits,2); }
|
||||
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
|
||||
IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2;
|
||||
_END(obits,3); }
|
||||
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
|
||||
IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
||||
_END(obits,4); }
|
||||
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
|
||||
IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
||||
_END(obits,5); }
|
||||
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
|
||||
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
||||
_END(obits,6); }
|
||||
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
|
||||
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d6, IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
||||
_END(obits,7); }
|
||||
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
||||
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) VL_MT_SAFE {
|
||||
IData d7, IData d6, IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||
_END(obits,8); }
|
||||
@@ -2156,7 +2251,8 @@ static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
||||
|
||||
// Partial constant, lower words of vector wider than 8*32, starting at bit number lsb
|
||||
static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
|
||||
IData d7, IData d6, IData d5, IData d4, IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
IData d7, IData d6, IData d5, IData d4,
|
||||
IData d3, IData d2, IData d1, IData d0) VL_MT_SAFE {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
######################################################################
|
||||
# DESCRIPTION: Makefile commands for all verilated target files
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
# Copyright 2003-2018 by Wilson Snyder. Verilator 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.
|
||||
######################################################################
|
||||
@@ -186,14 +186,16 @@ endif
|
||||
|
||||
debug-make::
|
||||
@echo
|
||||
@echo CPPFLAGS: $(CPPFLAGS)
|
||||
@echo VM_PREFIX: $(VM_PREFIX)
|
||||
@echo VM_PARALLEL_BUILDS: $(VM_PARALLEL_BUILDS)
|
||||
@echo VM_CLASSES_FAST: $(VM_CLASSES_FAST)
|
||||
@echo VM_CLASSES_SLOW: $(VM_CLASSES_SLOW)
|
||||
@echo VM_SUPPORT_FAST: $(VM_SUPPORT_FAST)
|
||||
@echo VM_SUPPORT_SLOW: $(VM_SUPPORT_SLOW)
|
||||
@echo VM_GLOBAL_FAST: $(VM_GLOBAL_FAST)
|
||||
@echo VM_GLOBAL_SLOW: $(VM_GLOBAL_SLOW)
|
||||
@echo CPPFLAGS: $(CPPFLAGS)
|
||||
@echo VK_OBJS: $(VK_OBJS)
|
||||
@echo
|
||||
|
||||
######################################################################
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
@@ -233,12 +233,12 @@ public:
|
||||
// PUBLIC METHODS
|
||||
void clear() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
clearGuts();
|
||||
}
|
||||
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (matchp && matchp[0]) {
|
||||
ItemList newlist;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
@@ -254,7 +254,7 @@ public:
|
||||
}
|
||||
void zero() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
@@ -262,18 +262,18 @@ public:
|
||||
|
||||
// We assume there's always call to i/f/p in that order
|
||||
void inserti (VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(!m_insertp);
|
||||
m_insertp = itemp;
|
||||
}
|
||||
void insertf (const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
m_insertFilenamep = filenamep;
|
||||
m_insertLineno = lineno;
|
||||
}
|
||||
void insertp (const char* ckeyps[MAX_KEYS],
|
||||
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
|
||||
void write(const char* filename) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
#ifndef VM_COVERAGE
|
||||
VL_FATAL_MT("",0,"","%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
|
||||
+34
-34
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
@@ -104,39 +104,39 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
|
||||
class VerilatedCovKey {
|
||||
public:
|
||||
static std::string shortKey(const std::string& key) VL_PURE {
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
||||
if (key == "col0") return VL_CIK_COL0;
|
||||
if (key == "col0_name") return VL_CIK_COL0_NAME;
|
||||
if (key == "col1") return VL_CIK_COL1;
|
||||
if (key == "col1_name") return VL_CIK_COL1_NAME;
|
||||
if (key == "col2") return VL_CIK_COL2;
|
||||
if (key == "col2_name") return VL_CIK_COL2_NAME;
|
||||
if (key == "col3") return VL_CIK_COL3;
|
||||
if (key == "col3_name") return VL_CIK_COL3_NAME;
|
||||
if (key == "column") return VL_CIK_COLUMN;
|
||||
if (key == "comment") return VL_CIK_COMMENT;
|
||||
if (key == "filename") return VL_CIK_FILENAME;
|
||||
if (key == "groupcmt") return VL_CIK_GROUPCMT;
|
||||
if (key == "groupdesc") return VL_CIK_GROUPDESC;
|
||||
if (key == "groupname") return VL_CIK_GROUPNAME;
|
||||
if (key == "hier") return VL_CIK_HIER;
|
||||
if (key == "limit") return VL_CIK_LIMIT;
|
||||
if (key == "lineno") return VL_CIK_LINENO;
|
||||
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
|
||||
if (key == "row0") return VL_CIK_ROW0;
|
||||
if (key == "row0_name") return VL_CIK_ROW0_NAME;
|
||||
if (key == "row1") return VL_CIK_ROW1;
|
||||
if (key == "row1_name") return VL_CIK_ROW1_NAME;
|
||||
if (key == "row2") return VL_CIK_ROW2;
|
||||
if (key == "row2_name") return VL_CIK_ROW2_NAME;
|
||||
if (key == "row3") return VL_CIK_ROW3;
|
||||
if (key == "row3_name") return VL_CIK_ROW3_NAME;
|
||||
if (key == "table") return VL_CIK_TABLE;
|
||||
if (key == "thresh") return VL_CIK_THRESH;
|
||||
if (key == "type") return VL_CIK_TYPE;
|
||||
if (key == "weight") return VL_CIK_WEIGHT;
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_END
|
||||
return key;
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
||||
if (key == "col0") return VL_CIK_COL0;
|
||||
if (key == "col0_name") return VL_CIK_COL0_NAME;
|
||||
if (key == "col1") return VL_CIK_COL1;
|
||||
if (key == "col1_name") return VL_CIK_COL1_NAME;
|
||||
if (key == "col2") return VL_CIK_COL2;
|
||||
if (key == "col2_name") return VL_CIK_COL2_NAME;
|
||||
if (key == "col3") return VL_CIK_COL3;
|
||||
if (key == "col3_name") return VL_CIK_COL3_NAME;
|
||||
if (key == "column") return VL_CIK_COLUMN;
|
||||
if (key == "comment") return VL_CIK_COMMENT;
|
||||
if (key == "filename") return VL_CIK_FILENAME;
|
||||
if (key == "groupcmt") return VL_CIK_GROUPCMT;
|
||||
if (key == "groupdesc") return VL_CIK_GROUPDESC;
|
||||
if (key == "groupname") return VL_CIK_GROUPNAME;
|
||||
if (key == "hier") return VL_CIK_HIER;
|
||||
if (key == "limit") return VL_CIK_LIMIT;
|
||||
if (key == "lineno") return VL_CIK_LINENO;
|
||||
if (key == "per_instance") return VL_CIK_PER_INSTANCE;
|
||||
if (key == "row0") return VL_CIK_ROW0;
|
||||
if (key == "row0_name") return VL_CIK_ROW0_NAME;
|
||||
if (key == "row1") return VL_CIK_ROW1;
|
||||
if (key == "row1_name") return VL_CIK_ROW1_NAME;
|
||||
if (key == "row2") return VL_CIK_ROW2;
|
||||
if (key == "row2_name") return VL_CIK_ROW2_NAME;
|
||||
if (key == "row3") return VL_CIK_ROW3;
|
||||
if (key == "row3_name") return VL_CIK_ROW3_NAME;
|
||||
if (key == "table") return VL_CIK_TABLE;
|
||||
if (key == "thresh") return VL_CIK_THRESH;
|
||||
if (key == "type") return VL_CIK_TYPE;
|
||||
if (key == "weight") return VL_CIK_WEIGHT;
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_END
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+562
-100
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2018 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.
|
||||
@@ -16,8 +16,8 @@
|
||||
/// \file
|
||||
/// \brief Verilator: DPI implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the DPI.
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the DPI.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@@ -44,9 +44,12 @@
|
||||
#define _VL_SVDPI_UNIMP() \
|
||||
VL_FATAL_MT(__FILE__,__LINE__,"",(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
|
||||
|
||||
#define _VL_SVDPI_WARN(message...) \
|
||||
VL_PRINTF_MT(message)
|
||||
|
||||
// Function requires a "context" in the import declaration
|
||||
#define _VL_SVDPI_CONTEXT_WARN() \
|
||||
VL_PRINTF_MT("%%Warning: DPI C Function called by Verilog DPI import with missing 'context' keyword.\n");
|
||||
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing 'context' keyword.\n");
|
||||
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
@@ -61,196 +64,655 @@ const char* svDpiVersion() {
|
||||
// Bit-select utility functions.
|
||||
|
||||
svBit svGetBitselBit(const svBitVecVal* sp, int bit) {
|
||||
return VL_BITISSET_W(sp,bit);
|
||||
return VL_BITRSHIFT_W(sp,bit) & 1;
|
||||
}
|
||||
svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
// Not VL_BITRSHIFT_W as sp is a different structure type
|
||||
// Verilator doesn't support X/Z so only aval
|
||||
return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
|
||||
| (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1)<<1));
|
||||
}
|
||||
|
||||
void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) {
|
||||
VL_ASSIGNBIT_WI(32, bit, dp, s);
|
||||
}
|
||||
void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
// Verilator doesn't support X/Z so only aval
|
||||
dp[VL_BITWORD_I(bit)].aval
|
||||
= ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
| ((s&1)<<VL_BITBIT_I(bit)));
|
||||
dp[VL_BITWORD_I(bit)].bval
|
||||
= ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
| ((s&2)>>1<<VL_BITBIT_I(bit)));
|
||||
}
|
||||
|
||||
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int i, int w) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
|
||||
// See also VL_SEL_WWI
|
||||
int msb = lsb+width-1;
|
||||
int word_shift = VL_BITWORD_I(lsb);
|
||||
if (VL_BITBIT_I(lsb)==0) {
|
||||
// Just a word extract
|
||||
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
|
||||
} else {
|
||||
int loffset = lsb & VL_SIZEBITS_I;
|
||||
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
int words = VL_WORDS_I(msb-lsb+1);
|
||||
for (int i=0; i<words; ++i) {
|
||||
dp[i] = sp[i+word_shift]>>loffset;
|
||||
int upperword = i+word_shift+1;
|
||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||
dp[i] |= sp[upperword] << nbitsfromlow;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clean result
|
||||
dp[VL_WORDS_I(width)-1] &= VL_MASK_I(width);
|
||||
}
|
||||
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int i, int w) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
|
||||
int msb = lsb+width-1;
|
||||
int word_shift = VL_BITWORD_I(lsb);
|
||||
if (VL_BITBIT_I(lsb)==0) {
|
||||
// Just a word extract
|
||||
for (int i=0; i<VL_WORDS_I(width); ++i) dp[i] = sp[i+word_shift];
|
||||
} else {
|
||||
int loffset = lsb & VL_SIZEBITS_I;
|
||||
int nbitsfromlow = 32-loffset; // bits that end up in lword (know loffset!=0)
|
||||
// Middle words
|
||||
int words = VL_WORDS_I(msb-lsb+1);
|
||||
for (int i=0; i<words; ++i) {
|
||||
dp[i].aval = sp[i+word_shift].aval >> loffset;
|
||||
dp[i].bval = sp[i+word_shift].bval >> loffset;
|
||||
int upperword = i+word_shift+1;
|
||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||
dp[i].aval |= sp[upperword].aval << nbitsfromlow;
|
||||
dp[i].bval |= sp[upperword].bval << nbitsfromlow;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clean result
|
||||
dp[VL_WORDS_I(width)-1].aval &= VL_MASK_I(width);
|
||||
dp[VL_WORDS_I(width)-1].bval &= VL_MASK_I(width);
|
||||
}
|
||||
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
|
||||
// See also _VL_INSERT_WI
|
||||
int hbit = lbit+width-1;
|
||||
int hoffset = VL_BITBIT_I(hbit);
|
||||
int loffset = VL_BITBIT_I(lbit);
|
||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||
// Fast and common case, word based insertion
|
||||
dp[VL_BITWORD_I(lbit)] = s;
|
||||
}
|
||||
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;
|
||||
dp[lword] = (dp[lword] & ~insmask) | ((s<<loffset) & insmask);
|
||||
} else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
||||
dp[lword] = (dp[lword] & ~linsmask) | ((s<<loffset) & linsmask);
|
||||
dp[hword] = (dp[hword] & ~hinsmask) | ((s>>nbitsonright) & hinsmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
// cppcheck-suppress passedByValue
|
||||
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
|
||||
int hbit = lbit+width-1;
|
||||
int hoffset = VL_BITBIT_I(hbit);
|
||||
int loffset = VL_BITBIT_I(lbit);
|
||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||
// Fast and common case, word based insertion
|
||||
dp[VL_BITWORD_I(lbit)].aval = s.aval;
|
||||
dp[VL_BITWORD_I(lbit)].bval = s.bval;
|
||||
}
|
||||
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;
|
||||
dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval<<loffset) & insmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval<<loffset) & insmask);
|
||||
} else {
|
||||
IData hinsmask = (VL_MASK_I(hoffset-0+1))<<0;
|
||||
IData linsmask = (VL_MASK_I(31-loffset+1))<<loffset;
|
||||
int nbitsonright = 32-loffset; // bits that end up in lword
|
||||
dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval<<loffset) & linsmask);
|
||||
dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval<<loffset) & linsmask);
|
||||
dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval>>nbitsonright) & hinsmask);
|
||||
dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval>>nbitsonright) & hinsmask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int i, int w) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
}
|
||||
void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int i, int w) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
//======================================================================
|
||||
// Open array internals
|
||||
|
||||
static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
|
||||
if (VL_UNLIKELY(!h)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"%%Error: DPI svOpenArrayHandle function called with NULL handle");
|
||||
}
|
||||
const VerilatedDpiOpenVar* varp = reinterpret_cast<const VerilatedDpiOpenVar*>(h);
|
||||
if (VL_UNLIKELY(!varp->magicOk())) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"%%Error: DPI svOpenArrayHandle function called with non-Verilator handle");
|
||||
}
|
||||
return varp;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Open array querying functions
|
||||
|
||||
int svLeft(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_openhandle_varp(h)->left(d);
|
||||
}
|
||||
int svRight(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_openhandle_varp(h)->right(d);
|
||||
}
|
||||
int svLow(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_openhandle_varp(h)->low(d);
|
||||
}
|
||||
int svHigh(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_openhandle_varp(h)->high(d);
|
||||
}
|
||||
int svIncrement(const svOpenArrayHandle h, int d) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_openhandle_varp(h)->increment(d);
|
||||
}
|
||||
int svSize(const svOpenArrayHandle h, int d) {
|
||||
return _vl_openhandle_varp(h)->elements(d);
|
||||
}
|
||||
int svDimensions(const svOpenArrayHandle h) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_openhandle_varp(h)->udims();
|
||||
}
|
||||
|
||||
void *svGetArrayPtr(const svOpenArrayHandle) {
|
||||
_VL_SVDPI_UNIMP(); return NULL;
|
||||
/// Return pointer to open array data, or NULL if not in IEEE standard C layout
|
||||
void* svGetArrayPtr(const svOpenArrayHandle h) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
||||
return varp->datap();
|
||||
}
|
||||
|
||||
int svSizeOfArray(const svOpenArrayHandle) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
}
|
||||
|
||||
void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP(); return NULL;
|
||||
}
|
||||
void *svGetArrElemPtr1(const svOpenArrayHandle, int indx1) {
|
||||
_VL_SVDPI_UNIMP(); return NULL;
|
||||
}
|
||||
void *svGetArrElemPtr2(const svOpenArrayHandle, int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP(); return NULL;
|
||||
}
|
||||
void *svGetArrElemPtr3(const svOpenArrayHandle, int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP(); return NULL;
|
||||
/// Return size of open array, or 0 if not in IEEE standard C layout
|
||||
int svSizeOfArray(const svOpenArrayHandle h) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return 0;
|
||||
// Truncate 64 bits to int; DPI is limited to 4GB
|
||||
return static_cast<int>(varp->totalSize());
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// s=source, d=destination
|
||||
// From user space into simulator storage
|
||||
// Open array access internals
|
||||
|
||||
static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp,
|
||||
int nargs, int indx1, int indx2, int indx3) {
|
||||
void* datap = varp->datap();
|
||||
if (VL_UNLIKELY(nargs != varp->udims())) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
|
||||
" %d dimensional array using %d dimensional function.\n",
|
||||
varp->udims(), nargs);
|
||||
return NULL;
|
||||
}
|
||||
if (nargs>=1) {
|
||||
datap = varp->datapAdjustIndex(datap, 1, indx1);
|
||||
if (VL_UNLIKELY(!datap)) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 out of bounds; %d outside [%d:%d].\n",
|
||||
indx1, varp->left(1), varp->right(1));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (nargs>=2) {
|
||||
datap = varp->datapAdjustIndex(datap, 2, indx2);
|
||||
if (VL_UNLIKELY(!datap)) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 out of bounds; %d outside [%d:%d].\n",
|
||||
indx2, varp->left(2), varp->right(2));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (nargs>=3) {
|
||||
datap = varp->datapAdjustIndex(datap, 3, indx3);
|
||||
if (VL_UNLIKELY(!datap)) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 out of bounds; %d outside [%d:%d].\n",
|
||||
indx1, varp->left(3), varp->right(3));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return datap;
|
||||
}
|
||||
|
||||
static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
|
||||
if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) {
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d outside [%d:%d].\n",
|
||||
indx, varp->left(0), varp->right(0));
|
||||
return 0;
|
||||
}
|
||||
return indx - varp->low(0);
|
||||
}
|
||||
|
||||
/// Return pointer to simulator open array element, or NULL if outside range
|
||||
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
return datap;
|
||||
}
|
||||
|
||||
/// Copy to user bit array from simulator open array
|
||||
static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
|
||||
case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
|
||||
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
||||
case VLVT_UINT64: {
|
||||
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||
d[0] = lwp[0]; d[1] = lwp[1];
|
||||
break;
|
||||
}
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
/// Copy to user logic array from simulator open array
|
||||
static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: d[0].aval = *(reinterpret_cast<CData*>(datap)); d[0].bval=0; return;
|
||||
case VLVT_UINT16: d[0].aval = *(reinterpret_cast<SData*>(datap)); d[0].bval=0; return;
|
||||
case VLVT_UINT32: d[0].aval = *(reinterpret_cast<IData*>(datap)); d[0].bval=0; return;
|
||||
case VLVT_UINT64: {
|
||||
WData lwp[2]; VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||
d[0].aval = lwp[0]; d[0].bval=0;
|
||||
d[1].aval = lwp[1]; d[0].bval=0;
|
||||
break;
|
||||
}
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) {
|
||||
d[i].aval = wdatap[i]; d[i].bval = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Copy to simulator open array from from user bit array
|
||||
static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
|
||||
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); break;
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
/// Copy to simulator open array from from user logic array
|
||||
static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
|
||||
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval); break;
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
for (int i=0; i<VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return bit from simulator open array
|
||||
static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s,
|
||||
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
|
||||
// One extra index supported, as need bit number
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
void* datap;
|
||||
int lsb;
|
||||
if (varp->packed().elements()) {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
|
||||
: (nargs==2) ? indx2
|
||||
: (nargs==3) ? indx3
|
||||
: indx4));
|
||||
} else {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
lsb = 0;
|
||||
}
|
||||
if (VL_UNLIKELY(!datap)) return 0;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT16: return (*(reinterpret_cast<SData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT32: return (*(reinterpret_cast<IData*>(datap)) >> lsb) & 1;
|
||||
case VLVT_UINT64: return (*(reinterpret_cast<QData*>(datap)) >> static_cast<QData>(lsb)) & VL_ULL(1);
|
||||
case VLVT_WDATA: {
|
||||
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
|
||||
return VL_BITRSHIFT_W(wdatap, lsb) & 1;
|
||||
}
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/// Update simulator open array from bit
|
||||
static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value,
|
||||
int nargs, int indx1, int indx2, int indx3, int indx4) VL_MT_SAFE {
|
||||
// One extra index supported, as need bit number
|
||||
value &= 1; // Make sure clean
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
void* datap;
|
||||
int lsb;
|
||||
if (varp->packed().elements()) {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs-1, indx1, indx2, indx3);
|
||||
lsb = _vl_sv_adjusted_bit(varp, ((nargs==1) ? indx1
|
||||
: (nargs==2) ? indx2
|
||||
: (nargs==3) ? indx3
|
||||
: indx4));
|
||||
} else {
|
||||
datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
lsb = 0;
|
||||
}
|
||||
if (VL_UNLIKELY(!datap)) return;
|
||||
switch (varp->vltype()) {
|
||||
case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<CData*>(datap)), value); return;
|
||||
case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<SData*>(datap)), value); return;
|
||||
case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast<IData*>(datap)), value); return;
|
||||
case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast<QData*>(datap)), value); return;
|
||||
case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast<WDataOutP>(datap)), value); return;
|
||||
default:
|
||||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// DPI accessors that simply call above functions
|
||||
|
||||
void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
void* datap;
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
// va_arg is a macro, so need temporaries as used below
|
||||
switch (varp->udims()) {
|
||||
case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
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
|
||||
}
|
||||
va_end(ap);
|
||||
return datap;
|
||||
}
|
||||
void* svGetArrElemPtr1(const svOpenArrayHandle h, int indx1) {
|
||||
return _vl_svGetArrElemPtr(h, 1, indx1, 0, 0);
|
||||
}
|
||||
void* svGetArrElemPtr2(const svOpenArrayHandle h, int indx1, int indx2) {
|
||||
return _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
|
||||
}
|
||||
void* svGetArrElemPtr3(const svOpenArrayHandle h, int indx1, int indx2, int indx3) {
|
||||
return _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_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
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1) {
|
||||
_vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2) {
|
||||
_vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2, int indx3) {
|
||||
_vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_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
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1) {
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2) {
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2, int indx3) {
|
||||
_vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// From simulator storage into user space
|
||||
|
||||
void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_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
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1) {
|
||||
_vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2) {
|
||||
_vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2, int indx3) {
|
||||
_vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, ...) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_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
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1) {
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
|
||||
}
|
||||
void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2) {
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
|
||||
}
|
||||
void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
int indx1, int indx2, int indx3) {
|
||||
_vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
svBit out;
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
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
|
||||
}
|
||||
va_end(ap);
|
||||
return out;
|
||||
}
|
||||
svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0);
|
||||
}
|
||||
svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
|
||||
}
|
||||
svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP(); return 0;
|
||||
return _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
|
||||
}
|
||||
svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP(); return sv_x;
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s);
|
||||
svBit out;
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
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
|
||||
}
|
||||
va_end(ap);
|
||||
return out;
|
||||
}
|
||||
svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1) {
|
||||
_VL_SVDPI_UNIMP(); return sv_x;
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
return svGetBitArrElem1(s, indx1);
|
||||
}
|
||||
svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP(); return sv_x;
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
return svGetBitArrElem2(s, indx1, indx2);
|
||||
}
|
||||
svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP(); return sv_x;
|
||||
}
|
||||
void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
}
|
||||
void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
}
|
||||
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
}
|
||||
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
return svGetBitArrElem3(s, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_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
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
_vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0);
|
||||
}
|
||||
void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1, int indx2) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
|
||||
}
|
||||
void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1, int indx2, int indx3) {
|
||||
_VL_SVDPI_UNIMP();
|
||||
_vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
|
||||
}
|
||||
void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) {
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d);
|
||||
va_list ap;
|
||||
va_start(ap, indx1);
|
||||
switch (varp->udims()) {
|
||||
case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
|
||||
case 2: { int indx2=va_arg(ap,int);
|
||||
_vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0); break; }
|
||||
case 3: { int indx2=va_arg(ap,int); int indx3=va_arg(ap,int);
|
||||
_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
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
svPutBitArrElem1(d, value, indx1);
|
||||
}
|
||||
void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
svPutBitArrElem2(d, value, indx1, indx2);
|
||||
}
|
||||
void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2, int indx3) {
|
||||
// Verilator doesn't support X/Z so can just call Bit version
|
||||
svPutBitArrElem3(d, value, indx1, indx2, indx3);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
@@ -277,7 +739,7 @@ svScope svGetScopeFromName(const char* scopeName) {
|
||||
return (svScope)VerilatedImp::scopeFind(scopeName);
|
||||
}
|
||||
|
||||
int svPutUserData(const svScope scope, void *userKey, void* userData) {
|
||||
int svPutUserData(const svScope scope, void* userKey, void* userData) {
|
||||
VerilatedImp::userInsert(scope,userKey,userData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+24
-7
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -28,36 +28,53 @@
|
||||
#ifndef _VERILATED_DPI_H_
|
||||
#define _VERILATED_DPI_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated.h" // Presumed done by caller
|
||||
#include "verilated.h" // Also presumably included by caller
|
||||
#include "verilated_sym_props.h"
|
||||
#include "svdpi.h"
|
||||
|
||||
//===================================================================
|
||||
// SETTING OPERATORS
|
||||
|
||||
/// Return svBitVecVal from WData
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) VL_MT_SAFE {
|
||||
/// Return WData from svBitVecVal
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; ++i) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
/// Return svBitVecVal from WData
|
||||
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; ++i) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
// Note we ignore X/Z in svLogicVecVal
|
||||
|
||||
/// Convert svLogicVecVal to/from WData
|
||||
/// Note these functions ignore X/Z in svLogicVecVal
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; ++i) owp[i]=lwp[i].aval;
|
||||
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
|
||||
}
|
||||
static inline QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
return _VL_SET_QII(lwp[1].aval, lwp[0].aval);
|
||||
}
|
||||
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
|
||||
return lwp[0].aval;
|
||||
}
|
||||
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE {
|
||||
// Note we don't create X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words; ++i) owp[i].bval=0;
|
||||
for (int i=0; i<words-1; ++i) owp[i].aval=lwp[i];
|
||||
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, IData ld) VL_MT_SAFE {
|
||||
owp[0].aval=ld; owp[0].bval=0;
|
||||
}
|
||||
static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, QData ld) VL_MT_SAFE {
|
||||
WData lwp[2]; VL_SET_WQ(lwp,ld);
|
||||
owp[0].aval=lwp[0]; owp[0].bval=0;
|
||||
owp[1].aval=lwp[1]; owp[1].bval=0;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2018 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.
|
||||
@@ -56,15 +56,22 @@ inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData
|
||||
for (unsigned times=0; times<rep; ++times) out += lhs;
|
||||
return out;
|
||||
}
|
||||
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const std::string& lhs, IData rep) VL_PURE {
|
||||
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits,
|
||||
const std::string& lhs, IData rep) VL_PURE {
|
||||
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
|
||||
}
|
||||
|
||||
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
|
||||
|
||||
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const std::string& ofilename, void* memp, IData start, IData end) VL_MT_SAFE;
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
|
||||
const std::string& ofilename,
|
||||
void* memp, IData start, IData end) VL_MT_SAFE;
|
||||
extern void VL_WRITEMEM_N(bool hex, int width, int depth, int array_lsb,
|
||||
const std::string& ofilename,
|
||||
const void* memp, IData start, IData end) VL_MT_SAFE;
|
||||
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...) VL_MT_SAFE;
|
||||
extern void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...) VL_MT_SAFE;
|
||||
extern void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE;
|
||||
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
|
||||
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rdp) VL_MT_SAFE;
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) VL_MT_SAFE {
|
||||
|
||||
+45
-95
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2018 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.
|
||||
@@ -49,25 +49,25 @@ class VerilatedScope;
|
||||
// Threaded message passing
|
||||
|
||||
#ifdef VL_THREADED
|
||||
/// Message, enqueued on a train, and consumed on the main eval thread
|
||||
/// Message, enqueued on an mtask, and consumed on the main eval thread
|
||||
class VerilatedMsg {
|
||||
public:
|
||||
// TYPES
|
||||
struct Cmp {
|
||||
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) {
|
||||
return a.trainId() < b.trainId(); }
|
||||
bool operator() (const VerilatedMsg& a, const VerilatedMsg& b) const {
|
||||
return a.mtaskId() < b.mtaskId(); }
|
||||
};
|
||||
private:
|
||||
// MEMBERS
|
||||
vluint32_t m_trainId; ///< Train that did enqueue
|
||||
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)
|
||||
: m_trainId(Verilated::trainId()), m_cb(cb) {}
|
||||
: m_mtaskId(Verilated::mtaskId()), m_cb(cb) {}
|
||||
~VerilatedMsg() {}
|
||||
// METHODS
|
||||
vluint32_t trainId() const { return m_trainId; }
|
||||
vluint32_t mtaskId() const { return m_mtaskId; }
|
||||
/// Execute the lambda function
|
||||
void run() const { m_cb(); }
|
||||
};
|
||||
@@ -84,7 +84,9 @@ class VerilatedEvalMsgQueue {
|
||||
VerilatedThreadQueue m_queue VL_GUARDED_BY(m_mutex); ///< Message queue
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedEvalMsgQueue() : m_depth(0) { }
|
||||
VerilatedEvalMsgQueue() : m_depth(0) {
|
||||
assert(atomic_is_lock_free(&m_depth));
|
||||
}
|
||||
~VerilatedEvalMsgQueue() { }
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
|
||||
@@ -92,8 +94,7 @@ public:
|
||||
// METHODS
|
||||
//// Add message to queue (called by producer)
|
||||
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::endOfEvalReqdInc(); // No mutex, threadsafe
|
||||
VerilatedLockGuard guard(m_mutex);
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
m_queue.insert(msg); // Pass by value to copy the message into queue
|
||||
++m_depth;
|
||||
}
|
||||
@@ -114,10 +115,9 @@ public:
|
||||
m_queue.erase(it);
|
||||
m_mutex.unlock();
|
||||
m_depth--; // Ok if outside critical section as only this code checks the value
|
||||
Verilated::endOfEvalReqdDec(); // No mutex, threadsafe
|
||||
{
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("Executing callback from trainId=%d\n", msg.trainId()););
|
||||
msg.run();
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("Executing callback from mtaskId=%d\n", msg.mtaskId()););
|
||||
msg.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,8 +143,15 @@ private:
|
||||
public:
|
||||
/// Add message to queue, called by producer
|
||||
static void post(const VerilatedMsg& msg) VL_MT_SAFE {
|
||||
Verilated::endOfEvalReqdInc();
|
||||
threadton().m_queue.push(msg); // Pass by value to copy the message into queue
|
||||
// Handle calls to threaded routines outside
|
||||
// of any mtask -- if an initial block calls $finish, say.
|
||||
if (Verilated::mtaskId() == 0) {
|
||||
// No queueing, just do the action immediately
|
||||
msg.run();
|
||||
} else {
|
||||
Verilated::endOfEvalReqdInc();
|
||||
threadton().m_queue.push(msg); // Pass by value to copy the message into queue
|
||||
}
|
||||
}
|
||||
/// Push all messages to the eval's queue
|
||||
static void flush(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
||||
@@ -192,15 +199,10 @@ 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)
|
||||
|
||||
// Threads
|
||||
VerilatedMutex m_threadMutex; ///< Protect m_numThreads, etc
|
||||
bool m_spawned VL_GUARDED_BY(m_threadMutex); ///< Already called spawnThreads()
|
||||
unsigned m_numThreads VL_GUARDED_BY(m_threadMutex); ///< Number of threads user requested, 0x0=all cpus
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp()
|
||||
: m_argVecLoaded(false), m_exportNext(0), m_spawned(false), m_numThreads(0) {
|
||||
: m_argVecLoaded(false), m_exportNext(0) {
|
||||
m_fdps.resize(3);
|
||||
m_fdps[0] = stdin;
|
||||
m_fdps[1] = stdout;
|
||||
@@ -210,33 +212,16 @@ public: // But only for verilated*.cpp
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedImp);
|
||||
public:
|
||||
static void internalsDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_argMutex);
|
||||
VL_PRINTF_MT("internalsDump:\n");
|
||||
VL_PRINTF_MT(" Argv:");
|
||||
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF_MT(" %s",it->c_str());
|
||||
}
|
||||
VL_PRINTF_MT("\n");
|
||||
VL_PRINTF_MT(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
|
||||
scopesDump();
|
||||
exportsDump();
|
||||
userDump();
|
||||
}
|
||||
// METHODS - debug
|
||||
static void internalsDump() VL_MT_SAFE;
|
||||
static void versionDump() VL_MT_SAFE;
|
||||
|
||||
// METHODS - arguments
|
||||
public:
|
||||
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
VerilatedLockGuard guard(s_s.m_argMutex);
|
||||
s_s.m_argVec.clear(); // Always clear
|
||||
commandArgsAddGuts(argc, argv);
|
||||
}
|
||||
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
VerilatedLockGuard guard(s_s.m_argMutex);
|
||||
commandArgsAddGuts(argc, argv);
|
||||
}
|
||||
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
|
||||
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
|
||||
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
VerilatedLockGuard guard(s_s.m_argMutex);
|
||||
VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
// Note prefixp does not include the leading "+"
|
||||
size_t len = strlen(prefixp);
|
||||
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
|
||||
@@ -253,11 +238,7 @@ public:
|
||||
return "";
|
||||
}
|
||||
private:
|
||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex) {
|
||||
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||
for (int i=0; i<argc; ++i) s_s.m_argVec.push_back(argv[i]);
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
|
||||
|
||||
public:
|
||||
// METHODS - user scope tracking
|
||||
@@ -265,14 +246,14 @@ public:
|
||||
// There's often many more scopes than userdata's and thus having a ~48byte
|
||||
// per map overhead * N scopes would take much more space and cache thrashing.
|
||||
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_userMapMutex);
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
|
||||
if (it != s_s.m_userMap.end()) it->second = userData;
|
||||
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
|
||||
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep,userKey),userData));
|
||||
}
|
||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_userMapMutex);
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
|
||||
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
|
||||
else return NULL;
|
||||
@@ -281,7 +262,7 @@ private:
|
||||
/// Symbol table destruction cleans up the entries for each scope.
|
||||
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope on destruction, so we simply iterate.
|
||||
VerilatedLockGuard guard(s_s.m_userMapMutex);
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ) {
|
||||
if (it->first.first == scopep) {
|
||||
s_s.m_userMap.erase(it++);
|
||||
@@ -291,7 +272,7 @@ private:
|
||||
}
|
||||
}
|
||||
static void userDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_userMapMutex); // Avoid it changing in middle of dump
|
||||
VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
|
||||
bool first = true;
|
||||
for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; }
|
||||
@@ -304,27 +285,27 @@ 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
|
||||
VerilatedLockGuard guard(s_s.m_nameMutex);
|
||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||
if (it == s_s.m_nameMap.end()) {
|
||||
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(),scopep));
|
||||
}
|
||||
}
|
||||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT
|
||||
VerilatedLockGuard lock(s_s.m_nameMutex); // If too slow, can assume this is only VL_MT_SAFE_POSINIT
|
||||
VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
|
||||
else return NULL;
|
||||
}
|
||||
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope at destruction
|
||||
VerilatedLockGuard guard(s_s.m_nameMutex);
|
||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
userEraseScope(scopep);
|
||||
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
||||
}
|
||||
static void scopesDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_nameMutex);
|
||||
VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
VL_PRINTF_MT(" scopesDump:\n");
|
||||
for (VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||
const VerilatedScope* scopep = it->second;
|
||||
@@ -348,7 +329,7 @@ public: // But only for verilated*.cpp
|
||||
// miss at the cost of a multiply, and all lookups move to slowpath.
|
||||
static int exportInsert(const char* namep) VL_MT_SAFE {
|
||||
// Slow ok - called once/function at creation
|
||||
VerilatedLockGuard guard(s_s.m_exportMutex);
|
||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
|
||||
if (it == s_s.m_exportMap.end()) {
|
||||
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
|
||||
@@ -358,7 +339,7 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
}
|
||||
static int exportFind(const char* namep) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_exportMutex);
|
||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
ExportNameMap::const_iterator it=s_s.m_exportMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
||||
std::string msg = (std::string("%Error: Testbench C called ")+namep
|
||||
@@ -368,14 +349,14 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
static const char* exportName(int funcnum) VL_MT_SAFE {
|
||||
// Slowpath; find name for given export; errors only so no map to reverse-map it
|
||||
VerilatedLockGuard guard(s_s.m_exportMutex);
|
||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (it->second == funcnum) return it->first;
|
||||
}
|
||||
return "*UNKNOWN*";
|
||||
}
|
||||
static void exportsDump() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_exportMutex);
|
||||
VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
bool first = true;
|
||||
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; }
|
||||
@@ -390,7 +371,7 @@ public: // But only for verilated*.cpp
|
||||
static IData fdNew(FILE* fp) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
// Bit 31 indicates it's a descriptor not a MCD
|
||||
VerilatedLockGuard guard(s_s.m_fdMutex);
|
||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
if (s_s.m_fdFree.empty()) {
|
||||
// Need to create more space in m_fdps and m_fdFree
|
||||
size_t start = s_s.m_fdps.size();
|
||||
@@ -403,7 +384,7 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
static void fdDelete(IData fdi) VL_MT_SAFE {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
VerilatedLockGuard guard(s_s.m_fdMutex);
|
||||
VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
||||
s_s.m_fdps[idx] = NULL;
|
||||
@@ -411,41 +392,10 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
VerilatedLockGuard guard(s_s.m_fdMutex); // This might get slow, if it does we can cache it
|
||||
VerilatedLockGuard lock(s_s.m_fdMutex); // This might get slow, if it does we can cache it
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
|
||||
return s_s.m_fdps[idx];
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - Threading
|
||||
static void numThreads(unsigned threads) VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_threadMutex);
|
||||
if (!s_s.m_spawned) s_s.m_numThreads = threads;
|
||||
}
|
||||
static unsigned numThreads() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_threadMutex);
|
||||
#ifdef VL_THREADED
|
||||
unsigned threads = s_s.m_numThreads;
|
||||
if (threads == 0x0) {
|
||||
threads = std::thread::hardware_concurrency(); // Or 0=unknown, C++11
|
||||
}
|
||||
if (threads<1) threads = 1;
|
||||
return threads;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
static void spawnThreads() VL_MT_SAFE {
|
||||
VerilatedLockGuard guard(s_s.m_threadMutex);
|
||||
if (!s_s.m_spawned) {
|
||||
// Convert numThreads from 0 to the spawned number
|
||||
numThreads(numThreads());
|
||||
s_s.m_spawned = true;
|
||||
#ifdef VL_THREADED
|
||||
// THREADED-TODO startup threads
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2012-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2012-2018 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.
|
||||
//
|
||||
@@ -138,7 +138,8 @@ public:
|
||||
}
|
||||
// Read a datum and compare with expected value
|
||||
VerilatedDeserialize& readAssert(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
|
||||
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE { return readAssert(&data, sizeof(data)); }
|
||||
VerilatedDeserialize& readAssert(vluint64_t data) VL_MT_UNSAFE_ONE {
|
||||
return readAssert(&data, sizeof(data)); }
|
||||
private:
|
||||
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
|
||||
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2018 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.
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2018 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.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Include to provide information about symbol inspection
|
||||
///
|
||||
/// This file is for inclusion by internal files that need to inspect
|
||||
/// specific symbols.
|
||||
///
|
||||
/// User routines wanting to inspect the symbol table should use
|
||||
/// verilated_syms.h instead.
|
||||
///
|
||||
/// These classes are thread safe, and read only.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATED_SYM_PROPS_H_
|
||||
#define _VERILATED_SYM_PROPS_H_ 1 ///< Header Guard
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator range
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
// See also V3Ast::VNumRange
|
||||
class VerilatedRange {
|
||||
int m_left;
|
||||
int m_right;
|
||||
protected:
|
||||
friend class VerilatedVarProps;
|
||||
friend class VerilatedScope;
|
||||
VerilatedRange() : m_left(0), m_right(0) {}
|
||||
VerilatedRange(int left, int right) : m_left(left), m_right(right) {}
|
||||
void init(int left, int right) { m_left=left; m_right=right; }
|
||||
public:
|
||||
~VerilatedRange() {}
|
||||
int left() const { return m_left; }
|
||||
int right() const { return m_right; }
|
||||
int low() const { return (m_left < m_right) ? m_left : m_right; }
|
||||
int high() const { return (m_left > m_right) ? m_left : m_right; }
|
||||
int elements() const {
|
||||
return (VL_LIKELY(m_left>=m_right) ? (m_left-m_right+1) : (m_right-m_left+1)); }
|
||||
int increment() const { return (m_left >= m_right) ? 1 : -1; }
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator variable
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
class VerilatedVarProps {
|
||||
// TYPES
|
||||
enum { MAGIC = 0xddc4f829 };
|
||||
// MEMBERS
|
||||
const vluint32_t m_magic; // Magic number
|
||||
const VerilatedVarType m_vltype; // Data type
|
||||
const VerilatedVarFlags m_vlflags; // Direction
|
||||
const int m_pdims; // Packed dimensions
|
||||
const int m_udims; // Unpacked dimensions
|
||||
VerilatedRange m_packed; // Packed array range
|
||||
VerilatedRange m_unpacked[3]; // Unpacked array range
|
||||
// CONSTRUCTORS
|
||||
protected:
|
||||
friend class VerilatedScope;
|
||||
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags,
|
||||
int pdims, int udims)
|
||||
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(vlflags), m_pdims(pdims), m_udims(udims) {}
|
||||
public:
|
||||
class Unpacked {};
|
||||
// Without packed
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(0) { }
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Unpacked, int u0l, int u0r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(1) {
|
||||
m_unpacked[0].init(u0l, u0r); }
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(2) {
|
||||
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); }
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(0), m_udims(3) {
|
||||
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); }
|
||||
// With packed
|
||||
class Packed {};
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(0), m_packed(pl,pr) { }
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr,
|
||||
Unpacked, int u0l, int u0r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(1), m_packed(pl,pr) {
|
||||
m_unpacked[0].init(u0l, u0r); }
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r)
|
||||
: m_magic(MAGIC), m_vltype(vltype), m_vlflags(VerilatedVarFlags(vlflags)),
|
||||
m_pdims(1), m_udims(2), m_packed(pl,pr) {
|
||||
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); }
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags,
|
||||
Packed, int pl, int pr,
|
||||
Unpacked, int u0l, int u0r, int u1l, int u1r, int u2l, int u2r)
|
||||
: m_magic(MAGIC), m_vltype(vltype),
|
||||
m_vlflags(VerilatedVarFlags(vlflags)), m_pdims(1), m_udims(3), m_packed(pl,pr) {
|
||||
m_unpacked[0].init(u0l, u0r); m_unpacked[1].init(u1l, u1r); m_unpacked[2].init(u2l, u2r); }
|
||||
public:
|
||||
~VerilatedVarProps() {}
|
||||
// METHODS
|
||||
bool magicOk() const { return m_magic==MAGIC; }
|
||||
VerilatedVarType vltype() const { return m_vltype; }
|
||||
VerilatedVarFlags vldir() const {
|
||||
return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR); }
|
||||
vluint32_t entSize() const;
|
||||
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
|
||||
/// DPI compatible C standard layout
|
||||
bool isDpiCLayout() const { return ((m_vlflags & VLVF_DPI_CLAY) != 0); }
|
||||
int udims() const { return m_udims; }
|
||||
int dims() const { return m_pdims + m_udims; }
|
||||
const VerilatedRange& packed() const { return m_packed; }
|
||||
const VerilatedRange& unpacked() const { return m_unpacked[0]; }
|
||||
// DPI accessors
|
||||
int left(int dim) const {
|
||||
return dim==0 ? m_packed.left() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].left() : 0;
|
||||
}
|
||||
int right(int dim) const {
|
||||
return dim==0 ? m_packed.right() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].right() : 0;
|
||||
}
|
||||
int low(int dim) const {
|
||||
return dim==0 ? m_packed.low() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].low() : 0;
|
||||
}
|
||||
int high(int dim) const {
|
||||
return dim==0 ? m_packed.high() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].high() : 0;
|
||||
}
|
||||
int increment(int dim) const {
|
||||
return dim==0 ? m_packed.increment() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].increment() : 0;
|
||||
}
|
||||
int elements(int dim) const {
|
||||
return dim==0 ? m_packed.elements() : VL_LIKELY(dim>=1 && dim<=3) ? m_unpacked[dim-1].elements() : 0;
|
||||
}
|
||||
/// Total size in bytes (note DPI limited to 4GB)
|
||||
size_t totalSize() const;
|
||||
/// Adjust a data pointer to access a given array element, NuLL if something goes bad
|
||||
void* datapAdjustIndex(void* datap, int dim, int indx) const;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator DPI open array variable
|
||||
|
||||
class VerilatedDpiOpenVar {
|
||||
// MEMBERS
|
||||
const VerilatedVarProps* m_propsp; // Variable properties
|
||||
void* m_datap; // Location of data (local to thread always, so safe)
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap)
|
||||
: m_propsp(propsp), m_datap(datap) {}
|
||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
|
||||
: m_propsp(propsp), m_datap(const_cast<void*>(datap)) {}
|
||||
~VerilatedDpiOpenVar() {}
|
||||
// METHODS
|
||||
void* datap() const { return m_datap; }
|
||||
// METHODS - from VerilatedVarProps
|
||||
bool magicOk() const { return m_propsp->magicOk(); }
|
||||
VerilatedVarType vltype() const { return m_propsp->vltype(); }
|
||||
bool isDpiStdLayout() const { return m_propsp->isDpiCLayout(); }
|
||||
const VerilatedRange& packed() const { return m_propsp->packed(); }
|
||||
const VerilatedRange& unpacked() const { return m_propsp->unpacked(); }
|
||||
int udims() const { return m_propsp->udims(); }
|
||||
int left(int dim) const { return m_propsp->left(dim); }
|
||||
int right(int dim) const { return m_propsp->right(dim); }
|
||||
int low(int dim) const { return m_propsp->low(dim); }
|
||||
int high(int dim) const { return m_propsp->high(dim); }
|
||||
int increment(int dim) const { return m_propsp->increment(dim); }
|
||||
int elements(int dim) const { return m_propsp->elements(dim); }
|
||||
size_t totalSize() const { return m_propsp->totalSize(); }
|
||||
void* datapAdjustIndex(void* datap, int dim, int indx) const {
|
||||
return m_propsp->datapAdjustIndex(datap, dim, indx); }
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator variable
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
class VerilatedVar : public VerilatedVarProps {
|
||||
// MEMBERS
|
||||
void* m_datap; // Location of data
|
||||
const char* m_namep; // Name - slowpath
|
||||
protected:
|
||||
friend class VerilatedScope;
|
||||
// CONSTRUCTORS
|
||||
VerilatedVar(const char* namep, void* datap,
|
||||
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
|
||||
: VerilatedVarProps(vltype, vlflags, (dims>0?1:0), ((dims>1)?dims-1:0))
|
||||
, m_datap(datap), m_namep(namep) {}
|
||||
public:
|
||||
~VerilatedVar() {}
|
||||
// ACCESSORS
|
||||
void* datap() const { return m_datap; }
|
||||
const VerilatedRange& range() const { return packed(); } // Deprecated
|
||||
const VerilatedRange& array() const { return unpacked(); } // Deprecated
|
||||
const char* name() const { return m_namep; }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
+12
-59
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -16,12 +16,12 @@
|
||||
/// \file
|
||||
/// \brief Verilator: Include to allow symbol inspection
|
||||
///
|
||||
/// This file is for inclusion by files that need to inspect
|
||||
/// the symbol table. It is not included in verilated.h
|
||||
/// as it requires some heavyweight C++ classes.
|
||||
/// This file is for inclusion by files that need to inspect the symbol
|
||||
/// table. It is not included in verilated.h (instead see
|
||||
/// verilated_sym_props.h) as it requires some heavyweight C++ classes.
|
||||
///
|
||||
/// These classes are thread safe on read only. It is constructed
|
||||
/// only when a model is built (from the main thread).
|
||||
/// These classes are thread safe and read only. It is constructed only
|
||||
/// when a model is built (from the main thread).
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@@ -31,70 +31,22 @@
|
||||
#ifndef _VERILATED_SYMS_H_
|
||||
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated_sym_props.h"
|
||||
|
||||
#include "verilated_heavy.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator range
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
// See also V3Ast::VNumRange
|
||||
class VerilatedRange {
|
||||
int m_left;
|
||||
int m_right;
|
||||
protected:
|
||||
friend class VerilatedVar;
|
||||
friend class VerilatedScope;
|
||||
VerilatedRange() : m_left(0), m_right(0) {}
|
||||
void sets(int left, int right) { m_left=left; m_right=right; }
|
||||
public:
|
||||
~VerilatedRange() {}
|
||||
int left() const { return m_left; }
|
||||
int right() const { return m_right; }
|
||||
int elements() const { return (VL_LIKELY(m_left>=m_right)?(m_left-m_right+1):(m_right-m_left+1)); }
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator variable
|
||||
/// Thread safety: Assume is constructed only with model, then any number of readers
|
||||
|
||||
class VerilatedVar {
|
||||
void* m_datap; // Location of data
|
||||
VerilatedVarType m_vltype; // Data type
|
||||
VerilatedVarFlags m_vlflags; // Direction
|
||||
VerilatedRange m_range; // First range
|
||||
VerilatedRange m_array; // Array
|
||||
int m_dims; // Dimensions
|
||||
const char* m_namep; // Name - slowpath
|
||||
protected:
|
||||
friend class VerilatedScope;
|
||||
VerilatedVar(const char* namep, void* datap,
|
||||
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
|
||||
: m_datap(datap), m_vltype(vltype), m_vlflags(vlflags), m_dims(dims), m_namep(namep) {}
|
||||
public:
|
||||
~VerilatedVar() {}
|
||||
void* datap() const { return m_datap; }
|
||||
VerilatedVarType vltype() const { return m_vltype; }
|
||||
VerilatedVarFlags vldir() const { return static_cast<VerilatedVarFlags>(static_cast<int>(m_vlflags) & VLVF_MASK_DIR); }
|
||||
vluint32_t entSize() const;
|
||||
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
|
||||
const VerilatedRange& range() const { return m_range; }
|
||||
const VerilatedRange& array() const { return m_array; }
|
||||
const char* name() const { return m_namep; }
|
||||
int dims() const { return m_dims; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
/// Types
|
||||
|
||||
/// Class to sort maps keyed by const char*'s
|
||||
struct VerilatedCStrCmp {
|
||||
/// Ordering maps keyed by const char*'s
|
||||
bool operator() (const char *a, const char *b) const {
|
||||
return std::strcmp(a, b) < 0;
|
||||
return std::strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Map of sorted scope names to find associated scope class
|
||||
class VerilatedScopeNameMap
|
||||
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
||||
public:
|
||||
@@ -102,6 +54,7 @@ public:
|
||||
~VerilatedScopeNameMap() {}
|
||||
};
|
||||
|
||||
/// Map of sorted variable names to find associated variable class
|
||||
class VerilatedVarNameMap
|
||||
: public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||
public:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
@@ -61,18 +61,18 @@ private:
|
||||
static Singleton& singleton() { static Singleton s; return s; }
|
||||
public:
|
||||
static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
|
||||
VerilatedLockGuard guard(singleton().s_vcdMutex);
|
||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
||||
singleton().s_vcdVecp.push_back(vcdp);
|
||||
}
|
||||
static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
|
||||
VerilatedLockGuard guard(singleton().s_vcdMutex);
|
||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
||||
VcdVec::iterator pos = find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), vcdp);
|
||||
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
|
||||
}
|
||||
static void flush_all() VL_EXCLUDES(singleton().s_vcdMutex) VL_MT_UNSAFE_ONE {
|
||||
// Thread safety: Although this function is protected by a mutex so perhaps
|
||||
// in the future we can allow tracing in separate threads, vcdp->flush() assumes call from single thread
|
||||
VerilatedLockGuard guard(singleton().s_vcdMutex);
|
||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
||||
for (VcdVec::const_iterator it=singleton().s_vcdVecp.begin(); it!=singleton().s_vcdVecp.end(); ++it) {
|
||||
VerilatedVcd* vcdp = *it;
|
||||
vcdp->flush();
|
||||
@@ -343,7 +343,7 @@ void VerilatedVcd::bufferResize(vluint64_t minsize) {
|
||||
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
||||
m_writep = m_wrBufp + (m_writep - oldbufp);
|
||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||
delete oldbufp; oldbufp=NULL;
|
||||
delete [] oldbufp; oldbufp=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,12 +382,14 @@ void VerilatedVcd::bufferFlush () VL_MT_UNSAFE_ONE {
|
||||
// Simple methods
|
||||
|
||||
void VerilatedVcd::set_time_unit (const char* unitp) {
|
||||
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
|
||||
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)
|
||||
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
|
||||
m_timeUnit = timescaleToDouble(unitp);
|
||||
}
|
||||
|
||||
void VerilatedVcd::set_time_resolution (const char* unitp) {
|
||||
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
|
||||
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)
|
||||
// <<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
|
||||
m_timeRes = timescaleToDouble(unitp);
|
||||
}
|
||||
|
||||
@@ -567,7 +569,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
|
||||
sprintf(buf, " %2d ", bits);
|
||||
decl += buf;
|
||||
if (m_evcd) {
|
||||
sprintf(buf, "<%d", code);
|
||||
sprintf(buf, "<%u", code);
|
||||
decl += buf;
|
||||
} else {
|
||||
decl += stringCode(code);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
@@ -39,6 +39,11 @@ void VerilatedVcdSc::trace (const unsigned int &, const std::string &, const cha
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace( const tp& object, const std::string& name, int width ) {}
|
||||
|
||||
#if (SYSTEMC_VERSION>=20171012)
|
||||
DECL_TRACE_METHOD_A( sc_event )
|
||||
DECL_TRACE_METHOD_A( sc_time )
|
||||
#endif
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_logic )
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2017 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2018 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.
|
||||
//
|
||||
@@ -96,6 +96,11 @@ private:
|
||||
virtual void write_comment (const std::string &);
|
||||
virtual void trace (const unsigned int &, const std::string &, const char **);
|
||||
|
||||
#if (SYSTEMC_VERSION>=20171012)
|
||||
DECL_TRACE_METHOD_A( sc_event )
|
||||
DECL_TRACE_METHOD_A( sc_time )
|
||||
#endif
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_logic )
|
||||
|
||||
+86
-52
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2018 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.
|
||||
@@ -91,7 +91,8 @@ public:
|
||||
t_freeHead = oldp;
|
||||
}
|
||||
// MEMBERS
|
||||
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpio* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
|
||||
inline vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
|
||||
// ACCESSORS
|
||||
virtual const char* name() const { return "<null>"; }
|
||||
@@ -117,7 +118,8 @@ public:
|
||||
m_cbData.value = &m_value;
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiCallback; }
|
||||
vluint32_t reason() const { return m_cbData.reason; }
|
||||
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
|
||||
@@ -130,7 +132,8 @@ class VerilatedVpioConst : public VerilatedVpio {
|
||||
public:
|
||||
explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
|
||||
virtual ~VerilatedVpioConst() {}
|
||||
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioConst* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiUndefined; }
|
||||
vlsint32_t num() const { return m_num; }
|
||||
};
|
||||
@@ -141,7 +144,8 @@ class VerilatedVpioRange : public VerilatedVpio {
|
||||
public:
|
||||
explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiRange; }
|
||||
virtual vluint32_t size() const { return m_range->elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return m_range; }
|
||||
@@ -164,7 +168,8 @@ public:
|
||||
explicit VerilatedVpioScope(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep) {}
|
||||
virtual ~VerilatedVpioScope() {}
|
||||
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioScope* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiScope; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
virtual const char* name() const { return m_scopep->name(); }
|
||||
@@ -185,20 +190,21 @@ protected:
|
||||
vlsint32_t m_index;
|
||||
const VerilatedRange& get_range() const {
|
||||
// Determine number of dimensions and return outermost
|
||||
return (m_varp->dims()>1) ? m_varp->array() : m_varp->range();
|
||||
return (m_varp->dims()>1) ? m_varp->unpacked() : m_varp->packed();
|
||||
}
|
||||
public:
|
||||
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
|
||||
: m_varp(varp), m_scopep(scopep), m_index(0) {
|
||||
m_prevDatap = NULL;
|
||||
m_mask.u32 = VL_MASK_I(varp->range().elements());
|
||||
m_mask.u32 = VL_MASK_I(varp->packed().elements());
|
||||
m_entSize = varp->entSize();
|
||||
m_varDatap = varp->datap();
|
||||
}
|
||||
virtual ~VerilatedVpioVar() {
|
||||
if (m_prevDatap) { delete [] m_prevDatap; m_prevDatap = NULL; }
|
||||
}
|
||||
static inline VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVar*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioVar* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioVar*>((VerilatedVpio*)h); }
|
||||
const VerilatedVar* varp() const { return m_varp; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
vluint32_t mask() const { return m_mask.u32; }
|
||||
@@ -236,10 +242,11 @@ public:
|
||||
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
|
||||
}
|
||||
virtual ~VerilatedVpioMemoryWord() {}
|
||||
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiMemoryWord; }
|
||||
virtual vluint32_t size() const { return varp()->range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
|
||||
virtual vluint32_t size() const { return varp()->packed().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &(varp()->packed()); }
|
||||
virtual const char* fullname() const {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
@@ -256,7 +263,8 @@ public:
|
||||
explicit VerilatedVpioVarIter(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep), m_started(false) { }
|
||||
virtual ~VerilatedVpioVarIter() {}
|
||||
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioVarIter* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
@@ -281,12 +289,16 @@ class VerilatedVpioMemoryWordIter : public VerilatedVpio {
|
||||
bool m_done;
|
||||
public:
|
||||
VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp)
|
||||
: m_handle(handle), m_varp(varp), m_iteration(varp->array().right()), m_direction(VL_LIKELY(varp->array().left()>varp->array().right())?1:-1), m_done(false) { }
|
||||
: m_handle(handle), m_varp(varp), m_iteration(varp->unpacked().right()),
|
||||
m_direction(VL_LIKELY(varp->unpacked().left() > varp->unpacked().right())
|
||||
? 1 : -1),
|
||||
m_done(false) { }
|
||||
virtual ~VerilatedVpioMemoryWordIter() {}
|
||||
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
|
||||
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
void iterationInc() {
|
||||
if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction;
|
||||
if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration+=m_direction;
|
||||
}
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
vpiHandle result;
|
||||
@@ -337,7 +349,9 @@ public:
|
||||
varop->createPrevDatap();
|
||||
}
|
||||
}
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large");
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) {
|
||||
VL_FATAL_MT(__FILE__,__LINE__,"", "vpi bb reason too large");
|
||||
}
|
||||
s_s.m_cbObjLists[vop->reason()].push_back(vop);
|
||||
}
|
||||
static void cbTimedAdd(VerilatedVpioCb* vop) {
|
||||
@@ -459,11 +473,12 @@ public:
|
||||
m_errorInfo.level = level;
|
||||
return this;
|
||||
}
|
||||
void setMessage(std::string file, PLI_INT32 line, std::string message, ...) {
|
||||
void setMessage(std::string file, PLI_INT32 line, const char* message, ...) {
|
||||
// message cannot be a const string& as va_start cannot use a reference
|
||||
static VL_THREAD_LOCAL std::string filehold;
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
VL_VSNPRINTF(m_buff, sizeof(m_buff), message.c_str(), args);
|
||||
VL_VSNPRINTF(m_buff, sizeof(m_buff), message, args);
|
||||
va_end(args);
|
||||
m_errorInfo.state = vpiPLI;
|
||||
filehold = file;
|
||||
@@ -921,7 +936,8 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
|
||||
QData time = 0;
|
||||
if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
|
||||
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time);
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n",cb_data_p->reason,vop,time););
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb %d %p delay=%" VL_PRI64 "u\n",
|
||||
cb_data_p->reason, vop, time););
|
||||
VerilatedVpiImp::cbTimedAdd(vop);
|
||||
return vop->castVpiHandle();
|
||||
}
|
||||
@@ -1015,15 +1031,17 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
|
||||
_VL_VPI_ERROR_RESET(); // reset vpi error status
|
||||
if (VL_LIKELY(varop)) {
|
||||
if (varop->varp()->dims()<2) return 0;
|
||||
if (VL_LIKELY(varop->varp()->array().left() >= varop->varp()->array().right())) {
|
||||
if (VL_UNLIKELY(indx > varop->varp()->array().left() || indx < varop->varp()->array().right())) return 0;
|
||||
if (VL_LIKELY(varop->varp()->unpacked().left() >= varop->varp()->unpacked().right())) {
|
||||
if (VL_UNLIKELY(indx > varop->varp()->unpacked().left()
|
||||
|| indx < varop->varp()->unpacked().right())) return 0;
|
||||
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
|
||||
indx - varop->varp()->array().right()))
|
||||
indx - varop->varp()->unpacked().right()))
|
||||
->castVpiHandle();
|
||||
} else {
|
||||
if (VL_UNLIKELY(indx < varop->varp()->array().left() || indx > varop->varp()->array().right())) return 0;
|
||||
if (VL_UNLIKELY(indx < varop->varp()->unpacked().left()
|
||||
|| indx > varop->varp()->unpacked().right())) return 0;
|
||||
return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx,
|
||||
indx - varop->varp()->array().left()))
|
||||
indx - varop->varp()->unpacked().left()))
|
||||
->castVpiHandle();
|
||||
}
|
||||
} else {
|
||||
@@ -1206,7 +1224,8 @@ void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
|
||||
// value processing
|
||||
|
||||
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination
|
||||
// Maximum required size is for binary string, one byte per bit plus null termination
|
||||
static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32];
|
||||
// cppcheck-suppress variableScope
|
||||
static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1;
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n",object););
|
||||
@@ -1235,7 +1254,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().elements());
|
||||
int words = VL_WORDS_I(vop->varp()->packed().elements());
|
||||
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
|
||||
VL_FATAL_MT(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
|
||||
}
|
||||
@@ -1268,14 +1287,16 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int bits = vop->varp()->range().elements();
|
||||
int bits = vop->varp()->packed().elements();
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (bits > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
bits = outStrSz;
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
|
||||
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits);
|
||||
}
|
||||
for (i=0; i<bits; ++i) {
|
||||
char val = (datap[i>>3]>>(i&7))&1;
|
||||
@@ -1286,7 +1307,8 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
}
|
||||
default:
|
||||
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname());
|
||||
return;
|
||||
}
|
||||
} else if (value_p->format == vpiOctStrVal) {
|
||||
@@ -1297,14 +1319,16 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+2)/3;
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
int chars = (vop->varp()->packed().elements()+2)/3;
|
||||
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (chars > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
|
||||
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
|
||||
chars = outStrSz;
|
||||
}
|
||||
for (i=0; i<chars; ++i) {
|
||||
@@ -1320,7 +1344,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
if (i==(chars-1)) {
|
||||
// most signifcant char, mask off non existant bits when vector
|
||||
// size is not a multiple of 3
|
||||
unsigned int rem = vop->varp()->range().elements() % 3;
|
||||
unsigned int rem = vop->varp()->packed().elements() % 3;
|
||||
if (rem) {
|
||||
// generate bit mask & zero non existant bits
|
||||
val &= (1<<rem)-1;
|
||||
@@ -1363,13 +1387,15 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+3)>>2;
|
||||
int chars = (vop->varp()->packed().elements()+3)>>2;
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (chars > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
|
||||
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars);
|
||||
chars = outStrSz;
|
||||
}
|
||||
for (i=0; i<chars; ++i) {
|
||||
@@ -1377,7 +1403,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
if (i==(chars-1)) {
|
||||
// most signifcant char, mask off non existant bits when vector
|
||||
// size is not a multiple of 4
|
||||
unsigned int rem = vop->varp()->range().elements() & 3;
|
||||
unsigned int rem = vop->varp()->packed().elements() & 3;
|
||||
if (rem) {
|
||||
// generate bit mask & zero non existant bits
|
||||
val &= (1<<rem)-1;
|
||||
@@ -1401,12 +1427,13 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (bytes > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s"
|
||||
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes);
|
||||
bytes = outStrSz;
|
||||
@@ -1478,7 +1505,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n",
|
||||
vop->varp()->datap(), vop->varDatap()););
|
||||
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: ", vop->fullname());
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only,"
|
||||
" use public_flat_rw instead: ",
|
||||
vop->fullname());
|
||||
return 0;
|
||||
}
|
||||
if (value_p->format == vpiVectorVal) {
|
||||
@@ -1494,7 +1523,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
*(reinterpret_cast<IData*>(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
|
||||
return object;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().elements());
|
||||
int words = VL_WORDS_I(vop->varp()->packed().elements());
|
||||
WDataOutP datap = (reinterpret_cast<IData*>(vop->varDatap()));
|
||||
for (int i=0; i<words; ++i) {
|
||||
datap[i] = value_p->value.vector[i].aval;
|
||||
@@ -1523,7 +1552,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int bits = vop->varp()->range().elements();
|
||||
int bits = vop->varp()->packed().elements();
|
||||
int len = strlen(value_p->value.str);
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
for (int i=0; i<bits; ++i) {
|
||||
@@ -1550,8 +1579,8 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+2)/3;
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
int chars = (vop->varp()->packed().elements()+2)/3;
|
||||
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
|
||||
int len = strlen(value_p->value.str);
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
div_t idx;
|
||||
@@ -1615,7 +1644,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
}
|
||||
if (success > 1) {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s",
|
||||
VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
|
||||
VL_FUNC, remainder, value_p->value.str,
|
||||
VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname());
|
||||
}
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8 : *(reinterpret_cast<CData*>(vop->varDatap())) = val & vop->mask(); break;
|
||||
@@ -1637,7 +1668,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+3)>>2;
|
||||
int chars = (vop->varp()->packed().elements()+3)>>2;
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
char* val = value_p->value.str;
|
||||
// skip hex ident if one is detected at the start of the string
|
||||
@@ -1655,7 +1686,9 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10;
|
||||
else {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non hex character '%c' in '%s' as value %s for %s",
|
||||
VL_FUNC, digit, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
|
||||
VL_FUNC, digit, value_p->value.str,
|
||||
VerilatedVpiError::strFromVpiVal(value_p->format),
|
||||
vop->fullname());
|
||||
hex = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -1684,11 +1717,12 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_UINT32:
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
int bytes = VL_BYTES_I(vop->varp()->packed().elements());
|
||||
int len = strlen(value_p->value.str);
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
for (int i=0; i<bytes; ++i) {
|
||||
datap[i] = (i < len)?value_p->value.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes
|
||||
// prepend with 0 values before placing string the least signifcant bytes
|
||||
datap[i] = (i < len)?value_p->value.str[len-i-1]:0;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2018 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.
|
||||
|
||||
+38
-1
@@ -1,7 +1,7 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -353,6 +353,43 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# define VL_ROUND(n) round(n)
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
// Performance counters
|
||||
|
||||
/// The vluint64_t argument is loaded with a high-performance counter for profiling
|
||||
/// or 0x0 if not implemeted on this platform
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# define VL_RDTSC(val) { \
|
||||
vluint32_t hi, lo; \
|
||||
asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); \
|
||||
(val) = ((vluint64_t)lo) | (((vluint64_t)hi)<<32); \
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
# define VL_RDTSC(val) asm volatile("mrs %[rt],PMCCNTR_EL0" : [rt] "=r" (val));
|
||||
#else
|
||||
// We just silently ignore unknown OSes, as only leads to missing statistics
|
||||
# define VL_RDTSC(val) (val) = 0;
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
// Threading related OS-specific functions
|
||||
|
||||
#if VL_THREADED
|
||||
# if defined(__i386__) || defined(__x86_64__)
|
||||
/// For more efficient busy waiting on SMT CPUs, let the processor know
|
||||
/// we're just waiting so it can let another thread run
|
||||
# define VL_CPU_RELAX() asm volatile("rep; nop" ::: "memory")
|
||||
# elif defined(__ia64__)
|
||||
# define VL_CPU_RELAX() asm volatile("hint @pause" ::: "memory")
|
||||
# elif defined(__aarch64__)
|
||||
# define VL_CPU_RELAX() asm volatile("yield" ::: "memory")
|
||||
# elif defined(__powerpc64__)
|
||||
# define VL_CPU_RELAX() asm volatile("or 1, 1, 1; or 2, 2, 2;" ::: "memory")
|
||||
# else
|
||||
# error "Missing VL_CPU_RELAX() definition. Or, don't use VL_THREADED"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
|
||||
#endif /*guard*/
|
||||
|
||||
+22
-22
@@ -7,7 +7,7 @@
|
||||
* This file contains the constant definitions, structure definitions,
|
||||
* and routine declarations used by SystemVerilog DPI.
|
||||
*
|
||||
* This file is from the SystemVerilog IEEE 1800-2012 Annex I.
|
||||
* This file is from the SystemVerilog IEEE 1800-2017 Annex I.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SVDPI
|
||||
@@ -117,7 +117,7 @@ typedef uint32_t svBitVecVal;
|
||||
/*
|
||||
* Return implementation version information string ("1800-2005" or "SV3.1a").
|
||||
*/
|
||||
XXTERN const char* svDpiVersion();
|
||||
XXTERN const char* svDpiVersion( void );
|
||||
|
||||
/* a handle to a scope (an instance of a module or interface) */
|
||||
XXTERN typedef void* svScope;
|
||||
@@ -155,7 +155,7 @@ XXTERN void svGetPartselBit(svBitVecVal* d, const svBitVecVal* s, int i, int w);
|
||||
XXTERN void svGetPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
|
||||
|
||||
XXTERN void svPutPartselBit(svBitVecVal* d, const svBitVecVal s, int i, int w);
|
||||
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal* s, int i, int w);
|
||||
XXTERN void svPutPartselLogic(svLogicVecVal* d, const svLogicVecVal s, int i, int w);
|
||||
|
||||
/*
|
||||
* Open array querying functions
|
||||
@@ -241,28 +241,28 @@ XXTERN void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s
|
||||
XXTERN void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2, int indx3);
|
||||
|
||||
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
int indx3);
|
||||
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
int indx3);
|
||||
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
...);
|
||||
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
|
||||
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
|
||||
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
int indx2);
|
||||
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
int indx2, int indx3);
|
||||
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
|
||||
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
|
||||
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
|
||||
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
|
||||
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
int indx2);
|
||||
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
int indx2, int indx3);
|
||||
|
||||
/* Functions for working with DPI context */
|
||||
@@ -273,7 +273,7 @@ XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1
|
||||
* is the scope of the function's declaration site, not call site.
|
||||
* Returns NULL if called from C code that is *not* an imported function.
|
||||
*/
|
||||
XXTERN svScope svGetScope();
|
||||
XXTERN svScope svGetScope( void );
|
||||
|
||||
/*
|
||||
* Set context for subsequent export function execution.
|
||||
@@ -337,7 +337,7 @@ XXTERN int svGetCallerInfo(const char** fileName, int *lineNumber);
|
||||
* Returns 1 if the current execution thread is in the disabled state.
|
||||
* Disable protocol must be adhered to if in the disabled state.
|
||||
*/
|
||||
XXTERN int svIsDisabledState();
|
||||
XXTERN int svIsDisabledState( void );
|
||||
|
||||
/*
|
||||
* Imported functions call this API function during disable processing to
|
||||
@@ -345,7 +345,7 @@ XXTERN int svIsDisabledState();
|
||||
* This function must be called before returning from an imported function that is
|
||||
* in the disabled state.
|
||||
*/
|
||||
XXTERN void svAckDisabledState();
|
||||
XXTERN void svAckDisabledState( void );
|
||||
|
||||
/*
|
||||
**********************************************************
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* vpi_user.h
|
||||
*
|
||||
* IEEE Std 1800-2012 Programming Language Interface (PLI)
|
||||
* IEEE Std 1800-2017 Programming Language Interface (PLI)
|
||||
*
|
||||
* This file contains the constant definitions, structure definitions, and
|
||||
* routine declarations used by the SystemVerilog Verification Procedural
|
||||
@@ -251,7 +251,7 @@ typedef PLI_UINT32 *vpiHandle;
|
||||
#define vpiModPathOut 96 /* output terminal of a module path */
|
||||
#define vpiOperand 97 /* operand of expression */
|
||||
#define vpiPortInst 98 /* connected port instance */
|
||||
#define vpiProcess 99 /* process in module */
|
||||
#define vpiProcess 99 /* process in module, program or interface */
|
||||
#define vpiVariables 100 /* variables in module */
|
||||
#define vpiUse 101 /* usage */
|
||||
|
||||
@@ -978,7 +978,7 @@ XXTERN vpiHandle vpi_handle_by_multi_index PROTO_PARAMS((vpiHandle obj,
|
||||
|
||||
/****************************** GLOBAL VARIABLES ******************************/
|
||||
|
||||
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])();
|
||||
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])( void );
|
||||
|
||||
/* array of function pointers, last pointer should be null */
|
||||
|
||||
|
||||
+2
-2
@@ -749,7 +749,7 @@ File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
=item 2.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see L<TESTING>.
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see L</TESTING>.
|
||||
|
||||
=item 3.
|
||||
|
||||
@@ -785,7 +785,7 @@ in C<src/Makefile_obj.in> and reconfigure.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2008-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2018 by Wilson Snyder. This package is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2018 by Wilson Snyder. This package is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2018 by Wilson Snyder. This package is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
Executable
+177
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/perl -w
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use Getopt::Long;
|
||||
#use Data::Dumper; $Data::Dumper::Indent=1; $Data::Dumper::Sortkeys=1; #Debug
|
||||
use IO::File;
|
||||
use IO::Dir;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw ($Debug);
|
||||
|
||||
our $VERSION = '0.001';
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config ("no_auto_abbrev");
|
||||
if (! GetOptions (
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"help" => sub { print "Version $VERSION\n";
|
||||
pod2usage(-verbose=>2, -exitval => 2, output=>\*STDOUT, -noperldoc=>1); },
|
||||
"version" => sub { print "Version $VERSION\n"; exit(0); },
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'git_untabify --help'\n";
|
||||
}
|
||||
|
||||
read_patch();
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub read_patch {
|
||||
my $filename = undef;
|
||||
my $lineno = 0;
|
||||
my $editlines = {};
|
||||
while (defined(my $line = <STDIN>)) {
|
||||
if ($line =~ m!^\+\+\+ b/(.*)!) {
|
||||
edit_file($filename, $editlines);
|
||||
$filename = $1;
|
||||
$lineno = 0;
|
||||
$editlines = {};
|
||||
print "FILE $filename\n" if $Debug;
|
||||
}
|
||||
elsif ($line =~ m!^@@ -?[0-9]+,?[0-9]* \+?([0-9]+)!) {
|
||||
$lineno = $1 - 1;
|
||||
print " LINE $1 $line" if $Debug;
|
||||
}
|
||||
elsif ($line =~ m!^ !) {
|
||||
++$lineno;
|
||||
}
|
||||
elsif ($line =~ m!^\+!) {
|
||||
++$lineno;
|
||||
if ($line =~ m!\t!) {
|
||||
print " $lineno: $line" if $Debug;
|
||||
$editlines->{$lineno} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
edit_file($filename, $editlines);
|
||||
}
|
||||
|
||||
sub edit_file {
|
||||
my $filename = shift;
|
||||
my $editlines = shift;
|
||||
|
||||
return if (scalar keys(%$editlines) < 1);
|
||||
if (ignore($filename)) {
|
||||
print "%Warning: Ignoring $filename\n";
|
||||
return;
|
||||
}
|
||||
print "Edit $filename ",join(",",sort(keys %$editlines)),"\n";
|
||||
|
||||
my $lineno = 0;
|
||||
my @out;
|
||||
{
|
||||
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
++$lineno;
|
||||
if ($editlines->{$lineno}) {
|
||||
print $line;
|
||||
push @out, untabify($line);
|
||||
} else {
|
||||
push @out, $line;
|
||||
}
|
||||
}
|
||||
$fh->close;
|
||||
}
|
||||
{
|
||||
my $fh = IO::File->new(">${filename}.untab") or die "%Error: $! ${filename}.untab,";
|
||||
$fh->print(join('',@out));
|
||||
$fh->close;
|
||||
|
||||
my ($dev,$ino,$mode) = stat($filename);
|
||||
chmod $mode, "${filename}.untab";
|
||||
}
|
||||
|
||||
rename("${filename}.untab", $filename) or die "%Error: $! ${filename}.untab,";
|
||||
}
|
||||
|
||||
sub ignore {
|
||||
my $filename = shift;
|
||||
return 1 if ($filename =~ /(Makefile|\.mk)/);
|
||||
return 1 if ($filename =~ /\.(y|l|out|vcd)$/);
|
||||
#
|
||||
return 0 if ($filename =~ /\.(sv|v|vh|svh|h|vc|cpp|pl)$/);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub untabify {
|
||||
my $line = shift;
|
||||
my $out = "";
|
||||
my $col = 0;
|
||||
foreach my $c (split //, $line) {
|
||||
if ($c eq "\t") {
|
||||
my $destcol = int(($col+8)/8)*8;
|
||||
while ($col < $destcol) { ++$col; $out .= " "; }
|
||||
} else {
|
||||
$out .= $c;
|
||||
$col++;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
git_untabify - Pipe a git diff report and untabify differences
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
git diff a..b | git_untabify
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Take a patch file, and edit the files in the destination patch list to
|
||||
untabify the related patch lines.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item --version
|
||||
|
||||
Displays program version and exits.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./git_untabify "
|
||||
### End:
|
||||
+4
-4
@@ -100,14 +100,14 @@ sub write_verilog {
|
||||
my $fh = IO::File->new(">$dir/foo.cpp");
|
||||
$fh->print('#include "Vfoo.h"' ,"\n");
|
||||
$fh->print('unsigned int main_time = 0;' ,"\n");
|
||||
$fh->print('double sc_time_stamp () {' ,"\n");
|
||||
$fh->print('double sc_time_stamp() {' ,"\n");
|
||||
$fh->print(' return main_time;' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
$fh->print('int main() {' ,"\n");
|
||||
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
|
||||
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
|
||||
$fh->print(' top->eval();' ,"\n");
|
||||
$fh->print(' main_time++;' ,"\n");
|
||||
$fh->print(' top->eval();' ,"\n");
|
||||
$fh->print(' main_time++;' ,"\n");
|
||||
$fh->print(' }' ,"\n");
|
||||
$fh->print(' top->final();' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
@@ -184,7 +184,7 @@ Runs a specific test stage (see the script).
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2009-2017 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2009-2018 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2018 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2007-2017 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2007-2018 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
@@ -8,7 +8,7 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
eval `modulecmd perl add cds-ius/latest`;
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
@@ -28,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2018 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add synopsys-sim`;
|
||||
eval `modulecmd perl add synopsys-sim/latest`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
@@ -28,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2018 by Wilson Snyder. This package is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2017 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2018 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# DESCRIPTION: Verilator: GDB startup file with useful defines
|
||||
#
|
||||
# Copyright 2012-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2012-2018 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.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2018 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.
|
||||
|
||||
+8
-4
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -174,11 +174,13 @@ private:
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
if (m_check == CT_INITIAL) {
|
||||
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
|
||||
nodep->v3warn(INITIALDLY, "Delayed assignments (<=) in initial"
|
||||
" or final block; suggest blocking assignments (=).");
|
||||
} else if (m_check == CT_LATCH) {
|
||||
// Suppress. Shouldn't matter that the interior of the latch races
|
||||
} else {
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
nodep->v3warn(COMBDLY, "Delayed assignments (<=) in non-clocked"
|
||||
" (non flop or latch) block; suggest blocking assignments (=).");
|
||||
}
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
@@ -437,6 +439,8 @@ public:
|
||||
|
||||
void V3Active::activeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ActiveVisitor visitor (nodep);
|
||||
{
|
||||
ActiveVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+4
-2
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -159,6 +159,8 @@ public:
|
||||
|
||||
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ActiveTopVisitor visitor (nodep);
|
||||
{
|
||||
ActiveTopVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+35
-10
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2018 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.
|
||||
@@ -88,11 +88,17 @@ private:
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
|
||||
// Like newFireAssert() but omits the asserts-on check
|
||||
AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
|
||||
AstNode* bodysp = dispp;
|
||||
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
|
||||
bodysp->addNext(new AstStop (nodep->fileline()));
|
||||
return bodysp;
|
||||
}
|
||||
|
||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||
AstNode* bodysp = newFireAssertUnchecked(nodep, message);
|
||||
bodysp = newIfAssertOn(bodysp);
|
||||
return bodysp;
|
||||
}
|
||||
@@ -105,7 +111,9 @@ private:
|
||||
//
|
||||
AstNode* bodysp = NULL;
|
||||
bool selfDestruct = false;
|
||||
AstIf* ifp = NULL;
|
||||
if (AstPslCover* snodep = nodep->castPslCover()) {
|
||||
++m_statAsCover;
|
||||
if (!v3Global.opt.coverageUser()) {
|
||||
selfDestruct = true;
|
||||
} else {
|
||||
@@ -116,14 +124,30 @@ private:
|
||||
if (message!="") covincp->declp()->comment(message);
|
||||
bodysp = covincp;
|
||||
}
|
||||
|
||||
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
|
||||
ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
|
||||
bodysp = ifp;
|
||||
|
||||
} else if (nodep->castPslAssert()) {
|
||||
++m_statAsPsl;
|
||||
// Insert an automatic error message and $stop after
|
||||
// any user-supplied statements.
|
||||
AstNode* autoMsgp = newFireAssertUnchecked(nodep, "'assert property' failed.");
|
||||
if (stmtsp) {
|
||||
stmtsp->addNext(autoMsgp);
|
||||
} else {
|
||||
stmtsp = autoMsgp;
|
||||
}
|
||||
ifp = new AstIf(nodep->fileline(), propp, NULL, stmtsp);
|
||||
// It's more LIKELY that we'll take the NULL if clause
|
||||
// than the sim-killing else clause:
|
||||
ifp->branchPred(AstBranchPred::BP_LIKELY);
|
||||
bodysp = newIfAssertOn(ifp);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Unknown node type");
|
||||
}
|
||||
if (bodysp && stmtsp) bodysp = bodysp->addNext(stmtsp);
|
||||
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
|
||||
bodysp = ifp;
|
||||
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
//
|
||||
|
||||
AstNode* newp = new AstAlways (nodep->fileline(),
|
||||
VAlwaysKwd::ALWAYS,
|
||||
sentreep,
|
||||
@@ -294,12 +318,11 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstPslCover* nodep) {
|
||||
virtual void visit(AstNodePslCoverOrAssert* nodep) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||
nodep->stmtsp(), nodep->name()); VL_DANGLING(nodep);
|
||||
++m_statAsCover;
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep) {
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -349,6 +372,8 @@ public:
|
||||
|
||||
void V3Assert::assertAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
AssertVisitor visitor (nodep);
|
||||
{
|
||||
AssertVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2018 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.
|
||||
|
||||
+5
-3
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2018 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.
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstPslCover* nodep) {
|
||||
virtual void visit(AstNodePslCoverOrAssert* nodep) {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
clearAssertInfo();
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -136,6 +136,8 @@ public:
|
||||
|
||||
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
AssertPreVisitor visitor (nodep);
|
||||
{
|
||||
AssertPreVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2018 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.
|
||||
|
||||
+33
-22
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -229,7 +229,8 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
|
||||
// Called on all major tree changers.
|
||||
// Only for use for those really nasty bugs relating to internals
|
||||
// Note this may be null.
|
||||
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
|
||||
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "
|
||||
// <<prefix<<": "<<(void*)this<<" <e"<<AstNode::s_editCntGbl<<">"<<endl;
|
||||
//if (debug()) {
|
||||
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
||||
// // Commenting out the section below may crash, as the tree state
|
||||
@@ -290,8 +291,8 @@ void AstNode::addNextHere(AstNode* newp) {
|
||||
// This could be at head, tail, or both (single)
|
||||
// New could be head of single node, or list
|
||||
UDEBUGONLY(UASSERT(dynamic_cast<AstNode*>(this),"this should not be NULL"););
|
||||
UASSERT(newp,"Null item passed to addNext");
|
||||
UASSERT(newp->backp()==NULL,"New node (back) already assigned?");
|
||||
UASSERT(newp, "Null item passed to addNext");
|
||||
UASSERT(!newp->backp(), "New node (back) already assigned?");
|
||||
this->debugTreeChange("-addHereThs: ", __LINE__, false);
|
||||
newp->debugTreeChange("-addHereNew: ", __LINE__, true);
|
||||
newp->editCountInc();
|
||||
@@ -334,7 +335,7 @@ void AstNode::addNextHere(AstNode* newp) {
|
||||
}
|
||||
|
||||
void AstNode::setOp1p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to setOp1p\n");
|
||||
UASSERT(newp, "Null item passed to setOp1p");
|
||||
UDEBUGONLY(if (m_op1p) this->v3fatalSrc("Adding to non-empty, non-list op1"););
|
||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1"););
|
||||
@@ -347,7 +348,7 @@ void AstNode::setOp1p(AstNode* newp) {
|
||||
}
|
||||
|
||||
void AstNode::setOp2p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to setOp2p\n");
|
||||
UASSERT(newp, "Null item passed to setOp2p");
|
||||
UDEBUGONLY(if (m_op2p) this->v3fatalSrc("Adding to non-empty, non-list op2"););
|
||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2"););
|
||||
@@ -360,7 +361,7 @@ void AstNode::setOp2p(AstNode* newp) {
|
||||
}
|
||||
|
||||
void AstNode::setOp3p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to setOp3p\n");
|
||||
UASSERT(newp, "Null item passed to setOp3p");
|
||||
UDEBUGONLY(if (m_op3p) this->v3fatalSrc("Adding to non-empty, non-list op3"););
|
||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3"););
|
||||
@@ -373,7 +374,7 @@ void AstNode::setOp3p(AstNode* newp) {
|
||||
}
|
||||
|
||||
void AstNode::setOp4p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to setOp4p\n");
|
||||
UASSERT(newp, "Null item passed to setOp4p");
|
||||
UDEBUGONLY(if (m_op4p) this->v3fatalSrc("Adding to non-empty, non-list op4"););
|
||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4"););
|
||||
@@ -386,25 +387,25 @@ void AstNode::setOp4p(AstNode* newp) {
|
||||
}
|
||||
|
||||
void AstNode::addOp1p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to addOp1p\n");
|
||||
UASSERT(newp, "Null item passed to addOp1p");
|
||||
if (!m_op1p) { op1p(newp); }
|
||||
else { m_op1p->addNext(newp); }
|
||||
}
|
||||
|
||||
void AstNode::addOp2p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to addOp2p\n");
|
||||
UASSERT(newp, "Null item passed to addOp2p");
|
||||
if (!m_op2p) { op2p(newp); }
|
||||
else { m_op2p->addNext(newp); }
|
||||
}
|
||||
|
||||
void AstNode::addOp3p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to addOp3p\n");
|
||||
UASSERT(newp, "Null item passed to addOp3p");
|
||||
if (!m_op3p) { op3p(newp); }
|
||||
else { m_op3p->addNext(newp); }
|
||||
}
|
||||
|
||||
void AstNode::addOp4p(AstNode* newp) {
|
||||
UASSERT(newp,"Null item passed to addOp4p\n");
|
||||
UASSERT(newp, "Null item passed to addOp4p");
|
||||
if (!m_op4p) { op4p(newp); }
|
||||
else { m_op4p->addNext(newp); }
|
||||
}
|
||||
@@ -430,7 +431,7 @@ void AstNRelinker::dump(ostream& str) const {
|
||||
AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) {
|
||||
this->debugTreeChange("-unlinkWNextThs: ", __LINE__, true);
|
||||
AstNode* oldp = this;
|
||||
UASSERT(oldp->m_backp,"Node has no back, already unlinked?\n");
|
||||
UASSERT(oldp->m_backp, "Node has no back, already unlinked?");
|
||||
oldp->editCountInc();
|
||||
AstNode* backp = oldp->m_backp;
|
||||
if (linkerp) {
|
||||
@@ -478,7 +479,7 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) {
|
||||
AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) {
|
||||
this->debugTreeChange("-unlinkFrBkThs: ", __LINE__, true);
|
||||
AstNode* oldp = this;
|
||||
UASSERT(oldp->m_backp,"Node has no back, already unlinked?\n");
|
||||
UASSERT(oldp->m_backp, "Node has no back, already unlinked?");
|
||||
oldp->editCountInc();
|
||||
AstNode* backp = oldp->m_backp;
|
||||
if (linkerp) {
|
||||
@@ -530,8 +531,8 @@ AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) {
|
||||
void AstNode::relink(AstNRelinker* linkerp) {
|
||||
if (debug()>8) { UINFO(0," EDIT: relink: "); dumpPtrs(); }
|
||||
AstNode* newp = this;
|
||||
UASSERT(linkerp && linkerp->m_backp, "Need non-empty linker\n");
|
||||
UASSERT(newp->backp()==NULL, "New node already linked?\n");
|
||||
UASSERT(linkerp && linkerp->m_backp, "Need non-empty linker");
|
||||
UASSERT(!newp->backp(), "New node already linked?");
|
||||
newp->editCountInc();
|
||||
|
||||
if (debug()>8) { linkerp->dump(cout); cout<<endl; }
|
||||
@@ -667,7 +668,7 @@ AstNode* AstNode::cloneTree(bool cloneNextLink) {
|
||||
|
||||
void AstNode::deleteNode() {
|
||||
// private: Delete single node. Publicly call deleteTree() instead.
|
||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||
UASSERT(!m_backp, "Delete called on node with backlink still set");
|
||||
editCountInc();
|
||||
// Change links of old node so we coredump if used
|
||||
this->m_nextp = (AstNode*)1;
|
||||
@@ -677,9 +678,17 @@ void AstNode::deleteNode() {
|
||||
this->m_op2p = (AstNode*)1;
|
||||
this->m_op3p = (AstNode*)1;
|
||||
this->m_op4p = (AstNode*)1;
|
||||
if (
|
||||
#if !defined(VL_DEBUG) || defined(VL_LEAK_CHECKS)
|
||||
delete this; // Leak massively, so each pointer is unique and we can debug easier
|
||||
1
|
||||
#else
|
||||
!v3Global.opt.debugLeak()
|
||||
#endif
|
||||
) {
|
||||
delete this;
|
||||
}
|
||||
// Else leak massively, so each pointer is unique
|
||||
// and we can debug easier.
|
||||
}
|
||||
|
||||
AstNode::~AstNode() {
|
||||
@@ -704,7 +713,7 @@ void AstNode::deleteTreeIter() {
|
||||
void AstNode::deleteTree() {
|
||||
// deleteTree always deletes the next link, because you must have called
|
||||
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
|
||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||
UASSERT(!m_backp, "Delete called on node with backlink still set");
|
||||
this->debugTreeChange("-delTree: ", __LINE__, true);
|
||||
this->editCountInc();
|
||||
// MUST be depth first!
|
||||
@@ -779,7 +788,9 @@ void AstNode::iterateAndNext(AstNVisitor& v) {
|
||||
niterp->m_iterpp = &niterp;
|
||||
niterp->accept(v);
|
||||
// accept may do a replaceNode and change niterp on us...
|
||||
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep<<" now into "<<(void*)niterp<<endl); // niterp maybe NULL, so need cast
|
||||
// niterp maybe NULL, so need cast if printing
|
||||
//if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<(void*)nodep
|
||||
// <<" now into "<<(void*)niterp<<endl);
|
||||
if (!niterp) return; // Perhaps node deleted inside accept
|
||||
niterp->m_iterpp = NULL;
|
||||
if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept
|
||||
@@ -1037,8 +1048,8 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
||||
if (doDump) {
|
||||
{ // Write log & close
|
||||
UINFO(2,"Dumping "<<filename<<endl);
|
||||
const vl_unique_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
const vl_unique_ptr<std::ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||
if (logsp->fail()) v3fatal("Can't write "<<filename);
|
||||
*logsp<<"Verilator Tree Dump (format 0x3900) from <e"<<dec<<editCountLast()<<">";
|
||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||
if (editCountGbl()==editCountLast()
|
||||
|
||||
+96
-43
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -167,7 +167,7 @@ class AstEdgeType {
|
||||
public:
|
||||
// REMEMBER to edit the strings below too
|
||||
enum en {
|
||||
// These must be in general -> most specific order, as we sort by it in V3Const::visit AstSenTre
|
||||
// These must be in general -> most specific order, as we sort by it in V3Const::visit AstSenTree
|
||||
ET_ILLEGAL,
|
||||
// Involving a variable
|
||||
ET_ANYEDGE, // Default for sensitivities; rip them out
|
||||
@@ -364,8 +364,8 @@ public:
|
||||
return names[m_e];
|
||||
};
|
||||
static void selfTest() {
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"),"Enum array mismatch");
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"), "SelfTest: Enum mismatch");
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"SelfTest: Enum mismatch");
|
||||
}
|
||||
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
@@ -418,11 +418,21 @@ public:
|
||||
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isDpiUnsupported() const {
|
||||
return (m_e==TIME);
|
||||
bool isDpiBitVal() const { // DPI uses svBitVecVal
|
||||
return m_e==BIT;
|
||||
}
|
||||
bool isDpiLogicVal() const { // DPI uses svLogicVecVal
|
||||
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT || m_e==TIME;
|
||||
}
|
||||
bool isDpiUnreturnable() const { // Not legal as DPI function return
|
||||
return isDpiLogicVal();
|
||||
}
|
||||
bool isDpiUnsignable() const { // Can add "unsigned" to DPI
|
||||
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
|
||||
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
|
||||
}
|
||||
bool isDpiCLayout() const { // Uses standard C layout, for DPI runtime access
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT
|
||||
|| m_e==LONGINT || m_e==DOUBLE || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
||||
@@ -881,14 +891,18 @@ public:
|
||||
|
||||
class AstNVisitor {
|
||||
private:
|
||||
vector<AstNode*> m_deleteps; // Nodes to delete when we are finished
|
||||
vector<AstNode*> m_deleteps; // Nodes to delete when doDeletes() called
|
||||
protected:
|
||||
friend class AstNode;
|
||||
public:
|
||||
// Cleaning
|
||||
/// At the end of the visitor (or doDeletes()), delete this pushed node
|
||||
/// along with all children and next(s). This is often better to use
|
||||
/// than an immediate deleteTree, as any pointers into this node will
|
||||
/// persist for the lifetime of the visitor
|
||||
void pushDeletep(AstNode* nodep) {
|
||||
m_deleteps.push_back(nodep);
|
||||
}
|
||||
/// Call deleteTree on all previously pushDeletep()'ed nodes
|
||||
void doDeletes();
|
||||
public:
|
||||
virtual ~AstNVisitor() {
|
||||
@@ -1087,7 +1101,8 @@ public:
|
||||
AstNode* op4p() const { return m_op4p; }
|
||||
AstNodeDType* dtypep() const { return m_dtypep; }
|
||||
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
||||
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
||||
AstNode* firstAbovep() const { // Returns NULL when second or later in list
|
||||
return ((backp() && backp()->nextp()!=this) ? backp() : NULL); }
|
||||
bool brokeExists() const;
|
||||
bool brokeExistsAbove() const;
|
||||
|
||||
@@ -1273,12 +1288,13 @@ public:
|
||||
static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list
|
||||
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
|
||||
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
|
||||
void addNextHere(AstNode* newp); // Adds after speced node
|
||||
void addNextHere(AstNode* newp); // Insert newp at this->nextp
|
||||
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
|
||||
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
||||
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
||||
AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it.
|
||||
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||
// Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL);
|
||||
void swapWith(AstNode* bp);
|
||||
void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead
|
||||
void cloneRelinkNode() { cloneRelink(); }
|
||||
@@ -1307,17 +1323,20 @@ public:
|
||||
virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
|
||||
virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations
|
||||
virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out
|
||||
virtual bool isGateDedupable() const { return isGateOptimizable(); } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
||||
virtual bool isGateDedupable() const { return isGateOptimizable(); }
|
||||
virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out
|
||||
virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input
|
||||
virtual bool isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed
|
||||
virtual bool isUnlikely() const { return false; } // Else $stop or similar statement which means an above IF statement is unlikely to be taken
|
||||
// isUnlikely handles $stop or similar statement which means an above IF statement is unlikely to be taken
|
||||
virtual bool isUnlikely() const { return false; }
|
||||
virtual int instrCount() const { return 0; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
|
||||
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
|
||||
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
// Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
virtual bool maybePointedTo() const { return false; }
|
||||
virtual const char* broken() const { return NULL; }
|
||||
|
||||
// INVOKERS
|
||||
@@ -1440,7 +1459,9 @@ public:
|
||||
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
||||
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
||||
// METHODS
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) = 0; // Set out to evaluation of a AstConst'ed
|
||||
// Set out to evaluation of a AstConst'ed
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs,
|
||||
const V3Number& rhs, const V3Number& ths) = 0;
|
||||
virtual bool cleanLhs() = 0; // True if LHS must have extra upper bits zero
|
||||
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero
|
||||
virtual bool cleanThs() = 0; // True if THS must have extra upper bits zero
|
||||
@@ -1713,6 +1734,7 @@ public:
|
||||
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
|
||||
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
|
||||
virtual AstNodeDType* subDTypep() const { return NULL; } // Iff has a non-null subDTypep(), as generic node function
|
||||
virtual bool isFourstate() const;
|
||||
//
|
||||
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
||||
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
@@ -1725,7 +1747,8 @@ public:
|
||||
bool isNosign() const { return m_numeric.isNosign(); }
|
||||
AstNumeric numeric() const { return m_numeric; }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
||||
int widthMin() const { // If sized, the size, if unsized the min digits to represent it
|
||||
return m_widthMin?m_widthMin:m_width; }
|
||||
int widthPow2() const;
|
||||
void widthMinFromWidth() { m_widthMin = m_width; }
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
@@ -1735,6 +1758,7 @@ public:
|
||||
pair<uint32_t,uint32_t> dimensions(bool includeBasic);
|
||||
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
||||
static int uniqueNumInc() { return ++s_uniqueNum; }
|
||||
const char* charIQWN() const { return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); }
|
||||
};
|
||||
|
||||
class AstNodeClassDType : public AstNodeDType {
|
||||
@@ -1743,19 +1767,23 @@ private:
|
||||
typedef map<string,AstMemberDType*> MemberNameMap;
|
||||
// MEMBERS
|
||||
bool m_packed;
|
||||
bool m_isFourstate;
|
||||
MemberNameMap m_members;
|
||||
public:
|
||||
AstNodeClassDType(FileLine* fl, AstNumeric numericUnpack)
|
||||
: AstNodeDType(fl) {
|
||||
// AstNumeric::NOSIGN overloaded to indicate not packed
|
||||
m_packed = (numericUnpack != AstNumeric::NOSIGN);
|
||||
m_isFourstate = false; // V3Width computes
|
||||
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_BASE_FUNCS(NodeClassDType)
|
||||
virtual const char* broken() const;
|
||||
virtual void dump(ostream& str);
|
||||
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
||||
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
|
||||
virtual AstBasicDType* basicp() const {
|
||||
return (isFourstate() ? findLogicDType(width(),width(),numeric())->castBasicDType()
|
||||
: findBitDType(width(),width(),numeric())->castBasicDType()); }
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
||||
@@ -1769,6 +1797,8 @@ public:
|
||||
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
||||
bool packed() const { return m_packed; }
|
||||
bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs
|
||||
void isFourstate(bool flag) { m_isFourstate = flag; }
|
||||
virtual bool isFourstate() const { return m_isFourstate; }
|
||||
void clearCache() { m_members.clear(); }
|
||||
void repairMemberCache();
|
||||
AstMemberDType* findMember(const string& name) const {
|
||||
@@ -1867,21 +1897,24 @@ class AstNodeFTask : public AstNode {
|
||||
private:
|
||||
string m_name; // Name of task
|
||||
string m_cname; // Name of task if DPI import
|
||||
uint64_t m_dpiOpenParent; // DPI import open array, if !=0, how many callees
|
||||
bool m_taskPublic:1; // Public task
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
bool m_prototype:1; // Just a prototype
|
||||
bool m_dpiExport:1; // DPI exported
|
||||
bool m_dpiImport:1; // DPI imported
|
||||
bool m_dpiContext:1; // DPI import context
|
||||
bool m_dpiOpenChild:1; // DPI import open array child wrapper
|
||||
bool m_dpiTask:1; // DPI import task (vs. void function)
|
||||
bool m_pure:1; // DPI import pure
|
||||
public:
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
, m_name(name), m_taskPublic(false)
|
||||
, m_name(name)
|
||||
, m_dpiOpenParent(0), m_taskPublic(false)
|
||||
, m_attrIsolateAssign(false), m_prototype(false)
|
||||
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
|
||||
, m_dpiTask(false), m_pure(false) {
|
||||
, m_dpiOpenChild(false), m_dpiTask(false), m_pure(false) {
|
||||
addNOp3p(stmtsp);
|
||||
cname(name); // Might be overridden by dpi import/export
|
||||
}
|
||||
@@ -1903,23 +1936,29 @@ public:
|
||||
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
|
||||
// op4 = scope name
|
||||
AstScopeName* scopeNamep() const { return op4p()->castScopeName(); }
|
||||
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
void prototype(bool flag) { m_prototype = flag; }
|
||||
bool prototype() const { return m_prototype; }
|
||||
void dpiExport(bool flag) { m_dpiExport = flag; }
|
||||
bool dpiExport() const { return m_dpiExport; }
|
||||
void dpiImport(bool flag) { m_dpiImport = flag; }
|
||||
bool dpiImport() const { return m_dpiImport; }
|
||||
void dpiContext(bool flag) { m_dpiContext = flag; }
|
||||
bool dpiContext() const { return m_dpiContext; }
|
||||
void dpiTask(bool flag) { m_dpiTask = flag; }
|
||||
bool dpiTask() const { return m_dpiTask; }
|
||||
void pure(bool flag) { m_pure = flag; }
|
||||
bool pure() const { return m_pure; }
|
||||
// MORE ACCESSORS
|
||||
void dpiOpenParentInc() { ++m_dpiOpenParent; }
|
||||
void dpiOpenParentClear() { m_dpiOpenParent=0; }
|
||||
uint64_t dpiOpenParent() const { return m_dpiOpenParent; }
|
||||
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
void prototype(bool flag) { m_prototype = flag; }
|
||||
bool prototype() const { return m_prototype; }
|
||||
void dpiExport(bool flag) { m_dpiExport = flag; }
|
||||
bool dpiExport() const { return m_dpiExport; }
|
||||
void dpiImport(bool flag) { m_dpiImport = flag; }
|
||||
bool dpiImport() const { return m_dpiImport; }
|
||||
void dpiContext(bool flag) { m_dpiContext = flag; }
|
||||
bool dpiContext() const { return m_dpiContext; }
|
||||
void dpiOpenChild(bool flag) { m_dpiOpenChild = flag; }
|
||||
bool dpiOpenChild() const { return m_dpiOpenChild; }
|
||||
void dpiTask(bool flag) { m_dpiTask = flag; }
|
||||
bool dpiTask() const { return m_dpiTask; }
|
||||
void pure(bool flag) { m_pure = flag; }
|
||||
bool pure() const { return m_pure; }
|
||||
};
|
||||
|
||||
class AstNodeFTaskRef : public AstNode {
|
||||
@@ -1927,7 +1966,7 @@ class AstNodeFTaskRef : public AstNode {
|
||||
private:
|
||||
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
||||
string m_name; // Name of variable
|
||||
string m_dotted; // Dotted part of scope to task or ""
|
||||
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
@@ -2027,6 +2066,13 @@ public:
|
||||
bool recursiveClone() const { return m_recursiveClone; }
|
||||
};
|
||||
|
||||
class AstNodeRange : public AstNode {
|
||||
// A range, sized or unsized
|
||||
public:
|
||||
explicit AstNodeRange(FileLine* fl) : AstNode (fl) { }
|
||||
ASTNODE_BASE_FUNCS(NodeRange)
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#include "V3AstNodes.h"
|
||||
@@ -2040,11 +2086,16 @@ public:
|
||||
|
||||
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
||||
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
||||
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
|
||||
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
||||
inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
|
||||
inline bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
|
||||
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
||||
inline bool AstNode::width1() const { // V3Const uses to know it can optimize
|
||||
return dtypep() && dtypep()->width()==1; }
|
||||
inline int AstNode::widthInstrs() const {
|
||||
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
||||
inline bool AstNode::isDouble() const {
|
||||
return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
|
||||
inline bool AstNode::isString() const {
|
||||
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
|
||||
inline bool AstNode::isSigned() const {
|
||||
return dtypep() && dtypep()->isSigned(); }
|
||||
|
||||
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
|
||||
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
|
||||
@@ -2056,6 +2107,8 @@ inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(this, n
|
||||
|
||||
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
||||
|
||||
inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); }
|
||||
|
||||
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
|
||||
inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); }
|
||||
inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); }
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+81
-15
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -64,7 +64,8 @@ int AstNodeSel::bitConst() const {
|
||||
void AstNodeClassDType::repairMemberCache() {
|
||||
clearCache();
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||
if (m_members.find(itemp->name())!=m_members.end()) { itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
|
||||
if (m_members.find(itemp->name())!=m_members.end()) {
|
||||
itemp->v3error("Duplicate declaration of member name: "<<itemp->prettyName()); }
|
||||
else m_members.insert(make_pair(itemp->name(), itemp));
|
||||
}
|
||||
}
|
||||
@@ -239,11 +240,20 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||
} else if (isWide()) {
|
||||
arg += "WData"; // []'s added later
|
||||
}
|
||||
if (isWide() && !strtype) {
|
||||
arg += " (& "+name();
|
||||
arg += ")["+cvtToStr(widthWords())+"]";
|
||||
if (isDpiOpenArray() || (isWide() && !strtype)) {
|
||||
arg += " (& "+name()+")";
|
||||
for (AstNodeDType* dtp=dtypep(); dtp; ) {
|
||||
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstUnpackArrayDType* adtypep = dtp->castUnpackArrayDType()) {
|
||||
arg += "["+cvtToStr(adtypep->declRange().elements())+"]";
|
||||
dtp = adtypep->subDTypep();
|
||||
} else break;
|
||||
}
|
||||
if (isWide() && !strtype) {
|
||||
arg += "["+cvtToStr(widthWords())+"]";
|
||||
}
|
||||
} else {
|
||||
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
|
||||
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
|
||||
if (named) arg += " "+name();
|
||||
}
|
||||
return arg;
|
||||
@@ -275,15 +285,48 @@ string AstVar::vlEnumType() const {
|
||||
}
|
||||
|
||||
string AstVar::vlEnumDir() const {
|
||||
string out;
|
||||
if (isInout()) {
|
||||
return "VLVD_INOUT";
|
||||
out = "VLVD_INOUT";
|
||||
} else if (isInOnly()) {
|
||||
return "VLVD_IN";
|
||||
out = "VLVD_IN";
|
||||
} else if (isOutOnly()) {
|
||||
return "VLVD_OUT";
|
||||
out = "VLVD_OUT";
|
||||
} else {
|
||||
return "VLVD_NODIR";
|
||||
out = "VLVD_NODIR";
|
||||
}
|
||||
//
|
||||
if (isSigUserRWPublic()) out += "|VLVF_PUB_RW";
|
||||
else if (isSigUserRdPublic()) out += "|VLVF_PUB_RD";
|
||||
//
|
||||
if (AstBasicDType* bdtypep = basicp()) {
|
||||
if (bdtypep->keyword().isDpiCLayout()) out += "|VLVF_DPI_CLAY";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
string AstVar::vlPropInit() const {
|
||||
string out;
|
||||
out = vlEnumType(); // VLVT_UINT32 etc
|
||||
out += ", "+vlEnumDir(); // VLVD_IN etc
|
||||
if (AstBasicDType* bdtypep = basicp()) {
|
||||
out += ", VerilatedVarProps::Packed()";
|
||||
out += ", "+cvtToStr(bdtypep->left())+", "+cvtToStr(bdtypep->right());
|
||||
}
|
||||
bool first = true;
|
||||
for (AstNodeDType* dtp=dtypep(); dtp; ) {
|
||||
dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstNodeArrayDType* adtypep = dtp->castNodeArrayDType()) {
|
||||
if (first) {
|
||||
out += ", VerilatedVarProps::Unpacked()";
|
||||
first = false;
|
||||
}
|
||||
out += ", "+cvtToStr(adtypep->declRange().left())+", "+cvtToStr(adtypep->declRange().right());
|
||||
dtp = adtypep->subDTypep();
|
||||
}
|
||||
else break; // AstBasicDType - nothing below
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
@@ -313,8 +356,11 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
if (forReturn) named=false;
|
||||
string arg;
|
||||
if (!basicp()) arg = "UNKNOWN";
|
||||
if (basicp()->isBitLogic()) {
|
||||
if (isDpiOpenArray()) {
|
||||
arg = "const svOpenArrayHandle";
|
||||
} else if (!basicp()) {
|
||||
arg = "UNKNOWN";
|
||||
} else if (basicp()->keyword().isDpiBitVal()) {
|
||||
if (widthMin() == 1) {
|
||||
arg = "unsigned char";
|
||||
if (!forReturn && isOutput()) arg += "*";
|
||||
@@ -327,6 +373,19 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
arg = "svBitVecVal*";
|
||||
}
|
||||
}
|
||||
} else if (basicp()->keyword().isDpiLogicVal()) {
|
||||
if (widthMin() == 1) {
|
||||
arg = "unsigned char";
|
||||
if (!forReturn && isOutput()) arg += "*";
|
||||
} else {
|
||||
if (forReturn) {
|
||||
arg = "svLogicVecVal";
|
||||
} else if (isInOnly()) {
|
||||
arg = "const svLogicVecVal*";
|
||||
} else {
|
||||
arg = "svLogicVecVal*";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
arg = basicp()->keyword().dpiType();
|
||||
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
|
||||
@@ -851,6 +910,7 @@ void AstRefDType::dump(ostream& str) {
|
||||
void AstNodeClassDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packed()) str<<" [PACKED]";
|
||||
if (isFourstate()) str<<" [4STATE]";
|
||||
}
|
||||
void AstNodeDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -949,7 +1009,10 @@ void AstTypeTable::dump(ostream& str) {
|
||||
}
|
||||
// Note get newline from caller too.
|
||||
}
|
||||
|
||||
void AstUnsizedArrayDType::dumpSmall(ostream& str) {
|
||||
this->AstNodeDType::dumpSmall(str);
|
||||
str<<"[]";
|
||||
}
|
||||
void AstVarScope::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (isCircular()) str<<" [CIRC]";
|
||||
@@ -961,7 +1024,7 @@ void AstVarXRef::dump(ostream& str) {
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
str<<dotted()<<". - ";
|
||||
str<<".="<<dotted()<<" ";
|
||||
if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
|
||||
if (varScopep()) { varScopep()->dump(str); }
|
||||
else if (varp()) { varp()->dump(str); }
|
||||
@@ -996,6 +1059,7 @@ void AstVar::dump(ostream& str) {
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
if (isFuncReturn()) str<<" [FUNCRTN]";
|
||||
else if (isFuncLocal()) str<<" [FUNC]";
|
||||
if (isDpiOpenArray()) str<<" [DPIOPENA]";
|
||||
if (!attrClocker().unknown()) str<<" ["<<attrClocker().ascii()<<"] ";
|
||||
str<<" "<<varType();
|
||||
}
|
||||
@@ -1031,7 +1095,7 @@ void AstNodeFTaskRef::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
str<<" -> ";
|
||||
if (dotted()!="") { str<<dotted()<<". - "; }
|
||||
if (dotted()!="") { str<<".="<<dotted()<<" "; }
|
||||
if (taskp()) { taskp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
}
|
||||
@@ -1041,6 +1105,8 @@ void AstNodeFTask::dump(ostream& str) {
|
||||
if (prototype()) str<<" [PROTOTYPE]";
|
||||
if (dpiImport()) str<<" [DPII]";
|
||||
if (dpiExport()) str<<" [DPIX]";
|
||||
if (dpiOpenChild()) str<<" [DPIOPENCHILD]";
|
||||
if (dpiOpenParent()) str<<" [DPIOPENPARENT]";
|
||||
if ((dpiImport() || dpiExport()) && cname()!=name()) str<<" [c="<<cname()<<"]";
|
||||
}
|
||||
void AstBegin::dump(ostream& str) {
|
||||
|
||||
+383
-116
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -108,22 +108,22 @@ public:
|
||||
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
|
||||
};
|
||||
|
||||
class AstRange : public AstNode {
|
||||
class AstRange : public AstNodeRange {
|
||||
// Range specification, for use under variables and cells
|
||||
private:
|
||||
bool m_littleEndian:1; // Bit vector is little endian
|
||||
public:
|
||||
AstRange(FileLine* fl, AstNode* msbp, AstNode* lsbp)
|
||||
:AstNode(fl) {
|
||||
: AstNodeRange(fl) {
|
||||
m_littleEndian = false;
|
||||
setOp2p(msbp); setOp3p(lsbp); }
|
||||
AstRange(FileLine* fl, int msb, int lsb)
|
||||
:AstNode(fl) {
|
||||
: AstNodeRange(fl) {
|
||||
m_littleEndian = false;
|
||||
setOp2p(new AstConst(fl,msb)); setOp3p(new AstConst(fl,lsb));
|
||||
}
|
||||
AstRange(FileLine* fl, const VNumRange& range)
|
||||
:AstNode(fl) {
|
||||
: AstNodeRange(fl) {
|
||||
m_littleEndian = range.littleEndian();
|
||||
setOp2p(new AstConst(fl,range.hi())); setOp3p(new AstConst(fl,range.lo()));
|
||||
}
|
||||
@@ -146,6 +146,17 @@ public:
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
class AstUnsizedRange : public AstNodeRange {
|
||||
// Unsized range specification, for open arrays
|
||||
public:
|
||||
explicit AstUnsizedRange(FileLine* fl) : AstNodeRange(fl) { }
|
||||
ASTNODE_NODE_FUNCS(UnsizedRange)
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitVerilog() { return "[]"; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
class AstGatePin : public AstNodeMath {
|
||||
// Possibly expand a gate primitive input pin value to match the range of the gate primitive
|
||||
public:
|
||||
@@ -334,6 +345,49 @@ public:
|
||||
ASTNODE_NODE_FUNCS(UnpackArrayDType)
|
||||
};
|
||||
|
||||
class AstUnsizedArrayDType : public AstNodeDType {
|
||||
// Unsized/open-range Array data type, ie "some_dtype var_name []"
|
||||
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||
private:
|
||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||
public:
|
||||
AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
|
||||
: AstNodeDType(fl) {
|
||||
childDTypep(dtp); // Only for parser
|
||||
refDTypep(NULL);
|
||||
dtypep(NULL); // V3Width will resolve
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(UnsizedArrayDType)
|
||||
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
||||
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
||||
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
||||
m_refDTypep = m_refDTypep->clonep();
|
||||
}}
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
return (subDTypep()==asamep->subDTypep()); }
|
||||
virtual bool similarDType(AstNodeDType* samep) const {
|
||||
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
|
||||
}
|
||||
virtual void dumpSmall(ostream& str);
|
||||
virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); }
|
||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
|
||||
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
||||
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
||||
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
|
||||
};
|
||||
|
||||
class AstBasicDType : public AstNodeDType {
|
||||
// Builtin atomic/vectored data type
|
||||
// Children: RANGE (converted to constant in V3Width)
|
||||
@@ -345,7 +399,7 @@ private:
|
||||
return rhs.m_keyword == m_keyword
|
||||
&& rhs.m_nrange == m_nrange; }
|
||||
} m;
|
||||
// See also in AstNodeDtype: m_width, m_widthMin, m_numeric(issigned)
|
||||
// See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned)
|
||||
public:
|
||||
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSignedState signst=signedst_NOSIGN)
|
||||
: AstNodeDType(fl) {
|
||||
@@ -426,6 +480,7 @@ public:
|
||||
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
virtual bool isFourstate() const { return keyword().isFourstate(); }
|
||||
AstBasicDTypeKwd keyword() const { return m.m_keyword; } // Avoid using - use isSomething accessors instead
|
||||
bool isBitLogic() const { return keyword().isBitLogic(); }
|
||||
bool isDouble() const { return keyword().isDouble(); }
|
||||
@@ -615,7 +670,7 @@ public:
|
||||
|
||||
class AstMemberDType : public AstNodeDType {
|
||||
// A member of a struct/union
|
||||
// PARENT: AstClassDType
|
||||
// PARENT: AstNodeClassDType
|
||||
private:
|
||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||
string m_name; // Name of variable
|
||||
@@ -651,13 +706,17 @@ public:
|
||||
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
||||
virtual bool similarDType(AstNodeDType* samep) const { return this==samep; }
|
||||
//
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
// (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); }
|
||||
// op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
|
||||
virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); }
|
||||
virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); }
|
||||
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
|
||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
||||
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
||||
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
|
||||
// METHODS
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual void tag(const string& text) { m_tag = text;}
|
||||
@@ -1056,6 +1115,7 @@ private:
|
||||
bool m_isPulldown:1; // Tri0
|
||||
bool m_isPullup:1; // Tri1
|
||||
bool m_isIfaceParent:1; // dtype is reference to interface present in this module
|
||||
bool m_isDpiOpenArray:1; // DPI import open array
|
||||
bool m_noSubst:1; // Do not substitute out references
|
||||
bool m_trace:1; // Trace this variable
|
||||
AstVarAttrClocker m_attrClocker;
|
||||
@@ -1069,8 +1129,8 @@ private:
|
||||
m_funcLocal=false; m_funcReturn=false;
|
||||
m_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false;
|
||||
m_fileDescr=false; m_isConst=false; m_isStatic=false; m_isPulldown=false; m_isPullup=false;
|
||||
m_isIfaceParent=false; m_attrClocker=AstVarAttrClocker::CLOCKER_UNKNOWN; m_noSubst=false;
|
||||
m_trace=false;
|
||||
m_isIfaceParent=false; m_isDpiOpenArray=false; m_noSubst=false; m_trace=false;
|
||||
m_attrClocker=AstVarAttrClocker::CLOCKER_UNKNOWN;
|
||||
}
|
||||
public:
|
||||
AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
|
||||
@@ -1127,14 +1187,17 @@ public:
|
||||
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.
|
||||
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
|
||||
string vlArgType(bool named, bool forReturn, bool forFunc) const; // Return Verilator internal type for argument: CData, SData, IData, WData
|
||||
// Return Verilator internal type for argument: CData, SData, IData, WData
|
||||
string vlArgType(bool named, bool forReturn, bool forFunc) const;
|
||||
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
|
||||
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
|
||||
string vlPropInit() const; // Return VerilatorVarProps initializer
|
||||
void combineType(AstVarType type);
|
||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
|
||||
AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
// (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
|
||||
AstBasicDType* basicp() const { return subDTypep()->basicp(); }
|
||||
AstNode* valuep() const { return op3p(); } // op3 = Initial value that never changes (static const)
|
||||
void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than an AstConst
|
||||
void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
|
||||
@@ -1163,6 +1226,8 @@ public:
|
||||
void isIfaceParent(bool flag) { m_isIfaceParent = flag; }
|
||||
void funcLocal(bool flag) { m_funcLocal = flag; }
|
||||
void funcReturn(bool flag) { m_funcReturn = flag; }
|
||||
void isDpiOpenArray(bool flag) { m_isDpiOpenArray=flag; }
|
||||
bool isDpiOpenArray() const { return m_isDpiOpenArray; }
|
||||
void noSubst(bool flag) { m_noSubst=flag; }
|
||||
bool noSubst() const { return m_noSubst; }
|
||||
void trace(bool flag) { m_trace=flag; }
|
||||
@@ -1384,11 +1449,14 @@ class AstVarRef : public AstNodeVarRef {
|
||||
// A reference to a variable (lvalue or rvalue)
|
||||
public:
|
||||
AstVarRef(FileLine* fl, const string& name, bool lvalue)
|
||||
:AstNodeVarRef(fl, name, NULL, lvalue) {}
|
||||
AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) // This form only allowed post-link
|
||||
:AstNodeVarRef(fl, varp->name(), varp, lvalue) {} // because output/wire compression may lead to deletion of AstVar's
|
||||
AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue) // This form only allowed post-link
|
||||
:AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) { // because output/wire compression may lead to deletion of AstVar's
|
||||
: AstNodeVarRef(fl, name, NULL, lvalue) {}
|
||||
// This form only allowed post-link because output/wire compression may
|
||||
// lead to deletion of AstVar's
|
||||
AstVarRef(FileLine* fl, AstVar* varp, bool lvalue)
|
||||
: AstNodeVarRef(fl, varp->name(), varp, lvalue) {}
|
||||
// This form only allowed post-link (see above)
|
||||
AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue)
|
||||
: AstNodeVarRef(fl, varscp->varp()->name(), varscp->varp(), lvalue) {
|
||||
varScopep(varscp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(VarRef)
|
||||
@@ -1416,7 +1484,7 @@ class AstVarXRef : public AstNodeVarRef {
|
||||
// A VarRef to something in another module before AstScope.
|
||||
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
|
||||
private:
|
||||
string m_dotted; // Scope name to connected to
|
||||
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
public:
|
||||
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
|
||||
@@ -1881,7 +1949,7 @@ public:
|
||||
};
|
||||
|
||||
class AstDot : public AstNode {
|
||||
// A dot separating paths in an AstXRef, AstFuncRef or AstTaskRef
|
||||
// A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
|
||||
// These are eliminated in the link stage
|
||||
public:
|
||||
AstDot(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
@@ -2272,7 +2340,9 @@ public:
|
||||
ASTNODE_NODE_FUNCS(CoverDecl)
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists());
|
||||
if (m_dataDeclp && m_dataDeclp->m_dataDeclp) v3fatalSrc("dataDeclp should point to real data, not be a list"); // Avoid O(n^2) accessing
|
||||
if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing
|
||||
v3fatalSrc("dataDeclp should point to real data, not be a list");
|
||||
}
|
||||
return NULL; }
|
||||
virtual void cloneRelink() { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); }
|
||||
virtual void dump(ostream& str);
|
||||
@@ -2535,6 +2605,26 @@ public:
|
||||
void lhsp(AstNode* nodep) { setOp3p(nodep); }
|
||||
};
|
||||
|
||||
class AstSysFuncAsTask : public AstNodeStmt {
|
||||
// Call what is normally a system function (with a return) in a non-return context
|
||||
// Parents: stmtlist
|
||||
// Children: a system function
|
||||
public:
|
||||
AstSysFuncAsTask(FileLine* fileline, AstNode* exprsp)
|
||||
: AstNodeStmt (fileline) { addNOp1p(exprsp); }
|
||||
ASTNODE_NODE_FUNCS(SysFuncAsTask)
|
||||
virtual string verilogKwd() const { return ""; }
|
||||
virtual bool isGateOptimizable() const { return true; }
|
||||
virtual bool isPredictOptimizable() const { return true; }
|
||||
virtual bool isPure() const { return true; }
|
||||
virtual bool isOutputter() const { return false; }
|
||||
virtual int instrCount() const { return 0; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval
|
||||
void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval
|
||||
};
|
||||
|
||||
class AstSysIgnore : public AstNodeStmt {
|
||||
// Parents: stmtlist
|
||||
// Children: varrefs or exprs
|
||||
@@ -2683,17 +2773,16 @@ public:
|
||||
void fromp(AstNode* nodep) { setOp2p(nodep); }
|
||||
};
|
||||
|
||||
class AstReadMem : public AstNodeStmt {
|
||||
class AstNodeReadWriteMem : public AstNodeStmt {
|
||||
private:
|
||||
bool m_isHex; // readmemh, not readmemb
|
||||
public:
|
||||
AstReadMem(FileLine* fileline, bool hex,
|
||||
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
|
||||
AstNodeReadWriteMem(FileLine* fileline, bool hex,
|
||||
AstNode* filenamep, AstNode* memp,
|
||||
AstNode* lsbp, AstNode* msbp)
|
||||
: AstNodeStmt (fileline), m_isHex(hex) {
|
||||
setOp1p(filenamep); setOp2p(memp); setNOp3p(lsbp); setNOp4p(msbp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ReadMem)
|
||||
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isPure() const { return false; }
|
||||
@@ -2701,12 +2790,35 @@ public:
|
||||
virtual bool isUnlikely() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
return isHex()==static_cast<const AstReadMem*>(samep)->isHex(); }
|
||||
return isHex()==static_cast<const AstNodeReadWriteMem*>(samep)->isHex();
|
||||
}
|
||||
bool isHex() const { return m_isHex; }
|
||||
AstNode* filenamep() const { return op1p(); }
|
||||
AstNode* memp() const { return op2p(); }
|
||||
AstNode* lsbp() const { return op3p(); }
|
||||
AstNode* msbp() const { return op4p(); }
|
||||
virtual const char* cFuncPrefixp() const = 0;
|
||||
};
|
||||
|
||||
class AstReadMem : public AstNodeReadWriteMem {
|
||||
public:
|
||||
AstReadMem(FileLine* fileline, bool hex,
|
||||
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
|
||||
: AstNodeReadWriteMem(fileline, hex, filenamep, memp, lsbp, msbp)
|
||||
{ }
|
||||
ASTNODE_NODE_FUNCS(ReadMem);
|
||||
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
|
||||
virtual const char* cFuncPrefixp() const { return "VL_READMEM_"; }
|
||||
};
|
||||
|
||||
class AstWriteMem : public AstNodeReadWriteMem {
|
||||
public:
|
||||
AstWriteMem(FileLine* fileline,
|
||||
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
|
||||
: AstNodeReadWriteMem(fileline, true, filenamep, memp, lsbp, msbp) { }
|
||||
ASTNODE_NODE_FUNCS(WriteMem)
|
||||
virtual string verilogKwd() const { return (isHex()?"$writememh":"$writememb"); }
|
||||
virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; }
|
||||
};
|
||||
|
||||
class AstSystemT : public AstNodeStmt {
|
||||
@@ -3361,10 +3473,14 @@ public:
|
||||
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstText* scopeEntrp() const { return op2p()->castText(); }
|
||||
void scopeEntrp(AstNode* nodep) { addOp2p(nodep); }
|
||||
string scopeSymName() const { return scopeNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
|
||||
string scopeDpiName() const { return scopeNameFormatter(scopeEntrp()); } // Name for DPI import scope
|
||||
string scopePrettySymName() const { return scopePrettyNameFormatter(scopeAttrp()); } // Name for __Vscope variable including children
|
||||
string scopePrettyDpiName() const { return scopePrettyNameFormatter(scopeEntrp()); } // Name for __Vscope variable including children
|
||||
string scopeSymName() const { // Name for __Vscope variable including children
|
||||
return scopeNameFormatter(scopeAttrp()); }
|
||||
string scopeDpiName() const { // Name for DPI import scope
|
||||
return scopeNameFormatter(scopeEntrp()); }
|
||||
string scopePrettySymName() const { // Name for __Vscope variable including children
|
||||
return scopePrettyNameFormatter(scopeAttrp()); }
|
||||
string scopePrettyDpiName() const { // Name for __Vscope variable including children
|
||||
return scopePrettyNameFormatter(scopeEntrp()); }
|
||||
bool dpiExport() const { return m_dpiExport; }
|
||||
void dpiExport(bool flag) { m_dpiExport=flag; }
|
||||
};
|
||||
@@ -3545,6 +3661,18 @@ public:
|
||||
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
|
||||
};
|
||||
|
||||
class AstLenN : public AstNodeUniop {
|
||||
// Length of a string
|
||||
public:
|
||||
AstLenN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetSigned32(); }
|
||||
ASTNODE_NODE_FUNCS(LenN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLenN(lhs); }
|
||||
virtual string emitVerilog() { return "%f(%l)"; }
|
||||
virtual string emitC() { return "VL_LEN_IN(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
};
|
||||
class AstLogNot : public AstNodeUniop {
|
||||
public:
|
||||
AstLogNot(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
@@ -3876,94 +4004,176 @@ public:
|
||||
AstNode* filep() const { return lhsp(); }
|
||||
};
|
||||
|
||||
class AstCeilD : public AstNodeUniop {
|
||||
class AstNodeSystemUniop : public AstNodeUniop {
|
||||
public:
|
||||
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(CeilD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.setDouble(ceil(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$ceil(%l)"; }
|
||||
virtual string emitC() { return "ceil(%li)"; }
|
||||
AstNodeSystemUniop(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_BASE_FUNCS(NodeSystemUniop)
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstExpD : public AstNodeUniop {
|
||||
class AstLogD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(ExpD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.setDouble(exp(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$exp(%l)"; }
|
||||
virtual string emitC() { return "exp(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstFloorD : public AstNodeUniop {
|
||||
public:
|
||||
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
ASTNODE_NODE_FUNCS(FloorD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.setDouble(floor(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$floor(%l)"; }
|
||||
virtual string emitC() { return "floor(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstLogD : public AstNodeUniop {
|
||||
public:
|
||||
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(LogD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.setDouble(log(lhs.toDouble())); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$ln(%l)"; }
|
||||
virtual string emitC() { return "log(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstLog10D : public AstNodeUniop {
|
||||
class AstLog10D : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(Log10D)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.setDouble(log10(lhs.toDouble())); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log10(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$log10(%l)"; }
|
||||
virtual string emitC() { return "log10(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstSqrtD : public AstNodeUniop {
|
||||
class AstExpD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetDouble(); }
|
||||
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(ExpD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(exp(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$exp(%l)"; }
|
||||
virtual string emitC() { return "exp(%li)"; }
|
||||
};
|
||||
|
||||
class AstSqrtD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(SqrtD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.setDouble(sqrt(lhs.toDouble())); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sqrt(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$sqrt(%l)"; }
|
||||
virtual string emitC() { return "sqrt(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstFloorD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FloorD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(floor(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$floor(%l)"; }
|
||||
virtual string emitC() { return "floor(%li)"; }
|
||||
};
|
||||
|
||||
class AstCeilD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(CeilD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(ceil(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$ceil(%l)"; }
|
||||
virtual string emitC() { return "ceil(%li)"; }
|
||||
};
|
||||
|
||||
class AstSinD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstSinD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(SinD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sin(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$sin(%l)"; }
|
||||
virtual string emitC() { return "sin(%li)"; }
|
||||
};
|
||||
|
||||
class AstCosD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstCosD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(CosD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cos(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$cos(%l)"; }
|
||||
virtual string emitC() { return "cos(%li)"; }
|
||||
};
|
||||
|
||||
class AstTanD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstTanD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(TanD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tan(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$tan(%l)"; }
|
||||
virtual string emitC() { return "tan(%li)"; }
|
||||
};
|
||||
|
||||
class AstAsinD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstAsinD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(AsinD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asin(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$asin(%l)"; }
|
||||
virtual string emitC() { return "asin(%li)"; }
|
||||
};
|
||||
|
||||
class AstAcosD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstAcosD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(AcosD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acos(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$acos(%l)"; }
|
||||
virtual string emitC() { return "acos(%li)"; }
|
||||
};
|
||||
|
||||
class AstAtanD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstAtanD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(AtanD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atan(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$atan(%l)"; }
|
||||
virtual string emitC() { return "atan(%li)"; }
|
||||
};
|
||||
|
||||
class AstSinhD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstSinhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(SinhD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sinh(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$sinh(%l)"; }
|
||||
virtual string emitC() { return "sinh(%li)"; }
|
||||
};
|
||||
|
||||
class AstCoshD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstCoshD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(CoshD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cosh(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$cosh(%l)"; }
|
||||
virtual string emitC() { return "cosh(%li)"; }
|
||||
};
|
||||
|
||||
class AstTanhD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstTanhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(TanhD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tanh(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$tanh(%l)"; }
|
||||
virtual string emitC() { return "tanh(%li)"; }
|
||||
};
|
||||
|
||||
class AstAsinhD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstAsinhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(AsinhD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asinh(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$asinh(%l)"; }
|
||||
virtual string emitC() { return "asinh(%li)"; }
|
||||
};
|
||||
|
||||
class AstAcoshD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstAcoshD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(AcoshD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acosh(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$acosh(%l)"; }
|
||||
virtual string emitC() { return "acosh(%li)"; }
|
||||
};
|
||||
|
||||
class AstAtanhD : public AstNodeSystemUniop {
|
||||
public:
|
||||
AstAtanhD(FileLine* fl, AstNode* lhsp) : AstNodeSystemUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(AtanhD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atanh(lhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$atanh(%l)"; }
|
||||
virtual string emitC() { return "atanh(%li)"; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
@@ -4454,7 +4664,9 @@ public:
|
||||
virtual string emitSimpleOperator() { return ">>"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} // LHS size might be > output size, so don't want to force size
|
||||
// LHS size might be > output size, so don't want to force size
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
class AstShiftRS : public AstNodeBiop {
|
||||
// Shift right with sign extension, >>> operator
|
||||
@@ -4933,6 +5145,39 @@ public:
|
||||
AstNode* filep() const { return rhsp(); }
|
||||
};
|
||||
|
||||
class AstNodeSystemBiop : public AstNodeBiop {
|
||||
public:
|
||||
AstNodeSystemBiop(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
dtypeSetDouble(); }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleTrig(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
|
||||
class AstAtan2D : public AstNodeSystemBiop {
|
||||
public:
|
||||
AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeSystemBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(Atan2D)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAtan2D(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.setDouble(atan2(lhs.toDouble(), rhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$atan2(%l,%r)"; }
|
||||
virtual string emitC() { return "atan2(%li,%ri)"; }
|
||||
};
|
||||
|
||||
class AstHypotD : public AstNodeSystemBiop {
|
||||
public:
|
||||
AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeSystemBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(HypotD)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstHypotD(this->fileline(), lhsp, rhsp); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.setDouble(hypot(lhs.toDouble(), rhs.toDouble())); }
|
||||
virtual string emitVerilog() { return "%f$hypot(%l,%r)"; }
|
||||
virtual string emitC() { return "hypot(%li,%ri)"; }
|
||||
};
|
||||
|
||||
class AstPattern : public AstNodeMath {
|
||||
// Verilog '{a,b,c,d...}
|
||||
// Parents: AstNodeAssign, AstPattern, ...
|
||||
@@ -5038,30 +5283,44 @@ public:
|
||||
AstNode* propp() const { return op3p(); } // op3 = property
|
||||
};
|
||||
|
||||
class AstPslCover : public AstNodeStmt {
|
||||
class AstNodePslCoverOrAssert : public AstNodeStmt {
|
||||
// Psl Cover
|
||||
// Parents: {statement list}
|
||||
// Children: expression, report string
|
||||
private:
|
||||
string m_name; // Name to report
|
||||
public:
|
||||
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
|
||||
AstNodePslCoverOrAssert(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
|
||||
: AstNodeStmt(fl)
|
||||
, m_name(name) {
|
||||
addOp1p(propp);
|
||||
addNOp4p(stmtsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(PslCover)
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
ASTNODE_BASE_FUNCS(NodePslCoverOrAssert)
|
||||
virtual string name() const { return m_name; } // * = Var name
|
||||
virtual V3Hash sameHash() const { return V3Hash(name()); }
|
||||
virtual bool same(const AstNode* samep) const { return samep->name() == name(); }
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
AstNode* propp() const { return op1p(); } // op1 = property
|
||||
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
|
||||
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
|
||||
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
|
||||
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
|
||||
AstNode* stmtsp() const { return op4p(); } // op4 = statements
|
||||
AstNode* propp() const { return op1p(); } // op1 = property
|
||||
AstSenTree* sentreep() const { return op2p()->castSenTree(); } // op2 = clock domain
|
||||
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
|
||||
AstNode* stmtsp() const { return op4p(); } // op4 = statements
|
||||
};
|
||||
|
||||
class AstPslCover : public AstNodePslCoverOrAssert {
|
||||
public:
|
||||
ASTNODE_NODE_FUNCS(PslCover)
|
||||
AstPslCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
|
||||
: AstNodePslCoverOrAssert(fl, propp, stmtsp, name) {}
|
||||
AstNode* coverincp() const { return op3p(); } // op3 = coverage node
|
||||
void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node
|
||||
};
|
||||
|
||||
class AstPslAssert : public AstNodePslCoverOrAssert {
|
||||
public:
|
||||
ASTNODE_NODE_FUNCS(PslAssert)
|
||||
AstPslAssert(FileLine* fl, AstNode* propp, AstNode* stmtsp, const string& name="")
|
||||
: AstNodePslCoverOrAssert(fl, propp, stmtsp, name) {}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
@@ -5471,13 +5730,19 @@ class AstNetlist : public AstNode {
|
||||
private:
|
||||
AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup
|
||||
AstPackage* m_dollarUnitPkgp;
|
||||
AstCFunc* m_evalp; // The '_eval' function
|
||||
public:
|
||||
AstNetlist() : AstNode(new FileLine("AstRoot",0)) {
|
||||
m_typeTablep = NULL;
|
||||
m_dollarUnitPkgp = NULL;
|
||||
}
|
||||
AstNetlist()
|
||||
: AstNode(new FileLine("AstRoot",0))
|
||||
, m_typeTablep(NULL)
|
||||
, m_dollarUnitPkgp(NULL)
|
||||
, m_evalp(NULL) { }
|
||||
ASTNODE_NODE_FUNCS(Netlist)
|
||||
virtual const char* broken() const { BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); return NULL; }
|
||||
virtual const char* broken() const {
|
||||
BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists());
|
||||
BROKEN_RTN(m_evalp && !m_evalp->brokeExists());
|
||||
return NULL;
|
||||
}
|
||||
AstNodeModule* modulesp() const { return op1p()->castNodeModule();} // op1 = List of modules
|
||||
AstNodeModule* topModulep() const { return op1p()->castNodeModule(); } // * = Top module in hierarchy (first one added, for now)
|
||||
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
|
||||
@@ -5497,6 +5762,8 @@ public:
|
||||
addModulep(m_dollarUnitPkgp);
|
||||
}
|
||||
return m_dollarUnitPkgp; }
|
||||
AstCFunc* evalp() const { return m_evalp; }
|
||||
void evalp(AstCFunc* evalp) { m_evalp = evalp; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
+8
-6
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -291,10 +291,12 @@ public:
|
||||
|
||||
void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
BeginState state;
|
||||
{ BeginVisitor bvisitor (nodep,&state); }
|
||||
if (state.anyFuncInBegin()) {
|
||||
BeginRelinkVisitor brvisitor (nodep,&state);
|
||||
}
|
||||
{
|
||||
BeginState state;
|
||||
{ BeginVisitor bvisitor (nodep,&state); }
|
||||
if (state.anyFuncInBegin()) {
|
||||
BeginRelinkVisitor brvisitor (nodep,&state);
|
||||
}
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+6
-3
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -224,8 +224,11 @@ private:
|
||||
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<<whyp);
|
||||
}
|
||||
if (nodep->dtypep()) {
|
||||
if (!nodep->dtypep()->brokeExists()) { nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
else if (!nodep->dtypep()->castNodeDType()) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep()); }
|
||||
if (!nodep->dtypep()->brokeExists()) {
|
||||
nodep->v3fatalSrc("Broken link in node->dtypep() to "<<(void*)nodep->dtypep());
|
||||
} else if (!nodep->dtypep()->castNodeDType()) {
|
||||
nodep->v3fatalSrc("Non-dtype link in node->dtypep() to "<<(void*)nodep->dtypep());
|
||||
}
|
||||
}
|
||||
if (v3Global.assertDTypesResolved()) {
|
||||
if (nodep->hasDType()) {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+9
-5
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -77,7 +77,8 @@ public:
|
||||
m_numStmts += 1;
|
||||
}
|
||||
|
||||
V3CCtorsVisitor(AstNodeModule* nodep, string basename, string argsp="", string callargsp="",
|
||||
V3CCtorsVisitor(AstNodeModule* nodep, const string& basename,
|
||||
const string& argsp="", const string& callargsp="",
|
||||
const string& stmt="") {
|
||||
m_basename = basename;
|
||||
m_argsp = argsp;
|
||||
@@ -129,7 +130,8 @@ void V3CCtors::evalAsserts() {
|
||||
newp = new AstAnd(varp->fileline(), newp,
|
||||
new AstConst(varp->fileline(), num));
|
||||
AstNodeIf* ifp = new AstIf(varp->fileline(), newp,
|
||||
new AstCStmt(varp->fileline(), "Verilated::overWidthError(\""+varp->prettyName()+"\");"));
|
||||
new AstCStmt(varp->fileline(),
|
||||
"Verilated::overWidthError(\""+varp->prettyName()+"\");"));
|
||||
ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
newp = ifp;
|
||||
funcp->addStmtsp(newp);
|
||||
@@ -149,14 +151,16 @@ void V3CCtors::cctorsAll() {
|
||||
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstVar* varp = np->castVar()) {
|
||||
var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
|
||||
if (!varp->isIfaceParent() && !varp->isIfaceRef()) {
|
||||
var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v3Global.opt.coverage()) {
|
||||
V3CCtorsVisitor configure_coverage
|
||||
(modp, "_configure_coverage", EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first",
|
||||
"if (0 && vlSymsp && first) {} // Prevent unused\n");
|
||||
"if (0 && vlSymsp && first) {} // Prevent unused\n");
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstCoverDecl* coverp = np->castCoverDecl()) {
|
||||
AstNode* backp = coverp->backp();
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+9
-7
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -166,7 +166,7 @@ private:
|
||||
}
|
||||
UINFO(8,"Simple case statement: "<<nodep<<endl);
|
||||
// Zero list of items for each value
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) m_valueItem[i] = NULL;
|
||||
// Now pick up the values for each assignment
|
||||
// We can cheat and use uint32_t's because we only support narrow case's
|
||||
bool bitched = false;
|
||||
@@ -184,7 +184,7 @@ private:
|
||||
V3Number numval (itemp->fileline(), iconstp->width());
|
||||
numval.opBitsOne(iconstp->num());
|
||||
uint32_t val = numval.toUInt();
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
|
||||
if ((i & mask) == val) {
|
||||
if (!m_valueItem[i]) {
|
||||
m_valueItem[i] = itemp;
|
||||
@@ -199,12 +199,12 @@ private:
|
||||
}
|
||||
// Defaults were moved to last in the caseitem list by V3LinkDot
|
||||
if (itemp->isDefault()) { // Case statement's default... Fill the table
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
|
||||
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
|
||||
if (!m_valueItem[i]) {
|
||||
nodep->v3warn(CASEINCOMPLETE,"Case values incompletely covered (example pattern 0x"<<hex<<i<<")");
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
@@ -278,7 +278,7 @@ private:
|
||||
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
|
||||
|
||||
if (debug()>=9) {
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); ++i) {
|
||||
if (AstNode* itemp = m_valueItem[i]) {
|
||||
UINFO(9,"Value "<<hex<<i<<" "<<itemp<<endl);
|
||||
}
|
||||
@@ -488,7 +488,9 @@ public:
|
||||
|
||||
void V3Case::caseAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CaseVisitor visitor (nodep);
|
||||
{
|
||||
CaseVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
void V3Case::caseLint(AstNodeCase* nodep) {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+4
-2
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2018 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.
|
||||
@@ -187,6 +187,8 @@ public:
|
||||
|
||||
void V3Cast::castAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CastVisitor visitor (nodep);
|
||||
{
|
||||
CastVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2018 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.
|
||||
|
||||
+7
-7
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
, m_srcDomainSet(false), m_dstDomainSet(false)
|
||||
, m_asyncPath(false) {}
|
||||
virtual ~CdcEitherVertex() {}
|
||||
// Accessors
|
||||
// ACCESSORS
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
AstSenTree* srcDomainp() const { return m_srcDomainp; }
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: CdcEitherVertex(graphp, scopep, varScp), m_varScp(varScp), m_cntAsyncRst(0), m_fromFlop(false) {}
|
||||
virtual ~CdcVarVertex() {}
|
||||
// Accessors
|
||||
// ACCESSORS
|
||||
AstVarScope* varScp() const { return m_varScp; }
|
||||
virtual string name() const { return (cvtToStr((void*)m_varScp)+" "+varScp()->name()); }
|
||||
virtual string dotColor() const { return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue"; }
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
, m_hazard(false), m_isFlop(false)
|
||||
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
||||
virtual ~CdcLogicVertex() {}
|
||||
// Accessors
|
||||
// ACCESSORS
|
||||
virtual string name() const { return (cvtToStr((void*)nodep())+"@"+scopep()->prettyName()); }
|
||||
virtual string dotColor() const { return hazard() ? "black" : "yellow"; }
|
||||
bool hazard() const { return m_hazard; }
|
||||
@@ -496,8 +496,8 @@ private:
|
||||
}
|
||||
|
||||
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc_edges.txt";
|
||||
const vl_unique_ptr<ofstream> ofp (V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
const vl_unique_ptr<std::ofstream> ofp (V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatal("Can't write "<<filename);
|
||||
*ofp<<"Edge Report for "<<v3Global.opt.prefix()<<endl;
|
||||
|
||||
deque<string> report; // Sort output by name
|
||||
@@ -739,7 +739,7 @@ public:
|
||||
// Make report of all signal names and what clock edges they have
|
||||
string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc.txt";
|
||||
m_ofp = V3File::new_ofstream(filename);
|
||||
if (m_ofp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
if (m_ofp->fail()) v3fatal("Can't write "<<filename);
|
||||
m_ofFilename = filename;
|
||||
*m_ofp<<"CDC Report for "<<v3Global.opt.prefix()<<endl;
|
||||
*m_ofp<<"Each dump below traces logic from inputs/source flops to destination flop(s).\n";
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+11
-5
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -175,13 +175,17 @@ private:
|
||||
newChangeDet();
|
||||
} else {
|
||||
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-class-");
|
||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
|
||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
|
||||
" (probably with UNOPTFLAT warning suppressed): "
|
||||
<<m_vscp->varp()->prettyName());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (debug()) nodep->dumpTree(cout,"-DETECTARRAY-general-");
|
||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable (probably with UNOPTFLAT warning suppressed): "<<m_vscp->varp()->prettyName());
|
||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
|
||||
" (probably with UNOPTFLAT warning suppressed): "
|
||||
<<m_vscp->varp()->prettyName());
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
@@ -300,7 +304,9 @@ public:
|
||||
|
||||
void V3Changed::changedAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ChangedState state;
|
||||
ChangedVisitor visitor (nodep, &state);
|
||||
{
|
||||
ChangedState state;
|
||||
ChangedVisitor visitor (nodep, &state);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+6
-3
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -90,7 +90,8 @@ private:
|
||||
}
|
||||
void computeCppWidth (AstNode* nodep) {
|
||||
if (!nodep->user2() && nodep->hasDType()) {
|
||||
if (nodep->castVar() || nodep->castNodeDType()) { // Don't want to change variable widths!
|
||||
if (nodep->castVar() || nodep->castNodeDType() // Don't want to change variable widths!
|
||||
|| nodep->dtypep()->skipRefp()->castUnpackArrayDType()) { // Or arrays
|
||||
} else {
|
||||
setCppWidth(nodep);
|
||||
}
|
||||
@@ -296,6 +297,8 @@ public:
|
||||
|
||||
void V3Clean::cleanAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CleanVisitor visitor (nodep);
|
||||
{
|
||||
CleanVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+6
-4
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2008-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2008-2018 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.
|
||||
@@ -373,7 +373,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
}
|
||||
void scoreboardPli(AstNode* nodep) {
|
||||
// Order all PLI statements with other PLI statements
|
||||
// This insures $display's and such remain in proper order
|
||||
// This ensures $display's and such remain in proper order
|
||||
// We don't prevent splitting out other non-pli statements, however,
|
||||
// because it is common to have $uasserts sprinkled about.
|
||||
if (!m_pliVertexp) {
|
||||
@@ -912,8 +912,10 @@ public:
|
||||
|
||||
void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
// While the gater does well at some modules, it seems to slow down many others
|
||||
UINFO(5,"ClkGater is disabled due to performance issues\n");
|
||||
{
|
||||
// While the gater does well at some modules, it seems to slow down many others
|
||||
UINFO(5,"ClkGater is disabled due to performance issues\n");
|
||||
} // Destruct before checking
|
||||
//GaterVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("clkgater", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+16
-17
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -62,15 +62,12 @@ private:
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstTopScope* m_topScopep; // Current top scope
|
||||
AstScope* m_scopep; // Current scope
|
||||
AstActive* m_activep; // Current block
|
||||
AstUntilStable* m_untilp; // Current until
|
||||
AstCFunc* m_evalFuncp; // Top eval function we are creating
|
||||
AstCFunc* m_initFuncp; // Top initial function we are creating
|
||||
AstCFunc* m_finalFuncp; // Top final function we are creating
|
||||
AstCFunc* m_settleFuncp; // Top settlement function we are creating
|
||||
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
|
||||
AstIf* m_lastIfp; // Last sensitivity if active to add more under
|
||||
int m_stableNum; // Number of each untilstable
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -252,7 +249,6 @@ private:
|
||||
virtual void visit(AstNodeModule* nodep) {
|
||||
//UINFO(4," MOD "<<nodep<<endl);
|
||||
m_modp = nodep;
|
||||
m_stableNum = 0;
|
||||
nodep->iterateChildren(*this);
|
||||
m_modp= NULL;
|
||||
}
|
||||
@@ -330,16 +326,13 @@ private:
|
||||
pushDeletep(nodep);
|
||||
}
|
||||
void addToEvalLoop(AstNode* stmtsp) {
|
||||
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
||||
else m_evalFuncp->addStmtsp(stmtsp); // else add to top level function
|
||||
m_evalFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
}
|
||||
void addToSettleLoop(AstNode* stmtsp) {
|
||||
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
||||
else m_settleFuncp->addStmtsp(stmtsp); // else add to top level function
|
||||
m_settleFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
}
|
||||
void addToInitial(AstNode* stmtsp) {
|
||||
if (m_untilp) m_untilp->addBodysp(stmtsp); // In a until loop, add to body
|
||||
else m_initFuncp->addStmtsp(stmtsp); // else add to top level function
|
||||
m_initFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
}
|
||||
virtual void visit(AstActive* nodep) {
|
||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||
@@ -393,16 +386,20 @@ private:
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit ClockVisitor(AstNetlist* nodep) {
|
||||
m_modp=NULL; m_activep=NULL;
|
||||
m_modp = NULL;
|
||||
m_evalFuncp = NULL;
|
||||
m_topScopep=NULL;
|
||||
m_lastSenp=NULL;
|
||||
m_initFuncp = NULL;
|
||||
m_finalFuncp = NULL;
|
||||
m_settleFuncp = NULL;
|
||||
m_topScopep = NULL;
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_stableNum = 0;
|
||||
m_untilp = NULL;
|
||||
//
|
||||
nodep->accept(*this);
|
||||
// Allow downstream modules to find _eval()
|
||||
// easily without iterating through the tree.
|
||||
nodep->evalp(m_evalFuncp);
|
||||
}
|
||||
virtual ~ClockVisitor() {}
|
||||
};
|
||||
@@ -412,6 +409,8 @@ public:
|
||||
|
||||
void V3Clock::clockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ClockVisitor visitor (nodep);
|
||||
{
|
||||
ClockVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
+5
-2
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
@@ -402,6 +402,7 @@ private:
|
||||
UINFO(4," MOD "<<nodep<<endl);
|
||||
m_modp = nodep;
|
||||
m_modNFuncs = 0;
|
||||
m_walkLast2p = NULL;
|
||||
m_hashed.clear();
|
||||
// Compute hash of all statement trees in the function
|
||||
m_state = STATE_HASH;
|
||||
@@ -473,6 +474,8 @@ public:
|
||||
|
||||
void V3Combine::combineAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CombineVisitor visitor (nodep);
|
||||
{
|
||||
CombineVisitor visitor (nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2017 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2018 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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user