forked from github/verilator
SystemPerl is no longer required for tracing.
Applications must use VerilatedVcdC class in place of SpTraceVcdC.
This commit is contained in:
parent
3e6e6ec0a5
commit
11e702c430
3
Changes
3
Changes
@ -5,6 +5,9 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||||||
|
|
||||||
* Verilator 3.800***
|
* Verilator 3.800***
|
||||||
|
|
||||||
|
** SystemPerl is no longer required for tracing.
|
||||||
|
Applications must use VerilatedVcdC class in place of SpTraceVcdC.
|
||||||
|
|
||||||
** SystemVerilog 1800-2009 is now the default language.
|
** SystemVerilog 1800-2009 is now the default language.
|
||||||
Thus "global" etc are now keywords. See the --language option.
|
Thus "global" etc are now keywords. See the --language option.
|
||||||
|
|
||||||
|
@ -660,11 +660,11 @@ designs with only one top.
|
|||||||
|
|
||||||
Adds waveform tracing code to the model. Verilator will generate
|
Adds waveform tracing code to the model. Verilator will generate
|
||||||
additional {prefix}__Trace*.cpp files that will need to be compiled. In
|
additional {prefix}__Trace*.cpp files that will need to be compiled. In
|
||||||
addition Sp.cpp (for SystemC traces) or SpTraceVcdC.c (for C++ only) from
|
addition verilated_vcd_sc.cpp (for SystemC traces) or verilated_vcd_c.c
|
||||||
the SystemPerl kit's src directory must be compiled and linked in. If
|
(for both) must be compiled and linked in. If using the Verilator
|
||||||
using the Verilator generated Makefiles, these will be added as source
|
generated Makefiles, these will be added as source targets for you. If
|
||||||
targets for you. If you're not using the Verilator makefiles, you will
|
you're not using the Verilator makefiles, you will need to add these to
|
||||||
need to add these to your Makefile manually.
|
your Makefile manually.
|
||||||
|
|
||||||
Having tracing compiled in may result in some small performance losses,
|
Having tracing compiled in may result in some small performance losses,
|
||||||
even when waveforms are not turned on during model execution.
|
even when waveforms are not turned on during model execution.
|
||||||
@ -2527,31 +2527,30 @@ maximum typically needed.
|
|||||||
|
|
||||||
=item How do I generate waveforms (traces) in C++?
|
=item How do I generate waveforms (traces) in C++?
|
||||||
|
|
||||||
See the next question for tracing in SystemPerl mode.
|
See the next question for tracing in SystemC mode.
|
||||||
|
|
||||||
Add the --trace switch to Verilator, and make sure the SystemPerl package
|
Add the --trace switch to Verilator, and in your top level C code, call
|
||||||
is installed. SystemC itself does not need to be installed for C++ only
|
Verilated::traceEverOn(true). Then create a VerilatedVcdCFile object, and
|
||||||
tracing. You do not even need to compile SystemPerl; you may simply untar
|
in your main loop call "trace_object->dump(time)" every time step, and
|
||||||
the SystemPerl kit and point the SYSTEMPERL environment variable to the
|
finally call "trace_object->close()". For an example, see below and the
|
||||||
untarred directory.
|
test_c/sim_main.cpp file of the distribution.
|
||||||
|
|
||||||
In your top level C code, call Verilated::traceEverOn(true). Then create a
|
You also need to compile verilated_vcd_c.cpp and add it to your link. This
|
||||||
SpTraceVcdC object, and in your main loop call "trace_object->dump(time)"
|
is done for you if using the Verilator --exe flag.
|
||||||
every time step, and finally call "trace_object->close()". For an example,
|
|
||||||
see below and the test_c/sim_main.cpp file of the distribution.
|
|
||||||
|
|
||||||
You also need to compile SpTraceVcdC.cpp and add it to your link. This is
|
|
||||||
done for you if using the Verilator --exe flag.
|
|
||||||
|
|
||||||
Note you can also call ->trace on multiple Verilated objects with the same
|
Note you can also call ->trace on multiple Verilated objects with the same
|
||||||
trace file if you want all data to land in the same output file.
|
trace file if you want all data to land in the same output file.
|
||||||
|
|
||||||
#include "SpTraceVcdC.h"
|
Note also older versions of Verilator used the SystemPerl package and
|
||||||
|
SpTraceVcdCFile class. This still works, but is depreciated as it requires
|
||||||
|
strong coupling between the Verilator and SystemPerl versions.
|
||||||
|
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
...
|
...
|
||||||
int main(int argc, char **argv, char **env) {
|
int main(int argc, char **argv, char **env) {
|
||||||
...
|
...
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
SpTraceVcdCFile* tfp = new SpTraceVcdCFile;
|
VerilatedVcdCFile* tfp = new VerilatedVcdCFile;
|
||||||
topp->trace (tfp, 99);
|
topp->trace (tfp, 99);
|
||||||
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
||||||
...
|
...
|
||||||
@ -2562,32 +2561,30 @@ trace file if you want all data to land in the same output file.
|
|||||||
tfp->close();
|
tfp->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
=item How do I generate waveforms (traces) in SystemC/SystemPerl?
|
=item How do I generate waveforms (traces) in SystemC?
|
||||||
|
|
||||||
Add the --trace switch to Verilator, and make sure the SystemPerl package
|
Add the --trace switch to Verilator, and in your top level C sc_main code,
|
||||||
is installed.
|
include verilated_vcd_sc.h. Then call Verilated::traceEverOn(true). Then
|
||||||
|
create a VerilatedVcdSc object as you would create a normal SystemC trace
|
||||||
In your top level C sc_main code, include SpTraceVcd.h. Then call
|
file. For an example, see the call to VerilatedVcdSc in the
|
||||||
Verilated::traceEverOn(true). Then create a SpTraceFile object as you
|
test_sp/sc_main.cpp file of the distribution, and below.
|
||||||
would create a normal SystemC trace file. For an example, see the call to
|
|
||||||
SpTraceFile in the test_sp/sc_main.cpp file of the distribution, and below.
|
|
||||||
|
|
||||||
Alternatively you may use the C++ trace mechanism described in the previous
|
Alternatively you may use the C++ trace mechanism described in the previous
|
||||||
question, however the timescale and timeprecision will not inherited from
|
question, however the timescale and timeprecision will not inherited from
|
||||||
your SystemC settings.
|
your SystemC settings.
|
||||||
|
|
||||||
You'll then need to compile in Sp.cpp, which includes SpTraceVcd.cpp among
|
You also need to compile verilated_vcd_sc.cpp and add it to your link.
|
||||||
other things.
|
This is done for you if using the Verilator --exe flag.
|
||||||
|
|
||||||
Note you can also call ->trace on multiple Verilated objects with the same
|
Note you can also call ->trace on multiple Verilated objects with the same
|
||||||
trace file if you want all data to land in the same output file.
|
trace file if you want all data to land in the same output file.
|
||||||
|
|
||||||
#include "SpTraceVcd.h"
|
#include "verilated_vcd_sc.h"
|
||||||
...
|
...
|
||||||
int main(int argc, char **argv, char **env) {
|
int main(int argc, char **argv, char **env) {
|
||||||
...
|
...
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
SpTraceFile* tfp = new SpTraceFile;
|
VerilatedVcdSc* tfp = new VerilatedVcdSc;
|
||||||
topp->trace (tfp, 99);
|
topp->trace (tfp, 99);
|
||||||
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
tfp->open ("obj_dir/t_trace_ena_cc/simx.vcd");
|
||||||
...
|
...
|
||||||
@ -2604,9 +2601,9 @@ commercial offerings.
|
|||||||
|
|
||||||
=item How do I reduce the size of large waveform (trace) files?
|
=item How do I reduce the size of large waveform (trace) files?
|
||||||
|
|
||||||
First, instead of calling SpTraceVcdCFile->open at the beginning of time,
|
First, instead of calling VerilatedVcdC->open at the beginning of time,
|
||||||
delay calling it until the time stamp where you want to tracing to begin.
|
delay calling it until the time stamp where you want to tracing to begin.
|
||||||
Likewise you can also call SpTraceVcdCFile->open before the end of time
|
Likewise you can also call VerilatedVcdC->open before the end of time
|
||||||
(perhaps a short period after you detect a verification error.)
|
(perhaps a short period after you detect a verification error.)
|
||||||
|
|
||||||
Next, add /*verilator tracing_off*/ to any very low level modules you never
|
Next, add /*verilator tracing_off*/ to any very low level modules you never
|
||||||
@ -2620,9 +2617,12 @@ network disk. Network disks are generally far slower.
|
|||||||
=item How do I do coverage analysis?
|
=item How do I do coverage analysis?
|
||||||
|
|
||||||
Verilator supports both block (line) coverage and user inserted functional
|
Verilator supports both block (line) coverage and user inserted functional
|
||||||
coverage. First, run verilator with the --coverage option. If you're
|
coverage. Both currently require SystemPerl output mode and the SystemPerl
|
||||||
using your own makefile, compile the model with the GCC flag
|
package.
|
||||||
-DSP_COVERAGE_ENABLE (if using Verilator's, it will do this for you.)
|
|
||||||
|
First, run verilator with the --coverage option. If you're using your own
|
||||||
|
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
|
||||||
|
using Verilator's, it will do this for you.)
|
||||||
|
|
||||||
Run your tests in different directories. Each test will create a
|
Run your tests in different directories. Each test will create a
|
||||||
logs/coverage.pl file.
|
logs/coverage.pl file.
|
||||||
@ -2839,7 +2839,7 @@ performance gain.
|
|||||||
In 2009, major SystemVerilog and DPI language support was added.
|
In 2009, major SystemVerilog and DPI language support was added.
|
||||||
|
|
||||||
Currently, various language features and performance enhancements are added
|
Currently, various language features and performance enhancements are added
|
||||||
as the need arises. Verilator is now about 2x faster than in 2002, and is
|
as the need arises. Verilator is now about 3x faster than in 2002, and is
|
||||||
faster than many popular commercial simulators.
|
faster than many popular commercial simulators.
|
||||||
|
|
||||||
=head1 CONTRIBUTORS
|
=head1 CONTRIBUTORS
|
||||||
|
@ -39,6 +39,13 @@
|
|||||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Switches
|
||||||
|
|
||||||
|
#if VM_TRACE // Verilator tracing requested
|
||||||
|
# define WAVES 1 // Set backward compatibility flag as in systemperl.h
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Basic types
|
// Basic types
|
||||||
|
|
||||||
@ -57,6 +64,8 @@ typedef WData* WDataOutP; ///< Array output from a function
|
|||||||
|
|
||||||
class SpTraceVcd;
|
class SpTraceVcd;
|
||||||
class SpTraceVcdCFile;
|
class SpTraceVcdCFile;
|
||||||
|
class VerilatedVcd;
|
||||||
|
class VerilatedVcdC;
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
/// Base class for all Verilated module classes
|
/// Base class for all Verilated module classes
|
||||||
|
671
include/verilated_vcd_c.cpp
Normal file
671
include/verilated_vcd_c.cpp
Normal file
@ -0,0 +1,671 @@
|
|||||||
|
// -*- SystemC -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
|
//
|
||||||
|
// Copyright 2001-2010 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.
|
||||||
|
//
|
||||||
|
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief C++ Tracing in VCD Format
|
||||||
|
///
|
||||||
|
/// AUTHOR: Wilson Snyder
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
// SPDIFF_OFF
|
||||||
|
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "verilated.h"
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <ctime>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
|
# include <io.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// SPDIFF_ON
|
||||||
|
|
||||||
|
#ifndef O_LARGEFILE // For example on WIN32
|
||||||
|
# define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#ifndef O_NONBLOCK
|
||||||
|
# define O_NONBLOCK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Global
|
||||||
|
|
||||||
|
vector<VerilatedVcd*> VerilatedVcd::s_vcdVecp; ///< List of all created traces
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedVcdCallInfo
|
||||||
|
/// Internal callback routines for each module being traced.
|
||||||
|
////
|
||||||
|
/// Each SystemPerl module that wishes to be traced registers a set of
|
||||||
|
/// callbacks stored in this class. When the trace file is being
|
||||||
|
/// constructed, this class provides the callback routines to be executed.
|
||||||
|
|
||||||
|
class VerilatedVcdCallInfo {
|
||||||
|
protected:
|
||||||
|
friend class VerilatedVcd;
|
||||||
|
VerilatedVcdCallback_t m_initcb; ///< Initialization Callback function
|
||||||
|
VerilatedVcdCallback_t m_fullcb; ///< Full Dumping Callback function
|
||||||
|
VerilatedVcdCallback_t m_changecb; ///< Incremental Dumping Callback function
|
||||||
|
void* m_userthis; ///< Fake "this" for caller
|
||||||
|
vluint32_t m_code; ///< Starting code number
|
||||||
|
// CREATORS
|
||||||
|
VerilatedVcdCallInfo (VerilatedVcdCallback_t icb, VerilatedVcdCallback_t fcb,
|
||||||
|
VerilatedVcdCallback_t changecb,
|
||||||
|
void* ut, vluint32_t code)
|
||||||
|
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// Opening/Closing
|
||||||
|
|
||||||
|
void VerilatedVcd::open (const char* filename) {
|
||||||
|
if (isOpen()) return;
|
||||||
|
|
||||||
|
// Assertions, as we cast enum to vluint32_t pointers in AutoTrace.pm
|
||||||
|
enum VerilatedVcd_enumtest { FOO = 1 };
|
||||||
|
if (sizeof(VerilatedVcd_enumtest) != sizeof(vluint32_t)) {
|
||||||
|
vl_fatal(__FILE__,__LINE__,"", "Internal: VerilatedVcd::open cast assumption violated");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set member variables
|
||||||
|
m_filename = filename;
|
||||||
|
s_vcdVecp.push_back(this);
|
||||||
|
|
||||||
|
openNext (m_rolloverMB!=0);
|
||||||
|
if (!isOpen()) return;
|
||||||
|
|
||||||
|
dumpHeader();
|
||||||
|
|
||||||
|
// Allocate space now we know the number of codes
|
||||||
|
if (!m_sigs_oldvalp) {
|
||||||
|
m_sigs_oldvalp = new vluint32_t [m_nextCode+10];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_rolloverMB) {
|
||||||
|
openNext(true);
|
||||||
|
if (!isOpen()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::openNext (bool incFilename) {
|
||||||
|
// Open next filename in concat sequence, mangle filename if
|
||||||
|
// incFilename is true.
|
||||||
|
closePrev(); // Close existing
|
||||||
|
if (incFilename) {
|
||||||
|
// Find _0000.{ext} in filename
|
||||||
|
string name = m_filename;
|
||||||
|
size_t pos=name.rfind(".");
|
||||||
|
if (pos>8 && 0==strncmp("_cat",name.c_str()+pos-8,4)
|
||||||
|
&& isdigit(name.c_str()[pos-4])
|
||||||
|
&& isdigit(name.c_str()[pos-3])
|
||||||
|
&& isdigit(name.c_str()[pos-2])
|
||||||
|
&& isdigit(name.c_str()[pos-1])) {
|
||||||
|
// Increment code.
|
||||||
|
if ((++(name[pos-1])) > '9') {
|
||||||
|
name[pos-1] = '0';
|
||||||
|
if ((++(name[pos-2])) > '9') {
|
||||||
|
name[pos-2] = '0';
|
||||||
|
if ((++(name[pos-3])) > '9') {
|
||||||
|
name[pos-3] = '0';
|
||||||
|
if ((++(name[pos-4])) > '9') {
|
||||||
|
name[pos-4] = '0';
|
||||||
|
}}}}
|
||||||
|
} else {
|
||||||
|
// Append _cat0000
|
||||||
|
name.insert(pos,"_cat0000");
|
||||||
|
}
|
||||||
|
m_filename = name;
|
||||||
|
}
|
||||||
|
if (m_filename[0]=='|') {
|
||||||
|
assert(0); // Not supported yet.
|
||||||
|
} else {
|
||||||
|
m_fd = ::open (m_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||||
|
, 0666);
|
||||||
|
if (m_fd<0) {
|
||||||
|
// User code can check isOpen()
|
||||||
|
m_isOpen = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_isOpen = true;
|
||||||
|
m_fullDump = true; // First dump must be full
|
||||||
|
m_wroteBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VerilatedVcd::~VerilatedVcd() {
|
||||||
|
close();
|
||||||
|
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
|
||||||
|
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::closePrev () {
|
||||||
|
if (!isOpen()) return;
|
||||||
|
|
||||||
|
bufferFlush();
|
||||||
|
m_isOpen = false;
|
||||||
|
::close(m_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::closeErr () {
|
||||||
|
// Close due to an error. We might abort before even getting here,
|
||||||
|
// depending on the definition of vl_fatal.
|
||||||
|
if (!isOpen()) return;
|
||||||
|
|
||||||
|
// No buffer flush, just fclose
|
||||||
|
m_isOpen = false;
|
||||||
|
::close(m_fd); // May get error, just ignore it
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::close() {
|
||||||
|
if (!isOpen()) return;
|
||||||
|
if (m_evcd) {
|
||||||
|
printStr("$vcdclose ");
|
||||||
|
printTime(m_timeLastDump);
|
||||||
|
printStr(" $end\n");
|
||||||
|
}
|
||||||
|
closePrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::printStr (const char* str) {
|
||||||
|
// Not fast...
|
||||||
|
while (*str) {
|
||||||
|
*m_writep++ = *str++;
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::printQuad (vluint64_t n) {
|
||||||
|
char buf [100];
|
||||||
|
sprintf(buf,"%llu",(long long unsigned)n);
|
||||||
|
printStr(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::printTime (vluint64_t timeui) {
|
||||||
|
// VCD file format specification does not allow non-integers for timestamps
|
||||||
|
// Dinotrace doesn't mind, but Cadence vvision seems to choke
|
||||||
|
if (timeui < m_timeLastDump) {
|
||||||
|
timeui = m_timeLastDump;
|
||||||
|
static bool backTime = false;
|
||||||
|
if (!backTime) {
|
||||||
|
backTime = true;
|
||||||
|
VL_PRINTF("VCD time is moving backwards, wave file may be incorrect.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_timeLastDump = timeui;
|
||||||
|
printQuad(timeui);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::bufferFlush () {
|
||||||
|
// We add output data to m_writep.
|
||||||
|
// When it gets nearly full we dump it using this routine which calls write()
|
||||||
|
// This is much faster than using buffered I/O
|
||||||
|
if (!isOpen()) return;
|
||||||
|
char* wp = m_wrBufp;
|
||||||
|
while (1) {
|
||||||
|
size_t remaining = (m_writep - wp);
|
||||||
|
if (remaining==0) break;
|
||||||
|
errno = 0;
|
||||||
|
int got = write (m_fd, wp, remaining);
|
||||||
|
if (got>0) {
|
||||||
|
wp += got;
|
||||||
|
m_wroteBytes += got;
|
||||||
|
} else if (got < 0) {
|
||||||
|
if (errno != EAGAIN && errno != EINTR) {
|
||||||
|
// write failed, presume error (perhaps out of disk space)
|
||||||
|
string msg = (string)"VerilatedVcd::bufferFlush: "+strerror(errno);
|
||||||
|
vl_fatal("",0,"",msg.c_str());
|
||||||
|
closeErr();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset buffer
|
||||||
|
m_writep = m_wrBufp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Simple methods
|
||||||
|
|
||||||
|
void VerilatedVcd::set_time_unit (const char* unitp) {
|
||||||
|
string unitstr (unitp);
|
||||||
|
//cout<<" set_time_unit ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
|
||||||
|
m_timeUnit = timescaleToDouble(unitp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::set_time_resolution (const char* unitp) {
|
||||||
|
string unitstr (unitp);
|
||||||
|
//cout<<"set_time_resolution ("<<unitp<<") == "<<timescaleToDouble(unitp)<<" == "<<doubleToTimescale(timescaleToDouble(unitp))<<endl;
|
||||||
|
m_timeRes = timescaleToDouble(unitp);
|
||||||
|
}
|
||||||
|
|
||||||
|
double VerilatedVcd::timescaleToDouble (const char* unitp) {
|
||||||
|
char* endp;
|
||||||
|
double value = strtod(unitp, &endp);
|
||||||
|
if (!value) value=1; // On error so we allow just "ns" to return 1e-9.
|
||||||
|
unitp=endp;
|
||||||
|
while (*unitp && isspace(*unitp)) unitp++;
|
||||||
|
switch (*unitp) {
|
||||||
|
case 's': value *= 1e1; break;
|
||||||
|
case 'm': value *= 1e-3; break;
|
||||||
|
case 'u': value *= 1e-6; break;
|
||||||
|
case 'n': value *= 1e-9; break;
|
||||||
|
case 'p': value *= 1e-12; break;
|
||||||
|
case 'f': value *= 1e-15; break;
|
||||||
|
case 'a': value *= 1e-18; break;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string VerilatedVcd::doubleToTimescale (double value) {
|
||||||
|
const char* suffixp = "s";
|
||||||
|
if (value>=1e0) { suffixp="s"; value *= 1e0; }
|
||||||
|
else if (value>=1e-3 ) { suffixp="ms"; value *= 1e3; }
|
||||||
|
else if (value>=1e-6 ) { suffixp="us"; value *= 1e6; }
|
||||||
|
else if (value>=1e-9 ) { suffixp="ns"; value *= 1e9; }
|
||||||
|
else if (value>=1e-12) { suffixp="ps"; value *= 1e12; }
|
||||||
|
else if (value>=1e-15) { suffixp="fs"; value *= 1e15; }
|
||||||
|
else if (value>=1e-18) { suffixp="as"; value *= 1e18; }
|
||||||
|
char valuestr[100]; sprintf(valuestr,"%d%s",(int)(value), suffixp);
|
||||||
|
return valuestr; // Gets converted to string, so no ref to stack
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
void VerilatedVcd::printIndent (int level_change) {
|
||||||
|
if (level_change<0) m_modDepth += level_change;
|
||||||
|
assert(m_modDepth>=0);
|
||||||
|
for (int i=0; i<m_modDepth; i++) printStr(" ");
|
||||||
|
if (level_change>0) m_modDepth += level_change;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::dumpHeader () {
|
||||||
|
printStr("$version Generated by VerilatedVcd $end\n");
|
||||||
|
time_t time_str = time(NULL);
|
||||||
|
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
|
||||||
|
|
||||||
|
printStr("$timescale ");
|
||||||
|
printStr(doubleToTimescale(m_timeRes).c_str());
|
||||||
|
printStr(" $end\n");
|
||||||
|
|
||||||
|
// Take signal information from each module and build m_namemapp
|
||||||
|
m_namemapp = new NameMap;
|
||||||
|
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||||
|
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||||
|
cip->m_code = nextCode();
|
||||||
|
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal header
|
||||||
|
assert (m_modDepth==0);
|
||||||
|
printIndent(1);
|
||||||
|
printStr("\n");
|
||||||
|
|
||||||
|
// We detect the spaces in module names to determine hierarchy. This
|
||||||
|
// allows signals to be declared without fixed ordering, which is
|
||||||
|
// required as Verilog signals might be separately declared from
|
||||||
|
// "SP_TRACE" signals.
|
||||||
|
|
||||||
|
// Print the signal names
|
||||||
|
const char* lastName = "";
|
||||||
|
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||||
|
const char* hiername = (*it).first.c_str();
|
||||||
|
const char* decl = (*it).second.c_str();
|
||||||
|
|
||||||
|
// Determine difference between the old and new names
|
||||||
|
const char* lp = lastName;
|
||||||
|
const char* np = hiername;
|
||||||
|
lastName = hiername;
|
||||||
|
|
||||||
|
// Skip common prefix, it must break at a space or tab
|
||||||
|
for (; *np && (*np == *lp); np++, lp++) {}
|
||||||
|
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; }
|
||||||
|
//cout <<"hier "<<hiername<<endl<<" lp "<<lp<<endl<<" np "<<np<<endl;
|
||||||
|
|
||||||
|
// Any extra spaces in last name are scope ups we need to do
|
||||||
|
bool first = true;
|
||||||
|
for (; *lp; lp++) {
|
||||||
|
if (*lp==' ' || (first && *lp!='\t')) {
|
||||||
|
printIndent(-1);
|
||||||
|
printStr("$upscope $end\n");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any new spaces are scope downs we need to do
|
||||||
|
while (*np) {
|
||||||
|
if (*np==' ') np++;
|
||||||
|
if (*np=='\t') break; // tab means signal name starts
|
||||||
|
printIndent(1);
|
||||||
|
printStr("$scope module ");
|
||||||
|
for (; *np && *np!=' ' && *np!='\t'; np++) {
|
||||||
|
if (*np=='[') printStr("(");
|
||||||
|
else if (*np==']') printStr(")");
|
||||||
|
else *m_writep++=*np;
|
||||||
|
}
|
||||||
|
printStr(" $end\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printIndent(0);
|
||||||
|
printStr(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (m_modDepth>1) {
|
||||||
|
printIndent(-1);
|
||||||
|
printStr("$upscope $end\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printIndent(-1);
|
||||||
|
printStr("$enddefinitions $end\n\n\n");
|
||||||
|
assert (m_modDepth==0);
|
||||||
|
|
||||||
|
// Reclaim storage
|
||||||
|
delete m_namemapp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::module (string name) {
|
||||||
|
m_modName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
|
||||||
|
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
||||||
|
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
|
||||||
|
|
||||||
|
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
|
||||||
|
int codesNeeded = 1+int(bits/32);
|
||||||
|
if (tri) codesNeeded *= 2; // Space in change array for __en signals
|
||||||
|
|
||||||
|
// Make sure array is large enough
|
||||||
|
m_nextCode = max(nextCode(), code+codesNeeded);
|
||||||
|
if (m_sigs.capacity() <= m_nextCode) {
|
||||||
|
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save declaration info
|
||||||
|
VerilatedVcdSig sig = VerilatedVcdSig(code, bits);
|
||||||
|
m_sigs.push_back(sig);
|
||||||
|
|
||||||
|
// Split name into basename
|
||||||
|
// Spaces and tabs aren't legal in VCD signal names, so:
|
||||||
|
// Space separates each level of scope
|
||||||
|
// Tab separates final scope from signal name
|
||||||
|
// Tab sorts before spaces, so signals nicely will print before scopes
|
||||||
|
// Note the hiername may be nothing, if so we'll add "\t{name}"
|
||||||
|
string nameasstr = name;
|
||||||
|
if (m_modName!="") { nameasstr = m_modName+m_scopeEscape+nameasstr; } // Optional ->module prefix
|
||||||
|
string hiername;
|
||||||
|
string basename;
|
||||||
|
for (const char* cp=nameasstr.c_str(); *cp; cp++) {
|
||||||
|
if (isScopeEscape(*cp)) {
|
||||||
|
// Ahh, we've just read a scope, not a basename
|
||||||
|
if (hiername!="") hiername += " ";
|
||||||
|
hiername += basename;
|
||||||
|
basename = "";
|
||||||
|
} else {
|
||||||
|
basename += *cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hiername += "\t"+basename;
|
||||||
|
|
||||||
|
// Print reference
|
||||||
|
string decl = "$var ";
|
||||||
|
if (m_evcd) decl += "port"; else decl += wirep; // usually "wire"
|
||||||
|
char buf [1000];
|
||||||
|
sprintf(buf, " %2d ", bits);
|
||||||
|
decl += buf;
|
||||||
|
if (m_evcd) {
|
||||||
|
sprintf(buf, "<%d", code);
|
||||||
|
decl += buf;
|
||||||
|
} else {
|
||||||
|
decl += stringCode(code);
|
||||||
|
}
|
||||||
|
decl += " ";
|
||||||
|
decl += basename;
|
||||||
|
if (arraynum>=0) {
|
||||||
|
sprintf(buf, "(%d)", arraynum);
|
||||||
|
decl += buf;
|
||||||
|
hiername += buf;
|
||||||
|
}
|
||||||
|
if (bussed) {
|
||||||
|
sprintf(buf, " [%d:%d]", msb, lsb);
|
||||||
|
decl += buf;
|
||||||
|
}
|
||||||
|
decl += " $end\n";
|
||||||
|
m_namemapp->insert(make_pair(hiername,decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::declBit (vluint32_t code, const char* name, int arraynum)
|
||||||
|
{ declare (code, name, "wire", arraynum, false, false, 0, 0); }
|
||||||
|
void VerilatedVcd::declBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb)
|
||||||
|
{ declare (code, name, "wire", arraynum, false, true, msb, lsb); }
|
||||||
|
void VerilatedVcd::declQuad (vluint32_t code, const char* name, int arraynum, int msb, int lsb)
|
||||||
|
{ declare (code, name, "wire", arraynum, false, true, msb, lsb); }
|
||||||
|
void VerilatedVcd::declArray (vluint32_t code, const char* name, int arraynum, int msb, int lsb)
|
||||||
|
{ declare (code, name, "wire", arraynum, false, true, msb, lsb); }
|
||||||
|
void VerilatedVcd::declTriBit (vluint32_t code, const char* name, int arraynum)
|
||||||
|
{ declare (code, name, "wire", arraynum, true, false, 0, 0); }
|
||||||
|
void VerilatedVcd::declTriBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb)
|
||||||
|
{ declare (code, name, "wire", arraynum, true, true, msb, lsb); }
|
||||||
|
void VerilatedVcd::declTriQuad (vluint32_t code, const char* name, int arraynum, int msb, int lsb)
|
||||||
|
{ declare (code, name, "wire", arraynum, true, true, msb, lsb); }
|
||||||
|
void VerilatedVcd::declTriArray (vluint32_t code, const char* name, int arraynum, int msb, int lsb)
|
||||||
|
{ declare (code, name, "wire", arraynum, true, true, msb, lsb); }
|
||||||
|
void VerilatedVcd::declFloat (vluint32_t code, const char* name, int arraynum)
|
||||||
|
{ declare (code, name, "real", arraynum, false, false, 31, 0); }
|
||||||
|
void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum)
|
||||||
|
{ declare (code, name, "real", arraynum, false, false, 63, 0); }
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
|
||||||
|
(*((double*)&m_sigs_oldvalp[code])) = newval;
|
||||||
|
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
|
||||||
|
sprintf(m_writep, "r%.16g", newval);
|
||||||
|
m_writep += strlen(m_writep);
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
|
||||||
|
(*((float*)&m_sigs_oldvalp[code])) = newval;
|
||||||
|
// Buffer can't overflow; we have at least bufferInsertSize() bytes (>>>16 bytes)
|
||||||
|
sprintf(m_writep, "r%.16g", (double)newval);
|
||||||
|
m_writep += strlen(m_writep);
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Callbacks
|
||||||
|
|
||||||
|
void VerilatedVcd::addCallback (
|
||||||
|
VerilatedVcdCallback_t initcb, VerilatedVcdCallback_t fullcb, VerilatedVcdCallback_t changecb,
|
||||||
|
void* userthis)
|
||||||
|
{
|
||||||
|
if (isOpen()) {
|
||||||
|
string msg = (string)"Internal: "+__FILE__+"::"+__FUNCTION__+" called with already open file";
|
||||||
|
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||||
|
}
|
||||||
|
VerilatedVcdCallInfo* vci = new VerilatedVcdCallInfo(initcb, fullcb, changecb, userthis, nextCode());
|
||||||
|
m_callbacks.push_back(vci);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Dumping
|
||||||
|
|
||||||
|
void VerilatedVcd::dumpFull (vluint64_t timeui) {
|
||||||
|
dumpPrep (timeui);
|
||||||
|
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||||
|
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||||
|
(cip->m_fullcb) (this, cip->m_userthis, cip->m_code);
|
||||||
|
}
|
||||||
|
dumpDone ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::dump (vluint64_t timeui) {
|
||||||
|
if (!isOpen()) return;
|
||||||
|
if (m_fullDump) {
|
||||||
|
m_fullDump = false; // No need for more full dumps
|
||||||
|
dumpFull(timeui);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_rolloverMB && m_wroteBytes > this->m_rolloverMB) {
|
||||||
|
openNext(true);
|
||||||
|
if (!isOpen()) return;
|
||||||
|
}
|
||||||
|
dumpPrep (timeui);
|
||||||
|
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||||
|
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||||
|
(cip->m_changecb) (this, cip->m_userthis, cip->m_code);
|
||||||
|
}
|
||||||
|
dumpDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::dumpPrep (vluint64_t timeui) {
|
||||||
|
printStr("#");
|
||||||
|
printTime(timeui);
|
||||||
|
printStr("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerilatedVcd::dumpDone () {
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// Static members
|
||||||
|
|
||||||
|
void VerilatedVcd::flush_all() {
|
||||||
|
for (vluint32_t ent = 0; ent< s_vcdVecp.size(); ent++) {
|
||||||
|
VerilatedVcd* vcdp = s_vcdVecp[ent];
|
||||||
|
vcdp->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
//======================================================================
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#ifdef VERILATED_VCD_TEST
|
||||||
|
vluint32_t v1, v2, s1, s2[3];
|
||||||
|
vluint32_t tri96[3];
|
||||||
|
vluint32_t tri96__tri[3];
|
||||||
|
vluint8_t ch;
|
||||||
|
vluint64_t timestamp = 1;
|
||||||
|
double doub = 0;
|
||||||
|
|
||||||
|
void vcdInit (VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
||||||
|
vcdp->scopeEscape('.');
|
||||||
|
vcdp->module ("top");
|
||||||
|
vcdp->declBus (0x2, "v1",-1,5,1);
|
||||||
|
vcdp->declBus (0x3, "v2",-1,6,0);
|
||||||
|
vcdp->module ("top.sub1");
|
||||||
|
vcdp->declBit (0x4, "s1",-1);
|
||||||
|
vcdp->declBit (0x5, "ch",-1);
|
||||||
|
vcdp->module ("top.sub2");
|
||||||
|
vcdp->declArray (0x6, "s2",-1, 40,3);
|
||||||
|
// Note need to add 3 for next code.
|
||||||
|
vcdp->module ("top2");
|
||||||
|
vcdp->declBus (0x2, "t2v1",-1,4,1);
|
||||||
|
vcdp->declTriBit (0x10, "io1", -1);
|
||||||
|
vcdp->declTriBus (0x12, "io5", -1,4,0);
|
||||||
|
vcdp->declTriArray (0x16, "io96",-1,95,0);
|
||||||
|
// Note need to add 6 for next code.
|
||||||
|
vcdp->declDouble (0x1c, "doub",-1);
|
||||||
|
// Note need to add 2 for next code.
|
||||||
|
}
|
||||||
|
|
||||||
|
void vcdFull (VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
||||||
|
vcdp->fullBus (0x2, v1,5);
|
||||||
|
vcdp->fullBus (0x3, v2,7);
|
||||||
|
vcdp->fullBit (0x4, s1);
|
||||||
|
vcdp->fullBus (0x5, ch,2);
|
||||||
|
vcdp->fullArray(0x6, &s2[0], 38);
|
||||||
|
vcdp->fullTriBit (0x10, tri96[0]&1, tri96__tri[0]&1);
|
||||||
|
vcdp->fullTriBus (0x12, tri96[0]&0x1f, tri96__tri[0]&0x1f, 5);
|
||||||
|
vcdp->fullTriArray (0x16, tri96, tri96__tri, 96);
|
||||||
|
vcdp->fullDouble(0x1c, doub);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vcdChange (VerilatedVcd* vcdp, void* userthis, vluint32_t code) {
|
||||||
|
vcdp->chgBus (0x2, v1,5);
|
||||||
|
vcdp->chgBus (0x3, v2,7);
|
||||||
|
vcdp->chgBit (0x4, s1);
|
||||||
|
vcdp->chgBus (0x5, ch,2);
|
||||||
|
vcdp->chgArray(0x6, &s2[0], 38);
|
||||||
|
vcdp->chgTriBit (0x10, tri96[0]&1, tri96__tri[0]&1);
|
||||||
|
vcdp->chgTriBus (0x12, tri96[0]&0x1f, tri96__tri[0]&0x1f, 5);
|
||||||
|
vcdp->chgTriArray (0x16, tri96, tri96__tri, 96);
|
||||||
|
vcdp->chgDouble (0x1c, doub);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cout<<"test: O_LARGEFILE="<<O_LARGEFILE<<endl;
|
||||||
|
|
||||||
|
v1 = v2 = s1 = 0;
|
||||||
|
s2[0] = s2[1] = s2[2] = 0;
|
||||||
|
tri96[2] = tri96[1] = tri96[0] = 0;
|
||||||
|
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0;
|
||||||
|
ch = 0;
|
||||||
|
doub = 0;
|
||||||
|
{
|
||||||
|
VerilatedVcdC* vcdp = new VerilatedVcdC;
|
||||||
|
vcdp->spTrace()->addCallback (&vcdInit, &vcdFull, &vcdChange, 0);
|
||||||
|
vcdp->open ("test.vcd");
|
||||||
|
// Dumping
|
||||||
|
vcdp->dump(timestamp++);
|
||||||
|
v1 = 0xfff;
|
||||||
|
tri96[2] = 4; tri96[1] = 2; tri96[0] = 1;
|
||||||
|
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = ~0; // Still tri
|
||||||
|
doub = 1.5;
|
||||||
|
vcdp->dump(timestamp++);
|
||||||
|
v2 = 0x1;
|
||||||
|
s2[1] = 2;
|
||||||
|
tri96__tri[2] = tri96__tri[1] = tri96__tri[0] = 0; // enable w/o data change
|
||||||
|
doub = -1.66e13;
|
||||||
|
vcdp->dump(timestamp++);
|
||||||
|
ch = 2;
|
||||||
|
tri96[2] = ~4; tri96[1] = ~2; tri96[0] = ~1;
|
||||||
|
doub = -3.33e-13;
|
||||||
|
vcdp->dump(timestamp++);
|
||||||
|
vcdp->dump(timestamp++);
|
||||||
|
# ifdef VERILATED_VCD_TEST_64BIT
|
||||||
|
vluint64_t bytesPerDump = 15ULL;
|
||||||
|
for (vluint64_t i=0; i<((1ULL<<32) / bytesPerDump); i++) {
|
||||||
|
v1 = i;
|
||||||
|
vcdp->dump(timestamp++);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
vcdp->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//********************************************************************
|
||||||
|
// Local Variables:
|
||||||
|
// compile-command: "mkdir -p ../test_dir && cd ../test_dir && g++ -DVERILATED_VCD_TEST ../src/verilated_vcd_c.cpp -o verilated_vcd_c && ./verilated_vcd_c && cat test.vcd"
|
||||||
|
// End:
|
421
include/verilated_vcd_c.h
Normal file
421
include/verilated_vcd_c.h
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
// -*- SystemC -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
|
//
|
||||||
|
// Copyright 2001-2010 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.
|
||||||
|
//
|
||||||
|
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief C++ Tracing in VCD Format
|
||||||
|
///
|
||||||
|
/// AUTHOR: Wilson Snyder
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
// SPDIFF_OFF
|
||||||
|
|
||||||
|
#ifndef _VERILATED_VCD_C_H_
|
||||||
|
#define _VERILATED_VCD_C_H_ 1
|
||||||
|
|
||||||
|
#include "verilatedos.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define VERILATED_VCD_VERSION 1333 // Version number of this file AS_AN_INTEGER
|
||||||
|
|
||||||
|
class VerilatedVcd;
|
||||||
|
class VerilatedVcdCallInfo;
|
||||||
|
|
||||||
|
// SPDIFF_ON
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedVcdSig
|
||||||
|
/// Internal data on one signal being traced.
|
||||||
|
|
||||||
|
class VerilatedVcdSig {
|
||||||
|
protected:
|
||||||
|
friend class VerilatedVcd;
|
||||||
|
vluint32_t m_code; ///< VCD file code number
|
||||||
|
int m_bits; ///< Size of value in bits
|
||||||
|
VerilatedVcdSig (vluint32_t code, int bits)
|
||||||
|
: m_code(code), m_bits(bits) {}
|
||||||
|
public:
|
||||||
|
~VerilatedVcdSig() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
typedef void (*VerilatedVcdCallback_t)(VerilatedVcd* vcdp, void* userthis, vluint32_t code);
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedVcd
|
||||||
|
/// Create a SystemPerl VCD dump
|
||||||
|
|
||||||
|
class VerilatedVcd {
|
||||||
|
private:
|
||||||
|
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
|
||||||
|
int m_modDepth; ///< Depth of module hierarchy
|
||||||
|
bool m_fullDump; ///< True indicates dump ignoring if changed
|
||||||
|
vluint32_t m_nextCode; ///< Next code number to assign
|
||||||
|
string m_modName; ///< Module name being traced now
|
||||||
|
double m_timeRes; ///< Time resolution (ns/ms etc)
|
||||||
|
double m_timeUnit; ///< Time units (ns/ms etc)
|
||||||
|
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
||||||
|
|
||||||
|
char* m_wrBufp; ///< Output buffer
|
||||||
|
char* m_writep; ///< Write pointer into output buffer
|
||||||
|
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
||||||
|
|
||||||
|
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
|
||||||
|
vector<VerilatedVcdSig> m_sigs; ///< Pointer to signal information
|
||||||
|
vector<VerilatedVcdCallInfo*> m_callbacks; ///< Routines to perform dumping
|
||||||
|
typedef map<string,string> NameMap;
|
||||||
|
NameMap* m_namemapp; ///< List of names for the header
|
||||||
|
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
||||||
|
|
||||||
|
inline size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||||
|
inline size_t bufferInsertSize() { return 16*1024; }
|
||||||
|
void bufferFlush();
|
||||||
|
void bufferCheck() {
|
||||||
|
// Flush the write buffer if there's not enough space left for new information
|
||||||
|
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||||
|
if (m_writep > (m_wrBufp+(bufferSize()-bufferInsertSize()))) {
|
||||||
|
bufferFlush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void closePrev();
|
||||||
|
void closeErr();
|
||||||
|
void openNext();
|
||||||
|
void printIndent (int levelchange);
|
||||||
|
void printStr (const char* str);
|
||||||
|
void printQuad (vluint64_t n);
|
||||||
|
void printTime (vluint64_t timeui);
|
||||||
|
void declare (vluint32_t code, const char* name, const char* wirep,
|
||||||
|
int arraynum, bool tri, bool bussed, int msb, int lsb);
|
||||||
|
|
||||||
|
void dumpHeader();
|
||||||
|
void dumpPrep (vluint64_t timeui);
|
||||||
|
void dumpFull (vluint64_t timeui);
|
||||||
|
void dumpDone ();
|
||||||
|
inline void printCode (vluint32_t code) {
|
||||||
|
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
|
||||||
|
if (code>=(94*94)) *m_writep++ = ((char)((code/94/94)%94+33));
|
||||||
|
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
|
||||||
|
*m_writep++ = ((char)((code)%94+33));
|
||||||
|
}
|
||||||
|
string stringCode (vluint32_t code) {
|
||||||
|
string out;
|
||||||
|
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
|
||||||
|
if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
|
||||||
|
if (code>=(94)) out += ((char)((code/94)%94+33));
|
||||||
|
return out + ((char)((code)%94+33));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// METHODS
|
||||||
|
void evcd(bool flag) { m_evcd = flag; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CREATORS
|
||||||
|
VerilatedVcd () : m_isOpen(false), m_rolloverMB(0), m_modDepth(0), m_nextCode(1) {
|
||||||
|
m_wrBufp = new char [bufferSize()];
|
||||||
|
m_writep = m_wrBufp;
|
||||||
|
m_namemapp = NULL;
|
||||||
|
m_timeRes = m_timeUnit = 1e-9;
|
||||||
|
m_timeLastDump = 0;
|
||||||
|
m_sigs_oldvalp = NULL;
|
||||||
|
m_evcd = false;
|
||||||
|
m_scopeEscape = '.'; // Backward compatibility
|
||||||
|
m_wroteBytes = 0;
|
||||||
|
}
|
||||||
|
~VerilatedVcd();
|
||||||
|
|
||||||
|
// ACCESSORS
|
||||||
|
/// Inside dumping routines, return next VCD signal code
|
||||||
|
vluint32_t nextCode() const {return m_nextCode;}
|
||||||
|
/// Set size in megabytes after which new file should be created
|
||||||
|
void rolloverMB(vluint64_t rolloverMB) { m_rolloverMB=rolloverMB; };
|
||||||
|
/// Is file open?
|
||||||
|
bool isOpen() const { return m_isOpen; }
|
||||||
|
/// Change character that splits scopes. Note whitespace are ALWAYS escapes.
|
||||||
|
void scopeEscape(char flag) { m_scopeEscape = flag; }
|
||||||
|
/// Is this an escape?
|
||||||
|
inline bool isScopeEscape(char c) { return isspace(c) || c==m_scopeEscape; }
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
void open (const char* filename); ///< Open the file; call isOpen() to see if errors
|
||||||
|
void openNext (bool incFilename); ///< Open next data-only file
|
||||||
|
void flush() { bufferFlush(); } ///< Flush any remaining data
|
||||||
|
static void flush_all(); ///< Flush any remaining data from all files
|
||||||
|
void close (); ///< Close the file
|
||||||
|
|
||||||
|
void set_time_unit (const char* unit); ///< Set time units (s/ms, defaults to ns)
|
||||||
|
void set_time_unit (const string& unit) { set_time_unit(unit.c_str()); }
|
||||||
|
|
||||||
|
void set_time_resolution (const char* unit); ///< Set time resolution (s/ms, defaults to ns)
|
||||||
|
void set_time_resolution (const string& unit) { set_time_resolution(unit.c_str()); }
|
||||||
|
|
||||||
|
double timescaleToDouble (const char* unitp);
|
||||||
|
string doubleToTimescale (double value);
|
||||||
|
|
||||||
|
/// Inside dumping routines, called each cycle to make the dump
|
||||||
|
void dump (vluint64_t timeui);
|
||||||
|
/// Call dump with a absolute unscaled time in seconds
|
||||||
|
void dumpSeconds (double secs) { dump((vluint64_t)(secs * m_timeRes)); }
|
||||||
|
|
||||||
|
/// Inside dumping routines, declare callbacks for tracings
|
||||||
|
void addCallback (VerilatedVcdCallback_t init, VerilatedVcdCallback_t full,
|
||||||
|
VerilatedVcdCallback_t change,
|
||||||
|
void* userthis);
|
||||||
|
|
||||||
|
/// Inside dumping routines, declare a module
|
||||||
|
void module (const string name);
|
||||||
|
/// Inside dumping routines, declare a signal
|
||||||
|
void declBit (vluint32_t code, const char* name, int arraynum);
|
||||||
|
void declBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||||
|
void declQuad (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||||
|
void declArray (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||||
|
void declTriBit (vluint32_t code, const char* name, int arraynum);
|
||||||
|
void declTriBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||||
|
void declTriQuad (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||||
|
void declTriArray (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||||
|
void declDouble (vluint32_t code, const char* name, int arraynum);
|
||||||
|
void declFloat (vluint32_t code, const char* name, int arraynum);
|
||||||
|
// ... other module_start for submodules (based on cell name)
|
||||||
|
|
||||||
|
/// Inside dumping routines, dump one signal
|
||||||
|
void fullBit (vluint32_t code, const vluint32_t newval) {
|
||||||
|
// Note the &1, so we don't require clean input -- makes more common no change case faster
|
||||||
|
m_sigs_oldvalp[code] = newval;
|
||||||
|
*m_writep++=('0'+(char)(newval&1)); printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullBus (vluint32_t code, const vluint32_t newval, int bits) {
|
||||||
|
m_sigs_oldvalp[code] = newval;
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
*m_writep++=((newval&(1L<<bit))?'1':'0');
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullQuad (vluint32_t code, const vluint64_t newval, int bits) {
|
||||||
|
(*((vluint64_t*)&m_sigs_oldvalp[code])) = newval;
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
*m_writep++=((newval&(1ULL<<bit))?'1':'0');
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullArray (vluint32_t code, const vluint32_t* newval, int bits) {
|
||||||
|
for (int word=0; word<(((bits-1)/32)+1); ++word) {
|
||||||
|
m_sigs_oldvalp[code+word] = newval[word];
|
||||||
|
}
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
*m_writep++=((newval[(bit/32)]&(1L<<(bit&0x1f)))?'1':'0');
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullTriBit (vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
|
||||||
|
m_sigs_oldvalp[code] = newval;
|
||||||
|
m_sigs_oldvalp[code+1] = newtri;
|
||||||
|
*m_writep++ = "01zz"[m_sigs_oldvalp[code]
|
||||||
|
| (m_sigs_oldvalp[code+1]<<1)];
|
||||||
|
printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullTriBus (vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits) {
|
||||||
|
m_sigs_oldvalp[code] = newval;
|
||||||
|
m_sigs_oldvalp[code+1] = newtri;
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
*m_writep++ = "01zz"[((newval >> bit)&1)
|
||||||
|
| (((newtri >> bit)&1)<<1)];
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullTriQuad (vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits) {
|
||||||
|
(*((vluint64_t*)&m_sigs_oldvalp[code])) = newval;
|
||||||
|
(*((vluint64_t*)&m_sigs_oldvalp[code+1])) = newtri;
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
*m_writep++ = "01zz"[((newval >> bit)&1ULL)
|
||||||
|
| (((newtri >> bit)&1ULL)<<1ULL)];
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullTriArray (vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, int bits) {
|
||||||
|
for (int word=0; word<(((bits-1)/32)+1); ++word) {
|
||||||
|
m_sigs_oldvalp[code+word*2] = newvalp[word];
|
||||||
|
m_sigs_oldvalp[code+word*2+1] = newtrip[word];
|
||||||
|
}
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
vluint32_t valbit = (newvalp[(bit/32)]>>(bit&0x1f)) & 1;
|
||||||
|
vluint32_t tribit = (newtrip[(bit/32)]>>(bit&0x1f)) & 1;
|
||||||
|
*m_writep++ = "01zz"[valbit | (tribit<<1)];
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
void fullDouble (vluint32_t code, const double newval);
|
||||||
|
void fullFloat (vluint32_t code, const float newval);
|
||||||
|
|
||||||
|
/// Inside dumping routines, dump one signal as unknowns
|
||||||
|
/// Presently this code doesn't change the oldval vector.
|
||||||
|
/// Thus this is for special standalone applications that after calling
|
||||||
|
/// fullBitX, must when then value goes non-X call fullBit.
|
||||||
|
inline void fullBitX (vluint32_t code) {
|
||||||
|
*m_writep++='x'; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
inline void fullBusX (vluint32_t code, int bits) {
|
||||||
|
*m_writep++='b';
|
||||||
|
for (int bit=bits-1; bit>=0; --bit) {
|
||||||
|
*m_writep++='x';
|
||||||
|
}
|
||||||
|
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||||
|
bufferCheck();
|
||||||
|
}
|
||||||
|
inline void fullQuadX (vluint32_t code, int bits) { fullBusX (code, bits); }
|
||||||
|
inline void fullArrayX (vluint32_t code, int bits) { fullBusX (code, bits); }
|
||||||
|
|
||||||
|
/// Inside dumping routines, dump one signal if it has changed
|
||||||
|
inline void chgBit (vluint32_t code, const vluint32_t newval) {
|
||||||
|
vluint32_t diff = m_sigs_oldvalp[code] ^ newval;
|
||||||
|
if (VL_UNLIKELY(diff)) {
|
||||||
|
// Verilator 3.510 and newer provide clean input, so the below is only for back compatibility
|
||||||
|
if (VL_UNLIKELY(diff & 1)) { // Change after clean?
|
||||||
|
fullBit (code, newval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgBus (vluint32_t code, const vluint32_t newval, int bits) {
|
||||||
|
vluint32_t diff = m_sigs_oldvalp[code] ^ newval;
|
||||||
|
if (VL_UNLIKELY(diff)) {
|
||||||
|
if (VL_UNLIKELY(bits==32 || (diff & ((1U<<bits)-1) ))) {
|
||||||
|
fullBus (code, newval, bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgQuad (vluint32_t code, const vluint64_t newval, int bits) {
|
||||||
|
vluint64_t diff = (*((vluint64_t*)&m_sigs_oldvalp[code])) ^ newval;
|
||||||
|
if (VL_UNLIKELY(diff)) {
|
||||||
|
if (VL_UNLIKELY(bits==64 || (diff & ((1ULL<<bits)-1) ))) {
|
||||||
|
fullQuad(code, newval, bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgArray (vluint32_t code, const vluint32_t* newval, int bits) {
|
||||||
|
for (int word=0; word<(((bits-1)/32)+1); ++word) {
|
||||||
|
if (VL_UNLIKELY(m_sigs_oldvalp[code+word] ^ newval[word])) {
|
||||||
|
fullArray (code,newval,bits);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgTriBit (vluint32_t code, const vluint32_t newval, const vluint32_t newtri) {
|
||||||
|
vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval)
|
||||||
|
| (m_sigs_oldvalp[code+1] ^ newtri));
|
||||||
|
if (VL_UNLIKELY(diff)) {
|
||||||
|
// Verilator 3.510 and newer provide clean input, so the below is only for back compatibility
|
||||||
|
if (VL_UNLIKELY(diff & 1)) { // Change after clean?
|
||||||
|
fullTriBit (code, newval, newtri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgTriBus (vluint32_t code, const vluint32_t newval, const vluint32_t newtri, int bits) {
|
||||||
|
vluint32_t diff = ((m_sigs_oldvalp[code] ^ newval)
|
||||||
|
| (m_sigs_oldvalp[code+1] ^ newtri));
|
||||||
|
if (VL_UNLIKELY(diff)) {
|
||||||
|
if (VL_UNLIKELY(bits==32 || (diff & ((1U<<bits)-1) ))) {
|
||||||
|
fullTriBus (code, newval, newtri, bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgTriQuad (vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits) {
|
||||||
|
vluint64_t diff = ( ((*((vluint64_t*)&m_sigs_oldvalp[code])) ^ newval)
|
||||||
|
| ((*((vluint64_t*)&m_sigs_oldvalp[code+1])) ^ newtri));
|
||||||
|
if (VL_UNLIKELY(diff)) {
|
||||||
|
if (VL_UNLIKELY(bits==64 || (diff & ((1ULL<<bits)-1) ))) {
|
||||||
|
fullTriQuad(code, newval, newtri, bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgTriArray (vluint32_t code, const vluint32_t* newvalp, const vluint32_t* newtrip, int bits) {
|
||||||
|
for (int word=0; word<(((bits-1)/32)+1); ++word) {
|
||||||
|
if (VL_UNLIKELY((m_sigs_oldvalp[code+word*2] ^ newvalp[word])
|
||||||
|
| (m_sigs_oldvalp[code+word*2+1] ^ newtrip[word]))) {
|
||||||
|
fullTriArray (code,newvalp,newtrip,bits);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgDouble (vluint32_t code, const double newval) {
|
||||||
|
if (VL_UNLIKELY((*((double*)&m_sigs_oldvalp[code])) != newval)) {
|
||||||
|
fullDouble (code, newval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void chgFloat (vluint32_t code, const float newval) {
|
||||||
|
if (VL_UNLIKELY((*((float*)&m_sigs_oldvalp[code])) != newval)) {
|
||||||
|
fullFloat (code, newval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedVcdC
|
||||||
|
/// Create a VCD dump file in C standalone (no SystemC) simulations.
|
||||||
|
|
||||||
|
class VerilatedVcdC {
|
||||||
|
VerilatedVcd m_sptrace; ///< SystemPerl trace file being created
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VerilatedVcdC() {}
|
||||||
|
~VerilatedVcdC() {}
|
||||||
|
// ACCESSORS
|
||||||
|
/// Is file open?
|
||||||
|
bool isOpen() const { return m_sptrace.isOpen(); }
|
||||||
|
// METHODS
|
||||||
|
/// Open a new VCD file
|
||||||
|
void open (const char* filename) { m_sptrace.open(filename); }
|
||||||
|
/// Continue a VCD dump by rotating to a new file name
|
||||||
|
void openNext (bool incFilename=true) { m_sptrace.openNext(incFilename); }
|
||||||
|
/// Set size in megabytes after which new file should be created
|
||||||
|
void rolloverMB(size_t rolloverMB) { m_sptrace.rolloverMB(rolloverMB); };
|
||||||
|
/// Close dump
|
||||||
|
void close() { m_sptrace.close(); }
|
||||||
|
/// Flush dump
|
||||||
|
void flush() { m_sptrace.flush(); }
|
||||||
|
/// Write one cycle of dump data
|
||||||
|
void dump (vluint64_t timeui) { m_sptrace.dump(timeui); }
|
||||||
|
/// Write one cycle of dump data - backward compatible and to reduce
|
||||||
|
/// conversion warnings. It's better to use a vluint64_t time instead.
|
||||||
|
void dump (double timestamp) { dump((vluint64_t)timestamp); }
|
||||||
|
void dump (vluint32_t timestamp) { dump((vluint64_t)timestamp); }
|
||||||
|
void dump (int timestamp) { dump((vluint64_t)timestamp); }
|
||||||
|
/// Internal class access
|
||||||
|
inline VerilatedVcd* spTrace () { return &m_sptrace; };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // guard
|
159
include/verilated_vcd_sc.cpp
Normal file
159
include/verilated_vcd_sc.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
// -*- SystemC -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
|
//
|
||||||
|
// Copyright 2001-2010 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.
|
||||||
|
//
|
||||||
|
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief SystemPerl Tracing in VCD Format
|
||||||
|
///
|
||||||
|
/// AUTHOR: Wilson Snyder
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
// SPDIFF_OFF
|
||||||
|
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "verilated_vcd_sc.h"
|
||||||
|
|
||||||
|
// SPDIFF_ON
|
||||||
|
//======================================================================
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
#if (SYSTEMC_VERSION>=20050714)
|
||||||
|
// SystemC 2.1.v1
|
||||||
|
void VerilatedVcdSc::write_comment (const std::string &) {}
|
||||||
|
void VerilatedVcdSc::trace (const unsigned int &, const std::string &, const char **) {}
|
||||||
|
|
||||||
|
# define DECL_TRACE_METHOD_A(tp) \
|
||||||
|
void VerilatedVcdSc::trace( const tp& object, const std::string& name ) {}
|
||||||
|
# define DECL_TRACE_METHOD_B(tp) \
|
||||||
|
void VerilatedVcdSc::trace( const tp& object, const std::string& name, int width ) {}
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( bool )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_logic )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_B( unsigned char )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
|
#endif
|
||||||
|
DECL_TRACE_METHOD_B( char )
|
||||||
|
DECL_TRACE_METHOD_B( short )
|
||||||
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
DECL_TRACE_METHOD_B( long )
|
||||||
|
DECL_TRACE_METHOD_B( sc_dt::int64 )
|
||||||
|
DECL_TRACE_METHOD_B( sc_dt::uint64 )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( float )
|
||||||
|
DECL_TRACE_METHOD_A( double )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_int_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_uint_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_signed )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_unsigned )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxval )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxval_fast )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxnum )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxnum_fast )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
#elif (SYSTEMC_VERSION>20011000)
|
||||||
|
// SystemC 2.0.1
|
||||||
|
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
||||||
|
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
||||||
|
|
||||||
|
#define DECL_TRACE_METHOD_A(tp) \
|
||||||
|
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
|
||||||
|
#define DECL_TRACE_METHOD_B(tp) \
|
||||||
|
void VerilatedVcdSc::trace( const tp& object, const sc_string& name, int width ) {}
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( bool )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bit )
|
||||||
|
DECL_TRACE_METHOD_A( sc_logic )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned char )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
|
#endif
|
||||||
|
#if (SYSTEMC_VERSION>20041000)
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
|
DECL_TRACE_METHOD_B( long long)
|
||||||
|
#endif
|
||||||
|
DECL_TRACE_METHOD_B( char )
|
||||||
|
DECL_TRACE_METHOD_B( short )
|
||||||
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
DECL_TRACE_METHOD_B( long )
|
||||||
|
DECL_TRACE_METHOD_A( float )
|
||||||
|
DECL_TRACE_METHOD_A( double )
|
||||||
|
DECL_TRACE_METHOD_A( sc_int_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signed )
|
||||||
|
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxval )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxval_fast )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxnum )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bv_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_lv_base )
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
#else
|
||||||
|
// SystemC 1.2.1beta
|
||||||
|
void VerilatedVcdSc::write_comment (const sc_string &) {}
|
||||||
|
void VerilatedVcdSc::trace (const unsigned int &, const sc_string &, const char **) {}
|
||||||
|
|
||||||
|
#define DECL_TRACE_METHOD_A(tp) \
|
||||||
|
void VerilatedVcdSc::trace( const tp& object, const sc_string& name ) {}
|
||||||
|
#define DECL_TRACE_METHOD_B(tp) \
|
||||||
|
void VerilatedVcdSc::trace( const tp& object, const sc_string& name, int width ) {}
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( bool )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned char )
|
||||||
|
DECL_TRACE_METHOD_B( short unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( long unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( char )
|
||||||
|
DECL_TRACE_METHOD_B( short int )
|
||||||
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
DECL_TRACE_METHOD_B( long int )
|
||||||
|
DECL_TRACE_METHOD_A( float )
|
||||||
|
DECL_TRACE_METHOD_A( double )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bit )
|
||||||
|
DECL_TRACE_METHOD_A( sc_logic )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bool_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_logic_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_bool_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_logic_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_int_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signed )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_resolved )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef DECL_TRACE_METHOD_A
|
||||||
|
#undef DECL_TRACE_METHOD_B
|
||||||
|
|
||||||
|
//********************************************************************
|
213
include/verilated_vcd_sc.h
Normal file
213
include/verilated_vcd_sc.h
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
// -*- SystemC -*-
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// THIS MODULE IS PUBLICLY LICENSED
|
||||||
|
//
|
||||||
|
// Copyright 2001-2010 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.
|
||||||
|
//
|
||||||
|
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief SystemPerl tracing in VCD format
|
||||||
|
///
|
||||||
|
/// AUTHOR: Wilson Snyder
|
||||||
|
///
|
||||||
|
//=============================================================================
|
||||||
|
// SPDIFF_OFF
|
||||||
|
|
||||||
|
#ifndef _VERILATED_VCD_SC_H_
|
||||||
|
#define _VERILATED_VCD_SC_H_ 1
|
||||||
|
|
||||||
|
#include "verilated_sc.h"
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
|
|
||||||
|
// SPDIFF_ON
|
||||||
|
//=============================================================================
|
||||||
|
// VerilatedVcdSc
|
||||||
|
///
|
||||||
|
/// This class is passed to the SystemC simulation kernel, just like a
|
||||||
|
/// documented SystemC trace format.
|
||||||
|
|
||||||
|
class VerilatedVcdSc
|
||||||
|
: sc_trace_file
|
||||||
|
, public VerilatedVcdC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VerilatedVcdSc() {
|
||||||
|
sc_get_curr_simcontext()->add_trace_file(this);
|
||||||
|
# if (SYSTEMC_VERSION>=20060505)
|
||||||
|
// We want to avoid a depreciated warning, but still be back compatible.
|
||||||
|
// Turning off the message just for this still results in an annoying "to turn off" message.
|
||||||
|
sc_time t1sec(1,SC_SEC);
|
||||||
|
if (t1sec.to_default_time_units()!=0) {
|
||||||
|
sc_time tunits(1.0/t1sec.to_default_time_units(),SC_SEC);
|
||||||
|
spTrace()->set_time_unit(tunits.to_string());
|
||||||
|
}
|
||||||
|
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||||
|
# elif (SYSTEMC_VERSION>20011000)
|
||||||
|
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
|
||||||
|
// we allow both flavors with overloaded set_time_* functions.
|
||||||
|
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
|
||||||
|
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~VerilatedVcdSc() {}
|
||||||
|
/// Called by SystemC simulate()
|
||||||
|
virtual void cycle (bool delta_cycle) {
|
||||||
|
# if (SYSTEMC_VERSION>20011000)
|
||||||
|
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||||
|
# else
|
||||||
|
// VCD files must have integer timestamps, so we write all times in increments of time_resolution
|
||||||
|
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Fake outs for linker
|
||||||
|
|
||||||
|
#ifdef NC_SYSTEMC
|
||||||
|
// Cadence Incisive has these as abstract functions so we must create them
|
||||||
|
virtual void set_time_unit( int exponent10_seconds ) {} // deprecated
|
||||||
|
virtual void set_time_unit( double v, sc_time_unit tu ) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
# if (SYSTEMC_VERSION>=20050714)
|
||||||
|
// SystemC 2.1.v1
|
||||||
|
# define DECL_TRACE_METHOD_A(tp) \
|
||||||
|
virtual void trace( const tp& object, const std::string& name );
|
||||||
|
# define DECL_TRACE_METHOD_B(tp) \
|
||||||
|
virtual void trace( const tp& object, const std::string& name, int width );
|
||||||
|
|
||||||
|
virtual void write_comment (const std::string &);
|
||||||
|
virtual void trace (const unsigned int &, const std::string &, const char **);
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( bool )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_logic )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_B( unsigned char )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
|
#endif
|
||||||
|
DECL_TRACE_METHOD_B( char )
|
||||||
|
DECL_TRACE_METHOD_B( short )
|
||||||
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
DECL_TRACE_METHOD_B( long )
|
||||||
|
DECL_TRACE_METHOD_B( sc_dt::int64 )
|
||||||
|
DECL_TRACE_METHOD_B( sc_dt::uint64 )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( float )
|
||||||
|
DECL_TRACE_METHOD_A( double )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_int_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_uint_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_signed )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_unsigned )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxval )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxval_fast )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxnum )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_fxnum_fast )
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_bv_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
# elif (SYSTEMC_VERSION>20011000)
|
||||||
|
// SystemC 2.0.1
|
||||||
|
# define DECL_TRACE_METHOD_A(tp) \
|
||||||
|
virtual void trace( const tp& object, const sc_string& name );
|
||||||
|
# define DECL_TRACE_METHOD_B(tp) \
|
||||||
|
virtual void trace( const tp& object, const sc_string& name, int width );
|
||||||
|
|
||||||
|
virtual void write_comment (const sc_string &);
|
||||||
|
virtual void trace (const unsigned int &, const sc_string &, const char **);
|
||||||
|
virtual void delta_cycles (bool) {}
|
||||||
|
virtual void space( int n ) {}
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( bool )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bit )
|
||||||
|
DECL_TRACE_METHOD_A( sc_logic )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned char )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned short )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long )
|
||||||
|
#ifdef SYSTEMC_64BIT_PATCHES
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
|
#endif
|
||||||
|
#if (SYSTEMC_VERSION>20041000)
|
||||||
|
DECL_TRACE_METHOD_B( unsigned long long)
|
||||||
|
DECL_TRACE_METHOD_B( long long)
|
||||||
|
#endif
|
||||||
|
DECL_TRACE_METHOD_B( char )
|
||||||
|
DECL_TRACE_METHOD_B( short )
|
||||||
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
DECL_TRACE_METHOD_B( long )
|
||||||
|
DECL_TRACE_METHOD_A( float )
|
||||||
|
DECL_TRACE_METHOD_A( double )
|
||||||
|
DECL_TRACE_METHOD_A( sc_int_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signed )
|
||||||
|
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxval )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxval_fast )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxnum )
|
||||||
|
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bv_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_lv_base )
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
# else
|
||||||
|
// SystemC 1.2.1beta
|
||||||
|
# define DECL_TRACE_METHOD_A(tp) \
|
||||||
|
virtual void trace( const tp& object, const sc_string& name );
|
||||||
|
# define DECL_TRACE_METHOD_B(tp) \
|
||||||
|
virtual void trace( const tp& object, const sc_string& name, int width );
|
||||||
|
|
||||||
|
virtual void write_comment (const sc_string &);
|
||||||
|
virtual void trace (const unsigned int &, const sc_string &, const char **);
|
||||||
|
|
||||||
|
DECL_TRACE_METHOD_A( bool )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned char )
|
||||||
|
DECL_TRACE_METHOD_B( short unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( long unsigned int )
|
||||||
|
DECL_TRACE_METHOD_B( char )
|
||||||
|
DECL_TRACE_METHOD_B( short int )
|
||||||
|
DECL_TRACE_METHOD_B( int )
|
||||||
|
DECL_TRACE_METHOD_B( long int )
|
||||||
|
DECL_TRACE_METHOD_A( float )
|
||||||
|
DECL_TRACE_METHOD_A( double )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bit )
|
||||||
|
DECL_TRACE_METHOD_A( sc_logic )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bool_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_logic_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_bool_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_logic_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_int_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signed )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_resolved )
|
||||||
|
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
||||||
|
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# undef DECL_TRACE_METHOD_A
|
||||||
|
# undef DECL_TRACE_METHOD_B
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // guard
|
138
nodist/spdiff
Executable file
138
nodist/spdiff
Executable file
@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
######################################################################
|
||||||
|
#
|
||||||
|
# Copyright 2010-2010 by Wilson Snyder. This package is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# DESCRIPTION: Diff Verilator includes against SystemPerl include files
|
||||||
|
|
||||||
|
use Getopt::Long;
|
||||||
|
use IO::File;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
our $Debug;
|
||||||
|
our $Bad;
|
||||||
|
|
||||||
|
if (! GetOptions (
|
||||||
|
#"help" => \&usage,
|
||||||
|
"debug" => sub { $Debug = 1; },
|
||||||
|
)) {
|
||||||
|
die "usage();"
|
||||||
|
}
|
||||||
|
|
||||||
|
diff("$ARGV[0]/include/verilated_vcd_c.h", "$ARGV[1]/src/SpTraceVcdC.h");
|
||||||
|
diff("$ARGV[0]/include/verilated_vcd_sc.h", "$ARGV[1]/src/SpTraceVcd.h");
|
||||||
|
diff("$ARGV[0]/include/verilated_vcd_c.cpp", "$ARGV[1]/src/SpTraceVcdC.cpp");
|
||||||
|
diff("$ARGV[0]/include/verilated_vcd_sc.cpp", "$ARGV[1]/src/SpTraceVcd.cpp");
|
||||||
|
|
||||||
|
exit(10) if $Bad;
|
||||||
|
|
||||||
|
sub diff {
|
||||||
|
my $a=shift;
|
||||||
|
my $b=shift;
|
||||||
|
|
||||||
|
my $ta = "/tmp/spdiff.$$.a";
|
||||||
|
my $tb = "/tmp/spdiff.$$.b";
|
||||||
|
|
||||||
|
prep($a,$ta);
|
||||||
|
prep($b,$tb);
|
||||||
|
|
||||||
|
system("diff -u -w $ta $tb");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub prep {
|
||||||
|
my $filename = shift;
|
||||||
|
my $wfilename = shift;
|
||||||
|
|
||||||
|
my $sp;
|
||||||
|
if ($filename =~ m!src/Sp!) {
|
||||||
|
$sp = "Sp";
|
||||||
|
} elsif ($filename =~ m!include/verilated!) {
|
||||||
|
} else {
|
||||||
|
die "%Error: Not sure if Sp/Verilated: $filename,\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename";
|
||||||
|
my $fho = IO::File->new(">$wfilename") or die "%Error: $! writing $wfilename";
|
||||||
|
|
||||||
|
my @wf;
|
||||||
|
my $off;
|
||||||
|
while (defined(my $line = $fh->getline)) {
|
||||||
|
if ($line =~ m!// *SPDIFF_OFF!) {
|
||||||
|
$off = 1;
|
||||||
|
next;
|
||||||
|
} elsif ($line =~ m!// *SPDIFF_ON!) {
|
||||||
|
$off = 0;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
next if $off;
|
||||||
|
|
||||||
|
next if $line =~ /compile-command:/;
|
||||||
|
$line =~ s/SP_ABORT.*// if $sp;
|
||||||
|
$line =~ s/SP_NOTICE.*// if $sp;
|
||||||
|
$line =~ s/vl_fatal.*// if !$sp;
|
||||||
|
$line =~ s/VL_PRINT.*// if !$sp;
|
||||||
|
|
||||||
|
push @wf, $line;
|
||||||
|
|
||||||
|
my $check = $line;
|
||||||
|
$check =~ s/\bspace//i;
|
||||||
|
$check =~ s/\bsplit//i;
|
||||||
|
$check =~ s/"SP_TRACE"//;
|
||||||
|
|
||||||
|
if ($sp && $check =~ /Verilat/i
|
||||||
|
&& $check !~ /and newer/) {
|
||||||
|
warn "%Warning: $filename:$.: Verilator text in Sp version: $line";
|
||||||
|
$Bad = 1;
|
||||||
|
} elsif (!$sp && $check =~ /\b(Sp|SP)/
|
||||||
|
) {
|
||||||
|
warn "%Warning: $filename:$.: Sp text in Verilator version: $line";
|
||||||
|
$Bad = 1;
|
||||||
|
} elsif (!$sp && $check =~ /\<uint[0-9]+_t/) {
|
||||||
|
warn "%Warning: $filename:$.: uint in Verilator version: $line";
|
||||||
|
$Bad = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
!$off or die "%Error: $filename: SPDIFF_OFF block never terminated\n";
|
||||||
|
|
||||||
|
my $wholefile = join('',@wf);
|
||||||
|
|
||||||
|
if ($sp) {
|
||||||
|
$wholefile =~ s/SPTRACEVCDC_VERSION/VERILATED_VCD_VERSION/g;
|
||||||
|
$wholefile =~ s/SPTRACEVCDC_/VERILATED_VCD_C_/g;
|
||||||
|
$wholefile =~ s/SPTRACEVCD_TEST/VERILATED_VCD_TEST/g;
|
||||||
|
$wholefile =~ s/SPTRACEVCD_/VERILATED_VCD_SC_/g;
|
||||||
|
|
||||||
|
#
|
||||||
|
$wholefile =~ s/\bSpTraceFile\b/VerilatedVcdSc/g;
|
||||||
|
$wholefile =~ s/\bSpTraceFileC\b/VerilatedVcdC/g;
|
||||||
|
$wholefile =~ s/\bSpTraceVcd\b/VerilatedVcd/g;
|
||||||
|
$wholefile =~ s/\bSpTraceVcdCFile\b/VerilatedVcdC/g;
|
||||||
|
#
|
||||||
|
$wholefile =~ s/\bSpTraceCallInfo\b/VerilatedVcdCallInfo/g;
|
||||||
|
$wholefile =~ s/\bSpTraceCallback_t/VerilatedVcdCallback_t/g;
|
||||||
|
$wholefile =~ s/\bSpTraceVcd_/VerilatedVcd_/g;
|
||||||
|
$wholefile =~ s/\bSpTraceVcdSig\b/VerilatedVcdSig/g;
|
||||||
|
$wholefile =~ s/\bSpScBvExposer/VlScBvExposer/g;
|
||||||
|
#
|
||||||
|
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
|
||||||
|
#
|
||||||
|
$wholefile =~ s/\bSP_SC_BV/VL_SC_BV/g;
|
||||||
|
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fho->print($wholefile);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# compile-command: "./spdiff $SYP $V4"
|
||||||
|
# End:
|
10
readme.pod
10
readme.pod
@ -78,14 +78,14 @@ SYSTEMC_ARCH to the architecture name you used with SystemC, generally
|
|||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
If you will be using SystemC, download and install Verilog-Perl,
|
If you will be using SystemPerl or coverage, download and install
|
||||||
L<http://www.veripool.org/verilog-perl>.
|
Verilog-Perl, L<http://www.veripool.org/verilog-perl>.
|
||||||
|
|
||||||
=item
|
=item
|
||||||
|
|
||||||
If you will be using SystemC, download and install System-Perl,
|
If you will be using SystemPerl or coverage, download and install
|
||||||
L<http://www.veripool.org/systemperl>. Note you'll need to set a
|
System-Perl, L<http://www.veripool.org/systemperl>. Note you'll need to
|
||||||
C<SYSTEMPERL> environment variable to point to the downloaded kit.
|
set a C<SYSTEMPERL> environment variable to point to the downloaded kit.
|
||||||
Optionally also set C<SYSTEMPERL_INCLUDE> to point to the installed
|
Optionally also set C<SYSTEMPERL_INCLUDE> to point to the installed
|
||||||
headers.
|
headers.
|
||||||
|
|
||||||
|
@ -1614,11 +1614,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) {
|
||||||
if (optSystemPerl()) {
|
puts("class "+v3Global.opt.traceClassBase()+";\n");
|
||||||
puts("class SpTraceVcd;\n");
|
|
||||||
} else {
|
|
||||||
puts("class SpTraceVcdCFile;\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("\n//----------\n\n");
|
puts("\n//----------\n\n");
|
||||||
@ -1723,7 +1719,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
|||||||
}
|
}
|
||||||
if (v3Global.opt.trace() && !optSystemPerl()) {
|
if (v3Global.opt.trace() && !optSystemPerl()) {
|
||||||
if (modp->isTop()) puts("/// Trace signals in the model; called by application code\n");
|
if (modp->isTop()) puts("/// Trace signals in the model; called by application code\n");
|
||||||
puts("void trace (SpTraceVcdCFile* tfp, int levels, int options=0);\n");
|
puts("void trace (VerilatedVcdC* tfp, int levels, int options=0);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("\n// USER METHODS\n");
|
puts("\n// USER METHODS\n");
|
||||||
@ -1756,9 +1752,9 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
|||||||
|
|
||||||
if (!optSystemPerl() && v3Global.opt.trace()) {
|
if (!optSystemPerl() && v3Global.opt.trace()) {
|
||||||
ofp()->putsPrivate(false); // public:
|
ofp()->putsPrivate(false); // public:
|
||||||
puts("static void traceInit (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
|
puts("static void traceInit ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||||
puts("static void traceFull (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
|
puts("static void traceFull ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||||
puts("static void traceChg (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
|
puts("static void traceChg ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||||
@ -1920,8 +1916,9 @@ class EmitCTrace : EmitCStmts {
|
|||||||
// Includes
|
// Includes
|
||||||
if (optSystemPerl()) {
|
if (optSystemPerl()) {
|
||||||
puts("#include \"SpTraceVcd.h\"\n");
|
puts("#include \"SpTraceVcd.h\"\n");
|
||||||
|
} else {
|
||||||
|
puts("#include \"verilated_vcd_c.h\"\n");
|
||||||
}
|
}
|
||||||
puts("#include \"SpTraceVcdC.h\"\n");
|
|
||||||
puts("#include \""+ symClassName() +".h\"\n");
|
puts("#include \""+ symClassName() +".h\"\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
@ -1933,7 +1930,7 @@ class EmitCTrace : EmitCStmts {
|
|||||||
if (optSystemPerl()) {
|
if (optSystemPerl()) {
|
||||||
puts("SpTraceFile* tfp, int, int) {\n");
|
puts("SpTraceFile* tfp, int, int) {\n");
|
||||||
} else {
|
} else {
|
||||||
puts("SpTraceVcdCFile* tfp, int, int) {\n");
|
puts("VerilatedVcdC* tfp, int, int) {\n");
|
||||||
}
|
}
|
||||||
puts( "tfp->spTrace()->addCallback ("
|
puts( "tfp->spTrace()->addCallback ("
|
||||||
"&"+topClassName()+"::traceInit"
|
"&"+topClassName()+"::traceInit"
|
||||||
@ -1941,23 +1938,20 @@ class EmitCTrace : EmitCStmts {
|
|||||||
+", &"+topClassName()+"::traceChg, this);\n");
|
+", &"+topClassName()+"::traceChg, this);\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceInit(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
|
puts("void "+topClassName()+"::traceInit("
|
||||||
|
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
puts("// Callback from vcd->open()\n");
|
puts("// Callback from vcd->open()\n");
|
||||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||||
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||||
|
|
||||||
//Future; need to wait to estabilish backwards compatibility
|
|
||||||
puts("#if defined(SPTRACEVCDC_VERSION) && SPTRACEVCDC_VERSION >= 1330\n");
|
|
||||||
puts("vcdp->scopeEscape(' ');\n");
|
puts("vcdp->scopeEscape(' ');\n");
|
||||||
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
|
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
|
||||||
puts("vcdp->scopeEscape('.');\n"); // Restore so SystemPerl traced files won't break
|
puts("vcdp->scopeEscape('.');\n"); // Restore so SystemPerl traced files won't break
|
||||||
puts("#else\n");
|
|
||||||
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
|
|
||||||
puts("#endif\n");
|
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceFull(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
|
puts("void "+topClassName()+"::traceFull("
|
||||||
|
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
puts("// Callback from vcd->dump()\n");
|
puts("// Callback from vcd->dump()\n");
|
||||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||||
@ -1970,7 +1964,8 @@ class EmitCTrace : EmitCStmts {
|
|||||||
void emitTraceFast() {
|
void emitTraceFast() {
|
||||||
puts("\n//======================\n\n");
|
puts("\n//======================\n\n");
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceChg(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
|
puts("void "+topClassName()+"::traceChg("
|
||||||
|
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
puts("// Callback from vcd->dump()\n");
|
puts("// Callback from vcd->dump()\n");
|
||||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||||
|
@ -85,7 +85,10 @@ public:
|
|||||||
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
||||||
}
|
}
|
||||||
else if (v3Global.opt.trace()) {
|
else if (v3Global.opt.trace()) {
|
||||||
putMakeClassEntry(of, "SpTraceVcdC.cpp");
|
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||||
|
if (v3Global.opt.systemC()) {
|
||||||
|
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (support==2 && slow) {
|
else if (support==2 && slow) {
|
||||||
@ -187,7 +190,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
of.puts("\n### Link rules... (from --exe)\n");
|
of.puts("\n### Link rules... (from --exe)\n");
|
||||||
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n");
|
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a\n");
|
||||||
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS) 2>&1 | c++filt\n");
|
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS) 2>&1 | c++filt\n");
|
||||||
of.puts("\n");
|
of.puts("\n");
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ string V3Options::getenvSYSTEMPERL_INCLUDE() {
|
|||||||
// We warn about $SYSTEMPERL instead of _INCLUDE since that's more likely
|
// We warn about $SYSTEMPERL instead of _INCLUDE since that's more likely
|
||||||
// what users will want to set.
|
// what users will want to set.
|
||||||
if (var == "") {
|
if (var == "") {
|
||||||
v3fatal("Need $SYSTEMPERL and $SYSTEMPERL_INCLUDE in environment for --sp or --trace\n"
|
v3fatal("Need $SYSTEMPERL and $SYSTEMPERL_INCLUDE in environment for --sp or --coverage\n"
|
||||||
"Probably System-Perl isn't installed, see http://www.veripool.org/systemperl\n");
|
"Probably System-Perl isn't installed, see http://www.veripool.org/systemperl\n");
|
||||||
}
|
}
|
||||||
else if (var != "" && !V3Options::fileStatNormal(var+"/systemperl.h")) {
|
else if (var != "" && !V3Options::fileStatNormal(var+"/systemperl.h")) {
|
||||||
|
@ -205,7 +205,7 @@ class V3Options {
|
|||||||
bool systemC() const { return m_systemC; }
|
bool systemC() const { return m_systemC; }
|
||||||
bool systemPerl() const { return m_systemPerl; }
|
bool systemPerl() const { return m_systemPerl; }
|
||||||
bool usingSystemCLibs() const { return !lintOnly() && (systemPerl() || systemC()); }
|
bool usingSystemCLibs() const { return !lintOnly() && (systemPerl() || systemC()); }
|
||||||
bool usingSystemPerlLibs() const { return !lintOnly() && (systemPerl() || trace()); }
|
bool usingSystemPerlLibs() const { return !lintOnly() && (systemPerl() || coverage()); }
|
||||||
bool skipIdentical() const { return m_skipIdentical; }
|
bool skipIdentical() const { return m_skipIdentical; }
|
||||||
bool stats() const { return m_stats; }
|
bool stats() const { return m_stats; }
|
||||||
bool assertOn() const { return m_assert; } // assertOn as __FILE__ may be defined
|
bool assertOn() const { return m_assert; } // assertOn as __FILE__ may be defined
|
||||||
@ -279,6 +279,9 @@ class V3Options {
|
|||||||
bool oSubstConst() const { return m_oSubstConst; }
|
bool oSubstConst() const { return m_oSubstConst; }
|
||||||
bool oTable() const { return m_oTable; }
|
bool oTable() const { return m_oTable; }
|
||||||
|
|
||||||
|
// METHODS (uses above)
|
||||||
|
string traceClassBase() const { return systemPerl() ? "SpTraceVcd" : "VerilatedVcd"; }
|
||||||
|
|
||||||
// METHODS (from main)
|
// METHODS (from main)
|
||||||
static string version();
|
static string version();
|
||||||
static string argString(int argc, char** argv); ///< Return list of arguments as simple string
|
static string argString(int argc, char** argv); ///< Return list of arguments as simple string
|
||||||
|
@ -339,7 +339,8 @@ private:
|
|||||||
AstCFunc* newCFunc(AstCFuncType type, const string& name, AstCFunc* basep) {
|
AstCFunc* newCFunc(AstCFuncType type, const string& name, AstCFunc* basep) {
|
||||||
AstCFunc* funcp = new AstCFunc(basep->fileline(), name, basep->scopep());
|
AstCFunc* funcp = new AstCFunc(basep->fileline(), name, basep->scopep());
|
||||||
funcp->slow(basep->slow());
|
funcp->slow(basep->slow());
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar()+", SpTraceVcd* vcdp, uint32_t code");
|
funcp->argTypes(EmitCBaseVisitor::symClassVar()
|
||||||
|
+", "+v3Global.opt.traceClassBase()+"* vcdp, uint32_t code");
|
||||||
funcp->funcType(type);
|
funcp->funcType(type);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
basep->addNext(funcp);
|
basep->addNext(funcp);
|
||||||
|
@ -86,7 +86,7 @@ private:
|
|||||||
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
|
AstCFunc* newCFunc(AstCFuncType type, const string& name, bool slow) {
|
||||||
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
|
AstCFunc* funcp = new AstCFunc(m_scopetopp->fileline(), name, m_scopetopp);
|
||||||
funcp->slow(slow);
|
funcp->slow(slow);
|
||||||
funcp->argTypes(EmitCBaseVisitor::symClassVar()+", SpTraceVcd* vcdp, uint32_t code");
|
funcp->argTypes(EmitCBaseVisitor::symClassVar()+", "+v3Global.opt.traceClassBase()+"* vcdp, uint32_t code");
|
||||||
funcp->funcType(type);
|
funcp->funcType(type);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
m_scopetopp->addActivep(funcp);
|
m_scopetopp->addActivep(funcp);
|
||||||
|
@ -31,8 +31,7 @@ test_debug: prep_dbg compile run
|
|||||||
test_valgrind: prep_vg compile run
|
test_valgrind: prep_vg compile run
|
||||||
|
|
||||||
VERILATOR_FLAGS = --cc -f $(VERILATOR_ROOT)/test_v/input.vc top.v
|
VERILATOR_FLAGS = --cc -f $(VERILATOR_ROOT)/test_v/input.vc top.v
|
||||||
#Note turning on traces requires SystemPerl to be installed
|
VERILATOR_FLAGS += --trace
|
||||||
#VERILATOR_FLAGS += --trace
|
|
||||||
|
|
||||||
prep:
|
prep:
|
||||||
$(PERL) $(VERILATOR_ROOT)/bin/verilator $(DEBUG) $(VERILATOR_FLAGS)
|
$(PERL) $(VERILATOR_ROOT)/bin/verilator $(DEBUG) $(VERILATOR_FLAGS)
|
||||||
|
@ -29,12 +29,7 @@ endif
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
# Linking final exe -- presumes have a sim_main.cpp
|
# Linking final exe -- presumes have a sim_main.cpp
|
||||||
|
|
||||||
SP_SRCS = verilated.o
|
simx: sim_main.o $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a
|
||||||
ifeq ($(VM_TRACE),1)
|
|
||||||
SP_SRCS += SpTraceVcdC.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
simx: sim_main.o $(SP_SRCS) $(VM_PREFIX)__ALL.a
|
|
||||||
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||||
|
|
||||||
sim_main.o: sim_main.cpp $(VM_PREFIX).h
|
sim_main.o: sim_main.cpp $(VM_PREFIX).h
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <verilated.h> // Defines common routines
|
#include <verilated.h> // Defines common routines
|
||||||
#include "Vtop.h" // From Verilating "top.v"
|
#include "Vtop.h" // From Verilating "top.v"
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
# include <SpTraceVcdC.h> // Trace file format header (from SystemPerl)
|
# include <verilated_vcd_c.h> // Trace file format header
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Vtop *top; // Instantiation of module
|
Vtop *top; // Instantiation of module
|
||||||
@ -28,8 +28,8 @@ int main(int argc, char **argv, char **env) {
|
|||||||
|
|
||||||
#if VM_TRACE // If verilator was invoked with --trace
|
#if VM_TRACE // If verilator was invoked with --trace
|
||||||
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
||||||
cout << "Enabling waves...\n";
|
VL_PRINTF("Enabling waves...\n");
|
||||||
SpTraceVcdCFile* tfp = new SpTraceVcdCFile;
|
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||||
top->trace (tfp, 99); // Trace 99 levels of hierarchy
|
top->trace (tfp, 99); // Trace 99 levels of hierarchy
|
||||||
tfp->open ("vlt_dump.vcd"); // Open the dump file
|
tfp->open ("vlt_dump.vcd"); // Open the dump file
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,7 +50,7 @@ ifeq ($(VM_SP_OR_SC),1)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
#Default compile, using normal make rules
|
#Default compile, using normal make rules
|
||||||
#$(VM_PREFIX): $(SP_SRCS) $(VK_OBJS)
|
#$(VM_PREFIX): $(VK_GLOBAL_OBJS) $(VK_OBJS)
|
||||||
# $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
# $(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt
|
||||||
|
|
||||||
#Our own compile rules; Faster compile, all in one file
|
#Our own compile rules; Faster compile, all in one file
|
||||||
|
@ -462,7 +462,7 @@ sub compile {
|
|||||||
$self->error("Test requires SystemC; ignore error since not installed\n");
|
$self->error("Test requires SystemC; ignore error since not installed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
elsif ($self->{trace} && !$Have_System_Perl) {
|
elsif ($self->{coverage} && !$Have_System_Perl) {
|
||||||
$self->error("Test requires SystemPerl; ignore error since not installed\n");
|
$self->error("Test requires SystemPerl; ignore error since not installed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -729,7 +729,7 @@ sub _make_main {
|
|||||||
print $fh "#include \"verilated.h\"\n";
|
print $fh "#include \"verilated.h\"\n";
|
||||||
print $fh "#include \"systemc.h\"\n" if $self->sc;
|
print $fh "#include \"systemc.h\"\n" if $self->sc;
|
||||||
print $fh "#include \"systemperl.h\"\n" if $self->sp;
|
print $fh "#include \"systemperl.h\"\n" if $self->sp;
|
||||||
print $fh "#include \"SpTraceVcdC.h\"\n" if $self->{trace} && !$self->sp;
|
print $fh "#include \"verilated_vcd_c.h\"\n" if $self->{trace} && !$self->sp;
|
||||||
print $fh "#include \"SpTraceVcd.h\"\n" if $self->{trace} && $self->sp;
|
print $fh "#include \"SpTraceVcd.h\"\n" if $self->{trace} && $self->sp;
|
||||||
|
|
||||||
print $fh "$VM_PREFIX * topp;\n";
|
print $fh "$VM_PREFIX * topp;\n";
|
||||||
@ -774,7 +774,7 @@ sub _make_main {
|
|||||||
if ($self->{sp}) {
|
if ($self->{sp}) {
|
||||||
$fh->print(" SpTraceFile* tfp = new SpTraceFile;\n");
|
$fh->print(" SpTraceFile* tfp = new SpTraceFile;\n");
|
||||||
} else {
|
} else {
|
||||||
$fh->print(" SpTraceVcdCFile* tfp = new SpTraceVcdCFile;\n");
|
$fh->print(" VerilatedVcdC* tfp = new VerilatedVcdC;\n");
|
||||||
}
|
}
|
||||||
$fh->print(" topp->trace (tfp, 99);\n");
|
$fh->print(" topp->trace (tfp, 99);\n");
|
||||||
$fh->print(" tfp->open (\"$self->{obj_dir}/simx.vcd\");\n");
|
$fh->print(" tfp->open (\"$self->{obj_dir}/simx.vcd\");\n");
|
||||||
|
23
test_regress/t/t_dist_spdiff.pl
Executable file
23
test_regress/t/t_dist_spdiff.pl
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2010 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.
|
||||||
|
|
||||||
|
my $root = "..";
|
||||||
|
if (!-r "$root/.git") {
|
||||||
|
$Self->skip("Not in a git repository");
|
||||||
|
} else {
|
||||||
|
my $cmd = "cd $root && nodist/spdiff . $ENV{SYSTEMPERL}";
|
||||||
|
my $grep = `$cmd`;
|
||||||
|
print "$grep\n";
|
||||||
|
if ($grep ne "") {
|
||||||
|
$Self->error("Include mismatches SystemPerl src\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
@ -4,7 +4,7 @@
|
|||||||
// without warranty, 2008 by Wilson Snyder.
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
#include <verilated.h>
|
#include <verilated.h>
|
||||||
#include <SpTraceVcdC.h>
|
#include <verilated_vcd_c.h>
|
||||||
|
|
||||||
#include "Vt_trace_public_func.h"
|
#include "Vt_trace_public_func.h"
|
||||||
#include "Vt_trace_public_func_t.h"
|
#include "Vt_trace_public_func_t.h"
|
||||||
@ -23,7 +23,7 @@ int main(int argc, char **argv, char **env) {
|
|||||||
Verilated::debug(0);
|
Verilated::debug(0);
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
|
|
||||||
SpTraceVcdCFile* tfp = new SpTraceVcdCFile;
|
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||||
top->trace(tfp,99);
|
top->trace(tfp,99);
|
||||||
tfp->open("obj_dir/t_trace_public_func/simx.vcd");
|
tfp->open("obj_dir/t_trace_public_func/simx.vcd");
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// without warranty, 2008 by Wilson Snyder.
|
// without warranty, 2008 by Wilson Snyder.
|
||||||
|
|
||||||
#include <verilated.h>
|
#include <verilated.h>
|
||||||
#include <SpTraceVcdC.h>
|
#include <verilated_vcd_c.h>
|
||||||
|
|
||||||
#include "Vt_trace_public_sig.h"
|
#include "Vt_trace_public_sig.h"
|
||||||
#include "Vt_trace_public_sig_t.h"
|
#include "Vt_trace_public_sig_t.h"
|
||||||
@ -23,7 +23,7 @@ int main(int argc, char **argv, char **env) {
|
|||||||
Verilated::debug(0);
|
Verilated::debug(0);
|
||||||
Verilated::traceEverOn(true);
|
Verilated::traceEverOn(true);
|
||||||
|
|
||||||
SpTraceVcdCFile* tfp = new SpTraceVcdCFile;
|
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||||
top->trace(tfp,99);
|
top->trace(tfp,99);
|
||||||
tfp->open("obj_dir/t_trace_public_sig/simx.vcd");
|
tfp->open("obj_dir/t_trace_public_sig/simx.vcd");
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ test_debug: precopy prep_dbg preproc compile run
|
|||||||
|
|
||||||
V_FLAGS = -f $(VERILATOR_ROOT)/test_v/input.vc
|
V_FLAGS = -f $(VERILATOR_ROOT)/test_v/input.vc
|
||||||
VERILATOR_FLAGS = --sc $(V_FLAGS) top.v
|
VERILATOR_FLAGS = --sc $(V_FLAGS) top.v
|
||||||
|
VERILATOR_FLAGS += --trace
|
||||||
|
|
||||||
precopy: obj_dir obj_dir/sc_main.cpp
|
precopy: obj_dir obj_dir/sc_main.cpp
|
||||||
obj_dir/sc_main.cpp: ../test_sp/sc_main.cpp
|
obj_dir/sc_main.cpp: ../test_sp/sc_main.cpp
|
||||||
|
@ -16,9 +16,7 @@ default: simx
|
|||||||
include Vtop.mk
|
include Vtop.mk
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Use sp_log.cpp, so we can get output in sim.log
|
|
||||||
|
|
||||||
CPPFLAGS += -DUTIL_PRINTF=printf
|
|
||||||
CPPFLAGS += -Wno-deprecated
|
CPPFLAGS += -Wno-deprecated
|
||||||
CPPFLAGS += $(SYSTEMC_CXX_FLAGS)
|
CPPFLAGS += $(SYSTEMC_CXX_FLAGS)
|
||||||
|
|
||||||
@ -27,11 +25,9 @@ LDFLAGS += $(SYSTEMC_CXX_FLAGS)
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
# Linking final exe -- presumes have a sim_main.cpp
|
# Linking final exe -- presumes have a sim_main.cpp
|
||||||
|
|
||||||
SP_SRCS = verilated.o
|
|
||||||
|
|
||||||
SC_LIB = $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/libsystemc.a
|
SC_LIB = $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/libsystemc.a
|
||||||
|
|
||||||
simx: sc_main.o $(SP_SRCS) \
|
simx: sc_main.o $(VK_GLOBAL_OBJS) \
|
||||||
$(VM_PREFIX)__ALL.a $(SC_LIB)
|
$(VM_PREFIX)__ALL.a $(SC_LIB)
|
||||||
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(SC_LIBS) $(LIBS) 2>&1 | c++filt
|
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(SC_LIBS) $(LIBS) 2>&1 | c++filt
|
||||||
|
|
||||||
|
@ -31,11 +31,9 @@ LDFLAGS += $(SYSTEMC_CXX_FLAGS)
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
# Linking final exe -- presumes have a sim_main.cpp
|
# Linking final exe -- presumes have a sim_main.cpp
|
||||||
|
|
||||||
SP_SRCS = Sp.o verilated.o
|
|
||||||
|
|
||||||
SC_LIB = $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/libsystemc.a
|
SC_LIB = $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/libsystemc.a
|
||||||
|
|
||||||
simx: sc_main.o $(SP_SRCS) \
|
simx: sc_main.o $(VK_GLOBAL_OBJS) \
|
||||||
$(VM_PREFIX)__ALL.a $(SC_LIB)
|
$(VM_PREFIX)__ALL.a $(SC_LIB)
|
||||||
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(SC_LIBS) $(LIBS) 2>&1 | c++filt
|
$(LINK) $(LDFLAGS) -g $^ $(LOADLIBES) $(LDLIBS) -o $@ $(SC_LIBS) $(LIBS) 2>&1 | c++filt
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
# include "SpCoverage.h"
|
# include "SpCoverage.h"
|
||||||
#else
|
#else
|
||||||
# include "systemc.h" // SystemC global header
|
# include "systemc.h" // SystemC global header
|
||||||
|
# include "verilated_vcd_sc.h" // Tracing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Vtop.h" // Top level header, generated from verilog
|
#include "Vtop.h" // Top level header, generated from verilog
|
||||||
@ -118,7 +119,11 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
#if WAVES
|
#if WAVES
|
||||||
cout << "Enabling waves...\n";
|
cout << "Enabling waves...\n";
|
||||||
|
# ifdef SYSTEMPERL
|
||||||
SpTraceFile* tfp = new SpTraceFile;
|
SpTraceFile* tfp = new SpTraceFile;
|
||||||
|
# else
|
||||||
|
VerilatedVcdSc* tfp = new VerilatedVcdSc;
|
||||||
|
# endif
|
||||||
top->trace (tfp, 99);
|
top->trace (tfp, 99);
|
||||||
tfp->open ("vlt_dump.vcd");
|
tfp->open ("vlt_dump.vcd");
|
||||||
#endif
|
#endif
|
||||||
@ -156,7 +161,7 @@ int sc_main(int argc, char* argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!passed) {
|
if (!passed) {
|
||||||
UTIL_PRINTF ("A Test failed!!\n");
|
VL_PRINTF ("A Test failed!!\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user