mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a0babb47d | ||
|
|
b085b34a69 | ||
|
|
abc738b6f1 | ||
|
|
d37cc5a160 | ||
|
|
1a0de753e9 | ||
|
|
b798f4fe71 | ||
|
|
0c0a588b55 | ||
|
|
faa5ef193b | ||
|
|
4c7b5005a6 | ||
|
|
9cf61cef9d | ||
|
|
28c61b548b | ||
|
|
0b24e62d43 | ||
|
|
b19dd49fc9 | ||
|
|
91b1e66933 | ||
|
|
eea2712eac | ||
|
|
b19a4b6956 | ||
|
|
a01c995a53 | ||
|
|
59b491e3a8 | ||
|
|
c44febe85e | ||
|
|
15b3c9797b | ||
|
|
584cfa4d4a | ||
|
|
b92f57eacb | ||
|
|
aeeaaa53d4 | ||
|
|
a532fce0e4 | ||
|
|
510fe8e634 | ||
|
|
556d90a1b4 | ||
|
|
4dde1ede0e | ||
|
|
1c833f8a9a | ||
|
|
6a36bd8514 | ||
|
|
12cb819adc | ||
|
|
0607edd191 | ||
|
|
96c7abdb39 | ||
|
|
6835aecdce | ||
|
|
8174c1ad02 | ||
|
|
6129452681 | ||
|
|
be1a3f427e | ||
|
|
18dc947fa9 | ||
|
|
348c43de63 | ||
|
|
cd9b15b2a6 | ||
|
|
8b20d777b0 | ||
|
|
ec0947ef7e | ||
|
|
02e6005fa9 | ||
|
|
a32caac3c1 | ||
|
|
2aa618ce98 | ||
|
|
96b23f6edd | ||
|
|
02d162858f | ||
|
|
82844a5591 | ||
|
|
46fb5a852f | ||
|
|
10a3aa18bc | ||
|
|
3c395c26be | ||
|
|
ea78520220 | ||
|
|
92fbec2294 | ||
|
|
b9be4ae4e8 | ||
|
|
e9a7f60fa7 | ||
|
|
0a02d1f336 | ||
|
|
663f3592ba | ||
|
|
f9484a894f | ||
|
|
4e522ab7f5 | ||
|
|
96d150e92d | ||
|
|
592b2e76a8 | ||
|
|
a3e463030d | ||
|
|
4569278c53 | ||
|
|
851b022c7a | ||
|
|
0985f675e3 | ||
|
|
7df730cedd | ||
|
|
314ffd9353 | ||
|
|
2c953dc37f | ||
|
|
9b9e4e5a3f | ||
|
|
50f835c701 | ||
|
|
cbb3351d97 | ||
|
|
fb81721e7e | ||
|
|
2cedef1333 | ||
|
|
4a1697a1b5 | ||
|
|
86f08a341c | ||
|
|
3d85cbe6b5 | ||
|
|
6d3dd98e77 | ||
|
|
9b2004d6b7 | ||
|
|
eb072da81c | ||
|
|
38669d0a10 | ||
|
|
202a8bc3bb | ||
|
|
45e8ed6b49 | ||
|
|
96692e8a5b | ||
|
|
ecb08b0cf3 | ||
|
|
71bdfd9710 | ||
|
|
193dcf38f4 | ||
|
|
09091781cf | ||
|
|
023519c8f6 | ||
|
|
d60d0a60c7 | ||
|
|
8fe0c3dd84 | ||
|
|
85419f01a9 | ||
|
|
a199f4a849 | ||
|
|
290795a76b | ||
|
|
c2cf2bc0ba | ||
|
|
2224918730 | ||
|
|
c4e69daecd | ||
|
|
9162e68d82 | ||
|
|
08f736ae33 | ||
|
|
81092edab4 | ||
|
|
21b5a4e9e4 | ||
|
|
057928b079 | ||
|
|
4beaa45199 | ||
|
|
8f88fa45f1 | ||
|
|
13e8176884 | ||
|
|
aac0130613 | ||
|
|
0877f44cb5 | ||
|
|
59159b4811 | ||
|
|
12bd12e112 | ||
|
|
0e4f9170fa | ||
|
|
6f81a9cb1e | ||
|
|
41555e5aa3 | ||
|
|
3d06720628 | ||
|
|
c1d2b98386 | ||
|
|
1a60723d77 | ||
|
|
cc31ab84d7 | ||
|
|
a07a234761 | ||
|
|
0bb4ccd7cd | ||
|
|
74cf205bcf | ||
|
|
77405ddded | ||
|
|
6b46da0240 | ||
|
|
0815812546 | ||
|
|
0fed1d34d1 | ||
|
|
a1e091cff7 | ||
|
|
adebc99e49 | ||
|
|
d3d1291d5a | ||
|
|
de61015e08 | ||
|
|
9d856ec1bf | ||
|
|
ad19d32a66 | ||
|
|
5bdb8674ed | ||
|
|
5563c9666c | ||
|
|
30ad20be52 | ||
|
|
314c9de845 | ||
|
|
41dbfc9e1c | ||
|
|
b07dd622fa | ||
|
|
6ad21b3b3b | ||
|
|
a242c1019d | ||
|
|
c595d67311 | ||
|
|
8b77379e2c | ||
|
|
7ad29c6329 | ||
|
|
14756fa131 | ||
|
|
ddbfc176b6 | ||
|
|
ab668b066f | ||
|
|
a4bcb3de4a | ||
|
|
211894cb3e | ||
|
|
7565b1f4f2 | ||
|
|
b75ff3652c | ||
|
|
13f6c5a934 | ||
|
|
2e0f6e2b13 | ||
|
|
c5d41ee2d9 | ||
|
|
5f70c1aa68 | ||
|
|
d2105ba390 | ||
|
|
e46e7bbf99 | ||
|
|
4eeeb72dd5 | ||
|
|
adefa45fb4 | ||
|
|
cfc06ab2a7 | ||
|
|
f3a4752799 | ||
|
|
3d788b4b93 | ||
|
|
5d2675e38a | ||
|
|
288d7bd9dc | ||
|
|
3e8cf26c1a | ||
|
|
ce212722ad | ||
|
|
5c127daeb4 | ||
|
|
e49fc945df | ||
|
|
384807ebbd | ||
|
|
ac619ef3d8 | ||
|
|
a348bd3458 | ||
|
|
bcc7045fc9 | ||
|
|
3b1929259a | ||
|
|
cdd6ea8e60 | ||
|
|
4b8927af75 | ||
|
|
0fba25c1b3 | ||
|
|
f19ba9d54d | ||
|
|
8e9a0121ac | ||
|
|
bd6e8d808c | ||
|
|
11b9a631d4 | ||
|
|
f197dd29cb | ||
|
|
daf7f42138 | ||
|
|
dd487d4184 | ||
|
|
d90071637d | ||
|
|
d8efae2aba | ||
|
|
22543f3e19 | ||
|
|
6aaef67e73 | ||
|
|
82a934d6fb | ||
|
|
eca6f2ca05 | ||
|
|
ef69f36403 | ||
|
|
99cf981c2f | ||
|
|
fc7a449f6d | ||
|
|
b7fafdafaa | ||
|
|
8e180cfcde | ||
|
|
4770fd39d2 | ||
|
|
df107628c6 | ||
|
|
3463080a71 | ||
|
|
500dc2170f | ||
|
|
a76ae67a81 | ||
|
|
1d091e49e1 | ||
|
|
2b63219cc6 | ||
|
|
f1b7762bef | ||
|
|
043ad86482 | ||
|
|
74ca9578ed | ||
|
|
d499161446 | ||
|
|
34e8de56bc | ||
|
|
8a7864ebaa | ||
|
|
9e5fb5467f | ||
|
|
fb34bf7222 | ||
|
|
4591f35b7c | ||
|
|
f0a06182ca | ||
|
|
d9e47a6293 | ||
|
|
a555f87705 | ||
|
|
826b997166 | ||
|
|
d34bc6f304 | ||
|
|
5771ea48ef | ||
|
|
a4f3199427 | ||
|
|
e6a43fc127 | ||
|
|
701bd38d01 | ||
|
|
1a8c8bec0d | ||
|
|
20aa21d4b6 | ||
|
|
8c6adeb85a | ||
|
|
09b7ba1317 | ||
|
|
0703843ac1 | ||
|
|
d962dfe48c | ||
|
|
d6884db439 | ||
|
|
fdcbedef8f | ||
|
|
8afd19648f | ||
|
|
3017f12238 | ||
|
|
23ee0342c6 | ||
|
|
499f98a51c | ||
|
|
3073db4e81 | ||
|
|
5703377a5f | ||
|
|
b85aa872cc | ||
|
|
5a1a5a7d97 | ||
|
|
52912c6329 | ||
|
|
056f72f27f | ||
|
|
bb038e86a2 | ||
|
|
cc6c71eb37 | ||
|
|
de4358f8d8 | ||
|
|
d6e9c72424 | ||
|
|
96608fb18d | ||
|
|
280b826d6d | ||
|
|
538d3d46f4 | ||
|
|
66b8ec8935 | ||
|
|
4f30025aa0 | ||
|
|
faad36a3ef | ||
|
|
0b461599d1 | ||
|
|
0cbab84143 | ||
|
|
a4e2a770f6 | ||
|
|
36e84973ec | ||
|
|
f6c8888ee2 | ||
|
|
f2bf6a037b | ||
|
|
9dade8fbd9 | ||
|
|
d2d38edf06 | ||
|
|
e0abd238e3 | ||
|
|
7edcc08886 | ||
|
|
0c73b547f1 | ||
|
|
73c3d4bb50 | ||
|
|
77f063367a | ||
|
|
8e812058cb | ||
|
|
506c36beed | ||
|
|
0110f0193e | ||
|
|
7b870f4b2a | ||
|
|
aa2630f837 | ||
|
|
e137e93f94 | ||
|
|
215bdfccc2 | ||
|
|
956a0a9c99 | ||
|
|
ab83717b7d | ||
|
|
61e876e4bf | ||
|
|
9ca3dbc140 | ||
|
|
a02e2e25bb | ||
|
|
a9281f2c37 | ||
|
|
95395a8b87 | ||
|
|
ecdbd72fa1 | ||
|
|
3a2f8224e4 | ||
|
|
15841fe5f6 | ||
|
|
7e5a7b65a0 | ||
|
|
549bf876e4 | ||
|
|
bd60cf12f8 | ||
|
|
61fbab1910 | ||
|
|
957f495314 | ||
|
|
280eb48ba4 | ||
|
|
ebe5711b40 | ||
|
|
a16477d84f | ||
|
|
f6fb2362c6 | ||
|
|
170427bba1 | ||
|
|
93531e520a | ||
|
|
aa2db8fdde | ||
|
|
7c3c2af90b | ||
|
|
6dca9b4ba4 | ||
|
|
ede37bb9d8 | ||
|
|
4a1729eaab | ||
|
|
b1565f5b89 | ||
|
|
4fb8dcfd4e | ||
|
|
16d1f2b835 | ||
|
|
73594e5aa5 | ||
|
|
c0a365bd34 | ||
|
|
45940ff820 | ||
|
|
d545ae242c | ||
|
|
e862aaf2e1 | ||
|
|
30c3540086 | ||
|
|
663a084ca4 | ||
|
|
b4d9ccd9af | ||
|
|
98fff6a4ce | ||
|
|
4977a5e1d9 | ||
|
|
e4297486ef | ||
|
|
ad591767c9 |
@@ -1,3 +1,4 @@
|
|||||||
|
*~
|
||||||
*.old
|
*.old
|
||||||
*.gz
|
*.gz
|
||||||
*.gz.uu
|
*.gz.uu
|
||||||
@@ -7,7 +8,7 @@
|
|||||||
*.1
|
*.1
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tex
|
*.tex
|
||||||
Makefile
|
/Makefile
|
||||||
README
|
README
|
||||||
config.cache
|
config.cache
|
||||||
config.status
|
config.status
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
Artistic License 2.0
|
||||||
|
|
||||||
|
Copyright (c) 2000-2006, The Perl Foundation.
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this
|
||||||
|
license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
********
|
||||||
|
|
||||||
|
This license establishes the terms under which a given free software
|
||||||
|
Package may be copied, modified, distributed, and/or redistributed. The
|
||||||
|
intent is that the Copyright Holder maintains some artistic control over
|
||||||
|
the development of that Package while still keeping the Package
|
||||||
|
available as open source and free software.
|
||||||
|
|
||||||
|
You are always permitted to make arrangements wholly outside of this
|
||||||
|
license directly with the Copyright Holder of a given Package. If the
|
||||||
|
terms of this license do not permit the full use that you propose to
|
||||||
|
make of the Package, you should contact the Copyright Holder and seek a
|
||||||
|
different licensing arrangement.
|
||||||
|
|
||||||
|
Definitions
|
||||||
|
***********
|
||||||
|
|
||||||
|
"Copyright Holder" means the individual(s) or organization(s) named in
|
||||||
|
the copyright notice for the entire Package.
|
||||||
|
|
||||||
|
"Contributor" means any party that has contributed code or other
|
||||||
|
material to the Package, in accordance with the Copyright Holder's
|
||||||
|
procedures.
|
||||||
|
|
||||||
|
"You" and "your" means any person who would like to copy, distribute, or
|
||||||
|
modify the Package.
|
||||||
|
|
||||||
|
"Package" means the collection of files distributed by the Copyright
|
||||||
|
Holder, and derivatives of that collection and/or of those files. A
|
||||||
|
given Package may consist of either the Standard Version, or a Modified
|
||||||
|
Version.
|
||||||
|
|
||||||
|
"Distribute" means providing a copy of the Package or making it
|
||||||
|
accessible to anyone else, or in the case of a company or organization,
|
||||||
|
to others outside of your company or organization.
|
||||||
|
|
||||||
|
"Distributor Fee" means any fee that you charge for Distributing this
|
||||||
|
Package or providing support for this Package to another party. It does
|
||||||
|
not mean licensing fees.
|
||||||
|
|
||||||
|
"Standard Version" refers to the Package if it has not been modified, or
|
||||||
|
has been modified only in ways explicitly requested by the Copyright
|
||||||
|
Holder.
|
||||||
|
|
||||||
|
"Modified Version" means the Package, if it has been changed, and such
|
||||||
|
changes were not explicitly requested by the Copyright Holder.
|
||||||
|
|
||||||
|
"Original License" means this Artistic License as Distributed with the
|
||||||
|
Standard Version of the Package, in its current version or as it may be
|
||||||
|
modified by The Perl Foundation in the future.
|
||||||
|
|
||||||
|
"Source" form means the source code, documentation source, and
|
||||||
|
configuration files for the Package.
|
||||||
|
|
||||||
|
"Compiled" form means the compiled bytecode, object code, binary, or any
|
||||||
|
other form resulting from mechanical transformation or translation of
|
||||||
|
the Source form.
|
||||||
|
|
||||||
|
Permission for Use and Modification Without Distribution
|
||||||
|
********************************************************
|
||||||
|
|
||||||
|
(1) You are permitted to use the Standard Version and create and use
|
||||||
|
Modified Versions for any purpose without restriction, provided that you
|
||||||
|
do not Distribute the Modified Version.
|
||||||
|
|
||||||
|
Permissions for Redistribution of the Standard Version
|
||||||
|
******************************************************
|
||||||
|
|
||||||
|
(2) You may Distribute verbatim copies of the Source form of the
|
||||||
|
Standard Version of this Package in any medium without restriction,
|
||||||
|
either gratis or for a Distributor Fee, provided that you duplicate all
|
||||||
|
of the original copyright notices and associated disclaimers. At your
|
||||||
|
discretion, such verbatim copies may or may not include a Compiled form
|
||||||
|
of the Package.
|
||||||
|
|
||||||
|
(3) You may apply any bug fixes, portability changes, and other
|
||||||
|
modifications made available from the Copyright Holder. The resulting
|
||||||
|
Package will still be considered the Standard Version, and as such will
|
||||||
|
be subject to the Original License.
|
||||||
|
|
||||||
|
Distribution of Modified Versions of the Package as Source
|
||||||
|
**********************************************************
|
||||||
|
|
||||||
|
(4) You may Distribute your Modified Version as Source (either gratis or
|
||||||
|
for a Distributor Fee, and with or without a Compiled form of the
|
||||||
|
Modified Version) provided that you clearly document how it differs from
|
||||||
|
the Standard Version, including, but not limited to, documenting any
|
||||||
|
non-standard features, executables, or modules, and provided that you do
|
||||||
|
at least ONE of the following:
|
||||||
|
|
||||||
|
(a) make the Modified Version available to the Copyright Holder of the
|
||||||
|
Standard Version, under the Original License, so that the Copyright
|
||||||
|
Holder may include your modifications in the Standard Version.
|
||||||
|
|
||||||
|
(b) ensure that installation of your Modified Version does not prevent
|
||||||
|
the user installing or running the Standard Version. In addition, the
|
||||||
|
Modified Version must bear a name that is different from the name of the
|
||||||
|
Standard Version.
|
||||||
|
|
||||||
|
(c) allow anyone who receives a copy of the Modified Version to make the
|
||||||
|
Source form of the Modified Version available to others under
|
||||||
|
|
||||||
|
(i) the Original License or
|
||||||
|
|
||||||
|
(ii) a license that permits the licensee to freely copy, modify and
|
||||||
|
redistribute the Modified Version using the same licensing terms that
|
||||||
|
apply to the copy that the licensee received, and requires that the
|
||||||
|
Source form of the Modified Version, and of any works derived from it,
|
||||||
|
be made freely available in that license fees are prohibited but
|
||||||
|
Distributor Fees are allowed.
|
||||||
|
|
||||||
|
Distribution of Compiled Forms of the Standard Version or Modified
|
||||||
|
******************************************************************
|
||||||
|
Versions without the Source
|
||||||
|
***************************
|
||||||
|
|
||||||
|
(5) You may Distribute Compiled forms of the Standard Version without
|
||||||
|
the Source, provided that you include complete instructions on how to
|
||||||
|
get the Source of the Standard Version. Such instructions must be valid
|
||||||
|
at the time of your distribution. If these instructions, at any time
|
||||||
|
while you are carrying out such distribution, become invalid, you must
|
||||||
|
provide new instructions on demand or cease further distribution. If
|
||||||
|
you provide valid instructions or cease distribution within thirty days
|
||||||
|
after you become aware that the instructions are invalid, then you do
|
||||||
|
not forfeit any of your rights under this license.
|
||||||
|
|
||||||
|
(6) You may Distribute a Modified Version in Compiled form without the
|
||||||
|
Source, provided that you comply with Section 4 with respect to the
|
||||||
|
Source of the Modified Version.
|
||||||
|
|
||||||
|
Aggregating or Linking the Package
|
||||||
|
**********************************
|
||||||
|
|
||||||
|
(7) You may aggregate the Package (either the Standard Version or
|
||||||
|
Modified Version) with other packages and Distribute the resulting
|
||||||
|
aggregation provided that you do not charge a licensing fee for the
|
||||||
|
Package. Distributor Fees are permitted, and licensing fees for other
|
||||||
|
components in the aggregation are permitted. The terms of this license
|
||||||
|
apply to the use and Distribution of the Standard or Modified Versions
|
||||||
|
as included in the aggregation.
|
||||||
|
|
||||||
|
(8) You are permitted to link Modified and Standard Versions with other
|
||||||
|
works, to embed the Package in a larger work of your own, or to build
|
||||||
|
stand-alone binary or bytecode versions of applications that include the
|
||||||
|
Package, and Distribute the result without restriction, provided the
|
||||||
|
result does not expose a direct interface to the Package.
|
||||||
|
|
||||||
|
Items That are Not Considered Part of a Modified Version
|
||||||
|
********************************************************
|
||||||
|
|
||||||
|
(9) Works (including, but not limited to, modules and scripts) that
|
||||||
|
merely extend or make use of the Package, do not, by themselves, cause
|
||||||
|
the Package to be a Modified Version. In addition, such works are not
|
||||||
|
considered parts of the Package itself, and are not subject to the terms
|
||||||
|
of this license.
|
||||||
|
|
||||||
|
General Provisions
|
||||||
|
******************
|
||||||
|
|
||||||
|
(10) Any use, modification, and distribution of the Standard or Modified
|
||||||
|
Versions is governed by this Artistic License. By using, modifying or
|
||||||
|
distributing the Package, you accept this license. Do not use, modify,
|
||||||
|
or distribute the Package, if you do not accept this license.
|
||||||
|
|
||||||
|
(11) If your Modified Version has been derived from a Modified Version
|
||||||
|
made by someone other than you, you are nevertheless required to ensure
|
||||||
|
that your Modified Version complies with the requirements of this
|
||||||
|
license.
|
||||||
|
|
||||||
|
(12) This license does not grant you the right to use any trademark,
|
||||||
|
service mark, tradename, or logo of the Copyright Holder.
|
||||||
|
|
||||||
|
(13) This license includes the non-exclusive, worldwide, free-of-charge
|
||||||
|
patent license to make, have made, use, offer to sell, sell, import and
|
||||||
|
otherwise transfer the Package with respect to any patent claims
|
||||||
|
licensable by the Copyright Holder that are necessarily infringed by the
|
||||||
|
Package. If you institute patent litigation (including a cross-claim or
|
||||||
|
counterclaim) against any party alleging that the Package constitutes
|
||||||
|
direct or contributory patent infringement, then this Artistic License
|
||||||
|
to you shall terminate on the date that such litigation is filed.
|
||||||
|
|
||||||
|
(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
|
||||||
|
HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
|
||||||
|
PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
@@ -1,285 +1,626 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 2, June 1991
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
The GNU General Public License is a free, copyleft license for
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
software and other kinds of works.
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
The licenses for most software and other practical works are designed
|
||||||
General Public License applies to most of the Free Software
|
to take away your freedom to share and change the works. By contrast,
|
||||||
Foundation's software and to any other program whose authors commit to
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
share and change all versions of a program--to make sure it remains free
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
your programs, too.
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
have the freedom to distribute copies of free software (and charge for
|
have the freedom to distribute copies of free software (and charge for
|
||||||
this service if you wish), that you receive source code or can get it
|
them if you wish), that you receive source code or can get it if you
|
||||||
if you want it, that you can change the software or use pieces of it
|
want it, that you can change the software or use pieces of it in new
|
||||||
in new free programs; and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
To protect your rights, we need to prevent others from denying you
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
These restrictions translate to certain responsibilities for you if you
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
distribute copies of the software, or if you modify it.
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
For example, if you distribute copies of such a program, whether
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
you have. You must make sure that they, too, receive or can get the
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
source code. And you must show them these terms so they know their
|
or can get the source code. And you must show them these terms so they
|
||||||
rights.
|
know their rights.
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
distribute and/or modify the software.
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
that everyone understands that there is no warranty for this free
|
that there is no warranty for this free software. For both users' and
|
||||||
software. If the software is modified by someone else and passed on, we
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
want its recipients to know that what they have is not the original, so
|
changed, so that their problems will not be attributed erroneously to
|
||||||
that any problems introduced by others will not reflect on the original
|
authors of previous versions.
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
Some devices are designed to deny users access to install or run
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
modified versions of the software inside them, although the manufacturer
|
||||||
program will individually obtain patent licenses, in effect making the
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
protecting users' freedom to change the software. The systematic
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
TERMS AND CONDITIONS
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
0. Definitions.
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
of it, thus forming a work based on the Program, and copy and
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
distribute such modifications or work under the terms of Section 1
|
"recipients" may be individuals or organizations.
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
stating that you changed the files and the date of any change.
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
A "covered work" means either the unmodified Program or a work based
|
||||||
whole or in part contains or is derived from the Program or any
|
on the Program.
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
To "propagate" a work means to do anything with it that, without
|
||||||
when run, you must cause it, when started running for such
|
permission, would make you directly or secondarily liable for
|
||||||
interactive use in the most ordinary way, to print or display an
|
infringement under applicable copyright law, except executing it on a
|
||||||
announcement including an appropriate copyright notice and a
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
notice that there is no warranty (or else, saying that you provide
|
distribution (with or without modification), making available to the
|
||||||
a warranty) and that users may redistribute the program under
|
public, and in some countries other activities as well.
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
To "convey" a work means any kind of propagation that enables other
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
exercise the right to control the distribution of derivative or
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
to the extent that it includes a convenient and prominently visible
|
||||||
a storage or distribution medium does not bring the other work under
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
the scope of this License.
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
1. Source Code.
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
The "source code" for a work means the preferred form of the work
|
||||||
source code, which must be distributed under the terms of Sections
|
for making modifications to it. "Object code" means any non-source
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
form of a work.
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
A "Standard Interface" means an interface that either is an official
|
||||||
years, to give any third party, for a charge no more than your
|
standard defined by a recognized standards body, or, in the case of
|
||||||
cost of physically performing source distribution, a complete
|
interfaces specified for a particular programming language, one that
|
||||||
machine-readable copy of the corresponding source code, to be
|
is widely used among developers working in that language.
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
The "System Libraries" of an executable work include anything, other
|
||||||
to distribute corresponding source code. (This alternative is
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
allowed only for noncommercial distribution and only if you
|
packaging a Major Component, but which is not part of that Major
|
||||||
received the program in object code or executable form with such
|
Component, and (b) serves only to enable use of the work with that
|
||||||
an offer, in accord with Subsection b above.)
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
The "Corresponding Source" for a work in object code form means all
|
||||||
making modifications to it. For an executable work, complete source
|
the source code needed to generate, install, and (for an executable
|
||||||
code means all the source code for all modules it contains, plus any
|
work) run the object code and to modify the work, including scripts to
|
||||||
associated interface definition files, plus the scripts used to
|
control those activities. However, it does not include the work's
|
||||||
control compilation and installation of the executable. However, as a
|
System Libraries, or general-purpose tools or generally available free
|
||||||
special exception, the source code distributed need not include
|
programs which are used unmodified in performing those activities but
|
||||||
anything that is normally distributed (in either source or binary
|
which are not part of the work. For example, Corresponding Source
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
includes interface definition files associated with source files for
|
||||||
operating system on which the executable runs, unless that component
|
the work, and the source code for shared libraries and dynamically
|
||||||
itself accompanies the executable.
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
The Corresponding Source need not include anything that users
|
||||||
access to copy from a designated place, then offering equivalent
|
can regenerate automatically from other parts of the Corresponding
|
||||||
access to copy the source code from the same place counts as
|
Source.
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
The Corresponding Source for a work in source code form is that
|
||||||
signed it. However, nothing else grants you permission to modify or
|
same work.
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
2. Basic Permissions.
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
All rights granted under this License are granted for the term of
|
||||||
these terms and conditions. You may not impose any further
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
You are not responsible for enforcing compliance by third parties to
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
this License.
|
this License.
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
infringement or for any other reason (not limited to patent issues),
|
patent license under the contributor's essential patent claims, to
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
excuse you from the conditions of this License. If you cannot
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
License and any other pertinent obligations, then as a consequence you
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
may not distribute the Program at all. For example, if a patent
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
license would not permit royalty-free redistribution of the Program by
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
all those who receive copies directly or indirectly through you, then
|
the Program, the only way you could satisfy both those terms and this
|
||||||
the only way you could satisfy both it and this License would be to
|
License would be to refrain entirely from conveying the Program.
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
13. Use with the GNU Affero General Public License.
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
Notwithstanding any other provision of this License, you have
|
||||||
patents or other property right claims or to contest validity of any
|
permission to link or combine any covered work with a work licensed
|
||||||
such claims; this section has the sole purpose of protecting the
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
integrity of the free software distribution system, which is
|
combined work, and to convey the resulting work. The terms of this
|
||||||
implemented by public license practices. Many people have made
|
License will continue to apply to the part which is the covered work,
|
||||||
generous contributions to the wide range of software distributed
|
but the special requirements of the GNU Affero General Public License,
|
||||||
through that system in reliance on consistent application of that
|
section 13, concerning interaction through a network will apply to the
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
combination as such.
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
14. Revised Versions of this License.
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
of the General Public License from time to time. Such new versions will
|
the GNU General Public License from time to time. Such new versions will
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
Each version is given a distinguishing version number. If the
|
||||||
specifies a version number of this License which applies to it and "any
|
Program specifies that a certain numbered version of the GNU General
|
||||||
later version", you have the option of following the terms and conditions
|
Public License "or any later version" applies to it, you have the
|
||||||
either of that version or of any later version published by the Free
|
option of following the terms and conditions either of that numbered
|
||||||
Software Foundation. If the Program does not specify a version number of
|
version or of any later version published by the Free Software
|
||||||
this License, you may choose any version ever published by the Free Software
|
Foundation. If the Program does not specify a version number of the
|
||||||
Foundation.
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
If the Program specifies that a proxy can decide which future
|
||||||
programs whose distribution conditions are different, write to the author
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
public statement of acceptance of a version permanently authorizes you
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
to choose that version for the Program.
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
15. Disclaimer of Warranty.
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
16. Limitation of Liability.
|
||||||
|
|
||||||
Appendix: How to Apply These Terms to Your New Programs
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
If you develop a new program, and you want it to be of the greatest
|
||||||
possible use to the public, the best way to achieve this is to make it
|
possible use to the public, the best way to achieve this is to make it
|
||||||
@@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms.
|
|||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
To do so, attach the following notices to the program. It is safest
|
||||||
to attach them to the start of each source file to most effectively
|
to attach them to the start of each source file to most effectively
|
||||||
convey the exclusion of warranty; and each file should have at least
|
state the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
Copyright (C) 19yy <name of author>
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
@@ -304,36 +645,30 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
If the program does terminal interaction, make it output a short
|
||||||
when it starts in an interactive mode:
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
<program> Copyright (C) <year> <name of author>
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
under certain conditions; type `show c' for details.
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
parts of the General Public License. Of course, the commands you use may
|
parts of the General Public License. Of course, your program's commands
|
||||||
be called something other than `show w' and `show c'; they could even be
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
necessary. Here is a sample; alter the names:
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
The GNU General Public License does not permit incorporating your program
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
<signature of Ty Coon>, 1 April 1989
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Ty Coon, President of Vice
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Library General
|
|
||||||
Public License instead of this License.
|
|
||||||
|
|||||||
@@ -3,6 +3,363 @@ Revision history for Verilator
|
|||||||
The contributors that suggested a given feature are shown in []. [by ...]
|
The contributors that suggested a given feature are shown in []. [by ...]
|
||||||
indicates the contributor was also the author of the fix; Thanks!
|
indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
|
* Verilator 3.714 2009/09/18
|
||||||
|
|
||||||
|
** Add --bbox-sys option to blackbox $system calls.
|
||||||
|
|
||||||
|
** Support generate for var++, var--, ++var, --var.
|
||||||
|
|
||||||
|
*** Improved warning when "do" used as identifier.
|
||||||
|
|
||||||
|
**** Don't require SYSTEMPERL_INCLUDE if SYSTEMPERL/src exists. [Gary Thomas]
|
||||||
|
|
||||||
|
**** Fix deep defines causing flex scanner overflows. [Brad Dobbie]
|
||||||
|
|
||||||
|
**** Fix preprocessing commas in deep parameterized macros. [Brad Dobbie]
|
||||||
|
|
||||||
|
**** Fix tracing escaped dotted identifiers, bug107.
|
||||||
|
|
||||||
|
**** Fix $display with uppercase %M.
|
||||||
|
|
||||||
|
**** Fix --error-limit option being ignored.
|
||||||
|
|
||||||
|
* Verilator 3.713 2009/08/04
|
||||||
|
|
||||||
|
** Support constant function calls for parameters. [many!]
|
||||||
|
|
||||||
|
*** Support SystemVerilog "logic", bug101. [by Alex Duller]
|
||||||
|
|
||||||
|
*** Name SYMRSVDWORD error, and allow disabling it, bug103. [Gary Thomas]
|
||||||
|
|
||||||
|
**** Fix escaped preprocessor identifiers, bug106. [Nimrod Gileadi]
|
||||||
|
|
||||||
|
* Verilator 3.712 2009/07/14
|
||||||
|
|
||||||
|
** Patching SystemC is no longer required to trace sc_bvs.
|
||||||
|
|
||||||
|
*** Support zero-width constants in concatenations. [Jeff Winston]
|
||||||
|
|
||||||
|
*** Add verilator --pins-uint8 option to use sc_in<uint8_t/uint16_t>.
|
||||||
|
|
||||||
|
*** Add verilator -V option, to show verbose version.
|
||||||
|
|
||||||
|
*** On WIDTH warnings, show variable name causing error. [Jeff Winston]
|
||||||
|
|
||||||
|
**** Add BLKLOOPINIT error code, and describe --unroll-count. [Jeff Winston]
|
||||||
|
|
||||||
|
* Verilator 3.711 2009/06/23
|
||||||
|
|
||||||
|
**** Support decimal constants of arbitrary widths. [Mark Marshall]
|
||||||
|
|
||||||
|
**** Fix error on case statement with all duplicate items, bug99. [Gary Thomas]
|
||||||
|
|
||||||
|
**** Fix segfault on unrolling for's with bad inits, bug90. [Andreas Olofsson]
|
||||||
|
|
||||||
|
**** Fix tristates causing "Assigned pin is neither...". [by Lane Brooks]
|
||||||
|
|
||||||
|
**** Fix compiler errors under Fedora release candidate 11. [Chitlesh Goorah]
|
||||||
|
|
||||||
|
* Verilator 3.710 2009/05/19
|
||||||
|
|
||||||
|
** Verilator is now licensed under LGPL v3 and/or Artistic v2.0.
|
||||||
|
|
||||||
|
*** `__FILE__ now expands to a string, per draft SystemVerilog 2010(ish).
|
||||||
|
|
||||||
|
**** The front end parser has been re-factored to enable more SV parsing.
|
||||||
|
Code should parse the same, but minor parsing bugs may pop up.
|
||||||
|
|
||||||
|
**** Verilator_includer is no longer installed twice, bug48. [Lane Brooks]
|
||||||
|
|
||||||
|
**** Fix escaped identifiers with '.' causing conflicts, bug83. [J Baxter]
|
||||||
|
|
||||||
|
**** Fix define formal arguments that contain newlines, bug84. [David A]
|
||||||
|
|
||||||
|
* Verilator 3.703 2009/05/02
|
||||||
|
|
||||||
|
*** Fix $clog2 calculation error with powers-of-2, bug81. [Patricio Kaplan]
|
||||||
|
|
||||||
|
**** Fix error with tasks that have output first, bug78. [Andrea Foletto]
|
||||||
|
|
||||||
|
**** Fix "cloning" error with -y/--top-module, bug76. [Dimitris Nalbantis]
|
||||||
|
|
||||||
|
**** Fix segfault with error on bad --top-module, bug79. [Dimitris Nalbantis]
|
||||||
|
|
||||||
|
**** Fix "redefining I" error with complex includes. [Duraid Madina]
|
||||||
|
|
||||||
|
**** Fix GCC 4.3.2 compile warnings.
|
||||||
|
|
||||||
|
* Verilator 3.702 2009/03/28
|
||||||
|
|
||||||
|
*** Add --pins-bv option to use sc_bv for all ports. [Brian Small]
|
||||||
|
|
||||||
|
*** Add SYSTEMPERL_INCLUDE envvar to assist RPM builds. [Chitlesh Goorah]
|
||||||
|
|
||||||
|
**** Report errors when duplicate labels are used, bug72. [Vasu Kandadi]
|
||||||
|
|
||||||
|
**** Fix the SC_MODULE name() to not include __PVT__. [Bob Fredieu]
|
||||||
|
|
||||||
|
* Verilator 3.701 2009/02/26
|
||||||
|
|
||||||
|
** Support repeat and forever statements. [Jeremy Bennett]
|
||||||
|
|
||||||
|
*** Add --debugi-<srcfile> option, for internal debugging. [Dennis Muhlestein]
|
||||||
|
|
||||||
|
**** Fix compile issues with GCC 4.3, bug47. [Lane Brooks]
|
||||||
|
|
||||||
|
**** Fix VL_RANDom to better randomize bits. [Art Stamness]
|
||||||
|
|
||||||
|
**** Fix error messages to consistently go to stderr. [Jeremy Bennett]
|
||||||
|
|
||||||
|
**** Fix left associativity for ?: operators.
|
||||||
|
|
||||||
|
* Verilator 3.700 2009/01/08
|
||||||
|
|
||||||
|
** Add limited support for tristate inouts. Written by Lane Brooks,
|
||||||
|
under support by Ubixum Inc. This allows common pad ring and
|
||||||
|
tristate-mux structures to be Verilated. See the documentation for
|
||||||
|
more information on supported constructs.
|
||||||
|
|
||||||
|
** Add --coverage_toggle for toggle coverage analysis.
|
||||||
|
Running coverage now requires SystemPerl 1.301 or newer.
|
||||||
|
|
||||||
|
*** Add /*verilator coverage_on/_off */ to bracket coverage regions.
|
||||||
|
|
||||||
|
*** Optimize two-level shift and and/or trees, +23% on one test.
|
||||||
|
|
||||||
|
*** Support posedge of bit-selected signals, bug45. [Rodney Sinclair]
|
||||||
|
|
||||||
|
*** Line coverage now aggregates by hierarchy automatically.
|
||||||
|
Previously this would be done inside SystemPerl, which was slower.
|
||||||
|
|
||||||
|
**** Minor performance improvements of Verilator compiler runtime.
|
||||||
|
|
||||||
|
**** Coverage of each parametarized module is counted separately. [Bob Fredieu]
|
||||||
|
|
||||||
|
**** Fix creating parameterized modules when no parameter values are changed.
|
||||||
|
|
||||||
|
**** Fix certain generate-if cells causing "clone" error. [Stephane Laurent]
|
||||||
|
|
||||||
|
**** Fix line coverage of public functions. [Soon Koh]
|
||||||
|
|
||||||
|
**** Fix SystemC 2.2 deprecated warnings about sensitive() and sc_start().
|
||||||
|
|
||||||
|
**** Fix arrayed variables under function not compiling, bug44. [Ralf Karge]
|
||||||
|
|
||||||
|
**** Fix --output-split-cfuncs to also split trace code. [Niranjan Prabhu]
|
||||||
|
|
||||||
|
**** Fix 'bad select range' warning missing some cases, bug43. [Lane Brooks]
|
||||||
|
|
||||||
|
**** Fix internal signal names containing control characters (broke in 3.680).
|
||||||
|
|
||||||
|
**** Fix compile error on Ubuntu 8.10. [Christopher Boumenot]
|
||||||
|
|
||||||
|
**** Fix internal error on "output x; reg x = y;".
|
||||||
|
|
||||||
|
**** Fix wrong result for read of delayed FSM signal, bug46. [Rodney Sinclair]
|
||||||
|
|
||||||
|
* Verilator 3.681 2008/11/12
|
||||||
|
|
||||||
|
*** Add SystemVerilog unique and priority case.
|
||||||
|
|
||||||
|
**** Include Verilog file's directory name in coverage reports.
|
||||||
|
|
||||||
|
**** Fix 'for' under 'generate-for' causing error; bug38. [Rafael Shirakawa]
|
||||||
|
|
||||||
|
**** Fix coverage hierarchy being backwards with inlining. [Vasu Arasanipalai]
|
||||||
|
|
||||||
|
**** Fix GCC 4.3 compile error; bug35. [Lane Brooks]
|
||||||
|
|
||||||
|
**** Fix MSVC compile error; bug42. [John Stroebel]
|
||||||
|
|
||||||
|
* Verilator 3.680 2008/10/08
|
||||||
|
|
||||||
|
** Support negative bit indexes. [Stephane Laurent]
|
||||||
|
Tracing negative indexes requires latest Verilog-Perl and SystemPerl.
|
||||||
|
|
||||||
|
*** Suppress width warnings between constant strings and wider vectors.
|
||||||
|
[Rodney Sinclair]
|
||||||
|
|
||||||
|
**** Ignore SystemVerilog timeunit and timeprecision.
|
||||||
|
|
||||||
|
**** Expand environment variables in -f input files. [Lawrence Butcher]
|
||||||
|
|
||||||
|
**** Report error if port declaration is missing; bug32. [Guy-Armand Kamendje]
|
||||||
|
|
||||||
|
**** Fix genvars causing link error when using --public. [Chris Candler]
|
||||||
|
|
||||||
|
* Verilator 3.671 2008/09/19
|
||||||
|
|
||||||
|
** SystemC uint64_t pins are now the default instead of sc_bv<64>.
|
||||||
|
Use --no-pins64 for backward compatibility.
|
||||||
|
|
||||||
|
*** Support SystemVerilog "cover property" statements.
|
||||||
|
|
||||||
|
*** When warnings are disabled on signals that are flattened out, disable
|
||||||
|
the warnings on the signal(s) that replace it.
|
||||||
|
|
||||||
|
*** Add by-design and by-module subtotals to verilator_profcfunc.
|
||||||
|
|
||||||
|
*** Fix extra evaluation of pure combo blocks in SystemC output.
|
||||||
|
|
||||||
|
**** Add IMPERFECTSCH warning, disabled by default.
|
||||||
|
|
||||||
|
**** Support coverage under SystemPerl 1.285 and newer.
|
||||||
|
|
||||||
|
**** Fix stack overflow on large ? : trees. [John Sanguinetti]
|
||||||
|
|
||||||
|
**** Support arbitrary characters in identifiers. [Stephane Laurent]
|
||||||
|
|
||||||
|
* Verilator 3.670 2008/07/23
|
||||||
|
|
||||||
|
** Add --x-assign=fast option, and make it the default.
|
||||||
|
This chooses performance over reset debugging. See the manual.
|
||||||
|
|
||||||
|
** Add --autoflush, for flushing streams after $display. [Steve Tong]
|
||||||
|
|
||||||
|
** Add CASEWITHX lint warning and if disabled fix handling of casez with Xs.
|
||||||
|
|
||||||
|
*** Add $feof, $fgetc, $fgets, $fflush, $fscanf, $sscanf. [Holger Waechtler]
|
||||||
|
|
||||||
|
*** Add $stime. [Holger Waechtler]
|
||||||
|
|
||||||
|
*** Add $random.
|
||||||
|
|
||||||
|
*** Add --Wfuture-, for improving forward compatibility.
|
||||||
|
|
||||||
|
**** Fix verilator_includer not being installed properly. [Holger Waechtler]
|
||||||
|
|
||||||
|
**** Fix IMPURE errors due to X-assignment temporary variables. [Steve Tong]
|
||||||
|
|
||||||
|
**** Fix "lvalue" errors with public functions; bug25. [CY Wang]
|
||||||
|
|
||||||
|
**** Add WIDTH warning to $fopen etc file descriptors.
|
||||||
|
|
||||||
|
**** Internal changes to how $displays get compiled and executed.
|
||||||
|
|
||||||
|
* Verilator 3.665 2008/06/25
|
||||||
|
|
||||||
|
**** Ignore "// verilator" comments alone on endif lines. [Rodney Sinclair]
|
||||||
|
|
||||||
|
**** "Make install" now installs verilator_includer and verilator_profcfunc.
|
||||||
|
|
||||||
|
**** Fix tracing missing changes on undriven public wires. [Rodney Sinclair]
|
||||||
|
|
||||||
|
**** Fix syntax error when "`include `defname" is ifdefed. [John Dickol]
|
||||||
|
|
||||||
|
**** Fix error when macro call has commas in concatenate. [John Dickol]
|
||||||
|
|
||||||
|
**** Fix compile errors under Fedora 9, GCC 4.3.0. [by Jeremy Bennett]
|
||||||
|
|
||||||
|
**** Fix Makefile to find headers/libraries under prefix. [by Holger Waechtler]
|
||||||
|
|
||||||
|
* Verilator 3.664 2008/05/08
|
||||||
|
|
||||||
|
**** Fix missing file in kit.
|
||||||
|
|
||||||
|
* Verilator 3.663 2008/05/07
|
||||||
|
|
||||||
|
**** Add DESTDIR to Makefiles to assist RPM construction. [Gunter Dannoritzer]
|
||||||
|
|
||||||
|
**** Fix compiler warnings under GCC 4.2.1.
|
||||||
|
|
||||||
|
**** Fix preprocessor `else after series of `elsif. [Mark Nodine]
|
||||||
|
|
||||||
|
**** Fix parametrized defines calling define with comma. [Joshua Wise]
|
||||||
|
|
||||||
|
**** Fix comma separated list of primitives. [by Bryan Brady]
|
||||||
|
|
||||||
|
* Verilator 3.662 2008/04/25
|
||||||
|
|
||||||
|
*** Add Verilog 2005 $clog2() function.
|
||||||
|
This is useful in calculating bus-widths from parameters.
|
||||||
|
|
||||||
|
*** Support /**/ comments in -f option files. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Add error message when modules have duplicate names. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Support defines terminated in EOF, though against spec. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Support optional argument to $finish and $stop. [by Stefan Thiede]
|
||||||
|
|
||||||
|
**** Support ranges on gate primitive instantiations. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Ignore old standard(ish) Verilog-XL defines. [by Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix "always @ ((a) or (b))" syntax error. [by Niranjan Prabhu]
|
||||||
|
|
||||||
|
**** Fix "output reg name=expr;" syntax error. [Martin Scharrer]
|
||||||
|
|
||||||
|
**** Fix multiple .v files being read in random order. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix internal error when params get non-constants. [Johan Wouters]
|
||||||
|
|
||||||
|
**** Fix bug introduced in 3.661 with parametrized defines.
|
||||||
|
|
||||||
|
* Verilator 3.661 2008/04/04
|
||||||
|
|
||||||
|
*** The --enable-defenv configure option added in 3.660 is now the default.
|
||||||
|
This hard-codes a default for VERILATOR_ROOT etc in the executables.
|
||||||
|
|
||||||
|
*** Add --language option for supporting older code. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Add --top-module option to select between multiple tops. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Unsized concatenates now give WIDTHCONCAT warnings. [Jonathan Kimmitt]
|
||||||
|
Previously they threw fatal errors, which in most cases is correct
|
||||||
|
according to spec, but can be incorrect in presence of parameter values.
|
||||||
|
|
||||||
|
**** Support functions with "input integer". [Johan Wouters]
|
||||||
|
|
||||||
|
**** Ignore delays attached to gate UDPs. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix SystemVerilog parameterized defines with `` expansion,
|
||||||
|
and fix extra whitespace inserted on substitution. [Vladimir Matveyenko]
|
||||||
|
|
||||||
|
**** Fix no-module include files on command line. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix dropping of backslash quoted-quote at end of $display.
|
||||||
|
|
||||||
|
**** Fix task output pin connected to non-variables. [Jonathan Kimmitt]
|
||||||
|
|
||||||
|
**** Fix missing test_v in install datadir. [Holger Waechtler]
|
||||||
|
|
||||||
|
**** Fix internal error after MSB < LSB error reported to user. [Stefan Thiede]
|
||||||
|
|
||||||
|
* Verilator 3.660 2008/03/23
|
||||||
|
|
||||||
|
*** Add support for hard-coding VERILATOR_ROOT etc in the executables,
|
||||||
|
to enable easier use of Verilator RPMs. [Gunter Dannoritzer]
|
||||||
|
|
||||||
|
*** Allow multiple .v files on command line. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Convert re-defining macro error to warning. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Add --error-limit option. [Stefan Thiede]
|
||||||
|
|
||||||
|
*** Allow __ in cell names by quoting them in C. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix genvar to be signed, so "< 0" works properly. [Niranjan Prabhu]
|
||||||
|
|
||||||
|
**** Fix assignments to inputs inside functions/tasks. [Patricio Kaplan]
|
||||||
|
|
||||||
|
**** Fix definitions in main file.v, referenced in library. [Stefan Thiede]
|
||||||
|
|
||||||
|
**** Fix undefined assigns to be implicit warnings. [Stefan Thiede]
|
||||||
|
|
||||||
|
* Verilator 3.658 2008/02/25
|
||||||
|
|
||||||
|
**** Fix unistd compile error in 3.657. [Patricio Kaplan, Jonathan Kimmitt]
|
||||||
|
|
||||||
|
* Verilator 3.657 2008/02/20
|
||||||
|
|
||||||
|
**** Fix assignments of {a,b,c} = {c,b,a}. [Jonathan Kimmitt]
|
||||||
|
|
||||||
|
**** Fix Perl warning with --lint-only. [by Ding Xiaoliang]
|
||||||
|
|
||||||
|
**** Avoid creating obj_dir with --lint-only. [Ding Xiaoliang]
|
||||||
|
|
||||||
|
**** Fix parsing of always @(*). [Patricio Kaplan]
|
||||||
|
|
||||||
* Verilator 3.656 2008/01/18
|
* Verilator 3.656 2008/01/18
|
||||||
|
|
||||||
**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman]
|
**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman]
|
||||||
@@ -1128,14 +1485,13 @@ of input ports exists for tracing.
|
|||||||
**** First code written.
|
**** First code written.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
$Id$
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
|
|
||||||
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
||||||
|
|
||||||
Copyright 2001-2008 by Wilson Snyder. This program is free software;
|
Copyright 2001-2009 by Wilson Snyder. This program is free software; you
|
||||||
you can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
General Public License or the Perl Artistic License.
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
Version 2.0.
|
||||||
|
|
||||||
Local variables:
|
Local variables:
|
||||||
mode: outline
|
mode: outline
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
^CVS/
|
||||||
|
/CVS/
|
||||||
|
\.git/
|
||||||
|
\.svn/
|
||||||
|
\.(bak|old)/
|
||||||
|
\.(bak|old)$
|
||||||
|
\bMakefile$
|
||||||
|
\.tar\.
|
||||||
|
.*\.tgz
|
||||||
|
.*\.log
|
||||||
|
.*\.tmp
|
||||||
|
.*\.tex
|
||||||
|
.*\.key
|
||||||
|
.*\.vcd
|
||||||
|
/obj_dir/
|
||||||
|
/obj_dbg/
|
||||||
|
/obj_opt/
|
||||||
|
/INCA_libs/
|
||||||
|
/cov_work/
|
||||||
|
/logs/
|
||||||
|
Makefile
|
||||||
|
src/Makefile_obj
|
||||||
|
include/verilated.mk
|
||||||
|
config.cache
|
||||||
|
config.status
|
||||||
|
verilator_bin.*
|
||||||
|
autom4te\.cache/
|
||||||
|
nodist/
|
||||||
+91
-45
@@ -1,24 +1,24 @@
|
|||||||
# $Id$
|
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
# DESCRIPTION: Verilator top level: Makefile pre-configure version
|
# DESCRIPTION: Verilator top level: Makefile pre-configure version
|
||||||
#
|
#
|
||||||
# This file is part of Verilator.
|
# This file is part of Verilator.
|
||||||
#
|
#
|
||||||
# Author: Wilson Snyder <[email protected]>
|
# Author: Wilson Snyder <[email protected]>
|
||||||
#
|
#
|
||||||
# Code available from: http://www.veripool.com/verilator
|
# Code available from: http://www.veripool.org/verilator
|
||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# 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,
|
# Verilator is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
#****************************************************************************/
|
#****************************************************************************/
|
||||||
#
|
#
|
||||||
# make all to compile and build Verilator.
|
# make all to compile and build Verilator.
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
# source and built the program without creating any other files,
|
# source and built the program without creating any other files,
|
||||||
# `make distclean' should leave only the files that were in the
|
# `make distclean' should leave only the files that were in the
|
||||||
# distribution.
|
# distribution.
|
||||||
#
|
#
|
||||||
# make maintainer-clean
|
# make maintainer-clean
|
||||||
# Delete everything from the current directory that can be
|
# Delete everything from the current directory that can be
|
||||||
# reconstructed with this Makefile. This typically includes
|
# reconstructed with this Makefile. This typically includes
|
||||||
@@ -61,6 +61,9 @@ MAKEINFO = makeinfo
|
|||||||
TEXI2DVI = texi2dvi
|
TEXI2DVI = texi2dvi
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
|
|
||||||
|
# Destination prefix for RPMs
|
||||||
|
DESTDIR =
|
||||||
|
|
||||||
#### Don't edit: You're much better using configure switches to set these
|
#### Don't edit: You're much better using configure switches to set these
|
||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
exec_prefix = @exec_prefix@
|
exec_prefix = @exec_prefix@
|
||||||
@@ -78,8 +81,15 @@ datadir = @datadir@
|
|||||||
infodir = @infodir@
|
infodir = @infodir@
|
||||||
|
|
||||||
# Directory in which to install package specific files
|
# Directory in which to install package specific files
|
||||||
|
# Generally ${prefix}/share/verilator
|
||||||
pkgdatadir = @pkgdatadir@
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
|
# Directory in which to install data across multiple architectures
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
|
||||||
|
# Compile options
|
||||||
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
@@ -94,26 +104,33 @@ DISTDEP = info Makefile
|
|||||||
# Files to distribute.
|
# Files to distribute.
|
||||||
DISTBIN = $(wildcard bin/verilator-*)
|
DISTBIN = $(wildcard bin/verilator-*)
|
||||||
|
|
||||||
DISTFILES_INC = $(INFOS) .cvsignore COPYING *.in *.ac \
|
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING *.in *.ac \
|
||||||
Changes README TODO \
|
Changes README TODO \
|
||||||
|
MANIFEST.SKIP \
|
||||||
bin/* \
|
bin/* \
|
||||||
install-sh configure mkinstalldirs *.texi \
|
install-sh configure mkinstalldirs *.texi \
|
||||||
include/verilated.[chv]* \
|
include/verilated*.[chv]* \
|
||||||
include/verilatedos.[chv]* \
|
|
||||||
include/*.in \
|
include/*.in \
|
||||||
src/.cvsignore src/*.in src/*.cpp src/*.[chly] src/astgen src/flexfix \
|
include/.*ignore \
|
||||||
src/*.pl \
|
.*attributes */.*attributes */*/.*attributes \
|
||||||
test_*/.cvsignore test_*/Makefile* test_*/*.cpp \
|
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
||||||
|
src/*.pl src/*.pod \
|
||||||
|
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
||||||
test_verilated/vgen*.pl \
|
test_verilated/vgen*.pl \
|
||||||
test_regress/t/*.v* \
|
test_regress/t/*.cpp \
|
||||||
test_regress/t/*.pl \
|
test_regress/t/*.h \
|
||||||
|
test_regress/t/*.dat \
|
||||||
|
test_regress/t/*.mem \
|
||||||
test_regress/t/*.out \
|
test_regress/t/*.out \
|
||||||
|
test_regress/t/*.pl \
|
||||||
|
test_regress/t/*.v* \
|
||||||
verilator.* \
|
verilator.* \
|
||||||
|
|
||||||
INST_PROJ_FILES = \
|
INST_PROJ_FILES = \
|
||||||
bin/verilator \
|
bin/verilator \
|
||||||
bin/verilator_includer \
|
bin/verilator_includer \
|
||||||
|
bin/verilator_profcfunc \
|
||||||
include/verilated.[chv]* \
|
include/verilated.[chv]* \
|
||||||
include/verilated.mk \
|
include/verilated.mk \
|
||||||
include/verilatedos.[chv]* \
|
include/verilatedos.[chv]* \
|
||||||
@@ -124,8 +141,10 @@ INST_PROJ_BIN_FILES = \
|
|||||||
|
|
||||||
DISTFILES := $(DISTFILES_INC)
|
DISTFILES := $(DISTFILES_INC)
|
||||||
|
|
||||||
|
VL_INST_MAN_FILES = verilator.1
|
||||||
|
|
||||||
all: all_nomsg msg_test
|
all: all_nomsg msg_test
|
||||||
all_nomsg: verilator_exe
|
all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
|
||||||
|
|
||||||
.PHONY:verilator_exe
|
.PHONY:verilator_exe
|
||||||
verilator_exe verilator_bin verilator_bin_dbg:
|
verilator_exe verilator_bin verilator_bin_dbg:
|
||||||
@@ -140,6 +159,7 @@ msg_test:
|
|||||||
@echo "Type 'make test' to test."
|
@echo "Type 'make test' to test."
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
|
.PHONY:test
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||||
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
||||||
else
|
else
|
||||||
@@ -184,16 +204,18 @@ verilator.html: bin/verilator
|
|||||||
verilator.pdf: bin/verilator $(DISTCONFIG)
|
verilator.pdf: bin/verilator $(DISTCONFIG)
|
||||||
pod2latex --full --out verilator.tex bin/verilator
|
pod2latex --full --out verilator.tex bin/verilator
|
||||||
cat < verilator.tex \
|
cat < verilator.tex \
|
||||||
|
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
|
||||||
|
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\usepackage{fancyhdr} \\pagestyle{fancy}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\usepackage{fancyhdr} \\pagestyle{fancy}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\title{$(DISTTITLE)} \\date{${DISTDATE}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.com}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\title{$(DISTTITLE)} \\date{${DISTDATE}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.org}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\lhead[$(DISTTITLE)]{$(DISTTITLE)}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\lhead[$(DISTTITLE)]{$(DISTTITLE)}\n\\begin{document}/' \
|
||||||
| sed 's/\\tableofcontents/\\begin{titlepage} \\maketitle \\end{titlepage}\n\\tableofcontents/' \
|
| sed 's/\\tableofcontents/\\begin{titlepage} \\maketitle \\end{titlepage}\n\\tableofcontents/' \
|
||||||
> verilator2.tex
|
> verilator2.tex
|
||||||
mv verilator2.tex verilator.tex
|
mv verilator2.tex verilator.tex
|
||||||
pdflatex verilator.tex
|
pdflatex verilator.tex
|
||||||
pdflatex verilator.tex
|
pdflatex verilator.tex
|
||||||
-rm -f verilator.toc verilator.aux verilator.idx
|
-rm -f verilator.toc verilator.aux verilator.idx verilator.out
|
||||||
|
|
||||||
INSTALL: install.texi
|
INSTALL: install.texi
|
||||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/install.texi --output=$@ \
|
$(MAKEINFO) -I$(srcdir) $(srcdir)/install.texi --output=$@ \
|
||||||
@@ -203,21 +225,36 @@ README: readme.texi
|
|||||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/readme.texi --output=$@ \
|
$(MAKEINFO) -I$(srcdir) $(srcdir)/readme.texi --output=$@ \
|
||||||
--no-headers --no-validate
|
--no-headers --no-validate
|
||||||
|
|
||||||
installdirs:
|
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir)
|
|
||||||
|
|
||||||
# See uninstall also
|
# See uninstall also
|
||||||
VL_INST_BIN_FILES = verilator
|
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
|
||||||
|
verilator_includer verilator_profcfunc
|
||||||
|
# Some scripts go into both the search path and pkgdatadir,
|
||||||
|
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||||
installbin:
|
installbin:
|
||||||
( cd bin ; $(INSTALL_PROGRAM) verilator $(bindir)/verilator )
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
|
||||||
|
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
|
||||||
|
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||||
|
|
||||||
VL_INST_MAN_FILES = verilator.1
|
|
||||||
installman:
|
installman:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||||
for p in $(VL_INST_MAN_FILES) ; do \
|
for p in $(VL_INST_MAN_FILES) ; do \
|
||||||
$(INSTALL_PROGRAM) $$p $(mandir)/man1/$$p; \
|
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install: all_nomsg installdirs installbin installman install-msg
|
installdata:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r include $(DESTDIR)$(pkgdatadir)
|
||||||
|
cp -r test_c $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r test_sc $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r test_sp $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r test_v $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
|
||||||
|
VL_INST_DATA_FILES = verilator.1
|
||||||
|
install: all_nomsg installbin installman installdata install-msg
|
||||||
|
|
||||||
install-here: installman ftp
|
install-here: installman ftp
|
||||||
|
|
||||||
@@ -232,10 +269,14 @@ install-project: dist
|
|||||||
for p in verilator.1 ; do \
|
for p in verilator.1 ; do \
|
||||||
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
||||||
done
|
done
|
||||||
$(INST_PROJ_CVS) $(DISTNAME).tar.gz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
||||||
rm $(DISTNAME).tar.gz
|
rm $(DISTNAME).tgz
|
||||||
|
|
||||||
install-project-quick:
|
install-project-quick:
|
||||||
|
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||||
|
@echo "%Error: Reconfigure with './configure --disable-defenv' to avoid hardcoded paths."
|
||||||
|
false
|
||||||
|
endif
|
||||||
@echo "Install-project-quick (no strip) to $(DIRPROJECT)"
|
@echo "Install-project-quick (no strip) to $(DIRPROJECT)"
|
||||||
for p in $(INST_PROJ_FILES) ; do \
|
for p in $(INST_PROJ_FILES) ; do \
|
||||||
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p; \
|
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p; \
|
||||||
@@ -246,9 +287,6 @@ install-project-quick:
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ftp: info
|
ftp: info
|
||||||
echo "http://www.veripool.com/verilator3.html"
|
|
||||||
cp verilator.html verilator_man.html
|
|
||||||
ftp_tree --password $(VERIPOOL_PW) --user $(VERIPOOL_USER) verilator_man.html webftp.veripool.com:/web
|
|
||||||
|
|
||||||
install-msg:
|
install-msg:
|
||||||
@echo "Installed!"
|
@echo "Installed!"
|
||||||
@@ -261,8 +299,9 @@ install-msg:
|
|||||||
@echo
|
@echo
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
-cd $(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
||||||
-cd $(bindir) && rm -f $(VL_INST_BIN_FILES)
|
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
|
||||||
|
-rm -f $(DESTDIR)$(pkgdatadir)
|
||||||
|
|
||||||
# autoheader might not change config_build.h.in, so touch a stamp file.
|
# autoheader might not change config_build.h.in, so touch a stamp file.
|
||||||
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
||||||
@@ -287,7 +326,7 @@ configure: configure.ac
|
|||||||
maintainer-clean::
|
maintainer-clean::
|
||||||
@echo "This command is intended for maintainers to use;"
|
@echo "This command is intended for maintainers to use;"
|
||||||
@echo "rebuilding the deleted files requires makeinfo."
|
@echo "rebuilding the deleted files requires makeinfo."
|
||||||
rm -f *.info* $(INFOS) faq.html verilator.html configure bin/*
|
rm -f *.info* $(INFOS) faq.html verilator.html configure
|
||||||
|
|
||||||
clean mostlyclean distclean maintainer-clean maintainer-copy::
|
clean mostlyclean distclean maintainer-clean maintainer-copy::
|
||||||
for dir in $(SUBDIRS); do \
|
for dir in $(SUBDIRS); do \
|
||||||
@@ -296,7 +335,7 @@ clean mostlyclean distclean maintainer-clean maintainer-copy::
|
|||||||
done
|
done
|
||||||
|
|
||||||
clean mostlyclean distclean maintainer-clean::
|
clean mostlyclean distclean maintainer-clean::
|
||||||
rm -f $(SCRIPTS) *.tmp
|
rm -f $(SCRIPTS) *.tmp
|
||||||
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
||||||
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
||||||
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
||||||
@@ -312,6 +351,13 @@ TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/[a-z]*.in \
|
|||||||
TAGS: $(TAGFILES)
|
TAGS: $(TAGFILES)
|
||||||
etags $(TAGFILES)
|
etags $(TAGFILES)
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Test targets
|
||||||
|
|
||||||
|
dist-file-list:
|
||||||
|
@echo "begin-dist-file-list:"; # Scripts look for this
|
||||||
|
@echo $(wildcard $(DISTFILES))
|
||||||
|
@echo "end-dist-file-list:"; # Scripts look for this
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Distributions
|
# Distributions
|
||||||
@@ -320,7 +366,7 @@ DISTCONFIG = src/config_build.h.in
|
|||||||
|
|
||||||
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
|
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
|
||||||
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
|
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
|
||||||
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([0-3]\?[0-9].[0-3]\?[0-9].[1-2][0-9][0-9][0-9]\).*/\1/' -e q $(DISTCONFIG))
|
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
|
||||||
|
|
||||||
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
||||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||||
@@ -339,14 +385,14 @@ dist: $(DISTDEP) maintainer-copy
|
|||||||
chmod -R a+r $(DISTNAME)
|
chmod -R a+r $(DISTNAME)
|
||||||
tar chf $(DISTNAME).tar $(DISTNAME)
|
tar chf $(DISTNAME).tar $(DISTNAME)
|
||||||
gzip --force --best $(DISTNAME).tar
|
gzip --force --best $(DISTNAME).tar
|
||||||
|
mv $(DISTNAME).tar.gz $(DISTNAME).tgz
|
||||||
rm -fr $(DISTNAME)
|
rm -fr $(DISTNAME)
|
||||||
|
|
||||||
maintainer-diff:
|
maintainer-diff:
|
||||||
svnorcvs diff $(DISTTAGNAME)
|
svnorcvs diff $(DISTTAGNAME)
|
||||||
|
|
||||||
preexist:
|
preexist:
|
||||||
test ! -r ~/src/kits/$(DISTNAME).tar.gz
|
svnorcvs nexists $(DISTTAGNAME)
|
||||||
|
|
||||||
maintainer-dist: preexist dist tag
|
maintainer-dist: preexist dist tag
|
||||||
cp *.gz ~/backpack
|
svnorcvs release $(DISTNAME).tgz
|
||||||
cp *.gz ~/src/kits
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
// DESCRIPTION: Verilator: List of To Do issues.
|
// DESCRIPTION: Verilator: List of To Do issues.
|
||||||
//
|
//
|
||||||
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
Finish 3.400 new ordering fixes
|
Finish 3.400 new ordering fixes
|
||||||
Latch optimizations {Need here}
|
Latch optimizations {Need here}
|
||||||
Task I/Os connecting to non-simple variables.
|
Task I/Os connecting to non-simple variables.
|
||||||
Fix nested casez statements expanding into to huge C++. [JeanPaul Vanitegem]
|
Fix nested casez statements expanding into to huge C++. [JeanPaul Vanitegem]
|
||||||
@@ -50,7 +50,12 @@ Testing:
|
|||||||
|
|
||||||
Usability:
|
Usability:
|
||||||
Better reporting of unopt problems, including what lines of code
|
Better reporting of unopt problems, including what lines of code
|
||||||
Report more errors (all of them?) before exiting [Eugene Weber]
|
Report more errors (all of them?) before exiting [Eugene Weber]
|
||||||
|
|
||||||
|
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.
|
||||||
|
V3Graph should be templated container type, taking in Vertex + Edge types
|
||||||
|
|
||||||
Performance:
|
Performance:
|
||||||
Constant propagation
|
Constant propagation
|
||||||
@@ -65,7 +70,7 @@ Performance:
|
|||||||
Multithreaded execution
|
Multithreaded execution
|
||||||
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
|
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
|
||||||
Move _last sets and all other combo logic inside master
|
Move _last sets and all other combo logic inside master
|
||||||
if() that triggers on all possible sense items
|
if() that triggers on all possible sense items
|
||||||
Rewrite and combine V3Life, V3Subst
|
Rewrite and combine V3Life, V3Subst
|
||||||
If block temp only ever set in one place to constant, propagate it
|
If block temp only ever set in one place to constant, propagate it
|
||||||
Used in t_mem for array delayed assignments
|
Used in t_mem for array delayed assignments
|
||||||
@@ -135,15 +140,15 @@ Selectable SystemC types based on widths (see notes below)
|
|||||||
c) a conditional whose possible values are (a) or (b)
|
c) a conditional whose possible values are (a) or (b)
|
||||||
|
|
||||||
2) One can lose that fact that a node is a tristate node. This happens
|
2) One can lose that fact that a node is a tristate node. This happens
|
||||||
if a tristate node is assigned to a 'standard' node, or is used on
|
if a tristate node is assigned to a 'standard' node, or is used on
|
||||||
RHS of a conditional. The following infer tristate signals:
|
RHS of a conditional. The following infer tristate signals:
|
||||||
a) inout <SIGNAL>
|
a) inout <SIGNAL>
|
||||||
b) tri <SIGNAL>
|
b) tri <SIGNAL>
|
||||||
c) assigning to 'Z' (maybe through a conditional)
|
c) assigning to 'Z' (maybe through a conditional)
|
||||||
Note: tristate-ness of an output port determined only by
|
Note: tristate-ness of an output port determined only by
|
||||||
statements in the module (not the instances it calls)
|
statements in the module (not the instances it calls)
|
||||||
|
|
||||||
4) Tristate variables can't be multidimensional arrays
|
4) Tristate variables can't be multidimensional arrays
|
||||||
5) Only check tristate contention between modules (not within!)
|
5) Only check tristate contention between modules (not within!)
|
||||||
6) Only simple compares with 'Z' are allowed (===)
|
6) Only simple compares with 'Z' are allowed (===)
|
||||||
|
|
||||||
|
|||||||
+604
-190
File diff suppressed because it is too large
Load Diff
+18
-24
@@ -1,19 +1,7 @@
|
|||||||
: # -*-Mode: perl;-*- use perl, wherever it is
|
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||||
eval 'exec perl -wS $0 ${1+"$@"}'
|
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||||
if 0;
|
if 0;
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -33,14 +21,16 @@ use vars qw ($Debug);
|
|||||||
$Debug = 0;
|
$Debug = 0;
|
||||||
my $Opt_A;
|
my $Opt_A;
|
||||||
my $Opt_B;
|
my $Opt_B;
|
||||||
|
my $Opt_Lineno = 1;
|
||||||
autoflush STDOUT 1;
|
autoflush STDOUT 1;
|
||||||
autoflush STDERR 1;
|
autoflush STDERR 1;
|
||||||
Getopt::Long::config ("no_auto_abbrev");
|
Getopt::Long::config ("no_auto_abbrev");
|
||||||
if (! GetOptions (
|
if (! GetOptions (
|
||||||
"help" => \&usage,
|
"help" => \&usage,
|
||||||
"debug" => \&debug,
|
"debug" => \&debug,
|
||||||
"<>" => \¶meter,
|
"<>" => \¶meter,
|
||||||
)) {
|
"lineno!" => \$Opt_Lineno,
|
||||||
|
)) {
|
||||||
die "%Error: Bad usage, try 'verilator_difftree --help'\n";
|
die "%Error: Bad usage, try 'verilator_difftree --help'\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +81,7 @@ sub diff_file {
|
|||||||
|
|
||||||
filter ($a, $tmp_a);
|
filter ($a, $tmp_a);
|
||||||
filter ($b, $tmp_b);
|
filter ($b, $tmp_b);
|
||||||
system("diff $tmp_a $tmp_b");
|
system("diff -u $tmp_a $tmp_b");
|
||||||
unlink $tmp_a;
|
unlink $tmp_a;
|
||||||
unlink $tmp_b;
|
unlink $tmp_b;
|
||||||
}
|
}
|
||||||
@@ -106,6 +96,7 @@ sub filter {
|
|||||||
next if $line =~ / This=/;
|
next if $line =~ / This=/;
|
||||||
$line =~ s/0x[a-f0-9]+/0x/g;
|
$line =~ s/0x[a-f0-9]+/0x/g;
|
||||||
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
||||||
|
$line =~ s/{\d+}/{}/g if !$Opt_Lineno;
|
||||||
print $f2 $line;
|
print $f2 $line;
|
||||||
}
|
}
|
||||||
$f1->close;
|
$f1->close;
|
||||||
@@ -115,7 +106,6 @@ sub filter {
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -130,7 +120,7 @@ sub parameter {
|
|||||||
$Opt_A = $param;
|
$Opt_A = $param;
|
||||||
} elsif (!defined $Opt_B) {
|
} elsif (!defined $Opt_B) {
|
||||||
$Opt_B = $param;
|
$Opt_B = $param;
|
||||||
} else {
|
} else {
|
||||||
die "%Error: Unknown parameter: $param\n";
|
die "%Error: Unknown parameter: $param\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,15 +164,19 @@ directories, ignoring irrelevant pointer differences.
|
|||||||
|
|
||||||
Displays this message and program version and exits.
|
Displays this message and program version and exits.
|
||||||
|
|
||||||
|
=item --nolineno
|
||||||
|
|
||||||
|
Do not show differences in line numbering.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
The latest version is available from L<http://www.veripool.com/>.
|
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||||
|
|
||||||
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2009 by Wilson Snyder. This package is free software; you can
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
Lesser General Public License or the Perl Artistic License.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
: # -*-Mode: perl;-*- use perl, wherever it is
|
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||||
eval 'exec perl -wS $0 ${1+"$@"}'
|
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||||
if 0;
|
if 0;
|
||||||
# $Id$
|
|
||||||
# DESCRIPTION: Print include statements for each ARGV
|
# DESCRIPTION: Print include statements for each ARGV
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2009 by Wilson Snyder. This package is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
# General Public License or the Perl Artistic License.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.005;
|
require 5.005;
|
||||||
|
|||||||
+48
-31
@@ -1,19 +1,7 @@
|
|||||||
: # -*-Mode: perl;-*- use perl, wherever it is
|
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||||
eval 'exec perl -wS $0 ${1+"$@"}'
|
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||||
if 0;
|
if 0;
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2007-2008 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -21,6 +9,7 @@ use warnings;
|
|||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use IO::File;
|
use IO::File;
|
||||||
use Pod::Usage;
|
use Pod::Usage;
|
||||||
|
eval { use Data::Dumper; $Data::Dumper::Indent = 1; }; # Debug, ok if missing
|
||||||
use strict;
|
use strict;
|
||||||
use vars qw ($Debug);
|
use vars qw ($Debug);
|
||||||
|
|
||||||
@@ -50,7 +39,6 @@ profcfunc($Opt_File);
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -63,7 +51,7 @@ sub parameter {
|
|||||||
my $param = shift;
|
my $param = shift;
|
||||||
if (!defined $Opt_File) {
|
if (!defined $Opt_File) {
|
||||||
$Opt_File = $param;
|
$Opt_File = $param;
|
||||||
} else {
|
} else {
|
||||||
die "%Error: Unknown parameter: $param\n";
|
die "%Error: Unknown parameter: $param\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +66,8 @@ sub profcfunc {
|
|||||||
my %funcs;
|
my %funcs;
|
||||||
|
|
||||||
while (defined (my $line=$fh->getline())) {
|
while (defined (my $line=$fh->getline())) {
|
||||||
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+.*\s+(\S+)\s*$/) {
|
# %time cumesec selfsec calls {stuff} name
|
||||||
|
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
|
||||||
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
|
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
|
||||||
$funcs{$func}{pct} += $pct;
|
$funcs{$func}{pct} += $pct;
|
||||||
$funcs{$func}{sec} += $sec;
|
$funcs{$func}{sec} += $sec;
|
||||||
@@ -88,47 +77,75 @@ sub profcfunc {
|
|||||||
$fh->close;
|
$fh->close;
|
||||||
|
|
||||||
# Find modules
|
# Find modules
|
||||||
|
my %pointer_mods;
|
||||||
my %verilated_mods;
|
my %verilated_mods;
|
||||||
foreach my $func (keys %funcs) {
|
foreach my $func (keys %funcs) {
|
||||||
if ($func =~ /(.*)::_eval\(.*__Syms.*\)$/) {
|
if ($func =~ /(.*)::_eval\(([a-zA-Z_0-9]+__Syms).*\)$/) {
|
||||||
$verilated_mods{$1} = qr/^$1/;
|
$verilated_mods{$1} = qr/^$1/;
|
||||||
|
$pointer_mods{$2} = $1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#print Dumper(\%pointer_mods, \%verilated_mods);
|
||||||
|
|
||||||
# Resort by Verilog name
|
# Resort by Verilog name
|
||||||
my %vfuncs;
|
my %vfuncs;
|
||||||
my %groups;
|
my %groups;
|
||||||
foreach my $func (keys %funcs) {
|
foreach my $func (keys %funcs) {
|
||||||
|
my $pct = $funcs{$func}{pct};
|
||||||
my $vfunc = $func;
|
my $vfunc = $func;
|
||||||
my $design;
|
my $design;
|
||||||
|
|
||||||
|
if ($func =~ /\(([a-zA-Z_0-9]+__Syms)/) {
|
||||||
|
$design = $pointer_mods{$1};
|
||||||
|
}
|
||||||
|
|
||||||
foreach my $vde (keys %verilated_mods) {
|
foreach my $vde (keys %verilated_mods) {
|
||||||
|
last if $design;
|
||||||
if ($func =~ /$verilated_mods{$vde}/) {
|
if ($func =~ /$verilated_mods{$vde}/) {
|
||||||
$design=$vde;
|
$design=$vde;
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) {
|
|
||||||
|
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__l?([0-9]+)\(/) {
|
||||||
$vfunc = sprintf("VBlock %s:%d", $1, $2);
|
$vfunc = sprintf("VBlock %s:%d", $1, $2);
|
||||||
$groups{"Verilog Blocks under $design"} += $funcs{$func}{pct};
|
$groups{type}{"Verilog Blocks under $design"} += $pct;
|
||||||
|
$groups{design}{$design} += $pct;
|
||||||
|
$groups{module}{$1} += $pct;
|
||||||
} else {
|
} else {
|
||||||
if ($design) {
|
if ($design) {
|
||||||
$vfunc = sprintf("VCommon %s", $func);
|
$vfunc = sprintf("VCommon %s", $func);
|
||||||
$groups{"Common code under $design"} += $funcs{$func}{pct};
|
$groups{type}{"Common code under $design"} += $pct;
|
||||||
|
$groups{design}{$design} += $pct;
|
||||||
|
$groups{module}{$design." common code"} += $pct;
|
||||||
} else {
|
} else {
|
||||||
$vfunc = sprintf("C++ %s", $func);
|
$vfunc = sprintf("C++ %s", $func);
|
||||||
$groups{'C++'} += $funcs{$func}{pct};
|
$groups{type}{'C++'} += $pct;
|
||||||
|
$groups{design}{'C++'} += $pct;
|
||||||
|
$groups{module}{'C++'} += $pct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$vfuncs{$vfunc} = $funcs{$func};
|
$vfuncs{$vfunc} = $funcs{$func};
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Overall summary:\n");
|
|
||||||
print(" % time\n");
|
|
||||||
foreach (sort (keys %groups)) {
|
|
||||||
printf(" %6.2f In all %s\n", $groups{$_}, $_);
|
|
||||||
}
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
|
foreach my $type qw(type design module) {
|
||||||
|
my $missing = 100;
|
||||||
|
foreach (sort (keys %{$groups{$type}})) {
|
||||||
|
$missing -= $groups{$type}{$_};
|
||||||
|
}
|
||||||
|
if ($missing) {
|
||||||
|
$groups{$type}{"\377Unaccounted for/rounding error"} = $missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Overall summary by $type:\n");
|
||||||
|
printf(" %-6s %s\n","% time",$type);
|
||||||
|
foreach my $what (sort (keys %{$groups{$type}})) {
|
||||||
|
(my $pwhat = $what) =~ s/^\377//; # Just used to establish sort order
|
||||||
|
printf(" %6.2f %s\n", $groups{$type}{$what}, $pwhat);
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
print("Verilog code profile:\n");
|
print("Verilog code profile:\n");
|
||||||
print(" These are split into three categories:\n");
|
print(" These are split into three categories:\n");
|
||||||
@@ -189,11 +206,11 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
The latest version is available from L<http://www.veripool.com/>.
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
Copyright 2007-2008 by Wilson Snyder. This package is free software; you
|
Copyright 2007-2009 by Wilson Snyder. Verilator is free software; you can
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
Lesser General Public License or the Perl Artistic License.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
|||||||
+24
-7
@@ -1,20 +1,37 @@
|
|||||||
dnl $Id$
|
|
||||||
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||||
dnl Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
dnl
|
||||||
dnl redistribute it and/or modify it under the terms of either the GNU
|
dnl Copyright 2003-2009 by Wilson Snyder. Verilator is free software; you can
|
||||||
dnl General Public License or the Perl Artistic License.
|
dnl redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
|
dnl General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
AC_REVISION($Revision$)dnl
|
|
||||||
AC_INIT(src/Verilator.cpp)
|
AC_INIT(src/Verilator.cpp)
|
||||||
AC_CONFIG_HEADER(src/config_build.h)
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
|
|
||||||
dnl Special Substitutions
|
dnl Special Substitutions
|
||||||
|
AC_ARG_ENABLE(defenv,
|
||||||
|
[AS_HELP_STRING([--disable-defenv], [disable hardcoded default environment variables])],
|
||||||
|
CFG_WITH_DEFENV=$enableval,
|
||||||
|
CFG_WITH_DEFENV=yes)
|
||||||
|
AC_SUBST(CFG_WITH_DEFENV)
|
||||||
|
|
||||||
|
dnl Compiler flags
|
||||||
|
CXX=g++
|
||||||
|
CFLAGS=-I${includedir}
|
||||||
|
CPPFLAGS=-I${includedir}
|
||||||
|
CXXFLAGS=-I${includedir}
|
||||||
|
LDFLAGS=-L${libdir}
|
||||||
|
|
||||||
dnl Checks for programs.
|
dnl Checks for programs.
|
||||||
CXX=g++
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_CXX
|
AC_PROG_CXX
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
|
AC_LANG_PUSH(C++)
|
||||||
|
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
||||||
|
AC_TRY_RUN([int main() { return 0; }],
|
||||||
|
AC_MSG_RESULT(yes),
|
||||||
|
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]))
|
||||||
|
|
||||||
AC_PATH_PROG(PERL,perl)
|
AC_PATH_PROG(PERL,perl)
|
||||||
if test "x$PERL" = "x" ; then
|
if test "x$PERL" = "x" ; then
|
||||||
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
||||||
@@ -56,5 +73,5 @@ AC_SUBST(pkgdatadir)
|
|||||||
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||||
|
|
||||||
AC_MSG_RESULT([])
|
AC_MSG_RESULT([])
|
||||||
AC_MSG_RESULT([Now type 'make'])
|
AC_MSG_RESULT([Now type 'gmake'])
|
||||||
AC_MSG_RESULT([])
|
AC_MSG_RESULT([])
|
||||||
|
|||||||
+493
-100
@@ -1,15 +1,16 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
///
|
///
|
||||||
/// \file
|
/// \file
|
||||||
@@ -18,13 +19,12 @@
|
|||||||
/// This file must be compiled and linked against all objects
|
/// This file must be compiled and linked against all objects
|
||||||
/// created from Verilator.
|
/// created from Verilator.
|
||||||
///
|
///
|
||||||
/// Code available from: http://www.veripool.com/verilator
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
///
|
///
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
#include <string.h>
|
#include <cctype>
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||||
|
|
||||||
@@ -74,29 +74,49 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
|||||||
IData VL_RAND32() {
|
IData VL_RAND32() {
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
// Windows doesn't have lrand48(), although Cygwin does.
|
// Windows doesn't have lrand48(), although Cygwin does.
|
||||||
return (rand()<<16) | rand();
|
return (rand()<<16) ^ rand();
|
||||||
#else
|
#else
|
||||||
return (lrand48()<<16) | lrand48();
|
return (lrand48()<<16) ^ lrand48();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_RAND_RESET_I(int outBits) {
|
IData VL_RANDOM_I(int obits) {
|
||||||
|
return VL_RAND32() & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
|
||||||
|
QData VL_RANDOM_Q(int obits) {
|
||||||
|
QData data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
||||||
|
return data & VL_MASK_Q(obits);
|
||||||
|
}
|
||||||
|
|
||||||
|
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
|
||||||
|
for (int i=0; i<VL_WORDS_I(obits); i++) {
|
||||||
|
if (i<(VL_WORDS_I(obits)-1)) {
|
||||||
|
outwp[i] = VL_RAND32();
|
||||||
|
} else {
|
||||||
|
outwp[i] = VL_RAND32() & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outwp;
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_RAND_RESET_I(int obits) {
|
||||||
if (Verilated::randReset()==0) return 0;
|
if (Verilated::randReset()==0) return 0;
|
||||||
IData data = ~0;
|
IData data = ~0;
|
||||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||||
data = VL_RAND32();
|
data = VL_RANDOM_I(obits);
|
||||||
}
|
}
|
||||||
if (outBits<32) data &= VL_MASK_I(outBits);
|
if (obits<32) data &= VL_MASK_I(obits);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
QData VL_RAND_RESET_Q(int outBits) {
|
QData VL_RAND_RESET_Q(int obits) {
|
||||||
if (Verilated::randReset()==0) return 0;
|
if (Verilated::randReset()==0) return 0;
|
||||||
QData data = VL_ULL(~0);
|
QData data = VL_ULL(~0);
|
||||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||||
data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
data = VL_RANDOM_Q(obits);
|
||||||
}
|
}
|
||||||
if (outBits<64) data &= VL_MASK_Q(outBits);
|
if (obits<64) data &= VL_MASK_Q(obits);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,94 +139,368 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Formatting
|
// Formatting
|
||||||
|
|
||||||
const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld) {
|
// Do a va_arg returning a quad, assuming input argument is anything less than wide
|
||||||
// Convert value into %b/%o/%x/%s/%u/%d formatted string
|
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
|
||||||
// Note uses a single buffer; presumes only one call per printf
|
|
||||||
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
|
void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||||
char* strp = &str[0];
|
// Format a Verilog $write style format into the output list
|
||||||
int lsb=obits-1;
|
// The format must be pre-processed (and lower cased) by Verilator
|
||||||
if (drop0) while (lsb && !VL_BITISSET_Q(ld,lsb)) lsb--;
|
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||||
switch (fmt) {
|
//
|
||||||
case 'd':
|
// Note uses a single buffer internally; presumes only one usage per printf
|
||||||
sprintf(str,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(obits,obits,ld)));
|
// Note also assumes variables < 64 are not wide, this assumption is
|
||||||
return str;
|
// sometimes not true in low-level routines written here in verilated.cpp
|
||||||
case 'u':
|
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
sprintf(str,"%llu",ld);
|
bool inPct = false;
|
||||||
return str;
|
bool widthSet = false;
|
||||||
case 's':
|
int width = 0;
|
||||||
for (; lsb>=0; lsb--) {
|
const char* pos = formatp;
|
||||||
lsb = (lsb / 8) * 8; // Next digit
|
for (; *pos; ++pos) {
|
||||||
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xff;
|
if (!inPct && pos[0]=='%') {
|
||||||
*strp++ = (charval==0)?' ':charval;
|
inPct = true;
|
||||||
|
widthSet = false;
|
||||||
|
width = 0;
|
||||||
|
} else if (!inPct) { // Normal text
|
||||||
|
// Fast-forward to next escape and add to output
|
||||||
|
const char *ep = pos;
|
||||||
|
while (ep[0] && ep[0]!='%') ep++;
|
||||||
|
if (ep != pos) {
|
||||||
|
output += string(pos, ep-pos);
|
||||||
|
pos += ep-pos-1;
|
||||||
|
}
|
||||||
|
} else { // Format character
|
||||||
|
inPct = false;
|
||||||
|
char fmt = pos[0];
|
||||||
|
switch (fmt) {
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
inPct = true; // Get more digits
|
||||||
|
widthSet = true;
|
||||||
|
width = width*10 + (fmt - '0');
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
output += '%';
|
||||||
|
break;
|
||||||
|
case 'S': { // "C" string
|
||||||
|
const char* cstrp = va_arg(ap, const char*);
|
||||||
|
output += cstrp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Deal with all read-and-print somethings
|
||||||
|
const int lbits = va_arg(ap, int);
|
||||||
|
QData ld = 0;
|
||||||
|
WDataInP lwp;
|
||||||
|
if (lbits <= VL_QUADSIZE) {
|
||||||
|
WData qlwp[2];
|
||||||
|
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||||
|
VL_SET_WQ(qlwp,ld);
|
||||||
|
lwp = qlwp;
|
||||||
|
} else {
|
||||||
|
lwp = va_arg(ap,WDataInP);
|
||||||
|
ld = lwp[0];
|
||||||
|
if (fmt == 'u' || fmt == 'd') fmt = 'x'; // Not supported, but show something
|
||||||
|
}
|
||||||
|
int lsb=lbits-1;
|
||||||
|
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
||||||
|
switch (fmt) {
|
||||||
|
case 'c': {
|
||||||
|
IData charval = ld & 0xff;
|
||||||
|
output += charval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
lsb = (lsb / 8) * 8; // Next digit
|
||||||
|
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||||
|
output += (charval==0)?' ':charval;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd': { // Signed decimal
|
||||||
|
int digits=sprintf(tmp,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||||
|
int needmore = width-digits;
|
||||||
|
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': { // Unsigned decimal
|
||||||
|
int digits=sprintf(tmp,"%llu",ld);
|
||||||
|
int needmore = width-digits;
|
||||||
|
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't': { // Time
|
||||||
|
int digits;
|
||||||
|
if (VL_TIME_MULTIPLIER==1) {
|
||||||
|
digits=sprintf(tmp,"%llu",ld);
|
||||||
|
} else if (VL_TIME_MULTIPLIER==1000) {
|
||||||
|
digits=sprintf(tmp,"%llu.%03llu",
|
||||||
|
(QData)(ld/VL_TIME_MULTIPLIER),
|
||||||
|
(QData)(ld%VL_TIME_MULTIPLIER));
|
||||||
|
} else {
|
||||||
|
vl_fatal(__FILE__,__LINE__,"","%%Error: Unsupported VL_TIME_MULTIPLIER");
|
||||||
|
}
|
||||||
|
int needmore = width-digits;
|
||||||
|
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
lsb = (lsb / 3) * 3; // Next digit
|
||||||
|
// Octal numbers may span more than one wide word,
|
||||||
|
// so we need to grab each bit separately and check for overrun
|
||||||
|
// Octal is rare, so we'll do it a slow simple way
|
||||||
|
output += ('0'
|
||||||
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0)
|
||||||
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+1)) ? 2 : 0)
|
||||||
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
lsb = (lsb / 4) * 4; // Next digit
|
||||||
|
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
||||||
|
output += "0123456789abcdef"[charval];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
string msg = string("%%Error: Unknown _vl_vsformat code: ")+pos[0]+"\n";
|
||||||
|
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
}
|
}
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
case 'b':
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 1) + '0';
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
case 'o':
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 3) * 3; // Next digit
|
|
||||||
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 7) + '0';
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
default:
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 4) * 4; // Next digit
|
|
||||||
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xf;
|
|
||||||
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp) {
|
static inline bool _vl_vsss_eof(FILE* fp, int& floc) {
|
||||||
// Convert value into %b/%o/%x/%s/%u/%d formatted string
|
return fp ? feof(fp) : (floc<0);
|
||||||
// Note uses a single buffer; presumes only one call per printf
|
}
|
||||||
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
|
static inline void _vl_vsss_advance(FILE* fp, int& floc) {
|
||||||
char* strp = &str[0];
|
if (fp) fgetc(fp);
|
||||||
int lsb=obits-1;
|
else floc -= 8;
|
||||||
if (drop0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
}
|
||||||
switch (fmt) {
|
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
|
||||||
case 's':
|
// Get a character without advancing
|
||||||
for (; lsb>=0; lsb--) {
|
if (fp) {
|
||||||
lsb = (lsb / 8) * 8; // Next digit
|
int data = fgetc(fp);
|
||||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
if (data == EOF) return EOF;
|
||||||
*strp++ = (charval==0)?' ':charval;
|
ungetc(data,fp);
|
||||||
}
|
return data;
|
||||||
*strp++ = '\0';
|
} else {
|
||||||
return str;
|
if (floc < 0) return EOF;
|
||||||
case 'b':
|
floc = floc & ~7; // Align to closest character
|
||||||
for (; lsb>=0; lsb--) {
|
int data = (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
|
||||||
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
return data;
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
case 'o':
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 3) * 3; // Next digit
|
|
||||||
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 7) + '0';
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
default:
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 4) * 4; // Next digit
|
|
||||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
|
||||||
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
*strp++ = '\0';
|
}
|
||||||
return str;
|
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp) {
|
||||||
|
while (1) {
|
||||||
|
int c = _vl_vsss_peek(fp, floc, fromp);
|
||||||
|
if (c==EOF || !isspace(c)) return;
|
||||||
|
_vl_vsss_advance(fp, floc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp,
|
||||||
|
char* tmpp, const char* acceptp) {
|
||||||
|
// Read into tmp, consisting of characters from acceptp list
|
||||||
|
char* cp = tmpp;
|
||||||
|
while (1) {
|
||||||
|
int c = _vl_vsss_peek(fp, floc, fromp);
|
||||||
|
if (c==EOF || isspace(c)) break;
|
||||||
|
if (acceptp!=NULL // String - allow anything
|
||||||
|
&& NULL==strchr(acceptp, c)) break;
|
||||||
|
if (acceptp!=NULL) c = tolower(c); // Non-strings we'll simplify
|
||||||
|
*cp++ = c;
|
||||||
|
_vl_vsss_advance(fp, floc);
|
||||||
|
}
|
||||||
|
*cp++ = '\0';
|
||||||
|
//VL_PRINTF("\t_read got='%s'\n", tmpp);
|
||||||
|
}
|
||||||
|
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits, IData ld) {
|
||||||
|
for (; nbits && lsb<obits; nbits--, lsb++, ld>>=1) {
|
||||||
|
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
|
int fbits, WDataInP fromp, // Else if a sscanf
|
||||||
|
const char* formatp, va_list ap) {
|
||||||
|
// Read a Verilog $sscanf/$fscanf style format into the output list
|
||||||
|
// The format must be pre-processed (and lower cased) by Verilator
|
||||||
|
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||||
|
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
|
int floc = fbits - 1;
|
||||||
|
IData got = 0;
|
||||||
|
bool inPct = false;
|
||||||
|
const char* pos = formatp;
|
||||||
|
for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) {
|
||||||
|
//VL_PRINTF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc, _vl_vsss_peek(fp,floc,fromp));
|
||||||
|
if (!inPct && pos[0]=='%') {
|
||||||
|
inPct = true;
|
||||||
|
} else if (!inPct && isspace(pos[0])) { // Format spaces
|
||||||
|
while (isspace(pos[1])) pos++;
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
} else if (!inPct) { // Expected Format
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||||
|
if (c != pos[0]) goto done;
|
||||||
|
else _vl_vsss_advance(fp,floc);
|
||||||
|
} else { // Format character
|
||||||
|
// Skip loading spaces
|
||||||
|
inPct = false;
|
||||||
|
char fmt = pos[0];
|
||||||
|
switch (fmt) {
|
||||||
|
case '%': {
|
||||||
|
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||||
|
if (c != '%') goto done;
|
||||||
|
else _vl_vsss_advance(fp,floc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Deal with all read-and-scan somethings
|
||||||
|
// Note LSBs are preserved if there's an overflow
|
||||||
|
const int obits = va_arg(ap, int);
|
||||||
|
int lsb = 0;
|
||||||
|
WData qowp[2];
|
||||||
|
WDataOutP owp = qowp;
|
||||||
|
if (obits > VL_QUADSIZE) {
|
||||||
|
owp = va_arg(ap,WDataOutP);
|
||||||
|
}
|
||||||
|
for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||||
|
switch (fmt) {
|
||||||
|
case 'c': {
|
||||||
|
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||||
|
if (c==EOF) goto done;
|
||||||
|
else _vl_vsss_advance(fp,floc);
|
||||||
|
owp[0] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': { // Signed decimal
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
vlsint64_t ld;
|
||||||
|
sscanf(tmp,"%lld",&ld);
|
||||||
|
VL_SET_WQ(owp,ld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't': // FALLTHRU // Time
|
||||||
|
case 'u': { // Unsigned decimal
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
QData ld;
|
||||||
|
sscanf(tmp,"%llu",&ld);
|
||||||
|
VL_SET_WQ(owp,ld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "01xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
switch(tmp[pos]) {
|
||||||
|
case 'x': case 'z': case '?': //FALLTHRU
|
||||||
|
case '0': lsb++; break;
|
||||||
|
case '1': _vl_vsss_setbit(owp,obits,lsb, 1, 1); lsb++; break;
|
||||||
|
case '_': break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'o': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
switch(tmp[pos]) {
|
||||||
|
case 'x': case 'z': case '?': //FALLTHRU
|
||||||
|
case '0': lsb+=3; break;
|
||||||
|
case '1': _vl_vsss_setbit(owp,obits,lsb, 3, 1); lsb+=3; break;
|
||||||
|
case '2': _vl_vsss_setbit(owp,obits,lsb, 3, 2); lsb+=3; break;
|
||||||
|
case '3': _vl_vsss_setbit(owp,obits,lsb, 3, 3); lsb+=3; break;
|
||||||
|
case '4': _vl_vsss_setbit(owp,obits,lsb, 3, 4); lsb+=3; break;
|
||||||
|
case '5': _vl_vsss_setbit(owp,obits,lsb, 3, 5); lsb+=3; break;
|
||||||
|
case '6': _vl_vsss_setbit(owp,obits,lsb, 3, 6); lsb+=3; break;
|
||||||
|
case '7': _vl_vsss_setbit(owp,obits,lsb, 3, 7); lsb+=3; break;
|
||||||
|
case '_': break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefxz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
switch(tmp[pos]) {
|
||||||
|
case 'x': case 'z': case '?': //FALLTHRU
|
||||||
|
case '0': lsb+=4; break;
|
||||||
|
case '1': _vl_vsss_setbit(owp,obits,lsb, 4, 1); lsb+=4; break;
|
||||||
|
case '2': _vl_vsss_setbit(owp,obits,lsb, 4, 2); lsb+=4; break;
|
||||||
|
case '3': _vl_vsss_setbit(owp,obits,lsb, 4, 3); lsb+=4; break;
|
||||||
|
case '4': _vl_vsss_setbit(owp,obits,lsb, 4, 4); lsb+=4; break;
|
||||||
|
case '5': _vl_vsss_setbit(owp,obits,lsb, 4, 5); lsb+=4; break;
|
||||||
|
case '6': _vl_vsss_setbit(owp,obits,lsb, 4, 6); lsb+=4; break;
|
||||||
|
case '7': _vl_vsss_setbit(owp,obits,lsb, 4, 7); lsb+=4; break;
|
||||||
|
case '8': _vl_vsss_setbit(owp,obits,lsb, 4, 8); lsb+=4; break;
|
||||||
|
case '9': _vl_vsss_setbit(owp,obits,lsb, 4, 9); lsb+=4; break;
|
||||||
|
case 'a': _vl_vsss_setbit(owp,obits,lsb, 4, 10); lsb+=4; break;
|
||||||
|
case 'b': _vl_vsss_setbit(owp,obits,lsb, 4, 11); lsb+=4; break;
|
||||||
|
case 'c': _vl_vsss_setbit(owp,obits,lsb, 4, 12); lsb+=4; break;
|
||||||
|
case 'd': _vl_vsss_setbit(owp,obits,lsb, 4, 13); lsb+=4; break;
|
||||||
|
case 'e': _vl_vsss_setbit(owp,obits,lsb, 4, 14); lsb+=4; break;
|
||||||
|
case 'f': _vl_vsss_setbit(owp,obits,lsb, 4, 15); lsb+=4; break;
|
||||||
|
case '_': break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
string msg = string("%%Error: Unknown _vl_vsscanf code: ")+pos[0]+"\n";
|
||||||
|
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
got++;
|
||||||
|
// Reload data if non-wide (if wide, we put it in the right place directly)
|
||||||
|
if (obits <= VL_BYTESIZE) {
|
||||||
|
CData* p = va_arg(ap,CData*); *p = owp[0];
|
||||||
|
} else if (obits <= VL_SHORTSIZE) {
|
||||||
|
SData* p = va_arg(ap,SData*); *p = owp[0];
|
||||||
|
} else if (obits <= VL_WORDSIZE) {
|
||||||
|
IData* p = va_arg(ap,IData*); *p = owp[0];
|
||||||
|
} else if (obits <= VL_QUADSIZE) {
|
||||||
|
QData* p = va_arg(ap,QData*); *p = VL_SET_QW(owp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@@ -228,6 +522,44 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
|||||||
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||||
|
// Convert C string to Verilog format
|
||||||
|
int bytes = VL_BYTES_I(obits);
|
||||||
|
char* op = ((char*)(destp));
|
||||||
|
if (srclen > bytes) srclen = bytes; // Don't overflow destination
|
||||||
|
int i;
|
||||||
|
for (i=0; i<srclen; i++) { *op++ = srcp[srclen-1-i]; }
|
||||||
|
for (; i<bytes; i++) { *op++ = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||||
|
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||||
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
|
||||||
|
// The string needs to be padded with 0's in unused spaces in front of
|
||||||
|
// any read data. This means we can't know in what location the first
|
||||||
|
// character will finally live, so we need to copy. Yuk.
|
||||||
|
IData bytes = VL_BYTES_I(obits);
|
||||||
|
char buffer[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||||
|
// V3Emit has static check that bytes < VL_TO_STRING_MAX_WORDS, but be safe
|
||||||
|
if (VL_UNLIKELY(bytes > VL_TO_STRING_MAX_WORDS*VL_WORDSIZE)) {
|
||||||
|
vl_fatal(__FILE__,__LINE__,"","Internal: fgets buffer overrun");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't use fgets, as we must read \0s.
|
||||||
|
IData got = 0;
|
||||||
|
char* cp = buffer;
|
||||||
|
while (got < bytes) {
|
||||||
|
int c = getc(fp);
|
||||||
|
if (c==EOF) break;
|
||||||
|
*cp++ = c; got++;
|
||||||
|
if (c=='\n') break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_VL_STRING_TO_VINT(obits, destp, got, buffer);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||||
return VL_FOPEN_WI(2, fnw, mode);
|
return VL_FOPEN_WI(2, fnw, mode);
|
||||||
@@ -240,6 +572,67 @@ QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
|||||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VL_WRITEF(const char* formatp, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
string output;
|
||||||
|
_vl_vsformat(output, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
// Users can redefine VL_PRINTF if they wish.
|
||||||
|
VL_PRINTF("%s", output.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||||
|
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||||
|
if (VL_UNLIKELY(!fp)) return;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
string output;
|
||||||
|
_vl_vsformat(output, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
fputs(output.c_str(), fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||||
|
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||||
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(fp, 0, NULL, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
|
||||||
|
IData fnw[2]; VL_SET_WI(fnw, ld);
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
|
||||||
|
IData fnw[2]; VL_SET_WQ(fnw, ld);
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(NULL, lbits, lwp, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||||
QData ofilename, void* memp, IData start, IData end) {
|
QData ofilename, void* memp, IData start, IData end) {
|
||||||
IData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
IData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||||
@@ -276,7 +669,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||||||
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
||||||
// Skip // comments and detect /* comments
|
// Skip // comments and detect /* comments
|
||||||
else if (ignore_to_cmt && lastc=='*' && c=='/') {
|
else if (ignore_to_cmt && lastc=='*' && c=='/') {
|
||||||
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
|
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
|
||||||
} else if (!ignore_to_eol && !ignore_to_cmt) {
|
} else if (!ignore_to_eol && !ignore_to_cmt) {
|
||||||
if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
|
if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
|
||||||
else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
|
else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
|
||||||
@@ -355,7 +748,7 @@ const char* Verilated::catName(const char* n1, const char* n2) {
|
|||||||
// Used by symbol table creation to make module names
|
// Used by symbol table creation to make module names
|
||||||
static char* strp = NULL;
|
static char* strp = NULL;
|
||||||
static int len = -1;
|
static int len = -1;
|
||||||
int newlen = strlen(n1)+strlen(n2)+2;
|
int newlen = strlen(n1)+strlen(n2)+2;
|
||||||
if (newlen > len) {
|
if (newlen > len) {
|
||||||
if (strp) delete [] strp;
|
if (strp) delete [] strp;
|
||||||
strp = new char[newlen];
|
strp = new char[newlen];
|
||||||
|
|||||||
+161
-90
@@ -1,15 +1,16 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
///
|
///
|
||||||
/// \file
|
/// \file
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
/// all C++ files it generates. It contains standard macros and
|
/// all C++ files it generates. It contains standard macros and
|
||||||
/// classes required by the Verilated code.
|
/// classes required by the Verilated code.
|
||||||
///
|
///
|
||||||
/// Code available from: http://www.veripool.com/verilator
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
///
|
///
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
@@ -29,11 +30,11 @@
|
|||||||
|
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -129,7 +130,7 @@ struct Verilated {
|
|||||||
// Extern Vars
|
// Extern Vars
|
||||||
// Below two are used as bool, but having as uint32_t avoids conversion time
|
// Below two are used as bool, but having as uint32_t avoids conversion time
|
||||||
private:
|
private:
|
||||||
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||||
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||||
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||||
static bool s_gotFinish; ///< A $finish statement executed
|
static bool s_gotFinish; ///< A $finish statement executed
|
||||||
@@ -152,7 +153,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
/// Internal: Create a new module name by concatenating two strings
|
/// Internal: Create a new module name by concatenating two strings
|
||||||
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
||||||
/// Enable calculation of unused signals
|
/// Enable calculation of unused signals
|
||||||
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
||||||
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||||
/// Did the simulation $finish?
|
/// Did the simulation $finish?
|
||||||
@@ -165,7 +166,7 @@ public:
|
|||||||
/// Enable/disable assertions
|
/// Enable/disable assertions
|
||||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
static void assertOn(bool flag) { s_assertOn=flag; }
|
||||||
static bool assertOn() { return s_assertOn; }
|
static bool assertOn() { return s_assertOn; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Extern functions -- User may override -- See verilated.cpp
|
// Extern functions -- User may override -- See verilated.cpp
|
||||||
@@ -179,21 +180,21 @@ extern void vl_fatal (const char* filename, int linenum, const char* hier,
|
|||||||
const char* msg);
|
const char* msg);
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Extern functions -- Init time only, so slow is fine
|
// Extern functions -- Slow path
|
||||||
|
|
||||||
|
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||||
|
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||||
|
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||||
|
|
||||||
|
/// Init time only, so slow is fine
|
||||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||||
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
||||||
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
||||||
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
|
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
|
||||||
|
|
||||||
/// Return string with formated Verilog value
|
|
||||||
extern const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp);
|
|
||||||
extern const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld);
|
|
||||||
inline const char* VL_VALUE_FORMATTED_I(int obits, char fmt, bool drop0, IData ld) {
|
|
||||||
return VL_VALUE_FORMATTED_Q(obits,fmt,drop0,ld);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// File I/O
|
/// File I/O
|
||||||
|
extern IData VL_FGETS_IXQ(int sbits, void* strgp, QData fpq);
|
||||||
|
|
||||||
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||||
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||||
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||||
@@ -206,6 +207,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
|||||||
IData ofilename, void* memp, IData start, IData end) {
|
IData ofilename, void* memp, IData start, IData end) {
|
||||||
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||||
|
|
||||||
|
extern void VL_WRITEF(const char* formatp, ...);
|
||||||
|
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
|
||||||
|
|
||||||
|
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
||||||
|
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
||||||
|
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||||
|
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Base macros
|
// Base macros
|
||||||
|
|
||||||
@@ -213,9 +222,12 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
|||||||
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
|
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
|
||||||
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
|
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
|
|
||||||
/// Create two 32-bit words from quadword
|
/// Create two 32-bit words from quadword
|
||||||
#define VL_SET_WQ(decl,data) { decl[0]=(data); decl[1]=((data)>>VL_WORDSIZE); }
|
#define VL_SET_WQ(owp,data) { owp[0]=(data); owp[1]=((data)>>VL_WORDSIZE); }
|
||||||
|
#define VL_SET_WI(owp,data) { owp[0]=(data); owp[1]=0; }
|
||||||
|
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||||
|
|
||||||
// Use a union to avoid cast-to-different-size warnings
|
// Use a union to avoid cast-to-different-size warnings
|
||||||
/// Return FILE* from QData
|
/// Return FILE* from QData
|
||||||
@@ -236,7 +248,7 @@ static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) { return (-((lhs)&(VL
|
|||||||
|
|
||||||
// Debugging prints
|
// Debugging prints
|
||||||
static inline void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
|
static inline void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
|
||||||
printf(" Data: w%d: ", lbits);
|
printf(" Data: w%d: ", lbits);
|
||||||
for (int i=VL_WORDS_I(lbits)-1; i>=0; i--) { printf("%08x ",iwp[i]); }
|
for (int i=VL_WORDS_I(lbits)-1; i>=0; i--) { printf("%08x ",iwp[i]); }
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@@ -244,13 +256,17 @@ static inline void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
|
|||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Pli macros
|
// Pli macros
|
||||||
|
|
||||||
|
#ifndef VL_TIME_MULTIPLIER
|
||||||
|
# define VL_TIME_MULTIPLIER 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Return current simulation time
|
/// Return current simulation time
|
||||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||||
# define VL_TIME_I(ign) ((IData)sc_time_stamp().to_default_time_units())
|
# define VL_TIME_I(ign) ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
# define VL_TIME_Q(ign) ((QData)sc_time_stamp().to_default_time_units())
|
# define VL_TIME_Q(ign) ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
#else
|
#else
|
||||||
# define VL_TIME_I(ign) ((IData)sc_time_stamp())
|
# define VL_TIME_I(ign) ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
# define VL_TIME_Q(ign) ((QData)sc_time_stamp())
|
# define VL_TIME_Q(ign) ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
extern double sc_time_stamp();
|
extern double sc_time_stamp();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -321,8 +337,8 @@ static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) {
|
|||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) {
|
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) {
|
||||||
IData orig = owp[VL_BITWORD_I(bit)];
|
IData orig = owp[VL_BITWORD_I(bit)];
|
||||||
owp[VL_BITWORD_I(bit)] = (orig & ~(VL_UL(1)<<VL_BITBIT_I(bit))
|
owp[VL_BITWORD_I(bit)] = ((orig & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
| (rhs<<VL_BITBIT_I(bit)));
|
| (rhs<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
// Alternative form that is an instruction faster when rhs is constant one.
|
// Alternative form that is an instruction faster when rhs is constant one.
|
||||||
static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) {
|
static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) {
|
||||||
@@ -344,35 +360,45 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
|||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// SYSTEMC OPERATORS
|
// SYSTEMC OPERATORS
|
||||||
// Copying verilog format to/from systemc integers and bit vectors.
|
// Copying verilog format to systemc integers and bit vectors.
|
||||||
|
|
||||||
#define VL_ASSIGN_IS(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read()); }
|
|
||||||
#define VL_ASSIGN_SI(obits,svar,vvar) { (svar).write(vvar); }
|
|
||||||
|
|
||||||
|
#define VL_ASSIGN_ISI(obits,vvar,svar) { (vvar) = VL_CLEAN_II((obits),(obits),(svar).read()); }
|
||||||
#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read()); }
|
#define VL_ASSIGN_QSQ(obits,vvar,svar) { (vvar) = VL_CLEAN_QQ((obits),(obits),(svar).read()); }
|
||||||
|
|
||||||
|
#define VL_ASSIGN_ISW(obits,od,svar) { \
|
||||||
|
od = (svar.read().get_word(0)) & VL_MASK_I(obits); \
|
||||||
|
}
|
||||||
|
#define VL_ASSIGN_QSW(obits,od,svar) { \
|
||||||
|
od = (((QData)svar.read().get_word(1))<<VL_WORDSIZE | svar.read().get_word(0)) \
|
||||||
|
& VL_MASK_Q(obits); \
|
||||||
|
}
|
||||||
|
#define VL_ASSIGN_WSW(obits,owp,svar) { \
|
||||||
|
int words = VL_WORDS_I(obits); \
|
||||||
|
for (int i=0; i < words; i++) owp[i] = svar.read().get_word(i); \
|
||||||
|
owp[words-1] &= VL_MASK_I(obits); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copying verilog format from systemc integers and bit vectors.
|
||||||
|
|
||||||
|
#define VL_ASSIGN_SII(obits,svar,vvar) { (svar).write(vvar); }
|
||||||
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
|
#define VL_ASSIGN_SQQ(obits,svar,vvar) { (svar).write(vvar); }
|
||||||
|
|
||||||
#define VL_ASSIGN_SQ(obits,svar,rd) { \
|
#define VL_ASSIGN_SWI(obits,svar,rd) { \
|
||||||
|
sc_bv<obits> _bvtemp; \
|
||||||
|
_bvtemp.set_word(0,rd); \
|
||||||
|
svar.write(_bvtemp); \
|
||||||
|
}
|
||||||
|
#define VL_ASSIGN_SWQ(obits,svar,rd) { \
|
||||||
sc_bv<obits> _bvtemp; \
|
sc_bv<obits> _bvtemp; \
|
||||||
_bvtemp.set_word(0,rd); \
|
_bvtemp.set_word(0,rd); \
|
||||||
_bvtemp.set_word(1,rd>>VL_WORDSIZE); \
|
_bvtemp.set_word(1,rd>>VL_WORDSIZE); \
|
||||||
svar.write(_bvtemp); \
|
svar.write(_bvtemp); \
|
||||||
}
|
}
|
||||||
#define VL_ASSIGN_QS(obits,od,svar) { \
|
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
|
||||||
od = (((QData)svar.read().get_word(1))<<VL_WORDSIZE | svar.read().get_word(0)) \
|
|
||||||
& VL_MASK_Q(obits); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VL_ASSIGN_SW(obits,svar,rwp) { \
|
|
||||||
sc_bv<obits> _bvtemp; \
|
sc_bv<obits> _bvtemp; \
|
||||||
for (int i=0; i < VL_WORDS_I(obits); i++) _bvtemp.set_word(i,rwp[i]); \
|
for (int i=0; i < VL_WORDS_I(obits); i++) _bvtemp.set_word(i,rwp[i]); \
|
||||||
svar.write(_bvtemp); \
|
svar.write(_bvtemp); \
|
||||||
}
|
}
|
||||||
#define VL_ASSIGN_WS(obits,owp,svar) { \
|
|
||||||
int words = VL_WORDS_I(obits); \
|
|
||||||
for (int i=0; i < words; i++) owp[i] = svar.read().get_word(i); \
|
|
||||||
owp[words-1] &= VL_MASK_I(obits); \
|
|
||||||
}
|
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Extending sizes
|
// Extending sizes
|
||||||
@@ -416,7 +442,7 @@ static inline QData VL_EXTENDS_QQ(int, int lbits, QData lhs) {
|
|||||||
|
|
||||||
static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) {
|
static inline WDataOutP VL_EXTENDS_WI(int obits, int lbits, WDataOutP owp, IData ld) {
|
||||||
IData sign = VL_SIGNONES_I(lbits,ld);
|
IData sign = VL_SIGNONES_I(lbits,ld);
|
||||||
owp[0] = ld | sign & ~VL_MASK_I(lbits);
|
owp[0] = ld | (sign & ~VL_MASK_I(lbits));
|
||||||
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
||||||
return(owp);
|
return(owp);
|
||||||
}
|
}
|
||||||
@@ -431,7 +457,7 @@ static inline WDataOutP VL_EXTENDS_WW(int obits, int lbits, WDataOutP owp, WData
|
|||||||
for (int i=0; i < VL_WORDS_I(lbits)-1; i++) owp[i] = lwp[i];
|
for (int i=0; i < VL_WORDS_I(lbits)-1; i++) owp[i] = lwp[i];
|
||||||
int lmsw=VL_WORDS_I(lbits)-1;
|
int lmsw=VL_WORDS_I(lbits)-1;
|
||||||
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
||||||
owp[lmsw] = lwp[lmsw] | sign & ~VL_MASK_I(lbits);
|
owp[lmsw] = lwp[lmsw] | (sign & ~VL_MASK_I(lbits));
|
||||||
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
for (int i=VL_WORDS_I(lbits); i < VL_WORDS_I(obits); i++) owp[i] = sign;
|
||||||
return(owp);
|
return(owp);
|
||||||
}
|
}
|
||||||
@@ -460,43 +486,60 @@ static inline IData VL_REDOR_W(int words, WDataInP lwp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_REDXOR: oclean=dirty; obits=1;
|
// EMIT_RULE: VL_REDXOR: oclean=dirty; obits=1;
|
||||||
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
|
|
||||||
IData r = lwp[0];
|
|
||||||
for (int i=1; i < words; i++) r ^= lwp[i];
|
|
||||||
r=(r^(r>>1));
|
|
||||||
r=(r^(r>>2));
|
|
||||||
r=(r^(r>>4));
|
|
||||||
r=(r^(r>>8));
|
|
||||||
r=(r^(r>>16));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
static inline IData VL_REDXOR_2(IData r) {
|
static inline IData VL_REDXOR_2(IData r) {
|
||||||
|
// Experiments show VL_REDXOR_2 is faster than __builtin_parityl
|
||||||
r=(r^(r>>1));
|
r=(r^(r>>1));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_4(IData r) {
|
static inline IData VL_REDXOR_4(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2));
|
r=(r^(r>>1)); r=(r^(r>>2));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_8(IData r) {
|
static inline IData VL_REDXOR_8(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_16(IData r) {
|
static inline IData VL_REDXOR_16(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_32(IData r) {
|
static inline IData VL_REDXOR_32(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_64(QData r) {
|
static inline IData VL_REDXOR_64(QData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityll(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16)); r=(r^(r>>32));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16)); r=(r^(r>>32));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
|
||||||
|
IData r = lwp[0];
|
||||||
|
for (int i=1; i < words; i++) r ^= lwp[i];
|
||||||
|
return VL_REDXOR_32(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_COUNTONES_II: oclean = false; lhs clean
|
// EMIT_RULE: VL_COUNTONES_II: oclean = false; lhs clean
|
||||||
static inline IData VL_COUNTONES_I(IData lhs) {
|
static inline IData VL_COUNTONES_I(IData lhs) {
|
||||||
|
// This is faster than __builtin_popcountl
|
||||||
IData r = lhs - ((lhs >> 1) & 033333333333) - ((lhs >> 2) & 011111111111);
|
IData r = lhs - ((lhs >> 1) & 033333333333) - ((lhs >> 2) & 011111111111);
|
||||||
r = (r + (r>>3)) & 030707070707;
|
r = (r + (r>>3)) & 030707070707;
|
||||||
r = (r + (r>>6));
|
r = (r + (r>>6));
|
||||||
@@ -548,6 +591,36 @@ static inline IData VL_ONEHOT0_W(int words, WDataInP lwp) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline IData VL_CLOG2_I(IData lhs) {
|
||||||
|
// There are faster algorithms, or fls GCC4 builtins, but rarely used
|
||||||
|
if (!lhs) return 0;
|
||||||
|
lhs--;
|
||||||
|
int shifts=0;
|
||||||
|
for (; lhs!=0; shifts++) lhs = lhs >> 1;
|
||||||
|
return shifts;
|
||||||
|
}
|
||||||
|
static inline IData VL_CLOG2_Q(QData lhs) {
|
||||||
|
if (!lhs) return 0;
|
||||||
|
lhs--;
|
||||||
|
int shifts=0;
|
||||||
|
for (; lhs!=0; shifts++) lhs = lhs >> VL_ULL(1);
|
||||||
|
return shifts;
|
||||||
|
}
|
||||||
|
static inline IData VL_CLOG2_W(int words, WDataInP lwp) {
|
||||||
|
IData adjust = (VL_COUNTONES_W(words,lwp)==1) ? 0 : 1;
|
||||||
|
for (int i=words-1; i>=0; i--) {
|
||||||
|
if (lwp[i]) {
|
||||||
|
for (int bit=31; bit>=0; bit--) {
|
||||||
|
if (VL_UNLIKELY(VL_BITISSET_I(lwp[i],bit))) {
|
||||||
|
return i*VL_WORDSIZE + bit + adjust;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Can't get here - one bit must be set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// SIMPLE LOGICAL OPERATORS
|
// SIMPLE LOGICAL OPERATORS
|
||||||
|
|
||||||
@@ -829,7 +902,7 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
|
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
|
||||||
|
|
||||||
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
||||||
if (lhs==0) return 0;
|
if (lhs==0) return 0;
|
||||||
@@ -847,23 +920,23 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
|||||||
|
|
||||||
// INTERNAL: Stuff LHS bit 0++ into OUTPUT at specified offset
|
// INTERNAL: Stuff LHS bit 0++ into OUTPUT at specified offset
|
||||||
// ld may be "dirty", output is clean
|
// ld may be "dirty", output is clean
|
||||||
static inline void _VL_INSERT_II(int, CData& lhsr, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_II(int, CData& lhsr, IData ld, int hbit, int lbit) {
|
||||||
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_II(int, SData& lhsr, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_II(int, SData& lhsr, IData ld, int hbit, int lbit) {
|
||||||
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_II(int, IData& lhsr, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_II(int, IData& lhsr, IData ld, int hbit, int lbit) {
|
||||||
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_QQ(int, QData& lhsr, QData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_QQ(int, QData& lhsr, QData ld, int hbit, int lbit) {
|
||||||
QData insmask = (VL_MASK_Q(hbit-lbit+1))<<lbit;
|
QData insmask = (VL_MASK_Q(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbit) {
|
||||||
int hoffset = VL_BITBIT_I(hbit);
|
int hoffset = VL_BITBIT_I(hbit);
|
||||||
int loffset = VL_BITBIT_I(lbit);
|
int loffset = VL_BITBIT_I(lbit);
|
||||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||||
@@ -888,7 +961,7 @@ static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbi
|
|||||||
|
|
||||||
// INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
|
// INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
|
||||||
// lwp may be "dirty"
|
// lwp may be "dirty"
|
||||||
static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int lbit) {
|
static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int lbit) {
|
||||||
int hoffset = hbit & VL_SIZEBITS_I;
|
int hoffset = hbit & VL_SIZEBITS_I;
|
||||||
int loffset = lbit & VL_SIZEBITS_I;
|
int loffset = lbit & VL_SIZEBITS_I;
|
||||||
int lword = VL_BITWORD_I(lbit);
|
int lword = VL_BITWORD_I(lbit);
|
||||||
@@ -917,16 +990,16 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
|
|||||||
{ // Lower word
|
{ // Lower word
|
||||||
int oword = lword+i;
|
int oword = lword+i;
|
||||||
IData d = lwp[i]<<loffset;
|
IData d = lwp[i]<<loffset;
|
||||||
IData od = owp[oword] & ~linsmask | d & linsmask;
|
IData od = (owp[oword] & ~linsmask) | (d & linsmask);
|
||||||
if (oword==hword) owp[oword] = owp[oword] & ~hinsmask | od & hinsmask;
|
if (oword==hword) owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask);
|
||||||
else owp[oword] = od;
|
else owp[oword] = od;
|
||||||
}
|
}
|
||||||
{ // Upper word
|
{ // Upper word
|
||||||
int oword = lword+i+1;
|
int oword = lword+i+1;
|
||||||
if (oword <= hword) {
|
if (oword <= hword) {
|
||||||
IData d = lwp[i]>>nbitsonright;
|
IData d = lwp[i]>>nbitsonright;
|
||||||
IData od = d & ~linsmask | owp[oword] & linsmask;
|
IData od = (d & ~linsmask) | (owp[oword] & linsmask);
|
||||||
if (oword==hword) owp[oword] = owp[oword] & ~hinsmask | od & hinsmask;
|
if (oword==hword) owp[oword] = (owp[oword] & ~hinsmask) | (od & hinsmask);
|
||||||
else owp[oword] = od;
|
else owp[oword] = od;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -934,7 +1007,7 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit) {
|
||||||
WData lwp[2]; VL_SET_WQ(lwp,ld);
|
WData lwp[2]; VL_SET_WQ(lwp,ld);
|
||||||
_VL_INSERT_WW(obits,owp,lwp,hbit,lbit);
|
_VL_INSERT_WW(obits,owp,lwp,hbit,lbit);
|
||||||
}
|
}
|
||||||
@@ -1114,12 +1187,12 @@ static inline IData VL_SHIFTRS_III(int obits, int, int, IData lhs, IData rhs) {
|
|||||||
// Note the C standard does not specify the >> operator as a arithmetic shift!
|
// Note the C standard does not specify the >> operator as a arithmetic shift!
|
||||||
IData sign = -(lhs >> (obits-1)); // ffff_ffff if negative
|
IData sign = -(lhs >> (obits-1)); // ffff_ffff if negative
|
||||||
IData signext = ~(VL_MASK_I(obits) >> rhs); // One with bits where we've shifted "past"
|
IData signext = ~(VL_MASK_I(obits) >> rhs); // One with bits where we've shifted "past"
|
||||||
return (lhs >> rhs) | sign & VL_CLEAN_II(obits,obits,signext);
|
return (lhs >> rhs) | (sign & VL_CLEAN_II(obits,obits,signext));
|
||||||
}
|
}
|
||||||
static inline QData VL_SHIFTRS_QQI(int obits, int, int, QData lhs, IData rhs) {
|
static inline QData VL_SHIFTRS_QQI(int obits, int, int, QData lhs, IData rhs) {
|
||||||
QData sign = -(lhs >> (obits-1));
|
QData sign = -(lhs >> (obits-1));
|
||||||
QData signext = ~(VL_MASK_Q(obits) >> rhs);
|
QData signext = ~(VL_MASK_Q(obits) >> rhs);
|
||||||
return (lhs >> rhs) | sign & VL_CLEAN_QQ(obits,obits,signext);
|
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
||||||
}
|
}
|
||||||
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||||
int word_shift = VL_BITWORD_I(rd);
|
int word_shift = VL_BITWORD_I(rd);
|
||||||
@@ -1214,7 +1287,7 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData ls
|
|||||||
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) {
|
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) {
|
||||||
int msb = lsb+width-1;
|
int msb = lsb+width-1;
|
||||||
int word_shift = VL_BITWORD_I(lsb);
|
int word_shift = VL_BITWORD_I(lsb);
|
||||||
if (msb>lbits) { // Outside bounds,
|
if (msb>lbits) { // Outside bounds,
|
||||||
for (int i=0; i<VL_WORDS_I(obits)-1; i++) owp[i] = ~0;
|
for (int i=0; i<VL_WORDS_I(obits)-1; i++) owp[i] = ~0;
|
||||||
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits);
|
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits);
|
||||||
} else if (VL_BITBIT_I(lsb)==0) {
|
} else if (VL_BITBIT_I(lsb)==0) {
|
||||||
@@ -1290,61 +1363,59 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
|
|||||||
|
|
||||||
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
|
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
|
||||||
|
|
||||||
#define I IData
|
|
||||||
#define _END(obits,wordsSet) \
|
#define _END(obits,wordsSet) \
|
||||||
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
|
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
|
||||||
return o
|
return o
|
||||||
|
|
||||||
#define VL_HAVE_CONST_W_1X
|
#define VL_HAVE_CONST_W_1X
|
||||||
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
|
||||||
I d0) {
|
IData d0) {
|
||||||
o[0]=d0;
|
o[0]=d0;
|
||||||
_END(obits,1); }
|
_END(obits,1); }
|
||||||
#define VL_HAVE_CONST_W_2X
|
#define VL_HAVE_CONST_W_2X
|
||||||
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
|
||||||
I d1,I d0) {
|
IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1;
|
o[0]=d0; o[1]=d1;
|
||||||
_END(obits,2); }
|
_END(obits,2); }
|
||||||
#define VL_HAVE_CONST_W_3X
|
#define VL_HAVE_CONST_W_3X
|
||||||
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
|
||||||
I d2,I d1,I d0) {
|
IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2;
|
o[0]=d0; o[1]=d1; o[2]=d2;
|
||||||
_END(obits,3); }
|
_END(obits,3); }
|
||||||
#define VL_HAVE_CONST_W_4X
|
#define VL_HAVE_CONST_W_4X
|
||||||
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
|
||||||
I d3,I d2,I d1,I d0) {
|
IData d3,IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
||||||
_END(obits,4); }
|
_END(obits,4); }
|
||||||
#define VL_HAVE_CONST_W_5X
|
#define VL_HAVE_CONST_W_5X
|
||||||
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
|
||||||
I d4,I d3,I d2,I d1,I d0) {
|
IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
||||||
_END(obits,5); }
|
_END(obits,5); }
|
||||||
#define VL_HAVE_CONST_W_6X
|
#define VL_HAVE_CONST_W_6X
|
||||||
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
|
||||||
I d5,I d4,I d3,I d2,I d1,I d0) {
|
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
||||||
_END(obits,6); }
|
_END(obits,6); }
|
||||||
#define VL_HAVE_CONST_W_7X
|
#define VL_HAVE_CONST_W_7X
|
||||||
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
|
||||||
I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
||||||
_END(obits,7); }
|
_END(obits,7); }
|
||||||
#define VL_HAVE_CONST_W_8X
|
#define VL_HAVE_CONST_W_8X
|
||||||
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||||
_END(obits,8); }
|
_END(obits,8); }
|
||||||
#define VL_HAVE_CONST_W_9X
|
#define VL_HAVE_CONST_W_9X
|
||||||
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||||
I d8,
|
IData d8,
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||||
o[8]=d8;
|
o[8]=d8;
|
||||||
_END(obits,9); }
|
_END(obits,9); }
|
||||||
|
|
||||||
#undef _END
|
#undef _END
|
||||||
#undef I
|
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
|
|
||||||
|
|||||||
+14
-13
@@ -1,10 +1,10 @@
|
|||||||
# $Id$ -*- Makefile -*-
|
# -*- Makefile -*-
|
||||||
######################################################################
|
######################################################################
|
||||||
# DESCRIPTION: Makefile commands for all verilated target files
|
# DESCRIPTION: Makefile commands for all verilated target files
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2009 by Wilson Snyder. Verilator is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
# Lesser General Public License or the Perl Artistic License.
|
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
@@ -28,6 +28,7 @@ VK_CPPFLAGS_ALWAYS += \
|
|||||||
-I$(VERILATOR_ROOT)/include \
|
-I$(VERILATOR_ROOT)/include \
|
||||||
-DVL_PRINTF=printf \
|
-DVL_PRINTF=printf \
|
||||||
-DVM_TRACE=$(VM_TRACE) \
|
-DVM_TRACE=$(VM_TRACE) \
|
||||||
|
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||||
|
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||||
VK_CPPFLAGS_WALL += -Wall \
|
VK_CPPFLAGS_WALL += -Wall \
|
||||||
@@ -44,7 +45,7 @@ CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL)
|
|||||||
VPATH += ..
|
VPATH += ..
|
||||||
VPATH += $(VERILATOR_ROOT)/include
|
VPATH += $(VERILATOR_ROOT)/include
|
||||||
|
|
||||||
#OPT = -ggdb -DPRINTINITSTR -DDETECTCHANGE
|
#OPT = -ggdb -DPRINTINITSTR -DDETECTCHANGE
|
||||||
#OPT = -ggdb -DPRINTINITSTR
|
#OPT = -ggdb -DPRINTINITSTR
|
||||||
CPPFLAGS += $(OPT)
|
CPPFLAGS += $(OPT)
|
||||||
|
|
||||||
@@ -59,11 +60,11 @@ LDFLAGS += $(USER_LDFLAGS)
|
|||||||
# See the benchmarking section of bin/verilator.
|
# See the benchmarking section of bin/verilator.
|
||||||
# Support class optimizations. This includes the tracing and symbol table.
|
# Support class optimizations. This includes the tracing and symbol table.
|
||||||
# SystemC takes minutes to optimize, thus it is off by default.
|
# SystemC takes minutes to optimize, thus it is off by default.
|
||||||
#OPT_SLOW =
|
#OPT_SLOW =
|
||||||
# Fast path optimizations. Most time is spent in these classes.
|
# Fast path optimizations. Most time is spent in these classes.
|
||||||
#OPT_FAST = -O2 -fstrict-aliasing
|
#OPT_FAST = -O2 -fstrict-aliasing
|
||||||
#OPT_FAST = -O
|
#OPT_FAST = -O
|
||||||
#OPT_FAST =
|
#OPT_FAST =
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##### Aggregates
|
##### Aggregates
|
||||||
@@ -88,8 +89,8 @@ endif
|
|||||||
##### SystemPerl builds
|
##### SystemPerl builds
|
||||||
|
|
||||||
ifeq ($(VM_SP),1)
|
ifeq ($(VM_SP),1)
|
||||||
CPPFLAGS += -I$(SYSTEMPERL)/src -DSYSTEMPERL
|
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE) -DSYSTEMPERL
|
||||||
VPATH += $(SYSTEMPERL)/src
|
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||||
LIBS += -lm -lstdc++
|
LIBS += -lm -lstdc++
|
||||||
|
|
||||||
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
|
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
|
||||||
@@ -109,8 +110,8 @@ endif
|
|||||||
ifeq ($(VM_SC),1)
|
ifeq ($(VM_SC),1)
|
||||||
LIBS += -lm -lstdc++
|
LIBS += -lm -lstdc++
|
||||||
ifeq ($(VM_TRACE),1)
|
ifeq ($(VM_TRACE),1)
|
||||||
CPPFLAGS += -I$(SYSTEMPERL)/src
|
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||||
VPATH += $(SYSTEMPERL)/src
|
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -120,8 +121,8 @@ endif
|
|||||||
ifeq ($(VM_PCLI),1)
|
ifeq ($(VM_PCLI),1)
|
||||||
LIBS += -lm -lstdc++
|
LIBS += -lm -lstdc++
|
||||||
ifeq ($(VM_TRACE),1)
|
ifeq ($(VM_TRACE),1)
|
||||||
CPPFLAGS += -I$(SYSTEMPERL)/src
|
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||||
VPATH += $(SYSTEMPERL)/src
|
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -1,19 +1,20 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License or the Perl Artistic License.
|
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||||
|
// Version 2.0.
|
||||||
//
|
//
|
||||||
// This is distributed in the hope that it will be useful,
|
// This is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
// DESCRIPTION: Verilator: Include in verilog files to hide verilator defines
|
// DESCRIPTION: Verilator: Include in verilog files to hide verilator defines
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
`ifdef verilator `else
|
`ifdef verilator `else
|
||||||
`define coverage_block_off
|
`define coverage_block_off
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// Hide file descriptor difference
|
// Hide file descriptor difference
|
||||||
`ifdef verilator
|
`ifdef verilator
|
||||||
`define verilator_file_descriptor reg [63:0]
|
`define verilator_file_descriptor reg [63:0]
|
||||||
|
|||||||
+17
-12
@@ -1,15 +1,16 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// Lesser General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
///
|
///
|
||||||
/// \file
|
/// \file
|
||||||
@@ -21,7 +22,7 @@
|
|||||||
/// config_build.h.in, code needed by Verilated code only goes into
|
/// config_build.h.in, code needed by Verilated code only goes into
|
||||||
/// verilated.h, and code needed by both goes here (verilatedos.h).
|
/// verilated.h, and code needed by both goes here (verilatedos.h).
|
||||||
///
|
///
|
||||||
/// Code available from: http://www.veripool.com/verilator
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
///
|
///
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
@@ -84,36 +85,40 @@ typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
|||||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||||
typedef long vlsint32_t; ///< 32-bit signed type
|
typedef long vlsint32_t; ///< 32-bit signed type
|
||||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
#elif defined(_WIN32) && !defined(__MINGW32__)
|
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||||
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
typedef unsigned int uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||||
typedef int vlsint32_t; ///< 32-bit signed type
|
typedef int vlsint32_t; ///< 32-bit signed type
|
||||||
typedef unsigned int vluint32_t; ///< 32-bit unsigned type
|
typedef unsigned int vluint32_t; ///< 32-bit unsigned type
|
||||||
typedef __int64 vlsint64_t; ///< 64-bit signed type
|
typedef __int64 vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||||
#else // Linux or compliant Unix flavors, -m64
|
#else // Linux or compliant Unix flavors, -m64
|
||||||
# include <stdint.h> // Linux and most flavors
|
# include <stdint.h> // Linux and most flavors
|
||||||
# include <inttypes.h> // Solaris
|
# include <inttypes.h> // Solaris
|
||||||
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
||||||
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
||||||
typedef int vlsint32_t; ///< 32-bit signed type
|
typedef int vlsint32_t; ///< 32-bit signed type
|
||||||
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Integer size macros
|
// Integer size macros
|
||||||
|
|
||||||
|
#define VL_BYTESIZE 8 ///< Bits in a byte
|
||||||
|
#define VL_SHORTSIZE 16 ///< Bits in a short
|
||||||
#define VL_WORDSIZE 32 ///< Bits in a word
|
#define VL_WORDSIZE 32 ///< Bits in a word
|
||||||
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
||||||
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
||||||
|
|
||||||
|
/// Bytes this number of bits needs (1 bit=1 byte)
|
||||||
|
#define VL_BYTES_I(nbits) (((nbits)+(VL_BYTESIZE-1))/VL_BYTESIZE)
|
||||||
/// Words this number of bits needs (1 bit=1 word)
|
/// Words this number of bits needs (1 bit=1 word)
|
||||||
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
|
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2009-2009 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: Common include for all Verilated SystemC files
|
||||||
|
///
|
||||||
|
/// This file is included automatically by Verilator at the top of
|
||||||
|
/// all SystemC files it generates.
|
||||||
|
///
|
||||||
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
|
///
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _VERILATEDSC_H_
|
||||||
|
#define _VERILATEDSC_H_ 1 ///< Header Guard
|
||||||
|
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "systemc.h"
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VL_SC_BV_DATAP
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
|
||||||
|
class VlScBvExposer : public sc_bv_base {
|
||||||
|
public:
|
||||||
|
static uint32_t* sp_datap(const sc_bv_base& base) {
|
||||||
|
return static_cast<const VlScBvExposer*>(&base)->sp_datatp(); }
|
||||||
|
uint32_t* sp_datatp() const { return (uint32_t*)(m_data); }
|
||||||
|
// Above reads this protected element in sc_bv_base:
|
||||||
|
// sc_digit* m_data; // data array
|
||||||
|
};
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
|
||||||
|
#endif // guard
|
||||||
+1
-1
@@ -115,7 +115,7 @@ fi
|
|||||||
if [ x"$dir_arg" != x ]; then
|
if [ x"$dir_arg" != x ]; then
|
||||||
dst=$src
|
dst=$src
|
||||||
src=""
|
src=""
|
||||||
|
|
||||||
if [ -d $dst ]; then
|
if [ -d $dst ]; then
|
||||||
instcmd=:
|
instcmd=:
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
# Created: 1993-05-16
|
# Created: 1993-05-16
|
||||||
# Public domain
|
# Public domain
|
||||||
|
|
||||||
# $Id:$
|
|
||||||
|
|
||||||
errstatus=0
|
errstatus=0
|
||||||
|
|
||||||
for file
|
for file
|
||||||
|
|||||||
Executable
+85
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
######################################################################
|
||||||
|
#
|
||||||
|
# Copyright 2007-2009 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.
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# DESCRIPTION: Diff bison files
|
||||||
|
|
||||||
|
use Getopt::Long;
|
||||||
|
use IO::File;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
our $Debug;
|
||||||
|
our $Opt_Unsup;
|
||||||
|
|
||||||
|
if (! GetOptions (
|
||||||
|
#"help" => \&usage,
|
||||||
|
"debug" => sub { $Debug = 1; },
|
||||||
|
"unsup!" => \$Opt_Unsup, # Ignore unsupported
|
||||||
|
)) {
|
||||||
|
die "usage();"
|
||||||
|
}
|
||||||
|
|
||||||
|
diff($ARGV[0],$ARGV[1]);
|
||||||
|
|
||||||
|
sub diff {
|
||||||
|
my $a=shift;
|
||||||
|
my $b=shift;
|
||||||
|
|
||||||
|
my $ta = "/tmp/bisondiff.$$.a";
|
||||||
|
my $tb = "/tmp/bisondiff.$$.b";
|
||||||
|
|
||||||
|
prep($a,$ta);
|
||||||
|
prep($b,$tb);
|
||||||
|
|
||||||
|
system("diff -u -w $ta $tb");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prep {
|
||||||
|
my $filename = shift;
|
||||||
|
my $wfilename = shift;
|
||||||
|
|
||||||
|
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
|
||||||
|
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
|
||||||
|
|
||||||
|
my %declared;
|
||||||
|
my %used;
|
||||||
|
|
||||||
|
my $body = 0;
|
||||||
|
my $rule = "";
|
||||||
|
my $skip = 1;
|
||||||
|
while (defined(my $line = $fh->getline)) {
|
||||||
|
if ($skip == 1) {
|
||||||
|
next if $line !~ /%token/;
|
||||||
|
$skip = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Opt_Unsup) {
|
||||||
|
$line =~ s!//UNSUP!|!g;
|
||||||
|
$line =~ s!(\s+)\|(\s+)!$1$2!g; # As "UNSUP" often replaces "|"
|
||||||
|
}
|
||||||
|
|
||||||
|
# %type<foo>
|
||||||
|
$line =~ s/^(%\S+)<(\S+)>/$1/;
|
||||||
|
# rule<foo>
|
||||||
|
$line =~ s/^([a-zA-Z0-9_]+)<\S+>:/$1:/;
|
||||||
|
# Productions
|
||||||
|
$line =~ s/[ \t]{[^}]*?}/\t{}/g;
|
||||||
|
|
||||||
|
$fho->print($line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# compile-command: "./bisondiff --unsup $WUP/Verilog/Parser/VParseBison.y ../src/verilog.y"
|
||||||
|
# End:
|
||||||
+8
-14
@@ -1,22 +1,16 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
#$Id$
|
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2007-2008 by Wilson Snyder.
|
# Copyright 2007-2009 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.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of either the GNU General Public License or the
|
|
||||||
# Perl Artistic License.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the Perl Artistic License
|
|
||||||
# along with this module; see the file COPYING. If not, see
|
|
||||||
# www.cpan.org
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
# DESCRIPTION: Debugging of bison output
|
# DESCRIPTION: Debugging of bison output
|
||||||
@@ -43,8 +37,8 @@ foreach my $line (<STDIN>) {
|
|||||||
$rule .= $line;
|
$rule .= $line;
|
||||||
if ($line =~ m!^\s*;\s*$!) {
|
if ($line =~ m!^\s*;\s*$!) {
|
||||||
#print "Rule: $rule\n";
|
#print "Rule: $rule\n";
|
||||||
($rule =~ /^([a-zA-Z0-9_]+):(.*)$/) or die "%Error: No rule name: $1\n";
|
($rule =~ /^([a-zA-Z0-9_]+)(<\S+>)?:(.*)$/) or die "%Error: No rule name: $1\n";
|
||||||
my $rulename = $1; my $preaction = $2;
|
my $rulename = $1; my $preaction = $3;
|
||||||
$declared{$rulename} = $lineno;
|
$declared{$rulename} = $lineno;
|
||||||
$preaction =~ s/\{[^\}]*\}/ /g;
|
$preaction =~ s/\{[^\}]*\}/ /g;
|
||||||
#print "RULEN $rulename PA $preaction\n" if $Debug;
|
#print "RULEN $rulename PA $preaction\n" if $Debug;
|
||||||
@@ -63,5 +57,5 @@ foreach my $line (<STDIN>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Local Variables:
|
# Local Variables:
|
||||||
# compile-command: "./bisonreader < verilog.y"
|
# compile-command: "./bisonreader < ../src/verilog.y"
|
||||||
# End:
|
# End:
|
||||||
|
|||||||
+5
-18
@@ -1,17 +1,5 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -50,7 +38,6 @@ cwrite ("graph_export.cpp");
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -120,7 +107,7 @@ sub cwrite {
|
|||||||
foreach my $edge (@Edges) {
|
foreach my $edge (@Edges) {
|
||||||
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
|
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
|
||||||
$edge->{from}, $edge->{to},
|
$edge->{from}, $edge->{to},
|
||||||
$edge->{weight}, $edge->{cutable}?"true":"false");
|
$edge->{weight}, $edge->{cutable}?"true":"false");
|
||||||
}
|
}
|
||||||
$fh->print("}\n");
|
$fh->print("}\n");
|
||||||
}
|
}
|
||||||
@@ -156,9 +143,9 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2009 by Wilson Snyder. Verilator is free software; you can
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
Lesser General Public License or the Perl Artistic License.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
|||||||
+5
-18
@@ -1,17 +1,5 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -55,7 +43,6 @@ dotwrite();
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -175,7 +162,7 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
dot_pruner -
|
dot_pruner -
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@@ -197,9 +184,9 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2009 by Wilson Snyder. Verilator is free software; you can
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
Lesser General Public License or the Perl Artistic License.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
|||||||
Executable
+61
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
######################################################################
|
||||||
|
#
|
||||||
|
# Copyright 2007-2009 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.
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# DESCRIPTION: Diff flex files
|
||||||
|
|
||||||
|
use IO::File;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my $Debug;
|
||||||
|
|
||||||
|
diff($ARGV[0],$ARGV[1]);
|
||||||
|
|
||||||
|
sub diff {
|
||||||
|
my $a=shift;
|
||||||
|
my $b=shift;
|
||||||
|
|
||||||
|
my $ta = "/tmp/flexdiff.$$.a";
|
||||||
|
my $tb = "/tmp/flexdiff.$$.b";
|
||||||
|
|
||||||
|
prep($a,$ta);
|
||||||
|
prep($b,$tb);
|
||||||
|
|
||||||
|
system("diff -u -w $ta $tb");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prep {
|
||||||
|
my $filename = shift;
|
||||||
|
my $wfilename = shift;
|
||||||
|
|
||||||
|
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
|
||||||
|
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
|
||||||
|
|
||||||
|
my %declared;
|
||||||
|
my %used;
|
||||||
|
my @lines;
|
||||||
|
|
||||||
|
while (defined(my $line = $fh->getline)) {
|
||||||
|
# Productions
|
||||||
|
$line =~ s/[ \t]{[^}]*?}/\t{}/g;
|
||||||
|
push @lines, $line;
|
||||||
|
}
|
||||||
|
|
||||||
|
#@lines = sort @lines;
|
||||||
|
$fho->print(@lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# compile-command: "./flexdiff $WUP/Verilog/Parser/VParseLex.l ../src/verilog.l"
|
||||||
|
# End:
|
||||||
Executable
+59
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
# See copyright, etc in below POD section.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
require 5.006_001;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# main
|
||||||
|
|
||||||
|
delete $ENV{MODULE_VERSION};
|
||||||
|
_setup_modules();
|
||||||
|
module('add','cadence_verif');
|
||||||
|
exec('iccr',@ARGV);
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Modules package
|
||||||
|
|
||||||
|
sub _setup_modules {
|
||||||
|
# Load the 'module' command into the environment
|
||||||
|
my $init = "/sicortex/$ENV{DIRPROJECT_ARCH}/lib/Modules/default/init/perl";
|
||||||
|
(-f $init) or die "%Error: Script not found: $init,";
|
||||||
|
require $init;
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
invoke_iccr - Invoke tool under "modules" command
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
invoke_iccr {ncv arguments}
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
Copyright 2007-2009 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.
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Wilson Snyder <[email protected]>
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### Local Variables:
|
||||||
|
### compile-command: "./invoke_iccr -help"
|
||||||
|
### End:
|
||||||
+4
-15
@@ -1,17 +1,5 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2007-2008 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -52,9 +40,10 @@ invoke_ncverilog - Invoke tool under "modules" command
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2007-2008 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2009 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License or the Perl Artistic License.
|
Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
Version 2.0.
|
||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export GLIBCPP_FORCE_NEW=1
|
||||||
|
compile with -DVL_LEAK_CHECKS
|
||||||
|
valgrind --tool=memcheck --leak-check=yes /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg -MMD --bin /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg --cc -f /home/wsnyder/src/verilator/v4/verilator/test_c/../test_v/input.vc top.v --no-skip-identical 2>&1 | tee ~/d/aa
|
||||||
|
valgrind --tool=memcheck --leak-check=yes /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg -MMD --bin /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg --cc /home/wsnyder/src/verilator/v4/verilator/test_regress/t/t_case_huge.v --no-skip-identical -I/home/wsnyder/src/verilator/v4/verilator/test_regress/t 2>&1 | tee ~/d/aa
|
||||||
+6
-19
@@ -1,17 +1,5 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program 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.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -52,7 +40,6 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -292,7 +279,7 @@ sub p_var {
|
|||||||
}
|
}
|
||||||
p "\t";
|
p "\t";
|
||||||
{
|
{
|
||||||
local $Avoid_Hex=1;
|
local $Avoid_Hex=1;
|
||||||
t1;
|
t1;
|
||||||
}
|
}
|
||||||
p "\t";
|
p "\t";
|
||||||
@@ -322,7 +309,7 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
vtree_importer -
|
vtree_importer -
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@@ -344,9 +331,9 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2009 by Wilson Snyder. Verilator is free software; you can
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||||
Lesser General Public License or the Perl Artistic License.
|
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
|||||||
+28
-19
@@ -1,6 +1,5 @@
|
|||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
$c $Id$
|
|
||||||
@setfilename readme.info
|
@setfilename readme.info
|
||||||
@settitle Verilator Installation
|
@settitle Verilator Installation
|
||||||
@c %**end of header
|
@c %**end of header
|
||||||
@@ -15,25 +14,29 @@ $c $Id$
|
|||||||
This is the Verilator Package.
|
This is the Verilator Package.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Copyright::
|
* Copyright::
|
||||||
* Description::
|
* Description::
|
||||||
* Obtaining Distribution::
|
* Obtaining Distribution::
|
||||||
* Directory Structure::
|
* Directory Structure::
|
||||||
* Supported Systems::
|
* Supported Systems::
|
||||||
* Installation::
|
* Installation::
|
||||||
* Limitations::
|
* Limitations::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Copyright, Description, Top, Top
|
@node Copyright, Description, Top, Top
|
||||||
@section Copyright
|
@section Copyright
|
||||||
|
|
||||||
This package is Copyright 2003-2008 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
This package is Copyright 2003-2009 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||||
|
|
||||||
You may distribute under the terms of either the GNU General Public License
|
Verilator is free software; you can redistribute it and/or modify it
|
||||||
or the Artistic License, as specified in the Perl README file.
|
under the terms of either the GNU General Public License Version 3 or
|
||||||
|
the Perl Artistic License Version 2.0. (See the documentation for
|
||||||
|
more details.)
|
||||||
|
|
||||||
This code is provided with no warranty of any kind, and is used entirely at
|
This program is distributed in the hope that it will be useful, but
|
||||||
your own risk.
|
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.
|
||||||
|
|
||||||
@node Description, Obtaining Distribution, Copyright, Top
|
@node Description, Obtaining Distribution, Copyright, Top
|
||||||
@section Description
|
@section Description
|
||||||
@@ -45,7 +48,7 @@ Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
|
|||||||
reads the specified Verilog code, lints it, and optionally adds coverage
|
reads the specified Verilog code, lints it, and optionally adds coverage
|
||||||
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
||||||
it outputs .sp files for the SystemPerl preprocessor available at
|
it outputs .sp files for the SystemPerl preprocessor available at
|
||||||
http://veripool.com.
|
http://www.veripool.org.
|
||||||
|
|
||||||
The resulting files are then compiled with C++. The user writes a little
|
The resulting files are then compiled with C++. The user writes a little
|
||||||
C++ wrapper file, which instantiates the top level module. This is
|
C++ wrapper file, which instantiates the top level module. This is
|
||||||
@@ -56,11 +59,11 @@ The resulting executable will perform the actual simulation.
|
|||||||
@node Obtaining Distribution, Directory Structure, Description, Top
|
@node Obtaining Distribution, Directory Structure, Description, Top
|
||||||
@section Obtaining Distribution
|
@section Obtaining Distribution
|
||||||
|
|
||||||
The latest version is available at
|
The latest version is available at
|
||||||
@uref{http://veripool.com/verilator.htm}
|
@uref{http://www.veripool.org/verilator}
|
||||||
|
|
||||||
Download the latest package from that site, and decompress.
|
Download the latest package from that site, and decompress.
|
||||||
@samp{gunzip verilator_version.tar.gz ; tar xvf verilator_version.tar}
|
@samp{tar xvzf verilator_version.tgz}
|
||||||
|
|
||||||
@node Directory Structure, Supported Systems, Obtaining Distribution, Top
|
@node Directory Structure, Supported Systems, Obtaining Distribution, Top
|
||||||
@section Directory Structure
|
@section Directory Structure
|
||||||
@@ -117,8 +120,8 @@ If you will be using SystemC, download and install Verilog-Perl,
|
|||||||
If you will be using SystemC, download and install System-Perl,
|
If you will be using SystemC, download and install System-Perl,
|
||||||
@url{http://search.cpan.org/search?module=SystemC::Netlist}. Note
|
@url{http://search.cpan.org/search?module=SystemC::Netlist}. Note
|
||||||
you'll need to set a @samp{SYSTEMPERL} environment variable to point
|
you'll need to set a @samp{SYSTEMPERL} environment variable to point
|
||||||
to the downloaded kit (not the installed files.) Also, make sure to
|
to the downloaded kit. Optionally also set @samp{SYSTEMPERL_INCLUDE}
|
||||||
do a @code{make sc_patch}.
|
to point to the installed headers.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
@code{cd} to the Verilator directory containing this README.
|
@code{cd} to the Verilator directory containing this README.
|
||||||
@@ -126,6 +129,12 @@ do a @code{make sc_patch}.
|
|||||||
@item
|
@item
|
||||||
Type @samp{./configure} to configure Verilator for your system.
|
Type @samp{./configure} to configure Verilator for your system.
|
||||||
|
|
||||||
|
If you are configuring Verilator to be part of a RPM or other
|
||||||
|
distribution package system, you may want to use the --enable-defenv
|
||||||
|
configure flag. This will take the current value of VERILATOR_ROOT,
|
||||||
|
SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE and build
|
||||||
|
them as defaults into the executable.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Type @samp{make} to compile Verilator.
|
Type @samp{make} to compile Verilator.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
*~
|
||||||
*.old
|
*.old
|
||||||
config_build.h
|
config_build.h
|
||||||
Makefile
|
Makefile
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Verilator Source Code Notes
|
||||||
|
|
||||||
|
=head1 INTRODUCTION
|
||||||
|
|
||||||
|
See also the Verilator internals presentation at http://www.veripool.org.
|
||||||
|
|
||||||
|
=head1 VISITOR FUNCTIONS
|
||||||
|
|
||||||
|
=head2 Passing Variables
|
||||||
|
|
||||||
|
There's three ways data is passed between visitor functions.
|
||||||
|
|
||||||
|
1. A visitor-class member variable. This is generally for passing "parent"
|
||||||
|
information down to children. m_modp is a common example. It's set to
|
||||||
|
NULL in the constructor, where that node (AstModule visitor) sets it, then
|
||||||
|
the children are iterated, then it's cleared. Children under an AstModule
|
||||||
|
will see it set, while nodes elsewhere will see it clear. If there can be
|
||||||
|
nested items (for example an AstFor under an AstFor) the variable needs to
|
||||||
|
be save-set-restored in the AstFor visitor, otherwise exiting the lower for
|
||||||
|
will loose the upper for's setting.
|
||||||
|
|
||||||
|
2. User() attributes. Each node has 4 ->user() number or ->userp() pointer
|
||||||
|
utility values (a common technique lifted from graph traversal packages).
|
||||||
|
A visitor first clears the one it wants to use by calling
|
||||||
|
AstNode::user#ClearTree(), then it can mark any node's user() with whatever
|
||||||
|
data it wants. Readers just call nodep->user(), but may need to cast
|
||||||
|
appropriately, so you'll often see nodep->userp()->castSOMETYPE(). At the
|
||||||
|
top of each visitor are comments describing how the user() stuff applies to
|
||||||
|
that visitor class. For example:
|
||||||
|
|
||||||
|
// NODE STATE
|
||||||
|
// Cleared entire netlist
|
||||||
|
// AstModule::user1p() // bool. True to inline this module
|
||||||
|
|
||||||
|
This says that at the AstNetlist user1ClearTree() is called. Each
|
||||||
|
AstModule's is user1() is used to indicate if we're going to inline it.
|
||||||
|
|
||||||
|
These comments are important to make sure a user#() on a given AstNode type
|
||||||
|
is never being used for two different purposes.
|
||||||
|
|
||||||
|
Note that calling user#ClearTree is fast, it doesn't walk the tree, so it's
|
||||||
|
ok to call fairly often. For example, it's commonly called on every
|
||||||
|
module.
|
||||||
|
|
||||||
|
3. Parameters can be passed between the visitors in close to the "normal"
|
||||||
|
function caller to callee way. This is the second "vup" parameter that is
|
||||||
|
ignored on most of the visitor functions. V3Width does this, but it proved
|
||||||
|
more messy than the above and is deprecated. (V3Width was nearly the first
|
||||||
|
module written. Someday this scheme may be removed, as it slows the
|
||||||
|
program down to have to pass vup everywhere.)
|
||||||
|
|
||||||
|
=head1 DEBUGGING WITH GDB
|
||||||
|
|
||||||
|
The test_regress/driver.pl script accepts --gdb to start Verilator under
|
||||||
|
gdb.
|
||||||
|
|
||||||
|
To break at a specific edit number which changed a node (presumably to find
|
||||||
|
what made a <e####> line in the tree dumps):
|
||||||
|
|
||||||
|
watch AstNode::s_editCntGbl==####
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
Copyright 2008-2009 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.
|
||||||
+12
-8
@@ -1,15 +1,16 @@
|
|||||||
# $Id$ */
|
# -*- Makefile -*-
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# DESCRIPTION: Verilator: Makefile for verilog source
|
# DESCRIPTION: Verilator: Makefile for verilog source
|
||||||
#
|
#
|
||||||
# Code available from: http://www.veripool.com/verilator
|
# Code available from: http://www.veripool.org/verilator
|
||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# 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,
|
# Verilator is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -40,12 +41,16 @@ export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnam
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OBJCACHE_HOSTS),)
|
ifeq ($(OBJCACHE_HOSTS),)
|
||||||
export OBJCACHE :=
|
export OBJCACHE :=
|
||||||
else
|
else
|
||||||
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||||
export OBJCACHE := @objcache --read --write
|
export OBJCACHE := @objcache --read --write
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
UNDER_GIT = $(wildcard ../.git/logs/HEAD)
|
||||||
|
|
||||||
|
#*********************************************************************
|
||||||
|
|
||||||
obj_opt:
|
obj_opt:
|
||||||
mkdir $@
|
mkdir $@
|
||||||
obj_dbg:
|
obj_dbg:
|
||||||
@@ -71,10 +76,10 @@ dbg: ../verilator_bin_dbg
|
|||||||
|
|
||||||
prefiles::
|
prefiles::
|
||||||
|
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||||
prefiles:: config_rev.h
|
prefiles:: config_rev.h
|
||||||
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
||||||
config_rev.h: config_rev.pl .svn/entries
|
config_rev.h: config_rev.pl ../.git/logs/HEAD
|
||||||
$(PERL) config_rev.pl . >$@
|
$(PERL) config_rev.pl . >$@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -83,7 +88,6 @@ clean mostlyclean distclean maintainer-clean::
|
|||||||
-rm -rf obj_* *.log *.dmp *.vpd core
|
-rm -rf obj_* *.log *.dmp *.vpd core
|
||||||
-rm -f *.o *.d perlxsi.c *_gen_*
|
-rm -f *.o *.d perlxsi.c *_gen_*
|
||||||
-rm -f *__gen*
|
-rm -f *__gen*
|
||||||
-rm -f *.yy.* y.output y.tab.[cho] *_test
|
|
||||||
-rm -f .objcache*
|
-rm -f .objcache*
|
||||||
|
|
||||||
distclean maintainer-clean::
|
distclean maintainer-clean::
|
||||||
|
|||||||
+62
-23
@@ -1,15 +1,16 @@
|
|||||||
# $Id$ -*- Makefile -*-
|
# -*- Makefile -*-
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# DESCRIPTION: Verilator: Makefile for verilog source
|
# DESCRIPTION: Verilator: Makefile for verilog source
|
||||||
#
|
#
|
||||||
# Code available from: http://www.veripool.com/verilator
|
# Code available from: http://www.veripool.org/verilator
|
||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# 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,
|
# Verilator is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -23,11 +24,27 @@
|
|||||||
srcdir = ..
|
srcdir = ..
|
||||||
incdir = ../../include
|
incdir = ../../include
|
||||||
|
|
||||||
PERL = @PERL@
|
# Programs
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
CXX = @CXX@
|
CXX = @CXX@
|
||||||
LINK = @CXX@
|
LINK = @CXX@
|
||||||
|
LEX = @LEX@
|
||||||
|
LFLAGS = -d
|
||||||
|
PERL = @PERL@
|
||||||
|
YACC = @YACC@
|
||||||
|
|
||||||
|
prefix = @prefix@
|
||||||
|
|
||||||
|
# Directory in which to install data across multiple architectures
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
|
||||||
|
# Directory in which to install package specific files
|
||||||
|
# Generally ${prefix}/share/verilator
|
||||||
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
|
# Compile options
|
||||||
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
|
CPPFLAGSNOWALL += @CPPFLAGS@
|
||||||
LDFLAGS += @LDFLAGS@
|
LDFLAGS += @LDFLAGS@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
@@ -48,17 +65,12 @@ COPT = -ggdb -DVL_DEBUG
|
|||||||
endif
|
endif
|
||||||
#################
|
#################
|
||||||
|
|
||||||
LEX = @LEX@
|
|
||||||
LFLAGS = -d
|
|
||||||
YACC = @YACC@
|
|
||||||
YFLAGS = -y -d -v
|
|
||||||
|
|
||||||
#LIBS += -ldl
|
#LIBS += -ldl
|
||||||
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
|
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
|
||||||
|
|
||||||
LIBS = -lm -lfl
|
LIBS = -lm -lfl
|
||||||
|
|
||||||
CPPFLAGSNOWALL = -MMD
|
CPPFLAGSNOWALL += -MMD
|
||||||
CPPFLAGSNOWALL += -I. -I$(srcdir) -I$(incdir)
|
CPPFLAGSNOWALL += -I. -I$(srcdir) -I$(incdir)
|
||||||
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
||||||
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||||
@@ -70,9 +82,30 @@ CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
|||||||
#CPPFLAGS += -pedantic-errors
|
#CPPFLAGS += -pedantic-errors
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
|
||||||
|
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
|
||||||
|
#else if set, leave as-is.
|
||||||
|
#else if SYSTEMPERL="" don't set _INCLUDE so source will figure it out
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Allow RPM builds to specify hardcoded data directories
|
||||||
|
# To do this:
|
||||||
|
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMPERL_INCLUDE=\"$(SYSTEMPERL_INCLUDE)\"
|
||||||
|
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
|
||||||
|
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(pkgdatadir)\"
|
||||||
|
else
|
||||||
|
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(VERILATOR_ROOT)\"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
HEADERS = $(wildcard V*.h v*.h)
|
HEADERS = $(wildcard V*.h v*.h)
|
||||||
|
|
||||||
ASTGEN = $(srcdir)/astgen
|
ASTGEN = $(srcdir)/astgen
|
||||||
|
BISONPRE = $(srcdir)/bisonpre
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
#### Top level
|
#### Top level
|
||||||
@@ -85,7 +118,6 @@ make_info:
|
|||||||
clean mostlyclean distclean maintainer-clean::
|
clean mostlyclean distclean maintainer-clean::
|
||||||
-rm -f *.o *.d perlxsi.c *_gen_*
|
-rm -f *.o *.d perlxsi.c *_gen_*
|
||||||
-rm -f *__gen*
|
-rm -f *__gen*
|
||||||
-rm -f *.yy.* y.output y.tab.[cho] *_test
|
|
||||||
-rm -f obj_* .objcache*
|
-rm -f obj_* .objcache*
|
||||||
|
|
||||||
distclean maintainer-clean:: clean
|
distclean maintainer-clean:: clean
|
||||||
@@ -111,10 +143,12 @@ RAW_OBJS = \
|
|||||||
V3Cast.o \
|
V3Cast.o \
|
||||||
V3Changed.o \
|
V3Changed.o \
|
||||||
V3Clean.o \
|
V3Clean.o \
|
||||||
|
V3ClkGater.o \
|
||||||
V3Clock.o \
|
V3Clock.o \
|
||||||
V3Combine.o \
|
V3Combine.o \
|
||||||
V3Const__gen.o \
|
V3Const__gen.o \
|
||||||
V3Coverage.o \
|
V3Coverage.o \
|
||||||
|
V3CoverageJoin.o \
|
||||||
V3Dead.o \
|
V3Dead.o \
|
||||||
V3Delayed.o \
|
V3Delayed.o \
|
||||||
V3Depth.o \
|
V3Depth.o \
|
||||||
@@ -166,6 +200,7 @@ RAW_OBJS = \
|
|||||||
V3Task.o \
|
V3Task.o \
|
||||||
V3Trace.o \
|
V3Trace.o \
|
||||||
V3TraceDecl.o \
|
V3TraceDecl.o \
|
||||||
|
V3Tristate.o \
|
||||||
V3Unknown.o \
|
V3Unknown.o \
|
||||||
V3Unroll.o \
|
V3Unroll.o \
|
||||||
V3Width.o \
|
V3Width.o \
|
||||||
@@ -193,15 +228,15 @@ $(TGT): V3Ast__gen_classes.h $(OBJS)
|
|||||||
@echo " Linking $@..."
|
@echo " Linking $@..."
|
||||||
-rm -rf $@ [email protected]
|
-rm -rf $@ [email protected]
|
||||||
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
||||||
@-cp [email protected] $@
|
@-(cp [email protected] $@ || true)
|
||||||
# ok if cp failes on linux, it's there to insure make works on NT
|
# ok if cp failes on linux, it's there to insure executable works on NT
|
||||||
|
|
||||||
V3Number_test: V3Number_test.o
|
V3Number_test: V3Number_test.o
|
||||||
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||||
|
|
||||||
#### Modules
|
#### Modules
|
||||||
|
|
||||||
%__gen.cpp: %.cpp $(ASTGEN)
|
%__gen.cpp: %.cpp $(ASTGEN) V3Ast.h V3AstNodes.h
|
||||||
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
@@ -209,10 +244,10 @@ V3Number_test: V3Number_test.o
|
|||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $<
|
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $<
|
||||||
|
|
||||||
V3Read.o: V3Read.cpp V3Lexer.yy.cpp
|
V3Read.o: V3Read.cpp V3Lexer.yy.cpp V3ParseBison.c
|
||||||
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
||||||
|
|
||||||
V3Parse.o: V3Parse.cpp y.tab.c
|
V3Parse.o: V3Parse.cpp V3ParseBison.c
|
||||||
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
||||||
|
|
||||||
V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
|
V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
|
||||||
@@ -221,22 +256,27 @@ V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
|
|||||||
#### Generated files
|
#### Generated files
|
||||||
|
|
||||||
# Target rule called before parallel build to make generated files
|
# Target rule called before parallel build to make generated files
|
||||||
serial:: V3Ast__gen_classes.h
|
serial:: V3Ast__gen_classes.h V3ParseBison.c
|
||||||
|
|
||||||
V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
|
V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
|
||||||
$(PERL) $(ASTGEN) -I$(srcdir) --classes
|
$(PERL) $(ASTGEN) -I$(srcdir) --classes
|
||||||
|
|
||||||
y.tab.c y.tab.h: verilog.y $(HEADERS)
|
V3ParseBison.h: V3ParseBison.c
|
||||||
@echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer."
|
|
||||||
${YACC} ${YFLAGS} $<
|
|
||||||
|
|
||||||
V3Lexer_pregen.yy.cpp: verilog.l y.tab.h $(HEADERS)
|
# Have only one output file in this rule to prevent parallel make issues
|
||||||
|
V3ParseBison.c: verilog.y $(BISONPRE)
|
||||||
|
@echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer."
|
||||||
|
$(PERL) $(BISONPRE) --yacc ${YACC} -d -v -o V3ParseBison.c $<
|
||||||
|
|
||||||
|
V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS)
|
||||||
|
${LEX} --version
|
||||||
${LEX} ${LFLAGS} -o$@ $<
|
${LEX} ${LFLAGS} -o$@ $<
|
||||||
|
|
||||||
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp
|
V3Lexer.yy.cpp: V3Lexer_pregen.yy.cpp
|
||||||
$(PERL) $(srcdir)/flexfix <$< >$@
|
$(PERL) $(srcdir)/flexfix <$< >$@
|
||||||
|
|
||||||
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
V3PreLex_pregen.yy.cpp: V3PreLex.l $(HEADERS)
|
||||||
|
${LEX} --version
|
||||||
${LEX} ${LFLAGS} -o$@ $<
|
${LEX} ${LFLAGS} -o$@ $<
|
||||||
|
|
||||||
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp
|
V3PreLex.yy.cpp: V3PreLex_pregen.yy.cpp
|
||||||
@@ -249,4 +289,3 @@ DEPS := $(wildcard *.d)
|
|||||||
ifneq ($(DEPS),)
|
ifneq ($(DEPS),)
|
||||||
include $(DEPS)
|
include $(DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
+67
-30
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Active's Transformations:
|
// V3Active's Transformations:
|
||||||
//
|
//
|
||||||
// Note this can be called multiple times.
|
// Note this can be called multiple times.
|
||||||
// Create a IACTIVE(initial), SACTIVE(combo)
|
// Create a IACTIVE(initial), SACTIVE(combo)
|
||||||
// ALWAYS: Remove any-edges from sense list
|
// ALWAYS: Remove any-edges from sense list
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "V3Active.h"
|
#include "V3Active.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3EmitCBase.h"
|
#include "V3EmitCBase.h"
|
||||||
|
#include "V3Const.h"
|
||||||
|
|
||||||
//***** See below for main transformation engine
|
//***** See below for main transformation engine
|
||||||
|
|
||||||
@@ -52,7 +53,11 @@
|
|||||||
|
|
||||||
class ActiveBaseVisitor : public AstNVisitor {
|
class ActiveBaseVisitor : public AstNVisitor {
|
||||||
protected:
|
protected:
|
||||||
//int debug() { return 9; }
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ActiveNamer : public ActiveBaseVisitor {
|
class ActiveNamer : public ActiveBaseVisitor {
|
||||||
@@ -78,8 +83,8 @@ private:
|
|||||||
// Don't clear scopep, the namer persists beyond this visit
|
// Don't clear scopep, the namer persists beyond this visit
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||||
// Sort sensitivity list
|
// Simplify sensitivity list
|
||||||
nodep->sortSenses();
|
V3Const::constifyTreeExpensive(nodep);
|
||||||
}
|
}
|
||||||
// Empty visitors, speed things up
|
// Empty visitors, speed things up
|
||||||
virtual void visit(AstNodeStmt* nodep, AstNUser*) { }
|
virtual void visit(AstNodeStmt* nodep, AstNUser*) { }
|
||||||
@@ -130,7 +135,7 @@ public:
|
|||||||
found:
|
found:
|
||||||
// Not found, form a new one
|
// Not found, form a new one
|
||||||
if (!activep) {
|
if (!activep) {
|
||||||
AstSenTree* newsenp = sensesp->cloneTree(false)->castSenTree();
|
AstSenTree* newsenp = sensesp->cloneTree(false);
|
||||||
activep = new AstActive(fl, "sequent", newsenp);
|
activep = new AstActive(fl, "sequent", newsenp);
|
||||||
activep->sensesStorep(activep->sensesp());
|
activep->sensesStorep(activep->sensesp());
|
||||||
UINFO(8," New ACTIVE "<<activep<<endl);
|
UINFO(8," New ACTIVE "<<activep<<endl);
|
||||||
@@ -186,10 +191,15 @@ public:
|
|||||||
class ActiveVisitor : public ActiveBaseVisitor {
|
class ActiveVisitor : public ActiveBaseVisitor {
|
||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
|
// Each call to V3Const::constify
|
||||||
|
// AstNode::user4() Used by V3Const::constify, called below
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
ActiveNamer m_namer; // Tracking of active names
|
ActiveNamer m_namer; // Tracking of active names
|
||||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||||
|
AstAlways* m_alwaysp; // Under always
|
||||||
|
bool m_itemCombo; // Found a SenItem combo
|
||||||
|
bool m_itemSequent; // Found a SenItem sequential
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
@@ -224,6 +234,13 @@ private:
|
|||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
wantactivep->addStmtsp(nodep);
|
wantactivep->addStmtsp(nodep);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
||||||
|
// Relink to CACTIVE, unless already under it
|
||||||
|
UINFO(4," COVERTOGGLE "<<nodep<<endl);
|
||||||
|
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
|
||||||
|
nodep->unlinkFrBack();
|
||||||
|
wantactivep->addStmtsp(nodep);
|
||||||
|
}
|
||||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
virtual void visit(AstFinal* nodep, AstNUser*) {
|
||||||
// Relink to CFUNC for the final
|
// Relink to CFUNC for the final
|
||||||
UINFO(4," FINAL "<<nodep<<endl);
|
UINFO(4," FINAL "<<nodep<<endl);
|
||||||
@@ -246,6 +263,7 @@ private:
|
|||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); nodep = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// METHODS
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
// Move always to appropriate ACTIVE based on its sense list
|
// Move always to appropriate ACTIVE based on its sense list
|
||||||
UINFO(4," ALW "<<nodep<<endl);
|
UINFO(4," ALW "<<nodep<<endl);
|
||||||
@@ -256,7 +274,10 @@ private:
|
|||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nodep->sensesp() && nodep->sensesp()->sensesp() && nodep->sensesp()->sensesp()->isNever()) {
|
if (nodep->sensesp()
|
||||||
|
&& nodep->sensesp()->sensesp()
|
||||||
|
&& nodep->sensesp()->sensesp()->castSenItem()
|
||||||
|
&& nodep->sensesp()->sensesp()->castSenItem()->isNever()) {
|
||||||
// Never executing. Kill it.
|
// Never executing. Kill it.
|
||||||
if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
@@ -264,24 +285,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read sensitivitues
|
// Read sensitivitues
|
||||||
bool combo = false;
|
m_alwaysp = nodep;
|
||||||
bool sequent = false;
|
m_itemCombo = false;
|
||||||
if (nodep->sensesp()) {
|
m_itemSequent = false;
|
||||||
for (AstSenItem* nextp, *senp = nodep->sensesp()->sensesp(); senp; senp=nextp) {
|
nodep->sensesp()->iterateAndNext(*this);
|
||||||
nextp = senp->nextp()->castSenItem();
|
m_alwaysp = NULL;
|
||||||
if (senp->edgeType() == AstEdgeType::ANYEDGE) {
|
bool combo = m_itemCombo;
|
||||||
combo = true;
|
bool sequent = m_itemSequent;
|
||||||
// Delete the sensitivity
|
|
||||||
// We'll add it as a generic COMBO SenItem in a moment.
|
|
||||||
senp->unlinkFrBack()->deleteTree(); senp=NULL;
|
|
||||||
} else if (senp->varrefp()) {
|
|
||||||
if (senp->varrefp()->width()>1) senp->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
|
||||||
<<senp->varrefp()->prettyName());
|
|
||||||
sequent = true;
|
|
||||||
senp->varrefp()->varp()->usedClock(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
||||||
#ifndef NEW_ORDERING
|
#ifndef NEW_ORDERING
|
||||||
if (combo && sequent) {
|
if (combo && sequent) {
|
||||||
@@ -320,6 +331,29 @@ private:
|
|||||||
ActiveDlyVisitor dlyvisitor (nodep);
|
ActiveDlyVisitor dlyvisitor (nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
||||||
|
AstSenItem* subitemp = nodep->sensesp();
|
||||||
|
if (subitemp->edgeType() != AstEdgeType::ANYEDGE
|
||||||
|
&& subitemp->edgeType() != AstEdgeType::POSEDGE
|
||||||
|
&& subitemp->edgeType() != AstEdgeType::NEGEDGE) {
|
||||||
|
nodep->v3fatalSrc("Strange activity type under SenGate");
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||||
|
if (nodep->edgeType() == AstEdgeType::ANYEDGE) {
|
||||||
|
m_itemCombo = true;
|
||||||
|
// Delete the sensitivity
|
||||||
|
// We'll add it as a generic COMBO SenItem in a moment.
|
||||||
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
} else if (nodep->varrefp()) {
|
||||||
|
// V3LinkResolve should have cleaned most of these up
|
||||||
|
if (nodep->varrefp()->width()>1) nodep->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: "
|
||||||
|
<<nodep->varrefp()->prettyName());
|
||||||
|
m_itemSequent = true;
|
||||||
|
nodep->varrefp()->varp()->usedClock(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Empty visitors, speed things up
|
// Empty visitors, speed things up
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
||||||
@@ -332,6 +366,9 @@ public:
|
|||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveVisitor(AstNode* nodep) {
|
ActiveVisitor(AstNode* nodep) {
|
||||||
m_scopeFinalp = NULL;
|
m_scopeFinalp = NULL;
|
||||||
|
m_alwaysp = NULL;
|
||||||
|
m_itemCombo = false;
|
||||||
|
m_itemSequent = false;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~ActiveVisitor() {}
|
virtual ~ActiveVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+23
-11
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Active's Transformations:
|
// V3Active's Transformations:
|
||||||
//
|
//
|
||||||
// Note this can be called multiple times.
|
// Note this can be called multiple times.
|
||||||
// Across all ACTIVES
|
// Across all ACTIVES
|
||||||
// SenTrees are now under each ACTIVE statement, we want them global:
|
// SenTrees are now under each ACTIVE statement, we want them global:
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "V3ActiveTop.h"
|
#include "V3ActiveTop.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3SenTree.h"
|
#include "V3SenTree.h"
|
||||||
|
#include "V3Const.h"
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Active class functions
|
// Active class functions
|
||||||
@@ -49,10 +50,20 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist
|
// Entire netlist
|
||||||
// AstNode::user() bool. True if processed
|
// AstNode::user() bool. True if processed
|
||||||
|
// Each call to V3Const::constify
|
||||||
|
// AstNode::user4() Used by V3Const::constify, called below
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
||||||
SenTreeFinder m_finder; // Find global sentree's and add them
|
SenTreeFinder m_finder; // Find global sentree's and add them
|
||||||
//int debug() { return 9; }
|
|
||||||
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
||||||
@@ -71,8 +82,10 @@ private:
|
|||||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||||
AstSenTree* sensesp = nodep->sensesp();
|
AstSenTree* sensesp = nodep->sensesp();
|
||||||
if (!sensesp) nodep->v3fatalSrc("NULL");
|
if (!sensesp) nodep->v3fatalSrc("NULL");
|
||||||
sensesp->sortSenses(); // Remove duplicate clocks and such
|
V3Const::constifyTreeExpensive(nodep); // Remove duplicate clocks and such
|
||||||
if (sensesp->sensesp() && sensesp->sensesp()->isNever()) {
|
if (sensesp->sensesp()
|
||||||
|
&& sensesp->sensesp()->castSenItem()
|
||||||
|
&& sensesp->sensesp()->castSenItem()->isNever()) {
|
||||||
// Never executing. Kill it.
|
// Never executing. Kill it.
|
||||||
if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
@@ -134,7 +147,6 @@ public:
|
|||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ActiveTopVisitor(AstNetlist* nodep) {
|
ActiveTopVisitor(AstNetlist* nodep) {
|
||||||
m_topscopep = NULL;
|
m_topscopep = NULL;
|
||||||
AstNode::userClearTree();
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~ActiveTopVisitor() {}
|
virtual ~ActiveTopVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+35
-15
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Collect and print statistics
|
// DESCRIPTION: Verilator: Collect and print statistics
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -41,9 +41,11 @@ private:
|
|||||||
// NODE STATE/TYPES
|
// NODE STATE/TYPES
|
||||||
// Cleared on netlist
|
// Cleared on netlist
|
||||||
// AstNode::user() -> bool. True if processed
|
// AstNode::user() -> bool. True if processed
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstModule* m_modp; // Last module
|
AstModule* m_modp; // Last module
|
||||||
|
AstBegin* m_beginp; // Last begin
|
||||||
V3Double0 m_statAsCover; // Statistic tracking
|
V3Double0 m_statAsCover; // Statistic tracking
|
||||||
V3Double0 m_statAsPsl; // Statistic tracking
|
V3Double0 m_statAsPsl; // Statistic tracking
|
||||||
V3Double0 m_statAsFull; // Statistic tracking
|
V3Double0 m_statAsFull; // Statistic tracking
|
||||||
@@ -63,7 +65,9 @@ private:
|
|||||||
AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack();
|
AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack();
|
||||||
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
||||||
nodep->exprsp(timesp);
|
nodep->exprsp(timesp);
|
||||||
if (!nodep->scopeNamep() && nodep->name().find("%m") != string::npos) {
|
if (!nodep->scopeNamep()
|
||||||
|
&& (nodep->name().find("%m") != string::npos
|
||||||
|
|| nodep->name().find("%M") != string::npos)) {
|
||||||
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,19 +105,21 @@ private:
|
|||||||
return bodysp;
|
return bodysp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) {
|
void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep,
|
||||||
|
AstNode* stmtsp, const string& message) {
|
||||||
propp->unlinkFrBack();
|
propp->unlinkFrBack();
|
||||||
sentreep->unlinkFrBack();
|
sentreep->unlinkFrBack();
|
||||||
|
if (stmtsp) stmtsp->unlinkFrBack();
|
||||||
//
|
//
|
||||||
AstNode* bodysp = NULL;
|
AstNode* bodysp = NULL;
|
||||||
bool selfDestruct = false;
|
bool selfDestruct = false;
|
||||||
if (AstPslCover* snodep = nodep->castPslCover()) {
|
if (AstPslCover* snodep = nodep->castPslCover()) {
|
||||||
if (!v3Global.opt.coverageUser()) {
|
if (!v3Global.opt.coverageUser()) {
|
||||||
selfDestruct = true;
|
selfDestruct = true;
|
||||||
} else {
|
} else {
|
||||||
// V3Coverage assigned us a bucket to increment.
|
// V3Coverage assigned us a bucket to increment.
|
||||||
AstCoverInc* covincp = snodep->coverincp()->castCoverInc();
|
AstCoverInc* covincp = snodep->coverincp()->castCoverInc();
|
||||||
if (!covincp) snodep->v3fatalSrc("Missing coverage in PSL");
|
if (!covincp) snodep->v3fatalSrc("Missing AstCoverInc under assertion");
|
||||||
covincp->unlinkFrBack();
|
covincp->unlinkFrBack();
|
||||||
if (message!="") covincp->declp()->comment(message);
|
if (message!="") covincp->declp()->comment(message);
|
||||||
bodysp = covincp;
|
bodysp = covincp;
|
||||||
@@ -127,6 +133,7 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc("Unknown node type");
|
nodep->v3fatalSrc("Unknown node type");
|
||||||
}
|
}
|
||||||
|
if (stmtsp) bodysp = bodysp->addNext(stmtsp);
|
||||||
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
|
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
|
||||||
bodysp = ifp;
|
bodysp = ifp;
|
||||||
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
|
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
|
||||||
@@ -172,8 +179,8 @@ private:
|
|||||||
// VISITORS //========== Case assertions
|
// VISITORS //========== Case assertions
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->user()) {
|
if (!nodep->user1()) {
|
||||||
nodep->user(true);
|
nodep->user1(true);
|
||||||
bool has_default=false;
|
bool has_default=false;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
if (itemp->isDefault()) has_default=true;
|
if (itemp->isDefault()) has_default=true;
|
||||||
@@ -233,12 +240,15 @@ private:
|
|||||||
|
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||||
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
|
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
||||||
m_statAsCover++;
|
m_statAsCover++;
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
|
NULL, nodep->name()); nodep=NULL;
|
||||||
m_statAsPsl++;
|
m_statAsPsl++;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||||
@@ -254,6 +264,16 @@ private:
|
|||||||
// Reset defaults
|
// Reset defaults
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||||
|
// This code is needed rather than a visitor in V3Begin,
|
||||||
|
// because V3Assert is called before V3Begin
|
||||||
|
AstBegin* lastp = m_beginp;
|
||||||
|
{
|
||||||
|
m_beginp = nodep;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_beginp = lastp;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS //========== Temporal Layer
|
// VISITORS //========== Temporal Layer
|
||||||
|
|
||||||
@@ -269,9 +289,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AssertVisitor(AstNetlist* nodep) {
|
AssertVisitor(AstNetlist* nodep) {
|
||||||
|
m_beginp = NULL;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
// Process
|
// Process
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~AssertVisitor() {
|
virtual ~AssertVisitor() {
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Assertion expansion
|
// DESCRIPTION: Verilator: Assertion expansion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+51
-21
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Collect and print statistics
|
// DESCRIPTION: Verilator: Collect and print statistics
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -45,22 +45,33 @@ private:
|
|||||||
// NODE STATE/TYPES
|
// NODE STATE/TYPES
|
||||||
// STATE
|
// STATE
|
||||||
// Reset each module:
|
// Reset each module:
|
||||||
AstSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock)
|
AstNodeSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock)
|
||||||
// Reset each assertion:
|
// Reset each assertion:
|
||||||
AstSenItem* m_senip; // Last sensitivity
|
AstNodeSenItem* m_senip; // Last sensitivity
|
||||||
|
|
||||||
int debug() { return 0; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
AstSenTree* newSenTree(AstNode* nodep) {
|
AstSenTree* newSenTree(AstNode* nodep) {
|
||||||
// Create sentree based on clocked or default clock
|
// Create sentree based on clocked or default clock
|
||||||
// Return NULL for always
|
// Return NULL for always
|
||||||
AstSenTree* newp = NULL;
|
AstSenTree* newp = NULL;
|
||||||
AstSenItem* senip = m_senip ? m_senip : m_seniDefaultp;
|
AstNodeSenItem* senip = m_senip ? m_senip : m_seniDefaultp;
|
||||||
if (senip) newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
|
if (!senip) {
|
||||||
if (!senip) nodep->v3error("Unsupported: Unclocked assertion");
|
nodep->v3error("Unsupported: Unclocked assertion");
|
||||||
|
newp = new AstSenTree(nodep->fileline(), NULL);
|
||||||
|
} else {
|
||||||
|
newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
|
||||||
|
}
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
void clearAssertInfo() {
|
||||||
|
m_senip = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
// VISITORS //========== Statements
|
||||||
virtual void visit(AstPslDefClock* nodep, AstNUser*) {
|
virtual void visit(AstPslDefClock* nodep, AstNUser*) {
|
||||||
@@ -71,28 +82,47 @@ private:
|
|||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstClocking* nodep, AstNUser*) {
|
||||||
|
UINFO(8," CLOCKING"<<nodep<<endl);
|
||||||
|
// Store the new default clock, reset on new module
|
||||||
|
m_seniDefaultp = nodep->sensesp();
|
||||||
|
// Trash it, keeping children
|
||||||
|
if (nodep->bodysp()) {
|
||||||
|
nodep->replaceWith(nodep->bodysp()->unlinkFrBack());
|
||||||
|
} else {
|
||||||
|
nodep->unlinkFrBack();
|
||||||
|
}
|
||||||
|
pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||||
// Prep
|
if (nodep->sentreep()) return; // Already processed
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||||
// Prep
|
if (nodep->sentreep()) return; // Already processed
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_senip) {
|
if (m_senip) {
|
||||||
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion\n");
|
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion\n");
|
||||||
}
|
}
|
||||||
// Unlink and just keep a pointer to it, convert to sentree as needed
|
// Block is the new expression to evaluate
|
||||||
AstNode* blockp = nodep->propp()->unlinkFrBack();
|
AstNode* blockp = nodep->propp()->unlinkFrBack();
|
||||||
|
if (nodep->disablep()) {
|
||||||
|
blockp = new AstAnd(nodep->disablep()->fileline(),
|
||||||
|
new AstNot(nodep->disablep()->fileline(),
|
||||||
|
nodep->disablep()->unlinkFrBack()),
|
||||||
|
blockp);
|
||||||
|
}
|
||||||
|
// Unlink and just keep a pointer to it, convert to sentree as needed
|
||||||
m_senip = nodep->sensesp();
|
m_senip = nodep->sensesp();
|
||||||
nodep->replaceWith(blockp);
|
nodep->replaceWith(blockp);
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); nodep=NULL;
|
||||||
@@ -109,8 +139,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AssertPreVisitor(AstNetlist* nodep) {
|
AssertPreVisitor(AstNetlist* nodep) {
|
||||||
m_senip = NULL;
|
|
||||||
m_seniDefaultp = NULL;
|
m_seniDefaultp = NULL;
|
||||||
|
clearAssertInfo();
|
||||||
// Process
|
// Process
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Assertion pre-expansion
|
// DESCRIPTION: Verilator: Assertion pre-expansion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+142
-62
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structures
|
// DESCRIPTION: Verilator: Ast node structures
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -40,11 +40,15 @@ vluint64_t AstNode::s_editCntLast=0;
|
|||||||
// along with each userp, and thus by bumping this count we can make it look
|
// along with each userp, and thus by bumping this count we can make it look
|
||||||
// as if we iterated across the entire tree to set all the userp's to null.
|
// as if we iterated across the entire tree to set all the userp's to null.
|
||||||
int AstNode::s_cloneCntGbl=0;
|
int AstNode::s_cloneCntGbl=0;
|
||||||
int AstNode::s_userCntGbl=0;
|
uint32_t AstUser1InUse::s_userCntGbl=0; // Hot cache line, leave adjacent
|
||||||
int AstNode::s_user2CntGbl=0;
|
uint32_t AstUser2InUse::s_userCntGbl=0; // Hot cache line, leave adjacent
|
||||||
int AstNode::s_user3CntGbl=0;
|
uint32_t AstUser3InUse::s_userCntGbl=0; // Hot cache line, leave adjacent
|
||||||
int AstNode::s_user4CntGbl=0;
|
uint32_t AstUser4InUse::s_userCntGbl=0; // Hot cache line, leave adjacent
|
||||||
int AstNode::s_user5CntGbl=0;
|
|
||||||
|
bool AstUser1InUse::s_userBusy=false;
|
||||||
|
bool AstUser2InUse::s_userBusy=false;
|
||||||
|
bool AstUser3InUse::s_userBusy=false;
|
||||||
|
bool AstUser4InUse::s_userBusy=false;
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3AstType
|
// V3AstType
|
||||||
@@ -71,16 +75,49 @@ void AstNode::init() {
|
|||||||
m_signed = false;
|
m_signed = false;
|
||||||
m_width = 0;
|
m_width = 0;
|
||||||
m_widthMin = 0;
|
m_widthMin = 0;
|
||||||
m_userp = NULL;
|
m_user1p = NULL;
|
||||||
m_userCnt = 0;
|
m_user1Cnt = 0;
|
||||||
m_user2p = NULL;
|
m_user2p = NULL;
|
||||||
m_user2Cnt = 0;
|
m_user2Cnt = 0;
|
||||||
m_user3p = NULL;
|
m_user3p = NULL;
|
||||||
m_user3Cnt = 0;
|
m_user3Cnt = 0;
|
||||||
m_user4p = NULL;
|
m_user4p = NULL;
|
||||||
m_user4Cnt = 0;
|
m_user4Cnt = 0;
|
||||||
m_user5p = NULL;
|
}
|
||||||
m_user5Cnt = 0;
|
|
||||||
|
string AstNode::encodeName(const string& namein) {
|
||||||
|
// Encode signal name raw from parser, then not called again on same signal
|
||||||
|
const char* start = namein.c_str();
|
||||||
|
string out;
|
||||||
|
for (const char* pos = start; *pos; pos++) {
|
||||||
|
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers
|
||||||
|
: isalnum(pos[0])) {
|
||||||
|
out += pos[0];
|
||||||
|
} else if (pos[0]=='_') {
|
||||||
|
if (pos[1]=='_') {
|
||||||
|
out += "_"; out += "__05F"; // hex(_) = 0x5F
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
out += pos[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Need the leading 0 so this will never collide with
|
||||||
|
// a user identifier nor a temp we create in Verilator.
|
||||||
|
// We also do *NOT* use __DOT__ etc, as we search for those
|
||||||
|
// in some replacements, and don't want to mangle the user's names.
|
||||||
|
char hex[10]; sprintf(hex,"__0%02X",pos[0]);
|
||||||
|
out += hex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AstNode::encodeNumber(vlsint64_t num) {
|
||||||
|
if (num < 0) {
|
||||||
|
return "__02D"+cvtToStr(-num); // 2D=-
|
||||||
|
} else {
|
||||||
|
return cvtToStr(num);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstNode::shortName() const {
|
string AstNode::shortName() const {
|
||||||
@@ -103,18 +140,45 @@ string AstNode::dedotName(const string& namein) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string AstNode::prettyName(const string& namein) {
|
string AstNode::prettyName(const string& namein) {
|
||||||
string pretty = namein;
|
string pretty;
|
||||||
string::size_type pos;
|
pretty = "";
|
||||||
while ((pos=pretty.find("__BRA__")) != string::npos) {
|
for (const char* pos = namein.c_str(); *pos; ) {
|
||||||
pretty.replace(pos, 7, "[");
|
if (0==strncmp(pos,"__BRA__",7)) {
|
||||||
|
pretty += "[";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (0==strncmp(pos,"__KET__",7)) {
|
||||||
|
pretty += "]";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (0==strncmp(pos,"__DOT__",7)) {
|
||||||
|
pretty += ".";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (0==strncmp(pos,"__PVT__",7)) {
|
||||||
|
pretty += "";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0'
|
||||||
|
&& isxdigit(pos[3]) && isxdigit(pos[4])) {
|
||||||
|
char value = 0;
|
||||||
|
value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
|
||||||
|
value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10));
|
||||||
|
pretty += value;
|
||||||
|
pos += 5;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pretty += pos[0];
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while ((pos=pretty.find("__KET__")) != string::npos) {
|
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||||
pretty.replace(pos, 7, "]");
|
return pretty;
|
||||||
}
|
}
|
||||||
while ((pos=pretty.find("__PVT__")) != string::npos) {
|
|
||||||
pretty.replace(pos, 7, "");
|
string AstNode::prettyTypeName() const {
|
||||||
}
|
if (name()=="") return typeName();
|
||||||
return AstNode::dedotName(pretty);
|
return string(typeName())+" '"+prettyName()+"'";
|
||||||
}
|
}
|
||||||
|
|
||||||
int AstNode::widthPow2() const {
|
int AstNode::widthPow2() const {
|
||||||
@@ -238,8 +302,8 @@ void AstNode::addNextHere(AstNode* newp) {
|
|||||||
void AstNode::setOp1p(AstNode* newp) {
|
void AstNode::setOp1p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp1p\n");
|
UASSERT(newp,"Null item passed to setOp1p\n");
|
||||||
UDEBUGONLY(if (m_op1p) this->v3fatalSrc("Adding to non-empty, non-list op1"););
|
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_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1"););
|
||||||
this->debugTreeChange("-setOp1pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp1pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp1pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp1pNew: ", __LINE__, true);
|
||||||
m_op1p = newp;
|
m_op1p = newp;
|
||||||
@@ -251,8 +315,8 @@ void AstNode::setOp1p(AstNode* newp) {
|
|||||||
void AstNode::setOp2p(AstNode* newp) {
|
void AstNode::setOp2p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp2p\n");
|
UASSERT(newp,"Null item passed to setOp2p\n");
|
||||||
UDEBUGONLY(if (m_op2p) this->v3fatalSrc("Adding to non-empty, non-list op2"););
|
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_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2"););
|
||||||
this->debugTreeChange("-setOp2pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp2pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp2pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp2pNew: ", __LINE__, true);
|
||||||
m_op2p = newp;
|
m_op2p = newp;
|
||||||
@@ -264,8 +328,8 @@ void AstNode::setOp2p(AstNode* newp) {
|
|||||||
void AstNode::setOp3p(AstNode* newp) {
|
void AstNode::setOp3p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp3p\n");
|
UASSERT(newp,"Null item passed to setOp3p\n");
|
||||||
UDEBUGONLY(if (m_op3p) this->v3fatalSrc("Adding to non-empty, non-list op3"););
|
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_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3"););
|
||||||
this->debugTreeChange("-setOp3pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp3pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp3pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp3pNew: ", __LINE__, true);
|
||||||
m_op3p = newp;
|
m_op3p = newp;
|
||||||
@@ -277,8 +341,8 @@ void AstNode::setOp3p(AstNode* newp) {
|
|||||||
void AstNode::setOp4p(AstNode* newp) {
|
void AstNode::setOp4p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp4p\n");
|
UASSERT(newp,"Null item passed to setOp4p\n");
|
||||||
UDEBUGONLY(if (m_op4p) this->v3fatalSrc("Adding to non-empty, non-list op4"););
|
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_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4"););
|
||||||
this->debugTreeChange("-setOp4pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp4pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp4pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp4pNew: ", __LINE__, true);
|
||||||
m_op4p = newp;
|
m_op4p = newp;
|
||||||
@@ -614,11 +678,38 @@ void AstNode::operator delete(void* objp, size_t size) {
|
|||||||
// Iterators
|
// Iterators
|
||||||
|
|
||||||
void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateChildren(AstNVisitor& v, AstNUser* vup) {
|
||||||
|
// This is a very hot function
|
||||||
if (!this) return;
|
if (!this) return;
|
||||||
m_op1p->iterateAndNext(v, vup);
|
ASTNODE_PREFETCH(m_op1p);
|
||||||
m_op2p->iterateAndNext(v, vup);
|
ASTNODE_PREFETCH(m_op2p);
|
||||||
m_op3p->iterateAndNext(v, vup);
|
ASTNODE_PREFETCH(m_op3p);
|
||||||
m_op4p->iterateAndNext(v, vup);
|
ASTNODE_PREFETCH(m_op4p);
|
||||||
|
// if () not needed since iterateAndNext accepts null this, but faster with it.
|
||||||
|
if (m_op1p) m_op1p->iterateAndNext(v, vup);
|
||||||
|
if (m_op2p) m_op2p->iterateAndNext(v, vup);
|
||||||
|
if (m_op3p) m_op3p->iterateAndNext(v, vup);
|
||||||
|
if (m_op4p) m_op4p->iterateAndNext(v, vup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
||||||
|
// This is a very hot function
|
||||||
|
// IMPORTANT: If you replace a node that's the target of this iterator,
|
||||||
|
// then the NEW node will be iterated on next, it isn't skipped!
|
||||||
|
// if (!this) return; // Part of for()
|
||||||
|
for (AstNode* nodep=this; nodep;) {
|
||||||
|
AstNode* niterp = nodep;
|
||||||
|
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||||
|
niterp->m_iterpp = &niterp;
|
||||||
|
niterp->accept(v, vup);
|
||||||
|
// accept may do a replaceNode and change niterp on us...
|
||||||
|
if (!niterp) return;
|
||||||
|
niterp->m_iterpp = NULL;
|
||||||
|
if (niterp!=nodep) { // Edited it
|
||||||
|
nodep = niterp;
|
||||||
|
} else { // Same node, just loop
|
||||||
|
nodep = niterp->m_nextp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateListBackwards(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateListBackwards(AstNVisitor& v, AstNUser* vup) {
|
||||||
@@ -627,7 +718,7 @@ void AstNode::iterateListBackwards(AstNVisitor& v, AstNUser* vup) {
|
|||||||
while (nodep->m_nextp) nodep=nodep->m_nextp;
|
while (nodep->m_nextp) nodep=nodep->m_nextp;
|
||||||
while (nodep) {
|
while (nodep) {
|
||||||
// Edits not supported: nodep->m_iterpp = &nodep;
|
// Edits not supported: nodep->m_iterpp = &nodep;
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v, vup);
|
||||||
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
|
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
|
||||||
else nodep = NULL; // else: backp points up the tree.
|
else nodep = NULL; // else: backp points up the tree.
|
||||||
}
|
}
|
||||||
@@ -641,31 +732,12 @@ void AstNode::iterateChildrenBackwards(AstNVisitor& v, AstNUser* vup) {
|
|||||||
this->op4p()->iterateListBackwards(v,vup);
|
this->op4p()->iterateListBackwards(v,vup);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
|
||||||
// IMPORTANT: If you replace a node that's the target of this iterator,
|
|
||||||
// then the NEW node will be iterated on next, it isn't skipped!
|
|
||||||
// if (!this) return; // Part of for()
|
|
||||||
for (AstNode* nodep=this; nodep;) {
|
|
||||||
AstNode* niterp = nodep;
|
|
||||||
niterp->m_iterpp = &niterp;
|
|
||||||
niterp->accept(v, vup);
|
|
||||||
// accept may do a replaceNode and change niterp on us...
|
|
||||||
if (!niterp) return;
|
|
||||||
niterp->m_iterpp = NULL;
|
|
||||||
if (niterp!=nodep) { // Edited it
|
|
||||||
nodep = niterp;
|
|
||||||
} else { // Same node, just loop
|
|
||||||
nodep = niterp->m_nextp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
||||||
// Keep following the current list even if edits change it
|
// Keep following the current list even if edits change it
|
||||||
if (!this) return;
|
if (!this) return;
|
||||||
for (AstNode* nodep=this; nodep; ) {
|
for (AstNode* nodep=this; nodep; ) {
|
||||||
AstNode* nnextp = nodep->m_nextp;
|
AstNode* nnextp = nodep->m_nextp;
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v, vup);
|
||||||
nodep = nnextp;
|
nodep = nnextp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -730,6 +802,11 @@ void AstNode::checkTreeIter(AstNode* backp) {
|
|||||||
if (backp != this->backp()) {
|
if (backp != this->backp()) {
|
||||||
this->v3fatalSrc("Back node inconsistent");
|
this->v3fatalSrc("Back node inconsistent");
|
||||||
}
|
}
|
||||||
|
if (castNodeTermop() || castNodeVarRef()) {
|
||||||
|
// Termops have a short-circuited iterateChildren, so check usage
|
||||||
|
if (op1p()||op2p()||op3p()||op4p())
|
||||||
|
this->v3fatalSrc("Terminal operation with non-terminals");
|
||||||
|
}
|
||||||
if (op1p()) op1p()->checkTreeIterList(this);
|
if (op1p()) op1p()->checkTreeIterList(this);
|
||||||
if (op2p()) op2p()->checkTreeIterList(this);
|
if (op2p()) op2p()->checkTreeIterList(this);
|
||||||
if (op3p()) op3p()->checkTreeIterList(this);
|
if (op3p()) op3p()->checkTreeIterList(this);
|
||||||
@@ -772,7 +849,10 @@ void AstNode::dumpPtrs(ostream& os) {
|
|||||||
if (op2p()) os<<" op2p="<<(void*)op2p();
|
if (op2p()) os<<" op2p="<<(void*)op2p();
|
||||||
if (op3p()) os<<" op3p="<<(void*)op3p();
|
if (op3p()) os<<" op3p="<<(void*)op3p();
|
||||||
if (op4p()) os<<" op4p="<<(void*)op4p();
|
if (op4p()) os<<" op4p="<<(void*)op4p();
|
||||||
if (userp()) os<<" user="<<(void*)userp();
|
if (user1p()) os<<" user1p="<<(void*)user1p();
|
||||||
|
if (user2p()) os<<" user2p="<<(void*)user2p();
|
||||||
|
if (user3p()) os<<" user3p="<<(void*)user3p();
|
||||||
|
if (user4p()) os<<" user4p="<<(void*)user4p();
|
||||||
if (m_iterpp) {
|
if (m_iterpp) {
|
||||||
os<<" iterpp="<<(void*)m_iterpp;
|
os<<" iterpp="<<(void*)m_iterpp;
|
||||||
os<<"*="<<(void*)*m_iterpp;
|
os<<"*="<<(void*)*m_iterpp;
|
||||||
@@ -808,7 +888,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append) {
|
|||||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||||
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
||||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||||
if (editCountGbl()==editCountLast() && 1) { // Off, as messes up tree diffing
|
if (editCountGbl()==editCountLast()) {
|
||||||
*logsp<<endl;
|
*logsp<<endl;
|
||||||
*logsp<<"No changes since last dump!\n";
|
*logsp<<"No changes since last dump!\n";
|
||||||
} else {
|
} else {
|
||||||
@@ -827,7 +907,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append) {
|
|||||||
editCountSetLast();
|
editCountSetLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::v3errorEnd(ostringstream& str) {
|
void AstNode::v3errorEnd(ostringstream& str) const {
|
||||||
if (this && m_fileline) {
|
if (this && m_fileline) {
|
||||||
ostringstream nsstr;
|
ostringstream nsstr;
|
||||||
nsstr<<str.str();
|
nsstr<<str.str();
|
||||||
|
|||||||
+278
-132
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structure
|
// DESCRIPTION: Verilator: Ast node structure
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -40,10 +41,10 @@ public:
|
|||||||
// enum en {...};
|
// enum en {...};
|
||||||
// const char* ascii() const {...};
|
// const char* ascii() const {...};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstType () {};
|
inline AstType () {}
|
||||||
inline AstType (en _e) : m_e(_e) {};
|
inline AstType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstType lhs, AstType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstType lhs, AstType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstType lhs, AstType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstType lhs, AstType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -63,10 +64,10 @@ public:
|
|||||||
PUBLIC_TASK
|
PUBLIC_TASK
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstPragmaType () {};
|
inline AstPragmaType () {}
|
||||||
inline AstPragmaType (en _e) : m_e(_e) {};
|
inline AstPragmaType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstPragmaType lhs, AstPragmaType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstPragmaType lhs, AstPragmaType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstPragmaType lhs, AstPragmaType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstPragmaType lhs, AstPragmaType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -79,14 +80,21 @@ public:
|
|||||||
enum en {
|
enum en {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
TRACE_INIT,
|
TRACE_INIT,
|
||||||
|
TRACE_INIT_SUB,
|
||||||
TRACE_FULL,
|
TRACE_FULL,
|
||||||
TRACE_CHANGE
|
TRACE_FULL_SUB,
|
||||||
|
TRACE_CHANGE,
|
||||||
|
TRACE_CHANGE_SUB
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstCFuncType () {};
|
inline AstCFuncType () {}
|
||||||
inline AstCFuncType (en _e) : m_e(_e) {};
|
inline AstCFuncType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
|
// METHODS
|
||||||
|
bool isTrace() const { return (m_e==TRACE_INIT || m_e==TRACE_INIT_SUB
|
||||||
|
|| m_e==TRACE_FULL || m_e==TRACE_FULL_SUB
|
||||||
|
|| m_e==TRACE_CHANGE || m_e==TRACE_CHANGE_SUB); }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstCFuncType lhs, AstCFuncType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstCFuncType lhs, AstCFuncType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstCFuncType lhs, AstCFuncType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstCFuncType lhs, AstCFuncType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -98,7 +106,7 @@ class AstEdgeType {
|
|||||||
public:
|
public:
|
||||||
// REMEMBER to edit the strings below too
|
// REMEMBER to edit the strings below too
|
||||||
enum en {
|
enum en {
|
||||||
// These must be in general -> most specific order, as we sort by it in AstSenTree::sortSenses()
|
// These must be in general -> most specific order, as we sort by it in V3Const::visit AstSenTre
|
||||||
ILLEGAL,
|
ILLEGAL,
|
||||||
// Involving a variable
|
// Involving a variable
|
||||||
ANYEDGE, // Default for sensitivities; rip them out
|
ANYEDGE, // Default for sensitivities; rip them out
|
||||||
@@ -142,15 +150,15 @@ public:
|
|||||||
};
|
};
|
||||||
const char* verilogKwd() const {
|
const char* verilogKwd() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"%E-edge", "", "[both]", "posedge", "negedge", "[high]","[low]",
|
"%E-edge", "[any]", "[both]", "posedge", "negedge", "[high]","[low]",
|
||||||
"/*AS*/","[initial]","[settle]","[never]"
|
"*","[initial]","[settle]","[never]"
|
||||||
};
|
};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
};
|
||||||
inline AstEdgeType () {};
|
inline AstEdgeType () {}
|
||||||
inline AstEdgeType (en _e) : m_e(_e) {};
|
inline AstEdgeType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstEdgeType lhs, AstEdgeType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstEdgeType lhs, AstEdgeType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstEdgeType lhs, AstEdgeType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstEdgeType lhs, AstEdgeType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -161,16 +169,29 @@ public:
|
|||||||
class AstAttrType {
|
class AstAttrType {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
BITS,
|
BITS, // V3Const converts to constant
|
||||||
RANGE_LSB,
|
RANGE_LSB, // V3Const converts to constant
|
||||||
ARRAY_LSB,
|
ARRAY_LSB, // V3Const converts to constant
|
||||||
SCOPE_TEXT
|
//
|
||||||
|
VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked
|
||||||
|
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
|
||||||
|
VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic
|
||||||
|
VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic
|
||||||
|
VAR_ISOLATE_ASSIGNMENTS // V3LinkParse moves to AstVar::attrIsolateAssign
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstAttrType () {};
|
const char* ascii() const {
|
||||||
inline AstAttrType (en _e) : m_e(_e) {};
|
static const char* names[] = {
|
||||||
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {};
|
"BITS", "RANGE_LSB", "ARRAY_LSB",
|
||||||
operator en () const { return m_e; };
|
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_PUBLIC_FLAT",
|
||||||
|
"VAR_ISOLATE_ASSIGNMENTS"
|
||||||
|
};
|
||||||
|
return names[m_e];
|
||||||
|
};
|
||||||
|
inline AstAttrType () {}
|
||||||
|
inline AstAttrType (en _e) : m_e(_e) {}
|
||||||
|
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
|
operator en () const { return m_e; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstAttrType lhs, AstAttrType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstAttrType lhs, AstAttrType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstAttrType lhs, AstAttrType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstAttrType lhs, AstAttrType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -195,22 +216,24 @@ public:
|
|||||||
IMPLICIT,
|
IMPLICIT,
|
||||||
REG,
|
REG,
|
||||||
TRIWIRE,
|
TRIWIRE,
|
||||||
|
PORT, // Temp type used in parser only
|
||||||
BLOCKTEMP,
|
BLOCKTEMP,
|
||||||
MODULETEMP,
|
MODULETEMP,
|
||||||
STMTTEMP
|
STMTTEMP,
|
||||||
|
XTEMP
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstVarType () {};
|
inline AstVarType () {}
|
||||||
inline AstVarType (en _e) : m_e(_e) {};
|
inline AstVarType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"?","GPARAM","LPARAM","GENVAR",
|
"?","GPARAM","LPARAM","GENVAR",
|
||||||
"INTEGER","INPUT","OUTPUT","INOUT",
|
"INTEGER","INPUT","OUTPUT","INOUT",
|
||||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","REG","TRIWIRE",
|
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","REG","TRIWIRE","PORT",
|
||||||
"BLOCKTEMP","MODULETEMP","STMTTEMP"};
|
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
|
||||||
return names[m_e];};
|
return names[m_e]; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -229,10 +252,10 @@ public:
|
|||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
||||||
inline AstBranchPred () : m_e(UNKNOWN) {};
|
inline AstBranchPred () : m_e(UNKNOWN) {}
|
||||||
inline AstBranchPred (en _e) : m_e(_e) {};
|
inline AstBranchPred (en _e) : m_e(_e) {}
|
||||||
explicit inline AstBranchPred (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstBranchPred (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
AstBranchPred invert() const {
|
AstBranchPred invert() const {
|
||||||
if (m_e==UNLIKELY) return LIKELY;
|
if (m_e==UNLIKELY) return LIKELY;
|
||||||
else if (m_e==LIKELY) return UNLIKELY;
|
else if (m_e==LIKELY) return UNLIKELY;
|
||||||
@@ -241,7 +264,7 @@ public:
|
|||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"","VL_LIKELY","VL_UNLIKELY"};
|
"","VL_LIKELY","VL_UNLIKELY"};
|
||||||
return names[m_e];};
|
return names[m_e]; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstBranchPred lhs, AstBranchPred rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstBranchPred lhs, AstBranchPred rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstBranchPred lhs, AstBranchPred::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstBranchPred lhs, AstBranchPred::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -250,6 +273,25 @@ public:
|
|||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
|
class AstCaseType {
|
||||||
|
public:
|
||||||
|
enum en {
|
||||||
|
CASE,
|
||||||
|
CASEX,
|
||||||
|
CASEZ
|
||||||
|
};
|
||||||
|
enum en m_e;
|
||||||
|
inline AstCaseType () {}
|
||||||
|
inline AstCaseType (en _e) : m_e(_e) {}
|
||||||
|
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
|
operator en () const { return m_e; }
|
||||||
|
};
|
||||||
|
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
|
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
|
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); }
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
class AstDisplayType {
|
class AstDisplayType {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
@@ -261,16 +303,16 @@ public:
|
|||||||
FATAL
|
FATAL
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstDisplayType () {};
|
inline AstDisplayType () {}
|
||||||
inline AstDisplayType (en _e) : m_e(_e) {};
|
inline AstDisplayType (en _e) : m_e(_e) {}
|
||||||
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
bool addNewline() const { return m_e!=WRITE; }
|
bool addNewline() const { return m_e!=WRITE; }
|
||||||
bool needScopeTracking() const { return m_e!=DISPLAY && m_e!=WRITE; }
|
bool needScopeTracking() const { return m_e!=DISPLAY && m_e!=WRITE; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"display","write","info","error","warning","fatal"};
|
"display","write","info","error","warning","fatal"};
|
||||||
return names[m_e];};
|
return names[m_e]; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -289,14 +331,14 @@ public:
|
|||||||
_ENUM_END
|
_ENUM_END
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstParseRefExp() : m_e(NONE) {};
|
inline AstParseRefExp() : m_e(NONE) {}
|
||||||
inline AstParseRefExp (en _e) : m_e(_e) {};
|
inline AstParseRefExp (en _e) : m_e(_e) {}
|
||||||
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"","VAR_MEM","VAR_ANY","TASK","FUNC"};
|
"","VAR_MEM","VAR_ANY","TASK","FUNC"};
|
||||||
return names[m_e];};
|
return names[m_e]; }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstParseRefExp lhs, AstParseRefExp::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstParseRefExp lhs, AstParseRefExp::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -335,6 +377,83 @@ struct AstNUser {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// AstUserResource - Generic pointer base class for tracking usage of user()
|
||||||
|
//
|
||||||
|
// Where AstNode->user2() is going to be used, for example, you write:
|
||||||
|
//
|
||||||
|
// AstUser2InUse m_userres;
|
||||||
|
//
|
||||||
|
// This will clear the tree, and prevent another visitor from clobering
|
||||||
|
// user2. When the member goes out of scope it will be automagically
|
||||||
|
// freed up.
|
||||||
|
|
||||||
|
class AstUserInUseBase {
|
||||||
|
protected:
|
||||||
|
static void allocate(uint32_t& cntGblRef, bool& userBusyRef) {
|
||||||
|
// Perhaps there's still a AstUserInUse in scope for this?
|
||||||
|
UASSERT_STATIC(!userBusyRef, "Conflicting user use; AstUser*InUse request when under another AstUserInUse");
|
||||||
|
userBusyRef = true;
|
||||||
|
clearcnt(cntGblRef, userBusyRef);
|
||||||
|
}
|
||||||
|
static void free(uint32_t& cntGblRef, bool& userBusyRef) {
|
||||||
|
UASSERT_STATIC(userBusyRef, "Free of User*() not under AstUserInUse");
|
||||||
|
clearcnt(cntGblRef, userBusyRef); // Includes a checkUse for us
|
||||||
|
userBusyRef = false;
|
||||||
|
}
|
||||||
|
static void clearcnt(uint32_t& cntGblRef, bool& userBusyRef) {
|
||||||
|
UASSERT_STATIC(userBusyRef, "Clear of User*() not under AstUserInUse");
|
||||||
|
// If this really fires and is real (after 2^32 edits???)
|
||||||
|
// we could just walk the tree and clear manually
|
||||||
|
++cntGblRef;
|
||||||
|
UASSERT_STATIC(cntGblRef, "User*() overflowed!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// For each user() declare the in use structure
|
||||||
|
// We let AstNode peek into here, because when under low optimization even
|
||||||
|
// an accessor would be way too slow.
|
||||||
|
class AstUser1InUse : AstUserInUseBase {
|
||||||
|
protected:
|
||||||
|
friend class AstNode;
|
||||||
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
||||||
|
static bool s_userBusy; // Count is in use
|
||||||
|
public:
|
||||||
|
AstUser1InUse() { allocate(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
~AstUser1InUse() { free (s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
static void clear() { clearcnt(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
};
|
||||||
|
class AstUser2InUse : AstUserInUseBase {
|
||||||
|
protected:
|
||||||
|
friend class AstNode;
|
||||||
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
||||||
|
static bool s_userBusy; // Count is in use
|
||||||
|
public:
|
||||||
|
AstUser2InUse() { allocate(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
~AstUser2InUse() { free (s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
static void clear() { clearcnt(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
};
|
||||||
|
class AstUser3InUse : AstUserInUseBase {
|
||||||
|
protected:
|
||||||
|
friend class AstNode;
|
||||||
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
||||||
|
static bool s_userBusy; // Count is in use
|
||||||
|
public:
|
||||||
|
AstUser3InUse() { allocate(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
~AstUser3InUse() { free (s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
static void clear() { clearcnt(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
};
|
||||||
|
class AstUser4InUse : AstUserInUseBase {
|
||||||
|
protected:
|
||||||
|
friend class AstNode;
|
||||||
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
||||||
|
static bool s_userBusy; // Count is in use
|
||||||
|
public:
|
||||||
|
AstUser4InUse() { allocate(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
~AstUser4InUse() { free (s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
static void clear() { clearcnt(s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// AstNVisitor -- Allows new functions to be called on each node
|
// AstNVisitor -- Allows new functions to be called on each node
|
||||||
// type without changing the base classes. See "Modern C++ Design".
|
// type without changing the base classes. See "Modern C++ Design".
|
||||||
@@ -401,8 +520,9 @@ public:
|
|||||||
uint32_t depth() const { return (m_both >> 24) & 255; }
|
uint32_t depth() const { return (m_both >> 24) & 255; }
|
||||||
uint32_t hshval() const { return m_both & M24; }
|
uint32_t hshval() const { return m_both & M24; }
|
||||||
// OPERATORS
|
// OPERATORS
|
||||||
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; };
|
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
|
// CREATORS
|
||||||
class Illegal {}; // for creator type-overload selection
|
class Illegal {}; // for creator type-overload selection
|
||||||
class FullValue {}; // for creator type-overload selection
|
class FullValue {}; // for creator type-overload selection
|
||||||
@@ -415,13 +535,7 @@ public:
|
|||||||
// Creating from raw data (sameHash functions)
|
// Creating from raw data (sameHash functions)
|
||||||
V3Hash() { setBoth(1,0); }
|
V3Hash() { setBoth(1,0); }
|
||||||
V3Hash(uint32_t val) { setBoth(1,val); }
|
V3Hash(uint32_t val) { setBoth(1,val); }
|
||||||
V3Hash(void* vp) {
|
V3Hash(void* vp) { setBoth(1,cvtToHash(vp)); }
|
||||||
// It's just a hash, so we can shove a 64 bit pointer into a 32 bit bucket
|
|
||||||
// On 32 bit systems, lower is always 0, but who cares?
|
|
||||||
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
|
|
||||||
u.l.upper=0; u.l.lower=0; u.up=vp;
|
|
||||||
setBoth(1,u.l.upper^u.l.lower);
|
|
||||||
}
|
|
||||||
V3Hash(const string& name);
|
V3Hash(const string& name);
|
||||||
V3Hash(V3Hash lh, V3Hash rh) {
|
V3Hash(V3Hash lh, V3Hash rh) {
|
||||||
setBoth(1,lh.hshval()*31+rh.hshval());
|
setBoth(1,lh.hshval()*31+rh.hshval());
|
||||||
@@ -432,45 +546,46 @@ ostream& operator<<(ostream& os, V3Hash rhs);
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
// AstNode -- Base type of all Ast types
|
// AstNode -- Base type of all Ast types
|
||||||
|
|
||||||
|
// Prefetch a node.
|
||||||
|
// The if() makes it faster, even though prefetch won't fault on null pointers
|
||||||
|
#define ASTNODE_PREFETCH(nodep) \
|
||||||
|
{ if (nodep) { VL_PREFETCH_RD(&(nodep->m_nextp)); VL_PREFETCH_RD(&(nodep->m_iterpp)); }}
|
||||||
|
|
||||||
class AstNode {
|
class AstNode {
|
||||||
private:
|
// v ASTNODE_PREFETCH depends on below ordering of members
|
||||||
AstNode* m_nextp; // Next peer in the parent's list
|
AstNode* m_nextp; // Next peer in the parent's list
|
||||||
AstNode* m_backp; // Node that points to this one (via next/op1/op2/...)
|
AstNode* m_backp; // Node that points to this one (via next/op1/op2/...)
|
||||||
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
|
|
||||||
AstNode* m_op1p; // Generic pointer 1
|
AstNode* m_op1p; // Generic pointer 1
|
||||||
AstNode* m_op2p; // Generic pointer 2
|
AstNode* m_op2p; // Generic pointer 2
|
||||||
AstNode* m_op3p; // Generic pointer 3
|
AstNode* m_op3p; // Generic pointer 3
|
||||||
AstNode* m_op4p; // Generic pointer 4
|
AstNode* m_op4p; // Generic pointer 4
|
||||||
AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node.
|
AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node.
|
||||||
|
// ^ ASTNODE_PREFETCH depends on above ordering of members
|
||||||
|
|
||||||
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
|
||||||
int m_cloneCnt; // Mark of when userp was set
|
|
||||||
static int s_cloneCntGbl; // Count of which userp is set
|
|
||||||
|
|
||||||
FileLine* m_fileline; // Where it was declared
|
FileLine* m_fileline; // Where it was declared
|
||||||
vluint64_t m_editCount; // When it was last edited
|
vluint64_t m_editCount; // When it was last edited
|
||||||
static vluint64_t s_editCntGbl; // Global edit counter
|
static vluint64_t s_editCntGbl; // Global edit counter
|
||||||
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
||||||
|
|
||||||
|
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
||||||
|
int m_cloneCnt; // Mark of when userp was set
|
||||||
|
static int s_cloneCntGbl; // Count of which userp is set
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
bool m_signed; // Node is signed
|
bool m_signed; // Node is signed
|
||||||
int m_width; // Bit width of operation
|
int m_width; // Bit width of operation
|
||||||
int m_widthMin; // If unsized, bitwidth of minimum implementation
|
int m_widthMin; // If unsized, bitwidth of minimum implementation
|
||||||
AstNUser* m_userp; // Pointer to any information the user iteration routine wants
|
// This member ordering both allows 64 bit alignment and puts associated data together
|
||||||
int m_userCnt; // Mark of when userp was set
|
AstNUser* m_user1p; // Pointer to any information the user iteration routine wants
|
||||||
static int s_userCntGbl; // Count of which userp is set
|
uint32_t m_user1Cnt; // Mark of when userp was set
|
||||||
|
uint32_t m_user2Cnt; // Mark of when userp was set
|
||||||
AstNUser* m_user2p; // Pointer to any information the user iteration routine wants
|
AstNUser* m_user2p; // Pointer to any information the user iteration routine wants
|
||||||
int m_user2Cnt; // Mark of when userp was set
|
|
||||||
static int s_user2CntGbl; // Count of which userp is set
|
|
||||||
AstNUser* m_user3p; // Pointer to any information the user iteration routine wants
|
AstNUser* m_user3p; // Pointer to any information the user iteration routine wants
|
||||||
int m_user3Cnt; // Mark of when userp was set
|
uint32_t m_user3Cnt; // Mark of when userp was set
|
||||||
static int s_user3CntGbl; // Count of which userp is set
|
uint32_t m_user4Cnt; // Mark of when userp was set
|
||||||
AstNUser* m_user4p; // Pointer to any information the user iteration routine wants
|
AstNUser* m_user4p; // Pointer to any information the user iteration routine wants
|
||||||
int m_user4Cnt; // Mark of when userp was set
|
|
||||||
static int s_user4CntGbl; // Count of which userp is set
|
|
||||||
AstNUser* m_user5p; // Pointer to any information the user iteration routine wants
|
|
||||||
int m_user5Cnt; // Mark of when userp was set
|
|
||||||
static int s_user5CntGbl; // Count of which userp is set
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void op1p(AstNode* nodep) { m_op1p = nodep; if (nodep) nodep->m_backp = this; }
|
void op1p(AstNode* nodep) { m_op1p = nodep; if (nodep) nodep->m_backp = this; }
|
||||||
@@ -494,7 +609,7 @@ protected:
|
|||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
AstNode() {init(); }
|
AstNode() {init(); }
|
||||||
AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
|
AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
|
||||||
virtual AstNode* clone() = 0; // Generally, cloneTree/cloneNode is what you want
|
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
||||||
virtual void cloneRelink() {}
|
virtual void cloneRelink() {}
|
||||||
void cloneRelinkTree();
|
void cloneRelinkTree();
|
||||||
|
|
||||||
@@ -525,7 +640,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
virtual AstType type() const = 0;
|
virtual AstType type() const = 0;
|
||||||
const char* typeName() const { return type().ascii(); }
|
const char* typeName() const { return type().ascii(); } // See also prettyTypeName
|
||||||
AstNode* nextp() const { return m_nextp; }
|
AstNode* nextp() const { return m_nextp; }
|
||||||
AstNode* backp() const { return m_backp; }
|
AstNode* backp() const { return m_backp; }
|
||||||
AstNode* op1p() const { return m_op1p; }
|
AstNode* op1p() const { return m_op1p; }
|
||||||
@@ -554,11 +669,15 @@ public:
|
|||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
virtual string name() const { return ""; }
|
virtual string name() const { return ""; }
|
||||||
|
virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); }
|
||||||
virtual string verilogKwd() const { return ""; }
|
virtual string verilogKwd() const { return ""; }
|
||||||
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
||||||
static string dedotName(const string& namein); // Name with dots removed
|
static string dedotName(const string& namein); // Name with dots removed
|
||||||
static string prettyName(const string& namein); // Name for printing out to the user
|
static string prettyName(const string& namein); // Name for printing out to the user
|
||||||
|
static string encodeName(const string& namein); // Encode user name into internal C representation
|
||||||
|
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
|
||||||
string prettyName() const { return prettyName(name()); }
|
string prettyName() const { return prettyName(name()); }
|
||||||
|
string prettyTypeName() const; // "VARREF name" for error messages
|
||||||
FileLine* fileline() const { return m_fileline; }
|
FileLine* fileline() const { return m_fileline; }
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
bool width1() const { return width()==1; }
|
bool width1() const { return width()==1; }
|
||||||
@@ -576,34 +695,42 @@ public:
|
|||||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||||
|
|
||||||
int user() const { return userp()->castInt(); }
|
AstNUser* user1p() const {
|
||||||
AstNUser* userp() const { return ((m_userCnt==s_userCntGbl)?m_userp:NULL); }
|
// Slows things down measurably, so disabled by default
|
||||||
void userp(void* userp) { m_userp=(AstNUser*)(userp); m_userCnt=s_userCntGbl; }
|
//UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy");
|
||||||
void user(int val) { userp(AstNUser::fromInt(val)); }
|
return ((m_user1Cnt==AstUser1InUse::s_userCntGbl)?m_user1p:NULL);
|
||||||
static void userClearTree() { s_userCntGbl++; UASSERT_STATIC(s_userCntGbl,"Rollover"); } // Clear userp()'s across the entire tree
|
}
|
||||||
|
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
||||||
|
int user1() const { return user1p()->castInt(); }
|
||||||
|
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
||||||
|
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
|
AstNUser* user2p() const {
|
||||||
|
//UASSERT_STATIC(AstUser2InUse::s_userBusy, "user2p set w/o busy");
|
||||||
|
return ((m_user2Cnt==AstUser2InUse::s_userCntGbl)?m_user2p:NULL); }
|
||||||
|
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
||||||
int user2() const { return user2p()->castInt(); }
|
int user2() const { return user2p()->castInt(); }
|
||||||
AstNUser* user2p() const { return ((m_user2Cnt==s_user2CntGbl)?m_user2p:NULL); }
|
|
||||||
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=s_user2CntGbl; }
|
|
||||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
||||||
static void user2ClearTree() { s_user2CntGbl++; } // Clear userp()'s across the entire tree
|
static void user2ClearTree() { AstUser2InUse::clear(); }
|
||||||
|
|
||||||
|
AstNUser* user3p() const {
|
||||||
|
//UASSERT_STATIC(AstUser3InUse::s_userBusy, "user3p set w/o busy");
|
||||||
|
return ((m_user3Cnt==AstUser3InUse::s_userCntGbl)?m_user3p:NULL); }
|
||||||
|
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
||||||
int user3() const { return user3p()->castInt(); }
|
int user3() const { return user3p()->castInt(); }
|
||||||
AstNUser* user3p() const { return ((m_user3Cnt==s_user3CntGbl)?m_user3p:NULL); }
|
|
||||||
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=s_user3CntGbl; }
|
|
||||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
||||||
static void user3ClearTree() { s_user3CntGbl++; } // Clear userp()'s across the entire tree
|
static void user3ClearTree() { AstUser3InUse::clear(); }
|
||||||
|
|
||||||
|
AstNUser* user4p() const {
|
||||||
|
//UASSERT_STATIC(AstUser4InUse::s_userBusy, "user4p set w/o busy");
|
||||||
|
return ((m_user4Cnt==AstUser4InUse::s_userCntGbl)?m_user4p:NULL); }
|
||||||
|
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
||||||
int user4() const { return user4p()->castInt(); }
|
int user4() const { return user4p()->castInt(); }
|
||||||
AstNUser* user4p() const { return ((m_user4Cnt==s_user4CntGbl)?m_user4p:NULL); }
|
|
||||||
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=s_user4CntGbl; }
|
|
||||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
||||||
static void user4ClearTree() { s_user4CntGbl++; } // Clear userp()'s across the entire tree
|
static void user4ClearTree() { AstUser4InUse::clear(); }
|
||||||
int user5() const { return user5p()->castInt(); }
|
|
||||||
AstNUser* user5p() const { return ((m_user5Cnt==s_user5CntGbl)?m_user5p:NULL); }
|
|
||||||
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=s_user5CntGbl; }
|
|
||||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
|
||||||
static void user5ClearTree() { s_user5CntGbl++; } // Clear userp()'s across the entire tree
|
|
||||||
|
|
||||||
vluint64_t editCount() const { return m_editCount; }
|
vluint64_t editCount() const { return m_editCount; }
|
||||||
void editCountInc() { m_editCount = s_editCntGbl++; }
|
void editCountInc() { m_editCount = ++s_editCntGbl; }
|
||||||
static vluint64_t editCountLast() { return s_editCntLast; }
|
static vluint64_t editCountLast() { return s_editCntLast; }
|
||||||
static vluint64_t editCountGbl() { return s_editCntGbl; }
|
static vluint64_t editCountGbl() { return s_editCntGbl; }
|
||||||
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
||||||
@@ -621,7 +748,7 @@ public:
|
|||||||
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK
|
AstNode* addNextNull(AstNode* newp); // Returns this, adds to end of list, NULL is OK
|
||||||
void addNextHere(AstNode* newp); // Adds after speced node
|
void addNextHere(AstNode* newp); // Adds after speced node
|
||||||
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
||||||
void v3errorEnd(ostringstream& str);
|
void v3errorEnd(ostringstream& str) const;
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it.
|
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
|
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node
|
||||||
@@ -650,7 +777,6 @@ public:
|
|||||||
virtual bool same(AstNode* otherp) const { return true; }
|
virtual bool same(AstNode* otherp) const { return true; }
|
||||||
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||||
virtual bool broken() const { return false; }
|
virtual bool broken() const { return false; }
|
||||||
virtual bool emitWordForm() { return false; }
|
|
||||||
|
|
||||||
// INVOKERS
|
// INVOKERS
|
||||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
||||||
@@ -674,14 +800,18 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
//=== AstNode* : Derived generic node types
|
//=== AstNode* : Derived generic node types
|
||||||
|
|
||||||
|
#define ASTNODE_BASE_FUNCS(name) \
|
||||||
|
virtual ~Ast ##name() {} \
|
||||||
|
Ast ##name * cloneTree(bool cloneNext) { return AstNode::cloneTree(cloneNext)->cast ##name(); }
|
||||||
|
|
||||||
struct AstNodeMath : public AstNode {
|
struct AstNodeMath : public AstNode {
|
||||||
// Math -- anything that's part of an expression tree
|
// Math -- anything that's part of an expression tree
|
||||||
AstNodeMath(FileLine* fl)
|
AstNodeMath(FileLine* fl)
|
||||||
: AstNode(fl) {}
|
: AstNode(fl) {}
|
||||||
virtual ~AstNodeMath() {}
|
ASTNODE_BASE_FUNCS(NodeMath)
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
||||||
virtual string emitOperator() = 0;
|
virtual string emitC() = 0;
|
||||||
virtual string emitSimpleOperator() { return ""; }
|
virtual string emitSimpleOperator() { return ""; }
|
||||||
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
||||||
};
|
};
|
||||||
@@ -690,7 +820,10 @@ struct AstNodeTermop : public AstNodeMath {
|
|||||||
// Terminal operator -- a operator with no "inputs"
|
// Terminal operator -- a operator with no "inputs"
|
||||||
AstNodeTermop(FileLine* fl)
|
AstNodeTermop(FileLine* fl)
|
||||||
: AstNodeMath(fl) {}
|
: AstNodeMath(fl) {}
|
||||||
virtual ~AstNodeTermop() {}
|
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||||
|
// Know no children, and hot function, so skip iterator for speed
|
||||||
|
// See checkTreeIter also that asserts no children
|
||||||
|
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNodeUniop : public AstNodeMath {
|
struct AstNodeUniop : public AstNodeMath {
|
||||||
@@ -699,7 +832,7 @@ struct AstNodeUniop : public AstNodeMath {
|
|||||||
: AstNodeMath(fl) {
|
: AstNodeMath(fl) {
|
||||||
if (lhsp) widthSignedFrom(lhsp);
|
if (lhsp) widthSignedFrom(lhsp);
|
||||||
setOp1p(lhsp); }
|
setOp1p(lhsp); }
|
||||||
virtual ~AstNodeUniop() {}
|
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
||||||
@@ -715,7 +848,7 @@ struct AstNodeBiop : public AstNodeMath {
|
|||||||
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||||
: AstNodeMath(fl) {
|
: AstNodeMath(fl) {
|
||||||
setOp1p(lhs); setOp2p(rhs); }
|
setOp1p(lhs); setOp2p(rhs); }
|
||||||
virtual ~AstNodeBiop() {}
|
ASTNODE_BASE_FUNCS(NodeBiop)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
AstNode* rhsp() const { return op2p()->castNode(); }
|
||||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||||
@@ -737,7 +870,7 @@ struct AstNodeTriop : public AstNodeMath {
|
|||||||
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||||
: AstNodeMath(fl) {
|
: AstNodeMath(fl) {
|
||||||
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
||||||
virtual ~AstNodeTriop() {}
|
ASTNODE_BASE_FUNCS(NodeTriop)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
AstNode* rhsp() const { return op2p()->castNode(); }
|
||||||
AstNode* thsp() const { return op3p()->castNode(); }
|
AstNode* thsp() const { return op3p()->castNode(); }
|
||||||
@@ -761,14 +894,14 @@ struct AstNodeBiCom : public AstNodeBiop {
|
|||||||
// Binary math with commutative properties
|
// Binary math with commutative properties
|
||||||
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||||
: AstNodeBiop(fl, lhs, rhs) {}
|
: AstNodeBiop(fl, lhs, rhs) {}
|
||||||
virtual ~AstNodeBiCom() {}
|
ASTNODE_BASE_FUNCS(NodeBiCom)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNodeBiComAsv : public AstNodeBiCom {
|
struct AstNodeBiComAsv : public AstNodeBiCom {
|
||||||
// Binary math with commutative & associative properties
|
// Binary math with commutative & associative properties
|
||||||
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
||||||
: AstNodeBiCom(fl, lhs, rhs) {}
|
: AstNodeBiCom(fl, lhs, rhs) {}
|
||||||
virtual ~AstNodeBiComAsv() {}
|
ASTNODE_BASE_FUNCS(NodeBiComAsv)
|
||||||
};
|
};
|
||||||
struct AstNodeCond : public AstNodeTriop {
|
struct AstNodeCond : public AstNodeTriop {
|
||||||
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||||
@@ -776,14 +909,14 @@ struct AstNodeCond : public AstNodeTriop {
|
|||||||
if (expr1p) widthSignedFrom(expr1p);
|
if (expr1p) widthSignedFrom(expr1p);
|
||||||
else if (expr2p) widthSignedFrom(expr2p);
|
else if (expr2p) widthSignedFrom(expr2p);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeCond() {}
|
ASTNODE_BASE_FUNCS(NodeCond)
|
||||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
||||||
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
|
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
|
||||||
AstNode* condp() const { return op1p()->castNode(); } // op1 = Condition
|
AstNode* condp() const { return op1p()->castNode(); } // op1 = Condition
|
||||||
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
|
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
|
||||||
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
|
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
|
||||||
virtual string emitVerilog() { return "%k(%l %k? %r %k: %t)"; }
|
virtual string emitVerilog() { return "%k(%l %k? %r %k: %t)"; }
|
||||||
virtual string emitOperator() { return "VL_COND"; }
|
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
||||||
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
||||||
virtual bool cleanLhs() { return true; }
|
virtual bool cleanLhs() { return true; }
|
||||||
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
|
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
|
||||||
@@ -797,7 +930,7 @@ struct AstNodePreSel : public AstNode {
|
|||||||
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
||||||
: AstNode(fl) {
|
: AstNode(fl) {
|
||||||
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
||||||
virtual ~AstNodePreSel() {}
|
ASTNODE_BASE_FUNCS(NodePreSel)
|
||||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||||
AstNode* rhsp() const { return op2p()->castNode(); }
|
AstNode* rhsp() const { return op2p()->castNode(); }
|
||||||
AstNode* thsp() const { return op3p()->castNode(); }
|
AstNode* thsp() const { return op3p()->castNode(); }
|
||||||
@@ -813,7 +946,7 @@ struct AstNodeStmt : public AstNode {
|
|||||||
// Statement -- anything that's directly under a function
|
// Statement -- anything that's directly under a function
|
||||||
AstNodeStmt(FileLine* fl)
|
AstNodeStmt(FileLine* fl)
|
||||||
: AstNode(fl) {}
|
: AstNode(fl) {}
|
||||||
virtual ~AstNodeStmt() {}
|
ASTNODE_BASE_FUNCS(NodeStmt)
|
||||||
// METHODS
|
// METHODS
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -823,7 +956,7 @@ struct AstNodeAssign : public AstNodeStmt {
|
|||||||
setOp1p(rhsp); setOp2p(lhsp);
|
setOp1p(rhsp); setOp2p(lhsp);
|
||||||
if (lhsp) widthSignedFrom(lhsp);
|
if (lhsp) widthSignedFrom(lhsp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeAssign() {}
|
ASTNODE_BASE_FUNCS(NodeAssign)
|
||||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
||||||
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
|
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
|
||||||
AstNode* rhsp() const { return op1p()->castNode(); } // op1 = Assign from
|
AstNode* rhsp() const { return op1p()->castNode(); } // op1 = Assign from
|
||||||
@@ -842,13 +975,12 @@ struct AstNodeFor : public AstNodeStmt {
|
|||||||
: AstNodeStmt(fileline) {
|
: AstNodeStmt(fileline) {
|
||||||
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
|
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeFor() {}
|
ASTNODE_BASE_FUNCS(NodeFor)
|
||||||
AstNode* initsp() const { return op1p()->castNode(); } // op1= initial statements
|
AstNode* initsp() const { return op1p()->castNode(); } // op1= initial statements
|
||||||
AstNode* condp() const { return op2p()->castNode(); } // op2= condition to continue
|
AstNode* condp() const { return op2p()->castNode(); } // op2= condition to continue
|
||||||
AstNode* incsp() const { return op3p()->castNode(); } // op3= increment statements
|
AstNode* incsp() const { return op3p()->castNode(); } // op3= increment statements
|
||||||
AstNode* bodysp() const { return op4p()->castNode(); } // op4= body of loop
|
AstNode* bodysp() const { return op4p()->castNode(); } // op4= body of loop
|
||||||
virtual bool isGateOptimizable() const { return false; }
|
virtual bool isGateOptimizable() const { return false; }
|
||||||
virtual bool isPredictOptimizable() const { return false; }
|
|
||||||
virtual int instrCount() const { return instrCountBranch(); }
|
virtual int instrCount() const { return instrCountBranch(); }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
virtual bool same(AstNode* samep) const { return true; }
|
virtual bool same(AstNode* samep) const { return true; }
|
||||||
@@ -862,7 +994,7 @@ public:
|
|||||||
: AstNodeStmt(fl) {
|
: AstNodeStmt(fl) {
|
||||||
setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp);
|
setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeIf() {}
|
ASTNODE_BASE_FUNCS(NodeIf)
|
||||||
AstNode* condp() const { return op1p(); } // op1 = condition
|
AstNode* condp() const { return op1p(); } // op1 = condition
|
||||||
AstNode* ifsp() const { return op2p(); } // op2 = list of true statements
|
AstNode* ifsp() const { return op2p(); } // op2 = list of true statements
|
||||||
AstNode* elsesp() const { return op3p(); } // op3 = list of false statements
|
AstNode* elsesp() const { return op3p(); } // op3 = list of false statements
|
||||||
@@ -882,7 +1014,7 @@ struct AstNodeCase : public AstNodeStmt {
|
|||||||
: AstNodeStmt(fl) {
|
: AstNodeStmt(fl) {
|
||||||
setOp1p(exprp); addNOp2p(casesp);
|
setOp1p(exprp); addNOp2p(casesp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeCase() {}
|
ASTNODE_BASE_FUNCS(NodeCase)
|
||||||
virtual int instrCount() const { return instrCountBranch(); }
|
virtual int instrCount() const { return instrCountBranch(); }
|
||||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = case condition <expression>
|
AstNode* exprp() const { return op1p()->castNode(); } // op1 = case condition <expression>
|
||||||
AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions
|
AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions
|
||||||
@@ -891,8 +1023,19 @@ struct AstNodeCase : public AstNodeStmt {
|
|||||||
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstNodeSenItem : public AstNode {
|
||||||
|
// An AstSenItem or AstSenGate
|
||||||
|
AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
||||||
|
ASTNODE_BASE_FUNCS(NodeSenItem)
|
||||||
|
virtual bool isClocked() const = 0;
|
||||||
|
virtual bool isCombo() const = 0;
|
||||||
|
virtual bool isInitial() const = 0;
|
||||||
|
virtual bool isSettle() const = 0;
|
||||||
|
virtual bool isNever() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class AstNodeVarRef : public AstNodeMath {
|
class AstNodeVarRef : public AstNodeMath {
|
||||||
// A AstVarRef or AstVarXRef
|
// An AstVarRef or AstVarXRef
|
||||||
private:
|
private:
|
||||||
bool m_lvalue; // Left hand side assignment
|
bool m_lvalue; // Left hand side assignment
|
||||||
AstVar* m_varp; // [AfterLink] Pointer to variable itself
|
AstVar* m_varp; // [AfterLink] Pointer to variable itself
|
||||||
@@ -911,12 +1054,12 @@ public:
|
|||||||
// May have varp==NULL
|
// May have varp==NULL
|
||||||
if (m_varp) widthSignedFrom((AstNode*)m_varp);
|
if (m_varp) widthSignedFrom((AstNode*)m_varp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeVarRef() {}
|
ASTNODE_BASE_FUNCS(NodeVarRef)
|
||||||
virtual bool broken() const;
|
virtual bool broken() const;
|
||||||
virtual int instrCount() const { return widthInstrs(); }
|
virtual int instrCount() const { return widthInstrs(); }
|
||||||
virtual void cloneRelink();
|
virtual void cloneRelink();
|
||||||
virtual string name() const { return m_name; } // * = Var name
|
virtual string name() const { return m_name; } // * = Var name
|
||||||
void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
bool lvalue() const { return m_lvalue; }
|
bool lvalue() const { return m_lvalue; }
|
||||||
void lvalue(bool lval) { m_lvalue=lval; } // Avoid using this; Set in constructor
|
void lvalue(bool lval) { m_lvalue=lval; } // Avoid using this; Set in constructor
|
||||||
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
||||||
@@ -927,6 +1070,9 @@ public:
|
|||||||
void hiername(const string& hn) { m_hiername = hn; }
|
void hiername(const string& hn) { m_hiername = hn; }
|
||||||
bool hierThis() const { return m_hierThis; }
|
bool hierThis() const { return m_hierThis; }
|
||||||
void hierThis(bool flag) { m_hierThis = flag; }
|
void hierThis(bool flag) { m_hierThis = flag; }
|
||||||
|
// Know no children, and hot function, so skip iterator for speed
|
||||||
|
// See checkTreeIter also that asserts no children
|
||||||
|
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstNodePli : public AstNodeStmt {
|
class AstNodePli : public AstNodeStmt {
|
||||||
@@ -935,7 +1081,7 @@ public:
|
|||||||
AstNodePli(FileLine* fl, const string& text, AstNode* exprsp)
|
AstNodePli(FileLine* fl, const string& text, AstNode* exprsp)
|
||||||
: AstNodeStmt(fl), m_text(text) {
|
: AstNodeStmt(fl), m_text(text) {
|
||||||
addNOp1p(exprsp); }
|
addNOp1p(exprsp); }
|
||||||
virtual ~AstNodePli() {}
|
ASTNODE_BASE_FUNCS(NodePli)
|
||||||
virtual string name() const { return m_text; }
|
virtual string name() const { return m_text; }
|
||||||
virtual int instrCount() const { return instrCountPli(); }
|
virtual int instrCount() const { return instrCountPli(); }
|
||||||
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||||
@@ -954,7 +1100,7 @@ public:
|
|||||||
: AstNode(fileline) {
|
: AstNode(fileline) {
|
||||||
m_text = textp; // Copy it
|
m_text = textp; // Copy it
|
||||||
}
|
}
|
||||||
virtual ~AstNodeText() {}
|
ASTNODE_BASE_FUNCS(NodeText)
|
||||||
const string& text() const { return m_text; }
|
const string& text() const { return m_text; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
||||||
virtual bool same(AstNode* samep) const {
|
virtual bool same(AstNode* samep) const {
|
||||||
@@ -984,13 +1130,13 @@ public:
|
|||||||
, m_name(name), m_taskPublic(false) {
|
, m_name(name), m_taskPublic(false) {
|
||||||
addNOp3p(stmtsp);
|
addNOp3p(stmtsp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeFTask() {}
|
ASTNODE_BASE_FUNCS(NodeFTask)
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
virtual string name() const { return m_name; } // * = Var name
|
virtual string name() const { return m_name; } // * = Var name
|
||||||
virtual bool maybePointedTo() const { return true; }
|
virtual bool maybePointedTo() const { return true; }
|
||||||
// {AstFunc only} op1 = Range output variable
|
// {AstFunc only} op1 = Range output variable
|
||||||
// op3 = Statements/Ports/Vars
|
// op3 = Statements/Ports/Vars
|
||||||
void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
AstNode* stmtsp() const { return op3p()->castNode(); } // op1 = List of statements
|
AstNode* stmtsp() const { return op3p()->castNode(); } // op1 = List of statements
|
||||||
void addStmtsp(AstNode* nodep) { addOp3p(nodep); }
|
void addStmtsp(AstNode* nodep) { addOp3p(nodep); }
|
||||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||||
@@ -1008,9 +1154,9 @@ public:
|
|||||||
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
|
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
|
||||||
:AstNode(fl)
|
:AstNode(fl)
|
||||||
, m_taskp(NULL) {
|
, m_taskp(NULL) {
|
||||||
setOp1p(namep); addNOp2p(pinsp);
|
setOp1p(namep); addNOp2p(pinsp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeFTaskRef() {}
|
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
||||||
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
||||||
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
||||||
m_taskp = m_taskp->clonep()->castNodeFTask();
|
m_taskp = m_taskp->clonep()->castNodeFTask();
|
||||||
@@ -1023,7 +1169,7 @@ public:
|
|||||||
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
||||||
AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable
|
AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable
|
||||||
void taskp(AstNodeFTask* taskp) { m_taskp=taskp; }
|
void taskp(AstNodeFTask* taskp) { m_taskp=taskp; }
|
||||||
void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
void dotted(const string& name) { m_dotted = name; }
|
void dotted(const string& name) { m_dotted = name; }
|
||||||
// op1 = namep
|
// op1 = namep
|
||||||
AstNode* namep() const { return op1p(); }
|
AstNode* namep() const { return op1p(); }
|
||||||
|
|||||||
+45
-104
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structures
|
// DESCRIPTION: Verilator: Ast node structures
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -44,19 +44,19 @@ void AstNodeVarRef::cloneRelink() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int AstNodeSel::bitConst() const {
|
int AstNodeSel::bitConst() const {
|
||||||
AstConst* constp=bitp()->castConst(); return (constp?constp->asInt():0);
|
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isSigPublic() const {
|
bool AstVar::isSigPublic() const {
|
||||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp()));
|
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isScQuad() const {
|
bool AstVar::isScQuad() const {
|
||||||
return (isSc()&&isQuad()&&v3Global.opt.pins64());
|
return (isSc() && isQuad() && !isScBv());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isScWide() const {
|
bool AstVar::isScBv() const {
|
||||||
return (isWide() || isSc()&&isQuad()&&!v3Global.opt.pins64());
|
return (isSc() && width() >= v3Global.opt.pinsBv());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstVar::combineType(AstVarType type) {
|
void AstVar::combineType(AstVarType type) {
|
||||||
@@ -109,7 +109,7 @@ string AstVar::cType() const {
|
|||||||
return "bool";
|
return "bool";
|
||||||
} else if (widthMin() <= VL_WORDSIZE) {
|
} else if (widthMin() <= VL_WORDSIZE) {
|
||||||
return "uint32_t";
|
return "uint32_t";
|
||||||
} else if (isScWide()) {
|
} else if (isWide()) {
|
||||||
return "uint32_t"; // []'s added later
|
return "uint32_t"; // []'s added later
|
||||||
} else {
|
} else {
|
||||||
return "uint64_t";
|
return "uint64_t";
|
||||||
@@ -117,12 +117,18 @@ string AstVar::cType() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::scType() const {
|
string AstVar::scType() const {
|
||||||
if (widthMin() == 1) {
|
if (isScBv()) {
|
||||||
|
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
||||||
|
} else if (widthMin() == 1) {
|
||||||
return "bool";
|
return "bool";
|
||||||
} else if (widthMin() <= VL_WORDSIZE) {
|
} else if (widthMin() <= VL_WORDSIZE) {
|
||||||
return "uint32_t";
|
if (widthMin() <= 8 && v3Global.opt.pinsUint8()) {
|
||||||
} else if (isScWide()) {
|
return "uint8_t";
|
||||||
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
} else if (widthMin() <= 16 && v3Global.opt.pinsUint8()) {
|
||||||
|
return "uint16_t";
|
||||||
|
} else {
|
||||||
|
return "uint32_t";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return "uint64_t";
|
return "uint64_t";
|
||||||
}
|
}
|
||||||
@@ -164,113 +170,30 @@ string AstScope::nameDotless() const {
|
|||||||
return dotless;
|
return dotless;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AstSenItemCmp {
|
|
||||||
inline bool operator () (const AstSenItem* lhsp, const AstSenItem* rhsp) const {
|
|
||||||
// Looks visually better if we keep sorted by name
|
|
||||||
if (lhsp->edgeType() < rhsp->edgeType()) return true;
|
|
||||||
if (lhsp->edgeType() > rhsp->edgeType()) return false;
|
|
||||||
if (!lhsp->varrefp() && rhsp->varrefp()) return true;
|
|
||||||
if ( lhsp->varrefp() && !rhsp->varrefp()) return false;
|
|
||||||
if (lhsp->varrefp() && rhsp->varrefp()) {
|
|
||||||
if (lhsp->varrefp()->name() < rhsp->varrefp()->name()) return true;
|
|
||||||
if (lhsp->varrefp()->name() > rhsp->varrefp()->name()) return false;
|
|
||||||
// But might be same name with different scopes
|
|
||||||
if (lhsp->varrefp()->varScopep() < rhsp->varrefp()->varScopep()) return true;
|
|
||||||
if (lhsp->varrefp()->varScopep() > rhsp->varrefp()->varScopep()) return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void AstSenTree::sortSenses() {
|
|
||||||
// Sort the sensitivity names so "posedge a or b" and "posedge b or a" end up together.
|
|
||||||
// Also, remove duplicate assignments, and fold POS&NEGs into ANYEDGEs
|
|
||||||
//cout<<endl; this->dumpTree(cout,"ssin: ");
|
|
||||||
AstSenItem* nextp;
|
|
||||||
// Make things a little faster; check first if we need a sort
|
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
|
||||||
nextp=senp->nextp()->castSenItem();
|
|
||||||
AstSenItemCmp cmp;
|
|
||||||
if (nextp && !cmp(senp, nextp)) {
|
|
||||||
// Something's out of order, sort it
|
|
||||||
senp = NULL;
|
|
||||||
vector<AstSenItem*> vec;
|
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
|
||||||
vec.push_back(senp);
|
|
||||||
}
|
|
||||||
sort(vec.begin(), vec.end(), AstSenItemCmp());
|
|
||||||
for (vector<AstSenItem*>::iterator it=vec.begin(); it!=vec.end(); ++it) {
|
|
||||||
(*it)->unlinkFrBack();
|
|
||||||
}
|
|
||||||
for (vector<AstSenItem*>::iterator it=vec.begin(); it!=vec.end(); ++it) {
|
|
||||||
this->addSensesp(*it);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass2, remove dup edges
|
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=nextp) {
|
|
||||||
nextp=senp->nextp()->castSenItem();
|
|
||||||
AstSenItem* cmpp = nextp;
|
|
||||||
if (cmpp
|
|
||||||
&& ((senp->varrefp() && cmpp->varrefp() && senp->varrefp()->sameTree(cmpp->varrefp()))
|
|
||||||
|| (!senp->varrefp() && !cmpp->varrefp()))) {
|
|
||||||
// We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders
|
|
||||||
if (( senp->edgeType()==AstEdgeType::ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY
|
|
||||||
|| (senp->edgeType()==AstEdgeType::BOTHEDGE) // BOTH or {POS|NEG} -> BOTH
|
|
||||||
|| (senp->edgeType()==AstEdgeType::POSEDGE // POS or NEG -> BOTH
|
|
||||||
&& cmpp->edgeType()==AstEdgeType::NEGEDGE)
|
|
||||||
|| (senp->edgeType()==cmpp->edgeType()) // Identical edges
|
|
||||||
) {
|
|
||||||
// Fix edge of old node
|
|
||||||
if (senp->edgeType()==AstEdgeType::POSEDGE
|
|
||||||
&& cmpp->edgeType()==AstEdgeType::NEGEDGE)
|
|
||||||
senp->edgeType(AstEdgeType::BOTHEDGE);
|
|
||||||
// Remove redundant node
|
|
||||||
cmpp->unlinkFrBack()->deleteTree(); cmpp=NULL;
|
|
||||||
// Try to collapse again
|
|
||||||
nextp=senp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass3, remove nevers
|
|
||||||
if (sensesp()->nextp()) { // Else only one never, can't remove it
|
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=nextp) {
|
|
||||||
nextp=senp->nextp()->castSenItem();
|
|
||||||
if (senp->isNever()) {
|
|
||||||
senp->unlinkFrBack()->deleteTree(); senp=NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//this->dumpTree(cout,"ssou: ");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AstSenTree::hasClocked() {
|
bool AstSenTree::hasClocked() {
|
||||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
if (senp->isClocked()) return true;
|
if (senp->isClocked()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool AstSenTree::hasSettle() {
|
bool AstSenTree::hasSettle() {
|
||||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
if (senp->isSettle()) return true;
|
if (senp->isSettle()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool AstSenTree::hasInitial() {
|
bool AstSenTree::hasInitial() {
|
||||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
if (senp->isInitial()) return true;
|
if (senp->isInitial()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool AstSenTree::hasCombo() {
|
bool AstSenTree::hasCombo() {
|
||||||
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
||||||
for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
if (senp->isCombo()) return true;
|
if (senp->isCombo()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -290,6 +213,11 @@ void AstNode::dump(ostream& os) {
|
|||||||
if (!widthSized()) os<<"/"<<widthMin();
|
if (!widthSized()) os<<"/"<<widthMin();
|
||||||
if (name()!="") os<<" "<<name();
|
if (name()!="") os<<" "<<name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AstAttrOf::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
str<<" ["<<attrType().ascii()<<"]";
|
||||||
|
}
|
||||||
void AstCast::dump(ostream& str) {
|
void AstCast::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" sz"<<size();
|
str<<" sz"<<size();
|
||||||
@@ -298,12 +226,15 @@ void AstCell::dump(ostream& str) {
|
|||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (modp()) { str<<" -> "; modp()->dump(str); }
|
if (modp()) { str<<" -> "; modp()->dump(str); }
|
||||||
else { str<<" ->UNLINKED:"<<modName(); }
|
else { str<<" ->UNLINKED:"<<modName(); }
|
||||||
if (pinStar()) str<<" [.*]";
|
|
||||||
}
|
}
|
||||||
void AstCellInline::dump(ostream& str) {
|
void AstCellInline::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" -> "<<origModName();
|
str<<" -> "<<origModName();
|
||||||
}
|
}
|
||||||
|
void AstDisplay::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
//str<<" "<<displayType().ascii();
|
||||||
|
}
|
||||||
void AstPin::dump(ostream& str) {
|
void AstPin::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
||||||
@@ -389,6 +320,12 @@ void AstNodeFTask::dump(ostream& str) {
|
|||||||
}
|
}
|
||||||
void AstCoverDecl::dump(ostream& str) {
|
void AstCoverDecl::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
if (this->dataDeclNullp()) {
|
||||||
|
str<<" -> ";
|
||||||
|
this->dataDeclNullp()->dump(str);
|
||||||
|
} else {
|
||||||
|
if (binNum()) { str<<" bin"<<dec<<binNum(); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void AstCoverInc::dump(ostream& str) {
|
void AstCoverInc::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
@@ -414,3 +351,7 @@ void AstCCall::dump(ostream& str) {
|
|||||||
funcp()->dump(str);
|
funcp()->dump(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void AstCFunc::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (slow()) str<<" [SLOW]";
|
||||||
|
}
|
||||||
|
|||||||
+592
-790
File diff suppressed because it is too large
Load Diff
+54
-8
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Begin's Transformations:
|
// V3Begin's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Look for BEGINs
|
// Look for BEGINs
|
||||||
// BEGIN(VAR...) -> VAR ... {renamed}
|
// BEGIN(VAR...) -> VAR ... {renamed}
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -48,11 +48,19 @@ private:
|
|||||||
AstModule* m_modp; // Current module
|
AstModule* m_modp; // Current module
|
||||||
AstNodeFTask* m_ftaskp; // Current function/task
|
AstNodeFTask* m_ftaskp; // Current function/task
|
||||||
string m_beginScope; // Name of begin blocks above us
|
string m_beginScope; // Name of begin blocks above us
|
||||||
//int debug() { return 9; }
|
int m_repeatNum; // Repeat counter
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
|
m_repeatNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
@@ -131,6 +139,38 @@ private:
|
|||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstRepeat* nodep, AstNUser*) {
|
||||||
|
// So later optimizations don't need to deal with them,
|
||||||
|
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
|
||||||
|
// Note var can be signed or unsigned based on original number.
|
||||||
|
AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
|
||||||
|
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
|
||||||
|
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
|
||||||
|
new AstRange(nodep->fileline(), countp->width()-1, 0));
|
||||||
|
m_modp->addStmtp(varp);
|
||||||
|
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
|
||||||
|
countp);
|
||||||
|
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
|
||||||
|
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
||||||
|
new AstConst(nodep->fileline(), 1)));
|
||||||
|
AstNode* condp;
|
||||||
|
if (countp->isSigned()) {
|
||||||
|
condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
||||||
|
new AstConst(nodep->fileline(), 0));
|
||||||
|
} else {
|
||||||
|
condp = new AstGt (nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
||||||
|
new AstConst(nodep->fileline(), 0));
|
||||||
|
}
|
||||||
|
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
|
||||||
|
bodysp = bodysp->addNext(decp);
|
||||||
|
AstNode* newp = new AstWhile(nodep->fileline(),
|
||||||
|
condp,
|
||||||
|
bodysp);
|
||||||
|
initsp = initsp->addNext(newp);
|
||||||
|
newp = initsp;
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||||
// Similar code in V3Inline
|
// Similar code in V3Inline
|
||||||
@@ -143,6 +183,11 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
||||||
|
// Don't need to fix path in coverage statements, they're not under
|
||||||
|
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
@@ -151,6 +196,7 @@ public:
|
|||||||
BeginVisitor(AstNetlist* nodep) {
|
BeginVisitor(AstNetlist* nodep) {
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
m_ftaskp = NULL;
|
m_ftaskp = NULL;
|
||||||
|
m_repeatNum = 0;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~BeginVisitor() {}
|
virtual ~BeginVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+12
-7
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Branch prediction
|
// DESCRIPTION: Verilator: Branch prediction
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -44,9 +44,14 @@ private:
|
|||||||
// STATE
|
// STATE
|
||||||
int m_likely; // Excuses for branch likely taken
|
int m_likely; // Excuses for branch likely taken
|
||||||
int m_unlikely; // Excuses for branch likely not taken
|
int m_unlikely; // Excuses for branch likely not taken
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
m_likely = false;
|
m_likely = false;
|
||||||
m_unlikely = false;
|
m_unlikely = false;
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Branch prediction
|
// DESCRIPTION: Verilator: Branch prediction
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+10
-10
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Find broken links in tree
|
// DESCRIPTION: Verilator: Find broken links in tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Broken's Transformations:
|
// V3Broken's Transformations:
|
||||||
//
|
//
|
||||||
// Entire netlist
|
// Entire netlist
|
||||||
// Mark all nodes
|
// Mark all nodes
|
||||||
// Check all links point to marked nodes
|
// Check all links point to marked nodes
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -130,9 +130,9 @@ public:
|
|||||||
// Use only AstNode::dump instead of the virtual one, as there
|
// Use only AstNode::dump instead of the virtual one, as there
|
||||||
// may be varp() and other cross links that are bad.
|
// may be varp() and other cross links that are bad.
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
cout<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
||||||
((AstNode*)(it->first))->AstNode::dump(cout);
|
((AstNode*)(it->first))->AstNode::dump(cerr);
|
||||||
cout<<endl;
|
cerr<<endl;
|
||||||
V3Error::incErrors();
|
V3Error::incErrors();
|
||||||
}
|
}
|
||||||
it->second |= FLAG_LEAKED;
|
it->second |= FLAG_LEAKED;
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Find broken links in tree
|
// DESCRIPTION: Verilator: Find broken links in tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+73
-31
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Case's Transformations:
|
// V3Case's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// TBD: Eliminate tristates by adding __in, __inen, __en wires in parallel
|
// TBD: Eliminate tristates by adding __in, __inen, __en wires in parallel
|
||||||
// Need __en in changed list if a signal is on the LHS of a assign
|
// Need __en in changed list if a signal is on the LHS of a assign
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -59,7 +59,12 @@
|
|||||||
class CaseLintVisitor : public AstNVisitor {
|
class CaseLintVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
AstNodeCase* m_caseExprp; // Under a CASE value node, if so the relevant case statement
|
AstNodeCase* m_caseExprp; // Under a CASE value node, if so the relevant case statement
|
||||||
//int debug() { return 9; }
|
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
||||||
// Detect multiple defaults
|
// Detect multiple defaults
|
||||||
@@ -74,7 +79,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for X/Z in non-casex statements
|
// Check for X/Z in non-casex statements
|
||||||
if (!nodep->castCase() || !nodep->castCase()->casex()) {
|
{
|
||||||
m_caseExprp = nodep;
|
m_caseExprp = nodep;
|
||||||
nodep->exprp()->accept(*this);
|
nodep->exprp()->accept(*this);
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
@@ -84,11 +89,18 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||||
|
// See also neverItem
|
||||||
if (m_caseExprp && nodep->num().isFourState()) {
|
if (m_caseExprp && nodep->num().isFourState()) {
|
||||||
if (m_caseExprp->castGenCase()) {
|
if (m_caseExprp->castGenCase()) {
|
||||||
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
||||||
|
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
||||||
|
// Don't sweat it, we already complained about casex in general
|
||||||
|
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
|
||||||
|
if (nodep->num().isUnknown()) {
|
||||||
|
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->v3error("Use of x/? constant in case statement, (perhaps intended casex/casez)");
|
nodep->v3warn(CASEWITHX, "Use of x/? constant in case statement, (perhaps intended casex/casez)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,6 +124,7 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Cleared each Case
|
// Cleared each Case
|
||||||
// AstIf::user3() -> bool. Set true to indicate clone not needed
|
// AstIf::user3() -> bool. Set true to indicate clone not needed
|
||||||
|
AstUser3InUse m_inuser3;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
V3Double0 m_statCaseFast; // Statistic tracking
|
V3Double0 m_statCaseFast; // Statistic tracking
|
||||||
@@ -123,9 +136,13 @@ private:
|
|||||||
int m_caseNoOverlapsAllCovered; // Proven to be synopsys parallel_case compliant
|
int m_caseNoOverlapsAllCovered; // Proven to be synopsys parallel_case compliant
|
||||||
AstNode* m_valueItem[1<<CASE_OVERLAP_WIDTH]; // For each possible value, the case branch we need
|
AstNode* m_valueItem[1<<CASE_OVERLAP_WIDTH]; // For each possible value, the case branch we need
|
||||||
|
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
bool isCaseTreeFast(AstCase* nodep) {
|
bool isCaseTreeFast(AstCase* nodep) {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
m_caseItems = 0;
|
m_caseItems = 0;
|
||||||
@@ -153,20 +170,24 @@ private:
|
|||||||
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
|
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
if (neverItem(nodep, iconstp)) {
|
||||||
nummask.opBitsNonX(iconstp->num());
|
// X in casez can't ever be executed
|
||||||
uint32_t mask = nummask.asInt();
|
} else {
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
numval.opBitsOne(iconstp->num());
|
nummask.opBitsNonX(iconstp->num());
|
||||||
uint32_t val = numval.asInt();
|
uint32_t mask = nummask.toUInt();
|
||||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
if ((i & mask) == val) {
|
numval.opBitsOne(iconstp->num());
|
||||||
if (!m_valueItem[i]) {
|
uint32_t val = numval.toUInt();
|
||||||
m_valueItem[i] = itemp;
|
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||||
} else if (!itemp->ignoreOverlap() && !bitched) {
|
if ((i & mask) == val) {
|
||||||
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
|
if (!m_valueItem[i]) {
|
||||||
bitched = true;
|
m_valueItem[i] = itemp;
|
||||||
m_caseNoOverlapsAllCovered = false;
|
} else if (!itemp->ignoreOverlap() && !bitched) {
|
||||||
|
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
|
||||||
|
bitched = true;
|
||||||
|
m_caseNoOverlapsAllCovered = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,6 +219,7 @@ private:
|
|||||||
if (msb<0) {
|
if (msb<0) {
|
||||||
// There's no space for a IF. We know upperValue is thus down to a specific
|
// There's no space for a IF. We know upperValue is thus down to a specific
|
||||||
// exact value, so just return the tree value
|
// exact value, so just return the tree value
|
||||||
|
// Note can't clone here, as we're going to check for equivelence above
|
||||||
return m_valueItem[upperValue];
|
return m_valueItem[upperValue];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -235,7 +257,7 @@ private:
|
|||||||
// new AstConst(cexprp->fileline(), nummask));
|
// new AstConst(cexprp->fileline(), nummask));
|
||||||
AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false),
|
AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false),
|
||||||
msb, 1);
|
msb, 1);
|
||||||
AstNode* eqp = new AstNeq(cexprp->fileline(),
|
AstNode* eqp = new AstNeq(cexprp->fileline(),
|
||||||
new AstConst(cexprp->fileline(), 0),
|
new AstConst(cexprp->fileline(), 0),
|
||||||
and1p);
|
and1p);
|
||||||
AstIf* ifp = new AstIf(cexprp->fileline(), eqp, tree1p, tree0p);
|
AstIf* ifp = new AstIf(cexprp->fileline(), eqp, tree1p, tree0p);
|
||||||
@@ -263,6 +285,8 @@ private:
|
|||||||
|
|
||||||
AstNode::user3ClearTree();
|
AstNode::user3ClearTree();
|
||||||
AstNode* ifrootp = replaceCaseFastRecurse(cexprp, m_caseWidth-1, 0UL);
|
AstNode* ifrootp = replaceCaseFastRecurse(cexprp, m_caseWidth-1, 0UL);
|
||||||
|
// Case expressions can't be linked twice, so clone them
|
||||||
|
if (ifrootp && !ifrootp->user3()) ifrootp = ifrootp->cloneTree(true);
|
||||||
|
|
||||||
if (ifrootp) nodep->replaceWith(ifrootp);
|
if (ifrootp) nodep->replaceWith(ifrootp);
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
@@ -293,19 +317,26 @@ private:
|
|||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) {
|
||||||
icondNextp = icondp->nextp();
|
icondNextp = icondp->nextp();
|
||||||
icondp->unlinkFrBack();
|
icondp->unlinkFrBack();
|
||||||
|
|
||||||
AstNode* and1p;
|
AstNode* and1p;
|
||||||
AstNode* and2p;
|
AstNode* and2p;
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (iconstp && iconstp->num().isFourState()
|
if (iconstp && neverItem(nodep, iconstp)) {
|
||||||
&& nodep->casex()) {
|
// X in casez can't ever be executed
|
||||||
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
|
// For simplicity, make expression that is not equal, and let later
|
||||||
|
// optimizations remove it
|
||||||
|
and1p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,0));
|
||||||
|
and2p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,1));
|
||||||
|
} else if (iconstp && iconstp->num().isFourState()
|
||||||
|
&& (nodep->casex() || nodep->casez())) {
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
nummask.opBitsNonX(iconstp->num());
|
nummask.opBitsNonX(iconstp->num());
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
numval.opBitsOne(iconstp->num());
|
numval.opBitsOne(iconstp->num());
|
||||||
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
and2p = new AstAnd(itemp->fileline(),
|
and2p = new AstAnd(itemp->fileline(),
|
||||||
new AstConst(itemp->fileline(), numval),
|
new AstConst(itemp->fileline(), numval),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
@@ -395,6 +426,17 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool neverItem(AstCase* casep, AstConst* itemp) {
|
||||||
|
// Xs in case or casez are impossible due to two state simulations
|
||||||
|
if (casep->casex()) {
|
||||||
|
} else if (casep->casez()) {
|
||||||
|
if (itemp->num().isUnknown()) return true;
|
||||||
|
} else {
|
||||||
|
if (itemp->num().isFourState()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||||
V3Case::caseLint(nodep);
|
V3Case::caseLint(nodep);
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+27
-22
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Cast's Transformations:
|
// V3Cast's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each math operator, if above operator requires 32 bits,
|
// For each math operator, if above operator requires 32 bits,
|
||||||
// and this isn't, cast to 32 bits.
|
// and this isn't, cast to 32 bits.
|
||||||
@@ -44,8 +44,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -61,11 +61,17 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstNode::user() // bool. Indicates node is of known size
|
// AstNode::user() // bool. Indicates node is of known size
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
void insertCast(AstNode* nodep, int needsize) { // We'll insert ABOVE passed node
|
void insertCast(AstNode* nodep, int needsize) { // We'll insert ABOVE passed node
|
||||||
UINFO(4," NeedCast "<<nodep<<endl);
|
UINFO(4," NeedCast "<<nodep<<endl);
|
||||||
AstNRelinker relinkHandle;
|
AstNRelinker relinkHandle;
|
||||||
@@ -77,7 +83,7 @@ private:
|
|||||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||||
//
|
//
|
||||||
insureLower32Cast(castp);
|
insureLower32Cast(castp);
|
||||||
nodep->user(1); // Now must be of known size
|
nodep->user1(1); // Now must be of known size
|
||||||
}
|
}
|
||||||
int castSize (AstNode* nodep) {
|
int castSize (AstNode* nodep) {
|
||||||
if (nodep->isQuad()) return VL_QUADSIZE;
|
if (nodep->isQuad()) return VL_QUADSIZE;
|
||||||
@@ -87,7 +93,7 @@ private:
|
|||||||
}
|
}
|
||||||
void insureCast(AstNode* nodep) {
|
void insureCast(AstNode* nodep) {
|
||||||
if (castSize(nodep->backp()) != castSize(nodep)
|
if (castSize(nodep->backp()) != castSize(nodep)
|
||||||
|| !nodep->user()) {
|
|| !nodep->user1()) {
|
||||||
insertCast(nodep, castSize(nodep->backp()));
|
insertCast(nodep, castSize(nodep->backp()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,21 +111,21 @@ private:
|
|||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user(nodep->lhsp()->user());
|
nodep->user1(nodep->lhsp()->user1());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user(nodep->lhsp()->user()
|
nodep->user1(nodep->lhsp()->user1()
|
||||||
| nodep->rhsp()->user());
|
| nodep->rhsp()->user1());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
|
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user(nodep->lhsp()->user()
|
nodep->user1(nodep->lhsp()->user1()
|
||||||
| nodep->rhsp()->user()
|
| nodep->rhsp()->user1()
|
||||||
| nodep->thsp()->user());
|
| nodep->thsp()->user1());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||||
@@ -127,11 +133,11 @@ private:
|
|||||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureLower32Cast(nodep);
|
insureLower32Cast(nodep);
|
||||||
nodep->user(1);
|
nodep->user1(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user(nodep->lhsp()->user());
|
nodep->user1(nodep->lhsp()->user1());
|
||||||
if (nodep->lhsp()->widthMin()==1) {
|
if (nodep->lhsp()->widthMin()==1) {
|
||||||
// We want to avoid a GCC "converting of negative value" warning
|
// We want to avoid a GCC "converting of negative value" warning
|
||||||
// from our expansion of
|
// from our expansion of
|
||||||
@@ -148,16 +154,16 @@ private:
|
|||||||
&& nodep->backp()->width()
|
&& nodep->backp()->width()
|
||||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||||
// Cast vars to IData first, else below has upper bits wrongly set
|
// Cast vars to IData first, else below has upper bits wrongly set
|
||||||
// CData x=3; out = (QData)(x<<30);
|
// CData x=3; out = (QData)(x<<30);
|
||||||
insertCast (nodep, castSize(nodep));
|
insertCast (nodep, castSize(nodep));
|
||||||
}
|
}
|
||||||
nodep->user(1);
|
nodep->user1(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||||
// Constants are of unknown size if smaller than 33 bits, becase
|
// Constants are of unknown size if smaller than 33 bits, becase
|
||||||
// we're too lazy to wrap every constant in the universe in
|
// we're too lazy to wrap every constant in the universe in
|
||||||
// ((IData)#).
|
// ((IData)#).
|
||||||
nodep->user(nodep->isQuad() || nodep->isWide());
|
nodep->user1(nodep->isQuad() || nodep->isWide());
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOPs
|
// NOPs
|
||||||
@@ -172,7 +178,6 @@ private:
|
|||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CastVisitor(AstNetlist* nodep) {
|
CastVisitor(AstNetlist* nodep) {
|
||||||
AstNode::userClearTree();
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CastVisitor() {}
|
virtual ~CastVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+20
-12
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Changed's Transformations:
|
// V3Changed's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Each combo block
|
// Each combo block
|
||||||
// For each variable that comes from combo block and is generated AFTER a usage
|
// For each variable that comes from combo block and is generated AFTER a usage
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -51,19 +51,27 @@ class ChangedVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstVarScope::user() -> bool. True indicates processed
|
// AstVarScope::user1() -> bool. True indicates processed
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstModule* m_topModp; // Top module
|
AstModule* m_topModp; // Top module
|
||||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||||
AstCFunc* m_chgFuncp; // Change function we're building
|
AstCFunc* m_chgFuncp; // Change function we're building
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
void genChangeDet(AstVarScope* vscp) {
|
void genChangeDet(AstVarScope* vscp) {
|
||||||
#ifdef NEW_ORDERING
|
#ifdef NEW_ORDERING
|
||||||
vscp->v3fatalSrc("Not applicable\n");
|
vscp->v3fatalSrc("Not applicable\n");
|
||||||
#endif
|
#endif
|
||||||
AstVar* varp = vscp->varp();
|
AstVar* varp = vscp->varp();
|
||||||
|
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||||
if (varp->arraysp()) {
|
if (varp->arraysp()) {
|
||||||
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
||||||
} else {
|
} else {
|
||||||
@@ -101,7 +109,7 @@ private:
|
|||||||
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
||||||
UINFO(4," TS "<<nodep<<endl);
|
UINFO(4," TS "<<nodep<<endl);
|
||||||
// Clearing
|
// Clearing
|
||||||
AstNode::userClearTree();
|
AstNode::user1ClearTree();
|
||||||
// Create the change detection function
|
// Create the change detection function
|
||||||
AstScope* scopep = nodep->scopep();
|
AstScope* scopep = nodep->scopep();
|
||||||
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
if (!scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
||||||
@@ -120,8 +128,8 @@ private:
|
|||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||||
if (nodep->isCircular()) {
|
if (nodep->isCircular()) {
|
||||||
UINFO(8," CIRC "<<nodep<<endl);
|
UINFO(8," CIRC "<<nodep<<endl);
|
||||||
if (!nodep->user()) {
|
if (!nodep->user1()) {
|
||||||
nodep->user(true);
|
nodep->user1(true);
|
||||||
genChangeDet(nodep);
|
genChangeDet(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+21
-15
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Clean's Transformations:
|
// V3Clean's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each math operator, if it requires a clean operand,
|
// For each math operator, if it requires a clean operand,
|
||||||
// and the operand is dirty, insert a CLEAN node.
|
// and the operand is dirty, insert a CLEAN node.
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -48,15 +48,22 @@ private:
|
|||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN
|
// AstNode::user() -> CleanState. For this node, 0==UNKNOWN
|
||||||
// AstNode::user2() -> bool. True indicates minWidth has been propagated
|
// AstNode::user2() -> bool. True indicates minWidth has been propagated
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
AstUser2InUse m_inuser2;
|
||||||
|
|
||||||
|
// TYPES
|
||||||
|
enum CleanState { UNKNOWN, CLEAN, DIRTY };
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstModule* m_modp;
|
AstModule* m_modp;
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// ENUMS
|
|
||||||
enum CleanState { UNKNOWN, CLEAN, DIRTY };
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
// Width resetting
|
// Width resetting
|
||||||
int cppWidth(AstNode* nodep) {
|
int cppWidth(AstNode* nodep) {
|
||||||
if (nodep->width()<=VL_WORDSIZE) return VL_WORDSIZE;
|
if (nodep->width()<=VL_WORDSIZE) return VL_WORDSIZE;
|
||||||
@@ -79,10 +86,10 @@ private:
|
|||||||
|
|
||||||
// Store the clean state in the userp on each node
|
// Store the clean state in the userp on each node
|
||||||
void setCleanState(AstNode* nodep, CleanState clean) {
|
void setCleanState(AstNode* nodep, CleanState clean) {
|
||||||
nodep->user(clean);
|
nodep->user1(clean);
|
||||||
}
|
}
|
||||||
CleanState getCleanState(AstNode* nodep) {
|
CleanState getCleanState(AstNode* nodep) {
|
||||||
return ((CleanState)nodep->user());
|
return ((CleanState)nodep->user1());
|
||||||
}
|
}
|
||||||
bool isClean(AstNode* nodep) {
|
bool isClean(AstNode* nodep) {
|
||||||
CleanState clstate = getCleanState(nodep);
|
CleanState clstate = getCleanState(nodep);
|
||||||
@@ -156,6 +163,7 @@ private:
|
|||||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -257,8 +265,6 @@ public:
|
|||||||
CleanVisitor() {}
|
CleanVisitor() {}
|
||||||
virtual ~CleanVisitor() {}
|
virtual ~CleanVisitor() {}
|
||||||
void main(AstNetlist* nodep) {
|
void main(AstNetlist* nodep) {
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
|
||||||
AstNode::user2ClearTree(); // userp() used on entire tree
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
@@ -0,0 +1,918 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2008-2009 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
// V3ClkGater's Transformations:
|
||||||
|
//
|
||||||
|
// Look for clock gaters
|
||||||
|
// Note there's overlap between this process and V3Split's
|
||||||
|
// ALWAYS: Build graph
|
||||||
|
// IF: Form vertex pointing to any IFs or ALWAYS above
|
||||||
|
// VARREF: Form vertex pointing to IFs it is under
|
||||||
|
// ASSIGN: If under normal assignment, disable optimization
|
||||||
|
// FUTURE OPTIMIZE: If signal is set to itself, consider that OK for gating.
|
||||||
|
// !splitable: Mark all VARREFs in this statement as comming from it
|
||||||
|
// Optimize graph so if signal is referenced under multiple IF branches it moves up
|
||||||
|
// Make ALWAYS for each new gating term, and move statements there
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "V3Global.h"
|
||||||
|
#include "V3Ast.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
|
#include "V3Graph.h"
|
||||||
|
#include "V3ClkGater.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Base for debug
|
||||||
|
|
||||||
|
class GaterBaseVisitor : public AstNVisitor {
|
||||||
|
protected:
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Support classes
|
||||||
|
|
||||||
|
class GaterVarVertex;
|
||||||
|
|
||||||
|
class GaterVertex : public V3GraphVertex {
|
||||||
|
static uint32_t s_rankNum;
|
||||||
|
public:
|
||||||
|
GaterVertex(V3Graph* graphp)
|
||||||
|
: V3GraphVertex(graphp) {
|
||||||
|
s_rankNum++; rank(s_rankNum);
|
||||||
|
}
|
||||||
|
virtual ~GaterVertex() {}
|
||||||
|
virtual int typeNum() const = 0;
|
||||||
|
static void clearRank() { s_rankNum=0; }
|
||||||
|
virtual int sortCmp(const V3GraphVertex* rhsp) const;
|
||||||
|
};
|
||||||
|
uint32_t GaterVertex::s_rankNum = 0;
|
||||||
|
|
||||||
|
class GaterHeadVertex : public GaterVertex {
|
||||||
|
public:
|
||||||
|
GaterHeadVertex(V3Graph* graphp)
|
||||||
|
: GaterVertex(graphp) {}
|
||||||
|
virtual ~GaterHeadVertex() {}
|
||||||
|
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||||
|
virtual string name() const { return "*HEAD*"; }
|
||||||
|
virtual string dotColor() const { return "green"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class GaterPliVertex : public GaterVertex {
|
||||||
|
public:
|
||||||
|
GaterPliVertex(V3Graph* graphp)
|
||||||
|
: GaterVertex(graphp) {}
|
||||||
|
virtual ~GaterPliVertex() {}
|
||||||
|
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||||
|
virtual string name() const { return "*PLI*"; }
|
||||||
|
virtual string dotColor() const { return "red"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class GaterIfVertex : public GaterVertex {
|
||||||
|
AstNodeIf* m_nodep;
|
||||||
|
public:
|
||||||
|
AstNodeIf* nodep() const { return m_nodep; }
|
||||||
|
GaterIfVertex(V3Graph* graphp, AstNodeIf* nodep)
|
||||||
|
: GaterVertex(graphp), m_nodep(nodep) { }
|
||||||
|
virtual ~GaterIfVertex() {}
|
||||||
|
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||||
|
virtual string name() const { return cvtToStr((void*)m_nodep)+" {"+cvtToStr(m_nodep->fileline()->lineno())+"}"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class GaterVarVertex : public GaterVertex {
|
||||||
|
AstVarScope* m_nodep;
|
||||||
|
public:
|
||||||
|
AstVarScope* nodep() const { return m_nodep; }
|
||||||
|
GaterVarVertex(V3Graph* graphp, AstVarScope* nodep)
|
||||||
|
: GaterVertex(graphp), m_nodep(nodep) { }
|
||||||
|
virtual ~GaterVarVertex() {}
|
||||||
|
virtual int typeNum() const { return __LINE__; } // C++ typeof() equivelent
|
||||||
|
virtual string name() const { return nodep()->name(); }
|
||||||
|
virtual string dotColor() const { return "skyblue"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Edge types
|
||||||
|
|
||||||
|
class GaterEdge : public V3GraphEdge {
|
||||||
|
uint32_t m_ifelse; // True branch of if
|
||||||
|
public:
|
||||||
|
// These are used as shift amounts into node's user()
|
||||||
|
#define VU_DEFINE enum VarUsage { VU_NONE=0, VU_IF=1, VU_ELSE=2, VU_PLI=4, VU_MADE=8}
|
||||||
|
VU_DEFINE;
|
||||||
|
|
||||||
|
uint32_t ifelse() const { return m_ifelse; }
|
||||||
|
bool ifelseTrue() const { return m_ifelse & VU_IF; }
|
||||||
|
bool ifelseFalse() const { return m_ifelse & VU_ELSE; }
|
||||||
|
bool ifelseBoth() const { return ifelseTrue() && ifelseFalse(); }
|
||||||
|
GaterEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, uint32_t ifelse)
|
||||||
|
: V3GraphEdge(graphp, fromp, top, 10, false), m_ifelse(ifelse) {}
|
||||||
|
virtual ~GaterEdge() {}
|
||||||
|
virtual string dotColor() const { return ((ifelse() & VU_PLI) ? "red"
|
||||||
|
: (ifelseBoth() ? "blue"
|
||||||
|
: (ifelseTrue() ? "green"
|
||||||
|
: "darkgreen"))); }
|
||||||
|
virtual int sortCmp(const V3GraphEdge* rEdgep) const {
|
||||||
|
// Our master sort sorts by edges first, so we don't want to
|
||||||
|
// consider the upstream vertex::sortCmp when sorting by edges.
|
||||||
|
// We do want to order by something though; rank works
|
||||||
|
if (fromp()->rank() < rEdgep->fromp()->rank()) return -1;
|
||||||
|
if (fromp()->rank() > rEdgep->fromp()->rank()) return 1;
|
||||||
|
// If same, resolve by ifelse
|
||||||
|
const GaterEdge* crEdgep = static_cast<const GaterEdge*>(rEdgep);
|
||||||
|
if (m_ifelse < crEdgep->m_ifelse) return -1;
|
||||||
|
if (m_ifelse > crEdgep->m_ifelse) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int GaterVertex::sortCmp(const V3GraphVertex* rhsp) const {
|
||||||
|
const GaterVertex* crhsp = static_cast<const GaterVertex*>(rhsp);
|
||||||
|
// We really only care about ordering Var's together, but...
|
||||||
|
// First put same type together
|
||||||
|
if (typeNum() < crhsp->typeNum()) return -1;
|
||||||
|
if (typeNum() > crhsp->typeNum()) return 1;
|
||||||
|
// If variable, group by same input fanin
|
||||||
|
// (know they're the same type based on above compare)
|
||||||
|
if (dynamic_cast<const GaterVarVertex*>(this)) {
|
||||||
|
// We've already sorted by edges, so just see if same tree
|
||||||
|
// If this gets too slow, we could compute a hash up front
|
||||||
|
V3GraphEdge* lEdgep = this->inBeginp();
|
||||||
|
V3GraphEdge* rEdgep = rhsp->inBeginp();
|
||||||
|
while (lEdgep && rEdgep) {
|
||||||
|
const GaterEdge* clEdgep = static_cast<const GaterEdge*>(lEdgep);
|
||||||
|
const GaterEdge* crEdgep = static_cast<const GaterEdge*>(rEdgep);
|
||||||
|
if (lEdgep->fromp()->rank() < rEdgep->fromp()->rank()) return -1;
|
||||||
|
if (lEdgep->fromp()->rank() > rEdgep->fromp()->rank()) return 1;
|
||||||
|
if (clEdgep->ifelse() < crEdgep->ifelse()) return -1;
|
||||||
|
if (clEdgep->ifelse() > crEdgep->ifelse()) return 1;
|
||||||
|
lEdgep = lEdgep->inNextp();
|
||||||
|
rEdgep = rEdgep->inNextp();
|
||||||
|
}
|
||||||
|
if (!lEdgep && !rEdgep) return 0;
|
||||||
|
return lEdgep ? -1 : 1;
|
||||||
|
}
|
||||||
|
// Finally by rank of this vertex
|
||||||
|
if (rank() < rhsp->rank()) return -1;
|
||||||
|
if (rank() > rhsp->rank()) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Check for non-simple gating equations
|
||||||
|
|
||||||
|
class GaterCondVisitor : public GaterBaseVisitor {
|
||||||
|
private:
|
||||||
|
// RETURN STATE
|
||||||
|
bool m_isSimple; // Set false when we know it isn't simple
|
||||||
|
// METHODS
|
||||||
|
inline void okIterate(AstNode* nodep) {
|
||||||
|
if (m_isSimple) nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstOr* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
virtual void visit(AstAnd* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
virtual void visit(AstNot* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
virtual void visit(AstLogOr* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
virtual void visit(AstLogAnd* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
virtual void visit(AstLogNot* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) { okIterate(nodep); }
|
||||||
|
|
||||||
|
// Other possibilities are equals, etc
|
||||||
|
// But, we don't want to get too complicated or it will take too much
|
||||||
|
// effort to calculate the gater
|
||||||
|
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
m_isSimple = false;
|
||||||
|
//nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
GaterCondVisitor(AstNode* nodep) {
|
||||||
|
m_isSimple = true;
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
virtual ~GaterCondVisitor() {}
|
||||||
|
// PUBLIC METHODS
|
||||||
|
bool isSimple() const { return m_isSimple; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Check for non-simple gating equations
|
||||||
|
|
||||||
|
class GaterBodyVisitor : public GaterBaseVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// Input state
|
||||||
|
// AstVarScope::user2p() -> AstAlways* moving this variable to
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
// This is used as a bitmask
|
||||||
|
STATE_UNKNOWN=0,
|
||||||
|
STATE_KEEP=1, // Seen a variable we need, keep this statement
|
||||||
|
STATE_DELETE=2 // Seen a variable we need, delete this statement
|
||||||
|
// 3=keep & delete
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_original; // Deleting original statements, vs deleting new var statements
|
||||||
|
AstNode* m_exprp; // New gater expression we are building
|
||||||
|
bool m_cloning; // Clone this object 0=not sure yet, 1=do
|
||||||
|
uint32_t m_state; // Parsing state
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->lvalue()) {
|
||||||
|
AstVarScope* vscp = nodep->varScopep();
|
||||||
|
if (vscp->user2p()->castNode() == m_exprp) {
|
||||||
|
// This variable's block needs to move to the new always
|
||||||
|
if (m_original) {
|
||||||
|
UINFO(9," VARREF delete in old: "<<nodep<<endl);
|
||||||
|
m_state |= STATE_DELETE;
|
||||||
|
} else {
|
||||||
|
UINFO(9," VARREF stays in new: "<<nodep<<endl);
|
||||||
|
m_state |= STATE_KEEP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (m_original) {
|
||||||
|
UINFO(9," VARREF other stays in old\n");
|
||||||
|
m_state |= STATE_KEEP;
|
||||||
|
} else {
|
||||||
|
UINFO(9," VARREF other delete in new\n");
|
||||||
|
m_state |= STATE_DELETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//virtual void visit(AstNodeIf* nodep, AstNUser*) { ... }
|
||||||
|
// Not needed, it's the same handling as any other statement. Cool, huh?
|
||||||
|
// (We may get empty IFs but the constant propagater will rip them up for us)
|
||||||
|
|
||||||
|
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
||||||
|
uint32_t oldstate = m_state;
|
||||||
|
// Find if children want to delete this or not.
|
||||||
|
// Note children may bicker, and want to both keep and delete (branches on a if)
|
||||||
|
uint32_t childstate;
|
||||||
|
{
|
||||||
|
m_state = STATE_UNKNOWN;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
childstate = m_state;
|
||||||
|
}
|
||||||
|
m_state = oldstate;
|
||||||
|
UINFO(9," Did state="<<childstate<<" "<<nodep<<endl);
|
||||||
|
|
||||||
|
// Indeterminate (statement with no lvalue), so keep only in original
|
||||||
|
if (childstate == STATE_UNKNOWN) {
|
||||||
|
if (m_original) childstate |= STATE_KEEP;
|
||||||
|
else childstate |= STATE_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((childstate & STATE_DELETE) && !(childstate & STATE_KEEP)) {
|
||||||
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
// Pass upwards we did delete
|
||||||
|
m_state |= STATE_DELETE;
|
||||||
|
} else {
|
||||||
|
// Pass upwards we must keep
|
||||||
|
m_state |= STATE_KEEP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
GaterBodyVisitor(AstAlways* nodep, AstNode* exprp, bool original) {
|
||||||
|
m_exprp = exprp;
|
||||||
|
m_original = original;
|
||||||
|
m_state = STATE_UNKNOWN;
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
|
||||||
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
|
||||||
|
// If there's no statements we shouldn't have had a resulting graph
|
||||||
|
// vertex asking for this creation
|
||||||
|
}
|
||||||
|
virtual ~GaterBodyVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Create clock gaters
|
||||||
|
|
||||||
|
class GaterVisitor : public GaterBaseVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// Cleared on Always
|
||||||
|
// AstVarScope::user1p() -> GaterVarVertex*
|
||||||
|
// AstAlways::user4() -> bool. True indicates processed
|
||||||
|
// Cleared on each new Always
|
||||||
|
// AstVarScope::user2p() -> AstAlways* moving this variable to
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
AstUser2InUse m_inuser2;
|
||||||
|
AstUser4InUse m_inuser4;
|
||||||
|
|
||||||
|
// GRAPH STATE
|
||||||
|
// Cleared on simplify
|
||||||
|
// Vertex::user() -> VarUsage: Mark of which if/else edges are hit
|
||||||
|
|
||||||
|
// TYPES
|
||||||
|
VU_DEFINE;
|
||||||
|
|
||||||
|
enum MiscConsts {
|
||||||
|
IF_DEPTH_MAX = 4, // IFs deep we bother to analyze
|
||||||
|
DOMAINS_MAX = 32 // Clock domains before avoiding O(N^2) blowup
|
||||||
|
};
|
||||||
|
|
||||||
|
// MEMBERS
|
||||||
|
string m_nonopt; // Reason block is not optimizable
|
||||||
|
V3Double0 m_statGaters; // Statistic tracking
|
||||||
|
V3Double0 m_statBits; // Statistic tracking
|
||||||
|
bool m_directlyUnderAlw; // Immediately under Always or If
|
||||||
|
int m_ifDepth; // Depth of IF statements
|
||||||
|
int m_numIfs; // Number of IF statements
|
||||||
|
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||||
|
GaterPliVertex* m_pliVertexp; // Element specifying PLI ordering
|
||||||
|
GaterHeadVertex* m_headVertexp; // Top vertex
|
||||||
|
V3GraphVertex* m_aboveVertexp; // Vertex above this point in tree
|
||||||
|
uint32_t m_aboveTrue; // Vertex above this point is true branch
|
||||||
|
AstVarScope* m_stmtVscp; // Current statement had variable assigned
|
||||||
|
bool m_stmtInPli; // Current statement has PLI
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
void nonOptimizable(AstNode* nodep, const char* reasonp) {
|
||||||
|
if (m_nonopt=="") {
|
||||||
|
UINFO(9," Nonopt: "<<reasonp<<": "<<nodep<<endl);
|
||||||
|
m_nonopt = reasonp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void scoreboardPli(AstNode* nodep) {
|
||||||
|
// Order all PLI statements with other PLI statements
|
||||||
|
// This insures $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) {
|
||||||
|
m_pliVertexp = new GaterPliVertex(&m_graph);
|
||||||
|
}
|
||||||
|
if (m_stmtVscp) { // Already saw a variable, be sure to mark it!
|
||||||
|
GaterVarVertex* varVtxp = (GaterVarVertex*)(m_stmtVscp->user1p());
|
||||||
|
new GaterEdge(&m_graph, m_pliVertexp, varVtxp, VU_PLI);
|
||||||
|
}
|
||||||
|
m_stmtInPli = true; // Mark all followon variables too
|
||||||
|
}
|
||||||
|
|
||||||
|
// METHODS -- GRAPH stuff
|
||||||
|
void simplifyGraph() {
|
||||||
|
if (debug()>=9) m_graph.dumpDotFilePrefixed("gater_init", false);
|
||||||
|
|
||||||
|
// We now have all PLI variables with edges FROM the pli vertex
|
||||||
|
simplifyPli();
|
||||||
|
if (debug()>=9) m_graph.dumpDotFilePrefixed("gater_pli", false);
|
||||||
|
|
||||||
|
// Any vertex that points along both true & false path to variable
|
||||||
|
// can be simplfied so parent points to that vertex. Any vertex
|
||||||
|
// that points to a (great...) grandparent of a variable can just
|
||||||
|
// point to the edge.
|
||||||
|
m_graph.userClearVertices(); // user() will contain VarUsage
|
||||||
|
simplifyIfElseRecurse(m_headVertexp);
|
||||||
|
if (debug()>=9) m_graph.dumpDotFilePrefixed("gater_ifelse", false);
|
||||||
|
|
||||||
|
m_graph.userClearVertices(); // user() will contain VarUsage
|
||||||
|
simplifyGrandRecurse(m_headVertexp, 1);
|
||||||
|
if (debug()>=9) m_graph.dumpDotFilePrefixed("gater_grand", false);
|
||||||
|
|
||||||
|
simplifyRemoveUngated(m_headVertexp);
|
||||||
|
|
||||||
|
// Give all signals with same gating term same color
|
||||||
|
graphColorSameFeeder();
|
||||||
|
|
||||||
|
if (debug()>=9) m_graph.dumpDotFilePrefixed("gater_done", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyPli() {
|
||||||
|
// For now, we'll not gate any logic with PLI lvariables in it. In
|
||||||
|
// the future we may move PLI statements. One way to do so is to
|
||||||
|
// all below pli VARs to go IfVertex -> PliVertex -> VarVertex then
|
||||||
|
// they all must get colored the same. There may be a lot of
|
||||||
|
// duplicated edges to the PLI; they'll need cleanup. All of the
|
||||||
|
// later optimizations need to deal, and the GaterBodyVisitor needs
|
||||||
|
// to know how to move them.
|
||||||
|
if (m_pliVertexp) {
|
||||||
|
// Follow PLI out edges to find all relevant variables
|
||||||
|
for (V3GraphEdge* nextp,* edgep = m_pliVertexp->outBeginp(); edgep; edgep = nextp) {
|
||||||
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
|
if (GaterVarVertex* vVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
||||||
|
vVxp->unlinkDelete(&m_graph); vVxp=NULL; edgep=NULL;
|
||||||
|
} else {
|
||||||
|
m_graph.dump();
|
||||||
|
v3fatalSrc("PLI vertex points to non-signal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_pliVertexp->unlinkDelete(&m_graph); m_pliVertexp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyIfElseRecurse(V3GraphVertex* vertexp) {
|
||||||
|
// From bottom-up, propagate duplicate IF/ELSE branches to grandparent
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
simplifyIfElseRecurse(edgep->top());
|
||||||
|
}
|
||||||
|
//UINFO(9,"IERecurse "<<vertexp<<endl);
|
||||||
|
if (dynamic_cast<GaterIfVertex*>(vertexp)) {
|
||||||
|
// Clear indications
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
edgep->top()->user(VU_NONE);
|
||||||
|
}
|
||||||
|
// Mark nodes on to/from side
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
V3GraphVertex* toVxp = edgep->top();
|
||||||
|
GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
|
||||||
|
// We may mark this twice in one pass - if so it's duplicated; no worries
|
||||||
|
if (cedgep->ifelseTrue()) toVxp->user(toVxp->user() | VU_IF);
|
||||||
|
if (cedgep->ifelseFalse()) toVxp->user(toVxp->user() | VU_ELSE);
|
||||||
|
//UINFO(9," mark "<<edgep<<" "<<toVxp<<endl);
|
||||||
|
}
|
||||||
|
// Any with both IF & ELSE mark get removal mark, and new parent edge
|
||||||
|
for (V3GraphEdge* nextp,* edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||||
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
|
V3GraphVertex* toVxp = edgep->top();
|
||||||
|
//UINFO(9," to "<<toVxp->user()<<" "<<toVxp<<endl);
|
||||||
|
if ((toVxp->user() & VU_IF) && (toVxp->user() & VU_ELSE)) {
|
||||||
|
edgep->unlinkDelete(); edgep = NULL;
|
||||||
|
if (!(toVxp->user() & VU_MADE)) { // Make an edge only once
|
||||||
|
toVxp->user(toVxp->user() | VU_MADE);
|
||||||
|
GaterEdge* inedgep = static_cast<GaterEdge*>(vertexp->inBeginp());
|
||||||
|
V3GraphVertex* grandparent = inedgep->fromp();
|
||||||
|
new GaterEdge(&m_graph, grandparent, toVxp, inedgep->ifelse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyGrandRecurse(V3GraphVertex* vertexp, uint32_t depth) {
|
||||||
|
// From top-down delete any vars that grandparents source
|
||||||
|
// IE A -> B -> C -> VAR
|
||||||
|
// \----------^
|
||||||
|
//UINFO(9,"GRecurse "<<depth<<" "<<vertexp<<endl);
|
||||||
|
// Mark all variables to be swept
|
||||||
|
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||||
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
|
if (GaterVarVertex* toVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
||||||
|
if (toVxp->user() && toVxp->user() < depth) {
|
||||||
|
// A recursion "above" us marked it,
|
||||||
|
// Remove this edge, it's redundant with the upper edge
|
||||||
|
edgep->unlinkDelete(); edgep=NULL;
|
||||||
|
} else {
|
||||||
|
GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
|
||||||
|
if (cedgep->ifelseBoth()) {
|
||||||
|
toVxp->user(depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Recurse
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
simplifyGrandRecurse(edgep->top(), depth+1);
|
||||||
|
}
|
||||||
|
// Clean our marks
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
V3GraphVertex* toVxp = edgep->top();
|
||||||
|
if (toVxp->user() && toVxp->user() < depth) { // A recursion "above" us marked it; don't mess with it
|
||||||
|
} else {
|
||||||
|
toVxp->user(0); // We marked it originally, so unmark now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Delete any If nodes with no children
|
||||||
|
// Last, as want bottom-up cleanup
|
||||||
|
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||||
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
|
if (GaterIfVertex* toVxp = dynamic_cast<GaterIfVertex*>(edgep->top())) {
|
||||||
|
if (!toVxp->outBeginp()) {
|
||||||
|
if (!nextp || nextp->top() != edgep->top()) { // Else next would disappear; we'll do it next loop
|
||||||
|
toVxp->unlinkDelete(&m_graph); toVxp=NULL; edgep=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simplifyRemoveUngated(V3GraphVertex* vertexp) {
|
||||||
|
// Remove variables that are ungated
|
||||||
|
// At this point, any variable under the head is ungated
|
||||||
|
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||||
|
nextp = edgep->outNextp(); // We may edit the list
|
||||||
|
if (GaterVarVertex* toVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
|
||||||
|
if (!nextp || nextp->top() != edgep->top()) { // Else next would disappear; we'll do it next loop
|
||||||
|
toVxp->unlinkDelete(&m_graph); toVxp=NULL; edgep=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void graphColorSameFeeder() {
|
||||||
|
// Assign same color to all destination vertices that have same
|
||||||
|
// subgraph feeding into them
|
||||||
|
// (I.E. all "from" nodes are common within each color)
|
||||||
|
// We could hash, but instead it's faster to sort edges, so we know
|
||||||
|
// the same edge list is always adjacent. The result is a
|
||||||
|
// O(vertices*edges) loop, but we'd need that to hash too.
|
||||||
|
if (debug()>9) { cout<<"PreColor:\n"; m_graph.dump(); }
|
||||||
|
|
||||||
|
m_graph.sortEdges();
|
||||||
|
|
||||||
|
// Now sort vertices, so same inbound edge set ends up adjacent
|
||||||
|
m_graph.sortVertices();
|
||||||
|
|
||||||
|
// Now walk and assign colors; same color is adjacent
|
||||||
|
m_graph.clearColors();
|
||||||
|
m_graph.userClearEdges(); // Used by newExprFromGraph
|
||||||
|
uint32_t color = 1;
|
||||||
|
GaterVarVertex* lastVxp = NULL;
|
||||||
|
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
|
if (GaterVarVertex* vVxp = dynamic_cast<GaterVarVertex*>(vertexp)) {
|
||||||
|
if (!vVxp->inBeginp()) {
|
||||||
|
// At this point, any variable not linked is an error
|
||||||
|
// (It should have at least landed under the Head node)
|
||||||
|
vVxp->nodep()->v3fatalSrc("Variable became stranded in clk gate detection\n");
|
||||||
|
}
|
||||||
|
if (!lastVxp || vVxp->sortCmp(lastVxp)) {
|
||||||
|
// Different sources for this new node
|
||||||
|
color++;
|
||||||
|
}
|
||||||
|
vVxp->color(color);
|
||||||
|
lastVxp = vVxp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug()>9) { cout<<"PostColor:\n"; m_graph.dump(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode* newExprFromGraph(GaterVarVertex* vertexp) {
|
||||||
|
// Recurse backwards, then form equation on return path
|
||||||
|
// We could use user()!=0, but zeroing it is slow, so instead we'll mark with a generation
|
||||||
|
// We get equations like "a | (!a & b)" which obviously could be reduced here,
|
||||||
|
// instead out of generality, there's a V3Const::matchOrAndNot that'll clean it up
|
||||||
|
static uint32_t s_generation = 0;
|
||||||
|
++s_generation;
|
||||||
|
nafgMarkRecurse(vertexp, s_generation);
|
||||||
|
AstNode* nodep = nafgCreateRecurse(m_headVertexp, s_generation);
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," GateExpr: ");
|
||||||
|
return nodep;
|
||||||
|
}
|
||||||
|
void nafgMarkRecurse(V3GraphVertex* vertexp, uint32_t generation) {
|
||||||
|
// Backwards mark user() on the path we recurse
|
||||||
|
//UINFO(9," nafgMark: v "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
|
||||||
|
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||||
|
//UINFO(9," nafgMark: "<<(void*)(edgep)<<" "<<edgep->name()<<endl);
|
||||||
|
edgep->user(generation);
|
||||||
|
nafgMarkRecurse(edgep->fromp(), generation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AstNode* nafgCreateRecurse(V3GraphVertex* vertexp, uint32_t generation) {
|
||||||
|
// Forewards follow user() marked previously and build tree
|
||||||
|
AstNode* nodep = NULL;
|
||||||
|
// OR across all edges found at this level
|
||||||
|
//UINFO(9," nafgEnter: v "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
|
||||||
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||||
|
if (edgep->user() == generation) {
|
||||||
|
GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
|
||||||
|
AstNode* eqnp = NULL;
|
||||||
|
//UINFO(9," nafgFollow: "<<(void*)(edgep)<<" "<<edgep->name()<<endl);
|
||||||
|
if (dynamic_cast<GaterHeadVertex*>(edgep->fromp())) {
|
||||||
|
// Just OR in all lower terms
|
||||||
|
eqnp = nafgCreateRecurse(edgep->top(), generation);
|
||||||
|
} else if (GaterIfVertex* cVxp = dynamic_cast<GaterIfVertex*>(edgep->fromp())) {
|
||||||
|
// Edges from IFs represent a real IF branch in the equation tree
|
||||||
|
//UINFO(9," ifver "<<(void*)(edgep)<<" cc"<<edgep->dotColor()<<endl);
|
||||||
|
eqnp = cVxp->nodep()->condp()->cloneTree(true);
|
||||||
|
if (eqnp && cedgep->ifelseFalse()) {
|
||||||
|
eqnp = new AstNot(eqnp->fileline(),eqnp);
|
||||||
|
}
|
||||||
|
// We need to AND this term onto whatever was found below it
|
||||||
|
AstNode* belowp = nafgCreateRecurse(edgep->top(), generation);
|
||||||
|
if (belowp) eqnp = new AstAnd(eqnp->fileline(),eqnp,belowp);
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
else nodep = eqnp;
|
||||||
|
//if (debug()>=9) nodep->dumpTree(cout," followExpr: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//UINFO(9," nafgExit: "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
|
||||||
|
return nodep;
|
||||||
|
}
|
||||||
|
|
||||||
|
void newAlwaysTrees(AstAlways* nodep) {
|
||||||
|
// Across all variables we're moving
|
||||||
|
uint32_t lastColor = 0;
|
||||||
|
AstNode* lastExprp = NULL;
|
||||||
|
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
|
if (GaterVarVertex* vVxp = dynamic_cast<GaterVarVertex*>(vertexp)) {
|
||||||
|
if (!lastExprp || lastColor != vVxp->color()) {
|
||||||
|
lastColor = vVxp->color();
|
||||||
|
// Create the block we've just finished
|
||||||
|
if (lastExprp) newAlwaysTree(nodep, lastExprp); // Duplicate below
|
||||||
|
// New expression for this color
|
||||||
|
lastExprp = newExprFromGraph(vVxp);
|
||||||
|
}
|
||||||
|
// Mark variable to move
|
||||||
|
if (vVxp->nodep()->user2p()) vVxp->nodep()->v3fatalSrc("One variable got marked under two gaters");
|
||||||
|
vVxp->nodep()->user2p(lastExprp);
|
||||||
|
m_statBits += vVxp->nodep()->width(); // Moving a wide bus counts more!
|
||||||
|
// There shouldn't be two possibilities we want to
|
||||||
|
// move to, IE {A,B} <= Z because we marked such
|
||||||
|
// things as unoptimizable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create the final block we've just finished
|
||||||
|
if (lastExprp) newAlwaysTree(nodep, lastExprp); // Duplicate above
|
||||||
|
}
|
||||||
|
|
||||||
|
void newAlwaysTree(AstAlways* nodep, AstNode* exprp) {
|
||||||
|
// Create new always with specified gating expression
|
||||||
|
// Relevant vars are already marked with user2p
|
||||||
|
|
||||||
|
// Should we put the gater under the always itself,
|
||||||
|
// or make a new signal?
|
||||||
|
// New signal: May cause replicated logic until we can combine
|
||||||
|
// Need way to toggle signal on complicated pos/negedge
|
||||||
|
// Under Always: More complicated, may not propagate logic with gateer
|
||||||
|
// Untill we get better gate optimization, we'll go this route.
|
||||||
|
//#define GATER_NOP
|
||||||
|
#ifdef GATER_NOP
|
||||||
|
// For testing only, don't clock gate but still make new always
|
||||||
|
AstSenTree* sensesp = nodep->sensesp()->cloneTree(true);
|
||||||
|
#else
|
||||||
|
// Make a SenGate
|
||||||
|
AstSenItem* oldsenitemsp = nodep->sensesp()->sensesp()->castSenItem();
|
||||||
|
if (!oldsenitemsp) nodep->v3fatalSrc("SenTree doesn't have any SenItem under it");
|
||||||
|
|
||||||
|
AstSenTree* sensesp = new AstSenTree(nodep->fileline(),
|
||||||
|
new AstSenGate(nodep->fileline(),
|
||||||
|
oldsenitemsp->cloneTree(true),
|
||||||
|
exprp));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Make new body; note clone will preserve user2p() indicating moving vars
|
||||||
|
AstNode* bodyp = nodep->bodysp()->cloneTree(true);
|
||||||
|
|
||||||
|
AstAlways* alwp = new AstAlways(nodep->fileline(),
|
||||||
|
sensesp,
|
||||||
|
bodyp);
|
||||||
|
|
||||||
|
alwp->user4(1); // No need to process the new always again!
|
||||||
|
nodep->addNextHere(alwp);
|
||||||
|
|
||||||
|
// Blow moved statements from old body
|
||||||
|
GaterBodyVisitor(nodep,exprp,true);
|
||||||
|
// Blow old statements from new body
|
||||||
|
GaterBodyVisitor(alwp,exprp,false);
|
||||||
|
|
||||||
|
m_statGaters++;
|
||||||
|
if (debug()>=9) alwp->dumpTree(cout," new: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
|
if (debug()>=9) cout<<endl<<endl<<endl;
|
||||||
|
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
||||||
|
if (nodep->user4()) return;
|
||||||
|
nodep->user4(1);
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," Alwin: ");
|
||||||
|
|
||||||
|
// Look for constructs we can't optimize
|
||||||
|
// Form graph with Vertices at each IF, and each Variable
|
||||||
|
m_aboveTrue = VU_IF | VU_ELSE;
|
||||||
|
iterateChildrenAlw(nodep, true);
|
||||||
|
|
||||||
|
// Other reasons to not optimize
|
||||||
|
if (!m_numIfs) nonOptimizable(nodep, "No if statements");
|
||||||
|
|
||||||
|
// Something to optimize, oh my!
|
||||||
|
if (m_nonopt!="") {
|
||||||
|
UINFO(5, " Gater non-opt: "<<m_nonopt<<endl);
|
||||||
|
} else {
|
||||||
|
// Process it
|
||||||
|
simplifyGraph();
|
||||||
|
|
||||||
|
// See how much moves
|
||||||
|
uint32_t lastColor = 0;
|
||||||
|
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
|
if (GaterVarVertex* vVxp = dynamic_cast<GaterVarVertex*>(vertexp)) {
|
||||||
|
if (lastColor < vVxp->color()) {
|
||||||
|
lastColor = vVxp->color();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastColor == 0) { // Nothing we moved!
|
||||||
|
nonOptimizable(nodep, "Nothing moved");
|
||||||
|
}
|
||||||
|
else if (lastColor > DOMAINS_MAX) {
|
||||||
|
// Our move algorithm is fairly slow and if we're splitting
|
||||||
|
// up too much it'll get really nasty. It's probably a bad
|
||||||
|
// move for performance to split too much, anyhow, as the
|
||||||
|
// number of gaters will result in calling many small c functions.
|
||||||
|
nonOptimizable(nodep, "Too much moved");
|
||||||
|
}
|
||||||
|
if (m_nonopt=="") {
|
||||||
|
newAlwaysTrees(nodep);
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," Gaterout: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UINFO(5, " Gater done"<<endl);
|
||||||
|
}
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->lvalue()) {
|
||||||
|
AstVarScope* vscp = nodep->varScopep();
|
||||||
|
if (nodep->varp()->isSigPublic()) {
|
||||||
|
// Public signals shouldn't be changed, pli code might be messing with them
|
||||||
|
scoreboardPli(nodep);
|
||||||
|
}
|
||||||
|
// If another lvalue in this node, give up optimizing.
|
||||||
|
// We could just not optimize this variable, but we've already marked the
|
||||||
|
// other variable as optimizable, so we can instead pretend it's a PLI node.
|
||||||
|
if (m_stmtVscp) {
|
||||||
|
UINFO(5, " Multiple lvalues in one statement: "<<nodep<<endl);
|
||||||
|
scoreboardPli(nodep); // This will set m_stmtInPli
|
||||||
|
}
|
||||||
|
m_stmtVscp = vscp;
|
||||||
|
// Find, or make new Vertex
|
||||||
|
GaterVarVertex* vertexp = (GaterVarVertex*)(vscp->user1p());
|
||||||
|
if (!vertexp) {
|
||||||
|
vertexp = new GaterVarVertex(&m_graph, vscp);
|
||||||
|
vscp->user1p(vertexp);
|
||||||
|
}
|
||||||
|
new GaterEdge(&m_graph, m_aboveVertexp, vertexp, m_aboveTrue);
|
||||||
|
if (m_stmtInPli) {
|
||||||
|
new GaterEdge(&m_graph, m_pliVertexp, vertexp, VU_PLI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
||||||
|
m_ifDepth++;
|
||||||
|
bool allowGater = m_directlyUnderAlw && m_ifDepth <= IF_DEPTH_MAX;
|
||||||
|
if (allowGater) {
|
||||||
|
GaterCondVisitor condVisitor(nodep->condp());
|
||||||
|
if (!condVisitor.isSimple()) {
|
||||||
|
// Don't clear optimization, simply drop this IF as part of the gating
|
||||||
|
UINFO(5," IFnon-simple-condition: "<<nodep<<endl);
|
||||||
|
allowGater = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allowGater) {
|
||||||
|
// IF burried under something complicated
|
||||||
|
iterateChildrenAlw(nodep, true);
|
||||||
|
} else {
|
||||||
|
UINFO(5, " IF: "<<nodep<<endl);
|
||||||
|
m_numIfs++;
|
||||||
|
// Recurse to next level of if.
|
||||||
|
V3GraphVertex* lastabovep = m_aboveVertexp;
|
||||||
|
uint32_t lasttrue = m_aboveTrue;
|
||||||
|
GaterIfVertex* vertexp = new GaterIfVertex(&m_graph, nodep);
|
||||||
|
new GaterEdge(&m_graph, m_aboveVertexp, vertexp, m_aboveTrue);
|
||||||
|
{
|
||||||
|
nodep->condp()->iterateAndNext(*this); // directlyUnder stays as-is
|
||||||
|
}
|
||||||
|
{
|
||||||
|
m_aboveVertexp = vertexp; // Vars will point at this edge
|
||||||
|
m_aboveTrue = VU_IF;
|
||||||
|
nodep->ifsp()->iterateAndNext(*this); // directlyUnder stays as-is (true)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
m_aboveVertexp = vertexp; // Vars will point at this edge
|
||||||
|
m_aboveTrue = VU_ELSE;
|
||||||
|
nodep->elsesp()->iterateAndNext(*this); // directlyUnder stays as-is (true)
|
||||||
|
}
|
||||||
|
m_aboveVertexp = lastabovep;
|
||||||
|
m_aboveTrue = lasttrue;
|
||||||
|
}
|
||||||
|
m_ifDepth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
||||||
|
// iterateChildrenAlw will detect this is a statement for us
|
||||||
|
iterateChildrenAlw(nodep, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||||
|
// Note NOT AssignDly; handled above, We'll just mark this block as
|
||||||
|
// not optimizable.
|
||||||
|
//
|
||||||
|
// A future alternative is to look for any lvalues that are also
|
||||||
|
// variables in the sensitivity list, or rvalues in this block. If
|
||||||
|
// any hit, disable optimization. Unlikely to be useful (For loops
|
||||||
|
// being an exception, but they're already unrolled.)
|
||||||
|
nonOptimizable(nodep, "Non-delayed assignment");
|
||||||
|
// No reason to iterate.
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||||
|
if (!nodep->isClocked()) {
|
||||||
|
nonOptimizable(nodep, "Non-clocked sensitivity");
|
||||||
|
}
|
||||||
|
iterateChildrenAlw(nodep, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
if (m_nonopt=="") { // Else accelerate
|
||||||
|
iterateChildrenAlw(nodep, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void iterateChildrenAlw(AstNode* nodep, bool under) {
|
||||||
|
// **** USE THIS INSTEAD OF iterateChildren!
|
||||||
|
// Note If visitor doesn't call here; does it its own way
|
||||||
|
bool lastdua = m_directlyUnderAlw;
|
||||||
|
AstVarScope* lastvscp = m_stmtVscp;
|
||||||
|
bool lastpli = m_stmtInPli;
|
||||||
|
m_directlyUnderAlw = under;
|
||||||
|
if (nodep->castNodeStmt()) { // Restored below
|
||||||
|
UINFO(9," Stmt: "<<nodep<<endl);
|
||||||
|
m_stmtVscp = NULL;
|
||||||
|
m_stmtInPli = false;
|
||||||
|
}
|
||||||
|
if (!nodep->isSplittable()) {
|
||||||
|
// May also be a new statement (above if); if so we mark it immediately
|
||||||
|
UINFO(9," NotSplittable "<<nodep<<endl);
|
||||||
|
scoreboardPli(nodep);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_directlyUnderAlw = lastdua;
|
||||||
|
if (nodep->castNodeStmt()) { // Reset what set above; else propagate up to above statement
|
||||||
|
m_stmtVscp = lastvscp;
|
||||||
|
m_stmtInPli = lastpli;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
GaterVisitor(AstNode* nodep) {
|
||||||
|
// AstAlways visitor does the real work, so most zeroing needs to be in clear()
|
||||||
|
clear();
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
void clear() {
|
||||||
|
m_nonopt = "";
|
||||||
|
m_directlyUnderAlw = false;
|
||||||
|
m_ifDepth = 0;
|
||||||
|
m_numIfs = 0;
|
||||||
|
AstNode::user1ClearTree();
|
||||||
|
AstNode::user2ClearTree();
|
||||||
|
// Prepare graph
|
||||||
|
m_graph.clear();
|
||||||
|
GaterVertex::clearRank();
|
||||||
|
m_pliVertexp = NULL;
|
||||||
|
m_headVertexp = new GaterHeadVertex(&m_graph);
|
||||||
|
m_aboveVertexp = m_headVertexp;
|
||||||
|
m_aboveTrue = false;
|
||||||
|
m_stmtVscp = NULL;
|
||||||
|
m_stmtInPli = false;
|
||||||
|
}
|
||||||
|
virtual ~GaterVisitor() {
|
||||||
|
V3Stats::addStat("Optimizations, Gaters inserted", m_statGaters);
|
||||||
|
V3Stats::addStat("Optimizations, Gaters impacted bits", m_statBits);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Active class functions
|
||||||
|
|
||||||
|
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");
|
||||||
|
//GaterVisitor visitor (nodep);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Break always into clock gated blocks
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2009 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef _V3CLKGATER_H_
|
||||||
|
#define _V3CLKGATER_H_ 1
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "V3Error.h"
|
||||||
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
class V3ClkGater {
|
||||||
|
public:
|
||||||
|
static void clkGaterAll(AstNetlist* nodep);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
+103
-64
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Clock's Transformations:
|
// V3Clock's Transformations:
|
||||||
//
|
//
|
||||||
// Top Scope:
|
// Top Scope:
|
||||||
// Check created ACTIVEs
|
// Check created ACTIVEs
|
||||||
// Compress adjacent ACTIVEs with same sensitivity list
|
// Compress adjacent ACTIVEs with same sensitivity list
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -51,8 +51,10 @@ class ClockVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Cleared each Module:
|
// Cleared each Module:
|
||||||
// AstVarScope::userp() -> AstVarScope*. Temporary signal that was created.
|
// AstVarScope::user1p() -> AstVarScope*. Temporary signal that was created.
|
||||||
// AstVarScope::user2p() -> AstVarScope*. Temporary signal for change detects
|
// AstVarScope::user2p() -> AstVarScope*. Temporary signal for change detects
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
AstUser2InUse m_inuser2;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
enum { DOUBLE_OR_RATE = 10 }; // How many | per ||, Determined experimentally as best
|
enum { DOUBLE_OR_RATE = 10 }; // How many | per ||, Determined experimentally as best
|
||||||
@@ -70,20 +72,25 @@ private:
|
|||||||
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
|
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
|
||||||
AstIf* m_lastIfp; // Last sensitivity if active to add more under
|
AstIf* m_lastIfp; // Last sensitivity if active to add more under
|
||||||
int m_stableNum; // Number of each untilstable
|
int m_stableNum; // Number of each untilstable
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
||||||
if (vscp->userp()) return ((AstVarScope*)vscp->userp());
|
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
|
||||||
AstVar* varp = vscp->varp();
|
AstVar* varp = vscp->varp();
|
||||||
if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
if (varp->width()!=1) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
|
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
|
||||||
AstVar* newvarp
|
AstVar* newvarp
|
||||||
= new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname); // No range; 1 bit.
|
= new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, NULL, NULL); // No range; 1 bit.
|
||||||
newvarp->width(1,1);
|
newvarp->width(1,1);
|
||||||
m_modp->addStmtp(newvarp);
|
m_modp->addStmtp(newvarp);
|
||||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||||
vscp->userp(newvscp);
|
vscp->user1p(newvscp);
|
||||||
m_scopep->addVarp(newvscp);
|
m_scopep->addVarp(newvscp);
|
||||||
// At bottom, assign them
|
// At bottom, assign them
|
||||||
AstAssign* finalp
|
AstAssign* finalp
|
||||||
@@ -107,48 +114,66 @@ private:
|
|||||||
m_scopep->addVarp(newvscp);
|
m_scopep->addVarp(newvscp);
|
||||||
return newvscp;
|
return newvscp;
|
||||||
}
|
}
|
||||||
AstNode* createSenseEquation(AstSenTree* nodep) {
|
AstNode* createSenItemEquation(AstSenItem* nodep) {
|
||||||
|
// We know the var is clean, and one bit, so we use binary ops
|
||||||
|
// for speed instead of logical ops.
|
||||||
|
// POSEDGE: var & ~var_last
|
||||||
|
// NEGEDGE: ~var & var_last
|
||||||
|
// BOTHEDGE: var ^ var_last
|
||||||
|
// HIGHEDGE: var
|
||||||
|
// LOWEDGE: ~var
|
||||||
|
AstNode* newp = NULL;
|
||||||
|
AstVarScope* clkvscp = nodep->varrefp()->varScopep();
|
||||||
|
if (nodep->edgeType()==AstEdgeType::POSEDGE) {
|
||||||
|
AstVarScope* lastVscp = getCreateLastClk(clkvscp);
|
||||||
|
newp = new AstAnd(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(),
|
||||||
|
nodep->varrefp()->varScopep(), false),
|
||||||
|
new AstNot(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(),
|
||||||
|
lastVscp, false)));
|
||||||
|
} else if (nodep->edgeType()==AstEdgeType::NEGEDGE) {
|
||||||
|
AstVarScope* lastVscp = getCreateLastClk(clkvscp);
|
||||||
|
newp = new AstAnd(nodep->fileline(),
|
||||||
|
new AstNot(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(),
|
||||||
|
nodep->varrefp()->varScopep(), false)),
|
||||||
|
new AstVarRef(nodep->fileline(), lastVscp, false));
|
||||||
|
} else if (nodep->edgeType()==AstEdgeType::BOTHEDGE) {
|
||||||
|
AstVarScope* lastVscp = getCreateLastClk(clkvscp);
|
||||||
|
newp = new AstXor(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(),
|
||||||
|
nodep->varrefp()->varScopep(), false),
|
||||||
|
new AstVarRef(nodep->fileline(), lastVscp, false));
|
||||||
|
} else if (nodep->edgeType()==AstEdgeType::HIGHEDGE) {
|
||||||
|
newp = new AstVarRef(nodep->fileline(),
|
||||||
|
clkvscp, false);
|
||||||
|
} else if (nodep->edgeType()==AstEdgeType::LOWEDGE) {
|
||||||
|
newp = new AstNot(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(),
|
||||||
|
clkvscp, false));
|
||||||
|
} else {
|
||||||
|
nodep->v3fatalSrc("Bad edge type");
|
||||||
|
}
|
||||||
|
return newp;
|
||||||
|
}
|
||||||
|
AstNode* createSenGateEquation(AstSenGate* nodep) {
|
||||||
|
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||||
|
createSenseEquation(nodep->sensesp()),
|
||||||
|
nodep->rhsp()->cloneTree(true));
|
||||||
|
return newp;
|
||||||
|
}
|
||||||
|
AstNode* createSenseEquation(AstNodeSenItem* nodesp) {
|
||||||
|
// Nodep may be a list of elements; we need to walk it
|
||||||
AstNode* senEqnp = NULL;
|
AstNode* senEqnp = NULL;
|
||||||
for (AstSenItem* senp = nodep->sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
for (AstNodeSenItem* senp = nodesp; senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
// We know the var is clean, and one bit, so we use binary ops
|
|
||||||
// for speed instead of logical ops.
|
|
||||||
// POSEDGE: var & ~var_last
|
|
||||||
// NEGEDGE: ~var & var_last
|
|
||||||
// BOTHEDGE: var ^ var_last
|
|
||||||
// HIGHEDGE: var
|
|
||||||
// LOWEDGE: ~var
|
|
||||||
AstVarScope* lastVscp = senp->varrefp()->varScopep()->userp()->castNode()->castVarScope();
|
|
||||||
AstNode* senOnep = NULL;
|
AstNode* senOnep = NULL;
|
||||||
if (senp->edgeType()==AstEdgeType::POSEDGE) {
|
if (AstSenItem* itemp = senp->castSenItem()) {
|
||||||
if (!lastVscp) senp->v3fatalSrc("No last var ptr?\n");
|
senOnep = createSenItemEquation(itemp);
|
||||||
senOnep = new AstAnd(senp->fileline(),
|
} else if (AstSenGate* itemp = senp->castSenGate()) {
|
||||||
new AstVarRef(senp->fileline(),
|
senOnep = createSenGateEquation(itemp);
|
||||||
senp->varrefp()->varScopep(), false),
|
|
||||||
new AstNot(senp->fileline(),
|
|
||||||
new AstVarRef(senp->fileline(),
|
|
||||||
lastVscp, false)));
|
|
||||||
} else if (senp->edgeType()==AstEdgeType::NEGEDGE) {
|
|
||||||
if (!lastVscp) senp->v3fatalSrc("No last var ptr?\n");
|
|
||||||
senOnep = new AstAnd(senp->fileline(),
|
|
||||||
new AstNot(senp->fileline(),
|
|
||||||
new AstVarRef(senp->fileline(),
|
|
||||||
senp->varrefp()->varScopep(), false)),
|
|
||||||
new AstVarRef(senp->fileline(), lastVscp, false));
|
|
||||||
} else if (senp->edgeType()==AstEdgeType::BOTHEDGE) {
|
|
||||||
if (!lastVscp) senp->v3fatalSrc("No last var ptr?\n");
|
|
||||||
senOnep = new AstXor(senp->fileline(),
|
|
||||||
new AstVarRef(senp->fileline(),
|
|
||||||
senp->varrefp()->varScopep(), false),
|
|
||||||
new AstVarRef(senp->fileline(), lastVscp, false));
|
|
||||||
} else if (senp->edgeType()==AstEdgeType::HIGHEDGE) {
|
|
||||||
senOnep = new AstVarRef(senp->fileline(),
|
|
||||||
senp->varrefp()->varScopep(), false);
|
|
||||||
} else if (senp->edgeType()==AstEdgeType::LOWEDGE) {
|
|
||||||
senOnep = new AstNot(senp->fileline(),
|
|
||||||
new AstVarRef(senp->fileline(),
|
|
||||||
senp->varrefp()->varScopep(), false));
|
|
||||||
} else {
|
} else {
|
||||||
senp->v3fatalSrc("Bad edge type");
|
senp->v3fatalSrc("Strange node under sentree");
|
||||||
}
|
}
|
||||||
if (senEqnp) {
|
if (senEqnp) {
|
||||||
// Add new OR to the sensitivity list equation
|
// Add new OR to the sensitivity list equation
|
||||||
@@ -160,14 +185,7 @@ private:
|
|||||||
return senEqnp;
|
return senEqnp;
|
||||||
}
|
}
|
||||||
AstIf* makeActiveIf(AstSenTree* sensesp) {
|
AstIf* makeActiveIf(AstSenTree* sensesp) {
|
||||||
for (AstSenItem* senp = sensesp->sensesp(); senp; senp=senp->nextp()->castSenItem()) {
|
AstNode* senEqnp = createSenseEquation(sensesp->sensesp());
|
||||||
if (senp->edgeType() != AstEdgeType::HIGHEDGE
|
|
||||||
&& senp->varrefp()) {
|
|
||||||
AstVarScope* oldvscp = senp->varrefp()->varScopep();
|
|
||||||
getCreateLastClk(oldvscp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AstNode* senEqnp = createSenseEquation(sensesp);
|
|
||||||
if (!senEqnp) sensesp->v3fatalSrc("No sense equation, shouldn't be in sequent activation.");
|
if (!senEqnp) sensesp->v3fatalSrc("No sense equation, shouldn't be in sequent activation.");
|
||||||
AstIf* newifp = new AstIf (sensesp->fileline(),
|
AstIf* newifp = new AstIf (sensesp->fileline(),
|
||||||
senEqnp, NULL, NULL);
|
senEqnp, NULL, NULL);
|
||||||
@@ -184,8 +202,8 @@ private:
|
|||||||
m_topScopep=nodep;
|
m_topScopep=nodep;
|
||||||
m_scopep = nodep->scopep();
|
m_scopep = nodep->scopep();
|
||||||
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?\n");
|
||||||
//VV***** We reset all userp()
|
//VV***** We reset all user1p()
|
||||||
AstNode::userClearTree();
|
AstNode::user1ClearTree();
|
||||||
// Make top functions
|
// Make top functions
|
||||||
{
|
{
|
||||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
|
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
|
||||||
@@ -245,12 +263,13 @@ private:
|
|||||||
//UINFO(4," MOD "<<nodep<<endl);
|
//UINFO(4," MOD "<<nodep<<endl);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_stableNum = 0;
|
m_stableNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_modp= NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
//UINFO(4," SCOPE "<<nodep<<endl);
|
//UINFO(4," SCOPE "<<nodep<<endl);
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (AstNode* movep = nodep->finalClksp()) {
|
if (AstNode* movep = nodep->finalClksp()) {
|
||||||
if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope");
|
if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope");
|
||||||
movep->unlinkFrBackWithNext();
|
movep->unlinkFrBackWithNext();
|
||||||
@@ -278,6 +297,26 @@ private:
|
|||||||
}
|
}
|
||||||
nodep->deleteTree(); nodep = NULL;
|
nodep->deleteTree(); nodep = NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
||||||
|
//nodep->dumpTree(cout,"ct:");
|
||||||
|
//COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||||
|
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||||
|
AstNode* incp = nodep->incp()->unlinkFrBack();
|
||||||
|
AstNode* origp = nodep->origp()->unlinkFrBack();
|
||||||
|
AstNode* changep = nodep->changep()->unlinkFrBack();
|
||||||
|
AstIf* newp = new AstIf(nodep->fileline(),
|
||||||
|
new AstXor(nodep->fileline(),
|
||||||
|
origp,
|
||||||
|
changep),
|
||||||
|
incp, NULL);
|
||||||
|
// We could add another IF to detect posedges, and only increment if so.
|
||||||
|
// It's another whole branch though verus a potential memory miss.
|
||||||
|
// We'll go with the miss.
|
||||||
|
newp->addIfsp(new AstAssign(nodep->fileline(),
|
||||||
|
changep->cloneTree(false),
|
||||||
|
origp->cloneTree(false)));
|
||||||
|
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||||
nodep->replaceWith(cmtp);
|
nodep->replaceWith(cmtp);
|
||||||
@@ -416,7 +455,7 @@ private:
|
|||||||
new AstConst(fl, 1)));
|
new AstConst(fl, 1)));
|
||||||
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
||||||
new AstConst(fl, 0)));
|
new AstConst(fl, 0)));
|
||||||
|
|
||||||
// Add stable variables & preinits
|
// Add stable variables & preinits
|
||||||
AstNode* setChglastp = NULL;
|
AstNode* setChglastp = NULL;
|
||||||
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+29
-17
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Combine common code into functions
|
// DESCRIPTION: Verilator: Combine common code into functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Combine's Transformations:
|
// V3Combine's Transformations:
|
||||||
//
|
//
|
||||||
// For every function that we spit out
|
// For every function that we spit out
|
||||||
// Examine code to find largest common blocks
|
// Examine code to find largest common blocks
|
||||||
// Hash each node depth first
|
// Hash each node depth first
|
||||||
@@ -32,13 +32,13 @@
|
|||||||
// Make new function
|
// Make new function
|
||||||
// Move common block to function
|
// Move common block to function
|
||||||
// Replace each common block ref with funccall
|
// Replace each common block ref with funccall
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -59,8 +59,14 @@
|
|||||||
class CombBaseVisitor : public AstNVisitor {
|
class CombBaseVisitor : public AstNVisitor {
|
||||||
protected:
|
protected:
|
||||||
// STATE
|
// STATE
|
||||||
//int debug() { return 9; }
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~CombBaseVisitor() {}
|
virtual ~CombBaseVisitor() {}
|
||||||
|
|
||||||
//***** optimization levels
|
//***** optimization levels
|
||||||
@@ -175,6 +181,9 @@ private:
|
|||||||
// AstCFunc::user3p() -> AstCFunc*, If set, replace ccalls to this func with new func
|
// AstCFunc::user3p() -> AstCFunc*, If set, replace ccalls to this func with new func
|
||||||
// AstNodeStmt::user3() -> AstNode*. True if to ignore this cell
|
// AstNodeStmt::user3() -> AstNode*. True if to ignore this cell
|
||||||
// AstNodeStmt::user4() -> V3Hashed::V3Hash. Hash value of this node (hash of 0 is illegal)
|
// AstNodeStmt::user4() -> V3Hashed::V3Hash. Hash value of this node (hash of 0 is illegal)
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
AstUser3InUse m_inuser3;
|
||||||
|
//AstUser4InUse part of V3Hashed
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
typedef enum {STATE_IDLE, STATE_HASH, STATE_DUP} CombineState;
|
typedef enum {STATE_IDLE, STATE_HASH, STATE_DUP} CombineState;
|
||||||
@@ -187,7 +196,7 @@ private:
|
|||||||
int m_modNFuncs; // Number of functions made
|
int m_modNFuncs; // Number of functions made
|
||||||
AstNode* m_walkLast1p; // Final node that is the same in duplicate list
|
AstNode* m_walkLast1p; // Final node that is the same in duplicate list
|
||||||
AstNode* m_walkLast2p; // Final node that is the same in duplicate list
|
AstNode* m_walkLast2p; // Final node that is the same in duplicate list
|
||||||
V3Hashed m_hashed; // Hash for every node
|
V3Hashed m_hashed; // Hash for every node in module
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void hashStatement(AstNode* nodep) {
|
void hashStatement(AstNode* nodep) {
|
||||||
@@ -280,7 +289,7 @@ private:
|
|||||||
if (node1p==node2p) continue;
|
if (node1p==node2p) continue;
|
||||||
//
|
//
|
||||||
// We need to mark iteration to prevent matching code inside code (abab matching in ababab)
|
// We need to mark iteration to prevent matching code inside code (abab matching in ababab)
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
AstNode::user1ClearTree(); // user1p() used on entire tree
|
||||||
m_walkLast1p = NULL;
|
m_walkLast1p = NULL;
|
||||||
m_walkLast2p = NULL;
|
m_walkLast2p = NULL;
|
||||||
int depth = walkDupCodeNext(node1p, node2p, 1);
|
int depth = walkDupCodeNext(node1p, node2p, 1);
|
||||||
@@ -306,7 +315,7 @@ private:
|
|||||||
|
|
||||||
int walkDupCodeNext(AstNode* node1p, AstNode* node2p, int level) {
|
int walkDupCodeNext(AstNode* node1p, AstNode* node2p, int level) {
|
||||||
// Find number of common statements between the two node1p_nextp's...
|
// Find number of common statements between the two node1p_nextp's...
|
||||||
if (node1p->userp() || node2p->userp()) return 0; // Already iterated
|
if (node1p->user1p() || node2p->user1p()) return 0; // Already iterated
|
||||||
if (node1p->user3p() || node2p->user3p()) return 0; // Already merged
|
if (node1p->user3p() || node2p->user3p()) return 0; // Already merged
|
||||||
if (!m_hashed.sameNodes(node1p,node2p)) return 0; // walk of tree has same comparison
|
if (!m_hashed.sameNodes(node1p,node2p)) return 0; // walk of tree has same comparison
|
||||||
V3Hash hashval(node1p->user4p());
|
V3Hash hashval(node1p->user4p());
|
||||||
@@ -314,8 +323,8 @@ private:
|
|||||||
//UINFO(9," wdup2 "<<level<<" "<<V3Hash(node2p->user4p())<<" "<<node2p<<endl);
|
//UINFO(9," wdup2 "<<level<<" "<<V3Hash(node2p->user4p())<<" "<<node2p<<endl);
|
||||||
m_walkLast1p = node1p;
|
m_walkLast1p = node1p;
|
||||||
m_walkLast2p = node2p;
|
m_walkLast2p = node2p;
|
||||||
node1p->user(true);
|
node1p->user1(true);
|
||||||
node2p->user(true);
|
node2p->user1(true);
|
||||||
if (node1p->nextp() && node2p->nextp()) {
|
if (node1p->nextp() && node2p->nextp()) {
|
||||||
return hashval.depth()+walkDupCodeNext(node1p->nextp(), node2p->nextp(), level+1);
|
return hashval.depth()+walkDupCodeNext(node1p->nextp(), node2p->nextp(), level+1);
|
||||||
}
|
}
|
||||||
@@ -379,8 +388,7 @@ private:
|
|||||||
// Track all callers of each function
|
// Track all callers of each function
|
||||||
m_call.main(nodep);
|
m_call.main(nodep);
|
||||||
//
|
//
|
||||||
AstNode::user3ClearTree(); // userp() used on entire tree
|
//In V3Hashed AstNode::user4ClearTree(); // user4p() used on entire tree
|
||||||
//In V3Hashed AstNode::user4ClearTree(); // userp() used on entire tree
|
|
||||||
// Iterate modules backwards, in bottom-up order.
|
// Iterate modules backwards, in bottom-up order.
|
||||||
// Required so that a module instantiating another can benefit from collapsing.
|
// Required so that a module instantiating another can benefit from collapsing.
|
||||||
nodep->iterateChildrenBackwards(*this);
|
nodep->iterateChildrenBackwards(*this);
|
||||||
@@ -392,8 +400,11 @@ private:
|
|||||||
m_hashed.clear();
|
m_hashed.clear();
|
||||||
// Compute hash of all statement trees in the function
|
// Compute hash of all statement trees in the function
|
||||||
m_state = STATE_HASH;
|
m_state = STATE_HASH;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_state = STATE_IDLE;
|
m_state = STATE_IDLE;
|
||||||
|
if (debug()>=9) {
|
||||||
|
m_hashed.dumpFilePrefixed("combine");
|
||||||
|
}
|
||||||
// Walk the hashes removing empty functions
|
// Walk the hashes removing empty functions
|
||||||
if (emptyFunctionDeletion()) {
|
if (emptyFunctionDeletion()) {
|
||||||
walkEmptyFuncs();
|
walkEmptyFuncs();
|
||||||
@@ -408,6 +419,7 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_state = STATE_IDLE;
|
m_state = STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
m_funcp = nodep;
|
m_funcp = nodep;
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Combine common code into functions
|
// DESCRIPTION: Verilator: Combine common code into functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+548
-64
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Constant folding
|
// DESCRIPTION: Verilator: Constant folding
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -27,10 +27,11 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Const.h"
|
#include "V3Const.h"
|
||||||
@@ -38,23 +39,82 @@
|
|||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3Width.h"
|
#include "V3Width.h"
|
||||||
#include "V3Signed.h"
|
#include "V3Signed.h"
|
||||||
|
#include "V3Simulate.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Utilities
|
||||||
|
|
||||||
|
class ConstVarMarkVisitor : public AstNVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// AstVar::user4p -> bool, Var marked, 0=not set yet
|
||||||
|
private:
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->varp()) nodep->varp()->user4(1);
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
ConstVarMarkVisitor(AstNode* nodep) {
|
||||||
|
AstNode::user4ClearTree(); // Check marked InUse before we're called
|
||||||
|
nodep->iterateAndNext(*this, NULL);
|
||||||
|
}
|
||||||
|
virtual ~ConstVarMarkVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstVarFindVisitor : public AstNVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// AstVar::user4p -> bool, input from ConstVarMarkVisitor
|
||||||
|
// MEMBERS
|
||||||
|
bool m_found;
|
||||||
|
private:
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->varp() && nodep->varp()->user4()) m_found = true;
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
ConstVarFindVisitor(AstNode* nodep) {
|
||||||
|
m_found = false;
|
||||||
|
nodep->iterateAndNext(*this, NULL);
|
||||||
|
}
|
||||||
|
virtual ~ConstVarFindVisitor() {}
|
||||||
|
// METHODS
|
||||||
|
bool found() const { return m_found; }
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Const state, as a visitor of each AstNode
|
// Const state, as a visitor of each AstNode
|
||||||
|
|
||||||
class ConstVisitor : public AstNVisitor {
|
class ConstVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
|
// NODE STATE
|
||||||
|
// ** only when m_warn/m_expensive is set. If state is needed other times,
|
||||||
|
// ** must track down everywhere V3Const is called and make sure no overlaps.
|
||||||
|
// AstVar::user4p -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_params; // If true, propogate parameterized and true numbers only
|
bool m_params; // If true, propogate parameterized and true numbers only
|
||||||
bool m_required; // If true, must become a constant
|
bool m_required; // If true, must become a constant
|
||||||
bool m_wremove; // Inside scope, no assignw removal
|
bool m_wremove; // Inside scope, no assignw removal
|
||||||
bool m_warn; // Output warnings
|
bool m_warn; // Output warnings
|
||||||
bool m_cpp; // C++ conversions only
|
bool m_cpp; // C++ conversions only
|
||||||
AstModule* m_modp; // Current module
|
bool m_expensive; // Enable computationally expensive optimizations
|
||||||
|
AstModule* m_modp; // Current module
|
||||||
AstNode* m_scopep; // Current scope
|
AstNode* m_scopep; // Current scope
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
bool operandConst (AstNode* nodep) {
|
bool operandConst (AstNode* nodep) {
|
||||||
return (nodep->castConst());
|
return (nodep->castConst());
|
||||||
}
|
}
|
||||||
@@ -81,18 +141,103 @@ private:
|
|||||||
if (rnodep->width() != bnodep->width()) return false;
|
if (rnodep->width() != bnodep->width()) return false;
|
||||||
return operandsSame(bnodep->lhsp(), rnodep->lhsp());
|
return operandsSame(bnodep->lhsp(), rnodep->lhsp());
|
||||||
}
|
}
|
||||||
|
bool operandAsvLUp (AstNode* nodep) {
|
||||||
|
// BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r))
|
||||||
|
//
|
||||||
|
// Example of how this is useful:
|
||||||
|
// BIASV(BIASV(CONSTa,b...),BIASV(CONSTc,d...)) // hits operandAsvUp
|
||||||
|
// BIASV(CONSTa,BIASV(b...,BIASV(CONSTc,d...))) // hits operandAsvUp
|
||||||
|
// BIASV(CONSTa,BIASV(CONSTc,BIASV(c...,d...))) // hits operandAsvConst
|
||||||
|
// BIASV(BIASV(CONSTa,CONSTc),BIASV(c...,d...))) // hits normal constant propagation
|
||||||
|
// BIASV(CONST_a_c,BIASV(c...,d...)))
|
||||||
|
//
|
||||||
|
// Idea for the future: All BiComAsvs could be lists, sorted by if they're constant
|
||||||
|
AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv();
|
||||||
|
if (!bnodep) return false;
|
||||||
|
AstNodeBiComAsv* lnodep = bnodep->lhsp()->castNodeBiComAsv();
|
||||||
|
if (!lnodep) return false;
|
||||||
|
if (lnodep->type() != bnodep->type()) return false;
|
||||||
|
if (lnodep->width() != bnodep->width()) return false;
|
||||||
|
return lnodep->lhsp()->castConst();
|
||||||
|
}
|
||||||
|
bool operandAsvRUp (AstNode* nodep) {
|
||||||
|
// BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr))
|
||||||
|
AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv();
|
||||||
|
if (!bnodep) return false;
|
||||||
|
AstNodeBiComAsv* rnodep = bnodep->rhsp()->castNodeBiComAsv();
|
||||||
|
if (!rnodep) return false;
|
||||||
|
if (rnodep->type() != bnodep->type()) return false;
|
||||||
|
if (rnodep->width() != bnodep->width()) return false;
|
||||||
|
return rnodep->lhsp()->castConst();
|
||||||
|
}
|
||||||
|
static bool operandAndOrSame(AstNode* nodep) {
|
||||||
|
AstNodeBiop* np = nodep->castNodeBiop();
|
||||||
|
AstNodeBiop* lp = np->lhsp()->castNodeBiop();
|
||||||
|
AstNodeBiop* rp = np->rhsp()->castNodeBiop();
|
||||||
|
return (lp && rp
|
||||||
|
&& lp->width()==rp->width()
|
||||||
|
&& lp->type()==rp->type()
|
||||||
|
&& operandsSame(lp->lhsp(),rp->lhsp()));
|
||||||
|
}
|
||||||
|
static bool matchOrAndNot(AstNodeBiop* nodep) {
|
||||||
|
// AstOr{$a, AstAnd{AstNot{$b}, $c}} if $a.width1, $a==$b => AstOr{$a,$c}
|
||||||
|
// Someday we'll sort the biops completely and this can be simplified
|
||||||
|
// This often results from our simplified clock generation:
|
||||||
|
// if (rst) ... else if (enable)... -> OR(rst,AND(!rst,enable))
|
||||||
|
AstNode* ap;
|
||||||
|
AstNodeBiop* andp;
|
||||||
|
if (nodep->lhsp()->castAnd()) { andp=nodep->lhsp()->castAnd(); ap=nodep->rhsp(); }
|
||||||
|
else if (nodep->rhsp()->castAnd()) { andp=nodep->rhsp()->castAnd(); ap=nodep->lhsp(); }
|
||||||
|
else return false;
|
||||||
|
AstNodeUniop* notp;
|
||||||
|
AstNode* cp;
|
||||||
|
if (andp->lhsp()->castNot()) { notp=andp->lhsp()->castNot(); cp=andp->rhsp(); }
|
||||||
|
else if (andp->rhsp()->castNot()) { notp=andp->rhsp()->castNot(); cp=andp->lhsp(); }
|
||||||
|
else return false;
|
||||||
|
AstNode* bp = notp->lhsp();
|
||||||
|
if (!operandsSame(ap, bp)) return false;
|
||||||
|
// Do it
|
||||||
|
cp->unlinkFrBack();
|
||||||
|
andp->unlinkFrBack()->deleteTree(); andp=NULL; notp=NULL;
|
||||||
|
// Replace whichever branch is now dangling
|
||||||
|
if (nodep->rhsp()) nodep->lhsp(cp);
|
||||||
|
else nodep->rhsp(cp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static bool operandShiftSame(AstNode* nodep) {
|
||||||
|
AstNodeBiop* np = nodep->castNodeBiop();
|
||||||
|
{
|
||||||
|
AstShiftL* lp = np->lhsp()->castShiftL();
|
||||||
|
AstShiftL* rp = np->rhsp()->castShiftL();
|
||||||
|
if (lp && rp) {
|
||||||
|
return (lp->width() == rp->width()
|
||||||
|
&& lp->lhsp()->width() == rp->lhsp()->width()
|
||||||
|
&& operandsSame(lp->rhsp(), rp->rhsp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
AstShiftR* lp = np->lhsp()->castShiftR();
|
||||||
|
AstShiftR* rp = np->rhsp()->castShiftR();
|
||||||
|
if (lp && rp) {
|
||||||
|
return (lp->width() == rp->width()
|
||||||
|
&& lp->lhsp()->width() == rp->lhsp()->width()
|
||||||
|
&& operandsSame(lp->rhsp(), rp->rhsp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->width()));
|
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()));
|
||||||
}
|
}
|
||||||
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->lhsp()->width()));
|
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()));
|
||||||
}
|
}
|
||||||
bool operandIsTwo(AstNode* nodep) {
|
bool operandIsTwo(AstNode* nodep) {
|
||||||
return (nodep->castConst()
|
return (nodep->castConst()
|
||||||
&& nodep->width() <= VL_QUADSIZE
|
&& nodep->width() <= VL_QUADSIZE
|
||||||
&& nodep->castConst()->asQuad()==2);
|
&& nodep->castConst()->toUQuad()==2);
|
||||||
}
|
}
|
||||||
bool operandIsTwostate(AstNode* nodep) {
|
bool operandIsTwostate(AstNode* nodep) {
|
||||||
return (nodep->castConst()
|
return (nodep->castConst()
|
||||||
@@ -129,7 +274,7 @@ private:
|
|||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->fromp()->castNodeVarRef()
|
&& nodep->fromp()->castNodeVarRef()
|
||||||
&& !nodep->fromp()->castNodeVarRef()->lvalue()
|
&& !nodep->fromp()->castNodeVarRef()->lvalue()
|
||||||
&& ((int)(nodep->rhsp()->castConst()->asInt())
|
&& ((int)(nodep->rhsp()->castConst()->toUInt())
|
||||||
>= nodep->fromp()->castNodeVarRef()->varp()->widthWords()));
|
>= nodep->fromp()->castNodeVarRef()->varp()->widthWords()));
|
||||||
}
|
}
|
||||||
bool operandSelFull(AstSel* nodep) {
|
bool operandSelFull(AstSel* nodep) {
|
||||||
@@ -164,15 +309,28 @@ private:
|
|||||||
bool warnSelect(AstSel* nodep) {
|
bool warnSelect(AstSel* nodep) {
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||||
|
AstVar* varp = varrefp->varp();
|
||||||
if (m_warn
|
if (m_warn
|
||||||
&& nodep->lsbp()->castConst()
|
&& nodep->lsbp()->castConst()
|
||||||
&& nodep->widthp()->castConst()
|
&& nodep->widthp()->castConst()
|
||||||
&& (!varrefp->varp()->rangep() || varrefp->varp()->msb()) // else it's non-resolvable parameterized
|
&& (!varp->rangep() || varp->msb())) { // else it's non-resolvable parameterized
|
||||||
&& ( ( (nodep->msbConst() > varrefp->varp()->msb())
|
if (nodep->lsbp()->castConst()->num().isFourState()
|
||||||
|| (nodep->lsbConst() > varrefp->varp()->msb())))) {
|
|| nodep->widthp()->castConst()->num().isFourState()) {
|
||||||
nodep->v3error("Selection index out of range: "
|
nodep->v3error("Selection index is constantly unknown or tristated: "
|
||||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
"lsb="<<nodep->lsbp()->name()<<" width="<<nodep->widthp()->name());
|
||||||
<<" outside "<<varrefp->varp()->msb()<<":0");
|
// Replacing nodep will make a mess above, so we replace the offender
|
||||||
|
replaceZero(nodep->lsbp());
|
||||||
|
}
|
||||||
|
else if ((nodep->msbConst() > varp->msbMaxSelect())
|
||||||
|
|| (nodep->lsbConst() > varp->msbMaxSelect())) {
|
||||||
|
// See also warning in V3Width
|
||||||
|
nodep->v3error("Selection index out of range: "
|
||||||
|
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||||
|
<<" outside "<<varp->msbMaxSelect()<<":0"
|
||||||
|
<<(varp->lsb()>=0 ? ""
|
||||||
|
:" (adjusted +"+cvtToStr(-varp->lsb())+" to account for negative lsb)"));
|
||||||
|
// Don't replace with zero, we'll do it later
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false; // Not a transform, so NOP
|
return false; // Not a transform, so NOP
|
||||||
@@ -218,7 +376,9 @@ private:
|
|||||||
void replaceNum (AstNode* oldp, const V3Number& num) {
|
void replaceNum (AstNode* oldp, const V3Number& num) {
|
||||||
// Replace oldp node with a constant set to specified value
|
// Replace oldp node with a constant set to specified value
|
||||||
UASSERT (oldp, "Null old\n");
|
UASSERT (oldp, "Null old\n");
|
||||||
if (oldp->castConst()) oldp->v3fatalSrc("Already constant??\n");
|
if (oldp->castConst() && !oldp->castConst()->num().isFourState()) {
|
||||||
|
oldp->v3fatalSrc("Already constant??\n");
|
||||||
|
}
|
||||||
AstNode* newp = new AstConst(oldp->fileline(), num);
|
AstNode* newp = new AstConst(oldp->fileline(), num);
|
||||||
newp->widthSignedFrom(oldp);
|
newp->widthSignedFrom(oldp);
|
||||||
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
if (debug()>5) oldp->dumpTree(cout," const_old: ");
|
||||||
@@ -313,6 +473,66 @@ private:
|
|||||||
if (rp->lhsp()->castConst() && rp->rhsp()->castConst()) replaceConst(rp);
|
if (rp->lhsp()->castConst() && rp->rhsp()->castConst()) replaceConst(rp);
|
||||||
//nodep->dumpTree(cout, " repAsvConst_new: ");
|
//nodep->dumpTree(cout, " repAsvConst_new: ");
|
||||||
}
|
}
|
||||||
|
void replaceAsvLUp (AstNodeBiop* nodep) {
|
||||||
|
// BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r))
|
||||||
|
AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop();
|
||||||
|
AstNode* llp = lp->lhsp()->unlinkFrBack();
|
||||||
|
AstNode* lrp = lp->rhsp()->unlinkFrBack();
|
||||||
|
AstNode* rp = nodep->rhsp()->unlinkFrBack();
|
||||||
|
nodep->lhsp(llp);
|
||||||
|
nodep->rhsp(lp);
|
||||||
|
lp->lhsp(lrp);
|
||||||
|
lp->rhsp(rp);
|
||||||
|
//nodep->dumpTree(cout, " repAsvLUp_new: ");
|
||||||
|
}
|
||||||
|
void replaceAsvRUp (AstNodeBiop* nodep) {
|
||||||
|
// BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr))
|
||||||
|
AstNode* lp = nodep->lhsp()->unlinkFrBack();
|
||||||
|
AstNodeBiop* rp = nodep->rhsp()->unlinkFrBack()->castNodeBiop();
|
||||||
|
AstNode* rlp = rp->lhsp()->unlinkFrBack();
|
||||||
|
AstNode* rrp = rp->rhsp()->unlinkFrBack();
|
||||||
|
nodep->lhsp(rlp);
|
||||||
|
nodep->rhsp(rp);
|
||||||
|
rp->lhsp(lp);
|
||||||
|
rp->rhsp(rrp);
|
||||||
|
//nodep->dumpTree(cout, " repAsvRUp_new: ");
|
||||||
|
}
|
||||||
|
void replaceAndOr (AstNodeBiop* nodep) {
|
||||||
|
// Or(And(CONSTll,lr),And(CONSTrl==ll,rr)) -> And(CONSTll,Or(lr,rr))
|
||||||
|
// (Or/And may also be reversed)
|
||||||
|
AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop();
|
||||||
|
AstNode* llp = lp->lhsp()->unlinkFrBack();
|
||||||
|
AstNode* lrp = lp->rhsp()->unlinkFrBack();
|
||||||
|
AstNodeBiop* rp = nodep->rhsp()->unlinkFrBack()->castNodeBiop();
|
||||||
|
AstNode* rlp = rp->lhsp()->unlinkFrBack();
|
||||||
|
AstNode* rrp = rp->rhsp()->unlinkFrBack();
|
||||||
|
nodep->replaceWith(lp);
|
||||||
|
lp->lhsp(llp);
|
||||||
|
lp->rhsp(nodep);
|
||||||
|
nodep->lhsp(lrp);
|
||||||
|
nodep->rhsp(rrp);
|
||||||
|
rp->deleteTree();
|
||||||
|
rlp->deleteTree();
|
||||||
|
//nodep->dumpTree(cout, " repAndOr_new: ");
|
||||||
|
}
|
||||||
|
void replaceShiftSame (AstNodeBiop* nodep) {
|
||||||
|
// Or(Shift(ll,CONSTlr),Shift(rl,CONSTrr==lr)) -> Shift(Or(ll,rl),CONSTlr)
|
||||||
|
// (Or/And may also be reversed)
|
||||||
|
AstNodeBiop* lp = nodep->lhsp()->unlinkFrBack()->castNodeBiop();
|
||||||
|
AstNode* llp = lp->lhsp()->unlinkFrBack();
|
||||||
|
AstNode* lrp = lp->rhsp()->unlinkFrBack();
|
||||||
|
AstNodeBiop* rp = nodep->rhsp()->unlinkFrBack()->castNodeBiop();
|
||||||
|
AstNode* rlp = rp->lhsp()->unlinkFrBack();
|
||||||
|
AstNode* rrp = rp->rhsp()->unlinkFrBack();
|
||||||
|
nodep->replaceWith(lp);
|
||||||
|
lp->lhsp(nodep);
|
||||||
|
lp->rhsp(lrp);
|
||||||
|
nodep->lhsp(llp);
|
||||||
|
nodep->rhsp(rlp);
|
||||||
|
rp->deleteTree();
|
||||||
|
rrp->deleteTree();
|
||||||
|
//nodep->dumpTree(cout, " repShiftSame_new: ");
|
||||||
|
}
|
||||||
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
|
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
|
||||||
// -> EXTEND(nodep)
|
// -> EXTEND(nodep)
|
||||||
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
|
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
|
||||||
@@ -360,7 +580,7 @@ private:
|
|||||||
AstNode* ap = lhsp->lhsp()->unlinkFrBack();
|
AstNode* ap = lhsp->lhsp()->unlinkFrBack();
|
||||||
AstNode* bp = lhsp->rhsp()->unlinkFrBack();
|
AstNode* bp = lhsp->rhsp()->unlinkFrBack();
|
||||||
AstNodeBiop* shift1p = nodep;
|
AstNodeBiop* shift1p = nodep;
|
||||||
AstNodeBiop* shift2p = nodep->cloneTree(true)->castNodeBiop();
|
AstNodeBiop* shift2p = nodep->cloneTree(true);
|
||||||
shift1p->lhsp(ap); shift1p->rhsp(shiftp->cloneTree(true));
|
shift1p->lhsp(ap); shift1p->rhsp(shiftp->cloneTree(true));
|
||||||
shift2p->lhsp(bp); shift2p->rhsp(shiftp);
|
shift2p->lhsp(bp); shift2p->rhsp(shiftp);
|
||||||
AstNodeBiop* newp = lhsp;
|
AstNodeBiop* newp = lhsp;
|
||||||
@@ -381,8 +601,8 @@ private:
|
|||||||
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
||||||
} else {
|
} else {
|
||||||
// We know shift amounts are constant, but might be a mixed left/right shift
|
// We know shift amounts are constant, but might be a mixed left/right shift
|
||||||
int shift1 = shift1p->castConst()->asInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
||||||
int shift2 = shift2p->castConst()->asInt(); if (nodep->castShiftR()) shift2=-shift2;
|
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
|
||||||
int newshift = shift1+shift2;
|
int newshift = shift1+shift2;
|
||||||
shift1p->deleteTree(); shift1p=NULL;
|
shift1p->deleteTree(); shift1p=NULL;
|
||||||
shift2p->deleteTree(); shift1p=NULL;
|
shift2p->deleteTree(); shift1p=NULL;
|
||||||
@@ -439,11 +659,11 @@ private:
|
|||||||
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
|
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
|
||||||
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
|
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
|
||||||
// Swap?
|
// Swap?
|
||||||
if (( con1p->asInt() != con2p->asInt() + sel2p->width())
|
if (( con1p->toSInt() != con2p->toSInt() + sel2p->width())
|
||||||
&&(con2p->asInt() != con1p->asInt() + sel1p->width())) return false;
|
&&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false;
|
||||||
bool lsbFirstAssign = (con1p->asInt() < con2p->asInt());
|
bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt());
|
||||||
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
|
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
|
||||||
//if (VL_BITBIT_I(con1p->asInt()) == 0) return false;
|
//if (VL_BITBIT_I(con1p->toUInt()) == 0) return false;
|
||||||
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
|
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
|
||||||
UINFO(4," && "<<nextp<<endl);
|
UINFO(4," && "<<nextp<<endl);
|
||||||
//nodep->dumpTree(cout, "comb1: ");
|
//nodep->dumpTree(cout, "comb1: ");
|
||||||
@@ -466,7 +686,7 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool varNotReferenced(AstNode* nodep, AstVar* varp, bool level=0) {
|
bool varNotReferenced(AstNode* nodep, AstVar* varp, int level=0) {
|
||||||
// Return true if varp never referenced under node.
|
// Return true if varp never referenced under node.
|
||||||
// Return false if referenced, or tree too deep to be worth it
|
// Return false if referenced, or tree too deep to be worth it
|
||||||
if (!nodep) return true;
|
if (!nodep) return true;
|
||||||
@@ -494,10 +714,29 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
||||||
UINFO(4," ASSI "<<nodep<<endl);
|
bool need_temp = false;
|
||||||
|
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
|
||||||
|
// Note only do this (need user4) when m_warn, which is
|
||||||
|
// done as unique visitor
|
||||||
|
AstUser4InUse m_inuser4;
|
||||||
|
ConstVarMarkVisitor mark(nodep->lhsp());
|
||||||
|
ConstVarFindVisitor find(nodep->rhsp());
|
||||||
|
if (find.found()) need_temp = true;
|
||||||
|
}
|
||||||
|
if (need_temp) {
|
||||||
|
// The first time we constify, there may be the same variable on the LHS
|
||||||
|
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
|
||||||
|
UINFO(4," ASSITEMP "<<nodep<<endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(temp1,SEL(rhs,{size})),
|
||||||
|
// ASSIGN(temp2,SEL(newrhs,{size}))
|
||||||
|
// ASSIGN(lc1,temp1),
|
||||||
|
// ASSIGN(lc2,temp2)
|
||||||
|
} else {
|
||||||
|
UINFO(4," ASSI "<<nodep<<endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
|
||||||
|
// ASSIGN(lc2,SEL(newrhs,{size}))
|
||||||
|
}
|
||||||
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
|
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
|
||||||
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
|
|
||||||
// ASSIGN(lc2,SEL(newrhs,{size}))
|
|
||||||
// Unlink the stuff
|
// Unlink the stuff
|
||||||
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
|
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
|
||||||
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
|
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
|
||||||
@@ -517,14 +756,50 @@ private:
|
|||||||
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
// Make new assigns of same flavor as old one
|
// Make new assigns of same flavor as old one
|
||||||
//*** Not cloneTree; just one node.
|
//*** Not cloneTree; just one node.
|
||||||
AstNodeAssign* asn1p=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
AstNode* newp = NULL;
|
||||||
AstNodeAssign* asn2p=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
if (!need_temp) {
|
||||||
asn1p->width(msb1-lsb1+1,msb1-lsb1+1);
|
AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
||||||
asn2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||||
nodep->addNextHere(asn1p);
|
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
nodep->addNextHere(asn2p);
|
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
if (debug()>=9) asn1p->dumpTree(cout," _new: ");
|
newp = newp->addNext(asn1ap);
|
||||||
if (debug()>=9) asn2p->dumpTree(cout," _new: ");
|
newp = newp->addNext(asn2ap);
|
||||||
|
} else {
|
||||||
|
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
||||||
|
// We could create just one temp variable, but we'll get better optimization
|
||||||
|
// if we make one per term.
|
||||||
|
string name1 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
|
string name2 = ((string)"__Vconcswap"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
|
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
|
||||||
|
new AstRange(sel1p->fileline(), msb1-lsb1, 0));
|
||||||
|
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
|
||||||
|
new AstRange(sel2p->fileline(), msb2-lsb2, 0));
|
||||||
|
m_modp->addStmtp(temp1p);
|
||||||
|
m_modp->addStmtp(temp2p);
|
||||||
|
AstNodeAssign* asn1ap=nodep->cloneType
|
||||||
|
(new AstVarRef(sel1p->fileline(), temp1p, true),
|
||||||
|
sel1p)->castNodeAssign();
|
||||||
|
AstNodeAssign* asn2ap=nodep->cloneType
|
||||||
|
(new AstVarRef(sel2p->fileline(), temp2p, true),
|
||||||
|
sel2p)->castNodeAssign();
|
||||||
|
AstNodeAssign* asn1bp=nodep->cloneType
|
||||||
|
(lc1p, new AstVarRef(sel1p->fileline(), temp1p, false))
|
||||||
|
->castNodeAssign();
|
||||||
|
AstNodeAssign* asn2bp=nodep->cloneType
|
||||||
|
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
|
||||||
|
->castNodeAssign();
|
||||||
|
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
|
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
|
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
|
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
|
// This order matters
|
||||||
|
newp = newp->addNext(asn1ap);
|
||||||
|
newp = newp->addNext(asn2ap);
|
||||||
|
newp = newp->addNext(asn1bp);
|
||||||
|
newp = newp->addNext(asn2bp);
|
||||||
|
}
|
||||||
|
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: ");
|
||||||
|
nodep->addNextHere(newp);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
conp->deleteTree(); conp=NULL;
|
conp->deleteTree(); conp=NULL;
|
||||||
@@ -545,7 +820,7 @@ private:
|
|||||||
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
|
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
|
||||||
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
|
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
|
||||||
if (!shiftp->rhsp()->castConst()) return false;
|
if (!shiftp->rhsp()->castConst()) return false;
|
||||||
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->asInt()) return false;
|
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->toUInt()) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void replaceBoolShift(AstNode* nodep) {
|
void replaceBoolShift(AstNode* nodep) {
|
||||||
@@ -564,6 +839,26 @@ private:
|
|||||||
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
if (debug()>=9) newp->dumpTree(cout," _new: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replaceWithSimulation(AstNode* nodep) {
|
||||||
|
SimulateVisitor simvis;
|
||||||
|
// Run it - may be unoptimizable due to large for loop, etc
|
||||||
|
simvis.mainParamEmulate(nodep);
|
||||||
|
if (!simvis.optimizable()) {
|
||||||
|
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||||
|
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
|
||||||
|
<<nodep->prettyTypeName()<<endl
|
||||||
|
<<V3Error::msgPrefix()<<errorp->fileline()<<"... Location of non-constant "
|
||||||
|
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||||
|
replaceZero(nodep); nodep=NULL;
|
||||||
|
} else {
|
||||||
|
// Fetch the result
|
||||||
|
V3Number* outnump = simvis.fetchNumberNull(nodep);
|
||||||
|
if (!outnump) nodep->v3fatalSrc("No number returned from simulation");
|
||||||
|
// Replace it
|
||||||
|
replaceNum(nodep,*outnump); nodep=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
@@ -641,7 +936,7 @@ private:
|
|||||||
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
||||||
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
||||||
bcConcp->deleteTree(); bcConcp=NULL;
|
bcConcp->deleteTree(); bcConcp=NULL;
|
||||||
} else {
|
} else {
|
||||||
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
||||||
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
||||||
AstNode* bp = abConcp->rhsp()->unlinkFrBack();
|
AstNode* bp = abConcp->rhsp()->unlinkFrBack();
|
||||||
@@ -681,7 +976,7 @@ private:
|
|||||||
AstNode* newlsbp;
|
AstNode* newlsbp;
|
||||||
if (lsb1p->castConst() && lsb2p->castConst()) {
|
if (lsb1p->castConst() && lsb2p->castConst()) {
|
||||||
newlsbp = new AstConst(lsb1p->fileline(),
|
newlsbp = new AstConst(lsb1p->fileline(),
|
||||||
lsb1p->castConst()->asInt() + lsb2p->castConst()->asInt());
|
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
|
||||||
lsb1p->deleteTree(); lsb1p=NULL;
|
lsb1p->deleteTree(); lsb1p=NULL;
|
||||||
lsb2p->deleteTree(); lsb2p=NULL;
|
lsb2p->deleteTree(); lsb2p=NULL;
|
||||||
} else {
|
} else {
|
||||||
@@ -748,7 +1043,7 @@ private:
|
|||||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||||
AstSel* newp = new AstSel(nodep->fileline(),
|
AstSel* newp = new AstSel(nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
new AstConst(lsbp->fileline(), lsbp->asInt() % fromp->width()),
|
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||||
widthp);
|
widthp);
|
||||||
newp->widthSignedFrom(nodep);
|
newp->widthSignedFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||||
@@ -779,8 +1074,7 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||||
// Don't iterate children, don't want to loose VarRef.
|
// Don't iterate children, don't want to loose VarRef.
|
||||||
if (nodep->attrType()==AstAttrType::SCOPE_TEXT) {
|
if (nodep->attrType()==AstAttrType::BITS) {
|
||||||
} else if (nodep->attrType()==AstAttrType::BITS) {
|
|
||||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
||||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
|
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
|
||||||
replaceNum(nodep, num); nodep=NULL;
|
replaceNum(nodep, num); nodep=NULL;
|
||||||
@@ -804,19 +1098,26 @@ private:
|
|||||||
} else nodep->v3fatalSrc("Missing ATTR type case\n");
|
} else nodep->v3fatalSrc("Missing ATTR type case\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool onlySenItemInSenTree(AstNodeSenItem* nodep) {
|
||||||
|
// Only one if it's not in a list
|
||||||
|
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||||
|
}
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (nodep->sensp()->castConst()
|
if (nodep->sensp()->castConst()
|
||||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
||||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||||
AstSenItem* newp;
|
|
||||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||||
newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
|
if (onlySenItemInSenTree(nodep)) {
|
||||||
|
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
|
} else {
|
||||||
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
} else { // Otherwise it may compute a result that needs to settle out
|
} else { // Otherwise it may compute a result that needs to settle out
|
||||||
newp = new AstSenItem(nodep->fileline(), AstSenItem::Combo());
|
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
nodep->replaceWith(newp);
|
|
||||||
nodep->deleteTree(); nodep=NULL;
|
|
||||||
} else if (nodep->sensp()->castNot()) {
|
} else if (nodep->sensp()->castNot()) {
|
||||||
// V3Gate may propagate NOTs into clocks... Just deal with it
|
// V3Gate may propagate NOTs into clocks... Just deal with it
|
||||||
AstNode* sensp = nodep->sensp();
|
AstNode* sensp = nodep->sensp();
|
||||||
@@ -836,6 +1137,150 @@ private:
|
|||||||
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
if (nodep->hasVar() && !nodep->varrefp()) nodep->v3fatalSrc("Null sensitivity variable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
||||||
|
if (constp->isZero()) {
|
||||||
|
UINFO(4,"SENGATE(...,0)->NEVER"<<endl);
|
||||||
|
if (onlySenItemInSenTree(nodep)) {
|
||||||
|
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
|
} else {
|
||||||
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UINFO(4,"SENGATE(SENITEM,0)->ALWAYS SENITEM"<<endl);
|
||||||
|
AstNode* senitemp = nodep->sensesp()->unlinkFrBack();
|
||||||
|
nodep->replaceWith(senitemp);
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SenItemCmp {
|
||||||
|
inline bool operator () (AstNodeSenItem* lhsp, AstNodeSenItem* rhsp) const {
|
||||||
|
if (lhsp->type() < rhsp->type()) return true;
|
||||||
|
if (lhsp->type() > rhsp->type()) return false;
|
||||||
|
const AstSenItem* litemp = lhsp->castSenItem();
|
||||||
|
const AstSenItem* ritemp = rhsp->castSenItem();
|
||||||
|
if (litemp && ritemp) {
|
||||||
|
// Looks visually better if we keep sorted by name
|
||||||
|
if (litemp->edgeType() < ritemp->edgeType()) return true;
|
||||||
|
if (litemp->edgeType() > ritemp->edgeType()) return false;
|
||||||
|
if (!litemp->varrefp() && ritemp->varrefp()) return true;
|
||||||
|
if ( litemp->varrefp() && !ritemp->varrefp()) return false;
|
||||||
|
if (litemp->varrefp() && ritemp->varrefp()) {
|
||||||
|
if (litemp->varrefp()->name() < ritemp->varrefp()->name()) return true;
|
||||||
|
if (litemp->varrefp()->name() > ritemp->varrefp()->name()) return false;
|
||||||
|
// But might be same name with different scopes
|
||||||
|
if (litemp->varrefp()->varScopep() < ritemp->varrefp()->varScopep()) return true;
|
||||||
|
if (litemp->varrefp()->varScopep() > ritemp->varrefp()->varScopep()) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_expensive) {
|
||||||
|
//cout<<endl; nodep->dumpTree(cout,"ssin: ");
|
||||||
|
// Optimize ideas for the future:
|
||||||
|
// SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b))
|
||||||
|
|
||||||
|
// SENTREE(... SENITEM(x), SENGATE(SENITEM(x),*) ...) => SENITEM(x)
|
||||||
|
// Do we need the SENITEM's to be identical? No because we're
|
||||||
|
// ORing between them; we just need to insure that the result is at
|
||||||
|
// least as frequently activating. So we simply
|
||||||
|
// SENGATE(SENITEM(x)) -> SENITEM(x), then let it collapse with the
|
||||||
|
// other SENITEM(x).
|
||||||
|
{
|
||||||
|
AstUser4InUse m_inuse4;
|
||||||
|
// Mark x in SENITEM(x)
|
||||||
|
for (AstNodeSenItem* senp = nodep->sensesp()->castNodeSenItem();
|
||||||
|
senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
|
if (AstSenItem* itemp = senp->castSenItem()) {
|
||||||
|
if (itemp->varrefp() && itemp->varrefp()->varScopep()) {
|
||||||
|
itemp->varrefp()->varScopep()->user4(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Find x in SENTREE(SENITEM(x))
|
||||||
|
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
||||||
|
senp; senp=nextp) {
|
||||||
|
nextp=senp->nextp()->castNodeSenItem();
|
||||||
|
if (AstSenGate* gatep = senp->castSenGate()) {
|
||||||
|
if (AstSenItem* itemp = gatep->sensesp()->castSenItem()) {
|
||||||
|
if (itemp->varrefp() && itemp->varrefp()->varScopep()) {
|
||||||
|
if (itemp->varrefp()->varScopep()->user4()) {
|
||||||
|
// Found, push this item up to the top
|
||||||
|
itemp->unlinkFrBack();
|
||||||
|
nodep->addSensesp(itemp);
|
||||||
|
gatep->unlinkFrBack()->deleteTree(); gatep=NULL; senp=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the sensitivity names so "posedge a or b" and "posedge b or a" end up together.
|
||||||
|
// Also, remove duplicate assignments, and fold POS&NEGs into ANYEDGEs
|
||||||
|
// Make things a little faster; check first if we need a sort
|
||||||
|
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
||||||
|
senp; senp=nextp) {
|
||||||
|
nextp=senp->nextp()->castNodeSenItem();
|
||||||
|
SenItemCmp cmp;
|
||||||
|
if (nextp && !cmp(senp, nextp)) {
|
||||||
|
// Something's out of order, sort it
|
||||||
|
senp = NULL;
|
||||||
|
vector<AstNodeSenItem*> vec;
|
||||||
|
for (AstNodeSenItem* senp = nodep->sensesp()->castNodeSenItem(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
||||||
|
vec.push_back(senp);
|
||||||
|
}
|
||||||
|
sort(vec.begin(), vec.end(), SenItemCmp());
|
||||||
|
for (vector<AstNodeSenItem*>::iterator it=vec.begin(); it!=vec.end(); ++it) {
|
||||||
|
(*it)->unlinkFrBack();
|
||||||
|
}
|
||||||
|
for (vector<AstNodeSenItem*>::iterator it=vec.begin(); it!=vec.end(); ++it) {
|
||||||
|
nodep->addSensesp(*it);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass2, remove dup edges
|
||||||
|
for (AstNodeSenItem* nextp, * senp = nodep->sensesp()->castNodeSenItem();
|
||||||
|
senp; senp=nextp) {
|
||||||
|
nextp=senp->nextp()->castNodeSenItem();
|
||||||
|
AstNodeSenItem* cmpp = nextp;
|
||||||
|
AstSenItem* litemp = senp->castSenItem();
|
||||||
|
AstSenItem* ritemp = cmpp->castSenItem();
|
||||||
|
if (litemp && ritemp) {
|
||||||
|
if ((litemp->varrefp() && ritemp->varrefp() && litemp->varrefp()->sameTree(ritemp->varrefp()))
|
||||||
|
|| (!litemp->varrefp() && !ritemp->varrefp())) {
|
||||||
|
// We've sorted in the order ANY, BOTH, POS, NEG, so we don't need to try opposite orders
|
||||||
|
if (( litemp->edgeType()==AstEdgeType::ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY
|
||||||
|
|| (litemp->edgeType()==AstEdgeType::BOTHEDGE) // BOTH or {POS|NEG} -> BOTH
|
||||||
|
|| (litemp->edgeType()==AstEdgeType::POSEDGE // POS or NEG -> BOTH
|
||||||
|
&& ritemp->edgeType()==AstEdgeType::NEGEDGE)
|
||||||
|
|| (litemp->edgeType()==ritemp->edgeType()) // Identical edges
|
||||||
|
) {
|
||||||
|
// Fix edge of old node
|
||||||
|
if (litemp->edgeType()==AstEdgeType::POSEDGE
|
||||||
|
&& ritemp->edgeType()==AstEdgeType::NEGEDGE)
|
||||||
|
litemp->edgeType(AstEdgeType::BOTHEDGE);
|
||||||
|
// Remove redundant node
|
||||||
|
ritemp->unlinkFrBack()->deleteTree(); ritemp=NULL; cmpp=NULL;
|
||||||
|
// Try to collapse again
|
||||||
|
nextp=litemp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//nodep->dumpTree(cout,"ssou: ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----
|
//-----
|
||||||
// Zero elimination
|
// Zero elimination
|
||||||
@@ -913,7 +1358,7 @@ private:
|
|||||||
&& nodep->ifsp() && nodep->elsesp()) {
|
&& nodep->ifsp() && nodep->elsesp()) {
|
||||||
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
||||||
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
||||||
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||||
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||||
ifp->branchPred(nodep->branchPred().invert());
|
ifp->branchPred(nodep->branchPred().invert());
|
||||||
@@ -934,7 +1379,7 @@ private:
|
|||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||||
&& operandIfIf(nodep)) {
|
&& operandIfIf(nodep)) {
|
||||||
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||||
@@ -1007,6 +1452,13 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstFuncRef* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_params) { // Only parameters force us to do constant function call propagation
|
||||||
|
replaceWithSimulation(nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (nodep->condp()->isZero()) {
|
if (nodep->condp()->isZero()) {
|
||||||
@@ -1025,9 +1477,18 @@ private:
|
|||||||
// $accessor_name, ...
|
// $accessor_name, ...
|
||||||
// # ,, gets replaced with a , rather than &&
|
// # ,, gets replaced with a , rather than &&
|
||||||
// }" # bracket not paren
|
// }" # bracket not paren
|
||||||
// ,"function to call"
|
// ,"what to call"
|
||||||
// or ,"AstREPLACEMENT_TYPE{ $accessor }"
|
//
|
||||||
// or ,"! # Print line number when matches, so can see operations
|
// Where "what_to_call" is:
|
||||||
|
// "function to call"
|
||||||
|
// "AstREPLACEMENT_TYPE{ $accessor }"
|
||||||
|
// "! # Print line number when matches, so can see operations
|
||||||
|
// "NEVER" # Print error message
|
||||||
|
// "DONE" # Process of matching did the transform already
|
||||||
|
|
||||||
|
// In the future maybe support more complicated match & replace:
|
||||||
|
// ("AstOr {%a, AstAnd{AstNot{%b}, %c}} if %a.width1 if %a==%b", "AstOr{%a,%c}; %b.delete");
|
||||||
|
// Lhs/rhs would be implied; for non math operations you'd need $lhsp etc.
|
||||||
|
|
||||||
// Lint Checks
|
// Lint Checks
|
||||||
// v--- *1* These ops are always first, as we warn before replacing
|
// v--- *1* These ops are always first, as we warn before replacing
|
||||||
@@ -1101,6 +1562,8 @@ private:
|
|||||||
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||||
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
||||||
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||||
|
TREEOP("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
||||||
|
TREEOP("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
||||||
// v--- *1* as These ops are always first, as we warn before replacing
|
// v--- *1* as These ops are always first, as we warn before replacing
|
||||||
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
||||||
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
||||||
@@ -1212,6 +1675,14 @@ private:
|
|||||||
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
|
// CONCAT({const},CONCAT({const},{c})) -> CONCAT((constifiedCONC{const|const},{c}))
|
||||||
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
|
TREEOPV("AstConcat{operandConcatMove(nodep)}", "moveConcat(nodep)");
|
||||||
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
|
TREEOPV("AstConcat{$lhsp.isZero, $rhsp}", "replaceExtend(nodep, nodep->rhsp())");
|
||||||
|
// Common two-level operations that can be simplified
|
||||||
|
TREEOP ("AstAnd {$lhsp.castOr, $rhsp.castOr, operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
|
||||||
|
TREEOP ("AstOr {$lhsp.castAnd,$rhsp.castAnd,operandAndOrSame(nodep)}", "replaceAndOr(nodep)");
|
||||||
|
TREEOP ("AstOr {matchOrAndNot(nodep)}", "DONE");
|
||||||
|
TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||||
|
TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||||
|
TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||||
|
TREEOP ("AstXnor{operandShiftSame(nodep)}", "replaceShiftSame(nodep)");
|
||||||
// Note can't simplify a extend{extends}, extends{extend}, as the sign bits end up in the wrong places
|
// Note can't simplify a extend{extends}, extends{extend}, as the sign bits end up in the wrong places
|
||||||
TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, nodep->lhsp()->castExtend()->lhsp())");
|
TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, nodep->lhsp()->castExtend()->lhsp())");
|
||||||
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())");
|
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())");
|
||||||
@@ -1242,7 +1713,7 @@ private:
|
|||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
if (m_required) {
|
if (m_required) {
|
||||||
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
nodep->v3error("Expecting expression to be constant, but can't convert a "
|
||||||
<<nodep->typeName()<<" to constant.");
|
<<nodep->prettyTypeName()<<" to constant.");
|
||||||
} else {
|
} else {
|
||||||
// Calculate the width of this operation
|
// Calculate the width of this operation
|
||||||
if (m_params && !nodep->width()) {
|
if (m_params && !nodep->width()) {
|
||||||
@@ -1255,8 +1726,11 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
ConstVisitor(bool params, bool required, bool warn, bool cpp) {
|
ConstVisitor(bool params, bool expensive, bool warn, bool cpp) {
|
||||||
m_params = params; m_required = required; m_warn=warn; m_cpp=cpp;
|
m_params = params; m_required = params;
|
||||||
|
m_expensive = expensive;
|
||||||
|
m_warn = warn;
|
||||||
|
m_cpp = cpp;
|
||||||
m_wremove = true;
|
m_wremove = true;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
m_scopep = NULL;
|
m_scopep = NULL;
|
||||||
@@ -1273,23 +1747,29 @@ public:
|
|||||||
|
|
||||||
void V3Const::constifyParam(AstNode* nodep) {
|
void V3Const::constifyParam(AstNode* nodep) {
|
||||||
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
|
//if (debug()>0) nodep->dumpTree(cout," forceConPRE : ");
|
||||||
if (!nodep->width()) {
|
V3Width::widthSignedIfNotAlready(nodep); // Make sure we've sized everything first
|
||||||
V3Width::widthParams(nodep);
|
ConstVisitor visitor (true,false,false,false);
|
||||||
V3Signed::signedParams(nodep);
|
if (AstVar* varp=nodep->castVar()) {
|
||||||
|
// If a var wants to be constified, it's really a param, and
|
||||||
|
// we want the value to be constant. We aren't passed just the
|
||||||
|
// init value because we need widthing above to handle the var's type.
|
||||||
|
if (varp->initp()) visitor.main(varp->initp());
|
||||||
|
} else {
|
||||||
|
visitor.main(nodep);
|
||||||
}
|
}
|
||||||
ConstVisitor visitor (true,true,false,false);
|
|
||||||
visitor.main(nodep);
|
|
||||||
// Because we do edits, nodep links may get trashed and core dump this.
|
// Because we do edits, nodep links may get trashed and core dump this.
|
||||||
//if (debug()>0) nodep->dumpTree(cout," forceConDONE: ");
|
//if (debug()>0) nodep->dumpTree(cout," forceConDONE: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||||
|
// Only call from Verilator.cpp, as it uses user#'s
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
ConstVisitor visitor (false,false,false,false);
|
ConstVisitor visitor (false,true,false,false);
|
||||||
visitor.main(nodep);
|
visitor.main(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Const::constifyAllLint(AstNetlist* nodep) {
|
void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||||
|
// Only call from Verilator.cpp, as it uses user#'s
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
ConstVisitor visitor (false,false,true,false);
|
ConstVisitor visitor (false,false,true,false);
|
||||||
visitor.main(nodep);
|
visitor.main(nodep);
|
||||||
@@ -1306,3 +1786,7 @@ void V3Const::constifyTree(AstNode* nodep) {
|
|||||||
visitor.main(nodep);
|
visitor.main(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Const::constifyTreeExpensive(AstNode* nodep) {
|
||||||
|
ConstVisitor visitor (false,true,false,false);
|
||||||
|
visitor.main(nodep);
|
||||||
|
}
|
||||||
|
|||||||
+7
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Propagate constants across AST
|
// DESCRIPTION: Verilator: Propagate constants across AST
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -40,6 +41,8 @@ public:
|
|||||||
static void constifyCpp(AstNetlist* nodep);
|
static void constifyCpp(AstNetlist* nodep);
|
||||||
// Only the current node and lower
|
// Only the current node and lower
|
||||||
static void constifyTree(AstNode* nodep);
|
static void constifyTree(AstNode* nodep);
|
||||||
|
// Only the current node and lower, with special SenTree optimization
|
||||||
|
static void constifyTreeExpensive(AstNode* nodep);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+188
-24
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Netlist (top level) functions
|
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -31,15 +31,14 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Coverage.h"
|
#include "V3Coverage.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3Const.h"
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Coverage state, as a visitor of each AstNode
|
// Coverage state, as a visitor of each AstNode
|
||||||
@@ -47,59 +46,198 @@
|
|||||||
class CoverageVisitor : public AstNVisitor {
|
class CoverageVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef map<FileLine*,int> FileMap;
|
typedef map<string,int> FileMap;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_checkBlock; // Should this block get covered?
|
bool m_checkBlock; // Should this block get covered?
|
||||||
AstModule* m_modp; // Current module to add statement to
|
AstModule* m_modp; // Current module to add statement to
|
||||||
|
bool m_inToggleOff; // In function/task etc
|
||||||
FileMap m_fileps; // Column counts for each fileline
|
FileMap m_fileps; // Column counts for each fileline
|
||||||
|
string m_beginHier; // AstBegin hier name for user coverage points
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
AstCoverInc* newCoverInc(FileLine* fl, const string& type, const string& comment) {
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* varIgnoreToggle(AstVar* nodep) {
|
||||||
|
// Return true if this shouldn't be traced
|
||||||
|
// See also similar rule in V3TraceDecl::varIgnoreTrace
|
||||||
|
string prettyName = nodep->prettyName();
|
||||||
|
if (!nodep->isToggleCoverable())
|
||||||
|
return "Not relevant signal type";
|
||||||
|
if (prettyName.c_str()[0] == '_')
|
||||||
|
return "Leading underscore";
|
||||||
|
if (prettyName.find("._") != string::npos)
|
||||||
|
return "Inlined leading underscore";
|
||||||
|
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
|
||||||
|
// We allow this, though tracing doesn't
|
||||||
|
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstCoverInc* newCoverInc(FileLine* fl, const string& hier,
|
||||||
|
const string& page_prefix, const string& comment) {
|
||||||
|
// For line coverage, we may have multiple if's on one line, so disambiguate if
|
||||||
|
// everything is otherwise identical
|
||||||
|
// (Don't set column otherwise as it may result in making bins not match up with
|
||||||
|
// different types of coverage enabled.)
|
||||||
|
string key = fl->filename()+"\001"+cvtToStr(fl->lineno())+"\001"+hier+"\001"+page_prefix+"\001"+comment;
|
||||||
int column = 0;
|
int column = 0;
|
||||||
FileMap::iterator it = m_fileps.find(fl);
|
FileMap::iterator it = m_fileps.find(key);
|
||||||
if (it == m_fileps.end()) {
|
if (it == m_fileps.end()) {
|
||||||
m_fileps.insert(make_pair(fl,column+1));
|
m_fileps.insert(make_pair(key,column+1));
|
||||||
} else {
|
} else {
|
||||||
column = (it->second)++;
|
column = (it->second)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstCoverDecl* declp = new AstCoverDecl(fl, column, type, comment);
|
// We could use the basename of the filename to the page, but seems better for code
|
||||||
|
// from an include file to be listed under the module using it rather than the include file.
|
||||||
|
// Note the module name could have parameters appended, we'll consider this
|
||||||
|
// a feature as it allows for each parameterized block to be counted separately.
|
||||||
|
// Someday the user might be allowed to specify a different page suffix
|
||||||
|
string page = page_prefix + "/" + m_modp->prettyName();
|
||||||
|
|
||||||
|
AstCoverDecl* declp = new AstCoverDecl(fl, column, page, comment);
|
||||||
|
declp->hier(hier);
|
||||||
m_modp->addStmtp(declp);
|
m_modp->addStmtp(declp);
|
||||||
|
|
||||||
return new AstCoverInc(fl, declp);
|
return new AstCoverInc(fl, declp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS - BOTH
|
||||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_fileps.clear();
|
m_fileps.clear();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VISITORS - TOGGLE COVERAGE
|
||||||
|
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||||
|
bool oldtog = m_inToggleOff;
|
||||||
|
{
|
||||||
|
m_inToggleOff = true;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_inToggleOff = oldtog;
|
||||||
|
}
|
||||||
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_modp && !m_inToggleOff
|
||||||
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
|
||||||
|
const char* disablep = varIgnoreToggle(nodep);
|
||||||
|
if (disablep) {
|
||||||
|
UINFO(4, " Disable Toggle: "<<disablep<<" "<<nodep<<endl);
|
||||||
|
} else {
|
||||||
|
UINFO(4, " Toggle: "<<nodep<<endl);
|
||||||
|
// There's several overall ways to approach this
|
||||||
|
// Treat like tracing, where a end-of-timestamp action sees all changes
|
||||||
|
// Works ok, but would be quite slow as need to reform vectors before the calls
|
||||||
|
// Convert to "always @ (posedge signal[#]) coverinc"
|
||||||
|
// Would mark many signals as clocks, precluding many later optimizations
|
||||||
|
// Convert to "if (x & !lastx) CoverInc"
|
||||||
|
// OK, but we couldn't later detect them to schedule where the IFs get called
|
||||||
|
// Convert to "AstCoverInc(CoverInc...)"
|
||||||
|
// We'll do this, and make the if(...) coverinc later.
|
||||||
|
|
||||||
|
// Compute size of the problem
|
||||||
|
int dimensions = 0;
|
||||||
|
for (AstRange* arrayp=nodep->arraysp(); arrayp; arrayp = arrayp->nextp()->castRange()) {
|
||||||
|
dimensions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add signal to hold the old value
|
||||||
|
string newvarname = (string)"__Vtogcov__"+nodep->shortName();
|
||||||
|
AstVar* chgVarp = new AstVar (nodep->fileline(), AstVarType::MODULETEMP, newvarname, nodep);
|
||||||
|
m_modp->addStmtp(chgVarp);
|
||||||
|
|
||||||
|
// Create bucket for each dimension * bit.
|
||||||
|
// This is necessarily an O(n^2) expansion, which is why
|
||||||
|
// we limit coverage to signals with < 256 bits.
|
||||||
|
vector<int> selects_docs; selects_docs.resize(dimensions);
|
||||||
|
vector<int> selects_code; selects_code.resize(dimensions);
|
||||||
|
toggleVarRecurse(nodep, chgVarp, nodep->arraysp(),
|
||||||
|
0, selects_docs, selects_code );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleVarRecurse(AstVar* nodep, AstVar* chgVarp, AstRange* arrayp,
|
||||||
|
int dimension, vector<int>& selects_docs, vector<int>& selects_code) {
|
||||||
|
if (arrayp) {
|
||||||
|
for (int index=arrayp->lsbConst(); index<=arrayp->msbConst()+1; index++) {
|
||||||
|
// Handle the next dimension, if any
|
||||||
|
selects_docs[dimension] = index;
|
||||||
|
selects_code[dimension] = index - arrayp->lsbConst();
|
||||||
|
toggleVarRecurse(nodep, chgVarp, arrayp->nextp()->castRange(),
|
||||||
|
dimension+1, selects_docs, selects_code);
|
||||||
|
}
|
||||||
|
} else { // No more arraying - just each bit in the width
|
||||||
|
if (nodep->rangep()) {
|
||||||
|
for (int bitindex_docs=nodep->lsb(); bitindex_docs<nodep->msb()+1; bitindex_docs++) {
|
||||||
|
toggleVarBottom(nodep, chgVarp,
|
||||||
|
dimension, selects_docs, selects_code,
|
||||||
|
true, bitindex_docs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toggleVarBottom(nodep, chgVarp,
|
||||||
|
dimension, selects_docs, selects_code,
|
||||||
|
false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void toggleVarBottom(AstVar* nodep, AstVar* chgVarp,
|
||||||
|
int dimension, vector<int>& selects_docs, vector<int>& selects_code,
|
||||||
|
bool bitsel, int bitindex_docs) {
|
||||||
|
string comment = nodep->name();
|
||||||
|
AstNode* varRefp = new AstVarRef(nodep->fileline(), nodep, false);
|
||||||
|
AstNode* chgRefp = new AstVarRef(nodep->fileline(), chgVarp, true);
|
||||||
|
// Now determine the name of, and how to get to the bit of this slice
|
||||||
|
for (int dim=0; dim<dimension; dim++) {
|
||||||
|
// Comments are strings, not symbols, so we don't need __BRA__ __KET__
|
||||||
|
comment += "["+cvtToStr(selects_docs[dim])+"]";
|
||||||
|
varRefp = new AstArraySel(nodep->fileline(), varRefp, selects_code[dim]);
|
||||||
|
chgRefp = new AstArraySel(nodep->fileline(), chgRefp, selects_code[dim]);
|
||||||
|
}
|
||||||
|
if (bitsel) {
|
||||||
|
comment += "["+cvtToStr(bitindex_docs)+"]";
|
||||||
|
int bitindex_code = bitindex_docs - nodep->lsb();
|
||||||
|
varRefp = new AstSel(nodep->fileline(), varRefp, bitindex_code, 1);
|
||||||
|
chgRefp = new AstSel(nodep->fileline(), chgRefp, bitindex_code, 1);
|
||||||
|
}
|
||||||
|
AstCoverToggle* newp = new AstCoverToggle (nodep->fileline(),
|
||||||
|
newCoverInc(nodep->fileline(), "", "v_toggle", comment),
|
||||||
|
varRefp, chgRefp);
|
||||||
|
m_modp->addStmtp(newp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS - LINE COVERAGE
|
||||||
virtual void visit(AstIf* nodep, AstNUser*) {
|
virtual void visit(AstIf* nodep, AstNUser*) {
|
||||||
UINFO(4," IF: "<<nodep<<endl);
|
UINFO(4," IF: "<<nodep<<endl);
|
||||||
if (m_checkBlock) {
|
if (m_checkBlock) {
|
||||||
nodep->ifsp()->iterateAndNext(*this);
|
nodep->ifsp()->iterateAndNext(*this);
|
||||||
if (m_checkBlock && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
|
if (m_checkBlock
|
||||||
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
|
||||||
if (!nodep->backp()->castIf()
|
if (!nodep->backp()->castIf()
|
||||||
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
|
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
|
||||||
UINFO(4," COVER: "<<nodep<<endl);
|
UINFO(4," COVER: "<<nodep<<endl);
|
||||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "block", "if"));
|
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Don't do empty else's, only empty if/case's
|
// Don't do empty else's, only empty if/case's
|
||||||
if (nodep->elsesp()) {
|
if (nodep->elsesp()) {
|
||||||
m_checkBlock = true;
|
m_checkBlock = true;
|
||||||
nodep->elsesp()->iterateAndNext(*this);
|
nodep->elsesp()->iterateAndNext(*this);
|
||||||
if (m_checkBlock && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
if (m_checkBlock
|
||||||
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
|
||||||
UINFO(4," COVER: "<<nodep<<endl);
|
UINFO(4," COVER: "<<nodep<<endl);
|
||||||
if (nodep->elsesp()->castIf()) {
|
if (nodep->elsesp()->castIf()) {
|
||||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "block", "elsif"));
|
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "elsif"));
|
||||||
} else {
|
} else {
|
||||||
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "block", "else"));
|
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "v_line", "else"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,22 +246,25 @@ private:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
||||||
UINFO(4," CASEI: "<<nodep<<endl);
|
UINFO(4," CASEI: "<<nodep<<endl);
|
||||||
if (m_checkBlock && v3Global.opt.coverageLine()) {
|
if (m_checkBlock
|
||||||
|
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
if (m_checkBlock) { // if the case body didn't disable it
|
if (m_checkBlock) { // if the case body didn't disable it
|
||||||
UINFO(4," COVER: "<<nodep<<endl);
|
UINFO(4," COVER: "<<nodep<<endl);
|
||||||
nodep->addBodysp(newCoverInc(nodep->fileline(), "block", "case"));
|
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case"));
|
||||||
}
|
}
|
||||||
m_checkBlock = true; // Reset as a child may have cleared it
|
m_checkBlock = true; // Reset as a child may have cleared it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||||
UINFO(4," PSLCOVER: "<<nodep<<endl);
|
UINFO(4," PSLCOVER: "<<nodep<<endl);
|
||||||
|
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->coverincp()) {
|
if (!nodep->coverincp()) {
|
||||||
// Note the name may be overridden by V3Assert processing
|
// Note the name may be overridden by V3Assert processing
|
||||||
nodep->coverincp(newCoverInc(nodep->fileline(), "psl_cover", "cover"));
|
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover"));
|
||||||
}
|
}
|
||||||
|
m_checkBlock = true; // Reset as a child may have cleared it
|
||||||
}
|
}
|
||||||
virtual void visit(AstStop* nodep, AstNUser*) {
|
virtual void visit(AstStop* nodep, AstNUser*) {
|
||||||
UINFO(4," STOP: "<<nodep<<endl);
|
UINFO(4," STOP: "<<nodep<<endl);
|
||||||
@@ -135,9 +276,30 @@ private:
|
|||||||
UINFO(4," OFF: "<<nodep<<endl);
|
UINFO(4," OFF: "<<nodep<<endl);
|
||||||
m_checkBlock = false;
|
m_checkBlock = false;
|
||||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
} else {
|
||||||
|
if (m_checkBlock) nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
if (m_checkBlock) nodep->iterateChildren(*this);
|
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||||
|
// Record the hierarchy of any named begins, so we can apply to user
|
||||||
|
// coverage points. This is because there may be cov points inside
|
||||||
|
// generate blocks; each point should get separate consideration.
|
||||||
|
// (Currently ignored for line coverage, since any generate iteration
|
||||||
|
// covers the code in that line.)
|
||||||
|
string oldHier = m_beginHier;
|
||||||
|
bool oldtog = m_inToggleOff;
|
||||||
|
{
|
||||||
|
m_inToggleOff = true;
|
||||||
|
if (nodep->name()!="") {
|
||||||
|
m_beginHier = m_beginHier + (m_beginHier!=""?".":"") + nodep->name();
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_beginHier = oldHier;
|
||||||
|
m_inToggleOff = oldtog;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS - BOTH
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
if (m_checkBlock) {
|
if (m_checkBlock) {
|
||||||
@@ -151,6 +313,8 @@ public:
|
|||||||
CoverageVisitor(AstNetlist* rootp) {
|
CoverageVisitor(AstNetlist* rootp) {
|
||||||
// Operate on all modules
|
// Operate on all modules
|
||||||
m_checkBlock = true;
|
m_checkBlock = true;
|
||||||
|
m_beginHier = "";
|
||||||
|
m_inToggleOff = false;
|
||||||
rootp->iterateChildren(*this);
|
rootp->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual ~CoverageVisitor() {}
|
virtual ~CoverageVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Coverage modules/signals together
|
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2009 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
// COVERAGEJOIN TRANSFORMATIONS:
|
||||||
|
// If two COVERTOGGLEs have same VARSCOPE, combine them
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "V3Global.h"
|
||||||
|
#include "V3CoverageJoin.h"
|
||||||
|
#include "V3Hashed.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// CoverageJoin state, as a visitor of each AstNode
|
||||||
|
|
||||||
|
class CoverageJoinVisitor : public AstNVisitor {
|
||||||
|
private:
|
||||||
|
// NODE STATE
|
||||||
|
// V3Hashed
|
||||||
|
// AstCoverToggle->VarRef::user4() // V3Hashed calculation
|
||||||
|
|
||||||
|
//AstUser4InUse In V3Hashed
|
||||||
|
|
||||||
|
// TYPES
|
||||||
|
typedef vector<AstCoverToggle*> ToggleList;
|
||||||
|
|
||||||
|
// STATE
|
||||||
|
ToggleList m_toggleps; // List of of all AstCoverToggle's
|
||||||
|
|
||||||
|
V3Double0 m_statToggleJoins; // Statistic tracking
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void detectDuplicates() {
|
||||||
|
UINFO(9,"Finding duplicates\n");
|
||||||
|
// Note uses user4
|
||||||
|
V3Hashed hashed; // Duplicate code detection
|
||||||
|
// Hash all of the original signals we toggle cover
|
||||||
|
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
||||||
|
AstCoverToggle* nodep = *it;
|
||||||
|
hashed.hashAndInsert(nodep->origp());
|
||||||
|
}
|
||||||
|
// Find if there are any duplicates
|
||||||
|
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
||||||
|
AstCoverToggle* nodep = *it;
|
||||||
|
if (nodep->backp()) { // nodep->backp() is null if we already detected it's a duplicate and unlinked it
|
||||||
|
// Want to choose a base node, and keep finding duplicates that are identical
|
||||||
|
// This prevents making chains where a->b, then c->d, then b->c, as we'll find a->b, a->c, a->d directly.
|
||||||
|
while (1) {
|
||||||
|
V3Hashed::iterator dupit = hashed.findDuplicate(nodep->origp());
|
||||||
|
if (dupit == hashed.end()) break;
|
||||||
|
//
|
||||||
|
AstNode* duporigp = hashed.iteratorNodep(dupit);
|
||||||
|
// Note hashed will point to the original variable (what's duplicated), not the covertoggle,
|
||||||
|
// but we need to get back to the covertoggle which is immediately above, so:
|
||||||
|
AstCoverToggle* removep = duporigp->backp()->castCoverToggle();
|
||||||
|
if (!removep) nodep->v3fatalSrc("CoverageJoin duplicate of wrong type");
|
||||||
|
UINFO(8," Orig "<<nodep<<" -->> "<<nodep->incp()->declp()<<endl);
|
||||||
|
UINFO(8," dup "<<removep<<" -->> "<<removep->incp()->declp()<<endl);
|
||||||
|
// The CoverDecl the duplicate pointed to now needs to point to the original's data
|
||||||
|
// IE the duplicate will get the coverage number from the non-duplicate
|
||||||
|
AstCoverDecl* datadeclp = nodep->incp()->declp()->dataDeclThisp();
|
||||||
|
removep->incp()->declp()->dataDeclp (datadeclp);
|
||||||
|
UINFO(8," new "<<removep->incp()->declp()<<endl);
|
||||||
|
// Mark the found node as a duplicate of the first node
|
||||||
|
// (Not vice-versa as we have the iterator for the found node)
|
||||||
|
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
|
||||||
|
// Remove node from comparison so don't hit it again
|
||||||
|
hashed.erase(dupit);
|
||||||
|
m_statToggleJoins++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
|
// Find all Coverage's
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
// Simplify
|
||||||
|
detectDuplicates();
|
||||||
|
}
|
||||||
|
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
||||||
|
m_toggleps.push_back(nodep);
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
//--------------------
|
||||||
|
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
CoverageJoinVisitor(AstNetlist* nodep) {
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
virtual ~CoverageJoinVisitor() {
|
||||||
|
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Coverage class functions
|
||||||
|
|
||||||
|
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
|
CoverageJoinVisitor visitor (rootp);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2009 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef _V3COVERAGEJOIN_H_
|
||||||
|
#define _V3COVERAGEJOIN_H_ 1
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "V3Error.h"
|
||||||
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
class V3CoverageJoin {
|
||||||
|
public:
|
||||||
|
// CREATORS
|
||||||
|
static void coverageJoin(AstNetlist* rootp);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
+21
-17
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Dead code elimination
|
// DESCRIPTION: Verilator: Dead code elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,13 +21,13 @@
|
|||||||
// DEAD TRANSFORMATIONS:
|
// DEAD TRANSFORMATIONS:
|
||||||
// Remove any unreferenced modules
|
// Remove any unreferenced modules
|
||||||
// Remove any unreferenced variables
|
// Remove any unreferenced variables
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -46,7 +46,7 @@ private:
|
|||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->modp()->user(nodep->modp()->user() - 1);
|
nodep->modp()->user1(nodep->modp()->user1() - 1);
|
||||||
}
|
}
|
||||||
//-----
|
//-----
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
||||||
@@ -71,6 +71,7 @@ private:
|
|||||||
// AstModule::user() -> int. Count of number of cells referencing this module.
|
// AstModule::user() -> int. Count of number of cells referencing this module.
|
||||||
// AstVar::user() -> int. Count of number of references
|
// AstVar::user() -> int. Count of number of references
|
||||||
// AstVarScope::user() -> int. Count of number of references
|
// AstVarScope::user() -> int. Count of number of references
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
||||||
@@ -81,23 +82,27 @@ private:
|
|||||||
AssignMap m_assignMap; // List of all simple assignments for each variable
|
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||||
bool m_elimUserVars; // Allow removal of user's vars
|
bool m_elimUserVars; // Allow removal of user's vars
|
||||||
bool m_sideEffect; // Side effects discovered in assign RHS
|
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->modp()->user(nodep->modp()->user() + 1);
|
nodep->modp()->user1(nodep->modp()->user1() + 1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (nodep->varScopep()) {
|
if (nodep->varScopep()) {
|
||||||
nodep->varScopep()->user(nodep->varScopep()->user() + 1);
|
nodep->varScopep()->user1(nodep->varScopep()->user1() + 1);
|
||||||
nodep->varScopep()->varp()->user(nodep->varScopep()->varp()->user() + 1);
|
nodep->varScopep()->varp()->user1(nodep->varScopep()->varp()->user1() + 1);
|
||||||
}
|
}
|
||||||
if (nodep->varp()) {
|
if (nodep->varp()) {
|
||||||
nodep->varp()->user(nodep->varp()->user() + 1);
|
nodep->varp()->user1(nodep->varp()->user1() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||||
@@ -143,7 +148,7 @@ private:
|
|||||||
AstModule* nextmodp;
|
AstModule* nextmodp;
|
||||||
for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
|
||||||
nextmodp = modp->nextp()->castModule();
|
nextmodp = modp->nextp()->castModule();
|
||||||
if (modp->level()>2 && modp->user()==0) {
|
if (modp->level()>2 && modp->user1()==0) {
|
||||||
// > 2 because L1 is the wrapper, L2 is the top user module
|
// > 2 because L1 is the wrapper, L2 is the top user module
|
||||||
UINFO(4," Dead module "<<modp<<endl);
|
UINFO(4," Dead module "<<modp<<endl);
|
||||||
// And its children may now be killable too; correct counts
|
// And its children may now be killable too; correct counts
|
||||||
@@ -164,7 +169,7 @@ private:
|
|||||||
// Delete any unused varscopes
|
// Delete any unused varscopes
|
||||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||||
AstVarScope* vscp = *it;
|
AstVarScope* vscp = *it;
|
||||||
if (vscp->user() == 0 && canElim(vscp->varp())) {
|
if (vscp->user1() == 0 && canElim(vscp->varp())) {
|
||||||
UINFO(4," Dead "<<vscp<<endl);
|
UINFO(4," Dead "<<vscp<<endl);
|
||||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||||
@@ -176,7 +181,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
|
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
|
||||||
if ((*it)->user() == 0 && canElim((*it))) {
|
if ((*it)->user1() == 0 && canElim((*it))) {
|
||||||
UINFO(4," Dead "<<(*it)<<endl);
|
UINFO(4," Dead "<<(*it)<<endl);
|
||||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
||||||
}
|
}
|
||||||
@@ -189,7 +194,6 @@ public:
|
|||||||
m_elimUserVars = elimUserVars;
|
m_elimUserVars = elimUserVars;
|
||||||
m_sideEffect = false;
|
m_sideEffect = false;
|
||||||
// Operate on whole netlist
|
// Operate on whole netlist
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
deadCheckVar();
|
deadCheckVar();
|
||||||
// Modules after vars, because might be vars we delete inside a mod we delete
|
// Modules after vars, because might be vars we delete inside a mod we delete
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Dead branch elimination
|
// DESCRIPTION: Verilator: Dead branch elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+46
-40
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Delayed's Transformations:
|
// V3Delayed's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Replace ASSIGNDLY var, exp
|
// Replace ASSIGNDLY var, exp
|
||||||
// With ASSIGNDLY newvar, exp
|
// With ASSIGNDLY newvar, exp
|
||||||
// At top of block: VAR newvar
|
// At top of block: VAR newvar
|
||||||
// At bottom of block: ASSIGNW var newvar
|
// At bottom of block: ASSIGNW var newvar
|
||||||
@@ -54,8 +54,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -73,17 +73,21 @@ class DelayedVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Cleared each module:
|
// Cleared each module:
|
||||||
// AstVarScope::userp() -> AstVarScope*. Points to temp var created.
|
// AstVarScope::user1p() -> AstVarScope*. Points to temp var created.
|
||||||
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal
|
// AstVarScope::user2p() -> AstActive*. Points to activity block of signal
|
||||||
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
|
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
|
||||||
|
// AstVar::user1() -> VarUsage. Tracks delayed vs non-delayed usage
|
||||||
// AstVar::user2() -> bool. Set true if already made warning
|
// AstVar::user2() -> bool. Set true if already made warning
|
||||||
// AstVar::user3() -> VarUsage. Tracks delayed vs non-delayed usage
|
|
||||||
// AstVar::user4() -> int. Vector number, for assignment creation
|
// AstVar::user4() -> int. Vector number, for assignment creation
|
||||||
// AstVarRef::user2() -> bool. Set true if already processed
|
// AstVarRef::user2() -> bool. Set true if already processed
|
||||||
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
|
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
|
||||||
// Cleared each scope:
|
// Cleared each scope:
|
||||||
// AstAssignDly::user5() -> AstVarScope*. __Vdlyvset__ created for this assign
|
// AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign
|
||||||
// AstAlwaysPost::user5() -> AstVarScope*. __Vdlyvset__ last referenced in IF
|
// AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
AstUser2InUse m_inuser2;
|
||||||
|
AstUser3InUse m_inuser3;
|
||||||
|
AstUser4InUse m_inuser4;
|
||||||
|
|
||||||
enum VarUsage { VU_NONE=0, VU_DLY=1, VU_NONDLY=2 };
|
enum VarUsage { VU_NONE=0, VU_DLY=1, VU_NONDLY=2 };
|
||||||
|
|
||||||
@@ -98,13 +102,18 @@ private:
|
|||||||
VarMap m_modVarMap; // Table of new var names created under module
|
VarMap m_modVarMap; // Table of new var names created under module
|
||||||
V3Double0 m_statSharedSet;// Statistic tracking
|
V3Double0 m_statSharedSet;// Statistic tracking
|
||||||
|
|
||||||
//static int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
void markVarUsage(AstVar* nodep, uint32_t flags) {
|
void markVarUsage(AstVar* nodep, uint32_t flags) {
|
||||||
//UINFO(4," MVU "<<flags<<" "<<nodep<<endl);
|
//UINFO(4," MVU "<<flags<<" "<<nodep<<endl);
|
||||||
nodep->user3( nodep->user3() | flags );
|
nodep->user1( nodep->user1() | flags );
|
||||||
if ((nodep->user3() & VU_DLY) && (nodep->user3() & VU_NONDLY)) {
|
if ((nodep->user1() & VU_DLY) && (nodep->user1() & VU_NONDLY)) {
|
||||||
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<<nodep->prettyName());
|
nodep->v3warn(BLKANDNBLK,"Unsupported: Blocked and non-blocking assignments to same variable: "<<nodep->prettyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +189,7 @@ private:
|
|||||||
dimreadps.push_front(dimp);
|
dimreadps.push_front(dimp);
|
||||||
} else {
|
} else {
|
||||||
string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension)
|
string bitvarname = (string("__Vdlyvdim")+cvtToStr(dimension)
|
||||||
+"__"+oldvarp->shortName()+"__"+cvtToStr(modVecNum));
|
+"__"+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width());
|
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width());
|
||||||
AstAssign* bitassignp
|
AstAssign* bitassignp
|
||||||
= new AstAssign (nodep->fileline(),
|
= new AstAssign (nodep->fileline(),
|
||||||
@@ -198,7 +207,7 @@ private:
|
|||||||
if (bitselp->fromp()->castConst()) {// vlsb = constant, can just push constant into where we use it
|
if (bitselp->fromp()->castConst()) {// vlsb = constant, can just push constant into where we use it
|
||||||
bitreadp = lsbvaluep;
|
bitreadp = lsbvaluep;
|
||||||
} else {
|
} else {
|
||||||
string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__"+cvtToStr(modVecNum));
|
string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width());
|
AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width());
|
||||||
AstAssign* bitassignp = new AstAssign (nodep->fileline(),
|
AstAssign* bitassignp = new AstAssign (nodep->fileline(),
|
||||||
new AstVarRef(nodep->fileline(), bitvscp, true),
|
new AstVarRef(nodep->fileline(), bitvscp, true),
|
||||||
@@ -213,7 +222,7 @@ private:
|
|||||||
if (nodep->rhsp()->castConst()) { // vval = constant, can just push constant into where we use it
|
if (nodep->rhsp()->castConst()) { // vval = constant, can just push constant into where we use it
|
||||||
valreadp = nodep->rhsp()->unlinkFrBack();
|
valreadp = nodep->rhsp()->unlinkFrBack();
|
||||||
} else {
|
} else {
|
||||||
string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__"+cvtToStr(modVecNum));
|
string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, nodep->rhsp()->width());
|
AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, nodep->rhsp()->width());
|
||||||
newlhsp = new AstVarRef(nodep->fileline(), valvscp, true);
|
newlhsp = new AstVarRef(nodep->fileline(), valvscp, true);
|
||||||
valreadp = new AstVarRef(nodep->fileline(), valvscp, false);
|
valreadp = new AstVarRef(nodep->fileline(), valvscp, false);
|
||||||
@@ -223,16 +232,16 @@ private:
|
|||||||
bool sharedVset = false;
|
bool sharedVset = false;
|
||||||
AstVarScope* setvscp;
|
AstVarScope* setvscp;
|
||||||
|
|
||||||
if (nodep->user5p()) {
|
if (nodep->user3p()) {
|
||||||
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
||||||
// then we told this nodep->user5 we can use its Vdlyvset rather than making a new one.
|
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
||||||
// This is good for code like:
|
// This is good for code like:
|
||||||
// for (i=0; i<5; i++) vector[i] <= something;
|
// for (i=0; i<5; i++) vector[i] <= something;
|
||||||
sharedVset = true;
|
sharedVset = true;
|
||||||
setvscp = nodep->user5p()->castNode()->castVarScope();
|
setvscp = nodep->user3p()->castNode()->castVarScope();
|
||||||
m_statSharedSet++;
|
m_statSharedSet++;
|
||||||
} else { // Create new one
|
} else { // Create new one
|
||||||
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__"+cvtToStr(modVecNum));
|
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
|
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
|
||||||
AstAssignPre* setinitp
|
AstAssignPre* setinitp
|
||||||
= new AstAssignPre (nodep->fileline(),
|
= new AstAssignPre (nodep->fileline(),
|
||||||
@@ -247,7 +256,7 @@ private:
|
|||||||
nodep->addNextHere(setassignp);
|
nodep->addNextHere(setassignp);
|
||||||
}
|
}
|
||||||
if (m_nextDlyp) { // Tell next assigndly it can share the variable
|
if (m_nextDlyp) { // Tell next assigndly it can share the variable
|
||||||
m_nextDlyp->user5p(setvscp);
|
m_nextDlyp->user3p(setvscp);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Create ALWAYSPOST for delayed variable
|
// Create ALWAYSPOST for delayed variable
|
||||||
@@ -269,12 +278,12 @@ private:
|
|||||||
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
||||||
if (!finalp) {
|
if (!finalp) {
|
||||||
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
|
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
|
||||||
UINFO(9," Created "<<finalp<<endl);
|
UINFO(9," Created "<<finalp<<endl);
|
||||||
m_activep->addStmtsp(finalp);
|
m_activep->addStmtsp(finalp);
|
||||||
varrefp->varScopep()->user4p(finalp);
|
varrefp->varScopep()->user4p(finalp);
|
||||||
}
|
}
|
||||||
AstIf* postLogicp;
|
AstIf* postLogicp;
|
||||||
if (finalp->user5p()->castNode() == setvscp) {
|
if (finalp->user3p()->castNode() == setvscp) {
|
||||||
// Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*,
|
// Optimize as above; if sharing Vdlyvset *ON SAME VARIABLE*,
|
||||||
// we can share the IF statement too
|
// we can share the IF statement too
|
||||||
postLogicp = finalp->user4p()->castNode()->castIf();
|
postLogicp = finalp->user4p()->castNode()->castIf();
|
||||||
@@ -284,9 +293,9 @@ private:
|
|||||||
new AstVarRef(nodep->fileline(), setvscp, false),
|
new AstVarRef(nodep->fileline(), setvscp, false),
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
UINFO(9," Created "<<postLogicp<<endl);
|
UINFO(9," Created "<<postLogicp<<endl);
|
||||||
finalp->addBodysp(postLogicp);
|
finalp->addBodysp(postLogicp);
|
||||||
finalp->user5p(setvscp); // Remember IF's vset variable
|
finalp->user3p(setvscp); // Remember IF's vset variable
|
||||||
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
||||||
}
|
}
|
||||||
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
||||||
@@ -298,15 +307,11 @@ private:
|
|||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
//VV***** We reset all userp() on the netlist
|
//VV***** We reset all userp() on the netlist
|
||||||
m_modVarMap.clear();
|
m_modVarMap.clear();
|
||||||
AstNode::userClearTree();
|
|
||||||
AstNode::user2ClearTree();
|
|
||||||
AstNode::user3ClearTree();
|
|
||||||
AstNode::user4ClearTree();
|
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
UINFO(4," MOD "<<nodep<<endl);
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
AstNode::user5ClearTree();
|
AstNode::user3ClearTree();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
@@ -330,7 +335,7 @@ private:
|
|||||||
&& nodep->lhsp()->castSel()->fromp()->castArraySel())) {
|
&& nodep->lhsp()->castSel()->fromp()->castArraySel())) {
|
||||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNode* newlhsp = createDlyArray(nodep, lhsp);
|
AstNode* newlhsp = createDlyArray(nodep, lhsp);
|
||||||
if (m_inLoop) nodep->v3error("Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs)");
|
if (m_inLoop) nodep->v3warn(BLKLOOPINIT,"Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs)");
|
||||||
if (newlhsp) {
|
if (newlhsp) {
|
||||||
nodep->lhsp(newlhsp);
|
nodep->lhsp(newlhsp);
|
||||||
} else {
|
} else {
|
||||||
@@ -347,7 +352,7 @@ private:
|
|||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
if (!nodep->user2()) { // Not done yet
|
if (!nodep->user2()) { // Not done yet
|
||||||
nodep->user2(true);
|
nodep->user2(true);
|
||||||
|
|
||||||
if (m_inDly && nodep->lvalue()) {
|
if (m_inDly && nodep->lvalue()) {
|
||||||
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
||||||
markVarUsage(nodep->varp(), VU_DLY);
|
markVarUsage(nodep->varp(), VU_DLY);
|
||||||
@@ -355,7 +360,7 @@ private:
|
|||||||
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
|
if (!m_activep->hasClocked()) nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active");
|
||||||
AstVarScope* oldvscp = nodep->varScopep();
|
AstVarScope* oldvscp = nodep->varScopep();
|
||||||
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!oldvscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||||
AstVarScope* dlyvscp = oldvscp->userp()->castNode()->castVarScope();
|
AstVarScope* dlyvscp = oldvscp->user1p()->castNode()->castVarScope();
|
||||||
if (dlyvscp) { // Multiple use of delayed variable
|
if (dlyvscp) { // Multiple use of delayed variable
|
||||||
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
|
AstActive* oldactivep = dlyvscp->user2p()->castNode()->castActive();
|
||||||
if (!oldactivep) nodep->v3fatalSrc("<= old dly assignment not put under sensitivity block");
|
if (!oldactivep) nodep->v3fatalSrc("<= old dly assignment not put under sensitivity block");
|
||||||
@@ -371,8 +376,8 @@ private:
|
|||||||
UINFO(4," Act: "<<m_activep<<endl);
|
UINFO(4," Act: "<<m_activep<<endl);
|
||||||
UINFO(4," Act: "<<oldactivep<<endl);
|
UINFO(4," Act: "<<oldactivep<<endl);
|
||||||
// Make a new sensitivity list, which is the combination of both blocks
|
// Make a new sensitivity list, which is the combination of both blocks
|
||||||
AstSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true)->castSenItem();
|
AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true);
|
||||||
AstSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true)->castSenItem();
|
AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true);
|
||||||
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
|
AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena);
|
||||||
if (senb) treep->addSensesp(senb);
|
if (senb) treep->addSensesp(senb);
|
||||||
if (AstSenTree* storep = oldactivep->sensesStorep()) {
|
if (AstSenTree* storep = oldactivep->sensesStorep()) {
|
||||||
@@ -395,13 +400,13 @@ private:
|
|||||||
new AstVarRef(nodep->fileline(), oldvscp, true),
|
new AstVarRef(nodep->fileline(), oldvscp, true),
|
||||||
new AstVarRef(nodep->fileline(), dlyvscp, false));
|
new AstVarRef(nodep->fileline(), dlyvscp, false));
|
||||||
postp->lhsp()->user2(true); // Don't detect this assignment
|
postp->lhsp()->user2(true); // Don't detect this assignment
|
||||||
oldvscp->userp(dlyvscp); // So we can find it later
|
oldvscp->user1p(dlyvscp); // So we can find it later
|
||||||
// Make new ACTIVE with identical sensitivity tree
|
// Make new ACTIVE with identical sensitivity tree
|
||||||
AstActive* newactp = new AstActive (nodep->fileline(), "sequentdly",
|
AstActive* newactp = new AstActive (nodep->fileline(), "sequentdly",
|
||||||
m_activep->sensesp());
|
m_activep->sensesp());
|
||||||
newactp->addStmtsp(prep); // Add to FRONT of statements
|
newactp->addStmtsp(prep); // Add to FRONT of statements
|
||||||
newactp->addStmtsp(postp);
|
newactp->addStmtsp(postp);
|
||||||
m_activep->addNext(newactp);
|
m_activep->addNext(newactp);
|
||||||
dlyvscp->user2p(newactp);
|
dlyvscp->user2p(newactp);
|
||||||
}
|
}
|
||||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
||||||
@@ -411,6 +416,7 @@ private:
|
|||||||
else if (!m_inDly && nodep->lvalue()) {
|
else if (!m_inDly && nodep->lvalue()) {
|
||||||
//UINFO(9,"NBA "<<nodep<<endl);
|
//UINFO(9,"NBA "<<nodep<<endl);
|
||||||
if (!m_inInitial) {
|
if (!m_inInitial) {
|
||||||
|
UINFO(4,"AssignNDlyVar: "<<nodep<<endl);
|
||||||
markVarUsage(nodep->varp(), VU_NONDLY);
|
markVarUsage(nodep->varp(), VU_NONDLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,7 +424,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
||||||
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Unroll\n");
|
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||||
bool oldloop = m_inLoop;
|
bool oldloop = m_inLoop;
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+16
-17
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Depth's Transformations:
|
// V3Depth's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each wide OP, assign a temporary variable.
|
// For each wide OP, assign a temporary variable.
|
||||||
// For each deep expression, assign expression to temporary.
|
// For each deep expression, assign expression to temporary.
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -52,14 +52,18 @@ private:
|
|||||||
int m_depth; // How deep in an expression
|
int m_depth; // How deep in an expression
|
||||||
int m_maxdepth; // Maximum depth in an expression
|
int m_maxdepth; // Maximum depth in an expression
|
||||||
|
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
void createDeepTemp(AstNode* nodep) {
|
void createDeepTemp(AstNode* nodep) {
|
||||||
UINFO(6," Deep "<<nodep<<endl);
|
UINFO(6," Deep "<<nodep<<endl);
|
||||||
//if (debug()>=9) nodep->dumpTree(cout,"deep:");
|
//if (debug()>=9) nodep->dumpTree(cout,"deep:");
|
||||||
|
|
||||||
string newvarname = ((string)"__Vdeeptemp__"+cvtToStr(m_modp->varNumGetInc()));
|
string newvarname = ((string)"__Vdeeptemp"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
AstVar* varp = new AstVar (nodep->fileline(), AstVarType::STMTTEMP, newvarname,
|
AstVar* varp = new AstVar (nodep->fileline(), AstVarType::STMTTEMP, newvarname,
|
||||||
// Width, not widthMin, as we may be in middle of BITSEL expression which
|
// Width, not widthMin, as we may be in middle of BITSEL expression which
|
||||||
// though it's one bit wide, needs the mask in the upper bits.
|
// though it's one bit wide, needs the mask in the upper bits.
|
||||||
@@ -86,6 +90,7 @@ private:
|
|||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
m_funcp = nodep;
|
m_funcp = nodep;
|
||||||
@@ -111,7 +116,7 @@ private:
|
|||||||
// We have some operator defines that use 2 parens, so += 2.
|
// We have some operator defines that use 2 parens, so += 2.
|
||||||
m_depth += 2;
|
m_depth += 2;
|
||||||
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_depth -= 2;
|
m_depth -= 2;
|
||||||
|
|
||||||
if (m_stmtp
|
if (m_stmtp
|
||||||
@@ -133,11 +138,6 @@ private:
|
|||||||
m_funcp->isStatic(false);
|
m_funcp->isStatic(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverInc* nodep, AstNUser*) {
|
|
||||||
// OPTIMIZE: For now this needs this->__Vcoverage, but could be globalized
|
|
||||||
needNonStaticFunc(nodep);
|
|
||||||
visitStmt(nodep);
|
|
||||||
}
|
|
||||||
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
||||||
needNonStaticFunc(nodep);
|
needNonStaticFunc(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -163,7 +163,6 @@ public:
|
|||||||
m_depth=0;
|
m_depth=0;
|
||||||
m_maxdepth=0;
|
m_maxdepth=0;
|
||||||
//
|
//
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~DepthVisitor() {}
|
virtual ~DepthVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+14
-9
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3DepthBlock's Transformations:
|
// V3DepthBlock's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each deep block, create cfunc including that block.
|
// For each deep block, create cfunc including that block.
|
||||||
//
|
//
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -49,9 +49,13 @@ private:
|
|||||||
int m_depth; // How deep in an expression
|
int m_depth; // How deep in an expression
|
||||||
int m_deepNum; // How many functions made
|
int m_deepNum; // How many functions made
|
||||||
|
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
AstCFunc* createDeepFunc(AstNode* nodep) {
|
AstCFunc* createDeepFunc(AstNode* nodep) {
|
||||||
AstNRelinker relinkHandle;
|
AstNRelinker relinkHandle;
|
||||||
nodep->unlinkFrBack(&relinkHandle);
|
nodep->unlinkFrBack(&relinkHandle);
|
||||||
@@ -78,6 +82,7 @@ private:
|
|||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_deepNum = 0;
|
m_deepNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
// We recurse into this.
|
// We recurse into this.
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+18
-12
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -24,13 +24,13 @@
|
|||||||
// Change varref name() to be relative to current module
|
// Change varref name() to be relative to current module
|
||||||
// Remove varScopep()
|
// Remove varScopep()
|
||||||
// This allows for better V3Combine'ing.
|
// This allows for better V3Combine'ing.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ private:
|
|||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Cleared entire netlist
|
// Cleared entire netlist
|
||||||
// AstCFunc::user() // bool. Indicates processing completed
|
// AstCFunc::user() // bool. Indicates processing completed
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef multimap<string,AstCFunc*> FuncMmap;
|
typedef multimap<string,AstCFunc*> FuncMmap;
|
||||||
@@ -55,9 +56,14 @@ private:
|
|||||||
AstScope* m_scopep; // Current scope
|
AstScope* m_scopep; // Current scope
|
||||||
bool m_needThis; // Add thisp to function
|
bool m_needThis; // Add thisp to function
|
||||||
FuncMmap m_modFuncs; // Name of public functions added
|
FuncMmap m_modFuncs; // Name of public functions added
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
string descopedName(AstScope* scopep, bool& hierThisr, AstVar* varp=NULL) {
|
string descopedName(AstScope* scopep, bool& hierThisr, AstVar* varp=NULL) {
|
||||||
UASSERT(scopep, "Var/Func not scoped\n");
|
UASSERT(scopep, "Var/Func not scoped\n");
|
||||||
hierThisr = true;
|
hierThisr = true;
|
||||||
@@ -107,7 +113,7 @@ private:
|
|||||||
if (moreOfSame1) {
|
if (moreOfSame1) {
|
||||||
// Multiple functions under this name, need a wrapper function
|
// Multiple functions under this name, need a wrapper function
|
||||||
UINFO(6," Wrapping "<<name<<" multifuncs\n");
|
UINFO(6," Wrapping "<<name<<" multifuncs\n");
|
||||||
AstCFunc* newfuncp = topFuncp->cloneTree(false)->castCFunc();
|
AstCFunc* newfuncp = topFuncp->cloneTree(false);
|
||||||
if (newfuncp->initsp()) newfuncp->initsp()->unlinkFrBackWithNext()->deleteTree();
|
if (newfuncp->initsp()) newfuncp->initsp()->unlinkFrBackWithNext()->deleteTree();
|
||||||
if (newfuncp->stmtsp()) newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree();
|
if (newfuncp->stmtsp()) newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree();
|
||||||
if (newfuncp->finalsp()) newfuncp->finalsp()->unlinkFrBackWithNext()->deleteTree();
|
if (newfuncp->finalsp()) newfuncp->finalsp()->unlinkFrBackWithNext()->deleteTree();
|
||||||
@@ -178,6 +184,7 @@ private:
|
|||||||
m_modFuncs.clear();
|
m_modFuncs.clear();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
makePublicFuncWrappers();
|
makePublicFuncWrappers();
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
@@ -210,10 +217,10 @@ private:
|
|||||||
// nodep->funcp()->scopep(NULL);
|
// nodep->funcp()->scopep(NULL);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
if (!nodep->user()) {
|
if (!nodep->user1()) {
|
||||||
m_needThis = false;
|
m_needThis = false;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->user(true);
|
nodep->user1(true);
|
||||||
if (m_needThis) {
|
if (m_needThis) {
|
||||||
nodep->v3fatalSrc("old code");
|
nodep->v3fatalSrc("old code");
|
||||||
// Really we should have more node types for backend optimization of this stuff
|
// Really we should have more node types for backend optimization of this stuff
|
||||||
@@ -245,7 +252,6 @@ public:
|
|||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
m_scopep = NULL;
|
m_scopep = NULL;
|
||||||
m_needThis = false;
|
m_needThis = false;
|
||||||
AstNode::userClearTree();
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~DescopeVisitor() {}
|
virtual ~DescopeVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+421
-356
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ code for module tree
|
// DESCRIPTION: Verilator: Emit C++ code for module tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+26
-18
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ for tree
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -24,10 +25,10 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3File.h"
|
#include "V3File.h"
|
||||||
@@ -42,7 +43,7 @@ public:
|
|||||||
V3OutCFile(const string& filename) : V3OutFile(filename) {
|
V3OutCFile(const string& filename) : V3OutFile(filename) {
|
||||||
resetPrivate();
|
resetPrivate();
|
||||||
}
|
}
|
||||||
virtual ~V3OutCFile() {};
|
virtual ~V3OutCFile() {}
|
||||||
virtual void putsCellDecl(const string& classname, const string& cellname) {
|
virtual void putsCellDecl(const string& classname, const string& cellname) {
|
||||||
this->printf("%-19s\t%s;\n",
|
this->printf("%-19s\t%s;\n",
|
||||||
(classname + "*").c_str(),cellname.c_str());
|
(classname + "*").c_str(),cellname.c_str());
|
||||||
@@ -65,30 +66,36 @@ public:
|
|||||||
class V3OutScFile : public V3OutCFile {
|
class V3OutScFile : public V3OutCFile {
|
||||||
public:
|
public:
|
||||||
V3OutScFile(const string& filename) : V3OutCFile(filename) {}
|
V3OutScFile(const string& filename) : V3OutCFile(filename) {}
|
||||||
virtual ~V3OutScFile() {};
|
virtual ~V3OutScFile() {}
|
||||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||||
virtual void putsIntTopInclude() { puts("#include \"systemc.h\"\n"); }
|
virtual void putsIntTopInclude() {
|
||||||
|
puts("#include \"systemc.h\"\n");
|
||||||
|
puts("#include \"verilatedsc.h\"\n");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class V3OutSpFile : public V3OutCFile {
|
class V3OutSpFile : public V3OutCFile {
|
||||||
public:
|
public:
|
||||||
V3OutSpFile(const string& filename) : V3OutCFile(filename) {}
|
V3OutSpFile(const string& filename) : V3OutCFile(filename) {}
|
||||||
virtual ~V3OutSpFile() {};
|
virtual ~V3OutSpFile() {}
|
||||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||||
virtual void putsIntTopInclude() { puts("#include \"systemperl.h\"\n"); }
|
virtual void putsIntTopInclude() {
|
||||||
|
puts("#include \"systemperl.h\"\n");
|
||||||
|
puts("#include \"verilatedsc.h\"\n");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class V3OutVFile : public V3OutCFile {
|
class V3OutVFile : public V3OutFile {
|
||||||
public:
|
public:
|
||||||
V3OutVFile(const string& filename) : V3OutCFile(filename) {}
|
V3OutVFile(const string& filename) : V3OutFile(filename) {}
|
||||||
virtual ~V3OutVFile() {};
|
virtual ~V3OutVFile() {}
|
||||||
virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); }
|
virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class V3OutMkFile : public V3OutFile {
|
class V3OutMkFile : public V3OutFile {
|
||||||
public:
|
public:
|
||||||
V3OutMkFile(const string& filename) : V3OutFile(filename) {}
|
V3OutMkFile(const string& filename) : V3OutFile(filename) {}
|
||||||
virtual ~V3OutMkFile() {};
|
virtual ~V3OutMkFile() {}
|
||||||
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
|
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
|
||||||
// No automatic indentation yet.
|
// No automatic indentation yet.
|
||||||
void puts(const char* strg) { putsNoTracking(strg); }
|
void puts(const char* strg) { putsNoTracking(strg); }
|
||||||
@@ -103,9 +110,10 @@ public:
|
|||||||
// STATE
|
// STATE
|
||||||
V3OutCFile* m_ofp;
|
V3OutCFile* m_ofp;
|
||||||
// METHODS
|
// METHODS
|
||||||
V3OutCFile* ofp() const { return m_ofp; };
|
V3OutCFile* ofp() const { return m_ofp; }
|
||||||
void puts(const string& str) { ofp()->puts(str); }
|
void puts(const string& str) { ofp()->puts(str); }
|
||||||
void putbs(const string& str) { ofp()->putbs(str); }
|
void putbs(const string& str) { ofp()->putbs(str); }
|
||||||
|
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
||||||
bool optSystemC() { return v3Global.opt.systemC(); }
|
bool optSystemC() { return v3Global.opt.systemC(); }
|
||||||
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
|
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
|
||||||
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
|
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
|
||||||
@@ -137,7 +145,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Fileize state, as a visitor of each AstNode
|
// Count operations under the given node, as a visitor of each AstNode
|
||||||
|
|
||||||
class EmitCBaseCounterVisitor : public AstNVisitor {
|
class EmitCBaseCounterVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ for tree
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
+42
-16
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ for tree
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -39,11 +39,17 @@
|
|||||||
// Symbol table emitting
|
// Symbol table emitting
|
||||||
|
|
||||||
class EmitCSyms : EmitCBaseVisitor {
|
class EmitCSyms : EmitCBaseVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// Cleared on Netlist
|
||||||
|
// AstModule::user1() -> bool. Set true __Vconfigure called
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstModule* m_modp; // Current module
|
AstModule* m_modp; // Current module
|
||||||
typedef pair<AstScope*,AstModule*> ScopeModPair;
|
typedef pair<AstScope*,AstModule*> ScopeModPair;
|
||||||
vector<ScopeModPair> m_scopes; // Every scope by module
|
vector<ScopeModPair> m_scopes; // Every scope by module
|
||||||
V3LanguageWords m_words; // Reserved word detector
|
V3LanguageWords m_words; // Reserved word detector
|
||||||
|
int m_coverBins; // Coverage bin number
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void emitInt();
|
void emitInt();
|
||||||
@@ -59,7 +65,9 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
if (nodep->name() != "") {
|
if (nodep->name() != "") {
|
||||||
string rsvd = m_words.isKeyword(nodep->name());
|
string rsvd = m_words.isKeyword(nodep->name());
|
||||||
if (rsvd != "") {
|
if (rsvd != "") {
|
||||||
nodep->v3error("Unsupported: "+rsvd+": "<<nodep->name());
|
// Generally V3Name should find all of these and throw SYMRSVDWORD.
|
||||||
|
// We'll still check here because the compiler errors resulting if we miss this warning are SO nasty
|
||||||
|
nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter, should have hit SYMRSVDWORD: '"<<nodep->name()<<"'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,9 +76,10 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
// Collect list of scopes
|
// Collect list of scopes
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
|
||||||
// Sort m_scopes by scope name
|
// Sort m_scopes by scope name
|
||||||
sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
emitInt();
|
emitInt();
|
||||||
emitImp();
|
emitImp();
|
||||||
@@ -79,11 +88,18 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
nameCheck(nodep);
|
nameCheck(nodep);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
nameCheck(nodep);
|
nameCheck(nodep);
|
||||||
m_scopes.push_back(make_pair(nodep, m_modp));
|
m_scopes.push_back(make_pair(nodep, m_modp));
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
||||||
|
// Assign numbers to all bins, so we know how big of an array to use
|
||||||
|
if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for
|
||||||
|
nodep->binNum(m_coverBins++);
|
||||||
|
}
|
||||||
|
}
|
||||||
// NOPs
|
// NOPs
|
||||||
virtual void visit(AstNodeStmt*, AstNUser*) {}
|
virtual void visit(AstNodeStmt*, AstNUser*) {}
|
||||||
virtual void visit(AstConst*, AstNUser*) {}
|
virtual void visit(AstConst*, AstNUser*) {}
|
||||||
@@ -97,6 +113,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
public:
|
public:
|
||||||
EmitCSyms(AstNetlist* nodep) {
|
EmitCSyms(AstNetlist* nodep) {
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
m_coverBins = 0;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -146,6 +163,12 @@ void EmitCSyms::emitInt() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
puts("\n// COVERAGE\n");
|
||||||
|
if (m_coverBins) {
|
||||||
|
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint32_t));
|
||||||
|
puts("uint32_t\t__Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
|
||||||
|
}
|
||||||
|
|
||||||
puts("\n// CREATORS\n");
|
puts("\n// CREATORS\n");
|
||||||
puts(symClassName()+"("+topClassName()+"* topp, const char* namep);\n");
|
puts(symClassName()+"("+topClassName()+"* topp, const char* namep);\n");
|
||||||
puts((string)"~"+symClassName()+"() {};\n");
|
puts((string)"~"+symClassName()+"() {};\n");
|
||||||
@@ -187,12 +210,10 @@ void EmitCSyms::emitImp() {
|
|||||||
AstScope* scopep = it->first; AstModule* modp = it->second;
|
AstScope* scopep = it->first; AstModule* modp = it->second;
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
} else {
|
} else {
|
||||||
string arrow = scopep->name();
|
|
||||||
if (arrow.substr(0,4) == "TOP.") arrow.replace(0,4,".");
|
|
||||||
ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
|
ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
|
||||||
puts("(Verilated::catName(topp->name(),\"");
|
puts("(Verilated::catName(topp->name(),");
|
||||||
puts(arrow);
|
putsQuoted("."+scopep->prettyName());
|
||||||
puts("\"))\n");
|
puts("))\n");
|
||||||
comma=',';
|
comma=',';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,11 +237,16 @@ void EmitCSyms::emitImp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
|
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
|
||||||
puts("TOPp->__Vconfigure(this);\n");
|
puts("TOPp->__Vconfigure(this, true);\n");
|
||||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||||
AstScope* scopep = it->first; AstModule* modp = it->second;
|
AstScope* scopep = it->first; AstModule* modp = it->second;
|
||||||
if (!modp->isTop()) {
|
if (!modp->isTop()) {
|
||||||
puts(scopep->nameDotless()+".__Vconfigure(this);\n");
|
// first is used by AstCoverDecl's call to __vlCoverInsert
|
||||||
|
bool first = !modp->user1();
|
||||||
|
modp->user1(true);
|
||||||
|
puts(scopep->nameDotless()+".__Vconfigure(this, "
|
||||||
|
+(first?"true":"false")
|
||||||
|
+");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-12
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Makefile
|
// DESCRIPTION: Verilator: Emit Makefile
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -38,15 +38,21 @@
|
|||||||
|
|
||||||
class EmitMkVisitor : public EmitCBaseVisitor {
|
class EmitMkVisitor : public EmitCBaseVisitor {
|
||||||
public:
|
public:
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
void emitClassMake() {
|
void emitClassMake() {
|
||||||
// Generate the makefile
|
// Generate the makefile
|
||||||
V3OutMkFile of (v3Global.opt.makeDir()+"/"+ v3Global.opt.prefix() + "_classes.mk");
|
V3OutMkFile of (v3Global.opt.makeDir()+"/"+ v3Global.opt.prefix() + "_classes.mk");
|
||||||
of.putsHeader();
|
of.putsHeader();
|
||||||
of.puts("\n");
|
of.puts("\n");
|
||||||
|
|
||||||
|
of.puts("VM_COVERAGE = "); of.puts(v3Global.opt.coverage()?"1":"0"); of.puts("\n");
|
||||||
of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n");
|
of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n");
|
||||||
of.puts("\n");
|
of.puts("\n");
|
||||||
|
|
||||||
@@ -79,16 +85,17 @@ public:
|
|||||||
of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n");
|
of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n");
|
||||||
}
|
}
|
||||||
of.puts("\n# Constants...\n");
|
of.puts("\n# Constants...\n");
|
||||||
of.puts("PERL = "+V3Options::getenvStr("PERL","perl")+"\n");
|
of.puts("PERL = "+V3Options::getenvPERL()+"\n");
|
||||||
of.puts("VERILATOR_ROOT = "+V3Options::getenvStr("VERILATOR_ROOT","")+"\n");
|
of.puts("VERILATOR_ROOT = "+V3Options::getenvVERILATOR_ROOT()+"\n");
|
||||||
of.puts("SYSTEMPERL = "+V3Options::getenvStr("SYSTEMPERL","")+"\n");
|
of.puts("SYSTEMPERL = "+V3Options::getenvSYSTEMPERL()+"\n");
|
||||||
|
of.puts("SYSTEMPERL_INCLUDE = "+V3Options::getenvSYSTEMPERL_INCLUDE()+"\n");
|
||||||
|
|
||||||
of.puts("\n# Switches...\n");
|
of.puts("\n# Switches...\n");
|
||||||
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
|
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
|
||||||
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
|
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
|
||||||
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
|
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
|
||||||
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
|
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
|
||||||
of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvStr("SYSTEMC_ARCH","")+"\n");
|
of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvSYSTEMC_ARCH()+"\n");
|
||||||
|
|
||||||
of.puts("\n# Vars...\n");
|
of.puts("\n# Vars...\n");
|
||||||
of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n");
|
of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n");
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Makefile
|
// DESCRIPTION: Verilator: Emit Makefile
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+114
-51
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Verilog from tree
|
// DESCRIPTION: Verilator: Emit Verilog from tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -36,21 +36,26 @@
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
// Emit statements and math operators
|
// Emit statements and math operators
|
||||||
|
|
||||||
class EmitVImp : public EmitCBaseVisitor {
|
class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
private:
|
// MEMBERS
|
||||||
bool m_suppressSemi;
|
bool m_suppressSemi;
|
||||||
AstModule* m_modp;
|
|
||||||
public:
|
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void puts(const string& str) = 0;
|
||||||
|
virtual void putbs(const string& str) = 0;
|
||||||
|
virtual void putsNoTracking(const string& str) = 0;
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
|
||||||
putbs("module "+modClassName(nodep)+";\n");
|
putbs("module "+modClassName(nodep)+";\n");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
puts("endmodule\n");
|
puts("endmodule\n");
|
||||||
@@ -87,7 +92,7 @@ public:
|
|||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
putbs("always ");
|
putbs("always ");
|
||||||
nodep->sensesp()->iterateAndNext(*this);
|
nodep->sensesp()->iterateAndNext(*this);
|
||||||
putbs("begin\n");
|
putbs(" begin\n");
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
puts("end\n");
|
puts("end\n");
|
||||||
}
|
}
|
||||||
@@ -118,17 +123,22 @@ public:
|
|||||||
if (!m_suppressSemi) puts(";\n");
|
if (!m_suppressSemi) puts(";\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||||
|
// AstSenItem is called for dumping in isolation by V3Order
|
||||||
putbs("@(");
|
putbs("@(");
|
||||||
nodep->iterateChildren(*this);
|
for (AstNode* expp=nodep->sensesp(); expp; expp = expp->nextp()) {
|
||||||
puts(") ");
|
nodep->iterateChildren(*this);
|
||||||
|
if (expp->nextp()) puts(" or ");
|
||||||
|
}
|
||||||
|
puts(")");
|
||||||
|
}
|
||||||
|
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
||||||
|
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->sensesp(), nodep->rhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||||
putbs("");
|
putbs("");
|
||||||
if (nodep->backp()->castSenItem()) puts(" or ");
|
|
||||||
puts(nodep->edgeType().verilogKwd());
|
puts(nodep->edgeType().verilogKwd());
|
||||||
puts(" ");
|
if (nodep->sensp()) puts(" ");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
puts(" ");
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
@@ -158,25 +168,33 @@ public:
|
|||||||
puts((string)"// "+nodep->name()+"\n");
|
puts((string)"// "+nodep->name()+"\n");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverDecl*, AstNUser*) {
|
virtual void visit(AstCoverDecl*, AstNUser*) {} // N/A
|
||||||
// N/A
|
virtual void visit(AstCoverInc*, AstNUser*) {} // N/A
|
||||||
}
|
virtual void visit(AstCoverToggle*, AstNUser*) {} // N/A
|
||||||
virtual void visit(AstCoverInc*, AstNUser*) {
|
|
||||||
// N/A
|
void visitNodeDisplay(AstNode* nodep, AstNode* filep, const string& text, AstNode* exprsp) {
|
||||||
}
|
|
||||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
putbs(" (");
|
putbs(" (");
|
||||||
if (nodep->filep()) { nodep->filep()->iterateAndNext(*this); putbs(","); }
|
if (filep) { filep->iterateAndNext(*this); putbs(","); }
|
||||||
puts("\"");
|
puts("\"");
|
||||||
ofp()->putsNoTracking(nodep->text());
|
putsNoTracking(text); // Not putsQuoted, as display text contains \ already
|
||||||
puts("\"");
|
puts("\"");
|
||||||
for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) {
|
for (AstNode* expp=exprsp; expp; expp = expp->nextp()) {
|
||||||
puts(",");
|
puts(",");
|
||||||
expp->iterateAndNext(*this);
|
expp->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||||
|
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||||
|
}
|
||||||
|
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||||
|
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||||
|
}
|
||||||
|
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||||
|
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
putbs(" (");
|
putbs(" (");
|
||||||
@@ -193,6 +211,12 @@ public:
|
|||||||
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||||
|
putbs(nodep->verilogKwd());
|
||||||
|
putbs(" (");
|
||||||
|
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
||||||
|
puts(");\n");
|
||||||
|
}
|
||||||
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
putbs(" (");
|
putbs(" (");
|
||||||
@@ -216,6 +240,13 @@ public:
|
|||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstRepeat* nodep, AstNUser*) {
|
||||||
|
puts("repeat (");
|
||||||
|
nodep->countp()->iterateAndNext(*this);
|
||||||
|
puts(") {\n");
|
||||||
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
|
puts("}\n");
|
||||||
|
}
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||||
nodep->precondsp()->iterateAndNext(*this);
|
nodep->precondsp()->iterateAndNext(*this);
|
||||||
puts("while (");
|
puts("while (");
|
||||||
@@ -244,7 +275,7 @@ public:
|
|||||||
putbs("$finish;\n");
|
putbs("$finish;\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstText* nodep, AstNUser*) {
|
virtual void visit(AstText* nodep, AstNUser*) {
|
||||||
ofp()->putsNoTracking(nodep->text());
|
putsNoTracking(nodep->text());
|
||||||
}
|
}
|
||||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||||
}
|
}
|
||||||
@@ -346,11 +377,11 @@ public:
|
|||||||
if (nodep->widthp()->isOne()) {
|
if (nodep->widthp()->isOne()) {
|
||||||
nodep->lsbp()->iterateAndNext(*this);
|
nodep->lsbp()->iterateAndNext(*this);
|
||||||
} else {
|
} else {
|
||||||
puts(cvtToStr(nodep->lsbp()->castConst()->asInt()
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()
|
||||||
+nodep->widthp()->castConst()->asInt()
|
+nodep->widthp()->castConst()->toSInt()
|
||||||
-1));
|
-1));
|
||||||
puts(":");
|
puts(":");
|
||||||
nodep->lsbp()->iterateAndNext(*this);
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->lsbp()->iterateAndNext(*this); puts("+:");
|
nodep->lsbp()->iterateAndNext(*this); puts("+:");
|
||||||
@@ -368,12 +399,12 @@ public:
|
|||||||
// Terminals
|
// Terminals
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
puts(nodep->hiername());
|
puts(nodep->hiername());
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->name());
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
||||||
puts(nodep->dotted());
|
puts(nodep->dotted());
|
||||||
puts(".");
|
puts(".");
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->name());
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||||
puts(nodep->num().ascii(true,true));
|
puts(nodep->num().ascii(true,true));
|
||||||
@@ -411,27 +442,56 @@ public:
|
|||||||
virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class
|
virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class
|
||||||
// Default
|
// Default
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
puts((string)"\n???? // "+nodep->typeName()+"\n");
|
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->v3fatalSrc("Unknown node type reached emitter: "<<nodep->typeName());
|
nodep->v3fatalSrc("Unknown node type reached emitter: "<<nodep->prettyTypeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EmitVImp() {
|
EmitVBaseVisitor() {
|
||||||
m_suppressSemi = false;
|
m_suppressSemi = false;
|
||||||
m_modp = NULL;
|
|
||||||
}
|
}
|
||||||
void main(AstNode* nodep, V3OutCFile* ofp);
|
virtual ~EmitVBaseVisitor() {}
|
||||||
virtual ~EmitVImp() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
// Emit to an output file
|
||||||
|
|
||||||
void EmitVImp::main(AstNode* modp, V3OutCFile* ofp) {
|
class EmitVFileVisitor : public EmitVBaseVisitor {
|
||||||
// Output a module, or overall netlist
|
// MEMBERS
|
||||||
m_ofp = ofp;
|
V3OutFile* m_ofp;
|
||||||
modp->accept(*this);
|
// METHODS
|
||||||
}
|
V3OutFile* ofp() const { return m_ofp; }
|
||||||
|
void puts(const string& str) { ofp()->puts(str); }
|
||||||
|
void putbs(const string& str) { ofp()->putbs(str); }
|
||||||
|
void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp) {
|
||||||
|
m_ofp = ofp;
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
virtual ~EmitVFileVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Emit to a stream (perhaps stringstream)
|
||||||
|
|
||||||
|
class EmitVStreamVisitor : public EmitVBaseVisitor {
|
||||||
|
// MEMBERS
|
||||||
|
ostream& m_os;
|
||||||
|
// METHODS
|
||||||
|
void puts(const string& str) { m_os<<str; }
|
||||||
|
void putbs(const string& str) { m_os<<str; }
|
||||||
|
void putsNoTracking(const string& str) { m_os<<str; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
EmitVStreamVisitor(AstNode* nodep, ostream& os)
|
||||||
|
: m_os(os) {
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
virtual ~EmitVStreamVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// EmitV class functions
|
// EmitV class functions
|
||||||
@@ -442,15 +502,18 @@ void V3EmitV::emitv() {
|
|||||||
// All-in-one file
|
// All-in-one file
|
||||||
V3OutVFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__Vout.v");
|
V3OutVFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__Vout.v");
|
||||||
of.putsHeader();
|
of.putsHeader();
|
||||||
EmitVImp imp;
|
EmitVFileVisitor visitor (v3Global.rootp(), &of);
|
||||||
imp.main(v3Global.rootp(), &of);
|
|
||||||
} else {
|
} else {
|
||||||
// Process each module in turn
|
// Process each module in turn
|
||||||
for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castModule()) {
|
for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castModule()) {
|
||||||
EmitVImp imp;
|
V3OutVFile of (v3Global.opt.makeDir()
|
||||||
V3OutVFile of (v3Global.opt.makeDir()+"/"+imp.modClassName(modp)+"__Vout.v");
|
+"/"+EmitCBaseVisitor::modClassName(modp)+"__Vout.v");
|
||||||
of.putsHeader();
|
of.putsHeader();
|
||||||
imp.main(modp, &of);
|
EmitVFileVisitor visitor (modp, &of);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3EmitV::verilogForTree(AstNode* nodep, ostream& os) {
|
||||||
|
EmitVStreamVisitor(nodep, os);
|
||||||
|
}
|
||||||
|
|||||||
+6
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
//-*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Verilog code for module tree
|
// DESCRIPTION: Verilator: Emit Verilog code for module tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
class V3EmitV {
|
class V3EmitV {
|
||||||
public:
|
public:
|
||||||
static void emitv();
|
static void emitv();
|
||||||
|
static void verilogForTree(AstNode* nodep, ostream& os=cout);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+63
-19
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Error handling
|
// DESCRIPTION: Verilator: Error handling
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#ifndef _V3ERROR_NO_GLOBAL_
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
@@ -38,6 +38,7 @@ FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
|
|||||||
int V3Error::s_errCount = 0;
|
int V3Error::s_errCount = 0;
|
||||||
int V3Error::s_warnCount = 0;
|
int V3Error::s_warnCount = 0;
|
||||||
int V3Error::s_debugDefault = 0;
|
int V3Error::s_debugDefault = 0;
|
||||||
|
int V3Error::s_tellManual = 0;
|
||||||
ostringstream V3Error::s_errorStr; // Error string being formed
|
ostringstream V3Error::s_errorStr; // Error string being formed
|
||||||
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
|
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
|
||||||
bool V3Error::s_describedEachWarn[V3ErrorCode::MAX];
|
bool V3Error::s_describedEachWarn[V3ErrorCode::MAX];
|
||||||
@@ -45,9 +46,9 @@ bool V3Error::s_describedWarnings = false;
|
|||||||
bool V3Error::s_pretendError[V3ErrorCode::MAX];
|
bool V3Error::s_pretendError[V3ErrorCode::MAX];
|
||||||
|
|
||||||
struct v3errorIniter {
|
struct v3errorIniter {
|
||||||
v3errorIniter() { V3Error::init(); };
|
v3errorIniter() { V3Error::init(); }
|
||||||
};
|
};
|
||||||
v3errorIniter v3errorInit;
|
v3errorIniter v3errorInit;
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// ErrorCode class functions
|
// ErrorCode class functions
|
||||||
@@ -66,6 +67,17 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
// FileLine class functions
|
// FileLine class functions
|
||||||
|
|
||||||
|
FileLine::FileLine(FileLine::EmptySecret) {
|
||||||
|
m_lineno=0;
|
||||||
|
m_filename="COMMAND_LINE";
|
||||||
|
|
||||||
|
m_warnOn=0;
|
||||||
|
for (int codei=V3ErrorCode::MIN; codei<V3ErrorCode::MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
warnOff(code, code.defaultsOff());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FileLine::lineDirective(const char* textp) {
|
void FileLine::lineDirective(const char* textp) {
|
||||||
// Handle `line directive
|
// Handle `line directive
|
||||||
// Skip `line
|
// Skip `line
|
||||||
@@ -142,7 +154,7 @@ const string FileLine::profileFuncname() const {
|
|||||||
!= string::npos) {
|
!= string::npos) {
|
||||||
name.replace(pos, 1, "_");
|
name.replace(pos, 1, "_");
|
||||||
}
|
}
|
||||||
name += "__"+cvtToStr(lineno());
|
name += "__l"+cvtToStr(lineno());
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,13 +166,23 @@ ostream& operator<<(ostream& os, FileLine* fileline) {
|
|||||||
return(os);
|
return(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLine::warnIsOff(V3ErrorCode code) {
|
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||||
if (m_warnOff.test(code)) return true;
|
if (!m_warnOn.test(code)) return true;
|
||||||
// UNOPTFLAT implies UNOPT
|
// UNOPTFLAT implies UNOPT
|
||||||
if (code==V3ErrorCode::UNOPT && m_warnOff.test(V3ErrorCode::UNOPTFLAT)) return true;
|
if (code==V3ErrorCode::UNOPT && !m_warnOn.test(V3ErrorCode::UNOPTFLAT)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileLine::warnStateInherit(const FileLine& from) {
|
||||||
|
// Any warnings that are off in "from", become off in "this".
|
||||||
|
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (from.warnIsOff(code)) {
|
||||||
|
this->warnOff(code, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FileLine::v3errorEnd(ostringstream& str) {
|
void FileLine::v3errorEnd(ostringstream& str) {
|
||||||
if (this && m_lineno) {
|
if (this && m_lineno) {
|
||||||
ostringstream nsstr;
|
ostringstream nsstr;
|
||||||
@@ -203,7 +225,7 @@ void FileLine::deleteAllRemaining() {
|
|||||||
while (1) {
|
while (1) {
|
||||||
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
|
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
|
||||||
if (it==fileLineLeakChecks.end()) break;
|
if (it==fileLineLeakChecks.end()) break;
|
||||||
delete *it;
|
delete *it;
|
||||||
// Operator delete will remove the iterated object from the list.
|
// Operator delete will remove the iterated object from the list.
|
||||||
// Eventually the list will be empty and terminate the loop.
|
// Eventually the list will be empty and terminate the loop.
|
||||||
}
|
}
|
||||||
@@ -243,8 +265,8 @@ void V3Error::incWarnings() {
|
|||||||
|
|
||||||
void V3Error::incErrors() {
|
void V3Error::incErrors() {
|
||||||
s_errCount++;
|
s_errCount++;
|
||||||
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
|
if (errorCount() == v3Global.opt.errorLimit()) { // Not >= as would otherwise recurse
|
||||||
v3fatal ("Exiting due to too many errors encountered\n");
|
v3fatal ("Exiting due to too many errors encountered; --error-limit="<<errorCount()<<endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +284,9 @@ void V3Error::abortIfWarnings() {
|
|||||||
|
|
||||||
bool V3Error::isError(V3ErrorCode code) {
|
bool V3Error::isError(V3ErrorCode code) {
|
||||||
if (code==V3ErrorCode::SUPPRESS) return false;
|
if (code==V3ErrorCode::SUPPRESS) return false;
|
||||||
|
else if (code==V3ErrorCode::INFO) return false;
|
||||||
else if (code==V3ErrorCode::FATAL) return true;
|
else if (code==V3ErrorCode::FATAL) return true;
|
||||||
|
else if (code==V3ErrorCode::FATALSRC) return true;
|
||||||
else if (code==V3ErrorCode::ERROR) return true;
|
else if (code==V3ErrorCode::ERROR) return true;
|
||||||
else if (code<V3ErrorCode::FIRST_WARN
|
else if (code<V3ErrorCode::FIRST_WARN
|
||||||
|| s_pretendError[code]) return true;
|
|| s_pretendError[code]) return true;
|
||||||
@@ -271,7 +295,9 @@ bool V3Error::isError(V3ErrorCode code) {
|
|||||||
|
|
||||||
string V3Error::msgPrefix(V3ErrorCode code) {
|
string V3Error::msgPrefix(V3ErrorCode code) {
|
||||||
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
|
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
|
||||||
|
else if (code==V3ErrorCode::INFO) return "-Info: ";
|
||||||
else if (code==V3ErrorCode::FATAL) return "%Error: ";
|
else if (code==V3ErrorCode::FATAL) return "%Error: ";
|
||||||
|
else if (code==V3ErrorCode::FATALSRC) return "%Error: Internal Error: ";
|
||||||
else if (code==V3ErrorCode::ERROR) return "%Error: ";
|
else if (code==V3ErrorCode::ERROR) return "%Error: ";
|
||||||
else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|
else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|
||||||
else return "%Warning-"+(string)code.ascii()+": ";
|
else return "%Warning-"+(string)code.ascii()+": ";
|
||||||
@@ -307,12 +333,15 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
|
|||||||
#ifdef __COVERITY__
|
#ifdef __COVERITY__
|
||||||
if (s_errorCode==V3ErrorCode::FATAL) __coverity_panic__(x);
|
if (s_errorCode==V3ErrorCode::FATAL) __coverity_panic__(x);
|
||||||
#endif
|
#endif
|
||||||
if (s_errorCode!=V3ErrorCode::SUPPRESS || debug()) {
|
if (s_errorCode!=V3ErrorCode::SUPPRESS
|
||||||
|
// On debug, show only non default-off warning to prevent pages of warnings
|
||||||
|
|| (debug() && !s_errorCode.defaultsOff())) {
|
||||||
cerr<<msgPrefix()<<sstr.str();
|
cerr<<msgPrefix()<<sstr.str();
|
||||||
if (sstr.str()[sstr.str().length()-1] != '\n') {
|
if (sstr.str()[sstr.str().length()-1] != '\n') {
|
||||||
cerr<<endl;
|
cerr<<endl;
|
||||||
}
|
}
|
||||||
if (s_errorCode!=V3ErrorCode::SUPPRESS) {
|
if (s_errorCode!=V3ErrorCode::SUPPRESS
|
||||||
|
&& s_errorCode!=V3ErrorCode::INFO) {
|
||||||
if (!s_describedEachWarn[s_errorCode]
|
if (!s_describedEachWarn[s_errorCode]
|
||||||
&& !s_pretendError[s_errorCode]) {
|
&& !s_pretendError[s_errorCode]) {
|
||||||
s_describedEachWarn[s_errorCode] = true;
|
s_describedEachWarn[s_errorCode] = true;
|
||||||
@@ -326,12 +355,27 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
|
|||||||
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If first warning is not the user's fault (internal/unsupported) then give the website
|
||||||
|
// Not later warnings, as a internal may be caused by an earlier problem
|
||||||
|
if (s_tellManual == 0) {
|
||||||
|
if (s_errorCode.mentionManual()
|
||||||
|
|| sstr.str().find("Unsupported") != string::npos) {
|
||||||
|
s_tellManual = 1;
|
||||||
|
} else {
|
||||||
|
s_tellManual = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (isError(s_errorCode)) incErrors();
|
if (isError(s_errorCode)) incErrors();
|
||||||
else incWarnings();
|
else incWarnings();
|
||||||
if (s_errorCode==V3ErrorCode::FATAL) {
|
if (s_errorCode==V3ErrorCode::FATAL
|
||||||
|
|| s_errorCode==V3ErrorCode::FATALSRC) {
|
||||||
static bool inFatal = false;
|
static bool inFatal = false;
|
||||||
if (!inFatal) {
|
if (!inFatal) {
|
||||||
inFatal = true;
|
inFatal = true;
|
||||||
|
if (s_tellManual==1) {
|
||||||
|
cerr<<msgPrefix()<<"See the manual and http://www.veripool.org/verilator for more assistance."<<endl;
|
||||||
|
s_tellManual = 2;
|
||||||
|
}
|
||||||
#ifndef _V3ERROR_NO_GLOBAL_
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
if (debug()) {
|
if (debug()) {
|
||||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
|
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
|
||||||
|
|||||||
+72
-30
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Error handling
|
// DESCRIPTION: Verilator: Error handling
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -33,26 +34,38 @@
|
|||||||
class V3ErrorCode {
|
class V3ErrorCode {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
|
MIN=0, // Keep first
|
||||||
|
//
|
||||||
SUPPRESS, // Warning suppressed by user
|
SUPPRESS, // Warning suppressed by user
|
||||||
|
INFO, // General information out
|
||||||
FATAL, // Kill the program
|
FATAL, // Kill the program
|
||||||
|
FATALSRC, // Kill the program, for internal source errors
|
||||||
ERROR, // General error out, can't suppress
|
ERROR, // General error out, can't suppress
|
||||||
|
// Boolean information we track per-line, but aren't errors
|
||||||
|
I_COVERAGE, // Coverage is on/off from /*verilator coverage_on/off*/
|
||||||
|
I_TRACING, // Tracing is on/off from /*verilator tracing_on/off*/
|
||||||
// Error codes:
|
// Error codes:
|
||||||
MULTITOP, // Error: Multiple top level modules
|
MULTITOP, // Error: Multiple top level modules
|
||||||
TASKNSVAR, // Error: Task I/O not simple
|
TASKNSVAR, // Error: Task I/O not simple
|
||||||
|
BLKLOOPINIT, // Error: Delayed assignment to array inside for loops
|
||||||
// Warning codes:
|
// Warning codes:
|
||||||
FIRST_WARN, // Just a code so the program knows where to start warnings
|
FIRST_WARN, // Just a code so the program knows where to start warnings
|
||||||
//
|
//
|
||||||
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
||||||
CASEINCOMPLETE, // Case statement has missing values
|
CASEINCOMPLETE, // Case statement has missing values
|
||||||
CASEOVERLAP, // Case statements overlap
|
CASEOVERLAP, // Case statements overlap
|
||||||
|
CASEWITHX, // Case with X values
|
||||||
CASEX, // Casex
|
CASEX, // Casex
|
||||||
CMPCONST, // Comparison is constant due to limited range
|
CMPCONST, // Comparison is constant due to limited range
|
||||||
COMBDLY, // Combinatorial delayed assignment
|
COMBDLY, // Combinatorial delayed assignment
|
||||||
STMTDLY, // Delayed statement
|
STMTDLY, // Delayed statement
|
||||||
|
SYMRSVDWORD, // Symbol is Reserved Word
|
||||||
GENCLK, // Generated Clock
|
GENCLK, // Generated Clock
|
||||||
|
IMPERFECTSCH, // Imperfect schedule (disabled by default)
|
||||||
IMPLICIT, // Implicit wire
|
IMPLICIT, // Implicit wire
|
||||||
IMPURE, // Impure function not being inlined
|
IMPURE, // Impure function not being inlined
|
||||||
MULTIDRIVEN, // Driven from multiple blocks
|
MULTIDRIVEN, // Driven from multiple blocks
|
||||||
|
REDEFMACRO, // Redefining existing define macro
|
||||||
UNDRIVEN, // No drivers
|
UNDRIVEN, // No drivers
|
||||||
UNOPT, // Unoptimizable block
|
UNOPT, // Unoptimizable block
|
||||||
UNOPTFLAT, // Unoptimizable block after flattening
|
UNOPTFLAT, // Unoptimizable block after flattening
|
||||||
@@ -60,43 +73,54 @@ public:
|
|||||||
UNUSED, // No receivers
|
UNUSED, // No receivers
|
||||||
VARHIDDEN, // Hiding variable
|
VARHIDDEN, // Hiding variable
|
||||||
WIDTH, // Width mismatch
|
WIDTH, // Width mismatch
|
||||||
|
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
|
||||||
MAX
|
MAX
|
||||||
// ***Add new elements below also***
|
// ***Add new elements below also***
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline V3ErrorCode () {};
|
inline V3ErrorCode () {}
|
||||||
inline V3ErrorCode (en _e) : m_e(_e) {};
|
inline V3ErrorCode (en _e) : m_e(_e) {}
|
||||||
V3ErrorCode (const char* msgp); // Matching code or ERROR
|
V3ErrorCode (const char* msgp); // Matching code or ERROR
|
||||||
explicit inline V3ErrorCode (int _e) : m_e(static_cast<en>(_e)) {};
|
explicit inline V3ErrorCode (int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en () const { return m_e; };
|
operator en () const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
const char* names[] = {
|
const char* names[] = {
|
||||||
// Leading spaces indicate it can't be disabled.
|
// Leading spaces indicate it can't be disabled.
|
||||||
" SUPPRESS", " FATAL", " ERROR",
|
" MIN", " SUPPRESS", " INFO", " FATAL", " FATALSRC", " ERROR",
|
||||||
"MULTITOP", "TASKNSVAR",
|
// Boolean
|
||||||
|
" I_COVERAGE", " I_TRACING",
|
||||||
|
// Errors
|
||||||
|
"MULTITOP", "TASKNSVAR", "BLKLOOPINIT",
|
||||||
|
// Warnings
|
||||||
" FIRST_WARN",
|
" FIRST_WARN",
|
||||||
"BLKANDNBLK",
|
"BLKANDNBLK",
|
||||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
|
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CMPCONST",
|
||||||
"COMBDLY", "STMTDLY", "GENCLK", "IMPLICIT", "IMPURE",
|
"COMBDLY", "STMTDLY", "SYMRSVDWORD", "GENCLK", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
|
||||||
"MULTIDRIVEN",
|
"MULTIDRIVEN", "REDEFMACRO",
|
||||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||||
"VARHIDDEN", "WIDTH",
|
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
||||||
" MAX"
|
" MAX"
|
||||||
};
|
};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
}
|
||||||
|
// Warnings that default to off
|
||||||
|
bool defaultsOff() const { return ( m_e==IMPERFECTSCH ); }
|
||||||
// Warnings that warn about nasty side effects
|
// Warnings that warn about nasty side effects
|
||||||
bool dangerous() const { return ( m_e==COMBDLY );};
|
bool dangerous() const { return ( m_e==COMBDLY ); }
|
||||||
// Warnings we'll present to the user as errors
|
// Warnings we'll present to the user as errors
|
||||||
// Later -Werror- options may make more of these.
|
// Later -Werror- options may make more of these.
|
||||||
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE); };
|
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE || m_e==SYMRSVDWORD); }
|
||||||
|
// Warnings to mention manual
|
||||||
|
bool mentionManual() const { return ( m_e==FATALSRC || pretendError() ); }
|
||||||
|
|
||||||
// Warnings that are lint only
|
// Warnings that are lint only
|
||||||
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|
||||||
|| m_e==CASEX || m_e==CMPCONST
|
|| m_e==CASEWITHX || m_e==CASEX
|
||||||
|
|| m_e==CMPCONST
|
||||||
|| m_e==IMPLICIT
|
|| m_e==IMPLICIT
|
||||||
|| m_e==UNDRIVEN || m_e==UNSIGNED
|
|| m_e==UNDRIVEN || m_e==UNSIGNED
|
||||||
|| m_e==UNUSED || m_e==VARHIDDEN
|
|| m_e==UNUSED || m_e==VARHIDDEN
|
||||||
|| m_e==WIDTH); };
|
|| m_e==WIDTH); }
|
||||||
};
|
};
|
||||||
inline bool operator== (V3ErrorCode lhs, V3ErrorCode rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (V3ErrorCode lhs, V3ErrorCode rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (V3ErrorCode lhs, V3ErrorCode::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (V3ErrorCode lhs, V3ErrorCode::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -114,6 +138,7 @@ class V3Error {
|
|||||||
static int s_debugDefault; // Default debugging level
|
static int s_debugDefault; // Default debugging level
|
||||||
static int s_errCount; // Error count
|
static int s_errCount; // Error count
|
||||||
static int s_warnCount; // Error count
|
static int s_warnCount; // Error count
|
||||||
|
static int s_tellManual; // Tell user to see manual, 0=not yet, 1=doit, 2=disable
|
||||||
static ostringstream s_errorStr; // Error string being formed
|
static ostringstream s_errorStr; // Error string being formed
|
||||||
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
||||||
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
||||||
@@ -157,11 +182,12 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
|||||||
|
|
||||||
// These allow errors using << operators: v3error("foo"<<"bar");
|
// These allow errors using << operators: v3error("foo"<<"bar");
|
||||||
// Careful, you can't put () around msg, as you would in most macro definitions
|
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||||
#define v3fatal(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::FATAL)<<msg),V3Error::v3errorStr()));
|
|
||||||
#define v3error(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::ERROR)<<msg),V3Error::v3errorStr()));
|
|
||||||
#define v3warn(code,msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::code)<<msg),V3Error::v3errorStr()));
|
#define v3warn(code,msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::code)<<msg),V3Error::v3errorStr()));
|
||||||
|
#define v3info(msg) v3warn(INFO,msg)
|
||||||
|
#define v3fatal(msg) v3warn(FATAL,msg)
|
||||||
|
#define v3error(msg) v3warn(ERROR,msg)
|
||||||
// Use this instead of fatal() to mention the source code line.
|
// Use this instead of fatal() to mention the source code line.
|
||||||
#define v3fatalSrc(msg) v3fatal("Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<": "<<msg)
|
#define v3fatalSrc(msg) v3warn(FATALSRC,__FILE__<<":"<<dec<<__LINE__<<": "<<msg)
|
||||||
|
|
||||||
#define UINFO(level,stmsg) {if(debug()>=(level)) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
|
#define UINFO(level,stmsg) {if(debug()>=(level)) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
|
||||||
#define UINFONL(level,stmsg) {if(debug()>=(level)) { cout<<stmsg; } }
|
#define UINFONL(level,stmsg) {if(debug()>=(level)) { cout<<stmsg; } }
|
||||||
@@ -169,7 +195,7 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
|||||||
#define UDEBUGONLY(stmts) {stmts}
|
#define UDEBUGONLY(stmts) {stmts}
|
||||||
#define UASSERT(condition,stmsg) { if (!(condition)) { v3fatalSrc(stmsg); }}
|
#define UASSERT(condition,stmsg) { if (!(condition)) { v3fatalSrc(stmsg); }}
|
||||||
// For use in V3Ast static functions only
|
// For use in V3Ast static functions only
|
||||||
#define UASSERT_STATIC(condition,stmsg) { if (!(condition)) { cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<(stmsg)<<endl; abort(); } }
|
#define UASSERT_STATIC(condition,stmsg) { if (!(condition)) { cerr<<"Internal Error: "<<__FILE__<<":"<<dec<<__LINE__<<":"<<(stmsg)<<endl; abort(); } }
|
||||||
|
|
||||||
#define V3ERROR_NA v3error("Internal: Unexpected Call")
|
#define V3ERROR_NA v3error("Internal: Unexpected Call")
|
||||||
|
|
||||||
@@ -179,13 +205,21 @@ template< class T> std::string cvtToStr (const T& t) {
|
|||||||
ostringstream os; os<<t; return os.str();
|
ostringstream os; os<<t; return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline uint32_t cvtToHash(void* vp) {
|
||||||
|
// We can shove a 64 bit pointer into a 32 bit bucket
|
||||||
|
// On 32 bit systems, lower is always 0, but who cares?
|
||||||
|
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
|
||||||
|
u.l.upper=0; u.l.lower=0; u.up=vp;
|
||||||
|
return u.l.upper^u.l.lower;
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
class FileLine {
|
class FileLine {
|
||||||
// File and line number of an object, mostly for error reporting
|
// File and line number of an object, mostly for error reporting
|
||||||
int m_lineno;
|
int m_lineno;
|
||||||
string m_filename;
|
string m_filename;
|
||||||
bitset<V3ErrorCode::MAX> m_warnOff;
|
bitset<V3ErrorCode::MAX> m_warnOn;
|
||||||
static FileLine s_defaultFileLine;
|
static FileLine s_defaultFileLine;
|
||||||
struct EmptySecret {};
|
struct EmptySecret {};
|
||||||
protected:
|
protected:
|
||||||
@@ -199,9 +233,9 @@ protected:
|
|||||||
void incLineno() { m_lineno++; }
|
void incLineno() { m_lineno++; }
|
||||||
FileLine* copyOrSameFileLine();
|
FileLine* copyOrSameFileLine();
|
||||||
public:
|
public:
|
||||||
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff; }
|
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOn=s_defaultFileLine.m_warnOn; }
|
||||||
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff; }
|
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOn=fromp->m_warnOn; }
|
||||||
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; }
|
FileLine (EmptySecret);
|
||||||
~FileLine() { }
|
~FileLine() { }
|
||||||
#ifdef VL_LEAK_CHECKS
|
#ifdef VL_LEAK_CHECKS
|
||||||
static void* operator new(size_t size);
|
static void* operator new(size_t size);
|
||||||
@@ -214,13 +248,21 @@ public:
|
|||||||
const string filebasename () const;
|
const string filebasename () const;
|
||||||
const char* cfilename () const { return m_filename.c_str(); }
|
const char* cfilename () const { return m_filename.c_str(); }
|
||||||
const string profileFuncname() const;
|
const string profileFuncname() const;
|
||||||
void warnOff(V3ErrorCode code, bool flag) { m_warnOff.set(code,flag); } // Turn on/off warning messages on this line.
|
void warnOff(V3ErrorCode code, bool flag) { m_warnOn.set(code,!flag); } // Turn on/off warning messages on this line.
|
||||||
bool warnOff(const string& code, bool flag); // Returns 1 if ok
|
bool warnOff(const string& code, bool flag); // Returns 1 if ok
|
||||||
bool warnIsOff(V3ErrorCode code);
|
bool warnIsOff(V3ErrorCode code) const;
|
||||||
void warnLintOff(bool flag);
|
void warnLintOff(bool flag);
|
||||||
void warnStateFrom(const FileLine& from) { m_warnOff=from.m_warnOff; }
|
void warnStateFrom(const FileLine& from) { m_warnOn=from.m_warnOn; }
|
||||||
|
void warnStateInherit(const FileLine& from);
|
||||||
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
|
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
|
||||||
|
|
||||||
|
// Boolean ACCESSORS/METHODS
|
||||||
|
bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); }
|
||||||
|
void coverageOn(bool flag) { m_warnOn.set(V3ErrorCode::I_COVERAGE,flag); }
|
||||||
|
bool tracingOn() const { return m_warnOn.test(V3ErrorCode::I_TRACING); }
|
||||||
|
void tracingOn(bool flag) { m_warnOn.set(V3ErrorCode::I_TRACING,flag); }
|
||||||
|
|
||||||
|
// METHODS
|
||||||
void v3errorEnd(ostringstream& str);
|
void v3errorEnd(ostringstream& str);
|
||||||
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
|
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
|
||||||
|
|
||||||
|
|||||||
+32
-29
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for expand nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for expand nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Expand's Transformations:
|
// V3Expand's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Expand verilated.h macros into internal micro optimizations (RTL)
|
// Expand verilated.h macros into internal micro optimizations (RTL)
|
||||||
// this will enable later optimizations.
|
// this will enable later optimizations.
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -51,9 +51,13 @@ private:
|
|||||||
// STATE
|
// STATE
|
||||||
AstNode* m_stmtp; // Current statement
|
AstNode* m_stmtp; // Current statement
|
||||||
|
|
||||||
//int debug() { return 9; }
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
int longOrQuadWidth (AstNode* nodep) {
|
int longOrQuadWidth (AstNode* nodep) {
|
||||||
// Return 32 or 64...
|
// Return 32 or 64...
|
||||||
return (nodep->width()+(VL_WORDSIZE-1)) & ~(VL_WORDSIZE-1);
|
return (nodep->width()+(VL_WORDSIZE-1)) & ~(VL_WORDSIZE-1);
|
||||||
@@ -168,12 +172,12 @@ private:
|
|||||||
}
|
}
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* newSelBitWord(AstNode* lsbp, int wordAdder) {
|
AstNode* newSelBitWord(AstNode* lsbp, int wordAdder) {
|
||||||
// Return equation to get the VL_BITWORD of a constant or non-constant
|
// Return equation to get the VL_BITWORD of a constant or non-constant
|
||||||
if (lsbp->castConst()) {
|
if (lsbp->castConst()) {
|
||||||
return new AstConst (lsbp->fileline(),
|
return new AstConst (lsbp->fileline(),
|
||||||
wordAdder + VL_BITWORD_I(lsbp->castConst()->asInt()));
|
wordAdder + VL_BITWORD_I(lsbp->castConst()->toUInt()));
|
||||||
} else {
|
} else {
|
||||||
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
|
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
|
||||||
lsbp->cloneTree(true),
|
lsbp->cloneTree(true),
|
||||||
@@ -204,7 +208,7 @@ private:
|
|||||||
// Return equation to get the VL_BITBIT of a constant or non-constant
|
// Return equation to get the VL_BITBIT of a constant or non-constant
|
||||||
if (lsbp->castConst()) {
|
if (lsbp->castConst()) {
|
||||||
return new AstConst (lsbp->fileline(),
|
return new AstConst (lsbp->fileline(),
|
||||||
VL_BITBIT_I(lsbp->castConst()->asInt()));
|
VL_BITBIT_I(lsbp->castConst()->toUInt()));
|
||||||
} else {
|
} else {
|
||||||
return new AstAnd (lsbp->fileline(),
|
return new AstAnd (lsbp->fileline(),
|
||||||
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
|
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
|
||||||
@@ -355,7 +359,7 @@ private:
|
|||||||
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
|
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
|
||||||
nodep->fromp()->cloneTree(true),
|
nodep->fromp()->cloneTree(true),
|
||||||
newSelBitWord(nodep->lsbp(), 0));
|
newSelBitWord(nodep->lsbp(), 0));
|
||||||
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCast(nodep->fileline(), lowwordp, nodep);
|
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCast(nodep->fileline(), lowwordp, nodep);
|
||||||
AstNode* lowp = new AstShiftR (nodep->fileline(),
|
AstNode* lowp = new AstShiftR (nodep->fileline(),
|
||||||
lowwordp,
|
lowwordp,
|
||||||
newSelBitBit(nodep->lsbp()),
|
newSelBitBit(nodep->lsbp()),
|
||||||
@@ -368,7 +372,7 @@ private:
|
|||||||
new AstWordSel (nodep->fromp()->fileline(),
|
new AstWordSel (nodep->fromp()->fileline(),
|
||||||
nodep->fromp()->cloneTree(true),
|
nodep->fromp()->cloneTree(true),
|
||||||
newSelBitWord(nodep->lsbp(), 1));
|
newSelBitWord(nodep->lsbp(), 1));
|
||||||
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCast(nodep->fileline(), midwordp, nodep);
|
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCast(nodep->fileline(), midwordp, nodep);
|
||||||
// If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits
|
// If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits
|
||||||
// else we need to form the lower word, so we << by 31 or less
|
// else we need to form the lower word, so we << by 31 or less
|
||||||
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
|
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
|
||||||
@@ -406,7 +410,7 @@ private:
|
|||||||
new AstWordSel (nodep->fromp()->fileline(),
|
new AstWordSel (nodep->fromp()->fileline(),
|
||||||
nodep->fromp()->cloneTree(true),
|
nodep->fromp()->cloneTree(true),
|
||||||
newSelBitWord(nodep->lsbp(), 2));
|
newSelBitWord(nodep->lsbp(), 2));
|
||||||
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCast(nodep->fileline(), hiwordp, nodep);
|
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCast(nodep->fileline(), hiwordp, nodep);
|
||||||
AstNode* himayp =
|
AstNode* himayp =
|
||||||
new AstShiftL (nodep->fileline(),
|
new AstShiftL (nodep->fileline(),
|
||||||
hiwordp,
|
hiwordp,
|
||||||
@@ -434,7 +438,7 @@ private:
|
|||||||
UINFO(8," SEL->SHIFT "<<nodep<<endl);
|
UINFO(8," SEL->SHIFT "<<nodep<<endl);
|
||||||
AstNode* fromp = nodep->fromp()->unlinkFrBack();
|
AstNode* fromp = nodep->fromp()->unlinkFrBack();
|
||||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||||
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCast(nodep->fileline(), fromp, nodep);
|
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCast(nodep->fileline(), fromp, nodep);
|
||||||
AstNode* newp = new AstShiftR (nodep->fileline(),
|
AstNode* newp = new AstShiftR (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
dropCondBound(lsbp),
|
dropCondBound(lsbp),
|
||||||
@@ -504,7 +508,7 @@ private:
|
|||||||
bool destwide = lhsp->fromp()->isWide();
|
bool destwide = lhsp->fromp()->isWide();
|
||||||
bool ones = nodep->rhsp()->isAllOnesV();
|
bool ones = nodep->rhsp()->isAllOnesV();
|
||||||
if (lhsp->lsbp()->castConst()) {
|
if (lhsp->lsbp()->castConst()) {
|
||||||
// The code should work without this constant test, but it won't
|
// The code should work without this constant test, but it won't
|
||||||
// constify as nicely as we'd like.
|
// constify as nicely as we'd like.
|
||||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||||
AstNode* destp = lhsp->fromp()->unlinkFrBack();
|
AstNode* destp = lhsp->fromp()->unlinkFrBack();
|
||||||
@@ -592,7 +596,7 @@ private:
|
|||||||
// For wide destp, we can either form a equation for every destination word,
|
// For wide destp, we can either form a equation for every destination word,
|
||||||
// with the appropriate long equation of if it's being written or not.
|
// with the appropriate long equation of if it's being written or not.
|
||||||
// Or, we can use a LHS variable arraysel with non-constant index to set the vector.
|
// Or, we can use a LHS variable arraysel with non-constant index to set the vector.
|
||||||
// Doing the variable arraysel is better for globals and large arrays,
|
// Doing the variable arraysel is better for globals and large arrays,
|
||||||
// doing every word is better for temporaries and if we're setting most words
|
// doing every word is better for temporaries and if we're setting most words
|
||||||
// since it may result in better substitution optimizations later.
|
// since it may result in better substitution optimizations later.
|
||||||
// This results in so much code, we're better off leaving a function call.
|
// This results in so much code, we're better off leaving a function call.
|
||||||
@@ -630,7 +634,7 @@ private:
|
|||||||
//newp->dumpTree(cout,"- new: ");
|
//newp->dumpTree(cout,"- new: ");
|
||||||
insertBefore(nodep,newp);
|
insertBefore(nodep,newp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,10 +645,10 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
UINFO(8," CONCAT "<<nodep<<endl);
|
UINFO(8," CONCAT "<<nodep<<endl);
|
||||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||||
int rhsshift = rhsp->widthMin();
|
int rhsshift = rhsp->widthMin();
|
||||||
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
||||||
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
||||||
AstNode* newp = new AstOr (nodep->fileline(),
|
AstNode* newp = new AstOr (nodep->fileline(),
|
||||||
new AstShiftL (nodep->fileline(),
|
new AstShiftL (nodep->fileline(),
|
||||||
lhsp,
|
lhsp,
|
||||||
@@ -657,7 +661,7 @@ private:
|
|||||||
}
|
}
|
||||||
bool expandWide (AstNodeAssign* nodep, AstConcat* rhsp) {
|
bool expandWide (AstNodeAssign* nodep, AstConcat* rhsp) {
|
||||||
UINFO(8," Wordize ASSIGN(CONCAT) "<<nodep<<endl);
|
UINFO(8," Wordize ASSIGN(CONCAT) "<<nodep<<endl);
|
||||||
// Lhs or Rhs may be word, long, or quad.
|
// Lhs or Rhs may be word, long, or quad.
|
||||||
// newAstWordSelClone nicely abstracts the difference.
|
// newAstWordSelClone nicely abstracts the difference.
|
||||||
int rhsshift = rhsp->rhsp()->widthMin();
|
int rhsshift = rhsp->rhsp()->widthMin();
|
||||||
// Sometimes doing the words backwards is preferrable.
|
// Sometimes doing the words backwards is preferrable.
|
||||||
@@ -670,7 +674,7 @@ private:
|
|||||||
rhsp->lhsp(), rhsshift),
|
rhsp->lhsp(), rhsshift),
|
||||||
newAstWordSelClone (rhsp->rhsp(), w)));
|
newAstWordSelClone (rhsp->rhsp(), w)));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||||
@@ -689,8 +693,8 @@ private:
|
|||||||
UINFO(8," REPLICATE "<<nodep<<endl);
|
UINFO(8," REPLICATE "<<nodep<<endl);
|
||||||
AstConst* constp = nodep->rhsp()->castConst();
|
AstConst* constp = nodep->rhsp()->castConst();
|
||||||
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
||||||
uint32_t times = constp->asInt();
|
uint32_t times = constp->toUInt();
|
||||||
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
||||||
newp = lhsp->cloneTree(true);
|
newp = lhsp->cloneTree(true);
|
||||||
for (unsigned repnum=1; repnum<times; repnum++) {
|
for (unsigned repnum=1; repnum<times; repnum++) {
|
||||||
int rhsshift = repnum*lhswidth;
|
int rhsshift = repnum*lhswidth;
|
||||||
@@ -714,7 +718,7 @@ private:
|
|||||||
int lhswidth = lhsp->widthMin();
|
int lhswidth = lhsp->widthMin();
|
||||||
AstConst* constp = rhsp->rhsp()->castConst();
|
AstConst* constp = rhsp->rhsp()->castConst();
|
||||||
if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
||||||
uint32_t times = constp->asInt();
|
uint32_t times = constp->toUInt();
|
||||||
for (int w=0; w<rhsp->widthWords(); w++) {
|
for (int w=0; w<rhsp->widthWords(); w++) {
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
if (lhswidth==1) {
|
if (lhswidth==1) {
|
||||||
@@ -731,7 +735,7 @@ private:
|
|||||||
}
|
}
|
||||||
addWordAssign(nodep, w, newp);
|
addWordAssign(nodep, w, newp);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstChangeXor* nodep, AstNUser*) {
|
virtual void visit(AstChangeXor* nodep, AstNUser*) {
|
||||||
@@ -906,7 +910,6 @@ public:
|
|||||||
}
|
}
|
||||||
virtual ~ExpandVisitor() {}
|
virtual ~ExpandVisitor() {}
|
||||||
void main(AstNode* nodep) {
|
void main(AstNode* nodep) {
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Expansion of wide operator macros to C operators
|
// DESCRIPTION: Verilator: Expansion of wide operator macros to C operators
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
+35
-8
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -21,8 +21,9 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -61,7 +62,7 @@ class V3FileDependImp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool operator<(const DependFile& rhs) const { return filename()<rhs.filename(); };
|
bool operator<(const DependFile& rhs) const { return filename()<rhs.filename(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
@@ -232,12 +233,21 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
|
|||||||
return dependImp.checkTimes(filename, cmdline);
|
return dependImp.checkTimes(filename, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3File::createMakeDir() {
|
||||||
|
static bool created = false;
|
||||||
|
if (!created) {
|
||||||
|
created = true;
|
||||||
|
mkdir(v3Global.opt.makeDir().c_str(), 0777);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
||||||
|
|
||||||
V3OutFile::V3OutFile(const string& filename)
|
V3OutFile::V3OutFile(const string& filename)
|
||||||
: m_lineno(1), m_column(0), m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
: m_filename(filename), m_lineno(1), m_column(0)
|
||||||
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
||||||
|
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
||||||
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
|
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
|
||||||
v3fatal("Cannot write "<<filename);
|
v3fatal("Cannot write "<<filename);
|
||||||
}
|
}
|
||||||
@@ -421,6 +431,23 @@ void V3OutFile::putBreak () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3OutFile::putsQuoted(const char* strg) {
|
||||||
|
// Quote \ and " for use inside C programs
|
||||||
|
// Don't use to quote a filename for #include - #include doesn't \ escape.
|
||||||
|
putcNoTracking('"');
|
||||||
|
for (const char* cp=strg; *cp; cp++) {
|
||||||
|
if (*cp == '\\') {
|
||||||
|
putcNoTracking('\\');
|
||||||
|
putcNoTracking('\\');
|
||||||
|
} else if (*cp == '"') {
|
||||||
|
putcNoTracking('\\');
|
||||||
|
putcNoTracking('"');
|
||||||
|
} else {
|
||||||
|
putcNoTracking (*cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putcNoTracking('"');
|
||||||
|
}
|
||||||
void V3OutFile::putsNoTracking (const char *strg) {
|
void V3OutFile::putsNoTracking (const char *strg) {
|
||||||
// Don't track {}'s, probably because it's a $display format string
|
// Don't track {}'s, probably because it's a $display format string
|
||||||
for (const char* cp=strg; *cp; cp++) {
|
for (const char* cp=strg; *cp; cp++) {
|
||||||
|
|||||||
+19
-8
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -46,6 +47,7 @@ public:
|
|||||||
return new_ofstream_nodepend (filename, append);
|
return new_ofstream_nodepend (filename, append);
|
||||||
}
|
}
|
||||||
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
|
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
|
||||||
|
if (filename != "/dev/null") createMakeDir();
|
||||||
if (append) {
|
if (append) {
|
||||||
return new ofstream(filename.c_str(), ios::app);
|
return new ofstream(filename.c_str(), ios::app);
|
||||||
} else {
|
} else {
|
||||||
@@ -53,15 +55,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static FILE* new_fopen_w(const string& filename) {
|
static FILE* new_fopen_w(const string& filename) {
|
||||||
|
if (filename != "/dev/null") createMakeDir();
|
||||||
addTgtDepend(filename);
|
addTgtDepend(filename);
|
||||||
return fopen(filename.c_str(),"w");
|
return fopen(filename.c_str(),"w");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
static void addSrcDepend(const string& filename);
|
static void addSrcDepend(const string& filename);
|
||||||
static void addTgtDepend(const string& filename);
|
static void addTgtDepend(const string& filename);
|
||||||
static void writeDepend(const string& filename);
|
static void writeDepend(const string& filename);
|
||||||
static void writeTimes(const string& filename, const string& cmdline);
|
static void writeTimes(const string& filename, const string& cmdline);
|
||||||
static bool checkTimes(const string& filename, const string& cmdline);
|
static bool checkTimes(const string& filename, const string& cmdline);
|
||||||
|
|
||||||
|
// Directory utilities
|
||||||
|
static void createMakeDir();
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@@ -81,6 +88,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
FILE* m_fp;
|
FILE* m_fp;
|
||||||
|
string m_filename;
|
||||||
int m_lineno;
|
int m_lineno;
|
||||||
int m_column;
|
int m_column;
|
||||||
int m_nobreak; // Basic operator or begin paren, don't break next
|
int m_nobreak; // Basic operator or begin paren, don't break next
|
||||||
@@ -105,6 +113,8 @@ public:
|
|||||||
void puts(const string& strg) { puts(strg.c_str()); }
|
void puts(const string& strg) { puts(strg.c_str()); }
|
||||||
void putsNoTracking(const char* strg);
|
void putsNoTracking(const char* strg);
|
||||||
void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); }
|
void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); }
|
||||||
|
void putsQuoted(const char* strg);
|
||||||
|
void putsQuoted(const string& strg) { putsQuoted(strg.c_str()); }
|
||||||
void putBreak(); // Print linebreak if line is too wide
|
void putBreak(); // Print linebreak if line is too wide
|
||||||
void putBreakExpr(); // Print linebreak in expression if line is too wide
|
void putBreakExpr(); // Print linebreak in expression if line is too wide
|
||||||
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment
|
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment
|
||||||
@@ -113,9 +123,10 @@ public:
|
|||||||
bool exceededWidth() const { return m_column > WIDTH; }
|
bool exceededWidth() const { return m_column > WIDTH; }
|
||||||
bool tokenStart(const char* cp, const char* cmp);
|
bool tokenStart(const char* cp, const char* cmp);
|
||||||
bool tokenEnd(const char* cp);
|
bool tokenEnd(const char* cp);
|
||||||
void indentInc() { m_indentLevel += INDBLK; };
|
void indentInc() { m_indentLevel += INDBLK; }
|
||||||
void indentDec() { m_indentLevel -= INDBLK;
|
void indentDec() {
|
||||||
UASSERT(m_indentLevel>=0,"Underflow of indentation\n");
|
m_indentLevel -= INDBLK;
|
||||||
|
UASSERT(m_indentLevel>=0, ": "<<m_filename<<": Underflow of indentation\n");
|
||||||
}
|
}
|
||||||
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
|
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
|
||||||
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
|
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
|
||||||
|
|||||||
+38
-20
@@ -1,16 +1,16 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Gate optimizations, such as wire elimination
|
// DESCRIPTION: Verilator: Gate optimizations, such as wire elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Gate's Transformations:
|
// V3Gate's Transformations:
|
||||||
//
|
//
|
||||||
// Extract a graph of the *entire* netlist with cells expanded
|
// Extract a graph of the *entire* netlist with cells expanded
|
||||||
// Perform constant optimization across the graph
|
// Perform constant optimization across the graph
|
||||||
// Create VARSCOPEs for any variables we can rip out
|
// Create VARSCOPEs for any variables we can rip out
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -49,7 +49,11 @@ typedef list<AstNodeVarRef*> GateVarRefList;
|
|||||||
|
|
||||||
class GateBaseVisitor : public AstNVisitor {
|
class GateBaseVisitor : public AstNVisitor {
|
||||||
public:
|
public:
|
||||||
//int debug() { return 9; }
|
static int debug() {
|
||||||
|
static int level = -1;
|
||||||
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -170,7 +174,7 @@ private:
|
|||||||
// V3Const cleans up any NOTs by flipping the edges for us
|
// V3Const cleans up any NOTs by flipping the edges for us
|
||||||
if (m_buffersOnly
|
if (m_buffersOnly
|
||||||
&& !(nodep->rhsp()->castVarRef()
|
&& !(nodep->rhsp()->castVarRef()
|
||||||
// Until NEW_ORDERING, avoid making non-clocked logic into clocked,
|
// Until NEW_ORDERING, avoid making non-clocked logic into clocked,
|
||||||
// as it slows down the verilator_sim_benchmark
|
// as it slows down the verilator_sim_benchmark
|
||||||
|| (nodep->rhsp()->castNot()
|
|| (nodep->rhsp()->castNot()
|
||||||
&& nodep->rhsp()->castNot()->lhsp()->castVarRef()
|
&& nodep->rhsp()->castNot()->lhsp()->castVarRef()
|
||||||
@@ -230,8 +234,9 @@ class GateVisitor : public GateBaseVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
//Entire netlist:
|
//Entire netlist:
|
||||||
// AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet
|
// AstVarScope::user1p -> GateVarVertex* for usage var, 0=not set yet
|
||||||
// {statement}Node::userp -> GateLogicVertex* for this statement
|
// {statement}Node::user1p -> GateLogicVertex* for this statement
|
||||||
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||||
@@ -263,11 +268,11 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
GateVarVertex* makeVarVertex(AstVarScope* varscp) {
|
GateVarVertex* makeVarVertex(AstVarScope* varscp) {
|
||||||
GateVarVertex* vertexp = (GateVarVertex*)(varscp->userp());
|
GateVarVertex* vertexp = (GateVarVertex*)(varscp->user1p());
|
||||||
if (!vertexp) {
|
if (!vertexp) {
|
||||||
UINFO(6,"New vertex "<<varscp<<endl);
|
UINFO(6,"New vertex "<<varscp<<endl);
|
||||||
vertexp = new GateVarVertex(&m_graph, m_scopep, varscp);
|
vertexp = new GateVarVertex(&m_graph, m_scopep, varscp);
|
||||||
varscp->userp(vertexp);
|
varscp->user1p(vertexp);
|
||||||
if (varscp->varp()->isSigPublic()) {
|
if (varscp->varp()->isSigPublic()) {
|
||||||
// Public signals shouldn't be changed, pli code might be messing with them
|
// Public signals shouldn't be changed, pli code might be messing with them
|
||||||
vertexp->clearReducible("SigPublic");
|
vertexp->clearReducible("SigPublic");
|
||||||
@@ -294,8 +299,6 @@ private:
|
|||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
//VV***** We reset userp() and user2p
|
|
||||||
AstNode::userClearTree();
|
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
//if (debug()>6) m_graph.dump();
|
//if (debug()>6) m_graph.dump();
|
||||||
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
|
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
|
||||||
@@ -317,6 +320,7 @@ private:
|
|||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_activeReducible = true;
|
m_activeReducible = true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
UINFO(4," SCOPE "<<nodep<<endl);
|
UINFO(4," SCOPE "<<nodep<<endl);
|
||||||
@@ -343,7 +347,7 @@ private:
|
|||||||
UINFO(5," VARREF to "<<varscp<<endl);
|
UINFO(5," VARREF to "<<varscp<<endl);
|
||||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||||
// the weight will increase
|
// the weight will increase
|
||||||
if (nodep->lvalue()) {
|
if (nodep->lvalue()) {
|
||||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||||
} else {
|
} else {
|
||||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||||
@@ -357,10 +361,21 @@ private:
|
|||||||
iterateNewStmt(nodep, "User C Function", "User C Function");
|
iterateNewStmt(nodep, "User C Function", "User C Function");
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||||
|
// Note we look at only AstSenItems, not AstSenGate's
|
||||||
|
// The gating term of a AstSenGate is normal logic
|
||||||
m_inSenItem = true;
|
m_inSenItem = true;
|
||||||
iterateNewStmt(nodep, NULL, NULL);
|
if (m_logicVertexp) { // Already under logic; presumably a SenGate
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
} else { // Standalone item, probably right under a SenTree
|
||||||
|
iterateNewStmt(nodep, NULL, NULL);
|
||||||
|
}
|
||||||
m_inSenItem = false;
|
m_inSenItem = false;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
||||||
|
// First handle the clock part will be handled in a minute by visit AstSenItem
|
||||||
|
// The logic gating term is delt with as logic
|
||||||
|
iterateNewStmt(nodep, "Clock gater", "Clock gater");
|
||||||
|
}
|
||||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||||
bool lastslow = m_inSlow;
|
bool lastslow = m_inSlow;
|
||||||
m_inSlow = true;
|
m_inSlow = true;
|
||||||
@@ -373,6 +388,9 @@ private:
|
|||||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||||
iterateNewStmt(nodep, NULL, NULL);
|
iterateNewStmt(nodep, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
||||||
|
iterateNewStmt(nodep, "CoverToggle", "CoverToggle");
|
||||||
|
}
|
||||||
virtual void visit(AstTraceInc* nodep, AstNUser*) {
|
virtual void visit(AstTraceInc* nodep, AstNUser*) {
|
||||||
bool lastslow = m_inSlow;
|
bool lastslow = m_inSlow;
|
||||||
m_inSlow = true;
|
m_inSlow = true;
|
||||||
@@ -421,7 +439,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
|||||||
if (!vvertexp->isTop() // Ok if top inputs are driverless
|
if (!vvertexp->isTop() // Ok if top inputs are driverless
|
||||||
&& !vvertexp->varScp()->varp()->initp()
|
&& !vvertexp->varScp()->varp()->initp()
|
||||||
&& !vvertexp->varScp()->varp()->isSigPublic()) {
|
&& !vvertexp->varScp()->varp()->isSigPublic()) {
|
||||||
UINFO(1, "No drivers "<<vvertexp->varScp()<<endl);
|
UINFO(4, "No drivers "<<vvertexp->varScp()<<endl);
|
||||||
if (0) {
|
if (0) {
|
||||||
// If we warned here after constant propagation, what the user considered
|
// If we warned here after constant propagation, what the user considered
|
||||||
// reasonable logic may have disappeared. Issuing a warning would
|
// reasonable logic may have disappeared. Issuing a warning would
|
||||||
@@ -490,7 +508,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
|||||||
if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
|
if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
|
||||||
m_statSigs++;
|
m_statSigs++;
|
||||||
while (V3GraphEdge* edgep = vvertexp->outBeginp()) {
|
while (V3GraphEdge* edgep = vvertexp->outBeginp()) {
|
||||||
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
|
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
|
||||||
AstNode* consumerp = consumeVertexp->nodep();
|
AstNode* consumerp = consumeVertexp->nodep();
|
||||||
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
|
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
|
||||||
// If the new replacement referred to a signal,
|
// If the new replacement referred to a signal,
|
||||||
@@ -565,7 +583,7 @@ void GateVisitor::replaceAssigns() {
|
|||||||
//if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<<endl;}
|
//if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<<endl;}
|
||||||
if (!vscp->valuep()->castNodeMath()
|
if (!vscp->valuep()->castNodeMath()
|
||||||
|| vscp->valuep()->nextp()) {
|
|| vscp->valuep()->nextp()) {
|
||||||
vscp->dumpTree(cout, "vscStrange: ");
|
vscp->dumpTree(cerr, "vscStrange: ");
|
||||||
vscp->v3fatalSrc("Value of varscope not mathematical\n");
|
vscp->v3fatalSrc("Value of varscope not mathematical\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,16 +1,17 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// 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,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user