mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +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 | ||
|
|
0478dbdd1f | ||
|
|
38b0e8a777 | ||
|
|
fe9f1add6f | ||
|
|
ae9179f412 | ||
|
|
4c35a76cdb | ||
|
|
8ca3428fb6 | ||
|
|
7369500bb7 | ||
|
|
45702e319b | ||
|
|
813468bfe6 | ||
|
|
78192308e1 | ||
|
|
cb72390b57 | ||
|
|
71b2eeef67 | ||
|
|
57c8590b21 | ||
|
|
f8ad0a0923 | ||
|
|
7c443ab108 | ||
|
|
0d645757e7 | ||
|
|
dd37c2ea86 | ||
|
|
d3032bfc21 | ||
|
|
bd6ecdfa6f | ||
|
|
3558e70722 | ||
|
|
a579e9273b | ||
|
|
21369bec95 | ||
|
|
d119d10569 | ||
|
|
38988c005c | ||
|
|
8cc4b588b2 | ||
|
|
12607abb33 | ||
|
|
562f17ea4b | ||
|
|
0aea9b7709 | ||
|
|
c0afe96b80 | ||
|
|
5c919cd0de | ||
|
|
f555c93c11 | ||
|
|
cbb7cd16d0 | ||
|
|
4d074b5414 | ||
|
|
dfd22b2b07 | ||
|
|
6edaef9598 | ||
|
|
f63e946f04 | ||
|
|
add5cc8b56 | ||
|
|
2a4e830bee | ||
|
|
eb87232472 | ||
|
|
52c3031a82 | ||
|
|
df471e87eb | ||
|
|
ec6fae5d1a | ||
|
|
cb422a9a02 | ||
|
|
f91bac7b31 | ||
|
|
d542921ff7 | ||
|
|
ad693d67b2 | ||
|
|
350932e9c0 | ||
|
|
4e98d96755 | ||
|
|
c17a9eb5f1 | ||
|
|
252ed4c1ae | ||
|
|
f9fd634fae | ||
|
|
c17c81254e | ||
|
|
5ead61dc7b | ||
|
|
e403db5877 | ||
|
|
32874fa848 | ||
|
|
b90f383cfe | ||
|
|
eb65984368 | ||
|
|
10e0d34140 | ||
|
|
f4b00d3c64 | ||
|
|
cc0b780412 | ||
|
|
fbbbe4ec87 | ||
|
|
1372d62186 | ||
|
|
a69936de74 | ||
|
|
f5dfa1e9c3 | ||
|
|
5fb21c2159 |
@@ -23,6 +23,7 @@ dddrun*
|
||||
doxygen-doc
|
||||
gdbrun*
|
||||
gmon.out
|
||||
ncverilog.history
|
||||
internals.txt
|
||||
verilator.txt
|
||||
verilator_bin*
|
||||
|
||||
@@ -2,6 +2,138 @@ 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]
|
||||
|
||||
*** Support $error/$warning in elaboration time blocks.
|
||||
|
||||
*** Support $size/$bits/etc on type references.
|
||||
|
||||
*** Add error when driving input-only modport, bug1110. [Trevor Elbourne]
|
||||
|
||||
*** Add BSSPACE and COLONPLUS lint warnings.
|
||||
|
||||
**** Detect MSB overflow when under VL_DEBUG, bug1238. [Junyi Xi]
|
||||
|
||||
**** Add data types to --xml. [Rui Terra]
|
||||
|
||||
**** Fix partial slicing with pattern assignments, bug991. [Johan Bjork]
|
||||
|
||||
**** Fix false unused warning on interfaces, bug1241. [Laurens van Dam]
|
||||
|
||||
**** Fix error on "unique case" with no cases.
|
||||
|
||||
**** Fix MacOS portability, bug1232. [Jeff Bush]
|
||||
|
||||
|
||||
* Verilator 3.914 2017-10-14
|
||||
|
||||
** Added new examples/ directory with appropriate examples. This replaces the
|
||||
@@ -2081,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]
|
||||
|
||||
@@ -2949,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$
|
||||
|
||||
+14
-2
@@ -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.
|
||||
@@ -92,6 +92,7 @@ datarootdir = @datarootdir@
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
CFG_WITH_THREADED = @CFG_WITH_THREADED@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
@@ -213,7 +214,7 @@ test_regress: all_nomsg
|
||||
|
||||
examples: all_nomsg
|
||||
for p in examples/* ; do \
|
||||
$(MAKE) -C $$p VERILATOR_ROOT=`pwd` ; \
|
||||
$(MAKE) -C $$p VERILATOR_ROOT=`pwd` || exit 10; \
|
||||
done
|
||||
|
||||
info: $(INFOS)
|
||||
@@ -429,6 +430,14 @@ cppcheck: $(CPPCHECK_DEP)
|
||||
%.cppcheck: %.cpp
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $<
|
||||
|
||||
analyzer-src:
|
||||
-rm -rf src/obj_dbg
|
||||
scan-build $(MAKE) -k verilator_coverage_bin_dbg verilator_bin_dbg
|
||||
|
||||
analyzer-include:
|
||||
-rm -rf examples/*/obj*
|
||||
scan-build $(MAKE) -k examples
|
||||
|
||||
ftp: info
|
||||
|
||||
install-msg:
|
||||
@@ -505,6 +514,9 @@ dist-file-list:
|
||||
@echo $(wildcard $(DISTFILES))
|
||||
@echo "end-dist-file-list:"; # Scripts look for this
|
||||
|
||||
print-cfg-with-threaded:
|
||||
@echo $(CFG_WITH_THREADED)
|
||||
|
||||
######################################################################
|
||||
# Distributions
|
||||
|
||||
|
||||
+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,
|
||||
|
||||
+257
-149
@@ -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.
|
||||
@@ -547,7 +566,7 @@ Coverage analysis adds statements at each code flow change point, which are
|
||||
the branches of IF and CASE statements, a super-set of normal Verilog Line
|
||||
Coverage. At each such branch a unique counter is incremented. At the end
|
||||
of a test, the counters along with the filename and line number
|
||||
corresponding to each counter are written into logs/coverage.pl.
|
||||
corresponding to each counter are written into logs/coverage.dat.
|
||||
|
||||
Verilator automatically disables coverage of branches that have a $stop in
|
||||
them, as it is assumed $stop branches contain an error check that should
|
||||
@@ -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,17 +1285,18 @@ 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
|
||||
|
||||
Disable all lint related warning messages, and all style warnings. This is
|
||||
equivalent to "-Wno-ALWCOMBORDER -Wno-CASEINCOMPLETE -Wno-CASEOVERLAP
|
||||
-Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-ENDLABEL -Wno-IMPLICIT
|
||||
-Wno-LITENDIAN -Wno-PINCONNECTEMPTY -Wno-PINMISSING -Wno-SYNCASYNCNET
|
||||
-Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for
|
||||
Wno-style.
|
||||
equivalent to "-Wno-ALWCOMBORDER -Wno-BSSPACE -Wno-CASEINCOMPLETE
|
||||
-Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEWITHX -Wno-CMPCONST -Wno-COLONPLUS
|
||||
-Wno-ENDLABEL -Wno-IMPLICIT -Wno-LITENDIAN -Wno-PINCONNECTEMPTY
|
||||
-Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
|
||||
-Wno-WIDTH" plus the list shown for Wno-style.
|
||||
|
||||
It is strongly recommended you cleanup your code rather than using this
|
||||
option, it is only intended to be use when running test-cases of code
|
||||
@@ -1284,10 +1325,10 @@ Enables the specified warning message.
|
||||
|
||||
Enable all lint related warning messages (note by default they are already
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-ALWCOMBORDER -Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX
|
||||
-Wwarn-CASEWITHX -Wwarn-CMPCONST -Wwarn-ENDLABEL -Wwarn-IMPLICIT
|
||||
-Wwarn-LITENDIAN -Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED
|
||||
-Wwarn-WIDTH".
|
||||
"-Wwarn-ALWCOMBORDER -Wwarn-BSSPACE -Wwarn-CASEINCOMPLETE
|
||||
-Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX -Wwarn-CMPCONST
|
||||
-Wwarn-COLONPLUS -Wwarn-ENDLABEL -Wwarn-IMPLICIT -Wwarn-LITENDIAN
|
||||
-Wwarn-PINMISSING -Wwarn-REALCVT -Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
|
||||
=item -Wwarn-style
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1734,7 +1775,7 @@ Verilator RPM as the hardcoded value should be correct.
|
||||
=head1 CONNECTING TO C++
|
||||
|
||||
Verilator creates a .h and .cpp file for the top level module and all
|
||||
modules under it. See the test_c directory in the kit for an example.
|
||||
modules under it. See the examples directory in the kit for examples.
|
||||
|
||||
After the modules are completed, there will be a I<module>.mk file that may
|
||||
be used with Make to produce a I<module>__ALL.a file with all required
|
||||
@@ -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
|
||||
@@ -2349,7 +2395,7 @@ Verilator configuration commands.
|
||||
|
||||
Switch back to processing Verilog code after a `systemc_... mode switch.
|
||||
The Verilog code returns to the last language mode specified with
|
||||
`begin_keywords, or SystemVerilog if none were specified.
|
||||
`begin_keywords, or SystemVerilog if none was specified.
|
||||
|
||||
=item /*verilator clock_enable*/
|
||||
|
||||
@@ -2466,6 +2512,13 @@ lint_restore*/. For example:
|
||||
If SOME_WARNING was on before the lint_off, it will now be restored to on,
|
||||
and if it was off before the lint_off it will remain off.
|
||||
|
||||
=item /*verilator no_inline_module*/
|
||||
|
||||
Specifies the module the comment appears in should not be inlined into any
|
||||
modules that use this module. This is useful especially at the top level
|
||||
module to reduce the size of the interface class, to aid compile time at a
|
||||
small performance loss.
|
||||
|
||||
=item /*verilator no_inline_task*/
|
||||
|
||||
Used in a function or task variable definition section to specify the
|
||||
@@ -3034,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
|
||||
@@ -3074,6 +3129,17 @@ generally unrolls small loops. You may want to try increasing
|
||||
--unroll-count (and occasionally --unroll-stmts) which will raise the small
|
||||
loop bar to avoid this error.
|
||||
|
||||
=item BSSPACE
|
||||
|
||||
Warns that a backslash is followed by a space then a newline. Likely the
|
||||
intent was to have a backslash directly followed by a newline (e.g. when
|
||||
making a `define) and there's accidentally whitespace at the end of the
|
||||
line. If the space is not accidental, suggest removing the backslash in
|
||||
the code as it serves no function.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEINCOMPLETE
|
||||
|
||||
Warns that inside a case statement there is a stimulus pattern for which
|
||||
@@ -3113,6 +3179,15 @@ instead intended is to use a casez with C<?>.
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item COLONPLUS
|
||||
|
||||
Warns that a :+ is seen. Likely the intent was to use +: to select a range
|
||||
of bits. If the intent was a range that is explicitly positive, suggest
|
||||
adding a space, e.g. use ": +".
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CDCRSTLOGIC
|
||||
|
||||
With --cdc only, warns that asynchronous flop reset terms come from other
|
||||
@@ -3248,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
|
||||
@@ -3274,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
|
||||
|
||||
@@ -3624,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.
|
||||
|
||||
@@ -3644,24 +3735,24 @@ program above:
|
||||
|
||||
=item Does it run under Windows?
|
||||
|
||||
Yes, using Cygwin. Verilated output should also compile under Microsoft
|
||||
Visual C++ Version 7 or newer, but this is not tested by the author.
|
||||
Yes, using Cygwin. Verilated output also compiles under Microsoft Visual
|
||||
C++ Version 7 or newer, but this is not tested every release.
|
||||
|
||||
=item Can you provide binaries?
|
||||
|
||||
Verilator is available as a RPM for SuSE, Fedora, and perhaps other
|
||||
systems; this is done by porters and may slightly lag the primary
|
||||
distribution. If there isn't a binary build for your distribution, how
|
||||
about you set one up? Please contact the authors for assistance.
|
||||
Verilator is available as a RPM for Debian/Ubuntu, SuSE, Fedora, and
|
||||
perhaps other systems; this is done by porters and may slightly lag the
|
||||
primary distribution. If there isn't a binary build for your distribution,
|
||||
how about you set one up? Please contact the authors for assistance.
|
||||
|
||||
Note people sometimes request binaries when they are having problems with
|
||||
their C++ compiler. Alas, binaries won't help this, as in the end a fully
|
||||
working C++ compiler is required to compile the output of Verilator.
|
||||
|
||||
=item How can it be faster than (name-the-simulator)?
|
||||
=item How can it be faster than (name-the-commercial-simulator)?
|
||||
|
||||
Generally, the implied part of the question is "... with all of their
|
||||
manpower they can put into it."
|
||||
Generally, the implied part is of the question is "... with all of the
|
||||
manpower they can put into developing it."
|
||||
|
||||
Most commercial simulators have to be Verilog compliant, meaning event
|
||||
driven. This prevents them from being able to reorder blocks and make
|
||||
@@ -3694,17 +3785,18 @@ source code available.
|
||||
As is standard with Open Source, contributions back to Verilator will be
|
||||
placed under the Verilator copyright and LGPL/Artistic license. Small test
|
||||
cases will be released into the public domain so they can be used anywhere,
|
||||
large tests under the LGPL/Artistic, unless requested otherwise.
|
||||
and large tests under the LGPL/Artistic, unless requested otherwise.
|
||||
|
||||
=item Why is Verilation so slow?
|
||||
|
||||
Verilator needs more memory than the resulting simulator will require, as
|
||||
Verilator creates internally all of the state of the resulting simulator in
|
||||
order to optimize it. If it takes more than a minute or so (and you're not
|
||||
using --debug since debug is disk bound), see if your machine is paging;
|
||||
most likely you need to run it on a machine with more memory. Verilator is
|
||||
a full 64-bit application and may use more than 4GB, but about 1GB is the
|
||||
maximum typically needed.
|
||||
Verilator creates internally all of the state of the resulting generated
|
||||
simulator in order to optimize it. If it takes more than a minute or so
|
||||
(and you're not using --debug since debug is disk bound), see if your
|
||||
machine is paging; most likely you need to run it on a machine with more
|
||||
memory. Verilator is a full 64-bit application and may use more than 4GB,
|
||||
but about 1GB is the maximum typically needed, and very large commercial
|
||||
designs have topped 16GB.
|
||||
|
||||
=item How do I generate waveforms (traces) in C++?
|
||||
|
||||
@@ -3714,7 +3806,7 @@ Add the --trace switch to Verilator, and in your top level C code, call
|
||||
Verilated::traceEverOn(true). Then create a VerilatedVcdC object, and
|
||||
in your main loop call "trace_object->dump(time)" every time step, and
|
||||
finally call "trace_object->close()". For an example, see below and the
|
||||
test_c/sim_main.cpp file of the distribution.
|
||||
examples/tracing_c/sim_main.cpp file of the distribution.
|
||||
|
||||
You also need to compile verilated_vcd_c.cpp and add it to your link,
|
||||
preferably by adding the dependencies in $(VK_GLOBAL_OBJS) to your
|
||||
@@ -3740,15 +3832,13 @@ trace file if you want all data to land in the same output file.
|
||||
tfp->close();
|
||||
}
|
||||
|
||||
Also see the examples/tracing_cc directory in the distribution.
|
||||
|
||||
=item How do I generate waveforms (traces) in SystemC?
|
||||
|
||||
Add the --trace switch to Verilator, and in your top level C sc_main code,
|
||||
include verilated_vcd_sc.h. Then call Verilated::traceEverOn(true). Then
|
||||
create a VerilatedVcdSc object as you would create a normal SystemC trace
|
||||
file. For an example, see the call to VerilatedVcdSc in the
|
||||
test_sc/sc_main.cpp file of the distribution, and below.
|
||||
examples/tracing_sc/sc_main.cpp file of the distribution, and below.
|
||||
|
||||
Alternatively you may use the C++ trace mechanism described in the previous
|
||||
question, however the timescale and timeprecision will not inherited from
|
||||
@@ -3776,8 +3866,6 @@ trace file if you want all data to land in the same output file.
|
||||
tfp->close();
|
||||
}
|
||||
|
||||
Also see the examples/tracing_cc directory in the distribution.
|
||||
|
||||
=item How do I view waveforms (traces)?
|
||||
|
||||
Verilator makes standard VCD (Value Change Dump) files. They are viewable
|
||||
@@ -3796,8 +3884,8 @@ want to trace (such as perhaps library cells). Finally, use the
|
||||
--trace-depth option to limit the depth of tracing, for example
|
||||
--trace-depth 1 to see only the top level signals.
|
||||
|
||||
Also be sure you write your trace files to a local disk, instead of to a
|
||||
network disk. Network disks are generally far slower.
|
||||
Also be sure you write your trace files to a local solid-state disk,
|
||||
instead of to a network disk. Network disks are generally far slower.
|
||||
|
||||
=item How do I do coverage analysis?
|
||||
|
||||
@@ -3812,14 +3900,14 @@ At the end of your test, call VerilatedCov::write passing the name of the
|
||||
coverage data file (typically "logs/coverage.dat").
|
||||
|
||||
Run each of your tests in different directories. Each test will create a
|
||||
logs/coverage.pl file.
|
||||
logs/coverage.dat file.
|
||||
|
||||
After running all of your tests, verilator_coverage is executed.
|
||||
Verilator_coverage reads the logs/coverage.pl file(s), and creates an
|
||||
Verilator_coverage reads the logs/coverage.dat file(s), and creates an
|
||||
annotated source code listing showing code coverage details.
|
||||
|
||||
For an example, after running 'make test' in the Verilator distribution,
|
||||
see the test_sc/logs directory. Grep for lines starting
|
||||
see the examples/tracing_c/logs directory. Grep for lines starting
|
||||
with '%' to see what lines Verilator believes need more coverage.
|
||||
|
||||
=item Where is the translate_off command? (How do I ignore a construct?)
|
||||
@@ -3833,6 +3921,8 @@ the "VERILATOR" define for you, so just wrap the code in an ifndef region:
|
||||
Something_Verilator_Dislikes;
|
||||
`endif
|
||||
|
||||
Most synthesis tools similarly define SYNTHESIS for you.
|
||||
|
||||
=item Why do I get "unexpected `do'" or "unexpected `bit'" errors?
|
||||
|
||||
Do, bit, ref, return, and other words are now SystemVerilog keywords. You
|
||||
@@ -3869,7 +3959,7 @@ simulator knows the current time. See the "CONNECTING TO C++" examples.
|
||||
You need to link your compiled Verilated code against the verilated.cpp
|
||||
file found in the include directory of the Verilator kit. This is one
|
||||
target in the $(VK_GLOBAL_OBJS) make variable, which should be part of your
|
||||
Makefile's link rule.
|
||||
Makefile's link rule. If you use --exe, this is done for you.
|
||||
|
||||
=item Is the PLI supported?
|
||||
|
||||
@@ -3891,13 +3981,20 @@ test_regress/t/t_extend_class files show an example of how to do this.
|
||||
|
||||
=item How do I get faster build times?
|
||||
|
||||
Between GCC 3.0 to 3.3, each compiled progressively slower, thus if you can
|
||||
use GCC 2.95, or GCC 3.4 you'll have faster builds. Two ways to cheat are
|
||||
to compile on parallel machines and avoid compilations altogether. See the
|
||||
--output-split option, and the web for the ccache, distcc and icecream
|
||||
packages. ccache will skip GCC runs between identical source builds, even
|
||||
across different users. You can use the OBJCACHE environment variable to
|
||||
use these CC wrappers.
|
||||
Use a recent compiler. Newer compilers tend do be faster, with the
|
||||
now relatively old GCC 3.0 to 3.3 being horrible.
|
||||
|
||||
Compile in parallel on many machines and use caching; see the web for the
|
||||
ccache, distcc and icecream packages. ccache will skip GCC runs between
|
||||
identical source builds, even across different users. You can use the
|
||||
OBJCACHE environment variable to use these CC wrappers. Also see the
|
||||
--output-split option.
|
||||
|
||||
To reduce the compile time of classes that use a Verilated module (e.g. a
|
||||
top CPP file) you may wish to add /*verilator no_inline_module*/ to your
|
||||
top level module. This will decrease the amount of code in the model's
|
||||
Verilated class, improving compile times of any instantiating top level C++
|
||||
code, at a relatively small cost of execution performance.
|
||||
|
||||
=item Why do so many files need to recompile when I add a signal?
|
||||
|
||||
@@ -4037,7 +4134,7 @@ License.)
|
||||
In 2001, Wilson Snyder took the kit, and added a SystemC mode, and
|
||||
called it Verilator2. This was the first packaged public release.
|
||||
|
||||
In 2002, Wilson Snyder created Verilator3 by rewriting Verilator from
|
||||
In 2002, Wilson Snyder created Verilator 3.000 by rewriting Verilator from
|
||||
scratch in C++. This added many optimizations, yielding about a 2-5x
|
||||
performance gain.
|
||||
|
||||
@@ -4054,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
|
||||
@@ -4069,50 +4166,61 @@ Inc., picoChip Designs Ltd., Sun Microsystems Inc., Nauticus Networks Inc.,
|
||||
and SiCortex Inc.
|
||||
|
||||
The people who have contributed major functionality are Byron Bradley,
|
||||
Jeremy Bennett, Jie Xu, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson
|
||||
Snyder. Major testers include Jeff Dutton, Jonathon Donaldson, Ralf Karge,
|
||||
David Hewson, Iztok Jeras, Wim Michiels, Alex Solomatnikov, Sebastien Van
|
||||
Cauwenberghe, Gene Weber, and Clifford Wolf.
|
||||
Jeremy Bennett, Jie Xu, Lane Brooks, John Coiner, Duane Galbi, Paul Wasson,
|
||||
and Wilson Snyder. Major testers included Jeff Dutton, Jonathon Donaldson,
|
||||
Ralf Karge, David Hewson, Iztok Jeras, Wim Michiels, Alex Solomatnikov,
|
||||
Sebastien Van Cauwenberghe, Gene Weber, and Clifford Wolf.
|
||||
|
||||
Some of the people who have provided ideas and feedback for Verilator
|
||||
include: Yves Mathieu, David Addison, Nikana Anastasiadis, Hans Van
|
||||
Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad Bagri, Andrew Bardsley,
|
||||
Geoff Barrett, J Baxter, Julius Baxter, Jeremy Bennett, Michael Berman,
|
||||
David Binderman, David Black, Daniel Bone, Gregg Bouchard, Christopher
|
||||
Boumenot, Nick Bowler, Byron Bradley, Bryan Brady, Charlie Brej, Lane
|
||||
Brooks, John Brownlee, Jeff Bush, Lawrence Butcher, Ted Campbell, Chris
|
||||
Candler, Lauren Carlson, Donal Casey, Terry Chen, Robert A. Clark, Allan
|
||||
Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, Mike Denio,
|
||||
John Deroo, Philip Derrick, John Dickol, R. Diez, Ruben Diez, Danny Ding,
|
||||
Ivan Djordjevic, Jonathon Donaldson, Alex Duller, Jeff Dutton, Chandan
|
||||
Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell, Eugen Fekete,
|
||||
Fabrizio Ferrandi, Andrea Foletto, Bob Fredieu, Christian Gelinek, Glen
|
||||
Gibb, Shankar Giri, Sam Gladstone, Amir Gonnen, Chitlesh Goorah, Neil
|
||||
Hamilton, Junji Hashimoto, Thomas Hawkins, David Hewson, Hiroki Honda, Alex
|
||||
Hornung, Jae Hossell, Ben Jackson, Krzysztof Jankowski, HyungKi Jeong,
|
||||
Iztok Jeras, James Johnson, Christophe Joly, Franck Jullien, Mike Kagen,
|
||||
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, 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, 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, Sobhan Klnv, Gernot Koch,
|
||||
Soon Koh, Steve Kolecki, Brett Koonce, Wojciech Koszek, Varun Koyyalagunta,
|
||||
David Kravitz, Roland Kruse, 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, Jason McMullan, Wim
|
||||
Michiels, 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, Brad Parker, David
|
||||
Pierce, Dominic Plunkett, David Poole, Rich Porter, Niranjan Prabhu, Usha
|
||||
Priyadharshini, Mark Jackson Pulver, Prateek Puri, Chris Randall, Frederic
|
||||
Requin, Alberto Del Rio, Oleg Rodionov, Jan Egil Ruud, John Sanguinetti,
|
||||
Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey Short, Rodney
|
||||
Sinclair, Steven Slatter, Brian Small, Wilson Snyder, Alex Solomatnikov,
|
||||
Art Stamness, John Stevenson, Todd Strader, John Stroebel, Emerson
|
||||
Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu Takatsukasa, Peter
|
||||
Tengstrand, Stefan Thiede, Gary Thomas, Kevin Thompson, Mike Thyer, Steve
|
||||
Tong, Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters,
|
||||
Thomas Watts, Eugene Weber, David Welch, Leon Wildman, Gerald Williams,
|
||||
Trevor Williams, Jeff Winston, Joshua Wise, Clifford Wolf, Johan Wouters,
|
||||
Ding Xiaoliang, Jie Xu, and Amir Yazdanbakhsh.
|
||||
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, 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.
|
||||
|
||||
@@ -4121,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.
|
||||
@@ -173,7 +173,7 @@ additional points.
|
||||
Additional Verilog-standard arguments specify the search paths necessary to
|
||||
find the source code that the coverage analysis was performed on.
|
||||
|
||||
To get correct coverage percentages, you may wish to read logs/coverage.pl
|
||||
To get correct coverage percentages, you may wish to read logs/coverage.dat
|
||||
into Emacs and do a M-x keep-lines to include only those statistics of
|
||||
interest.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
+68
-4
@@ -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.914 2017-10-14])
|
||||
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; }])],
|
||||
@@ -107,7 +133,7 @@ AC_TYPE_SIZE_T
|
||||
AC_C_INLINE
|
||||
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([], [[int* a=new int; delete a; ]])],
|
||||
[AC_LANG_PROGRAM([#include <new>], [[int* a=new int; delete a; ]])],
|
||||
[], [AC_MSG_ERROR([$CXX does not seem to successfully compile a simple C++ program])])
|
||||
|
||||
AC_DEFUN([_MY_CXX_CHECK_FLAG],
|
||||
@@ -119,7 +145,7 @@ AC_DEFUN([_MY_CXX_CHECK_FLAG],
|
||||
CXXFLAGS="$CXXFLAGS $1 -Werror"
|
||||
AC_MSG_CHECKING([whether $CXX accepts $1])
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([], [[int* a=new int; delete a; ]])],
|
||||
[AC_LANG_PROGRAM([#include <new>], [[int* a=new int; delete a; ]])],
|
||||
[_my_result=yes
|
||||
if test -s conftest.err; then
|
||||
if grep -e "$1" conftest.err >/dev/null; then
|
||||
@@ -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)
|
||||
@@ -190,6 +219,7 @@ AC_SUBST(CFG_CXXFLAGS_STD_OLDEST)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wextra)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wfloat-conversion)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wlogical-op)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wthread-safety)
|
||||
AC_SUBST(CFG_CXXFLAGS_WEXTRA)
|
||||
|
||||
# Flags for compiling Verilator internals including parser always
|
||||
@@ -217,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)
|
||||
@@ -226,6 +257,39 @@ _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-variable)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-shadow)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
# Set CFG_WITH_THREADED if can support threading
|
||||
AC_MSG_CHECKING(whether $CXX supports Verilated threads)
|
||||
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD_NEWEST $CFG_CXXFLAGS_NO_UNUSED"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <thread>], [[ ]])],
|
||||
[_my_result=yes
|
||||
if test -s conftest.err; then
|
||||
if grep -e "$1" conftest.err >/dev/null; then
|
||||
_my_result=no
|
||||
fi
|
||||
fi],
|
||||
[_my_result=no])
|
||||
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),)
|
||||
@@ -73,7 +73,7 @@ run:
|
||||
@echo
|
||||
@echo "-- RUN ---------------------"
|
||||
@mkdir -p logs
|
||||
obj_dir/Vtop | tee logs/sim.log
|
||||
obj_dir/Vtop +trace
|
||||
|
||||
@echo
|
||||
@echo "-- COVERAGE ----------------"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -41,14 +41,19 @@ int main(int argc, char** argv, char** env) {
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
|
||||
|
||||
// If verilator was invoked with --trace, open trace
|
||||
#if VM_TRACE
|
||||
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
||||
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||
mkdir("logs", 0777);
|
||||
tfp->open("logs/vlt_dump.vcd"); // Open the dump file
|
||||
// If verilator was invoked with --trace argument,
|
||||
// and if at run time passed the +trace argument, turn on tracing
|
||||
VerilatedVcdC* tfp = NULL;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0==strcmp(flag, "+trace")) {
|
||||
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
||||
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
||||
tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||
mkdir("logs", 0777);
|
||||
tfp->open("logs/vlt_dump.vcd"); // Open the dump file
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set some inputs
|
||||
@@ -57,9 +62,9 @@ int main(int argc, char** argv, char** env) {
|
||||
top->clk = 0;
|
||||
top->in_small = 1;
|
||||
top->in_quad = 0x1234;
|
||||
top->in_wide[0] = 0x1;
|
||||
top->in_wide[0] = 0x11111111;
|
||||
top->in_wide[1] = 0x22222222;
|
||||
top->in_wide[2] = 0x33333333;
|
||||
top->in_wide[2] = 0x3;
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
@@ -85,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",
|
||||
@@ -97,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),)
|
||||
@@ -81,7 +81,7 @@ run:
|
||||
@echo
|
||||
@echo "-- RUN ---------------------"
|
||||
@mkdir -p logs
|
||||
obj_dir/Vtop | tee logs/sim.log
|
||||
obj_dir/Vtop +trace
|
||||
|
||||
@echo
|
||||
@echo "-- COVERAGE ----------------"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -87,13 +87,18 @@ int sc_main(int argc, char* argv[]) {
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
||||
// Turn on waves
|
||||
#if VM_TRACE
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
VerilatedVcdSc* tfp = new VerilatedVcdSc;
|
||||
top->trace (tfp, 99);
|
||||
mkdir("logs", 0777);
|
||||
tfp->open ("logs/vlt_dump.vcd");
|
||||
// If verilator was invoked with --trace argument,
|
||||
// and if at run time passed the +trace argument, turn on tracing
|
||||
VerilatedVcdSc* tfp = NULL;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0==strcmp(flag, "+trace")) {
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
tfp = new VerilatedVcdSc;
|
||||
top->trace(tfp, 99);
|
||||
mkdir("logs", 0777);
|
||||
tfp->open("logs/vlt_dump.vcd");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Simulate until $finish
|
||||
@@ -102,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);
|
||||
@@ -117,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;
|
||||
}
|
||||
|
||||
+634
-144
File diff suppressed because it is too large
Load Diff
+529
-258
File diff suppressed because it is too large
Load Diff
+14
-2
@@ -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.
|
||||
######################################################################
|
||||
@@ -109,6 +109,16 @@ ifeq ($(VM_SC),1)
|
||||
endif
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
##### Threaded builds
|
||||
|
||||
ifneq ($(VM_THREADS),0)
|
||||
ifneq ($(VM_THREADS),)
|
||||
# Need C++11 at least, so always default to newest
|
||||
CPPFLAGS += -DVL_THREADED $(CFG_CXXFLAGS_STD_NEWEST)
|
||||
endif
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
##### Stub
|
||||
|
||||
@@ -176,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.
|
||||
|
||||
+64
-48
@@ -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,13 +96,14 @@ private:
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
ValueIndexMap m_valueIndexes; ///< For each key/value a unique arbitrary index value
|
||||
IndexValueMap m_indexValues; ///< For each key/value a unique arbitrary index value
|
||||
ItemList m_items; ///< List of all items
|
||||
VerilatedMutex m_mutex; ///< Protects all members, when VL_THREADED. Wrapper deals with setting it.
|
||||
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
|
||||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< For each key/value a unique arbitrary index value
|
||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||
|
||||
VerilatedCovImpItem* m_insertp; ///< Item about to insert
|
||||
const char* m_insertFilenamep; ///< Filename about to insert
|
||||
int m_insertLineno; ///< Line number about to insert
|
||||
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert
|
||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
||||
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedCovImp() {
|
||||
@@ -110,16 +111,17 @@ private:
|
||||
m_insertFilenamep = NULL;
|
||||
m_insertLineno = 0;
|
||||
}
|
||||
VL_UNCOPYABLE(VerilatedCovImp);
|
||||
public:
|
||||
~VerilatedCovImp() { clear(); }
|
||||
static VerilatedCovImp& imp() {
|
||||
~VerilatedCovImp() { clearGuts(); }
|
||||
static VerilatedCovImp& imp() VL_MT_SAFE {
|
||||
static VerilatedCovImp s_singleton;
|
||||
return s_singleton;
|
||||
}
|
||||
|
||||
private:
|
||||
// PRIVATE METHODS
|
||||
int valueIndex(const std::string& value) {
|
||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||
static int nextIndex = KEY_UNDEF+1;
|
||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
@@ -128,7 +130,7 @@ private:
|
||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
||||
return nextIndex;
|
||||
}
|
||||
static std::string dequote(const std::string& text) {
|
||||
static std::string dequote(const std::string& text) VL_PURE {
|
||||
// Quote any special characters
|
||||
std::string rtn;
|
||||
for (const char* pos = text.c_str(); *pos; ++pos) {
|
||||
@@ -141,7 +143,7 @@ private:
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
static bool legalKey(const std::string& key) {
|
||||
static bool legalKey(const std::string& key) VL_PURE {
|
||||
// Because we compress long keys to a single letter, and
|
||||
// don't want applications to either get confused if they use
|
||||
// a letter differently, nor want them to rely on our compression...
|
||||
@@ -150,7 +152,7 @@ private:
|
||||
if (key.length()==2 && isdigit(key[1])) return false;
|
||||
return true;
|
||||
}
|
||||
static std::string keyValueFormatter (const std::string& key, const std::string& value) {
|
||||
static std::string keyValueFormatter(const std::string& key, const std::string& value) VL_PURE {
|
||||
std::string name;
|
||||
if (key.length()==1 && isalpha(key[0])) {
|
||||
name += std::string("\001")+key;
|
||||
@@ -160,7 +162,7 @@ private:
|
||||
name += std::string("\002")+dequote(value);
|
||||
return name;
|
||||
}
|
||||
static std::string combineHier (const std::string& old, const std::string& add) {
|
||||
static std::string combineHier(const std::string& old, const std::string& add) VL_PURE {
|
||||
// (foo.a.x, foo.b.x) => foo.*.x
|
||||
// (foo.a.x, foo.b.y) => foo.*
|
||||
// (foo.a.x, foo.b) => foo.*
|
||||
@@ -194,7 +196,7 @@ private:
|
||||
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
|
||||
return out;
|
||||
}
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) {
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) VL_REQUIRES(m_mutex) {
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
// We don't compare keys, only values
|
||||
@@ -206,21 +208,18 @@ private:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static void selftest() {
|
||||
static void selftest() VL_MT_SAFE {
|
||||
// Little selftest
|
||||
if (combineHier ("a.b.c","a.b.c") !="a.b.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.b.c","a.b") !="a.b*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.x.c","a.y.c") !="a.*.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.z.z.z.c","a.b.c") !="a.*.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("z","a") !="*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("q.a","q.b") !="q.*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("q.za","q.zb") !="q.z*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("1.2.3.a","9.8.7.a") !="*.a") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.b.c","a.b.c") !="a.b.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.b.c","a.b") !="a.b*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.x.c","a.y.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.z.z.z.c","a.b.c") !="a.*.c") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("z","a") !="*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("q.a","q.b") !="q.*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("q.za","q.zb") !="q.z*") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("1.2.3.a","9.8.7.a") !="*.a") VL_FATAL_MT(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
}
|
||||
|
||||
public:
|
||||
// PUBLIC METHODS
|
||||
void clear() {
|
||||
void clearGuts() VL_REQUIRES(m_mutex) {
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
delete itemp;
|
||||
@@ -229,7 +228,17 @@ public:
|
||||
m_indexValues.clear();
|
||||
m_valueIndexes.clear();
|
||||
}
|
||||
void clearNonMatch (const char* matchp) {
|
||||
|
||||
public:
|
||||
// PUBLIC METHODS
|
||||
void clear() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
clearGuts();
|
||||
}
|
||||
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (matchp && matchp[0]) {
|
||||
ItemList newlist;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
@@ -243,23 +252,28 @@ public:
|
||||
m_items = newlist;
|
||||
}
|
||||
}
|
||||
void zero() {
|
||||
void zero() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
}
|
||||
|
||||
// We assume there's always call to i/f/p in that order
|
||||
void inserti (VerilatedCovImpItem* itemp) {
|
||||
void inserti (VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(!m_insertp);
|
||||
m_insertp = itemp;
|
||||
}
|
||||
void insertf (const char* filenamep, int lineno) {
|
||||
void insertf (const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
m_insertFilenamep = filenamep;
|
||||
m_insertLineno = lineno;
|
||||
}
|
||||
void insertp (const char* ckeyps[MAX_KEYS],
|
||||
const char* valps[MAX_KEYS]) {
|
||||
const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
@@ -303,7 +317,7 @@ public:
|
||||
addKeynum++;
|
||||
if (!legalKey(key)) {
|
||||
std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,16 +326,18 @@ public:
|
||||
m_insertp = NULL;
|
||||
}
|
||||
|
||||
void write (const char* filename) {
|
||||
void write(const char* filename) VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
#ifndef VM_COVERAGE
|
||||
vl_fatal("",0,"","%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
|
||||
VL_FATAL_MT("",0,"","%Error: Called VerilatedCov::write when VM_COVERAGE disabled\n");
|
||||
#endif
|
||||
selftest();
|
||||
|
||||
std::ofstream os (filename);
|
||||
if (os.fail()) {
|
||||
std::string msg = std::string("%Error: Can't write '")+filename+"'";
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
return;
|
||||
}
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
@@ -385,25 +401,25 @@ public:
|
||||
//=============================================================================
|
||||
// VerilatedCov
|
||||
|
||||
void VerilatedCov::clear() {
|
||||
void VerilatedCov::clear() VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().clear();
|
||||
}
|
||||
void VerilatedCov::clearNonMatch (const char* matchp) {
|
||||
void VerilatedCov::clearNonMatch(const char* matchp) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().clearNonMatch(matchp);
|
||||
}
|
||||
void VerilatedCov::zero() {
|
||||
void VerilatedCov::zero() VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().zero();
|
||||
}
|
||||
void VerilatedCov::write (const char* filenamep) {
|
||||
void VerilatedCov::write(const char* filenamep) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().write(filenamep);
|
||||
}
|
||||
void VerilatedCov::_inserti (vluint32_t* itemp) {
|
||||
void VerilatedCov::_inserti(vluint32_t* itemp) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint32_t>(itemp));
|
||||
}
|
||||
void VerilatedCov::_inserti (vluint64_t* itemp) {
|
||||
void VerilatedCov::_inserti(vluint64_t* itemp) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp));
|
||||
}
|
||||
void VerilatedCov::_insertf (const char* filename, int lineno) {
|
||||
void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
|
||||
VerilatedCovImp::imp().insertf(filename,lineno);
|
||||
}
|
||||
|
||||
@@ -413,7 +429,7 @@ void VerilatedCov::_insertf (const char* filename, int lineno) {
|
||||
#define N(n) "","" // Null argument list
|
||||
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19),
|
||||
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) {
|
||||
A(20),A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29)) VL_MT_SAFE {
|
||||
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
|
||||
= {NULL,NULL,NULL, // filename,lineno,page
|
||||
key0,key1,key2,key3,key4,key5,key6,key7,key8,key9,
|
||||
@@ -428,20 +444,20 @@ void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
}
|
||||
|
||||
// And versions with fewer arguments (oh for a language with named parameters!)
|
||||
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) {
|
||||
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9)) VL_MT_SAFE {
|
||||
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
|
||||
N(10),N(11),N(12),N(13),N(14),N(15),N(16),N(17),N(18),N(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
}
|
||||
void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)) {
|
||||
A(10),A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19)) VL_MT_SAFE {
|
||||
_insertp(C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),C(9),
|
||||
C(10),C(11),C(12),C(13),C(14),C(15),C(16),C(17),C(18),C(19),
|
||||
N(20),N(21),N(22),N(23),N(24),N(25),N(26),N(27),N(28),N(29));
|
||||
}
|
||||
// Backward compatibility for Verilator
|
||||
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
K(4),const std::string& val4, A(5),A(6)) {
|
||||
K(4),const std::string& val4, A(5),A(6)) VL_MT_SAFE {
|
||||
std::string val2str = vlCovCvtToStr(val2);
|
||||
std::string val3str = vlCovCvtToStr(val3);
|
||||
_insertp(C(0),C(1),
|
||||
|
||||
+12
-10
@@ -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.
|
||||
//
|
||||
@@ -73,7 +73,7 @@
|
||||
//=============================================================================
|
||||
/// Convert VL_COVER_INSERT value arguments to strings
|
||||
|
||||
template< class T> std::string vlCovCvtToStr (const T& t) {
|
||||
template< class T> std::string vlCovCvtToStr (const T& t) VL_PURE {
|
||||
std::ostringstream os; os<<t; return os.str();
|
||||
}
|
||||
|
||||
@@ -82,23 +82,25 @@ template< class T> std::string vlCovCvtToStr (const T& t) {
|
||||
/// Verilator coverage global class
|
||||
////
|
||||
/// Global class with methods affecting all coverage data.
|
||||
/// All public methods in this class are thread safe.
|
||||
|
||||
class VerilatedCov {
|
||||
VL_UNCOPYABLE(VerilatedCov);
|
||||
public:
|
||||
// GLOBAL METHODS
|
||||
/// Return default filename
|
||||
static const char* defaultFilename() { return "coverage.dat"; }
|
||||
static const char* defaultFilename() VL_PURE { return "coverage.dat"; }
|
||||
/// Write all coverage data to a file
|
||||
static void write (const char* filenamep = defaultFilename());
|
||||
static void write (const char* filenamep = defaultFilename()) VL_MT_SAFE;
|
||||
/// Insert a coverage item
|
||||
/// We accept from 1-30 key/value pairs, all as strings.
|
||||
/// Call _insert1, followed by _insert2 and _insert3
|
||||
/// Do not call directly; use VL_COVER_INSERT or higher level macros instead
|
||||
// _insert1: Remember item pointer with count. (Not const, as may add zeroing function)
|
||||
static void _inserti (vluint32_t* itemp);
|
||||
static void _inserti (vluint64_t* itemp);
|
||||
static void _inserti (vluint32_t* itemp) VL_MT_SAFE;
|
||||
static void _inserti (vluint64_t* itemp) VL_MT_SAFE;
|
||||
// _insert2: Set default filename and line number
|
||||
static void _insertf (const char* filename, int lineno);
|
||||
static void _insertf (const char* filename, int lineno) VL_MT_SAFE;
|
||||
// _insert3: Set parameters
|
||||
// We could have just the maximum argument version, but this compiles
|
||||
// much slower (nearly 2x) than having smaller versions also. However
|
||||
@@ -120,11 +122,11 @@ public:
|
||||
#undef A
|
||||
#undef D
|
||||
/// Clear coverage points (and call delete on all items)
|
||||
static void clear();
|
||||
static void clear() VL_MT_SAFE;
|
||||
/// Clear items not matching the provided string
|
||||
static void clearNonMatch (const char* matchp);
|
||||
static void clearNonMatch (const char* matchp) VL_MT_SAFE;
|
||||
/// Zero coverage points
|
||||
static void zero();
|
||||
static void zero() VL_MT_SAFE;
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
||||
+40
-41
@@ -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.
|
||||
//
|
||||
@@ -63,12 +63,6 @@ VLCOVGEN_ITEM("name=>'row2', short=>'r2', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'row3', short=>'r3', group=>0, default=>undef, ")
|
||||
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCovKey
|
||||
/// Verilator coverage global class
|
||||
////
|
||||
/// Global class with methods affecting all coverage data.
|
||||
|
||||
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN
|
||||
#define VL_CIK_COL0 "c0"
|
||||
#define VL_CIK_COL0_NAME "C0"
|
||||
@@ -102,42 +96,47 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
|
||||
#define VL_CIK_WEIGHT "w"
|
||||
// VLCOVGEN_CIK_AUTO_EDIT_END
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedCovKey
|
||||
/// Verilator coverage global class.
|
||||
/// This class is thread safe.
|
||||
|
||||
class VerilatedCovKey {
|
||||
public:
|
||||
static std::string shortKey(const std::string& key) {
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
||||
if (key == "col0") return VL_CIK_COL0;
|
||||
if (key == "col0_name") return VL_CIK_COL0_NAME;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+563
-101
@@ -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
|
||||
///
|
||||
@@ -42,11 +42,14 @@
|
||||
|
||||
// Not supported yet
|
||||
#define _VL_SVDPI_UNIMP() \
|
||||
vl_fatal(__FILE__,__LINE__,"",(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
|
||||
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("%%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;
|
||||
}
|
||||
|
||||
+29
-12
@@ -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 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_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
|
||||
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_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; ++i) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
|
||||
// Note we ignore X/Z in svLogicVecVal
|
||||
|
||||
/// 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 void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
|
||||
// Note we don't create X/Z in svLogicVecVal
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
|
||||
+25
-18
@@ -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.
|
||||
@@ -36,49 +36,56 @@
|
||||
//======================================================================
|
||||
// Conversion functions
|
||||
|
||||
extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
|
||||
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) {
|
||||
extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE;
|
||||
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
|
||||
WData lw[2]; VL_SET_WQ(lw, lhs);
|
||||
return VL_CVT_PACK_STR_NW(2, lw);
|
||||
}
|
||||
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) {
|
||||
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) VL_PURE {
|
||||
return lhs;
|
||||
}
|
||||
inline std::string VL_CVT_PACK_STR_NI(IData lhs) {
|
||||
inline std::string VL_CVT_PACK_STR_NI(IData lhs) VL_PURE {
|
||||
WData lw[1]; lw[0] = lhs;
|
||||
return VL_CVT_PACK_STR_NW(1, lw);
|
||||
}
|
||||
inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) {
|
||||
inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) VL_PURE {
|
||||
return lhs+rhs;
|
||||
}
|
||||
inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData rep) {
|
||||
inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData rep) VL_PURE {
|
||||
std::string out; out.reserve(lhs.length() * rep);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
extern IData VL_FOPEN_NI(const std::string& filename, IData mode);
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const std::string& ofilename, void* memp, IData start, IData end);
|
||||
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...);
|
||||
extern void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...);
|
||||
extern std::string VL_SFORMATF_NX(const char* formatp, ...);
|
||||
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rdp);
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) {
|
||||
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,
|
||||
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 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 {
|
||||
WData rwp[2]; // WData must always be at least 2
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
|
||||
if (got) rdr = rwp[0];
|
||||
return got;
|
||||
}
|
||||
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr) {
|
||||
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr) VL_MT_SAFE {
|
||||
WData rwp[2];
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
|
||||
if (got) rdr = VL_SET_QW(rwp);
|
||||
return got;
|
||||
}
|
||||
extern IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr);
|
||||
extern IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE;
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+201
-59
@@ -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.
|
||||
@@ -34,14 +34,138 @@
|
||||
#include "verilated_syms.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#ifdef VL_THREADED
|
||||
# include <functional>
|
||||
# include <queue>
|
||||
#endif
|
||||
|
||||
class VerilatedScope;
|
||||
|
||||
//======================================================================
|
||||
// Types
|
||||
// Threaded message passing
|
||||
|
||||
#ifdef VL_THREADED
|
||||
/// 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) const {
|
||||
return a.mtaskId() < b.mtaskId(); }
|
||||
};
|
||||
private:
|
||||
// MEMBERS
|
||||
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_mtaskId(Verilated::mtaskId()), m_cb(cb) {}
|
||||
~VerilatedMsg() {}
|
||||
// METHODS
|
||||
vluint32_t mtaskId() const { return m_mtaskId; }
|
||||
/// Execute the lambda function
|
||||
void run() const { m_cb(); }
|
||||
};
|
||||
|
||||
/// Each thread has a queue it pushes to
|
||||
/// This assumes no thread starts pushing the next tick until the previous has drained.
|
||||
/// If more aggressiveness is needed, a double-buffered scheme might work well.
|
||||
class VerilatedEvalMsgQueue {
|
||||
typedef std::multiset<VerilatedMsg, VerilatedMsg::Cmp> VerilatedThreadQueue;
|
||||
|
||||
std::atomic<vluint64_t> m_depth; ///< Current depth of queue (see comments below)
|
||||
|
||||
VerilatedMutex m_mutex; ///< Mutex protecting queue
|
||||
VerilatedThreadQueue m_queue VL_GUARDED_BY(m_mutex); ///< Message queue
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedEvalMsgQueue() : m_depth(0) {
|
||||
assert(atomic_is_lock_free(&m_depth));
|
||||
}
|
||||
~VerilatedEvalMsgQueue() { }
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedEvalMsgQueue);
|
||||
public:
|
||||
// METHODS
|
||||
//// Add message to queue (called by producer)
|
||||
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
m_queue.insert(msg); // Pass by value to copy the message into queue
|
||||
++m_depth;
|
||||
}
|
||||
/// Service queue until completion (called by consumer)
|
||||
void process() VL_EXCLUDES(m_mutex) {
|
||||
// Tracking m_depth is redundant to e.g. getting the mutex and looking at queue size,
|
||||
// but on the reader side it's 4x faster to test an atomic then getting a mutex
|
||||
while (m_depth) {
|
||||
// Wait for a message to be added to the queue
|
||||
// We don't use unique_lock as want to unlock with the message copy still in scope
|
||||
m_mutex.lock();
|
||||
assert(!m_queue.empty()); // Otherwise m_depth is wrong
|
||||
// Unfortunately to release the lock we need to copy the message
|
||||
// (Or have the message be a pointer, but then new/delete cost on each message)
|
||||
// We assume messages are small, so copy
|
||||
auto it = m_queue.begin();
|
||||
const VerilatedMsg msg = *(it);
|
||||
m_queue.erase(it);
|
||||
m_mutex.unlock();
|
||||
m_depth--; // Ok if outside critical section as only this code checks the value
|
||||
{
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("Executing callback from mtaskId=%d\n", msg.mtaskId()););
|
||||
msg.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Each thread has a local queue to build up messages until the end of the eval() call
|
||||
class VerilatedThreadMsgQueue {
|
||||
std::queue<VerilatedMsg> m_queue;
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedThreadMsgQueue() { }
|
||||
~VerilatedThreadMsgQueue() {
|
||||
// The only call of this with a non-empty queue is a fatal error.
|
||||
// So this does not flush the queue, as the destination queue is not known to this class.
|
||||
}
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedThreadMsgQueue);
|
||||
// METHODS
|
||||
static VerilatedThreadMsgQueue& threadton() {
|
||||
static VL_THREAD_LOCAL VerilatedThreadMsgQueue t_s;
|
||||
return t_s;
|
||||
}
|
||||
public:
|
||||
/// Add message to queue, called by producer
|
||||
static void post(const VerilatedMsg& msg) VL_MT_SAFE {
|
||||
// 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 {
|
||||
while (!threadton().m_queue.empty()) {
|
||||
evalMsgQp->post(threadton().m_queue.front());
|
||||
threadton().m_queue.pop();
|
||||
Verilated::endOfEvalReqdDec();
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif // VL_THREADED
|
||||
|
||||
//======================================================================
|
||||
// VerilatedImp
|
||||
|
||||
class VerilatedImp {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
@@ -56,58 +180,55 @@ class VerilatedImp {
|
||||
|
||||
// Nothing here is save-restored; users expected to re-register appropriately
|
||||
|
||||
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
||||
VerilatedScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
||||
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
|
||||
ArgVec m_argVec VL_GUARDED_BY(m_argMutex); ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
|
||||
|
||||
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
|
||||
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
|
||||
|
||||
VerilatedMutex m_nameMutex; ///< Protect m_nameMap
|
||||
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex); ///< Map of <scope_name, scope pointer>
|
||||
// Slow - somewhat static:
|
||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext; ///< Next export funcnum
|
||||
VerilatedMutex m_exportMutex; ///< Protect m_nameMap
|
||||
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex); ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
|
||||
|
||||
// File I/O
|
||||
std::vector<FILE*> m_fdps; ///< File descriptors
|
||||
std::deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
|
||||
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
|
||||
std::deque<IData> m_fdFree VL_GUARDED_BY(m_fdMutex); ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
|
||||
VerilatedImp()
|
||||
: m_argVecLoaded(false), m_exportNext(0) {
|
||||
m_fdps.resize(3);
|
||||
m_fdps[0] = stdin;
|
||||
m_fdps[1] = stdout;
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
static void internalsDump() {
|
||||
VL_PRINTF("internalsDump:\n");
|
||||
VL_PRINTF(" Argv:");
|
||||
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF(" %s",it->c_str());
|
||||
}
|
||||
VL_PRINTF("\n");
|
||||
VL_PRINTF(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
|
||||
scopesDump();
|
||||
exportsDump();
|
||||
userDump();
|
||||
}
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedImp);
|
||||
public:
|
||||
// METHODS - debug
|
||||
static void internalsDump() VL_MT_SAFE;
|
||||
static void versionDump() VL_MT_SAFE;
|
||||
|
||||
// METHODS - arguments
|
||||
static void commandArgs(int argc, const char** argv) {
|
||||
s_s.m_argVec.clear(); // Always clear
|
||||
commandArgsAdd(argc, argv);
|
||||
}
|
||||
static void commandArgsAdd(int argc, const char** argv) {
|
||||
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||
for (int i=0; i<argc; ++i) s_s.m_argVec.push_back(argv[i]);
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
static std::string argPlusMatch(const char* prefixp) {
|
||||
public:
|
||||
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 lock(s_s.m_argMutex);
|
||||
// Note prefixp does not include the leading "+"
|
||||
size_t len = strlen(prefixp);
|
||||
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
|
||||
s_s.m_argVecLoaded = true; // Complain only once
|
||||
vl_fatal("unknown",0,"",
|
||||
"%Error: Verilog called $test$plusargs or $value$plusargs without"
|
||||
" testbench C first calling Verilated::commandArgs(argc,argv).");
|
||||
VL_FATAL_MT("unknown",0,"",
|
||||
"%Error: Verilog called $test$plusargs or $value$plusargs without"
|
||||
" testbench C first calling Verilated::commandArgs(argc,argv).");
|
||||
}
|
||||
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
if ((*it)[0]=='+') {
|
||||
@@ -116,26 +237,32 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
return "";
|
||||
}
|
||||
private:
|
||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
|
||||
|
||||
public:
|
||||
// METHODS - user scope tracking
|
||||
// We implement this as a single large map instead of one map per scope
|
||||
// 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) {
|
||||
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||
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) {
|
||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
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;
|
||||
}
|
||||
private:
|
||||
/// Symbol table destruction cleans up the entries for each scope.
|
||||
static void userEraseScope(const VerilatedScope* scopep) {
|
||||
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope on destruction, so we simply iterate.
|
||||
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++);
|
||||
@@ -144,44 +271,50 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
static void userDump() {
|
||||
static void userDump() VL_MT_SAFE {
|
||||
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(" userDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_USER_DATA scope %p key %p: %p\n",
|
||||
if (first) { VL_PRINTF_MT(" userDump:\n"); first=false; }
|
||||
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n",
|
||||
it->first.first, it->first.second, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - scope name
|
||||
static void scopeInsert(const VerilatedScope* scopep) {
|
||||
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope at construction
|
||||
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) {
|
||||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||
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) {
|
||||
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope at destruction
|
||||
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_PRINTF(" scopesDump:\n");
|
||||
static void scopesDump() VL_MT_SAFE {
|
||||
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;
|
||||
scopep->scopeDump();
|
||||
}
|
||||
VL_PRINTF("\n");
|
||||
VL_PRINTF_MT("\n");
|
||||
}
|
||||
static const VerilatedScopeNameMap* scopeNameMap() {
|
||||
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE_POSTINIT {
|
||||
// Thread save only assuming this is called only after model construction completed
|
||||
return &s_s.m_nameMap;
|
||||
}
|
||||
|
||||
@@ -194,8 +327,9 @@ public: // But only for verilated*.cpp
|
||||
// in the design that also happen to have our same callback function.
|
||||
// Rather than a 2D map, the integer scheme saves 500ish ns on a likely
|
||||
// miss at the cost of a multiply, and all lookups move to slowpath.
|
||||
static int exportInsert(const char* namep) {
|
||||
static int exportInsert(const char* namep) VL_MT_SAFE {
|
||||
// Slow ok - called once/function at creation
|
||||
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++));
|
||||
@@ -204,26 +338,29 @@ public: // But only for verilated*.cpp
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
static int exportFind(const char* namep) {
|
||||
static int exportFind(const char* namep) VL_MT_SAFE {
|
||||
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
|
||||
+" but no such DPI export function name exists in ANY model");
|
||||
vl_fatal("unknown",0,"", msg.c_str());
|
||||
VL_FATAL_MT("unknown",0,"", msg.c_str());
|
||||
return -1;
|
||||
}
|
||||
static const char* exportName(int funcnum) {
|
||||
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 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() {
|
||||
static void exportsDump() VL_MT_SAFE {
|
||||
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(" exportDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
if (first) { VL_PRINTF_MT(" exportDump:\n"); first=false; }
|
||||
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
}
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
@@ -231,9 +368,10 @@ public: // But only for verilated*.cpp
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - file IO
|
||||
static IData fdNew(FILE* fp) {
|
||||
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 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();
|
||||
@@ -244,18 +382,22 @@ public: // But only for verilated*.cpp
|
||||
s_s.m_fdps[idx] = fp;
|
||||
return (idx | (1UL<<31)); // bit 31 indicates not MCD
|
||||
}
|
||||
static void fdDelete(IData fdi) {
|
||||
static void fdDelete(IData fdi) VL_MT_SAFE {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
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;
|
||||
s_s.m_fdFree.push_back(idx);
|
||||
}
|
||||
static inline FILE* fdToFp(IData fdi) {
|
||||
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
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];
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+24
-20
@@ -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.
|
||||
//
|
||||
@@ -48,7 +48,7 @@ static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last by
|
||||
//=============================================================================
|
||||
// Searalization
|
||||
|
||||
bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t size) {
|
||||
bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
bufferCheck();
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
vluint8_t miss = 0;
|
||||
@@ -58,17 +58,17 @@ bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t siz
|
||||
return (miss!=0);
|
||||
}
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize save-restore file as was made from different model");
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
|
||||
void VerilatedSerialize::header() {
|
||||
void VerilatedSerialize::header() VL_MT_UNSAFE_ONE {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_HEADER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR));
|
||||
@@ -78,29 +78,29 @@ void VerilatedSerialize::header() {
|
||||
os.write(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::header() {
|
||||
void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong header signature");
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedSerialize::trailer() {
|
||||
void VerilatedSerialize::trailer() VL_MT_UNSAFE_ONE {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_TRAILER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR));
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::trailer() {
|
||||
void VerilatedDeserialize::trailer() VL_MT_UNSAFE_ONE {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature");
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
}
|
||||
@@ -110,9 +110,10 @@ void VerilatedDeserialize::trailer() {
|
||||
//=============================================================================
|
||||
// Opening/Closing
|
||||
|
||||
void VerilatedSave::open (const char* filenamep) {
|
||||
void VerilatedSave::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltSave: opening save file %s\n",filenamep););
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("- save: opening save file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
@@ -132,9 +133,10 @@ void VerilatedSave::open (const char* filenamep) {
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedRestore::open (const char* filenamep) {
|
||||
void VerilatedRestore::open(const char* filenamep) VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltRestore: opening restore file %s\n",filenamep););
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("- restore: opening restore file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
@@ -155,7 +157,7 @@ void VerilatedRestore::open (const char* filenamep) {
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedSave::close () {
|
||||
void VerilatedSave::close() VL_MT_UNSAFE_ONE {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
@@ -163,7 +165,7 @@ void VerilatedSave::close () {
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
void VerilatedRestore::close () {
|
||||
void VerilatedRestore::close() VL_MT_UNSAFE_ONE {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
@@ -174,7 +176,8 @@ void VerilatedRestore::close () {
|
||||
//=============================================================================
|
||||
// Buffer management
|
||||
|
||||
void VerilatedSave::flush() {
|
||||
void VerilatedSave::flush() VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
vluint8_t* wp = m_bufp;
|
||||
while (1) {
|
||||
@@ -188,7 +191,7 @@ void VerilatedSave::flush() {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
@@ -197,7 +200,8 @@ void VerilatedSave::flush() {
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
}
|
||||
|
||||
void VerilatedRestore::fill() {
|
||||
void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
|
||||
m_assertOne.check();
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||
vluint8_t* rp = m_bufp;
|
||||
@@ -216,7 +220,7 @@ void VerilatedRestore::fill() {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
|
||||
+40
-31
@@ -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.
|
||||
//
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedSerialize {
|
||||
protected:
|
||||
@@ -37,14 +38,17 @@ protected:
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
void header();
|
||||
void trailer();
|
||||
void header() VL_MT_UNSAFE_ONE;
|
||||
void trailer() VL_MT_UNSAFE_ONE;
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedSerialize);
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSerialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
@@ -57,9 +61,9 @@ public:
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
std::string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
inline VerilatedSerialize& write (const void* __restrict datap, size_t size) {
|
||||
virtual void close() VL_MT_UNSAFE_ONE { flush(); }
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
inline VerilatedSerialize& write(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
@@ -71,8 +75,7 @@ public:
|
||||
return *this; // For function chaining
|
||||
}
|
||||
private:
|
||||
VerilatedSerialize(const VerilatedSerialize& ); ///< N/A, no copy constructor
|
||||
VerilatedSerialize& bufferCheck() {
|
||||
VerilatedSerialize& bufferCheck() VL_MT_UNSAFE_ONE {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
@@ -84,6 +87,7 @@ private:
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedDeserial - load structures from a stream representation
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedDeserialize {
|
||||
protected:
|
||||
@@ -94,15 +98,18 @@ protected:
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
virtual void fill() = 0;
|
||||
void header();
|
||||
void trailer();
|
||||
void header() VL_MT_UNSAFE_ONE;
|
||||
void trailer() VL_MT_UNSAFE_ONE;
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedDeserialize);
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedDeserialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
@@ -116,9 +123,9 @@ public:
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
std::string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
||||
virtual void close() VL_MT_UNSAFE_ONE { flush(); }
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
inline VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
@@ -130,12 +137,12 @@ public:
|
||||
return *this; // For function chaining
|
||||
}
|
||||
// Read a datum and compare with expected value
|
||||
bool readDiffers (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (vluint64_t data) { return readAssert(&data, sizeof(data)); }
|
||||
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)); }
|
||||
private:
|
||||
VerilatedDeserialize(const VerilatedDeserialize& ); ///< N/A, no copy constructor
|
||||
VerilatedDeserialize& bufferCheck() {
|
||||
bool readDiffers(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE;
|
||||
VerilatedDeserialize& bufferCheck() VL_MT_UNSAFE_ONE {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
|
||||
@@ -147,40 +154,42 @@ private:
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSave - serialize to a file
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
// CONSTRUCTORS
|
||||
VerilatedSave() { m_fd=-1; }
|
||||
virtual ~VerilatedSave() { close(); }
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const std::string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
void open(const char* filenamep) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors
|
||||
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
||||
virtual void close() VL_MT_UNSAFE_ONE;
|
||||
virtual void flush() VL_MT_UNSAFE_ONE;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedRestore - deserialize from a file
|
||||
// This class is not thread safe, it must be called by a single thread
|
||||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
// CONSTRUCTORS
|
||||
VerilatedRestore() { m_fd=-1; }
|
||||
virtual ~VerilatedRestore() { close(); }
|
||||
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const std::string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush() {}
|
||||
virtual void fill();
|
||||
void open(const char* filenamep) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors
|
||||
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
||||
virtual void close() VL_MT_UNSAFE_ONE;
|
||||
virtual void flush() VL_MT_UNSAFE_ONE {}
|
||||
virtual void fill() 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.
|
||||
@@ -35,11 +35,12 @@
|
||||
// We want to get a pointer to m_data in the sc_bv_base class,
|
||||
// but it is protected. So make an exposing class, then use
|
||||
// cast magic to get at it. Saves patching get_datap in SystemC.
|
||||
// This class is thread safe (though most of SystemC is not).
|
||||
|
||||
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
|
||||
class VlScBvExposer : public sc_bv_base {
|
||||
public:
|
||||
static const vluint32_t* sp_datap(const sc_bv_base& base) {
|
||||
static const vluint32_t* sp_datap(const sc_bv_base& base) VL_MT_SAFE {
|
||||
return static_cast<const VlScBvExposer*>(&base)->sp_datatp(); }
|
||||
const vluint32_t* sp_datatp() const { return reinterpret_cast<vluint32_t*>(m_data); }
|
||||
// Above reads this protected element in sc_bv_base:
|
||||
|
||||
@@ -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
|
||||
+13
-55
@@ -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,9 +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 and read only. It is constructed only
|
||||
/// when a model is built (from the main thread).
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@@ -28,68 +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
|
||||
|
||||
// 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
|
||||
|
||||
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:
|
||||
@@ -97,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:
|
||||
|
||||
+46
-29
@@ -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.
|
||||
//
|
||||
@@ -55,18 +55,24 @@ class VerilatedVcdSingleton {
|
||||
private:
|
||||
typedef std::vector<VerilatedVcd*> VcdVec;
|
||||
struct Singleton {
|
||||
VcdVec s_vcdVecp; ///< List of all created traces
|
||||
VerilatedMutex s_vcdMutex; ///< Protect the singleton
|
||||
VcdVec s_vcdVecp VL_GUARDED_BY(s_vcdMutex); ///< List of all created traces
|
||||
};
|
||||
static Singleton& singleton() { static Singleton s; return s; }
|
||||
public:
|
||||
static void pushVcd(VerilatedVcd* vcdp) {
|
||||
static void pushVcd(VerilatedVcd* vcdp) VL_EXCLUDES(singleton().s_vcdMutex) {
|
||||
VerilatedLockGuard lock(singleton().s_vcdMutex);
|
||||
singleton().s_vcdVecp.push_back(vcdp);
|
||||
}
|
||||
static void removeVcd(const VerilatedVcd* vcdp) {
|
||||
static void removeVcd(const VerilatedVcd* vcdp) VL_EXCLUDES(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() {
|
||||
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 lock(singleton().s_vcdMutex);
|
||||
for (VcdVec::const_iterator it=singleton().s_vcdVecp.begin(); it!=singleton().s_vcdVecp.end(); ++it) {
|
||||
VerilatedVcd* vcdp = *it;
|
||||
vcdp->flush();
|
||||
@@ -90,7 +96,7 @@ protected:
|
||||
VerilatedVcdCallback_t m_changecb; ///< Incremental Dumping Callback function
|
||||
void* m_userthis; ///< Fake "this" for caller
|
||||
vluint32_t m_code; ///< Starting code number
|
||||
// CREATORS
|
||||
// CONSTRUCTORS
|
||||
VerilatedVcdCallInfo (VerilatedVcdCallback_t icb, VerilatedVcdCallback_t fcb,
|
||||
VerilatedVcdCallback_t changecb,
|
||||
void* ut, vluint32_t code)
|
||||
@@ -103,16 +109,16 @@ protected:
|
||||
//=============================================================================
|
||||
// VerilatedVcdFile
|
||||
|
||||
bool VerilatedVcdFile::open(const std::string& name) {
|
||||
bool VerilatedVcdFile::open(const std::string& name) VL_MT_UNSAFE {
|
||||
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK, 0666);
|
||||
return (m_fd>=0);
|
||||
}
|
||||
|
||||
void VerilatedVcdFile::close() {
|
||||
void VerilatedVcdFile::close() VL_MT_UNSAFE {
|
||||
::close(m_fd);
|
||||
}
|
||||
|
||||
ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) {
|
||||
ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE {
|
||||
return ::write(m_fd, bufp, len);
|
||||
}
|
||||
|
||||
@@ -141,6 +147,7 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
|
||||
}
|
||||
|
||||
void VerilatedVcd::open (const char* filename) {
|
||||
m_assertOne.check();
|
||||
if (isOpen()) return;
|
||||
|
||||
// Set member variables
|
||||
@@ -171,6 +178,7 @@ void VerilatedVcd::open (const char* filename) {
|
||||
void VerilatedVcd::openNext (bool incFilename) {
|
||||
// Open next filename in concat sequence, mangle filename if
|
||||
// incFilename is true.
|
||||
m_assertOne.check();
|
||||
closePrev(); // Close existing
|
||||
if (incFilename) {
|
||||
// Find _0000.{ext} in filename
|
||||
@@ -219,7 +227,7 @@ void VerilatedVcd::makeNameMap() {
|
||||
m_namemapp = new NameMap;
|
||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||
cip->m_code = nextCode();
|
||||
cip->m_code = m_nextCode;
|
||||
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
|
||||
}
|
||||
|
||||
@@ -265,6 +273,7 @@ VerilatedVcd::~VerilatedVcd() {
|
||||
}
|
||||
|
||||
void VerilatedVcd::closePrev () {
|
||||
// This function is on the flush() call path
|
||||
if (!isOpen()) return;
|
||||
|
||||
bufferFlush();
|
||||
@@ -273,6 +282,7 @@ void VerilatedVcd::closePrev () {
|
||||
}
|
||||
|
||||
void VerilatedVcd::closeErr () {
|
||||
// This function is on the flush() call path
|
||||
// Close due to an error. We might abort before even getting here,
|
||||
// depending on the definition of vl_fatal.
|
||||
if (!isOpen()) return;
|
||||
@@ -283,6 +293,8 @@ void VerilatedVcd::closeErr () {
|
||||
}
|
||||
|
||||
void VerilatedVcd::close() {
|
||||
// This function is on the flush() call path
|
||||
m_assertOne.check();
|
||||
if (!isOpen()) return;
|
||||
if (m_evcd) {
|
||||
printStr("$vcdclose ");
|
||||
@@ -311,10 +323,10 @@ void VerilatedVcd::printTime (vluint64_t timeui) {
|
||||
// Dinotrace doesn't mind, but Cadence vvision seems to choke
|
||||
if (VL_UNLIKELY(timeui < m_timeLastDump)) {
|
||||
timeui = m_timeLastDump;
|
||||
static bool backTime = false;
|
||||
static VL_THREAD_LOCAL bool backTime = false;
|
||||
if (!backTime) {
|
||||
backTime = true;
|
||||
VL_PRINTF("VCD time is moving backwards, wave file may be incorrect.\n");
|
||||
VL_PRINTF_MT("%%Warning: VCD time is moving backwards, wave file may be incorrect.\n");
|
||||
}
|
||||
}
|
||||
m_timeLastDump = timeui;
|
||||
@@ -331,14 +343,16 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedVcd::bufferFlush () {
|
||||
void VerilatedVcd::bufferFlush () VL_MT_UNSAFE_ONE {
|
||||
// This function is on the flush() call path
|
||||
// We add output data to m_writep.
|
||||
// When it gets nearly full we dump it using this routine which calls write()
|
||||
// This is much faster than using buffered I/O
|
||||
m_assertOne.check();
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
char* wp = m_wrBufp;
|
||||
while (1) {
|
||||
@@ -353,7 +367,7 @@ void VerilatedVcd::bufferFlush () {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
std::string msg = std::string("VerilatedVcd::bufferFlush: ")+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
VL_FATAL_MT("",0,"",msg.c_str());
|
||||
closeErr();
|
||||
break;
|
||||
}
|
||||
@@ -368,12 +382,14 @@ void VerilatedVcd::bufferFlush () {
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -499,19 +515,20 @@ void VerilatedVcd::dumpHeader () {
|
||||
}
|
||||
|
||||
void VerilatedVcd::module (const std::string& name) {
|
||||
m_assertOne.check();
|
||||
m_modName = name;
|
||||
}
|
||||
|
||||
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
|
||||
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
||||
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
|
||||
if (!code) { VL_FATAL_MT(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
|
||||
|
||||
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
|
||||
int codesNeeded = 1+int(bits/32);
|
||||
if (tri) codesNeeded *= 2; // Space in change array for __en signals
|
||||
|
||||
// Make sure array is large enough
|
||||
m_nextCode = std::max(nextCode(), code+codesNeeded);
|
||||
m_nextCode = std::max(m_nextCode, code+codesNeeded);
|
||||
if (m_sigs.capacity() <= m_nextCode) {
|
||||
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
|
||||
}
|
||||
@@ -552,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);
|
||||
@@ -617,15 +634,16 @@ void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
|
||||
//=============================================================================
|
||||
// Callbacks
|
||||
|
||||
void VerilatedVcd::addCallback (
|
||||
void VerilatedVcd::addCallback VL_MT_UNSAFE_ONE (
|
||||
VerilatedVcdCallback_t initcb, VerilatedVcdCallback_t fullcb, VerilatedVcdCallback_t changecb,
|
||||
void* userthis)
|
||||
{
|
||||
m_assertOne.check();
|
||||
if (VL_UNLIKELY(isOpen())) {
|
||||
std::string msg = std::string("Internal: ")+__FILE__+"::"+__FUNCTION__+" called with already open file";
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||
VL_FATAL_MT(__FILE__,__LINE__,"",msg.c_str());
|
||||
}
|
||||
VerilatedVcdCallInfo* vci = new VerilatedVcdCallInfo(initcb, fullcb, changecb, userthis, nextCode());
|
||||
VerilatedVcdCallInfo* vci = new VerilatedVcdCallInfo(initcb, fullcb, changecb, userthis, m_nextCode);
|
||||
m_callbacks.push_back(vci);
|
||||
}
|
||||
|
||||
@@ -633,15 +651,17 @@ void VerilatedVcd::addCallback (
|
||||
// Dumping
|
||||
|
||||
void VerilatedVcd::dumpFull (vluint64_t timeui) {
|
||||
m_assertOne.check();
|
||||
dumpPrep (timeui);
|
||||
Verilated::quiesce();
|
||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||
(cip->m_fullcb) (this, cip->m_userthis, cip->m_code);
|
||||
}
|
||||
dumpDone ();
|
||||
}
|
||||
|
||||
void VerilatedVcd::dump (vluint64_t timeui) {
|
||||
m_assertOne.check();
|
||||
if (!isOpen()) return;
|
||||
if (VL_UNLIKELY(m_fullDump)) {
|
||||
m_fullDump = false; // No need for more full dumps
|
||||
@@ -653,11 +673,11 @@ void VerilatedVcd::dump (vluint64_t timeui) {
|
||||
if (!isOpen()) return;
|
||||
}
|
||||
dumpPrep (timeui);
|
||||
Verilated::quiesce();
|
||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||
(cip->m_changecb) (this, cip->m_userthis, cip->m_code);
|
||||
}
|
||||
dumpDone();
|
||||
}
|
||||
|
||||
void VerilatedVcd::dumpPrep (vluint64_t timeui) {
|
||||
@@ -666,13 +686,10 @@ void VerilatedVcd::dumpPrep (vluint64_t timeui) {
|
||||
printStr("\n");
|
||||
}
|
||||
|
||||
void VerilatedVcd::dumpDone () {
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Static members
|
||||
|
||||
void VerilatedVcd::flush_all() {
|
||||
void VerilatedVcd::flush_all() VL_MT_UNSAFE_ONE {
|
||||
VerilatedVcdSingleton::flush_all();
|
||||
}
|
||||
|
||||
|
||||
+32
-25
@@ -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.
|
||||
//
|
||||
@@ -24,6 +24,7 @@
|
||||
#define _VERILATED_VCD_C_H_ 1
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -44,9 +45,9 @@ public:
|
||||
// METHODS
|
||||
VerilatedVcdFile() : m_fd(0) {}
|
||||
virtual ~VerilatedVcdFile() {}
|
||||
virtual bool open(const std::string& name);
|
||||
virtual void close();
|
||||
virtual ssize_t write(const char* bufp, ssize_t len);
|
||||
virtual bool open(const std::string& name) VL_MT_UNSAFE;
|
||||
virtual void close() VL_MT_UNSAFE;
|
||||
virtual ssize_t write(const char* bufp, ssize_t len) VL_MT_UNSAFE;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
@@ -104,8 +105,10 @@ private:
|
||||
typedef std::map<std::string,std::string> NameMap;
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
void bufferResize(vluint64_t minsize);
|
||||
void bufferFlush();
|
||||
void bufferFlush() VL_MT_UNSAFE_ONE;
|
||||
inline void bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
@@ -136,7 +139,7 @@ private:
|
||||
if (code>=(94)) *m_writep++ = static_cast<char>((code/94)%94+33);
|
||||
*m_writep++ = static_cast<char>((code)%94+33);
|
||||
}
|
||||
static std::string stringCode (vluint32_t code) {
|
||||
static std::string stringCode (vluint32_t code) VL_PURE {
|
||||
std::string out;
|
||||
if (code>=(94*94*94)) out += static_cast<char>((code/94/94/94)%94+33);
|
||||
if (code>=(94*94)) out += static_cast<char>((code/94/94)%94+33);
|
||||
@@ -144,20 +147,13 @@ private:
|
||||
return out + static_cast<char>((code)%94+33);
|
||||
}
|
||||
|
||||
VerilatedVcd(const VerilatedVcd& ); ///< N/A, no copy constructor
|
||||
|
||||
protected:
|
||||
// METHODS
|
||||
void evcd(bool flag) { m_evcd = flag; }
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedVcd);
|
||||
public:
|
||||
// CREATORS
|
||||
explicit VerilatedVcd(VerilatedVcdFile* filep=NULL);
|
||||
~VerilatedVcd();
|
||||
|
||||
// ACCESSORS
|
||||
/// Inside dumping routines, return next VCD signal code
|
||||
vluint32_t nextCode() const {return m_nextCode;}
|
||||
/// Set size in megabytes after which new file should be created
|
||||
void rolloverMB(vluint64_t rolloverMB) { m_rolloverMB=rolloverMB; };
|
||||
/// Is file open?
|
||||
@@ -168,11 +164,13 @@ public:
|
||||
inline bool isScopeEscape(char c) { return isspace(c) || c==m_scopeEscape; }
|
||||
|
||||
// METHODS
|
||||
void open (const char* filename); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const char* filename) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors
|
||||
void openNext (bool incFilename); ///< Open next data-only file
|
||||
void flush() { bufferFlush(); } ///< Flush any remaining data
|
||||
static void flush_all(); ///< Flush any remaining data from all files
|
||||
void close (); ///< Close the file
|
||||
void close() VL_MT_UNSAFE_ONE; ///< Close the file
|
||||
/// Flush any remaining data to this file
|
||||
void flush() VL_MT_UNSAFE_ONE { bufferFlush(); }
|
||||
/// Flush any remaining data from all files
|
||||
static void flush_all() VL_MT_UNSAFE_ONE;
|
||||
|
||||
void set_time_unit (const char* unit); ///< Set time units (s/ms, defaults to ns)
|
||||
void set_time_unit (const std::string& unit) { set_time_unit(unit.c_str()); }
|
||||
@@ -191,7 +189,7 @@ public:
|
||||
/// Inside dumping routines, declare callbacks for tracings
|
||||
void addCallback (VerilatedVcdCallback_t init, VerilatedVcdCallback_t full,
|
||||
VerilatedVcdCallback_t change,
|
||||
void* userthis);
|
||||
void* userthis) VL_MT_UNSAFE_ONE;
|
||||
|
||||
/// Inside dumping routines, declare a module
|
||||
void module (const std::string& name);
|
||||
@@ -393,18 +391,27 @@ public:
|
||||
fullFloat (code, newval);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// METHODS
|
||||
void evcd(bool flag) { m_evcd = flag; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedVcdC
|
||||
/// Create a VCD dump file in C standalone (no SystemC) simulations.
|
||||
/// Also derived for use in SystemC simulations.
|
||||
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
|
||||
|
||||
class VerilatedVcdC {
|
||||
VerilatedVcd m_sptrace; ///< Trace file being created
|
||||
public:
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedVcdC);
|
||||
public:
|
||||
explicit VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
|
||||
~VerilatedVcdC() {}
|
||||
public:
|
||||
// ACCESSORS
|
||||
/// Is file open?
|
||||
bool isOpen() const { return m_sptrace.isOpen(); }
|
||||
@@ -412,17 +419,17 @@ public:
|
||||
/// Open a new VCD file
|
||||
/// This includes a complete header dump each time it is called,
|
||||
/// just as if this object was deleted and reconstructed.
|
||||
void open (const char* filename) { m_sptrace.open(filename); }
|
||||
void open(const char* filename) VL_MT_UNSAFE_ONE { m_sptrace.open(filename); }
|
||||
/// Continue a VCD dump by rotating to a new file name
|
||||
/// The header is only in the first file created, this allows
|
||||
/// "cat" to be used to combine the header plus any number of data files.
|
||||
void openNext (bool incFilename=true) { m_sptrace.openNext(incFilename); }
|
||||
void openNext(bool incFilename=true) VL_MT_UNSAFE_ONE { m_sptrace.openNext(incFilename); }
|
||||
/// Set size in megabytes after which new file should be created
|
||||
void rolloverMB(size_t rolloverMB) { m_sptrace.rolloverMB(rolloverMB); };
|
||||
/// Close dump
|
||||
void close() { m_sptrace.close(); }
|
||||
void close() VL_MT_UNSAFE_ONE { m_sptrace.close(); }
|
||||
/// Flush dump
|
||||
void flush() { m_sptrace.flush(); }
|
||||
void flush() VL_MT_UNSAFE_ONE { m_sptrace.flush(); }
|
||||
/// Write one cycle of dump data
|
||||
void dump (vluint64_t timeui) { m_sptrace.dump(timeui); }
|
||||
/// Write one cycle of dump data - backward compatible and to reduce
|
||||
|
||||
@@ -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.
|
||||
//
|
||||
@@ -17,6 +17,8 @@
|
||||
/// \file
|
||||
/// \brief Verilator tracing in VCD format
|
||||
///
|
||||
/// This class is not threadsafe, as the SystemC kernel is not threadsafe.
|
||||
///
|
||||
//=============================================================================
|
||||
// SPDIFF_OFF
|
||||
|
||||
@@ -37,6 +39,8 @@ class VerilatedVcdSc
|
||||
: sc_trace_file
|
||||
, public VerilatedVcdC
|
||||
{
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedVcdSc);
|
||||
public:
|
||||
VerilatedVcdSc() {
|
||||
sc_get_curr_simcontext()->add_trace_file(this);
|
||||
@@ -56,8 +60,9 @@ public:
|
||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
# endif
|
||||
}
|
||||
|
||||
virtual ~VerilatedVcdSc() {}
|
||||
|
||||
// METHODS
|
||||
/// Called by SystemC simulate()
|
||||
virtual void cycle (bool delta_cycle) {
|
||||
# if (SYSTEMC_VERSION>20011000)
|
||||
@@ -91,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 )
|
||||
|
||||
+610
-75
File diff suppressed because it is too large
Load Diff
+11
-459
@@ -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: VPI implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the VPI.
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the VPI.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@@ -29,472 +29,24 @@
|
||||
#include "verilated.h"
|
||||
#include "verilated_syms.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
//======================================================================
|
||||
// From IEEE 1800-2009 annex K
|
||||
|
||||
#include "vltstd/vpi_user.h"
|
||||
|
||||
//======================================================================
|
||||
// Internal constants
|
||||
|
||||
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
|
||||
#define VL_VPI_LINE_SIZE 8192
|
||||
|
||||
//======================================================================
|
||||
// Internal macros
|
||||
|
||||
#define _VL_VPI_INTERNAL VerilatedVpi::error_info()->setMessage(vpiInternal)->setMessage
|
||||
#define _VL_VPI_SYSTEM VerilatedVpi::error_info()->setMessage(vpiSystem )->setMessage
|
||||
#define _VL_VPI_ERROR VerilatedVpi::error_info()->setMessage(vpiError )->setMessage
|
||||
#define _VL_VPI_WARNING VerilatedVpi::error_info()->setMessage(vpiWarning )->setMessage
|
||||
#define _VL_VPI_NOTICE VerilatedVpi::error_info()->setMessage(vpiNotice )->setMessage
|
||||
#define _VL_VPI_ERROR_RESET VerilatedVpi::error_info()->resetError
|
||||
|
||||
// Not supported yet
|
||||
#define _VL_VPI_UNIMP() \
|
||||
_VL_VPI_ERROR(__FILE__,__LINE__,Verilated::catName("Unsupported VPI function: ",VL_FUNC));
|
||||
|
||||
//======================================================================
|
||||
// Implementation
|
||||
|
||||
// Base VPI handled object
|
||||
class VerilatedVpio {
|
||||
// MEM MANGLEMENT
|
||||
static vluint8_t* s_freeHead;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedVpio() {}
|
||||
virtual ~VerilatedVpio() {}
|
||||
inline static void* operator new(size_t size) {
|
||||
// We new and delete tons of vpi structures, so keep them around
|
||||
// To simplify our free list, we use a size large enough for all derived types
|
||||
// We reserve word zero for the next pointer, as that's safer in case a
|
||||
// dangling reference to the original remains around.
|
||||
static size_t chunk = 96;
|
||||
if (VL_UNLIKELY(size>chunk)) vl_fatal(__FILE__,__LINE__,"", "increase chunk");
|
||||
if (VL_LIKELY(s_freeHead)) {
|
||||
vluint8_t* newp = s_freeHead;
|
||||
s_freeHead = *((vluint8_t**)newp);
|
||||
return newp+8;
|
||||
} else {
|
||||
// +8: 8 bytes for next
|
||||
vluint8_t* newp = reinterpret_cast<vluint8_t*>(::operator new(chunk+8));
|
||||
return newp+8;
|
||||
}
|
||||
}
|
||||
inline static void operator delete(void* obj, size_t size) {
|
||||
vluint8_t* oldp = ((vluint8_t*)obj)-8;
|
||||
*((void**)oldp) = s_freeHead;
|
||||
s_freeHead = oldp;
|
||||
}
|
||||
// MEMBERS
|
||||
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>"; }
|
||||
virtual const char* fullname() const { return "<null>"; }
|
||||
virtual const char* defname() const { return "<null>"; }
|
||||
virtual vluint32_t type() const { return 0; }
|
||||
virtual vluint32_t size() const { return 0; }
|
||||
virtual const VerilatedRange* rangep() const { return NULL; }
|
||||
virtual vpiHandle dovpi_scan() { return 0; }
|
||||
};
|
||||
|
||||
typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
|
||||
|
||||
class VerilatedVpioCb : public VerilatedVpio {
|
||||
t_cb_data m_cbData;
|
||||
s_vpi_value m_value;
|
||||
QData m_time;
|
||||
public:
|
||||
// cppcheck-suppress uninitVar // m_value
|
||||
VerilatedVpioCb(const t_cb_data* cbDatap, QData time)
|
||||
: m_cbData(*cbDatap), m_time(time) {
|
||||
m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal;
|
||||
m_cbData.value = &m_value;
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
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; }
|
||||
t_cb_data* cb_datap() { return &(m_cbData); }
|
||||
QData time() const { return m_time; }
|
||||
};
|
||||
|
||||
class VerilatedVpioConst : public VerilatedVpio {
|
||||
vlsint32_t m_num;
|
||||
public:
|
||||
explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
|
||||
virtual ~VerilatedVpioConst() {}
|
||||
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; }
|
||||
};
|
||||
|
||||
class VerilatedVpioRange : public VerilatedVpio {
|
||||
const VerilatedRange* m_range;
|
||||
vlsint32_t m_iteration;
|
||||
public:
|
||||
explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() const { return vpiRange; }
|
||||
virtual vluint32_t size() const { return m_range->elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return m_range; }
|
||||
int iteration() const { return m_iteration; }
|
||||
void iterationInc() { ++m_iteration; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (!iteration()) {
|
||||
VerilatedVpioRange* nextp = new VerilatedVpioRange(*this);
|
||||
nextp->iterationInc();
|
||||
return ((nextp)->castVpiHandle());
|
||||
} else {
|
||||
return 0; // End of list - only one deep
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioScope : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
public:
|
||||
explicit VerilatedVpioScope(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep) {}
|
||||
virtual ~VerilatedVpioScope() {}
|
||||
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(); }
|
||||
virtual const char* fullname() const { return m_scopep->name(); }
|
||||
};
|
||||
|
||||
class VerilatedVpioVar : public VerilatedVpio {
|
||||
const VerilatedVar* m_varp;
|
||||
const VerilatedScope* m_scopep;
|
||||
vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange
|
||||
union {
|
||||
vluint8_t u8[4];
|
||||
vluint32_t u32;
|
||||
} m_mask; // memoized variable mask
|
||||
vluint32_t m_entSize; // memoized variable size
|
||||
protected:
|
||||
void* m_varDatap; // varp()->datap() adjusted for array entries
|
||||
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();
|
||||
}
|
||||
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_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); }
|
||||
const VerilatedVar* varp() const { return m_varp; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
vluint32_t mask() const { return m_mask.u32; }
|
||||
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
vluint32_t index() { return m_index; }
|
||||
virtual vluint32_t type() const {
|
||||
if (varp()->vldir() != vpiNoDirection) return vpiPort;
|
||||
return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
|
||||
}
|
||||
virtual vluint32_t size() const { return get_range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &get_range(); }
|
||||
virtual const char* name() const { return m_varp->name(); }
|
||||
virtual const char* fullname() const {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
out = std::string(m_scopep->name())+"."+name();
|
||||
return out.c_str();
|
||||
}
|
||||
void* prevDatap() const { return m_prevDatap; }
|
||||
void* varDatap() const { return m_varDatap; }
|
||||
void createPrevDatap() {
|
||||
if (VL_UNLIKELY(!m_prevDatap)) {
|
||||
m_prevDatap = new vluint8_t [entSize()];
|
||||
memcpy(prevDatap(), varp()->datap(), entSize());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioMemoryWord : public VerilatedVpioVar {
|
||||
public:
|
||||
VerilatedVpioMemoryWord(const VerilatedVar* varp, const VerilatedScope* scopep,
|
||||
vlsint32_t index, int offset)
|
||||
: VerilatedVpioVar(varp, scopep) {
|
||||
m_index = index;
|
||||
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
|
||||
}
|
||||
virtual ~VerilatedVpioMemoryWord() {}
|
||||
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 const char* fullname() const {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
out = std::string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
return out.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioVarIter : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
VerilatedVarNameMap::const_iterator m_it;
|
||||
bool m_started;
|
||||
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); }
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
VerilatedVarNameMap* varsp = m_scopep->varsp();
|
||||
if (VL_UNLIKELY(!m_started)) { m_it = varsp->begin(); m_started=true; }
|
||||
else if (VL_UNLIKELY(m_it == varsp->end())) return 0;
|
||||
else ++m_it;
|
||||
if (m_it == varsp->end()) return 0;
|
||||
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
|
||||
->castVpiHandle());
|
||||
} else {
|
||||
return 0; // End of list - only one deep
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioMemoryWordIter : public VerilatedVpio {
|
||||
const vpiHandle m_handle;
|
||||
const VerilatedVar* m_varp;
|
||||
vlsint32_t m_iteration;
|
||||
vlsint32_t m_direction;
|
||||
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) { }
|
||||
virtual ~VerilatedVpioMemoryWordIter() {}
|
||||
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;
|
||||
}
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
vpiHandle result;
|
||||
if (m_done) return 0;
|
||||
result = vpi_handle_by_index(m_handle, m_iteration);
|
||||
iterationInc();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
struct VerilatedVpiTimedCbsCmp {
|
||||
/// Ordering sets keyed by time, then callback descriptor
|
||||
bool operator() (const std::pair<QData,VerilatedVpioCb*>& a,
|
||||
const std::pair<QData,VerilatedVpioCb*>& b) const {
|
||||
if (a.first < b.first) return 1;
|
||||
if (a.first > b.first) return 0;
|
||||
return a.second < b.second;
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpiError;
|
||||
|
||||
class VerilatedVpi {
|
||||
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
|
||||
typedef std::list<VerilatedVpioCb*> VpioCbList;
|
||||
typedef std::set<std::pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
|
||||
|
||||
struct product_info {
|
||||
PLI_BYTE8* product;
|
||||
};
|
||||
|
||||
VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
|
||||
VpioTimedCbs m_timedCbs; // Time based callbacks
|
||||
VerilatedVpiError* m_errorInfop; // Container for vpi error info
|
||||
|
||||
static VerilatedVpi s_s; // Singleton
|
||||
|
||||
public:
|
||||
VerilatedVpi() { m_errorInfop=NULL; }
|
||||
~VerilatedVpi() {}
|
||||
static void cbReasonAdd(VerilatedVpioCb* vop) {
|
||||
if (vop->reason() == cbValueChange) {
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
varop->createPrevDatap();
|
||||
}
|
||||
}
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
|
||||
s_s.m_cbObjLists[vop->reason()].push_back(vop);
|
||||
}
|
||||
static void cbTimedAdd(VerilatedVpioCb* vop) {
|
||||
s_s.m_timedCbs.insert(std::make_pair(vop->time(), vop));
|
||||
}
|
||||
static void cbReasonRemove(VerilatedVpioCb* cbp) {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
|
||||
// We do not remove it now as we may be iterating the list,
|
||||
// instead set to NULL and will cleanup later
|
||||
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end(); ++it) {
|
||||
if (*it == cbp) *it = NULL;
|
||||
}
|
||||
}
|
||||
static void cbTimedRemove(VerilatedVpioCb* cbp) {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(std::make_pair(cbp->time(),cbp));
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
|
||||
s_s.m_timedCbs.erase(it);
|
||||
}
|
||||
}
|
||||
static void callTimedCbs() {
|
||||
QData time = VL_TIME_Q();
|
||||
for (VpioTimedCbs::iterator it=s_s.m_timedCbs.begin(); it!=s_s.m_timedCbs.end(); ) {
|
||||
if (VL_UNLIKELY(it->first <= time)) {
|
||||
VerilatedVpioCb* vop = it->second;
|
||||
++it; // iterator may be deleted by callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: timed_callback %p\n",vop););
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
else { ++it; }
|
||||
}
|
||||
}
|
||||
static QData cbNextDeadline() {
|
||||
VpioTimedCbs::const_iterator it=s_s.m_timedCbs.begin();
|
||||
if (VL_LIKELY(it!=s_s.m_timedCbs.end())) {
|
||||
return it->first;
|
||||
} else {
|
||||
return ~VL_ULL(0); // maxquad
|
||||
}
|
||||
}
|
||||
static void callCbs(vluint32_t reason) {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
|
||||
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
|
||||
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
|
||||
it = cbObjList.erase(it);
|
||||
continue;
|
||||
}
|
||||
VerilatedVpioCb* vop = *it++;
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
static void callValueCbs() {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
|
||||
typedef std::set<VerilatedVpioVar*> VpioVarSet;
|
||||
VpioVarSet update; // set of objects to update after callbacks
|
||||
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
|
||||
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
|
||||
it = cbObjList.erase(it);
|
||||
continue;
|
||||
}
|
||||
VerilatedVpioCb* vop = *it++;
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
void* newDatap = varop->varDatap();
|
||||
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_test %s v[0]=%d/%d %p %p\n",
|
||||
varop->fullname(), *((CData*)newDatap), *((CData*)prevDatap),
|
||||
newDatap, prevDatap););
|
||||
if (memcmp(prevDatap, newDatap, varop->entSize())) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
|
||||
vop,varop->fullname(), *((CData*)newDatap)););
|
||||
update.insert(varop);
|
||||
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (VpioVarSet::const_iterator it=update.begin(); it!=update.end(); ++it) {
|
||||
memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
|
||||
}
|
||||
}
|
||||
|
||||
static VerilatedVpiError* error_info(); // getter for vpi error info
|
||||
/// Call timed callbacks
|
||||
/// Users should call this from their main loops
|
||||
static void callTimedCbs() VL_MT_UNSAFE_ONE;
|
||||
/// Call value based callbacks
|
||||
/// Users should call this from their main loops
|
||||
static void callValueCbs() VL_MT_UNSAFE_ONE;
|
||||
/// Self test, for internal use only
|
||||
static void selfTest() VL_MT_UNSAFE_ONE;
|
||||
};
|
||||
|
||||
#define _VL_VPI_ERROR_SET \
|
||||
do { \
|
||||
va_list args; \
|
||||
va_start(args, message); \
|
||||
VL_VSNPRINTF(m_buff, sizeof(m_buff), message.c_str(), args); \
|
||||
va_end(args); \
|
||||
} while (0)
|
||||
|
||||
class VerilatedVpiError {
|
||||
//// Container for vpi error info
|
||||
|
||||
t_vpi_error_info m_errorInfo;
|
||||
bool m_flag;
|
||||
char m_buff[VL_VPI_LINE_SIZE];
|
||||
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
|
||||
m_errorInfo.message = message;
|
||||
m_errorInfo.file = file;
|
||||
m_errorInfo.line = line;
|
||||
m_errorInfo.code = code;
|
||||
do_callbacks();
|
||||
}
|
||||
void do_callbacks() {
|
||||
if (getError()->level >= vpiError && Verilated::fatalOnVpiError()) {
|
||||
// Stop on vpi error/unsupported
|
||||
vpi_unsupported();
|
||||
}
|
||||
// We need to run above code first because in the case that the callback executes further vpi
|
||||
// functions we will loose the error as it will be overwritten.
|
||||
VerilatedVpi::callCbs(cbPLIError);
|
||||
}
|
||||
public:
|
||||
|
||||
VerilatedVpiError() : m_flag(false) {
|
||||
m_buff[0] = '\0';
|
||||
m_errorInfo.product = (PLI_BYTE8*)Verilated::productName();
|
||||
}
|
||||
~VerilatedVpiError() {}
|
||||
static void selfTest();
|
||||
VerilatedVpiError* setMessage(PLI_INT32 level) {
|
||||
m_flag=true;
|
||||
m_errorInfo.level = level;
|
||||
return this;
|
||||
}
|
||||
void setMessage(std::string file, PLI_INT32 line, std::string message, ...) {
|
||||
static VL_THREAD_LOCAL std::string filehold;
|
||||
_VL_VPI_ERROR_SET;
|
||||
m_errorInfo.state = vpiPLI;
|
||||
filehold = file;
|
||||
setError((PLI_BYTE8*)m_buff, NULL, (PLI_BYTE8*)filehold.c_str(), line);
|
||||
}
|
||||
p_vpi_error_info getError() {
|
||||
if (m_flag) return &m_errorInfo;
|
||||
return NULL;
|
||||
}
|
||||
void resetError() {
|
||||
m_flag=false;
|
||||
}
|
||||
static void vpi_unsupported() {
|
||||
// Not supported yet
|
||||
p_vpi_error_info error_info_p = VerilatedVpi::error_info()->getError();
|
||||
if (error_info_p) {
|
||||
vl_fatal(error_info_p->file, error_info_p->line, "", error_info_p->message);
|
||||
return;
|
||||
}
|
||||
vl_fatal(__FILE__, __LINE__, "", "vpi_unsupported called without error info set");
|
||||
}
|
||||
static const char* strFromVpiVal(PLI_INT32 vpiVal);
|
||||
static const char* strFromVpiObjType(PLI_INT32 vpiVal);
|
||||
static const char* strFromVpiMethod(PLI_INT32 vpiVal);
|
||||
static const char* strFromVpiCallbackReason(PLI_INT32 vpiVal);
|
||||
static const char* strFromVpiProp(PLI_INT32 vpiVal);
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+116
-17
@@ -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.
|
||||
@@ -42,43 +42,84 @@
|
||||
# else
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__ ((format (printf, fmtArgNum, fmtArgNum+1)))
|
||||
# endif
|
||||
# define VL_ATTR_PURE __attribute__ ((pure))
|
||||
# define VL_ATTR_UNUSED __attribute__ ((unused))
|
||||
# define VL_FUNC __func__
|
||||
# if defined(__clang__) && defined(VL_THREADED)
|
||||
# define VL_ACQUIRE(...) __attribute__ ((acquire_capability(__VA_ARGS__)))
|
||||
# define VL_ACQUIRE_SHARED(...) __attribute__ ((acquire_shared_capability(__VA_ARGS__)))
|
||||
# define VL_RELEASE(...) __attribute__ ((release_capability(__VA_ARGS__)))
|
||||
# define VL_RELEASE_SHARED(...) __attribute__ ((release_shared_capability(__VA_ARGS__)))
|
||||
# define VL_TRY_ACQUIRE(...) __attribute__ ((try_acquire_capability(__VA_ARGS__)))
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) __attribute__ ((try_acquire_shared_capability(__VA_ARGS__)))
|
||||
# define VL_CAPABILITY(x) __attribute__ ((capability(x)))
|
||||
# define VL_REQUIRES(x) __attribute__ ((requires_capability(x)))
|
||||
# define VL_GUARDED_BY(x) __attribute__ ((guarded_by(x)))
|
||||
# define VL_EXCLUDES(x) __attribute__ ((locks_excluded(x)))
|
||||
# define VL_SCOPED_CAPABILITY __attribute__ ((scoped_lockable))
|
||||
# endif
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define VL_UNREACHABLE __builtin_unreachable();
|
||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
||||
#elif defined(_MSC_VER)
|
||||
# define VL_ATTR_ALIGNED(alignment)
|
||||
# define VL_ATTR_ALWINLINE
|
||||
# define VL_ATTR_NORETURN
|
||||
# define VL_ATTR_PRINTF(fmtArgNum)
|
||||
# define VL_ATTR_UNUSED
|
||||
# define VL_FUNC __FUNCTION__
|
||||
# define VL_LIKELY(x) (!!(x))
|
||||
# define VL_UNLIKELY(x) (!!(x))
|
||||
# define VL_UNREACHABLE
|
||||
# define VL_PREFETCH_RD(p)
|
||||
# define VL_PREFETCH_RW(p)
|
||||
#else
|
||||
#endif
|
||||
|
||||
// Defaults for unsupported compiler features
|
||||
#ifndef VL_ATTR_ALIGNED
|
||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||
#endif
|
||||
#ifndef VL_ATTR_ALWINLINE
|
||||
# define VL_ATTR_ALWINLINE ///< Inline, even when not optimizing
|
||||
#endif
|
||||
#ifndef VL_ATTR_NORETURN
|
||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||
#endif
|
||||
#ifndef VL_ATTR_PRINTF
|
||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||
#endif
|
||||
#ifndef VL_ATTR_PURE
|
||||
# define VL_ATTR_PURE ///< Function is pure (and thus also VL_MT_SAFE)
|
||||
#endif
|
||||
#ifndef VL_ATTR_UNUSED
|
||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||
#endif
|
||||
#ifndef VL_FUNC
|
||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||
#endif
|
||||
#ifndef VL_CAPABILITY
|
||||
# define VL_ACQUIRE(...) ///< Function requires a capability/lock (-fthread-safety)
|
||||
# define VL_ACQUIRE_SHARED(...) ///< Function aquires a shared capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE(...) ///< Function releases a capability/lock (-fthread-safety)
|
||||
# define VL_RELEASE_SHARED(...) ///< Function releases a shared capability/lock (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE(...) ///< Function returns bool if aquired a capability (-fthread-safety)
|
||||
# define VL_TRY_ACQUIRE_SHARED(...) ///< Function returns bool if aquired a shared capability (-fthread-safety)
|
||||
# define VL_REQUIRES(x) ///< Function requires a capability inbound (-fthread-safety)
|
||||
# define VL_EXCLUDES(x) ///< Function requires not having a capability inbound (-fthread-safety)
|
||||
# define VL_CAPABILITY(x) ///< Name of capability/lock (-fthread-safety)
|
||||
# define VL_GUARDED_BY(x) ///< Name of mutex protecting this variable (-fthread-safety)
|
||||
# define VL_SCOPED_CAPABILITY ///< Scoped threaded capability/lock (-fthread-safety)
|
||||
#endif
|
||||
#ifndef VL_LIKELY
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
#endif
|
||||
#ifndef VL_UNREACHABLE
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
#endif
|
||||
#ifndef VL_PREFETCH_RD
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
#endif
|
||||
#ifndef VL_PREFETCH_RW
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
#endif
|
||||
|
||||
#ifdef VL_THREADED
|
||||
# ifdef __GNUC__
|
||||
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
|
||||
# error "VL_THREADED support plans to move to C++-11 and later only; use newer --std to be ready"
|
||||
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
|
||||
# endif
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
@@ -90,6 +131,12 @@
|
||||
#define VL_THREAD ///< Deprecated
|
||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||
|
||||
#define VL_PURE ///< Comment tag that Function is pure (and thus also VL_MT_SAFE)
|
||||
#define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED
|
||||
#define VL_MT_SAFE_POSTINIT ///< Comment tag that function is threadsafe when VL_THREADED, only during normal operation (post-init)
|
||||
#define VL_MT_UNSAFE ///< Comment tag that function is not threadsafe when VL_THREADED
|
||||
#define VL_MT_UNSAFE_ONE ///< Comment tag that function is not threadsafe when VL_THREADED, protected to make sure single-caller
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VL_ULL(c) (c##ui64) ///< Add appropriate suffix to 64-bit constant
|
||||
#else
|
||||
@@ -109,15 +156,22 @@
|
||||
// C++-2011
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define VL_EQ_DELETE = delete
|
||||
# define VL_HAS_UNIQUE_PTR
|
||||
# define VL_HAS_UNORDERED_MAP
|
||||
# define VL_UNIQUE_PTR std::unique_ptr
|
||||
# define VL_UNORDERED_MAP std::unordered_map
|
||||
# define VL_HAS_UNORDERED_SET
|
||||
# define vl_unique_ptr std::unique_ptr
|
||||
# define vl_unordered_map std::unordered_map
|
||||
# define vl_unordered_set std::unordered_set
|
||||
# define VL_INCLUDE_UNORDERED_MAP <unordered_map>
|
||||
# define VL_INCLUDE_UNORDERED_SET <unordered_set>
|
||||
#else
|
||||
# define VL_UNIQUE_PTR std::auto_ptr
|
||||
# define VL_UNORDERED_MAP std::map
|
||||
# define VL_EQ_DELETE
|
||||
# define vl_unique_ptr std::auto_ptr
|
||||
# define vl_unordered_map std::map
|
||||
# define vl_unordered_set std::set
|
||||
# define VL_INCLUDE_UNORDERED_MAP <map>
|
||||
# define VL_INCLUDE_UNORDERED_SET <set>
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
@@ -257,6 +311,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
/// Words this number of bits needs (1 bit=1 word)
|
||||
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
|
||||
|
||||
//=========================================================================
|
||||
// Class definition helpers
|
||||
|
||||
// Used to declare a class as uncopyable; put after a private:
|
||||
#define VL_UNCOPYABLE(Type) \
|
||||
Type(const Type& other) VL_EQ_DELETE; \
|
||||
Type& operator= (const Type&) VL_EQ_DELETE
|
||||
|
||||
//=========================================================================
|
||||
// Verilated function size macros
|
||||
|
||||
@@ -291,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.
|
||||
|
||||
+2
-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.
|
||||
@@ -104,6 +104,7 @@ CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_WEXTRA) $(CFG_CXXFLAGS_SRC) -Werror
|
||||
else
|
||||
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
|
||||
endif
|
||||
|
||||
CPPFLAGSWALL = $(CPPFLAGS)
|
||||
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
|
||||
|
||||
|
||||
+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.
|
||||
|
||||
+42
-11
@@ -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.
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
timesp->unlinkFrBackWithNext();
|
||||
timenewp->addNext(timesp);
|
||||
}
|
||||
nodep->fmtp()->exprsp(timenewp);
|
||||
nodep->fmtp()->addExprsp(timenewp);
|
||||
if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) {
|
||||
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
}
|
||||
@@ -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,
|
||||
@@ -202,6 +226,9 @@ private:
|
||||
AstNode *newifp = nodep->cloneTree(false);
|
||||
bool allow_none = nodep->unique0Pragma();
|
||||
|
||||
// Empty case means no property
|
||||
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
|
||||
|
||||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||
// predicates evaluates to true.
|
||||
AstNode* ohot = ((allow_none || hasDefaultElse)
|
||||
@@ -259,6 +286,9 @@ private:
|
||||
else propp = onep;
|
||||
}
|
||||
}
|
||||
// Empty case means no property
|
||||
if (!propp) propp = new AstConst(nodep->fileline(), AstConst::LogicFalse());
|
||||
|
||||
bool allow_none = has_default || nodep->unique0Pragma();
|
||||
AstNode* ohot = (allow_none
|
||||
? static_cast<AstNode*>(new AstOneHot0(nodep->fileline(), propp))
|
||||
@@ -288,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);
|
||||
@@ -343,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()
|
||||
|
||||
+158
-69
@@ -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
|
||||
@@ -208,14 +208,37 @@ public:
|
||||
"COMBO","INITIAL","SETTLE","NEVER"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
}
|
||||
const char* verilogKwd() const {
|
||||
static const char* const names[] = {
|
||||
"%E-edge", "[any]", "edge", "posedge", "negedge", "[high]","[low]",
|
||||
"*","[initial]","[settle]","[never]"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
}
|
||||
// Return true iff this and the other have mutually exclusive transitions
|
||||
bool exclusiveEdge(const AstEdgeType& other) const {
|
||||
switch (m_e) {
|
||||
case AstEdgeType::ET_POSEDGE:
|
||||
switch (other.m_e) {
|
||||
case AstEdgeType::ET_NEGEDGE: // FALLTHRU
|
||||
case AstEdgeType::ET_LOWEDGE:
|
||||
return true;
|
||||
default: {}
|
||||
}
|
||||
break;
|
||||
case AstEdgeType::ET_NEGEDGE:
|
||||
switch (other.m_e) {
|
||||
case AstEdgeType::ET_POSEDGE: // FALLTHRU
|
||||
case AstEdgeType::ET_HIGHEDGE:
|
||||
return true;
|
||||
default: {}
|
||||
}
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstEdgeType (en _e) : m_e(_e) {}
|
||||
@@ -340,9 +363,9 @@ public:
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
static void test() {
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"),"Enum array mismatch");
|
||||
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
||||
static void selfTest() {
|
||||
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
|
||||
@@ -395,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);
|
||||
@@ -658,10 +691,14 @@ struct VNumRange {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
class LeftRight {};
|
||||
VNumRange() : m_hi(0), m_lo(0), mu_flags(0) {}
|
||||
VNumRange(int hi, int lo, bool littleEndian)
|
||||
: m_hi(0), m_lo(0), mu_flags(0)
|
||||
{ init(hi,lo,littleEndian); }
|
||||
VNumRange(LeftRight, int left, int right)
|
||||
: m_hi(0), m_lo(0), mu_flags(0)
|
||||
{ init((right>left)?right:left, (right>left)?left:right, (right>left)); }
|
||||
~VNumRange() {}
|
||||
// MEMBERS
|
||||
void init(int hi, int lo, bool littleEndian) {
|
||||
@@ -854,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() {
|
||||
@@ -919,7 +960,7 @@ public:
|
||||
inline bool operator== (const V3Hash& rh) const { return m_both==rh.m_both; }
|
||||
inline bool operator!= (const V3Hash& rh) const { return m_both!=rh.m_both; }
|
||||
inline bool operator< (const V3Hash& rh) const { return m_both<rh.m_both; }
|
||||
// CREATORS
|
||||
// CONSTRUCTORS
|
||||
class Illegal {}; // for creator type-overload selection
|
||||
class FullValue {}; // for creator type-overload selection
|
||||
explicit V3Hash(Illegal) { m_both=0; }
|
||||
@@ -1060,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;
|
||||
|
||||
@@ -1246,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(); }
|
||||
@@ -1280,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(AstNode* otherp) const { return true; }
|
||||
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
|
||||
@@ -1369,7 +1415,7 @@ public:
|
||||
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
class AstNodeBiop : public AstNodeMath {
|
||||
@@ -1396,7 +1442,7 @@ public:
|
||||
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
class AstNodeTriop : public AstNodeMath {
|
||||
@@ -1413,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
|
||||
@@ -1422,7 +1470,7 @@ public:
|
||||
virtual bool sizeMattersThs() = 0; // True if output result depends on ths size
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
class AstNodeBiCom : public AstNodeBiop {
|
||||
@@ -1482,7 +1530,7 @@ public:
|
||||
void attrp(AstAttrOf* nodep) { return setOp4p((AstNode*)nodep); }
|
||||
// METHODS
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
};
|
||||
|
||||
class AstNodeStmt : public AstNode {
|
||||
@@ -1514,7 +1562,7 @@ public:
|
||||
virtual bool cleanRhs() { return true; }
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
virtual bool same(const AstNode*) const { return true; }
|
||||
virtual string verilogKwd() const { return "="; }
|
||||
virtual bool brokeLhsMustBeLvalue() const = 0;
|
||||
};
|
||||
@@ -1534,7 +1582,7 @@ public:
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
class AstNodeIf : public AstNodeStmt {
|
||||
@@ -1556,7 +1604,7 @@ public:
|
||||
virtual bool isGateDedupable() const { return true; }
|
||||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
virtual bool same(const AstNode* samep) const { return true; }
|
||||
void branchPred(AstBranchPred flag) { m_branchPred = flag; }
|
||||
AstBranchPred branchPred() const { return m_branchPred; }
|
||||
};
|
||||
@@ -1648,8 +1696,9 @@ public:
|
||||
ASTNODE_BASE_FUNCS(NodeText)
|
||||
virtual void dump(ostream& str=cout);
|
||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return text()==samep->castNodeText()->text(); }
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
const AstNodeText* asamep = static_cast<const AstNodeText*>(samep);
|
||||
return text() == asamep->text(); }
|
||||
const string& text() const { return m_text; }
|
||||
};
|
||||
|
||||
@@ -1684,6 +1733,8 @@ public:
|
||||
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
|
||||
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
|
||||
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
|
||||
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; }
|
||||
@@ -1696,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; }
|
||||
@@ -1706,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 {
|
||||
@@ -1714,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; }
|
||||
@@ -1740,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 {
|
||||
@@ -1770,24 +1829,24 @@ public:
|
||||
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
||||
m_refDTypep = m_refDTypep->clonep();
|
||||
}}
|
||||
virtual bool same(AstNode* samep) const {
|
||||
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
||||
return (msb()==sp->msb()
|
||||
&& subDTypep()==sp->subDTypep()
|
||||
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
return (msb()==asamep->msb()
|
||||
&& subDTypep()==asamep->subDTypep()
|
||||
&& rangenp()->sameTree(asamep->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
||||
virtual bool similarDType(AstNodeDType* samep) const {
|
||||
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
||||
return (sp
|
||||
const AstNodeArrayDType* asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
return (asamep
|
||||
&& type() == samep->type()
|
||||
&& msb() == sp->msb()
|
||||
&& rangenp()->sameTree(sp->rangenp())
|
||||
&& subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()));
|
||||
&& msb() == asamep->msb()
|
||||
&& rangenp()->sameTree(asamep->rangenp())
|
||||
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
|
||||
}
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
||||
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
||||
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
|
||||
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); }
|
||||
@@ -1838,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
|
||||
}
|
||||
@@ -1874,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 {
|
||||
@@ -1898,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:
|
||||
@@ -1952,6 +2020,8 @@ private:
|
||||
bool m_inLibrary:1; // From a library, no error if not used, never top level
|
||||
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
|
||||
bool m_internal:1; // Internally created
|
||||
bool m_recursive:1; // Recursive module
|
||||
bool m_recursiveClone:1; // If recursive, what module it clones, otherwise NULL
|
||||
int m_level; // 1=top module, 2=cell off top module, ...
|
||||
int m_varNum; // Incrementing variable number
|
||||
int m_typeNum; // Incrementing implicit type number
|
||||
@@ -1959,7 +2029,8 @@ public:
|
||||
AstNodeModule(FileLine* fl, const string& name)
|
||||
: AstNode (fl)
|
||||
,m_name(name), m_origName(name)
|
||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false)
|
||||
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false)
|
||||
,m_internal(false), m_recursive(false), m_recursiveClone(false)
|
||||
,m_level(0), m_varNum(0), m_typeNum(0) { }
|
||||
ASTNODE_BASE_FUNCS(NodeModule)
|
||||
virtual void dump(ostream& str);
|
||||
@@ -1989,6 +2060,17 @@ public:
|
||||
bool dead() const { return m_dead; }
|
||||
void internal(bool flag) { m_internal = flag; }
|
||||
bool internal() const { return m_internal; }
|
||||
void recursive(bool flag) { m_recursive = flag; }
|
||||
bool recursive() const { return m_recursive; }
|
||||
void recursiveClone(bool flag) { m_recursiveClone = flag; }
|
||||
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)
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -2004,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()); }
|
||||
@@ -2020,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.
|
||||
|
||||
+96
-20
@@ -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.
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include VL_INCLUDE_UNORDERED_SET
|
||||
|
||||
#include "V3Ast.h"
|
||||
#include "V3File.h"
|
||||
@@ -63,13 +64,14 @@ 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));
|
||||
}
|
||||
}
|
||||
|
||||
const char* AstNodeClassDType::broken() const {
|
||||
set<AstMemberDType*> exists;
|
||||
vl_unordered_set<AstMemberDType*> exists;
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
|
||||
exists.insert(itemp);
|
||||
}
|
||||
@@ -238,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;
|
||||
@@ -274,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 {
|
||||
@@ -312,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 += "*";
|
||||
@@ -326,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()) {
|
||||
@@ -548,28 +608,28 @@ string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const {
|
||||
return out;
|
||||
}
|
||||
|
||||
bool AstSenTree::hasClocked() {
|
||||
bool AstSenTree::hasClocked() const {
|
||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||
if (senp->isClocked()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool AstSenTree::hasSettle() {
|
||||
bool AstSenTree::hasSettle() const {
|
||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||
if (senp->isSettle()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool AstSenTree::hasInitial() {
|
||||
bool AstSenTree::hasInitial() const {
|
||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||
if (senp->isInitial()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool AstSenTree::hasCombo() {
|
||||
bool AstSenTree::hasCombo() const {
|
||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||
if (senp->isCombo()) return true;
|
||||
@@ -778,6 +838,7 @@ void AstCCast::dump(ostream& str) {
|
||||
}
|
||||
void AstCell::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (recursive()) str<<" [RECURSIVE]";
|
||||
if (modp()) { str<<" -> "; modp()->dump(str); }
|
||||
else { str<<" ->UNLINKED:"<<modName(); }
|
||||
}
|
||||
@@ -849,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);
|
||||
@@ -886,6 +948,8 @@ void AstNodeModule::dump(ostream& str) {
|
||||
if (modPublic()) str<<" [P]";
|
||||
if (inLibrary()) str<<" [LIB]";
|
||||
if (dead()) str<<" [DEAD]";
|
||||
if (recursiveClone()) str<<" [RECURSIVE-CLONE]";
|
||||
else if (recursive()) str<<" [RECURSIVE]";
|
||||
}
|
||||
void AstPackageExport::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
@@ -902,6 +966,12 @@ void AstSel::dump(ostream& str) {
|
||||
if (declElWidth()!=1) str<<"/"<<declElWidth();
|
||||
}
|
||||
}
|
||||
void AstSliceSel::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (declRange().ranged()) {
|
||||
str<<" decl"<<declRange();
|
||||
}
|
||||
}
|
||||
void AstTypeTable::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
for (int i=0; i<(int)(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
@@ -939,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]";
|
||||
@@ -951,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); }
|
||||
@@ -986,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();
|
||||
}
|
||||
@@ -1021,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"; }
|
||||
}
|
||||
@@ -1031,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) {
|
||||
|
||||
+566
-234
File diff suppressed because it is too large
Load Diff
+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.
|
||||
|
||||
+2
-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.
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
class V3Branch {
|
||||
public:
|
||||
// CREATORS
|
||||
// CONSTRUCTORS
|
||||
static void branchAll(AstNetlist* rootp);
|
||||
};
|
||||
|
||||
|
||||
+7
-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.
|
||||
@@ -47,7 +47,7 @@ class BrokenTable : public AstNVisitor {
|
||||
private:
|
||||
// MEMBERS
|
||||
// For each node, we keep if it exists or not.
|
||||
typedef VL_UNORDERED_MAP<const AstNode*,int> NodeMap; // Performance matters (when --debug)
|
||||
typedef vl_unordered_map<const AstNode*,int> NodeMap; // Performance matters (when --debug)
|
||||
static NodeMap s_nodes; // Set of all nodes that exist
|
||||
// BITMASK
|
||||
enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed
|
||||
@@ -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.
|
||||
|
||||
+49
-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.
|
||||
@@ -23,6 +23,8 @@
|
||||
// for all AstCoverDecl, move the declaration into a _configure_coverage AstCFunc.
|
||||
// For each variable that needs reset, add a AstCReset node.
|
||||
//
|
||||
// For primary inputs, add _eval_debug_assertions.
|
||||
//
|
||||
// This transformation honors outputSplitCFuncs.
|
||||
//*************************************************************************
|
||||
#include "config_build.h"
|
||||
@@ -75,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;
|
||||
@@ -96,27 +99,68 @@ public:
|
||||
}
|
||||
~V3CCtorsVisitor() {}
|
||||
private:
|
||||
explicit V3CCtorsVisitor(const V3CCtorsVisitor&); ///< N/A, no copy constructor
|
||||
VL_UNCOPYABLE(V3CCtorsVisitor);
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
void V3CCtors::evalAsserts() {
|
||||
AstNodeModule* modp = v3Global.rootp()->modulesp(); // Top module
|
||||
AstCFunc* funcp = new AstCFunc(modp->fileline(), "_eval_debug_assertions", NULL, "void");
|
||||
funcp->declPrivate(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->slow(false);
|
||||
funcp->ifdef("VL_DEBUG");
|
||||
modp->addStmtp(funcp);
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstVar* varp = np->castVar()) {
|
||||
if (varp->isPrimaryIn() && !varp->isSc()) {
|
||||
if (AstBasicDType* basicp = varp->dtypeSkipRefp()->castBasicDType()) {
|
||||
int storedWidth = basicp->widthAlignBytes() * 8;
|
||||
int lastWordWidth = varp->width() % storedWidth;
|
||||
if (lastWordWidth != 0) {
|
||||
// if (signal & CONST(upper_non_clean_mask)) { fail; }
|
||||
AstNode* newp = new AstVarRef(varp->fileline(), varp, false);
|
||||
if (varp->isWide()) {
|
||||
newp = new AstWordSel(varp->fileline(), newp,
|
||||
new AstConst(varp->fileline(), varp->widthWords()-1));
|
||||
}
|
||||
uint64_t value = VL_MASK_Q(storedWidth) & ~VL_MASK_Q(lastWordWidth);
|
||||
V3Number num (varp->fileline(), storedWidth, value);
|
||||
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()+"\");"));
|
||||
ifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
newp = ifp;
|
||||
funcp->addStmtsp(newp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V3CCtors::cctorsAll() {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
evalAsserts();
|
||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
|
||||
// Process each module in turn
|
||||
{
|
||||
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();
|
||||
|
||||
+3
-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.
|
||||
@@ -30,6 +30,8 @@
|
||||
class V3CCtors {
|
||||
public:
|
||||
static void cctorsAll();
|
||||
private:
|
||||
static void evalAsserts();
|
||||
};
|
||||
|
||||
|
||||
|
||||
+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.
|
||||
|
||||
+7
-5
@@ -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) {
|
||||
@@ -621,7 +621,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
}
|
||||
// Top level we could choose to make multiple gaters, or ORs under the gater
|
||||
// Right now we'll put OR lower down and let other optimizations deal
|
||||
if (nodep) nodep = new AstOr(eqnp->fileline(),nodep,eqnp);
|
||||
if (nodep) nodep = new AstOr(nodep->fileline(), nodep, eqnp);
|
||||
else nodep = eqnp;
|
||||
//if (debug()>=9) nodep->dumpTree(cout," followExpr: ");
|
||||
}
|
||||
@@ -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