mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
793c974480 | ||
|
|
78a321925f | ||
|
|
643572595e | ||
|
|
fb4d462325 | ||
|
|
c0df07c86f | ||
|
|
e918d945f2 | ||
|
|
0ee5743853 | ||
|
|
486d69da5f | ||
|
|
005b4b7609 | ||
|
|
a0fd065dcf | ||
|
|
751384cb5c | ||
|
|
6ac672b4a3 | ||
|
|
a89502be9f | ||
|
|
04e7b3bd4d |
@@ -3,6 +3,23 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.872 2015-04-05
|
||||
|
||||
*** Add VerilatedVcdFile to allow real-time waveforms, bug890. [HyungKi Jeong]
|
||||
|
||||
*** Add --clk and related optimizations, msg1533. [Jie Xu]
|
||||
|
||||
*** Fix order of C style arrays. [Duraid Madina]
|
||||
|
||||
**** Add --dump-treei-<srcfile>, bug894. [Jie Xu]
|
||||
|
||||
**** Fix comma-instantiations with parameters, bug884. [Franck Jullien]
|
||||
|
||||
**** Fix SystemC arrayed bit vectors, bug886. [David Poole]
|
||||
|
||||
**** Fix compile error on MinGW, bug887. [HyungKi Jeong]
|
||||
|
||||
|
||||
* Verilator 3.870 2015-02-12
|
||||
|
||||
**** Suppress COMBDLY when inside always_latch, bug864. [Iztok Jeras]
|
||||
|
||||
+4
-6
@@ -3,8 +3,6 @@
|
||||
#
|
||||
# This file is part of Verilator.
|
||||
#
|
||||
# Author: Wilson Snyder <[email protected]>
|
||||
#
|
||||
# Code available from: http://www.veripool.org/verilator
|
||||
#
|
||||
#*****************************************************************************
|
||||
@@ -230,16 +228,16 @@ verilator.pdf: ${srcdir}/bin/verilator Makefile
|
||||
pdflatex verilator.tex
|
||||
-rm -f verilator.toc verilator.aux verilator.idx verilator.out
|
||||
|
||||
README: readme.pod
|
||||
README: README.pod
|
||||
-rm -f $@
|
||||
$(POD2TEXT) --loose $< > $@
|
||||
|
||||
README.html: readme.pod
|
||||
README.html: README.pod
|
||||
pod2html $< >$@
|
||||
|
||||
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||
README.pdf: readme.pod Makefile
|
||||
pod2latex --full --out README.tex readme.pod
|
||||
README.pdf: README.pod Makefile
|
||||
pod2latex --full --out README.tex README.pod
|
||||
$(PERL) $(POD2LATEXFIX) "$(DISTTITLE) README File" "${DISTDATE}" < README.tex > README2.tex
|
||||
mv README2.tex README.tex
|
||||
pdflatex README.tex
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
This is the Verilator Package README file.
|
||||
This is the Verilator package README file.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
http://www.veripool.org/verilator
|
||||
|
||||
This package is Copyright 2003-2015 by Wilson Snyder. (Report bugs to
|
||||
L<http://www.veripool.org/>.)
|
||||
|
||||
+108
-42
@@ -246,6 +246,7 @@ descriptions in the next sections for more information.
|
||||
-CFLAGS <flags> C++ Compiler flags for makefile
|
||||
--cc Create C++ output
|
||||
--cdc Clock domain crossing analysis
|
||||
--clk <signal-name> Mark specified signal as clock
|
||||
--compiler <compiler-name> Tune for specified C++ compiler
|
||||
--converge-limit <loops> Tune convergence settle time
|
||||
--coverage Enable all coverage
|
||||
@@ -262,6 +263,7 @@ descriptions in the next sections for more information.
|
||||
+define+<var>=<value> Set preprocessor define
|
||||
--dump-tree Enable dumping .tree files
|
||||
--dump-treei <level> Enable dumping .tree files at a level
|
||||
--dump-treei-<srcfile> <level> Enable dumping .tree file at a source file at a level
|
||||
-E Preprocess, but do not compile
|
||||
--error-limit <value> Abort after this number of errors
|
||||
--exe Link to create executable
|
||||
@@ -284,6 +286,7 @@ descriptions in the next sections for more information.
|
||||
--MP Create phony dependency targets
|
||||
--Mdir <directory> Name of output object directory
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--no-clk <signal-name> Prevent marking specified signal as clock
|
||||
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
||||
--no-skip-identical Disable skipping identical output
|
||||
+notimingchecks Ignored
|
||||
@@ -456,6 +459,23 @@ information is also written to the file {prefix}__cdc.txt.
|
||||
Currently only checks some items that other CDC tools missed; if you have
|
||||
interest in adding more traditional CDC checks, please contact the authors.
|
||||
|
||||
=item --clk I<signal-name>
|
||||
|
||||
Sometimes it is quite difficult for Verilator to distinguish clock signals from
|
||||
other data signals. Occasionally the clock signals can end up in the checking
|
||||
list of signals which determines if further evaluation is needed. This will
|
||||
heavily degrade the performance of verilated model.
|
||||
|
||||
With --clk <signal-name>, user can specified root clock into the model, then
|
||||
Verilator will mark the signal as clocker and propagate the clocker attribute
|
||||
automatically to other signals derived from that. In this way, Verilator will
|
||||
try to avoid taking the clocker signal into checking list.
|
||||
|
||||
Note signal-name is specified by the RTL hiearchy path. For example, v.foo.bar.
|
||||
If the signal is the input to top-module, the directly the signal name. If you
|
||||
find it difficult to find the exact name, try to use C</*verilator clocker*/> in
|
||||
RTL file to mark the signal directly.
|
||||
|
||||
=item --compiler I<compiler-name>
|
||||
|
||||
Enables tunings and work-arounds for the specified C++ compiler.
|
||||
@@ -573,7 +593,7 @@ alias for GCC compatibility.
|
||||
Select the debug built image of Verilator (if available), and enable more
|
||||
internal assertions (equivelent to C<--debug-check>), debugging messages
|
||||
(equivelent to C<--debugi 4>), and intermediate form dump files (equivilent
|
||||
to C<--dump-tree>).
|
||||
to C<--dump-treei 3>).
|
||||
|
||||
=item --debug-check
|
||||
|
||||
@@ -626,8 +646,12 @@ large and not desired.
|
||||
|
||||
=item --dump-treei <level>
|
||||
|
||||
Rarely needed. Enable writing .tree debug files with a specific dumping
|
||||
level, 0 disbles dumps and is equivalent to "--no-dump-tree". Level 9
|
||||
=item --dump-treei-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set internal tree dumping level
|
||||
globally to a specific dumping level or set the specified Verilator source
|
||||
file to the specified tree dumping level (e.g. C<--dump-treei-V3Order 9>).
|
||||
Level 0 disbles dumps and is equivalent to "--no-dump-tree". Level 9
|
||||
enables dumping of every stage.
|
||||
|
||||
=item -E
|
||||
@@ -761,6 +785,10 @@ otherwise manually create the Mdir before calling Verilator.
|
||||
Specifies the name to prepend to all lower level classes. Defaults to
|
||||
the same as --prefix.
|
||||
|
||||
=item --no-clk <signal-name>
|
||||
|
||||
Prevent the specified signal from being marked as clock. See C<--clk>.
|
||||
|
||||
=item --no-pins64
|
||||
|
||||
Backward compatible alias for "--pins-bv 33".
|
||||
@@ -1981,6 +2009,7 @@ Verilator likewise also asserts any "unique" or "priority" SystemVerilog
|
||||
keywords on case statement, as well as "unique" on if statements.
|
||||
However, "priority if" is currently simply ignored.
|
||||
|
||||
|
||||
=head1 LANGUAGE EXTENSIONS
|
||||
|
||||
The following additional constructs are the extensions Verilator supports
|
||||
@@ -2126,6 +2155,15 @@ scheduling algorithm, sometimes required for correct clock behavior, and
|
||||
always improving performance. It's also a good idea to enable the
|
||||
IMPERFECTSCH warning, to insure all clock enables are properly recognized.
|
||||
|
||||
=item /*verilator clocker*/
|
||||
|
||||
=item /*verilator no_clocker*/
|
||||
|
||||
Used after a signal declaration to indicate the signal is used as clock or
|
||||
not. This information is used by Verilator to mark the signal as clocker
|
||||
and propagate the clocker attribute automatically to derived signals. See
|
||||
C<--clk> for more information.
|
||||
|
||||
=item /*verilator coverage_block_off*/
|
||||
|
||||
Specifies the entire begin/end block should be ignored for coverage
|
||||
@@ -2842,6 +2880,16 @@ With --cdc only, warns that asynchronous flop reset terms come from other
|
||||
than primary inputs or flopped outputs, creating the potential for reset
|
||||
glitches.
|
||||
|
||||
=item CLKDATA
|
||||
|
||||
Warns that clock signal is mixed used with/as data signal. The checking for
|
||||
this warning is enabled only if user has explicitly marked some signal as
|
||||
clocker using command line option or in-source meta comment (see C<--clk>).
|
||||
|
||||
The warning can be disabled without affecting the simulation result. But it
|
||||
is recommanded to check the warning as this may degrade the performance of
|
||||
the Verilated model.
|
||||
|
||||
=item CMPCONST
|
||||
|
||||
Warns that you are comparing a value in a way that will always be constant.
|
||||
@@ -3745,50 +3793,75 @@ as the need arises. Verilator is now about 3x faster than in 2002, and is
|
||||
faster than many popular commercial simulators.
|
||||
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
When possible, please instead report bugs to L<http://www.veripool.org/>.
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
Major concepts by Paul Wasson, Duane Galbi and Jie Xu.
|
||||
|
||||
|
||||
=head1 CONTRIBUTORS
|
||||
|
||||
Many people have provided ideas and other assistance with Verilator.
|
||||
|
||||
The major corporate sponsors of Verilator, by providing significant
|
||||
contributions of time or funds include include Cavium Networks, Compaq
|
||||
Corporation, Digital Equipment Corporation, Embecosm Ltd., Hicamp Systems,
|
||||
Intel Corporation, Mindspeed Technologies Inc., MicroTune Inc., picoChip
|
||||
Designs Ltd., Sun Microsystems, Nauticus Networks, and SiCortex Inc.
|
||||
contributions of time or funds include include Atmel Corporation, Cavium
|
||||
Inc., Compaq Corporation, Digital Equipment Corporation, Embecosm Ltd.,
|
||||
Hicamp Systems, Intel Corporation, Mindspeed Technologies Inc., MicroTune
|
||||
Inc., picoChip Designs Ltd., Sun Microsystems Inc., Nauticus Networks Inc.,
|
||||
and SiCortex Inc.
|
||||
|
||||
The people who have contributed major functionality are Byron Bradley,
|
||||
Jeremy Bennett, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder.
|
||||
Major testers include Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels,
|
||||
Alex Solomatnikov, Sebastien Van Cauwenberghe and Gene Weber.
|
||||
Jeremy Bennett, Jie Xu, Lane Brooks, Duane Galbi, Paul Wasson, and Wilson
|
||||
Snyder. Major testers include Jeff Dutton, Jonathon Donaldson, Ralf Karge,
|
||||
David Hewson, Iztok Jeras, Wim Michiels, Alex Solomatnikov, Sebastien Van
|
||||
Cauwenberghe, Gene Weber, and Clifford Wolf.
|
||||
|
||||
Some of the people who have provided ideas and feedback for Verilator
|
||||
include: David Addison, Vasu Arasanipalai, Jens Arm, J Baxter, Jeremy
|
||||
Bennett, David Black, Gregg Bouchard, Christopher Boumenot, Nick Bowler,
|
||||
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher,
|
||||
Chris Candler, Lauren Carlson, Donal Casey, Terry Chen, Robert A. Clark,
|
||||
Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, Mike
|
||||
Denio, John Deroo, John Dickol, Ruben Diez, Danny Ding, Ivan Djordjevic,
|
||||
Alex Duller, Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy,
|
||||
Robert Farrell, Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri,
|
||||
Sam Gladstone, Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins,
|
||||
David Hewson, Jae Hossell, Ben Jackson, Iztok Jeras, Christophe Joly, Mike
|
||||
Kagen, Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan
|
||||
Katz, Sol Katzman, Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki,
|
||||
David Kravitz, Steve Lang, Stephane Laurent, Walter Lavino, Christian
|
||||
Leber, John Li, Charlie Lind, Andrew Ling, Paul Liu, Dan Lussier, Fred Ma,
|
||||
Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
|
||||
Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
|
||||
Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
|
||||
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Alberto Del Rio, Oleg
|
||||
Rodionov, John Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael
|
||||
Shirakawa, Jeffrey Short, Rodney Sinclair, Brian Small, Alex Solomatnikov,
|
||||
Art Stamness, John Stroebel, Emerson Suguimoto, Gene Sullivan, Renga
|
||||
Sundararajan, Stefan Thiede, Gary Thomas, Steve Tong, Hans Van Antwerpen,
|
||||
Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters, Thomas
|
||||
Watts, Eugene Weber, David Welch, Leon Wildman, Gerald Williams, Trevor
|
||||
Williams, Jeff Winston, Joshua Wise, Johan Wouters, and Ding Xiaoliang.
|
||||
include: Yves Mathieu, David Addison, Nikana Anastasiadis, Hans Van
|
||||
Antwerpen, Vasu Arasanipalai, Jens Arm, Sharad Bagri, Andrew Bardsley,
|
||||
Geoff Barrett, J Baxter, Julius Baxter, Jeremy Bennett, Michael Berman,
|
||||
David Binderman, David Black, Daniel Bone, Gregg Bouchard, Christopher
|
||||
Boumenot, Nick Bowler, Byron Bradley, Bryan Brady, Charlie Brej, Lane
|
||||
Brooks, John Brownlee, Jeff Bush, Lawrence Butcher, Ted Campbell, Chris
|
||||
Candler, Lauren Carlson, Donal Casey, Terry Chen, Robert A. Clark, Allan
|
||||
Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard Deadman, Mike Denio,
|
||||
John Deroo, Philip Derrick, John Dickol, R. Diez, Ruben Diez, Danny Ding,
|
||||
Ivan Djordjevic, Jonathon Donaldson, Alex Duller, Jeff Dutton, Chandan
|
||||
Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell, Eugen Fekete,
|
||||
Fabrizio Ferrandi, Andrea Foletto, Bob Fredieu, Christian Gelinek, Glen
|
||||
Gibb, Shankar Giri, Sam Gladstone, Amir Gonnen, Chitlesh Goorah, Neil
|
||||
Hamilton, Junji Hashimoto, Thomas Hawkins, David Hewson, Hiroki Honda, Alex
|
||||
Hornung, Jae Hossell, Ben Jackson, Krzysztof Jankowski, HyungKi Jeong,
|
||||
Iztok Jeras, James Johnson, Christophe Joly, Franck Jullien, Mike Kagen,
|
||||
Kaalia Kahn, Guy-Armand Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf
|
||||
Karge, Dan Katz, Sol Katzman, Jonathan Kimmitt, Sobhan Klnv, Gernot Koch,
|
||||
Soon Koh, Steve Kolecki, Brett Koonce, Wojciech Koszek, Varun Koyyalagunta,
|
||||
David Kravitz, Roland Kruse, Ed Lander, Steve Lang, Stephane Laurent,
|
||||
Walter Lavino, Christian Leber, Igor Lesik, John Li, Eivind Liland, Charlie
|
||||
Lind, Andrew Ling, Paul Liu, Derek Lockhart, Arthur Low, Stefan Ludwig, Dan
|
||||
Lussier, Fred Ma, Duraid Madina, Mark Marshall, Jason McMullan, Wim
|
||||
Michiels, Wai Sum Mong, Sean Moore, Dennis Muhlestein, John Murphy, Richard
|
||||
Myers, Dimitris Nalbantis, Bob Newgard, Cong Van Nguyen, Paul Nitza, Pete
|
||||
Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, David
|
||||
Pierce, Dominic Plunkett, David Poole, Rich Porter, Niranjan Prabhu, Usha
|
||||
Priyadharshini, Mark Jackson Pulver, Prateek Puri, Chris Randall, Frederic
|
||||
Requin, Alberto Del Rio, Oleg Rodionov, Jan Egil Ruud, John Sanguinetti,
|
||||
Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey Short, Rodney
|
||||
Sinclair, Steven Slatter, Brian Small, Wilson Snyder, Alex Solomatnikov,
|
||||
Art Stamness, John Stevenson, Todd Strader, John Stroebel, Emerson
|
||||
Suguimoto, Gene Sullivan, Renga Sundararajan, Yutetsu Takatsukasa, Peter
|
||||
Tengstrand, Stefan Thiede, Gary Thomas, Kevin Thompson, Mike Thyer, Steve
|
||||
Tong, Holger Waechtler, Stefan Wallentowitz, Shawn Wang, Greg Waters,
|
||||
Thomas Watts, Eugene Weber, David Welch, Leon Wildman, Gerald Williams,
|
||||
Trevor Williams, Jeff Winston, Joshua Wise, Clifford Wolf, Johan Wouters,
|
||||
Ding Xiaoliang, Jie Xu, and Amir Yazdanbakhsh.
|
||||
|
||||
Thanks to them, and all those we've missed including above.
|
||||
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
@@ -3798,13 +3871,6 @@ redistribute it and/or modify the Verilator internals under the terms of
|
||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||
License Version 2.0.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
When possible, please instead report bugs to L<http://www.veripool.org/>.
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
Major concepts by Paul Wasson and Duane Galbi.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.870 2015-02-12])
|
||||
AC_INIT([Verilator],[3.872 2015-04-05])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief Verilator coverage analysis
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief Coverage analysis support
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef _VERILATED_COV_H_
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief Coverage item keys
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef _VERILATED_COV_KEY_H_
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief C++ Tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief Save-restore serialization of verilated modules
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef _VERILATED_SAVE_C_H_
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief C++ Tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
// SPDIFF_OFF
|
||||
|
||||
@@ -76,11 +74,48 @@ protected:
|
||||
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {};
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// VerilatedVcdFile
|
||||
|
||||
bool VerilatedVcdFile::open(const string& name) {
|
||||
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK, 0666);
|
||||
return (m_fd>=0);
|
||||
}
|
||||
|
||||
void VerilatedVcdFile::close() {
|
||||
::close(m_fd);
|
||||
}
|
||||
|
||||
ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) {
|
||||
return ::write(m_fd, bufp, len);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Opening/Closing
|
||||
|
||||
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
|
||||
: m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
|
||||
// Not in header to avoid link issue if header is included without this .cpp file
|
||||
m_fileNewed = (filep == NULL);
|
||||
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
|
||||
m_namemapp = NULL;
|
||||
m_timeRes = m_timeUnit = 1e-9;
|
||||
m_timeLastDump = 0;
|
||||
m_sigs_oldvalp = NULL;
|
||||
m_evcd = false;
|
||||
m_scopeEscape = '.'; // Backward compatibility
|
||||
m_fullDump = true;
|
||||
m_wrChunkSize = 8*1024;
|
||||
m_wrBufp = new char [m_wrChunkSize*8];
|
||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||
m_writep = m_wrBufp;
|
||||
m_wroteBytes = 0;
|
||||
}
|
||||
|
||||
void VerilatedVcd::open (const char* filename) {
|
||||
if (isOpen()) return;
|
||||
|
||||
@@ -142,9 +177,7 @@ void VerilatedVcd::openNext (bool incFilename) {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
// cppcheck-suppress duplicateExpression
|
||||
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
if (!m_filep->open(m_filename)) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
@@ -199,6 +232,7 @@ VerilatedVcd::~VerilatedVcd() {
|
||||
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
|
||||
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
|
||||
deleteNameMap();
|
||||
if (m_filep && m_fileNewed) { delete m_filep; m_filep = NULL; }
|
||||
// Remove from list of traces
|
||||
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
|
||||
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
|
||||
@@ -209,7 +243,7 @@ void VerilatedVcd::closePrev () {
|
||||
|
||||
bufferFlush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd);
|
||||
m_filep->close();
|
||||
}
|
||||
|
||||
void VerilatedVcd::closeErr () {
|
||||
@@ -219,7 +253,7 @@ void VerilatedVcd::closeErr () {
|
||||
|
||||
// No buffer flush, just fclose
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
m_filep->close(); // May get error, just ignore it
|
||||
}
|
||||
|
||||
void VerilatedVcd::close() {
|
||||
@@ -285,7 +319,7 @@ void VerilatedVcd::bufferFlush () {
|
||||
ssize_t remaining = (m_writep - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = write (m_fd, wp, remaining);
|
||||
ssize_t got = m_filep->write(wp, remaining);
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
m_wroteBytes += got;
|
||||
|
||||
+20
-19
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief C++ Tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
// SPDIFF_OFF
|
||||
|
||||
@@ -36,6 +34,22 @@ class VerilatedVcd;
|
||||
class VerilatedVcdCallInfo;
|
||||
|
||||
// SPDIFF_ON
|
||||
//=============================================================================
|
||||
// VerilatedFile
|
||||
/// File handling routines, which can be overrode for e.g. socket I/O
|
||||
|
||||
class VerilatedVcdFile {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
public:
|
||||
// METHODS
|
||||
VerilatedVcdFile() : m_fd(0) {}
|
||||
virtual ~VerilatedVcdFile() {}
|
||||
virtual bool open(const string& name);
|
||||
virtual void close();
|
||||
virtual ssize_t write(const char* bufp, ssize_t len);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedVcdSig
|
||||
/// Internal data on one signal being traced.
|
||||
@@ -62,9 +76,10 @@ typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluin
|
||||
|
||||
class VerilatedVcd {
|
||||
private:
|
||||
VerilatedVcdFile* m_filep; ///< File we're writing to
|
||||
bool m_fileNewed; ///< m_filep needs destruction
|
||||
bool m_isOpen; ///< True indicates open file
|
||||
bool m_evcd; ///< True for evcd format
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
string m_filename; ///< Filename we're writing to (if open)
|
||||
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
|
||||
char m_scopeEscape; ///< Character to separate scope components
|
||||
@@ -135,21 +150,7 @@ protected:
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
|
||||
m_namemapp = NULL;
|
||||
m_timeRes = m_timeUnit = 1e-9;
|
||||
m_timeLastDump = 0;
|
||||
m_sigs_oldvalp = NULL;
|
||||
m_evcd = false;
|
||||
m_scopeEscape = '.'; // Backward compatibility
|
||||
m_fd = 0;
|
||||
m_fullDump = true;
|
||||
m_wrChunkSize = 8*1024;
|
||||
m_wrBufp = new char [m_wrChunkSize*8];
|
||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||
m_writep = m_wrBufp;
|
||||
m_wroteBytes = 0;
|
||||
}
|
||||
VerilatedVcd(VerilatedVcdFile* filep=NULL);
|
||||
~VerilatedVcd();
|
||||
|
||||
// ACCESSORS
|
||||
@@ -398,7 +399,7 @@ class VerilatedVcdC {
|
||||
VerilatedVcd m_sptrace; ///< Trace file being created
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedVcdC() {}
|
||||
VerilatedVcdC(VerilatedVcdFile* filep=NULL) : m_sptrace(filep) {}
|
||||
~VerilatedVcdC() {}
|
||||
// ACCESSORS
|
||||
/// Is file open?
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief Verilator tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
// SPDIFF_OFF
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
/// \file
|
||||
/// \brief Verilator tracing in VCD format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
// SPDIFF_OFF
|
||||
|
||||
|
||||
@@ -178,6 +178,7 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
|
||||
#else // Linux or compliant Unix flavors, -m64
|
||||
|
||||
# include <stdint.h> // Linux and most flavors
|
||||
# include <unistd.h> // Linux ssize_t
|
||||
# include <inttypes.h> // Solaris
|
||||
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
||||
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
||||
|
||||
@@ -407,6 +407,18 @@ Tests that fail should by convention have the suffix C<_bad> in their name,
|
||||
and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
|
||||
appropriate.
|
||||
|
||||
=head2 Preparing to Run Tests
|
||||
|
||||
For all tests to pass you must install the following packages:
|
||||
|
||||
* SystemC to compile the SystemC outputs, see http://systemc.org
|
||||
|
||||
* Parallel::Forker from CPAN to run tests in parallel, you can install this
|
||||
with e.g. "sudo cpan install Parallel::Forker".
|
||||
|
||||
* vcddiff to find differences in VCD outputs. See the readme at
|
||||
https://github.com/veripool/vcddiff
|
||||
|
||||
=head2 Controlling the Test Driver
|
||||
|
||||
Test drivers are written in PERL. All invoke the main test driver script,
|
||||
|
||||
@@ -215,6 +215,7 @@ RAW_OBJS = \
|
||||
V3Number.o \
|
||||
V3Options.o \
|
||||
V3Order.o \
|
||||
V3Os.o \
|
||||
V3Param.o \
|
||||
V3PreShell.o \
|
||||
V3Premit.o \
|
||||
|
||||
@@ -436,4 +436,5 @@ public:
|
||||
void V3Active::activeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ActiveVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("active.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -160,4 +160,5 @@ public:
|
||||
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ActiveTopVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("activetop.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -337,4 +337,5 @@ public:
|
||||
void V3Assert::assertAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
AssertVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("assert.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -137,4 +137,5 @@ public:
|
||||
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
AssertPreVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("assertpre.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+5
-1
@@ -176,6 +176,10 @@ string AstNode::prettyName(const string& namein) {
|
||||
pretty += ".";
|
||||
pos += 7;
|
||||
}
|
||||
else if (0==strncmp(pos,"->",2)) {
|
||||
pretty += ".";
|
||||
pos += 2;
|
||||
}
|
||||
else if (0==strncmp(pos,"__PVT__",7)) {
|
||||
pretty += "";
|
||||
pos += 7;
|
||||
@@ -1009,7 +1013,7 @@ void AstNode::dumpTreeAndNext(ostream& os, const string& indent, int maxDepth) {
|
||||
}
|
||||
|
||||
void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
||||
if (v3Global.opt.dumpTree() && doDump) {
|
||||
if (doDump) {
|
||||
{ // Write log & close
|
||||
UINFO(2,"Dumping "<<filename<<endl);
|
||||
const auto_ptr<ofstream> logsp (V3File::new_ofstream(filename, append));
|
||||
|
||||
+36
-2
@@ -257,7 +257,9 @@ public:
|
||||
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
|
||||
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
|
||||
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
|
||||
VAR_SFORMAT, // V3LinkParse moves to AstVar::attrSFormat
|
||||
VAR_CLOCKER, // V3LinkParse moves to AstVar::attrClocker
|
||||
VAR_NO_CLOCKER // V3LinkParse moves to AstVar::attrClocker
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
@@ -270,7 +272,8 @@ public:
|
||||
"MEMBER_BASE",
|
||||
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER",
|
||||
"VAR_NO_CLOCKER"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
@@ -485,6 +488,37 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstVarAttrClocker {
|
||||
public:
|
||||
enum en {
|
||||
CLOCKER_UNKNOWN=0,
|
||||
CLOCKER_YES,
|
||||
CLOCKER_NO,
|
||||
_ENUM_END
|
||||
};
|
||||
enum en m_e;
|
||||
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
||||
inline AstVarAttrClocker () : m_e(CLOCKER_UNKNOWN) {}
|
||||
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
AstVarAttrClocker invert() const {
|
||||
if (m_e==CLOCKER_YES) return CLOCKER_NO;
|
||||
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
|
||||
else return m_e;
|
||||
}
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"","clker","non_clker"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstVarAttrClocker::en lhs, AstVarAttrClocker rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstVarAttrClocker rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VAlwaysKwd {
|
||||
public:
|
||||
enum en {
|
||||
|
||||
@@ -350,6 +350,27 @@ string AstVar::scType() const {
|
||||
}
|
||||
}
|
||||
|
||||
AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
||||
// See if this is a SC assignment; if so return that type
|
||||
// Historically sc variables are identified by a variable
|
||||
// attribute. TODO it would better be a data type attribute.
|
||||
if (AstVar* anodep = nodep->castVar()) {
|
||||
if (anodep->isSc()) return anodep;
|
||||
else return NULL;
|
||||
}
|
||||
else if (nodep->castVarRef()) {
|
||||
if (nodep->castVarRef()->varp()->isSc()) return nodep->castVarRef()->varp();
|
||||
else return NULL;
|
||||
}
|
||||
else if (nodep->castArraySel()) {
|
||||
if (nodep->op1p()) if (AstVar* p = scVarRecurse(nodep->op1p())) return p;
|
||||
if (nodep->op2p()) if (AstVar* p = scVarRecurse(nodep->op2p())) return p;
|
||||
if (nodep->op3p()) if (AstVar* p = scVarRecurse(nodep->op3p())) return p;
|
||||
if (nodep->op4p()) if (AstVar* p = scVarRecurse(nodep->op4p())) return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
||||
// dimension passed from AstArraySel::dimension
|
||||
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
|
||||
|
||||
+5
-2
@@ -942,6 +942,7 @@ private:
|
||||
bool m_isIfaceParent:1; // dtype is reference to interface present in this module
|
||||
bool m_noSubst:1; // Do not substitute out references
|
||||
bool m_trace:1; // Trace this variable
|
||||
AstVarAttrClocker m_attrClocker;
|
||||
|
||||
void init() {
|
||||
m_input=false; m_output=false; m_tristate=false; m_declOutput=false;
|
||||
@@ -952,8 +953,7 @@ private:
|
||||
m_funcLocal=false; m_funcReturn=false;
|
||||
m_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false;
|
||||
m_fileDescr=false; m_isConst=false; m_isStatic=false; m_isPulldown=false; m_isPullup=false;
|
||||
m_isIfaceParent=false;
|
||||
m_noSubst=false;
|
||||
m_isIfaceParent=false; m_attrClocker=AstVarAttrClocker::CLOCKER_UNKNOWN; m_noSubst=false;
|
||||
m_trace=false;
|
||||
}
|
||||
public:
|
||||
@@ -1026,6 +1026,7 @@ public:
|
||||
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
|
||||
void attrClockEn(bool flag) { m_attrClockEn = flag; }
|
||||
void attrClocker(AstVarAttrClocker flag) { m_attrClocker = flag; }
|
||||
void attrFileDescr(bool flag) { m_fileDescr = flag; }
|
||||
void attrScClocked(bool flag) { m_scClocked = flag; }
|
||||
void attrScBv(bool flag) { m_attrScBv = flag; }
|
||||
@@ -1105,6 +1106,7 @@ public:
|
||||
bool attrScClocked() const { return m_scClocked; }
|
||||
bool attrSFormat() const { return m_attrSFormat; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
AstVarAttrClocker attrClocker() const { return m_attrClocker; }
|
||||
virtual string verilogKwd() const;
|
||||
void propagateAttrFrom(AstVar* fromp) {
|
||||
// This is getting connected to fromp; keep attributes
|
||||
@@ -1132,6 +1134,7 @@ public:
|
||||
if (varType()==AstVarType::INOUT) m_varType = AstVarType::TRIWIRE;
|
||||
if (varType()==AstVarType::INPUT || varType()==AstVarType::OUTPUT) m_varType = AstVarType::WIRE;
|
||||
}
|
||||
static AstVar* scVarRecurse(AstNode* nodep);
|
||||
};
|
||||
|
||||
class AstDefParam : public AstNode {
|
||||
|
||||
@@ -271,4 +271,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||
if (state.anyFuncInBegin()) {
|
||||
BeginRelinkVisitor brvisitor (nodep,&state);
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("begin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -491,6 +491,7 @@ public:
|
||||
void V3Case::caseAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CaseVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("case.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
void V3Case::caseLint(AstNodeCase* nodep) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
|
||||
@@ -149,6 +149,7 @@ private:
|
||||
if (!nodep->lvalue()
|
||||
&& !nodep->backp()->castCCast()
|
||||
&& nodep->backp()->castNodeMath()
|
||||
&& !nodep->backp()->castArraySel()
|
||||
&& nodep->backp()->width()
|
||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||
// Cast vars to IData first, else below has upper bits wrongly set
|
||||
@@ -187,4 +188,5 @@ public:
|
||||
void V3Cast::castAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CastVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("cast.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -252,4 +252,5 @@ void V3Changed::changedAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ChangedState state;
|
||||
ChangedVisitor visitor (nodep, &state);
|
||||
V3Global::dumpCheckGlobalTree("changed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -292,4 +292,5 @@ public:
|
||||
void V3Clean::cleanAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CleanVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("clean.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -914,4 +914,5 @@ void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
|
||||
// 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);
|
||||
V3Global::dumpCheckGlobalTree("clkgater.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -407,4 +407,5 @@ public:
|
||||
void V3Clock::clockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ClockVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("clock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -474,4 +474,5 @@ public:
|
||||
void V3Combine::combineAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CombineVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("combine.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -2383,12 +2383,14 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_CPP);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const_cpp.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
||||
@@ -2404,6 +2406,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
@@ -2411,6 +2414,7 @@ void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
|
||||
|
||||
@@ -395,4 +395,5 @@ public:
|
||||
void V3Coverage::coverage(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CoverageVisitor visitor (rootp);
|
||||
V3Global::dumpCheckGlobalTree("coverage.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -135,4 +135,5 @@ public:
|
||||
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CoverageJoinVisitor visitor (rootp);
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -291,12 +291,15 @@ public:
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true);
|
||||
V3Global::dumpCheckGlobalTree("deadDType.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -471,4 +471,5 @@ public:
|
||||
void V3Delayed::delayedAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DelayedVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("delayed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -175,4 +175,5 @@ public:
|
||||
void V3Depth::depthAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DepthVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("depth.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -140,4 +140,5 @@ public:
|
||||
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DepthBlockVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("deepblock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -262,4 +262,5 @@ public:
|
||||
void V3Descope::descopeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DescopeVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("descope.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+5
-6
@@ -83,6 +83,7 @@ public:
|
||||
: nodep->isQuad() ? "Q" : "I");
|
||||
}
|
||||
void emitScIQW(AstVar* nodep) {
|
||||
if (!nodep->isSc()) nodep->v3fatalSrc("emitting SystemC operator on non-SC variable");
|
||||
puts (nodep->isScBigUint() ? "SB"
|
||||
: nodep->isScUint() ? "SU"
|
||||
: nodep->isScBv() ? "SW"
|
||||
@@ -155,19 +156,17 @@ public:
|
||||
selp->lsbp()->iterateAndNext(*this); puts(", ");
|
||||
selp->fromp()->iterateAndNext(*this); puts(", ");
|
||||
}
|
||||
} else if (nodep->lhsp()->castVarRef()
|
||||
&& nodep->lhsp()->castVarRef()->varp()->isSc()) {
|
||||
} else if (AstVar* varp = AstVar::scVarRecurse(nodep->lhsp())) {
|
||||
putbs("VL_ASSIGN_"); // Set a systemC variable
|
||||
emitScIQW(nodep->lhsp()->castVarRef()->varp());
|
||||
emitScIQW(varp);
|
||||
emitIQW(nodep);
|
||||
puts("(");
|
||||
puts(cvtToStr(nodep->widthMin())+",");
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
} else if (nodep->rhsp()->castVarRef()
|
||||
&& nodep->rhsp()->castVarRef()->varp()->isSc()) {
|
||||
} else if (AstVar* varp = AstVar::scVarRecurse(nodep->rhsp())) {
|
||||
putbs("VL_ASSIGN_"); // Get a systemC variable
|
||||
emitIQW(nodep);
|
||||
emitScIQW(nodep->rhsp()->castVarRef()->varp());
|
||||
emitScIQW(varp);
|
||||
puts("(");
|
||||
puts(cvtToStr(nodep->widthMin())+",");
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
|
||||
+5
-4
@@ -29,6 +29,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3EmitMk.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
@@ -46,7 +47,7 @@ public:
|
||||
}
|
||||
|
||||
void putMakeClassEntry(V3OutMkFile& of, const string& name) {
|
||||
of.puts("\t"+V3Options::filenameNonDirExt(name)+" \\\n");
|
||||
of.puts("\t"+V3Os::filenameNonDirExt(name)+" \\\n");
|
||||
}
|
||||
|
||||
void emitClassMake() {
|
||||
@@ -184,8 +185,8 @@ public:
|
||||
const V3StringSet& cppFiles = v3Global.opt.cppFiles();
|
||||
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
|
||||
string cppfile = *it;
|
||||
of.puts("\t"+V3Options::filenameNonExt(cppfile)+" \\\n");
|
||||
string dir = V3Options::filenameDir(cppfile);
|
||||
of.puts("\t"+V3Os::filenameNonExt(cppfile)+" \\\n");
|
||||
string dir = V3Os::filenameDir(cppfile);
|
||||
if (dirs.find(dir) == dirs.end()) dirs.insert(dir);
|
||||
}
|
||||
of.puts("\n");
|
||||
@@ -209,7 +210,7 @@ public:
|
||||
of.puts("\n");
|
||||
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
|
||||
string cppfile = *it;
|
||||
string basename = V3Options::filenameNonExt(cppfile);
|
||||
string basename = V3Os::filenameNonExt(cppfile);
|
||||
of.puts(basename+".o: "+cppfile+"\n");
|
||||
of.puts("\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<\n");
|
||||
}
|
||||
|
||||
+3
-2
@@ -65,6 +65,7 @@ public:
|
||||
CASEWITHX, // Case with X values
|
||||
CASEX, // Casex
|
||||
CDCRSTLOGIC, // Logic in async reset path
|
||||
CLKDATA, // Clock used as data
|
||||
CMPCONST, // Comparison is constant due to limited range
|
||||
COMBDLY, // Combinatorial delayed assignment
|
||||
DEFPARAM, // Style: Defparam
|
||||
@@ -119,8 +120,8 @@ public:
|
||||
" EC_FIRST_WARN",
|
||||
"ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN",
|
||||
"BLKANDNBLK", "BLKSEQ",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
|
||||
"COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CLKDATA",
|
||||
"CMPCONST", "COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||
"ENDLABEL", "GENCLK",
|
||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
|
||||
"INCABSPATH", "INITIALDLY",
|
||||
|
||||
+5
-7
@@ -874,16 +874,13 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
bool did = false;
|
||||
if (nodep->isWide() && ((nodep->lhsp()->castVarRef()
|
||||
&& !nodep->lhsp()->castVarRef()->varp()->isSc())
|
||||
|| nodep->lhsp()->castArraySel())) {
|
||||
|| nodep->lhsp()->castArraySel()))
|
||||
&& !AstVar::scVarRecurse(nodep->lhsp()) // Need special function for SC
|
||||
&& !AstVar::scVarRecurse(nodep->rhsp())) {
|
||||
if (AstConst* rhsp = nodep->rhsp()->castConst()) {
|
||||
did = expandWide(nodep,rhsp);
|
||||
} else if (AstVarRef* rhsp = nodep->rhsp()->castVarRef()) {
|
||||
if (rhsp->varp()->isSc()) {
|
||||
// Still need special access function
|
||||
} else {
|
||||
did = expandWide(nodep,rhsp);
|
||||
}
|
||||
did = expandWide(nodep,rhsp);
|
||||
} else if (AstSel* rhsp = nodep->rhsp()->castSel()) {
|
||||
did = expandWide(nodep,rhsp);
|
||||
} else if (AstArraySel* rhsp = nodep->rhsp()->castArraySel()) {
|
||||
@@ -940,4 +937,5 @@ public:
|
||||
void V3Expand::expandAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ExpandVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("expand.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+2
-9
@@ -40,6 +40,7 @@
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3File.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3PreShell.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
@@ -259,19 +260,11 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
|
||||
return dependImp.checkTimes(filename, cmdline);
|
||||
}
|
||||
|
||||
void V3File::createDir(const string& dirname) {
|
||||
#ifndef _WIN32
|
||||
mkdir(dirname.c_str(), 0777);
|
||||
#else
|
||||
mkdir(dirname.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void V3File::createMakeDir() {
|
||||
static bool created = false;
|
||||
if (!created) {
|
||||
created = true;
|
||||
createDir(v3Global.opt.makeDir());
|
||||
V3Os::createDir(v3Global.opt.makeDir());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ public:
|
||||
static bool checkTimes(const string& filename, const string& cmdline);
|
||||
|
||||
// Directory utilities
|
||||
static void createDir(const string& dirname);
|
||||
static void createMakeDir();
|
||||
};
|
||||
|
||||
|
||||
@@ -1266,4 +1266,5 @@ void V3Gate::gateAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
GateVisitor visitor (nodep);
|
||||
GateDeassignVisitor deassign (nodep);
|
||||
V3Global::dumpCheckGlobalTree("gate.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -228,4 +228,5 @@ public:
|
||||
void V3GenClk::genClkAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
GenClkReadVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("genclk.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -563,4 +563,5 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
|
||||
modp->unlinkFrBack()->deleteTree(); modp=NULL;
|
||||
}
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("inline.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -322,9 +322,11 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
|
||||
void V3Inst::instAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
InstVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("inst.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Inst::dearrayAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
InstDeVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("dearray.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -515,4 +515,5 @@ void V3Life::lifeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
LifeState state;
|
||||
LifeTopVisitor visitor (nodep, &state);
|
||||
V3Global::dumpCheckGlobalTree("life.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -193,4 +193,5 @@ void V3LifePost::lifepostAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
// Mark redundant AssignPost
|
||||
LifePostDlyVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("life_post.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+12
-4
@@ -35,13 +35,21 @@ private:
|
||||
static void linkDotGuts(AstNetlist* nodep, VLinkDotStep step);
|
||||
public:
|
||||
static void linkDotPrimary(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PRIMARY); }
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PRIMARY);
|
||||
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
static void linkDotParamed(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PARAMED); }
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_PARAMED);
|
||||
V3Global::dumpCheckGlobalTree("paramlink.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
static void linkDotArrayed(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_ARRAYED); }
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_ARRAYED);
|
||||
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
static void linkDotScope(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_SCOPED); }
|
||||
UINFO(2,__FUNCTION__<<": "<<endl); linkDotGuts(nodep,LDS_SCOPED);
|
||||
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -263,4 +263,5 @@ public:
|
||||
void V3LinkJump::linkJump(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
LinkJumpVisitor bvisitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("link.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -269,6 +269,7 @@ public:
|
||||
void V3LinkLValue::linkLValue(AstNetlist* rootp) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
LinkLValueVisitor visitor(rootp, false);
|
||||
V3Global::dumpCheckGlobalTree("linklvalue.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
void V3LinkLValue::linkLValueSet(AstNode* nodep) {
|
||||
// Called by later link functions when it is known a node needs
|
||||
|
||||
@@ -80,6 +80,7 @@ void V3LinkLevel::modSortByLevel() {
|
||||
v3Global.rootp()->addModulep(nodep);
|
||||
}
|
||||
UINFO(9,"modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666
|
||||
V3Global::dumpCheckGlobalTree("cells.tree", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -237,6 +237,16 @@ private:
|
||||
m_varp->attrScBv(true);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_YES);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) {
|
||||
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
|
||||
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_NO);
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||
@@ -359,4 +369,5 @@ public:
|
||||
void V3LinkParse::linkParse(AstNetlist* rootp) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
LinkParseVisitor visitor(rootp);
|
||||
V3Global::dumpCheckGlobalTree("linkparse.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -462,4 +462,5 @@ void V3LinkResolve::linkResolve(AstNetlist* rootp) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
LinkResolveVisitor visitor(rootp);
|
||||
LinkBotupVisitor visitorb(rootp);
|
||||
V3Global::dumpCheckGlobalTree("linkresolve.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -250,4 +250,5 @@ void V3Localize::localizeAll(AstNetlist* nodep) {
|
||||
LocalizeVisitor visitor (nodep);
|
||||
// Fix up hiernames
|
||||
LocalizeDehierVisitor dvisitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("localize.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -149,4 +149,5 @@ public:
|
||||
void V3Name::nameAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
NameVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("name.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
+90
-153
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3Options.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3File.h"
|
||||
@@ -156,12 +157,27 @@ bool V3Options::isFuture(const string& flag) const {
|
||||
bool V3Options::isLibraryFile(const string& filename) const {
|
||||
return m_libraryFiles.find(filename) != m_libraryFiles.end();
|
||||
}
|
||||
|
||||
void V3Options::addLibraryFile(const string& filename) {
|
||||
if (m_libraryFiles.find(filename) == m_libraryFiles.end()) {
|
||||
m_libraryFiles.insert(filename);
|
||||
}
|
||||
}
|
||||
bool V3Options::isClocker(const string& signame) const {
|
||||
return m_clockers.find(signame) != m_clockers.end();
|
||||
}
|
||||
void V3Options::addClocker(const string& signame) {
|
||||
if (m_clockers.find(signame) == m_clockers.end()) {
|
||||
m_clockers.insert(signame);
|
||||
}
|
||||
}
|
||||
bool V3Options::isNoClocker(const string& signame) const {
|
||||
return m_noClockers.find(signame) != m_noClockers.end();
|
||||
}
|
||||
void V3Options::addNoClocker(const string& signame) {
|
||||
if (m_noClockers.find(signame) == m_noClockers.end()) {
|
||||
m_noClockers.insert(signame);
|
||||
}
|
||||
}
|
||||
void V3Options::addVFile(const string& filename) {
|
||||
// We use a list for v files, because it's legal to have includes
|
||||
// in a specific order and multiple of them.
|
||||
@@ -197,83 +213,6 @@ V3LangCode::V3LangCode (const char* textp) {
|
||||
//######################################################################
|
||||
// File searching
|
||||
|
||||
string V3Options::filenameFromDirBase (const string& dir, const string& basename) {
|
||||
// Don't return ./{filename} because if filename was absolute, that makes it relative
|
||||
if (dir == ".") return basename;
|
||||
else return dir+"/"+basename;
|
||||
}
|
||||
|
||||
string V3Options::filenameDir (const string& filename) {
|
||||
string::size_type pos;
|
||||
if ((pos = filename.rfind("/")) != string::npos) {
|
||||
return filename.substr(0,pos);
|
||||
} else {
|
||||
return ".";
|
||||
}
|
||||
}
|
||||
|
||||
string V3Options::filenameNonDir (const string& filename) {
|
||||
string::size_type pos;
|
||||
if ((pos = filename.rfind("/")) != string::npos) {
|
||||
return filename.substr(pos+1);
|
||||
} else {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
string V3Options::filenameNonExt (const string& filename) {
|
||||
string base = filenameNonDir(filename);
|
||||
string::size_type pos;
|
||||
if ((pos = base.find(".")) != string::npos) {
|
||||
base.erase(pos);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
string V3Options::filenameSubstitute (const string& filename) {
|
||||
string out;
|
||||
enum { NONE, PAREN, CURLY } brackets = NONE;
|
||||
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
|
||||
if ((filename[pos] == '$') && (pos+1 < filename.length())) {
|
||||
switch (filename[pos+1]) {
|
||||
case '{': brackets = CURLY; break;
|
||||
case '(': brackets = PAREN; break;
|
||||
default: brackets = NONE; break;
|
||||
}
|
||||
if (brackets != NONE) pos = pos+1;
|
||||
string::size_type endpos = pos+1;
|
||||
while (((endpos+1) < filename.length()) &&
|
||||
(((brackets==NONE) && (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) ||
|
||||
((brackets==CURLY) && (filename[endpos+1]!='}')) ||
|
||||
((brackets==PAREN) && (filename[endpos+1]!=')'))))
|
||||
++endpos;
|
||||
// Catch bracket errors
|
||||
if (((brackets==CURLY) && (filename[endpos+1]!='}')) ||
|
||||
((brackets==PAREN) && (filename[endpos+1]!=')'))) {
|
||||
v3fatal("Unmatched brackets in variable substitution in file: "+filename);
|
||||
}
|
||||
string envvar = filename.substr(pos+1,endpos-pos);
|
||||
const char* envvalue = NULL;
|
||||
if (envvar != "") envvalue = getenv(envvar.c_str());
|
||||
if (envvalue) {
|
||||
out += envvalue;
|
||||
if (brackets==NONE) pos = endpos;
|
||||
else pos = endpos+1;
|
||||
} else {
|
||||
out += filename[pos]; // *pos == '$'
|
||||
}
|
||||
} else {
|
||||
out += filename[pos];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
bool V3Options::filenameIsRel(const string& filename) {
|
||||
return (filename.length()>0 && filename[0] != '/');
|
||||
}
|
||||
|
||||
bool V3Options::fileStatDir(const string& filename) {
|
||||
struct stat sstat; // Stat information
|
||||
int err = stat(filename.c_str(), &sstat);
|
||||
@@ -306,8 +245,8 @@ string V3Options::fileExists (const string& filename) {
|
||||
// is quite slow; presumably because of re-reading each directory
|
||||
// many times. So we read a whole dir at once and cache it
|
||||
|
||||
string dir = filenameDir(filename);
|
||||
string basename = filenameNonDir(filename);
|
||||
string dir = V3Os::filenameDir(filename);
|
||||
string basename = V3Os::filenameNonDir(filename);
|
||||
|
||||
V3OptionsImp::DirMap::iterator diriter = m_impp->m_dirMap.find(dir);
|
||||
if (diriter == m_impp->m_dirMap.end()) {
|
||||
@@ -332,14 +271,14 @@ string V3Options::fileExists (const string& filename) {
|
||||
return ""; // Not found
|
||||
}
|
||||
// Check if it is a directory, ignore if so
|
||||
string filenameOut = filenameFromDirBase (dir, basename);
|
||||
string filenameOut = V3Os::filenameFromDirBase (dir, basename);
|
||||
if (!fileStatNormal(filenameOut)) return ""; // Directory
|
||||
return filenameOut;
|
||||
}
|
||||
|
||||
string V3Options::filePathCheckOneDir(const string& modname, const string& dirname) {
|
||||
for (list<string>::iterator extIter=m_impp->m_libExtVs.begin(); extIter!=m_impp->m_libExtVs.end(); ++extIter) {
|
||||
string fn = filenameFromDirBase(dirname, modname+*extIter);
|
||||
string fn = V3Os::filenameFromDirBase(dirname, modname+*extIter);
|
||||
string exists = fileExists(fn);
|
||||
if (exists!="") {
|
||||
// Strip ./, it just looks ugly
|
||||
@@ -385,14 +324,14 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||
for (list<string>::iterator dirIter=m_impp->m_incDirUsers.begin();
|
||||
dirIter!=m_impp->m_incDirUsers.end(); ++dirIter) {
|
||||
for (list<string>::iterator extIter=m_impp->m_libExtVs.begin(); extIter!=m_impp->m_libExtVs.end(); ++extIter) {
|
||||
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
|
||||
string fn = V3Os::filenameFromDirBase(*dirIter,modname+*extIter);
|
||||
fl->v3error(" "<<fn<<endl);
|
||||
}
|
||||
}
|
||||
for (list<string>::iterator dirIter=m_impp->m_incDirFallbacks.begin();
|
||||
dirIter!=m_impp->m_incDirFallbacks.end(); ++dirIter) {
|
||||
for (list<string>::iterator extIter=m_impp->m_libExtVs.begin(); extIter!=m_impp->m_libExtVs.end(); ++extIter) {
|
||||
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
|
||||
string fn = V3Os::filenameFromDirBase(*dirIter,modname+*extIter);
|
||||
fl->v3error(" "<<fn<<endl);
|
||||
}
|
||||
}
|
||||
@@ -404,7 +343,7 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||
//! If we recognize the extension, use its language, otherwise, use the
|
||||
//! default language.
|
||||
V3LangCode V3Options::fileLanguage(const string &filename) {
|
||||
string ext = filenameNonDir(filename);
|
||||
string ext = V3Os::filenameNonDir(filename);
|
||||
string::size_type pos;
|
||||
if ((pos = ext.rfind(".")) != string::npos) {
|
||||
ext.erase(0, pos + 1);
|
||||
@@ -417,63 +356,27 @@ V3LangCode V3Options::fileLanguage(const string &filename) {
|
||||
}
|
||||
|
||||
|
||||
void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
|
||||
if (DIR* dirp = opendir(dir.c_str())) {
|
||||
while (struct dirent* direntp = readdir(dirp)) {
|
||||
if (VString::wildmatch(direntp->d_name, regexp.c_str())) {
|
||||
string fullname = dir + "/" + string(direntp->d_name);
|
||||
unlink (fullname.c_str());
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Environment
|
||||
|
||||
string V3Options::getenvStr(const string& envvar, const string& defaultValue) {
|
||||
if (const char* envvalue = getenv(envvar.c_str())) {
|
||||
return envvalue;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
void V3Options::setenvStr(const string& envvar, const string& value, const string& why) {
|
||||
if (why != "") {
|
||||
UINFO(1,"export "<<envvar<<"="<<value<<" # "<<why<<endl);
|
||||
} else {
|
||||
UINFO(1,"export "<<envvar<<"="<<value<<endl);
|
||||
}
|
||||
#if defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
|
||||
setenv(envvar.c_str(),value.c_str(),true);
|
||||
#else
|
||||
//setenv() replaced by putenv() in MinGW/Solaris environment. Prototype is different
|
||||
//putenv() requires NAME=VALUE format
|
||||
string vareq = envvar + "=" + value;
|
||||
putenv(const_cast<char*>(vareq.c_str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
string V3Options::getenvPERL() {
|
||||
return getenvStr("PERL","perl");
|
||||
return V3Os::getenvStr("PERL","perl");
|
||||
}
|
||||
|
||||
string V3Options::getenvSYSTEMC() {
|
||||
string var = getenvStr("SYSTEMC","");
|
||||
string var = V3Os::getenvStr("SYSTEMC","");
|
||||
if (var == "" && string(DEFENV_SYSTEMC) != "") {
|
||||
var = DEFENV_SYSTEMC;
|
||||
setenvStr("SYSTEMC", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("SYSTEMC", var, "Hardcoded at build time");
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
string V3Options::getenvSYSTEMC_ARCH() {
|
||||
string var = getenvStr("SYSTEMC_ARCH","");
|
||||
string var = V3Os::getenvStr("SYSTEMC_ARCH","");
|
||||
if (var == "" && string(DEFENV_SYSTEMC_ARCH) != "") {
|
||||
var = DEFENV_SYSTEMC_ARCH;
|
||||
setenvStr("SYSTEMC_ARCH", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("SYSTEMC_ARCH", var, "Hardcoded at build time");
|
||||
}
|
||||
if (var == "") {
|
||||
#if defined (__MINGW32__)
|
||||
@@ -491,16 +394,16 @@ string V3Options::getenvSYSTEMC_ARCH() {
|
||||
else if (VString::wildmatch(sysname.c_str(), "*cygwin*")) { var ="cygwin"; }
|
||||
else { var = "linux"; }
|
||||
#endif
|
||||
setenvStr("SYSTEMC_ARCH", var,"From sysname '"+sysname+"'");
|
||||
V3Os::setenvStr("SYSTEMC_ARCH", var,"From sysname '"+sysname+"'");
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
string V3Options::getenvSYSTEMC_INCLUDE() {
|
||||
string var = getenvStr("SYSTEMC_INCLUDE","");
|
||||
string var = V3Os::getenvStr("SYSTEMC_INCLUDE","");
|
||||
if (var == "" && string(DEFENV_SYSTEMC_INCLUDE) != "") {
|
||||
var = DEFENV_SYSTEMC_INCLUDE;
|
||||
setenvStr("SYSTEMC_INCLUDE", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("SYSTEMC_INCLUDE", var, "Hardcoded at build time");
|
||||
}
|
||||
if (var == "") {
|
||||
string sc = getenvSYSTEMC();
|
||||
@@ -517,10 +420,10 @@ string V3Options::getenvSYSTEMC_INCLUDE() {
|
||||
}
|
||||
|
||||
string V3Options::getenvSYSTEMC_LIBDIR() {
|
||||
string var = getenvStr("SYSTEMC_LIBDIR","");
|
||||
string var = V3Os::getenvStr("SYSTEMC_LIBDIR","");
|
||||
if (var == "" && string(DEFENV_SYSTEMC_LIBDIR) != "") {
|
||||
var = DEFENV_SYSTEMC_LIBDIR;
|
||||
setenvStr("SYSTEMC_LIBDIR", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("SYSTEMC_LIBDIR", var, "Hardcoded at build time");
|
||||
}
|
||||
if (var == "") {
|
||||
string sc = getenvSYSTEMC();
|
||||
@@ -546,26 +449,26 @@ string V3Options::getenvSYSTEMPERL() {
|
||||
|
||||
string V3Options::getenvSYSTEMPERLGuts() {
|
||||
// Get SYSTEMPERL when SYSTEMPERL_INCLUDE has already been tested
|
||||
string var = getenvStr("SYSTEMPERL","");
|
||||
string var = V3Os::getenvStr("SYSTEMPERL","");
|
||||
if (var == "" && string(DEFENV_SYSTEMPERL) != "") {
|
||||
var = DEFENV_SYSTEMPERL;
|
||||
setenvStr("SYSTEMPERL", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("SYSTEMPERL", var, "Hardcoded at build time");
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
string V3Options::getenvSYSTEMPERL_INCLUDE() {
|
||||
string var = getenvStr("SYSTEMPERL_INCLUDE","");
|
||||
string var = V3Os::getenvStr("SYSTEMPERL_INCLUDE","");
|
||||
if (var == "") {
|
||||
string sp_src = V3Options::getenvSYSTEMPERLGuts()+"/src";
|
||||
if (V3Options::fileStatNormal(sp_src+"/systemperl.h")) {
|
||||
var = sp_src;
|
||||
setenvStr ("SYSTEMPERL_INCLUDE", var, "From $SYSTEMPERL/src");
|
||||
V3Os::setenvStr ("SYSTEMPERL_INCLUDE", var, "From $SYSTEMPERL/src");
|
||||
} else if (string(DEFENV_SYSTEMPERL_INCLUDE) != "") {
|
||||
// Note if SYSTEMPERL is DEFENVed, then SYSTEMPERL_INCLUDE is also DEFENVed
|
||||
// So we don't need to sweat testing DEFENV_SYSTEMPERL also
|
||||
var = DEFENV_SYSTEMPERL_INCLUDE;
|
||||
setenvStr("SYSTEMPERL_INCLUDE", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("SYSTEMPERL_INCLUDE", var, "Hardcoded at build time");
|
||||
}
|
||||
}
|
||||
// Only correct or check it if we really need the value
|
||||
@@ -584,10 +487,10 @@ string V3Options::getenvSYSTEMPERL_INCLUDE() {
|
||||
}
|
||||
|
||||
string V3Options::getenvVERILATOR_ROOT() {
|
||||
string var = getenvStr("VERILATOR_ROOT","");
|
||||
string var = V3Os::getenvStr("VERILATOR_ROOT","");
|
||||
if (var == "" && string(DEFENV_VERILATOR_ROOT) != "") {
|
||||
var = DEFENV_VERILATOR_ROOT;
|
||||
setenvStr("VERILATOR_ROOT", var, "Hardcoded at build time");
|
||||
V3Os::setenvStr("VERILATOR_ROOT", var, "Hardcoded at build time");
|
||||
}
|
||||
if (var == "") {
|
||||
v3fatal("$VERILATOR_ROOT needs to be in environment\n");
|
||||
@@ -639,7 +542,7 @@ void V3Options::parseOpts (FileLine* fl, int argc, char** argv) {
|
||||
|
||||
// Default prefix to the filename
|
||||
if (prefix()=="" && topModule()!="") m_prefix = string("V")+topModule();
|
||||
if (prefix()=="" && vFilesList.size()>=1) m_prefix = string("V")+filenameNonExt(*(vFilesList.begin()));
|
||||
if (prefix()=="" && vFilesList.size()>=1) m_prefix = string("V")+V3Os::filenameNonExt(*(vFilesList.begin()));
|
||||
if (modPrefix()=="") m_modPrefix = prefix();
|
||||
|
||||
// Find files in makedir
|
||||
@@ -831,6 +734,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
m_dumpTree = atoi(argv[i]);
|
||||
}
|
||||
else if ( !strncmp (sw, "-dump-treei-", strlen("-dump-treei-"))) {
|
||||
const char* src = sw+strlen("-dump-treei-");
|
||||
shift;
|
||||
setDumpTreeLevel(src, atoi(argv[i]));
|
||||
}
|
||||
else if ( !strcmp (sw, "-error-limit") && (i+1)<argc ) {
|
||||
shift;
|
||||
V3Error::errorLimit(atoi(argv[i]));
|
||||
@@ -910,6 +818,14 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
V3Options::addLibraryFile(parseFileArg(optdir,argv[i]));
|
||||
}
|
||||
else if ( !strcmp (sw, "-clk") && (i+1)<argc ) {
|
||||
shift;
|
||||
V3Options::addClocker(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-no-clk") && (i+1)<argc ) {
|
||||
shift;
|
||||
V3Options::addNoClocker(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-V") ) {
|
||||
showVersion(true);
|
||||
exit(0);
|
||||
@@ -1126,7 +1042,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
|
||||
}
|
||||
|
||||
// Path
|
||||
string optdir = (rel ? V3Options::filenameDir(filename) : ".");
|
||||
string optdir = (rel ? V3Os::filenameDir(filename) : ".");
|
||||
|
||||
// Convert to argv style arg list and parse them
|
||||
char* argv [args.size()+1];
|
||||
@@ -1139,8 +1055,8 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
|
||||
//======================================================================
|
||||
|
||||
string V3Options::parseFileArg(const string& optdir, const string& relfilename) {
|
||||
string filename = V3Options::filenameSubstitute(relfilename);
|
||||
if (optdir != "." && filenameIsRel(filename)) {
|
||||
string filename = V3Os::filenameSubstitute(relfilename);
|
||||
if (optdir != "." && V3Os::filenameIsRel(filename)) {
|
||||
filename = optdir + "/" + filename;
|
||||
}
|
||||
return filename;
|
||||
@@ -1190,15 +1106,15 @@ void V3Options::showVersion(bool verbose) {
|
||||
|
||||
cout <<endl;
|
||||
cout << "Environment:\n";
|
||||
cout << " PERL = " << getenvStr("PERL","")<<endl;
|
||||
cout << " SYSTEMC = " << getenvStr("SYSTEMC","")<<endl;
|
||||
cout << " SYSTEMC_ARCH = " << getenvStr("SYSTEMC_ARCH","")<<endl;
|
||||
cout << " SYSTEMC_INCLUDE = " << getenvStr("SYSTEMC_INCLUDE","")<<endl;
|
||||
cout << " SYSTEMC_LIBDIR = " << getenvStr("SYSTEMC_LIBDIR","")<<endl;
|
||||
cout << " SYSTEMPERL = " << getenvStr("SYSTEMPERL","")<<endl;
|
||||
cout << " SYSTEMPERL_INCLUDE = " << getenvStr("SYSTEMPERL_INCLUDE","")<<endl;
|
||||
cout << " VERILATOR_ROOT = " << getenvStr("VERILATOR_ROOT","")<<endl;
|
||||
cout << " VERILATOR_BIN = " << getenvStr("VERILATOR_BIN","")<<endl; // wrapper uses this
|
||||
cout << " PERL = " << V3Os::getenvStr("PERL","")<<endl;
|
||||
cout << " SYSTEMC = " << V3Os::getenvStr("SYSTEMC","")<<endl;
|
||||
cout << " SYSTEMC_ARCH = " << V3Os::getenvStr("SYSTEMC_ARCH","")<<endl;
|
||||
cout << " SYSTEMC_INCLUDE = " << V3Os::getenvStr("SYSTEMC_INCLUDE","")<<endl;
|
||||
cout << " SYSTEMC_LIBDIR = " << V3Os::getenvStr("SYSTEMC_LIBDIR","")<<endl;
|
||||
cout << " SYSTEMPERL = " << V3Os::getenvStr("SYSTEMPERL","")<<endl;
|
||||
cout << " SYSTEMPERL_INCLUDE = " << V3Os::getenvStr("SYSTEMPERL_INCLUDE","")<<endl;
|
||||
cout << " VERILATOR_ROOT = " << V3Os::getenvStr("VERILATOR_ROOT","")<<endl;
|
||||
cout << " VERILATOR_BIN = " << V3Os::getenvStr("VERILATOR_BIN","")<<endl; // wrapper uses this
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
@@ -1288,7 +1204,7 @@ V3Options::~V3Options() {
|
||||
|
||||
void V3Options::setDebugMode(int level) {
|
||||
V3Error::debugDefault(level);
|
||||
if (!m_dumpTree) m_dumpTree = true; // Don't override if already set.
|
||||
if (!m_dumpTree) m_dumpTree = 3; // Don't override if already set.
|
||||
m_stats = true;
|
||||
m_debugCheck = true;
|
||||
cout << "Starting "<<version()<<endl;
|
||||
@@ -1306,7 +1222,7 @@ void V3Options::setDebugSrcLevel(const string& srcfile, int level) {
|
||||
int V3Options::debugSrcLevel(const string& srcfile_path, int default_level) {
|
||||
// For simplicity, calling functions can just use __FILE__ for srcfile.
|
||||
// That means though we need to cleanup the filename from ../Foo.cpp -> Foo
|
||||
string srcfile = V3Options::filenameNonDirExt(srcfile_path);
|
||||
string srcfile = V3Os::filenameNonDirExt(srcfile_path);
|
||||
DebugSrcMap::iterator iter = m_debugSrcs.find(srcfile);
|
||||
if (iter!=m_debugSrcs.end()) {
|
||||
return iter->second;
|
||||
@@ -1315,6 +1231,27 @@ int V3Options::debugSrcLevel(const string& srcfile_path, int default_level) {
|
||||
}
|
||||
}
|
||||
|
||||
void V3Options::setDumpTreeLevel(const string& srcfile, int level) {
|
||||
DebugSrcMap::iterator iter = m_dumpTrees.find(srcfile);
|
||||
if (iter!=m_dumpTrees.end()) {
|
||||
iter->second = level;
|
||||
} else {
|
||||
m_dumpTrees.insert(make_pair(srcfile,level));
|
||||
}
|
||||
}
|
||||
|
||||
int V3Options::dumpTreeLevel(const string& srcfile_path) {
|
||||
// For simplicity, calling functions can just use __FILE__ for srcfile.
|
||||
// That means though we need to cleanup the filename from ../Foo.cpp -> Foo
|
||||
string srcfile = V3Os::filenameNonDirExt(srcfile_path);
|
||||
DebugSrcMap::iterator iter = m_dumpTrees.find(srcfile);
|
||||
if (iter!=m_dumpTrees.end()) {
|
||||
return iter->second;
|
||||
} else {
|
||||
return m_dumpTree;
|
||||
}
|
||||
}
|
||||
|
||||
void V3Options::optimize(int level) {
|
||||
// Set all optimizations to on/off
|
||||
bool flag = level > 0;
|
||||
|
||||
+9
-12
@@ -53,8 +53,11 @@ class V3Options {
|
||||
V3StringSet m_ldLibs; // argument: user LDFLAGS
|
||||
V3StringSet m_futures; // argument: -Wfuture- list
|
||||
V3StringSet m_libraryFiles; // argument: Verilog -v files
|
||||
V3StringSet m_clockers; // argument: Verilog -clk signals
|
||||
V3StringSet m_noClockers; // argument: Verilog -noclk signals
|
||||
V3StringList m_vFiles; // argument: Verilog files to read
|
||||
DebugSrcMap m_debugSrcs; // argument: --debugi-<srcfile>=<level>
|
||||
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
||||
|
||||
bool m_preprocOnly; // main switch: -E
|
||||
bool m_makeDepend; // main switch: -MMD
|
||||
@@ -169,8 +172,6 @@ class V3Options {
|
||||
bool parseLangExt(const char* swp, const char* langswp, const V3LangCode& lc);
|
||||
string filePathCheckOneDir(const string& modname, const string& dirname);
|
||||
|
||||
static string getenvStr(const string& envvar, const string& defaultValue);
|
||||
static void setenvStr(const string& envvar, const string& value, const string& why);
|
||||
static string getenvSYSTEMPERLGuts();
|
||||
|
||||
public:
|
||||
@@ -180,12 +181,16 @@ class V3Options {
|
||||
void setDebugMode(int level);
|
||||
void setDebugSrcLevel(const string& srcfile, int level);
|
||||
int debugSrcLevel(const string& srcfile, int default_level=V3Error::debugDefault());
|
||||
void setDumpTreeLevel(const string& srcfile, int level);
|
||||
int dumpTreeLevel(const string& srcfile);
|
||||
|
||||
// METHODS
|
||||
void addCppFile(const string& filename);
|
||||
void addCFlags(const string& filename);
|
||||
void addLdLibs(const string& filename);
|
||||
void addLibraryFile(const string& filename);
|
||||
void addClocker(const string& signame);
|
||||
void addNoClocker(const string& signame);
|
||||
void addVFile(const string& filename);
|
||||
|
||||
// ACCESSORS (options)
|
||||
@@ -272,6 +277,8 @@ class V3Options {
|
||||
|
||||
bool isFuture(const string& flag) const;
|
||||
bool isLibraryFile(const string& filename) const;
|
||||
bool isClocker(const string& signame) const;
|
||||
bool isNoClocker(const string& signame) const;
|
||||
|
||||
// ACCESSORS (optimization options)
|
||||
bool oAcycSimp() const { return m_oAcycSimp; }
|
||||
@@ -306,16 +313,6 @@ class V3Options {
|
||||
void parseOptsList (FileLine* fl, const string& optdir, int argc, char** argv);
|
||||
void parseOptsFile (FileLine* fl, const string& filename, bool rel);
|
||||
|
||||
// METHODS (generic file utilities)
|
||||
static string filenameFromDirBase (const string& dir, const string& basename);
|
||||
static string filenameNonDir (const string& filename); ///< Return non-directory part of filename
|
||||
static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename
|
||||
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
|
||||
static string filenameDir (const string& filename); ///< Return directory part of filename
|
||||
static string filenameSubstitute (const string& filename); ///< Return filename with env vars removed
|
||||
static bool filenameIsRel (const string& filename); ///< True if relative
|
||||
static void unlinkRegexp(const string& dir, const string& regexp);
|
||||
|
||||
// METHODS (environment)
|
||||
// Most of these may be built into the executable with --enable-defenv,
|
||||
// see the README. If adding new variables, also see src/Makefile_obj.in
|
||||
|
||||
+211
-1
@@ -241,6 +241,185 @@ struct OrderVarFanoutCmp {
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// The class is used for propagating the clocker attribute for further
|
||||
// avoiding marking clock signals as circular.
|
||||
// Transformation:
|
||||
// while (newClockerMarked)
|
||||
// check all assignments
|
||||
// if RHS is marked as clocker:
|
||||
// mark LHS as clocker as well.
|
||||
// newClockerMarked = true;
|
||||
//
|
||||
// In addition it also check whether clock and data signals are mixed, and
|
||||
// produce a CLKDATA warning if so.
|
||||
//
|
||||
class OrderClkMarkVisitor : public AstNVisitor {
|
||||
private:
|
||||
bool m_hasClk; // flag indicating whether there is clock signal on rhs
|
||||
bool m_inClocked; // Currently inside a sequential block
|
||||
bool m_newClkMarked; // Flag for deciding whether a new run is needed
|
||||
bool m_inAss; // Currently inside of a assignment
|
||||
int m_childClkWidth; // If in hasClk, width of clock signal in child
|
||||
int m_rightClkWidth; // Clk width on the RHS
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
m_hasClk = false;
|
||||
if (AstVarRef* varrefp = nodep->rhsp()->castVarRef()) {
|
||||
this->visit(varrefp, NULL);
|
||||
m_rightClkWidth = varrefp->width();
|
||||
if (varrefp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
|
||||
if (m_inClocked) {
|
||||
varrefp->v3warn(CLKDATA, "Clock used as data (on rhs of assignment) in sequential block "<<varrefp<<endl);
|
||||
} else {
|
||||
m_hasClk = true;
|
||||
UINFO(5, "node is already marked as clocker "<<varrefp<<endl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_inAss = true;
|
||||
m_childClkWidth = 0;
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
m_rightClkWidth = m_childClkWidth;
|
||||
m_inAss = false;
|
||||
}
|
||||
|
||||
// do the marking
|
||||
if (m_hasClk) {
|
||||
if (nodep->lhsp()->width() > m_rightClkWidth) {
|
||||
nodep->v3warn(CLKDATA, "Clock is assigned to part of data signal "<< nodep->lhsp()<<endl);
|
||||
UINFO(4, "CLKDATA: lhs with width " << nodep->lhsp()->width() <<endl);
|
||||
UINFO(4, " but rhs clock with width " << m_rightClkWidth <<endl);
|
||||
return; // skip the marking
|
||||
}
|
||||
|
||||
AstVarRef* lhsp = nodep->lhsp()->castVarRef();
|
||||
if (lhsp && (lhsp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_UNKNOWN)) {
|
||||
lhsp->varp()->attrClocker(AstVarAttrClocker::CLOCKER_YES); // mark as clocker
|
||||
m_newClkMarked = true; // enable a further run since new clocker is marked
|
||||
UINFO(5, "node is newly marked as clocker by assignment "<<lhsp<<endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (m_inAss && nodep->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
|
||||
if (m_inClocked) {
|
||||
nodep->v3warn(CLKDATA, "Clock used as data (on rhs of assignment) in sequential block "<<nodep->prettyName());
|
||||
} else {
|
||||
m_hasClk = true;
|
||||
m_childClkWidth = nodep->width(); // Pass up
|
||||
UINFO(5, "node is already marked as clocker "<<nodep<<endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConcat* nodep, AstNUser* wp) {
|
||||
if (m_inAss) {
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
int lw = m_childClkWidth;
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
int rw = m_childClkWidth;
|
||||
m_childClkWidth = lw + rw; // Pass up
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeSel* nodep, AstNUser* wp) {
|
||||
if (m_inAss) {
|
||||
nodep->iterateChildren(*this);
|
||||
// Pass up result width
|
||||
if (m_childClkWidth > nodep->width()) m_childClkWidth = nodep->width();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||
if (m_inAss) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_childClkWidth > nodep->width()) m_childClkWidth = nodep->width();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||
if (m_inAss) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->rhsp()->castConst()) {
|
||||
m_childClkWidth = m_childClkWidth * nodep->rhsp()->castConst()->toUInt();
|
||||
} else {
|
||||
m_childClkWidth = nodep->width(); // can not check in this case.
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstActive* nodep, AstNUser*) {
|
||||
m_inClocked = nodep->hasClocked();
|
||||
nodep->iterateChildren(*this);
|
||||
m_inClocked = false;
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
OrderClkMarkVisitor(AstNode* nodep) {
|
||||
m_hasClk = false;
|
||||
m_inClocked = false;
|
||||
m_inAss = false;
|
||||
m_childClkWidth = 0;
|
||||
m_rightClkWidth = 0;
|
||||
do {
|
||||
m_newClkMarked = false;
|
||||
nodep->accept(*this);
|
||||
} while (m_newClkMarked);
|
||||
}
|
||||
virtual ~OrderClkMarkVisitor() {}
|
||||
};
|
||||
|
||||
|
||||
//######################################################################
|
||||
// The class used to check if the assignment has clocker inside.
|
||||
class OrderClkAssVisitor : public AstNVisitor {
|
||||
private:
|
||||
bool m_clkAss; // There is signals marked as clocker in the assignment
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
if (AstVarRef* varrefp = nodep->lhsp()->castVarRef() )
|
||||
if (varrefp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
|
||||
m_clkAss = true;
|
||||
UINFO(6, "node was marked as clocker "<<varrefp<<endl);
|
||||
}
|
||||
nodep->rhsp()->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (nodep->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
|
||||
m_clkAss = true;
|
||||
UINFO(6, "node was marked as clocker "<<nodep<<endl);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
OrderClkAssVisitor(AstNode* nodep) {
|
||||
m_clkAss = false;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~OrderClkAssVisitor() {}
|
||||
|
||||
// METHODS
|
||||
bool isClkAss() {return m_clkAss;}
|
||||
};
|
||||
|
||||
|
||||
//######################################################################
|
||||
// Order class functions
|
||||
@@ -280,6 +459,7 @@ private:
|
||||
AstActive* m_activep; // Current activation block
|
||||
bool m_inSenTree; // Underneath AstSenItem; any varrefs are clocks
|
||||
bool m_inClocked; // Underneath clocked block
|
||||
bool m_inClkAss; // Underneath AstAssign
|
||||
bool m_inPre; // Underneath AstAssignPre
|
||||
bool m_inPost; // Underneath AstAssignPost
|
||||
OrderLogicVertex* m_activeSenVxp; // Sensitivity vertex
|
||||
@@ -356,6 +536,15 @@ private:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool isClkAssign(AstNodeAssign* nodep) {
|
||||
if (AstVarRef* varrefp = nodep->lhsp()->castVarRef()) {
|
||||
if (varrefp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void process();
|
||||
void processCircular();
|
||||
typedef deque<OrderEitherVertex*> VertexVec;
|
||||
@@ -650,6 +839,10 @@ private:
|
||||
// clock_enable attribute: user's worring about it for us
|
||||
con = false;
|
||||
}
|
||||
if (m_inClkAss && (varscp->varp()->attrClocker()) != AstVarAttrClocker::CLOCKER_YES) {
|
||||
con = false;
|
||||
UINFO(4, "nodep used as clock_enable "<<varscp<<" in "<<m_logicVxp->nodep()<<endl);
|
||||
}
|
||||
}
|
||||
if (gen) varscp->user4(varscp->user4() | VU_GEN);
|
||||
if (con) varscp->user4(varscp->user4() | VU_CON);
|
||||
@@ -672,7 +865,12 @@ private:
|
||||
<< varVxp << endl);
|
||||
varVxp->isDelayed(true);
|
||||
} else {
|
||||
new OrderComboCutEdge(&m_graph, m_logicVxp, varVxp);
|
||||
// If the lhs is a clocker, avoid marking that as circular by
|
||||
// putting a hard edge instead of normal cuttable
|
||||
if (varscp->varp()->attrClocker() == AstVarAttrClocker::CLOCKER_YES)
|
||||
new OrderEdge(&m_graph, m_logicVxp, varVxp, WEIGHT_NORMAL);
|
||||
else
|
||||
new OrderComboCutEdge(&m_graph, m_logicVxp, varVxp);
|
||||
}
|
||||
// For m_inPost:
|
||||
// Add edge consumed_var_POST->logic_vertex
|
||||
@@ -758,17 +956,26 @@ private:
|
||||
iterateNewStmt(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||
OrderClkAssVisitor visitor(nodep);
|
||||
m_inClkAss = visitor.isClkAss();
|
||||
iterateNewStmt(nodep);
|
||||
m_inClkAss = false;
|
||||
}
|
||||
virtual void visit(AstAssignPre* nodep, AstNUser*) {
|
||||
OrderClkAssVisitor visitor(nodep);
|
||||
m_inClkAss = visitor.isClkAss();
|
||||
m_inPre = true;
|
||||
iterateNewStmt(nodep);
|
||||
m_inPre = false;
|
||||
m_inClkAss = false;
|
||||
}
|
||||
virtual void visit(AstAssignPost* nodep, AstNUser*) {
|
||||
OrderClkAssVisitor visitor(nodep);
|
||||
m_inClkAss = visitor.isClkAss();
|
||||
m_inPost = true;
|
||||
iterateNewStmt(nodep);
|
||||
m_inPost = false;
|
||||
m_inClkAss = false;
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep, AstNUser*) {
|
||||
iterateNewStmt(nodep);
|
||||
@@ -799,6 +1006,7 @@ public:
|
||||
m_activep = NULL;
|
||||
m_inSenTree = false;
|
||||
m_inClocked = false;
|
||||
m_inClkAss = false;
|
||||
m_inPre = m_inPost = false;
|
||||
m_comboDomainp = NULL;
|
||||
m_deleteDomainp = NULL;
|
||||
@@ -1449,6 +1657,8 @@ void OrderVisitor::process() {
|
||||
|
||||
void V3Order::orderAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
OrderClkMarkVisitor markVisitor(nodep);
|
||||
OrderVisitor visitor;
|
||||
visitor.main(nodep);
|
||||
V3Global::dumpCheckGlobalTree("order.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Os-specific function wrapper
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2015 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.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <cstdarg>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
#if defined(WIN32) || defined(__MINGW32__)
|
||||
# include <direct.h> // mkdir
|
||||
#endif
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Os.h"
|
||||
|
||||
//######################################################################
|
||||
// Environment
|
||||
|
||||
string V3Os::getenvStr(const string& envvar, const string& defaultValue) {
|
||||
if (const char* envvalue = getenv(envvar.c_str())) {
|
||||
return envvalue;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
void V3Os::setenvStr(const string& envvar, const string& value, const string& why) {
|
||||
if (why != "") {
|
||||
UINFO(1,"export "<<envvar<<"="<<value<<" # "<<why<<endl);
|
||||
} else {
|
||||
UINFO(1,"export "<<envvar<<"="<<value<<endl);
|
||||
}
|
||||
#if defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
|
||||
setenv(envvar.c_str(),value.c_str(),true);
|
||||
#else
|
||||
//setenv() replaced by putenv() in MinGW/Solaris environment. Prototype is different
|
||||
//putenv() requires NAME=VALUE format
|
||||
string vareq = envvar + "=" + value;
|
||||
putenv(const_cast<char*>(vareq.c_str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Generic filename utilities
|
||||
|
||||
string V3Os::filenameFromDirBase (const string& dir, const string& basename) {
|
||||
// Don't return ./{filename} because if filename was absolute, that makes it relative
|
||||
if (dir == ".") return basename;
|
||||
else return dir+"/"+basename;
|
||||
}
|
||||
|
||||
string V3Os::filenameDir (const string& filename) {
|
||||
string::size_type pos;
|
||||
if ((pos = filename.rfind("/")) != string::npos) {
|
||||
return filename.substr(0,pos);
|
||||
} else {
|
||||
return ".";
|
||||
}
|
||||
}
|
||||
|
||||
string V3Os::filenameNonDir (const string& filename) {
|
||||
string::size_type pos;
|
||||
if ((pos = filename.rfind("/")) != string::npos) {
|
||||
return filename.substr(pos+1);
|
||||
} else {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
string V3Os::filenameNonExt (const string& filename) {
|
||||
string base = filenameNonDir(filename);
|
||||
string::size_type pos;
|
||||
if ((pos = base.find(".")) != string::npos) {
|
||||
base.erase(pos);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
string V3Os::filenameSubstitute (const string& filename) {
|
||||
string out;
|
||||
enum { NONE, PAREN, CURLY } brackets = NONE;
|
||||
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
|
||||
if ((filename[pos] == '$') && (pos+1 < filename.length())) {
|
||||
switch (filename[pos+1]) {
|
||||
case '{': brackets = CURLY; break;
|
||||
case '(': brackets = PAREN; break;
|
||||
default: brackets = NONE; break;
|
||||
}
|
||||
if (brackets != NONE) pos = pos+1;
|
||||
string::size_type endpos = pos+1;
|
||||
while (((endpos+1) < filename.length()) &&
|
||||
(((brackets==NONE) && (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) ||
|
||||
((brackets==CURLY) && (filename[endpos+1]!='}')) ||
|
||||
((brackets==PAREN) && (filename[endpos+1]!=')'))))
|
||||
++endpos;
|
||||
// Catch bracket errors
|
||||
if (((brackets==CURLY) && (filename[endpos+1]!='}')) ||
|
||||
((brackets==PAREN) && (filename[endpos+1]!=')'))) {
|
||||
v3fatal("Unmatched brackets in variable substitution in file: "+filename);
|
||||
}
|
||||
string envvar = filename.substr(pos+1,endpos-pos);
|
||||
const char* envvalue = NULL;
|
||||
if (envvar != "") envvalue = getenv(envvar.c_str());
|
||||
if (envvalue) {
|
||||
out += envvalue;
|
||||
if (brackets==NONE) pos = endpos;
|
||||
else pos = endpos+1;
|
||||
} else {
|
||||
out += filename[pos]; // *pos == '$'
|
||||
}
|
||||
} else {
|
||||
out += filename[pos];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
bool V3Os::filenameIsRel(const string& filename) {
|
||||
return (filename.length()>0 && filename[0] != '/');
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Directory utilities
|
||||
|
||||
void V3Os::createDir(const string& dirname) {
|
||||
#if defined(_WIN32) || defined(__MINGW32__)
|
||||
mkdir(dirname.c_str());
|
||||
#else
|
||||
mkdir(dirname.c_str(), 0777);
|
||||
#endif
|
||||
}
|
||||
|
||||
void V3Os::unlinkRegexp(const string& dir, const string& regexp) {
|
||||
if (DIR* dirp = opendir(dir.c_str())) {
|
||||
while (struct dirent* direntp = readdir(dirp)) {
|
||||
if (VString::wildmatch(direntp->d_name, regexp.c_str())) {
|
||||
string fullname = dir + "/" + string(direntp->d_name);
|
||||
unlink (fullname.c_str());
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Os-specific function wrapper
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2015 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 _V3OS_H_
|
||||
#define _V3OS_H_ 1
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include <cstdio>
|
||||
|
||||
//============================================================================
|
||||
// V3Os: OS static class
|
||||
|
||||
class V3Os {
|
||||
public:
|
||||
// METHODS (environment)
|
||||
static string getenvStr(const string& envvar, const string& defaultValue);
|
||||
static void setenvStr(const string& envvar, const string& value, const string& why);
|
||||
|
||||
// METHODS (generic filename utilities)
|
||||
static string filenameFromDirBase (const string& dir, const string& basename);
|
||||
static string filenameNonDir (const string& filename); ///< Return non-directory part of filename
|
||||
static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename
|
||||
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
|
||||
static string filenameDir (const string& filename); ///< Return directory part of filename
|
||||
static string filenameSubstitute (const string& filename); ///< Return filename with env vars removed
|
||||
static bool filenameIsRel (const string& filename); ///< True if relative
|
||||
|
||||
// METHODS (directory utilities)
|
||||
static void createDir(const string& dirname);
|
||||
static void unlinkRegexp(const string& dir, const string& regexp);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
@@ -570,4 +570,5 @@ void ParamVisitor::visitCell(AstCell* nodep) {
|
||||
void V3Param::param(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ParamVisitor visitor (rootp);
|
||||
V3Global::dumpCheckGlobalTree("param.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
+2
-1
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "V3Error.h"
|
||||
#include "V3Global.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3File.h"
|
||||
#include "V3ParseImp.h"
|
||||
@@ -91,7 +92,7 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) {
|
||||
|
||||
void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
|
||||
const string& errmsg) { // "" for no error, make fake node
|
||||
string modname = V3Options::filenameNonExt(modfilename);
|
||||
string modname = V3Os::filenameNonExt(modfilename);
|
||||
|
||||
UINFO(2,__FUNCTION__<<": "<<modname<<(inLibrary?" [LIB]":"")<<endl);
|
||||
m_fileline = new FileLine(fileline);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// Authors: Wilson Snyder
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2000-2015 by Wilson Snyder. This program is free software;
|
||||
|
||||
+3
-3
@@ -124,16 +124,16 @@ drop [\032]
|
||||
/* Protected blocks */
|
||||
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
|
||||
<PRTMODE><<EOF>> { linenoInc(); yyerrorf("EOF in `protected"); yyleng=0; yyterminate(); }
|
||||
<PRTMODE>{crnl} { linenoInc(); yymore(); }
|
||||
<PRTMODE>{crnl} { linenoInc(); return VP_TEXT; }
|
||||
<PRTMODE>. { yymore(); }
|
||||
<PRTMODE>"`endprotected" { yy_pop_state(); return (VP_TEXT); }
|
||||
<PRTMODE>"`endprotected" { yy_pop_state(); return VP_TEXT; }
|
||||
|
||||
/* Pass-through include <> filenames */
|
||||
<INCMODE><<EOF>> { linenoInc(); yyerrorf("EOF in unterminated include filename"); yyleng=0; yyterminate(); }
|
||||
<INCMODE>{crnl} { linenoInc(); yyerrorf("Unterminated include filename"); BEGIN(INITIAL); }
|
||||
<INCMODE>[^\>\\] { yymore(); }
|
||||
<INCMODE>{backslash}. { yymore(); }
|
||||
<INCMODE>[\>] { yy_pop_state(); return (VP_STRING); }
|
||||
<INCMODE>[\>] { yy_pop_state(); return VP_STRING; }
|
||||
|
||||
/* Reading definition formal parenthesis (or not) to begin formal arguments */
|
||||
/* Note '(' must IMMEDIATELY follow definition name */
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// Authors: Wilson Snyder
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2000-2015 by Wilson Snyder. This program is free software;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
// Authors: Wilson Snyder
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2000-2015 by Wilson Snyder. This program is free software;
|
||||
|
||||
+2
-1
@@ -124,7 +124,7 @@ private:
|
||||
|
||||
bool assignNoTemp(AstNodeAssign* nodep) {
|
||||
return (nodep->lhsp()->castVarRef()
|
||||
&& !nodep->lhsp()->castVarRef()->varp()->isSc()
|
||||
&& !AstVar::scVarRecurse(nodep->lhsp())
|
||||
&& nodep->rhsp()->castConst());
|
||||
}
|
||||
void checkNode(AstNode* nodep) {
|
||||
@@ -403,4 +403,5 @@ public:
|
||||
void V3Premit::premitAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
PremitVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("premit.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -243,6 +243,12 @@ private:
|
||||
UINFO(6," New scope "<<varscp<<endl);
|
||||
if (m_aboveCellp && !m_aboveCellp->isTrace()) varscp->trace(false);
|
||||
nodep->user1p(varscp);
|
||||
if (v3Global.opt.isClocker(varscp->prettyName())) {
|
||||
nodep->attrClocker(AstVarAttrClocker::CLOCKER_YES);
|
||||
}
|
||||
if (v3Global.opt.isNoClocker(varscp->prettyName())) {
|
||||
nodep->attrClocker(AstVarAttrClocker::CLOCKER_NO);
|
||||
}
|
||||
if (!m_scopep) nodep->v3fatalSrc("No scope for var");
|
||||
m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp));
|
||||
m_scopep->addVarp(varscp);
|
||||
@@ -410,4 +416,5 @@ void V3Scope::scopeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ScopeVisitor visitor (nodep);
|
||||
ScopeCleanupVisitor cleanVisitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("scope.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -501,4 +501,5 @@ public:
|
||||
void V3Slice::sliceAll(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SliceVisitor visitor(rootp);
|
||||
V3Global::dumpCheckGlobalTree("slices.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -578,8 +578,10 @@ public:
|
||||
void V3Split::splitReorderAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SplitVisitor visitor (nodep, true);
|
||||
V3Global::dumpCheckGlobalTree("reorder.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
void V3Split::splitAlwaysAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SplitVisitor visitor (nodep, false);
|
||||
V3Global::dumpCheckGlobalTree("split.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -216,4 +216,5 @@ public:
|
||||
void V3SplitAs::splitAsAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SplitAsVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("splitas.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -401,4 +401,5 @@ public:
|
||||
void V3Subst::substituteAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
SubstVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("subst.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -466,4 +466,5 @@ void TableSimulateVisitor::varRefCb(AstVarRef* nodep) {
|
||||
void V3Table::tableAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
TableVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("table.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -1294,4 +1294,5 @@ void V3Task::taskAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
TaskStateVisitor visitors (nodep);
|
||||
TaskVisitor visitor (nodep, &visitors);
|
||||
V3Global::dumpCheckGlobalTree("task.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -709,4 +709,5 @@ public:
|
||||
void V3Trace::traceAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
TraceVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("trace.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -329,4 +329,5 @@ public:
|
||||
void V3TraceDecl::traceDeclAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
TraceDeclVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("tracedecl.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -1323,4 +1323,5 @@ public:
|
||||
void V3Tristate::tristateAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
TristateVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("tristate.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -475,4 +475,5 @@ public:
|
||||
void V3Unknown::unknownAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
UnknownVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("unknown.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -463,6 +463,7 @@ public:
|
||||
void V3Unroll::unrollAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
UnrollVisitor visitor (nodep, false, "");
|
||||
V3Global::dumpCheckGlobalTree("unroll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Unroll::unrollGen(AstNodeFor* nodep, string beginName) {
|
||||
|
||||
@@ -3483,6 +3483,7 @@ void V3Width::width(AstNetlist* nodep) {
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
WidthRemoveVisitor rvisitor;
|
||||
(void)rvisitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("width.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
//! Single node parameter propagation
|
||||
@@ -3520,4 +3521,5 @@ AstNode* V3Width::widthGenerateParamsEdit(
|
||||
void V3Width::widthCommit(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
WidthCommitVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("widthcommit.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
+5
-83
@@ -68,6 +68,7 @@
|
||||
#include "V3Localize.h"
|
||||
#include "V3Name.h"
|
||||
#include "V3Order.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3Param.h"
|
||||
#include "V3Parse.h"
|
||||
#include "V3ParseSym.h"
|
||||
@@ -148,30 +149,22 @@ void V3Global::dumpCheckGlobalTree(const string& filename, int newNumber, bool d
|
||||
//######################################################################
|
||||
|
||||
void process () {
|
||||
bool dumpMore = (v3Global.opt.dumpTree() >= 9);
|
||||
|
||||
// Sort modules by level so later algorithms don't need to care
|
||||
V3LinkLevel::modSortByLevel();
|
||||
V3Global::dumpCheckGlobalTree("cells.tree");
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
// Convert parseref's to varrefs, and other directly post parsing fixups
|
||||
V3LinkParse::linkParse(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("linkparse.tree", 0, dumpMore);
|
||||
// Cross-link signal names
|
||||
// Cross-link dotted hierarchical references
|
||||
V3LinkDot::linkDotPrimary(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, dumpMore);
|
||||
v3Global.checkTree(); // Force a check, as link is most likely place for problems
|
||||
// Correct state we couldn't know at parse time, repair SEL's
|
||||
V3LinkResolve::linkResolve(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("linkresolve.tree", 0, dumpMore);
|
||||
// Set Lvalue's in variable refs
|
||||
V3LinkLValue::linkLValue(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("linklvalue.tree", 0, dumpMore);
|
||||
// Convert return/continue/disable to jumps
|
||||
V3LinkJump::linkJump(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("link.tree");
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Link");
|
||||
@@ -179,19 +172,15 @@ void process () {
|
||||
// Remove parameters by cloning modules to de-parameterized versions
|
||||
// This requires some width calculations and constant propagation
|
||||
V3Param::param(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("param.tree", 0, dumpMore);
|
||||
V3LinkDot::linkDotParamed(v3Global.rootp()); // Cleanup as made new modules
|
||||
V3Global::dumpCheckGlobalTree("paramlink.tree");
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
// Remove any modules that were parameterized and are no longer referenced.
|
||||
V3Dead::deadifyModules(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("dead.tree", 0, dumpMore);
|
||||
v3Global.checkTree();
|
||||
|
||||
// Calculate and check widths, edit tree to TRUNC/EXTRACT any width mismatches
|
||||
V3Width::width(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("width.tree");
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
@@ -199,19 +188,16 @@ void process () {
|
||||
V3Width::widthCommit(v3Global.rootp());
|
||||
v3Global.assertDTypesResolved(true);
|
||||
v3Global.assertWidthsMatch(true);
|
||||
V3Global::dumpCheckGlobalTree("widthcommit.tree", 0, dumpMore);
|
||||
|
||||
// Coverage insertion
|
||||
// Before we do dead code elimination and inlining, or we'll lose it.
|
||||
if (v3Global.opt.coverage()) {
|
||||
V3Coverage::coverage(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("coverage.tree");
|
||||
}
|
||||
|
||||
// Push constants, but only true constants preserving liveness
|
||||
// so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..."
|
||||
V3Const::constifyAllLive(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Signal based lint checks, no change to structures
|
||||
// Must be before first constification pass drops dead code
|
||||
@@ -220,10 +206,8 @@ void process () {
|
||||
// Assertion insertion
|
||||
// After we've added block coverage, but before other nasty transforms
|
||||
V3AssertPre::assertPreAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("assertpre.tree");
|
||||
//
|
||||
V3Assert::assertAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("assert.tree");
|
||||
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Add top level wrapper with instance pointing to old top
|
||||
@@ -234,39 +218,32 @@ void process () {
|
||||
|
||||
// Propagate constants into expressions
|
||||
V3Const::constifyAllLint(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Remove cell arrays (must be between V3Width and scoping)
|
||||
V3Inst::dearrayAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("dearray.tree", 0, dumpMore);
|
||||
}
|
||||
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Expand inouts, stage 2
|
||||
// Also simplify pin connections to always be AssignWs in prep for V3Unknown
|
||||
V3Tristate::tristateAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("tristate.tree");
|
||||
|
||||
// Task inlining & pushing BEGINs names to variables/cells
|
||||
// Begin processing must be after Param, before module inlining
|
||||
V3Begin::debeginAll(v3Global.rootp()); // Flatten cell names, before inliner
|
||||
V3Global::dumpCheckGlobalTree("begin.tree");
|
||||
|
||||
// Move assignments from X into MODULE temps.
|
||||
// (Before flattening, so each new X variable is shared between all scopes of that module.)
|
||||
V3Unknown::unknownAll(v3Global.rootp());
|
||||
v3Global.constRemoveXs(true);
|
||||
V3Global::dumpCheckGlobalTree("unknown.tree");
|
||||
|
||||
// Module inlining
|
||||
// Cannot remove dead variables after this, as alias information for final
|
||||
// V3Scope's V3LinkDot is in the AstVar.
|
||||
if (v3Global.opt.oInline()) {
|
||||
V3Inline::inlineAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("inline.tree");
|
||||
V3LinkDot::linkDotArrayed(v3Global.rootp()); // Cleanup as made new modules
|
||||
V3Global::dumpCheckGlobalTree("linkdot.tree", 0, dumpMore);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,11 +251,9 @@ void process () {
|
||||
|
||||
// Initial const/dead to reduce work for ordering code
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
|
||||
v3Global.checkTree();
|
||||
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
v3Global.checkTree();
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
@@ -291,17 +266,13 @@ void process () {
|
||||
|
||||
// Convert instantiations to wassigns and always blocks
|
||||
V3Inst::instAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("inst.tree");
|
||||
|
||||
// Inst may have made lots of concats; fix them
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Flatten hierarchy, creating a SCOPE for each module's usage as a cell
|
||||
V3Scope::scopeAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("scope.tree");
|
||||
V3LinkDot::linkDotScope(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("linkdot.tree");
|
||||
}
|
||||
|
||||
//--SCOPE BASED OPTIMIZATIONS--------------
|
||||
@@ -309,87 +280,69 @@ void process () {
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Cleanup
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
v3Global.checkTree();
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Convert case statements to if() blocks. Must be after V3Unknown
|
||||
// Must be before V3Task so don't need to deal with task in case value compares
|
||||
V3Case::caseAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("case.tree");
|
||||
|
||||
// Inline all tasks
|
||||
V3Task::taskAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("task.tree");
|
||||
|
||||
// Add __PVT's
|
||||
// After V3Task so task internal variables will get renamed
|
||||
V3Name::nameAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("name.tree", 0, dumpMore);
|
||||
|
||||
// Loop unrolling & convert FORs to WHILEs
|
||||
V3Unroll::unrollAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("unroll.tree");
|
||||
|
||||
// Expand slices of arrays
|
||||
V3Slice::sliceAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("slices.tree");
|
||||
|
||||
// Push constants across variables and remove redundant assignments
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
if (v3Global.opt.oLife()) {
|
||||
V3Life::lifeAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("life.tree");
|
||||
}
|
||||
|
||||
// Make large low-fanin logic blocks into lookup tables
|
||||
// This should probably be done much later, once we have common logic elimination.
|
||||
if (!v3Global.opt.lintOnly() && v3Global.opt.oTable()) {
|
||||
V3Table::tableAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("table.tree");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
|
||||
V3Dead::deadifyDTypes(v3Global.rootp());
|
||||
v3Global.checkTree();
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Detect clock enables and mode into sensitives, and split always based on clocks
|
||||
// (so this is a good prelude to splitAlways.)
|
||||
if (v3Global.opt.oFlopGater()) {
|
||||
V3ClkGater::clkGaterAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("clkgater.tree");
|
||||
}
|
||||
|
||||
// Move assignments/sensitives into a SBLOCK for each unique sensitivity list
|
||||
// (May convert some ALWAYS to combo blocks, so should be before V3Gate step.)
|
||||
V3Active::activeAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("active.tree");
|
||||
|
||||
// Split single ALWAYS blocks into multiple blocks for better ordering chances
|
||||
if (v3Global.opt.oSplit()) {
|
||||
V3Split::splitAlwaysAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("split.tree", 0, dumpMore);
|
||||
}
|
||||
V3SplitAs::splitAsAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("splitas.tree");
|
||||
|
||||
// Create tracing sample points, before we start eliminating signals
|
||||
if (v3Global.opt.trace()) {
|
||||
V3TraceDecl::traceDeclAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("tracedecl.tree");
|
||||
}
|
||||
|
||||
// Gate-based logic elimination; eliminate signals and push constant across cell boundaries
|
||||
// Instant propagation makes lots-o-constant reduction possibilities.
|
||||
if (v3Global.opt.oGate()) {
|
||||
V3Gate::gateAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("gate.tree");
|
||||
// V3Gate calls constant propagation itself.
|
||||
} else {
|
||||
v3info("Command Line disabled gate optimization with -Og/-O0. This may cause ordering problems.");
|
||||
@@ -398,14 +351,11 @@ void process () {
|
||||
// Combine COVERINCs with duplicate terms
|
||||
if (v3Global.opt.coverage()) {
|
||||
V3CoverageJoin::coverageJoin(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin.tree");
|
||||
}
|
||||
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Clock domain crossing analysis
|
||||
if (v3Global.opt.cdc()) {
|
||||
@@ -417,32 +367,26 @@ void process () {
|
||||
// Reorder assignments in pipelined blocks
|
||||
if (v3Global.opt.oReorder()) {
|
||||
V3Split::splitReorderAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("reorder.tree");
|
||||
}
|
||||
|
||||
// Create delayed assignments
|
||||
// This creates lots of duplicate ACTIVES so ActiveTop needs to be after this step
|
||||
V3Delayed::delayedAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("delayed.tree");
|
||||
|
||||
// Make Active's on the top level
|
||||
// Differs from V3Active, because identical clocks may be pushed down to a module and now be identical
|
||||
V3ActiveTop::activeTopAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("activetop.tree");
|
||||
|
||||
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "PreOrder");
|
||||
|
||||
// Order the code; form SBLOCKs and BLOCKCALLs
|
||||
V3Order::orderAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("order.tree");
|
||||
|
||||
// Change generated clocks to look at delayed signals
|
||||
V3GenClk::genClkAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("genclk.tree");
|
||||
|
||||
// Convert sense lists into IF statements.
|
||||
V3Clock::clockAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("clock.tree");
|
||||
|
||||
// Cleanup any dly vars or other temps that are simple assignments
|
||||
// Life must be done before Subst, as it assumes each CFunc under _eval is called only once.
|
||||
@@ -453,33 +397,25 @@ void process () {
|
||||
if (v3Global.opt.oLifePost()) {
|
||||
V3LifePost::lifepostAll(v3Global.rootp());
|
||||
}
|
||||
if (v3Global.opt.oLife() || v3Global.opt.oLifePost()) {
|
||||
V3Global::dumpCheckGlobalTree("life.tree");
|
||||
}
|
||||
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Detect change loop
|
||||
V3Changed::changedAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("changed.tree");
|
||||
|
||||
// Create tracing logic, since we ripped out some signals the user might want to trace
|
||||
// Note past this point, we presume traced variables won't move between CFuncs
|
||||
// (It's OK if untraced temporaries move around, or vars "effectively" activate the same way.)
|
||||
if (v3Global.opt.trace()) {
|
||||
V3Trace::traceAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("trace.tree");
|
||||
}
|
||||
|
||||
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Scoped");
|
||||
|
||||
// Remove scopes; make varrefs/funccalls relative to current module
|
||||
V3Descope::descopeAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("descope.tree");
|
||||
}
|
||||
|
||||
//--MODULE OPTIMIZATIONS--------------
|
||||
@@ -488,19 +424,16 @@ void process () {
|
||||
// Split deep blocks to appease MSVC++. Must be before Localize.
|
||||
if (!v3Global.opt.lintOnly() && v3Global.opt.compLimitBlocks()) {
|
||||
V3DepthBlock::depthBlockAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("deepblock.tree");
|
||||
}
|
||||
|
||||
// Move BLOCKTEMPS from class to local variables
|
||||
if (v3Global.opt.oLocalize()) {
|
||||
V3Localize::localizeAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("localize.tree", 0, dumpMore);
|
||||
}
|
||||
|
||||
// Icache packing; combine common code in each module's functions into subroutines
|
||||
if (v3Global.opt.oCombine()) {
|
||||
V3Combine::combineAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("combine.tree");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,9 +444,7 @@ void process () {
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
// Remove unused vars
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const_predead.tree", 0, dumpMore);
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
// Here down, widthMin() is the Verilog width, and width() is the C++ width
|
||||
// Bits between widthMin() and width() are irrelevant, but may be non zero.
|
||||
@@ -521,18 +452,15 @@ void process () {
|
||||
|
||||
// Make all math operations either 8, 16, 32 or 64 bits
|
||||
V3Clean::cleanAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("clean.tree");
|
||||
|
||||
// Move wide constants to BLOCK temps.
|
||||
V3Premit::premitAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("premit.tree");
|
||||
}
|
||||
|
||||
// Expand macros and wide operators into C++ primitives
|
||||
if (!v3Global.opt.xmlOnly()
|
||||
&& v3Global.opt.oExpand()) {
|
||||
V3Expand::expandAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("expand.tree");
|
||||
}
|
||||
|
||||
// Propagate constants across WORDSEL arrayed temporaries
|
||||
@@ -540,18 +468,14 @@ void process () {
|
||||
&& v3Global.opt.oSubst()) {
|
||||
// Constant folding of expanded stuff
|
||||
V3Const::constifyCpp(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
V3Subst::substituteAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("subst.tree");
|
||||
}
|
||||
if (!v3Global.opt.xmlOnly()
|
||||
&& v3Global.opt.oSubstConst()) {
|
||||
// Constant folding of substitutions
|
||||
V3Const::constifyCpp(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("constc.tree", 0, dumpMore);
|
||||
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("dead.tree");
|
||||
}
|
||||
|
||||
if (!v3Global.opt.lintOnly()
|
||||
@@ -559,7 +483,6 @@ void process () {
|
||||
// Fix very deep expressions
|
||||
// Mark evaluation functions as member functions, if needed.
|
||||
V3Depth::depthAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("depth.tree", 0, dumpMore);
|
||||
|
||||
// Branch prediction
|
||||
V3Branch::branchAll(v3Global.rootp());
|
||||
@@ -567,7 +490,6 @@ void process () {
|
||||
// Add C casts when longs need to become long-long and vice-versa
|
||||
// Note depth may insert something needing a cast, so this must be last.
|
||||
V3Cast::castAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("cast.tree");
|
||||
}
|
||||
|
||||
V3Error::abortIfErrors();
|
||||
@@ -660,9 +582,9 @@ int main(int argc, char** argv, char** env) {
|
||||
//--FRONTEND------------------
|
||||
|
||||
// Cleanup
|
||||
V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.tree");
|
||||
V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.dot");
|
||||
V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.txt");
|
||||
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.tree");
|
||||
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.dot");
|
||||
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.txt");
|
||||
|
||||
// Read first filename
|
||||
v3Global.readFiles();
|
||||
@@ -673,7 +595,7 @@ int main(int argc, char** argv, char** env) {
|
||||
}
|
||||
|
||||
// Final steps
|
||||
V3Global::dumpCheckGlobalTree("final.tree",990);
|
||||
V3Global::dumpCheckGlobalTree("final.tree", 990, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Error::abortIfWarnings();
|
||||
|
||||
if (!v3Global.opt.lintOnly() && !v3Global.opt.cdc()
|
||||
|
||||
+2
-13
@@ -21,6 +21,8 @@
|
||||
// Cheat for speed and compile .cpp files into one object
|
||||
#define _V3ERROR_NO_GLOBAL_ 1
|
||||
#include "V3Error.cpp"
|
||||
#include "V3String.cpp"
|
||||
#include "V3Os.cpp"
|
||||
#include "VlcTop.cpp"
|
||||
|
||||
#include "VlcOptions.h"
|
||||
@@ -130,19 +132,6 @@ void VlcOptions::showVersion(bool verbose) {
|
||||
cout << "See http://www.veripool.org/verilator for documentation\n";
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// File searching
|
||||
// (TODO: Make a V3Os with these functions and share with Verilator)
|
||||
|
||||
string VlcOptions::filenameNonDir (const string& filename) {
|
||||
string::size_type pos;
|
||||
if ((pos = filename.rfind("/")) != string::npos) {
|
||||
return filename.substr(pos+1);
|
||||
} else {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
int main(int argc, char** argv, char** env) {
|
||||
|
||||
@@ -77,9 +77,6 @@ public:
|
||||
|
||||
// METHODS (from main)
|
||||
static string version();
|
||||
|
||||
// METHODS (file searching)
|
||||
static string filenameNonDir(const string& filename);
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
+3
-3
@@ -18,8 +18,8 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
// Cheat for speed and compile .cpp files into one object
|
||||
#include "V3Error.h"
|
||||
#include "V3Os.h"
|
||||
#include "VlcOptions.h"
|
||||
#include "VlcTop.h"
|
||||
|
||||
@@ -194,12 +194,12 @@ void VlcTop::annotateCalcNeeded() {
|
||||
|
||||
void VlcTop::annotateOutputFiles(const string& dirname) {
|
||||
// Create if uncreated, ignore errors
|
||||
mkdir(dirname.c_str(), 0777);
|
||||
V3Os::createDir(dirname);
|
||||
for (VlcSources::NameMap::iterator sit=m_sources.begin(); sit!=m_sources.end(); ++sit) {
|
||||
VlcSource& source = sit->second;
|
||||
if (!source.needed()) continue;
|
||||
string filename = source.name();
|
||||
string outfilename = dirname+"/"+VlcOptions::filenameNonDir(filename);
|
||||
string outfilename = dirname+"/"+V3Os::filenameNonDir(filename);
|
||||
|
||||
UINFO(1,"annotateOutputFile "<<filename<<" -> "<<outfilename<<endl);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ private:
|
||||
VlcSources m_sources; //< List of all source files to annotate
|
||||
|
||||
// METHODS
|
||||
void createDir(const string& dirname);
|
||||
void annotateCalc();
|
||||
void annotateCalcNeeded();
|
||||
void annotateOutputFiles(const string& dirname);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// This file is part of Verilator.
|
||||
//
|
||||
// Author: Wilson Snyder <[email protected]>
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ my $header = ("\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geome
|
||||
."\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n"
|
||||
."\\usepackage{fancyhdr} \\pagestyle{fancy}\n"
|
||||
."\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n"
|
||||
."\\title{${Opt_DistTitle}} \\date{${Opt_DistDate}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.org}\n"
|
||||
."\\title{${Opt_DistTitle}} \\date{${Opt_DistDate}} \\author{http:\/\/www.veripool.org}\n"
|
||||
."\\lhead[${Opt_DistTitle}]{${Opt_DistTitle}}\n"
|
||||
);
|
||||
|
||||
|
||||
@@ -674,6 +674,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"/*verilator public_flat_rw*/" { FL; return yVL_PUBLIC_FLAT_RW; } // The @(edge) is converted by the preproc
|
||||
"/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; }
|
||||
"/*verilator sc_clock*/" { FL; return yVL_CLOCK; }
|
||||
"/*verilator clocker*/" { FL; return yVL_CLOCKER; }
|
||||
"/*verilator no_clocker*/" { FL; return yVL_NO_CLOCKER; }
|
||||
"/*verilator sc_bv*/" { FL; return yVL_SC_BV; }
|
||||
"/*verilator sformat*/" { FL; return yVL_SFORMAT; }
|
||||
"/*verilator systemc_clock*/" { FL; return yVL_CLOCK; }
|
||||
|
||||
+10
-4
@@ -489,6 +489,8 @@ class AstSenTree;
|
||||
%token<fl> yD_WRITE "$write"
|
||||
|
||||
%token<fl> yVL_CLOCK "/*verilator sc_clock*/"
|
||||
%token<fl> yVL_CLOCKER "/*verilator clocker*/"
|
||||
%token<fl> yVL_NO_CLOCKER "/*verilator no_clocker*/"
|
||||
%token<fl> yVL_CLOCK_ENABLE "/*verilator clock_enable*/"
|
||||
%token<fl> yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/"
|
||||
%token<fl> yVL_FULL_CASE "/*verilator full_case*/"
|
||||
@@ -1462,7 +1464,7 @@ variable_dimension<rangep>: // ==IEEE: variable_dimension
|
||||
//UNSUP '[' ']' { UNSUP }
|
||||
// // IEEE: unpacked_dimension
|
||||
anyrange { $$ = $1; }
|
||||
| '[' constExpr ']' { $$ = new AstRange($1,new AstSub($1,$2, new AstConst($1,1)), new AstConst($1,0)); }
|
||||
| '[' constExpr ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstSub($1, $2, new AstConst($1, 1))); }
|
||||
// // IEEE: associative_dimension
|
||||
//UNSUP '[' data_type ']' { UNSUP }
|
||||
//UNSUP yP_BRASTAR ']' { UNSUP }
|
||||
@@ -1927,6 +1929,8 @@ sigAttrList<nodep>:
|
||||
|
||||
sigAttr<nodep>:
|
||||
yVL_CLOCK { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK); }
|
||||
| yVL_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCKER); }
|
||||
| yVL_NO_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_NO_CLOCKER); }
|
||||
| yVL_CLOCK_ENABLE { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK_ENABLE); }
|
||||
| yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT); v3Global.dpi(true); }
|
||||
@@ -2013,7 +2017,8 @@ etcInst<nodep>: // IEEE: module_instantiation + gate_instantiation + udp_insta
|
||||
|
||||
instDecl<nodep>:
|
||||
id parameter_value_assignmentE {INSTPREP(*$1,$2);} instnameList ';'
|
||||
{ $$ = $4; GRAMMARP->m_impliedDecl=false;}
|
||||
{ $$ = $4; GRAMMARP->m_impliedDecl=false;
|
||||
if (GRAMMARP->m_instParamp) { GRAMMARP->m_instParamp->deleteTree(); GRAMMARP->m_instParamp = NULL; } }
|
||||
// // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers
|
||||
| id/*interface*/ '.' id/*modport*/
|
||||
{ VARRESET_NONLIST(AstVarType::IFACEREF);
|
||||
@@ -2038,9 +2043,10 @@ instnameList<nodep>:
|
||||
;
|
||||
|
||||
instnameParen<cellp>:
|
||||
id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2);
|
||||
// // Must clone m_instParamp as may be comma'ed list of instances
|
||||
id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp->cloneTree(true),$2);
|
||||
$$->trace(GRAMMARP->allTracingOn($<fl>1)); }
|
||||
| id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2);
|
||||
| id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp->cloneTree(true),$2);
|
||||
$$->trace(GRAMMARP->allTracingOn($<fl>1)); }
|
||||
//UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP
|
||||
// // Adding above and switching to the Verilog-Perl syntax
|
||||
|
||||
@@ -393,6 +393,7 @@ sub new {
|
||||
"-OD", # As currently disabled unless -O3
|
||||
"--debug-check"],
|
||||
verilator_flags2 => [],
|
||||
verilator_flags3 => ["--clk clk"],
|
||||
verilator_make_gcc => 1,
|
||||
verilated_debug => $Opt_Verilated_Debug,
|
||||
stdout_filename => undef, # Redirect stdout
|
||||
@@ -502,7 +503,8 @@ sub compile_vlt_flags {
|
||||
my $checkflags = join(' ',@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
@{$param{verilator_flags}},
|
||||
@{$param{verilator_flags2}});
|
||||
@{$param{verilator_flags2}},
|
||||
@{$param{verilator_flags3}});
|
||||
$self->{sc} = 1 if ($checkflags =~ /-sc\b/);
|
||||
$self->{sp} = 1 if ($checkflags =~ /-sp\b/);
|
||||
$self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\b/);
|
||||
@@ -533,6 +535,7 @@ sub compile_vlt_flags {
|
||||
"--prefix ".$param{VM_PREFIX},
|
||||
@verilator_flags,
|
||||
@{$param{verilator_flags2}},
|
||||
@{$param{verilator_flags3}},
|
||||
@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
$param{top_filename},
|
||||
|
||||
@@ -8,6 +8,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["-Wno-CLKDATA"],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
@@ -39,30 +39,23 @@ module t (clk);
|
||||
if (cyc==3) begin
|
||||
d1 <= 1'b1; d3<=3'h3; d8<=8'h44;
|
||||
ena <= 1'b1;
|
||||
// PROPER ANSWER is 8'h11, but we are negative-testing
|
||||
//if (q8 != 8'h11) $stop;
|
||||
if (q8 != 8'h33) $stop;
|
||||
if (q8 != 8'h11) $stop;
|
||||
end
|
||||
if (cyc==4) begin
|
||||
d1 <= 1'b1; d3<=3'h4; d8<=8'h77;
|
||||
ena <= 1'b1;
|
||||
// PROPER ANSWER is 8'h11, but we are negative-testing
|
||||
//if (q8 != 8'h11) $stop;
|
||||
if (q8 != 8'h33) $stop;
|
||||
if (q8 != 8'h11) $stop;
|
||||
end
|
||||
if (cyc==5) begin
|
||||
d1 <= 1'b1; d3<=3'h0; d8<=8'h88;
|
||||
ena <= 1'b1;
|
||||
// PROPER ANSWER is 8'h44, but we are negative-testing
|
||||
//if (q8 != 8'h44) $stop;
|
||||
if (q8 != 8'h44) $stop;
|
||||
end
|
||||
if (cyc==6) begin
|
||||
// PROPER ANSWER is 8'h77, but we are negative-testing
|
||||
//if (q8 != 8'h77) $stop;
|
||||
if (q8 != 8'h77) $stop;
|
||||
end
|
||||
if (cyc==7) begin
|
||||
// PROPER ANSWER is 8'h88, but we are negative-testing
|
||||
//if (q8 != 8'h88) $stop;
|
||||
if (q8 != 8'h88) $stop;
|
||||
end
|
||||
//
|
||||
if (cyc==20) begin
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
# verilator_flags2 => ["-Wno-UNOPTFLAT"]
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,66 @@
|
||||
// DESCRIPTION: Verilator: Simple test of CLkDATA
|
||||
//
|
||||
// Trigger the CLKDATA detection
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by Jie Xu.
|
||||
|
||||
localparam ID_MSB = 1;
|
||||
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk,
|
||||
res,
|
||||
res8,
|
||||
res16
|
||||
);
|
||||
input clk;
|
||||
output res;
|
||||
output [7:0] res8;
|
||||
output [15:0] res16;
|
||||
|
||||
|
||||
wire [7:0] clkSet;
|
||||
wire clk_1;
|
||||
wire [2:0] clk_3;
|
||||
wire [3:0] clk_4;
|
||||
wire clk_final;
|
||||
reg [7:0] count;
|
||||
|
||||
|
||||
assign clkSet = {8{clk}};
|
||||
assign clk_4 = clkSet[7:4];
|
||||
assign clk_1 = clk_4[0];;
|
||||
|
||||
// arraysel
|
||||
assign clk_3 = {3{clk_1}};
|
||||
assign clk_final = clk_3[0];
|
||||
|
||||
// the following two assignment triggers the CLKDATA warning
|
||||
// because on LHS there are a mix of signals both CLOCK and
|
||||
// DATA
|
||||
/* verilator lint_off CLKDATA */
|
||||
assign res8 = {clk_3, 1'b0, clk_4};
|
||||
assign res16 = {count, clk_3, clk_1, clk_4};
|
||||
/* verilator lint_on CLKDATA */
|
||||
|
||||
|
||||
initial
|
||||
count = 0;
|
||||
|
||||
|
||||
always @(posedge clk_final or negedge clk_final) begin
|
||||
count = count + 1;
|
||||
// the following assignment should trigger the CLKDATA warning
|
||||
// because CLOCK signal is used as DATA in sequential block
|
||||
/* verilator lint_off CLKDATA */
|
||||
res <= clk_final;
|
||||
/* verilator lint_on CLKDATA */
|
||||
if ( count == 8'hf) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user