Support IEEE time units and time precisions, #234. (#2253)

Includes `timescale, $printtimescale, $timeformat.
VL_TIME_MULTIPLIER, VL_TIME_PRECISION, VL_TIME_UNIT have been removed
and the time precision must now match the SystemC time precision.
To get closer behavior to older versions, use e.g. --timescale-override
"1ps/1ps".
This commit is contained in:
Wilson Snyder 2020-04-15 19:39:03 -04:00 committed by GitHub
parent 9b8aebb00c
commit d4f7f5297a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
131 changed files with 2611 additions and 1290 deletions

View File

@ -7,6 +7,13 @@ The contributors that suggested a given feature are shown in []. Thanks!
** Add simplistic class support with many restrictions, see manual, #377.
** Support IEEE time units and time precisions, #234.
Includes `timescale, $printtimescale, $timeformat.
VL_TIME_MULTIPLIER, VL_TIME_PRECISION, VL_TIME_UNIT have been removed
and the time precision must now match the SystemC time precision. To
get closer behavior to older versions, use e.g. --timescale-override
"1ps/1ps".
** Add --build to call make automatically, #2249. [Yutetsu TAKATSUKASA]
** Configuring with ccache present now defaults to using it; see OBJCACHE.

View File

@ -372,6 +372,8 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--threads <threads> Enable multithreading
--threads-dpi <mode> Enable multithreaded DPI
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
--timescale <timescale> Sets default timescale
--timescale-override <timescale> Overrides all timescales
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
@ -1266,6 +1268,10 @@ This allows for the secure delivery of sensitive IP without the need for
encrypted RTL (i.e. IEEE P1735). See examples/make_protect_lib in the
distribution for a demonstration of how to build and use the DPI library.
When using --protect-lib it is advised to also use C<--timescale-override
/1fs> to ensure the model has a time resolution that is always compatible
with the time precision of the upper instantiating module.
=item --private
Opposite of --public. Is the default; this option exists for backwards
@ -1424,6 +1430,24 @@ Rarely needed. When using --threads, specify the number of mtasks the
model is to be partitioned into. If unspecified, Verilator approximates a
good value.
=item --timescale I<timeunit>/I<timeprecision>
Sets default timescale, timeunit and timeprecision for when `timescale does
not occur in sources. Default is "1ps/1ps" (to match SystemC). This is
overriden by C<--timescale-override>.
=item --timescale-override I<timeunit>/I<timeprecision>
=item --timescale-override /I<timeprecision>
Overrides all `timescales in sources. The timeunit may be left empty to
specify only to override the timeprecision, e.g. "/1fs".
The time precision must be consistent with SystemC's
sc_set_time_resolution, or the C++ code instantiating the Verilated module.
As 1fs is the finest time precision it may be desirable to always use a
precision of 1fs.
=item --top-module I<topname>
When the input Verilog contains more than one top level module, specifies
@ -1786,10 +1810,10 @@ Defaults to "profile_threads.dat".
=item +verilator+prof+threads+start+I<value>
When using --prof-threads at simulation runtime, Verilator will wait until
$time is at this value, then start the profiling warmup, then
capturing. Generally this should be set to some time that is well within
the normal operation of the simulation, i.e. outside of reset. If 0, the
dump is disabled. Defaults to 1.
$time is at this value (expressed in units of the time precision), then
start the profiling warmup, then capturing. Generally this should be set to
some time that is well within the normal operation of the simulation,
i.e. outside of reset. If 0, the dump is disabled. Defaults to 1.
=item +verilator+prof+threads+window+I<value>
@ -2249,7 +2273,8 @@ example:
vluint64_t main_time = 0; // Current simulation time
// This is a 64-bit integer to reduce wrap over issues and
// allow modulus. You can also use a double, if you wish.
// allow modulus. This is in units of the timeprecision
// used in Verilog (or from --timescale-override)
double sc_time_stamp () { // Called by $time in Verilog
return main_time; // converts to double, to match
@ -3788,7 +3813,7 @@ This section describes specific limitations for each language keyword.
`begin_keywords, `begin_keywords, `define, `else, `elsif, `end_keywords,
`endif, `error, `ifdef, `ifndef, `include, `line, `systemc_ctor,
`systemc_dtor, `systemc_header, `systemc_imp_header,
`systemc_implementation, `systemc_interface, `timescale, `undef, `verilog
`systemc_implementation, `systemc_interface, `undef, `verilog
Fully supported.
@ -3940,13 +3965,6 @@ Supported, but the instantiating C++/SystemC testbench must call
to register the command line before calling $test$plusargs or
$value$plusargs.
=item $timeformat
Not supported as Verilator needs to determine all formatting at compile
time. Generally you can just ifdef them out for no ill effect. Note also
VL_TIME_MULTIPLIER can be defined at compile time to move the decimal point
when displaying all times, model wide.
=back
@ -4619,6 +4637,18 @@ increases.
Ignoring this warning will only slow simulations, it will simulate
correctly.
=item TIMESCALEMOD
Error that `timescale is used in some but not all modules.
Recommend using --timescale argument, or in front of all modules use:
`include "timescale.vh"
Then in that file set the timescale.
This is an error due to IEEE specifications, but it may be disabled similar
to warnings. Ignoring this error may result in a module having an
unexpected timescale.
=item UNDRIVEN
@ -5008,8 +5038,8 @@ to VerilatedVcdSc in the examples/make_tracing_sc/sc_main.cpp file of the
distribution, and below.
Alternatively you may use the C++ trace mechanism described in the previous
question, however the timescale and timeprecision will not inherited from
your SystemC settings.
question, note the timescale and timeprecision will be inherited from your
SystemC settings.
You also need to compile verilated_vcd_sc.cpp and verilated_vcd_c.cpp and
add them to your link, preferably by adding the dependencies in

View File

@ -29,6 +29,7 @@
#include <algorithm>
#include <cctype>
#include <cerrno>
#include <tgmath.h>
#include <sys/stat.h> // mkdir
// clang-format off
@ -101,8 +102,12 @@ void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
if (0 && hier) {}
Verilated::gotFinish(true);
VL_PRINTF( // Not VL_PRINTF_MT, already on main thread
"%%Error: %s:%d: %s\n", filename, linenum, msg);
if (filename && filename[0]) {
// Not VL_PRINTF_MT, already on main thread
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
} else {
VL_PRINTF("%%Error: %s\n", msg);
}
Verilated::flushCall();
VL_PRINTF("Aborting...\n"); // Not VL_PRINTF_MT, already on main thread
@ -238,6 +243,8 @@ Verilated::Serialized::Serialized() {
s_errorLimit = 1;
s_randReset = 0;
s_randSeed = 0;
s_timeunit = -VL_TIME_UNIT; // Initial value until overriden by _Vconfigure
s_timeprecision = -VL_TIME_PRECISION; // Initial value until overriden by _Vconfigure
}
Verilated::NonSerialized::NonSerialized() {
@ -252,6 +259,9 @@ Verilated::NonSerialized::~NonSerialized() {
}
}
size_t Verilated::serialized2Size() VL_PURE { return sizeof(VerilatedImp::m_ser); }
void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.m_ser; }
//===========================================================================
// Random -- Mostly called at init time, so not inline.
@ -608,6 +618,31 @@ std::string VL_DECIMAL_NW(int width, WDataInP lwp) VL_MT_SAFE {
return output;
}
std::string _vl_vsformat_time(char* tmp, double ld, bool left, size_t width) {
// Double may lose precision, but sc_time_stamp has similar limit
std::string suffix = VerilatedImp::timeFormatSuffix();
int userUnits = VerilatedImp::timeFormatUnits(); // 0..-15
int fracDigits = VerilatedImp::timeFormatPrecision(); // 0..N
int prec = Verilated::timeprecision(); // 0..-15
int shift = prec - userUnits + fracDigits; // 0..-15
double shiftd = vl_time_multiplier(shift);
double scaled = ld * shiftd;
QData fracDiv = static_cast<QData>(vl_time_multiplier(fracDigits));
QData whole = static_cast<QData>(scaled) / fracDiv;
QData fraction = static_cast<QData>(scaled) % fracDiv;
int digits;
if (!fracDigits) {
digits = sprintf(tmp, "%" VL_PRI64 "u%s", whole, suffix.c_str());
} else {
digits = sprintf(tmp, "%" VL_PRI64 "u.%0*" VL_PRI64 "u%s", whole, fracDigits, fraction,
suffix.c_str());
}
int needmore = width - digits;
std::string padding;
if (needmore > 0) padding.append(needmore, ' '); // Pad with spaces
return left ? (tmp + padding) : (padding + tmp);
}
// Do a va_arg returning a quad, assuming input argument is anything less than wide
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_IDATASIZE) ? va_arg(ap, IData) : va_arg(ap, QData))
@ -688,10 +723,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
if (lbits) {} // UNUSED - always 64
switch (fmt) {
case '^': { // Realtime
int digits = sprintf(tmp, "%g", d / VL_TIME_MULTIPLIER);
int needmore = width - digits;
if (needmore > 0) output.append(needmore, ' '); // Pre-pad spaces
output += tmp;
if (!widthSet) width = VerilatedImp::timeFormatWidth();
output += _vl_vsformat_time(tmp, d, left, width);
break;
}
default: {
@ -792,20 +825,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
break;
}
case 't': { // Time
int digits;
if (VL_TIME_MULTIPLIER == 1) {
digits = sprintf(tmp, "%" VL_PRI64 "u", ld);
} else if (VL_TIME_MULTIPLIER == 1000) {
digits = sprintf(tmp, "%" VL_PRI64 "u.%03" VL_PRI64 "u",
static_cast<QData>(ld / VL_TIME_MULTIPLIER),
static_cast<QData>(ld % VL_TIME_MULTIPLIER));
} else {
VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER");
}
int needmore = width - digits;
std::string padding;
if (needmore > 0) padding.append(needmore, ' '); // Pad with spaces
output += left ? (tmp + padding) : (padding + tmp);
if (!widthSet) width = VerilatedImp::timeFormatWidth();
output += _vl_vsformat_time(tmp, static_cast<double>(ld), left, width);
break;
}
case 'b':
@ -1984,6 +2005,69 @@ int VL_TIME_STR_CONVERT(const char* strp) {
if (*strp) return 0;
return scale;
}
static const char* vl_time_str(int scale) {
static const char* const names[]
= {"1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns",
"10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs"};
if (scale < 0) scale = -scale;
if (VL_UNLIKELY(scale > 15)) scale = 0;
return names[scale];
}
double vl_time_multiplier(int scale) {
// Return timescale multipler -15 to +15
// For speed, this does not check for illegal values
static double pow10[] = {1.0,
10.0,
100.0,
1000.0,
10000.0,
100000.0,
1000000.0,
10000000.0,
100000000.0,
1000000000.0,
10000000000.0,
100000000000.0,
1000000000000.0,
10000000000000.0,
100000000000000.0,
1000000000000000.0};
static double neg10[] = {1.0,
0.1,
0.01,
0.001,
0.0001,
0.00001,
0.000001,
0.0000001,
0.00000001,
0.000000001,
0.0000000001,
0.00000000001,
0.000000000001,
0.0000000000001,
0.00000000000001,
0.000000000000001};
if (scale < 0) {
return neg10[-scale];
} else {
return pow10[scale];
}
}
const char* Verilated::timeunitString() VL_MT_SAFE { return vl_time_str(timeunit()); }
const char* Verilated::timeprecisionString() VL_MT_SAFE { return vl_time_str(timeprecision()); }
void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp) VL_MT_SAFE {
VL_PRINTF_MT("Time scale of %s is %s / %s\n", namep, timeunitp,
Verilated::timeprecisionString());
}
void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
int width) VL_MT_SAFE {
VerilatedImp::timeFormatUnits(units);
VerilatedImp::timeFormatPrecision(precision);
VerilatedImp::timeFormatSuffix(suffix);
VerilatedImp::timeFormatWidth(width);
}
//===========================================================================
// Verilated:: Methods
@ -2051,6 +2135,43 @@ void Verilated::fatalOnVpiError(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_fatalOnVpiError = flag;
}
void Verilated::timeunit(int value) VL_MT_SAFE {
if (value < 0) value = -value; // Stored as 0..15
VerilatedLockGuard lock(m_mutex);
s_s.s_timeunit = value;
}
void Verilated::timeprecision(int value) VL_MT_SAFE {
if (value < 0) value = -value; // Stored as 0..15
VerilatedLockGuard lock(m_mutex);
s_s.s_timeprecision = value;
#ifdef SYSTEMC_VERSION
sc_time sc_res = sc_get_time_resolution();
int sc_prec = 99;
if (sc_res == sc_time(1, SC_SEC)) {
sc_prec = 0;
} else if (sc_res == sc_time(1, SC_MS)) {
sc_prec = 3;
} else if (sc_res == sc_time(1, SC_US)) {
sc_prec = 6;
} else if (sc_res == sc_time(1, SC_NS)) {
sc_prec = 9;
} else if (sc_res == sc_time(1, SC_PS)) {
sc_prec = 12;
} else if (sc_res == sc_time(1, SC_FS)) {
sc_prec = 15;
}
if (value != sc_prec) {
std::ostringstream msg;
msg << "SystemC's sc_set_time_resolution is 10^-" << sc_prec
<< ", which does not match Verilog timeprecision 10^-" << value
<< ". Suggest use 'sc_set_time_resolution(" << vl_time_str(value)
<< ")', or Verilator '--timescale-override " << vl_time_str(sc_prec) << "/"
<< vl_time_str(sc_prec) << "'";
std::string msgs = msg.str();
VL_FATAL_MT("", 0, "", msgs.c_str());
}
#endif
}
void Verilated::profThreadsStart(vluint64_t flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_ns.s_profThreadsStart = flag;
@ -2180,6 +2301,20 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
//===========================================================================
// VerilatedImp:: Methods
std::string VerilatedImp::timeFormatSuffix() VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_sergMutex);
return s_s.m_serg.m_timeFormatSuffix;
}
void VerilatedImp::timeFormatSuffix(const std::string& value) VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_sergMutex);
s_s.m_serg.m_timeFormatSuffix = value;
}
void VerilatedImp::timeFormatUnits(int value) VL_MT_SAFE { s_s.m_ser.m_timeFormatUnits = value; }
void VerilatedImp::timeFormatPrecision(int value) VL_MT_SAFE {
s_s.m_ser.m_timeFormatPrecision = value;
}
void VerilatedImp::timeFormatWidth(int value) VL_MT_SAFE { s_s.m_ser.m_timeFormatWidth = value; }
void VerilatedImp::internalsDump() VL_MT_SAFE {
VerilatedLockGuard lock(s_s.m_argMutex);
VL_PRINTF_MT("internalsDump:\n");
@ -2349,11 +2484,13 @@ VerilatedScope::~VerilatedScope() {
}
void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
const char* identifier, const Type type) VL_MT_UNSAFE {
const char* identifier, vlsint8_t timeunit,
const Type type) VL_MT_UNSAFE {
// Slowpath - called once/scope at construction
// We don't want the space and reference-count access overhead of strings.
m_symsp = symsp;
m_type = type;
m_timeunit = timeunit;
char* namep = new char[strlen(prefixp) + strlen(suffixp) + 2];
strcpy(namep, prefixp);
if (*prefixp && *suffixp) strcat(namep, ".");

View File

@ -329,19 +329,21 @@ private:
VerilatedVarNameMap* m_varsp; ///< Variable map
const char* m_namep; ///< Scope name (Slowpath)
const char* m_identifierp; ///< Identifier of scope (with escapes removed)
vlsint8_t m_timeunit; ///< Timeunit in negative power-of-10
Type m_type; ///< Type of the scope
public: // But internals only - called from VerilatedModule's
VerilatedScope();
~VerilatedScope();
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
const char* identifier, const Type type) VL_MT_UNSAFE;
const char* identifier, vlsint8_t timeunit, const Type type) VL_MT_UNSAFE;
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
void varInsert(int finalize, const char* namep, void* datap, VerilatedVarType vltype,
int vlflags, int dims, ...) VL_MT_UNSAFE;
// ACCESSORS
const char* name() const { return m_namep; }
const char* identifier() const { return m_identifierp; }
vlsint8_t timeunit() const { return m_timeunit; }
inline VerilatedSyms* symsp() const { return m_symsp; }
VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT;
VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; }
@ -383,6 +385,8 @@ class Verilated {
bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
// Slow path
unsigned s_timeunit : 4; ///< Time unit as 0..15
unsigned s_timeprecision : 4; ///< Time precision as 0..15
int s_errorCount; ///< Number of errors
int s_errorLimit; ///< Stop on error number
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
@ -481,6 +485,13 @@ public:
/// Enable/disable vpi fatal
static void fatalOnVpiError(bool flag) VL_MT_SAFE;
static bool fatalOnVpiError() VL_MT_SAFE { return s_s.s_fatalOnVpiError; }
/// Time handling
static int timeunit() VL_MT_SAFE { return -s_s.s_timeunit; }
static const char* timeunitString() VL_MT_SAFE;
static void timeunit(int value) VL_MT_SAFE;
static int timeprecision() VL_MT_SAFE { return -s_s.s_timeprecision; }
static const char* timeprecisionString() VL_MT_SAFE;
static void timeprecision(int value) VL_MT_SAFE;
/// --prof-threads related settings
static void profThreadsStart(vluint64_t flag) VL_MT_SAFE;
static vluint64_t profThreadsStart() VL_MT_SAFE { return s_ns.s_profThreadsStart; }
@ -555,8 +566,10 @@ public:
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
static int exportFuncNum(const char* namep) VL_MT_SAFE;
static size_t serializedSize() VL_PURE { return sizeof(s_s); }
static void* serializedPtr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
static size_t serialized1Size() VL_PURE { return sizeof(s_s); }
static void* serialized1Ptr() VL_MT_UNSAFE { return &s_s; } // Unsafe, for Serialize only
static size_t serialized2Size() VL_PURE;
static void* serialized2Ptr() VL_MT_UNSAFE;
#ifdef VL_THREADED
/// Set the mtaskId, called when an mtask starts
static void mtaskId(vluint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
@ -650,6 +663,8 @@ inline QData VL_RDTSC_Q() {
}
#endif
extern void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp) VL_MT_SAFE;
/// Math
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp,
bool is_modulus);
@ -787,37 +802,54 @@ extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
extern int VL_TIME_STR_CONVERT(const char* strp) VL_PURE;
// These are deprecated and used only to establish the default precision/units.
// Use Verilator timescale-override for better control.
// clang-format off
#ifndef VL_TIME_PRECISION
# ifdef VL_TIME_PRECISION_STR
# define VL_TIME_PRECISION VL_TIME_STR_CONVERT(VL_STRINGIFY(VL_TIME_PRECISION_STR))
# else
# define VL_TIME_PRECISION (-12) ///< Timescale units only for for VPI return - picoseconds
# define VL_TIME_PRECISION (-12) ///< Timescale default units if not in Verilog - picoseconds
# endif
#endif
#ifndef VL_TIME_UNIT
# ifdef VL_TIME_UNIT_STR
# define VL_TIME_UNIT VL_TIME_STR_CONVERT(VL_STRINGIFY(VL_TIME_PRECISION_STR))
# else
# define VL_TIME_UNIT (-12) ///< Timescale units only for for VPI return - picoseconds
# define VL_TIME_UNIT (-12) ///< Timescale default units if not in Verilog - picoseconds
# endif
#endif
#ifndef VL_TIME_MULTIPLIER
# define VL_TIME_MULTIPLIER 1
#endif
/// Return current simulation time
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
# define VL_TIME_I() (static_cast<IData>(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q() (static_cast<QData>(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() (static_cast<double>(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
#else
# define VL_TIME_I() (static_cast<IData>(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q() (static_cast<QData>(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() (static_cast<double>(sc_time_stamp()*VL_TIME_MULTIPLIER))
extern double sc_time_stamp();
#if defined(SYSTEMC_VERSION)
# if SYSTEMC_VERSION > 20011000
// Already defined: extern sc_time sc_time_stamp();
inline vluint64_t vl_time_stamp64() { return sc_time_stamp().value(); }
# else // Before SystemC changed to integral time representation
// Already defined: extern double sc_time_stamp();
inline vluint64_t vl_time_stamp64() { return static_cast<vluint64_t>(sc_time_stamp()); }
# endif
#else // Non-SystemC
# ifdef VL_TIME_STAMP64
extern vluint64_t vl_time_stamp64();
# else
extern double sc_time_stamp(); // Verilator 4.032 and newer
inline vluint64_t vl_time_stamp64() { return static_cast<vluint64_t>(sc_time_stamp()); }
# endif
#endif
#define VL_TIME_I() (static_cast<IData>(vl_time_stamp64()))
#define VL_TIME_Q() (static_cast<QData>(vl_time_stamp64()))
#define VL_TIME_D() (static_cast<double>(vl_time_stamp64()))
/// Time scaled from 1-per-precision into a module's time units ("Unit"-ed, not "United")
// Optimized assuming scale is always constant.
// Can't use multiply in Q flavor, as might lose precision
#define VL_TIME_UNITED_Q(scale) (VL_TIME_Q() / static_cast<QData>(scale))
#define VL_TIME_UNITED_D(scale) (VL_TIME_D() * (1.0 / (scale)))
/// Time imported from units to time precision
double vl_time_multiplier(int scale);
/// Evaluate expression if debug enabled
#ifdef VL_DEBUG
# define VL_DEBUG_IF(text) {if (VL_UNLIKELY(Verilated::debug())) {text}}

View File

@ -86,6 +86,8 @@ VerilatedFst::VerilatedFst(void* fst)
, m_symbolp(NULL)
, m_sigs_oldvalp(NULL) {
m_valueStrBuffer.reserve(64 + 1); // Need enough room for quad
set_time_unit(Verilated::timeunitString());
set_time_resolution(Verilated::timeprecisionString());
}
VerilatedFst::~VerilatedFst() {

View File

@ -235,11 +235,11 @@ public:
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
/// Set time units (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_unit(const char* unitp) { m_sptrace.set_time_unit(unitp); }
void set_time_unit(const std::string& unit) { set_time_unit(unit.c_str()); }
/// Set time resolution (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_resolution(const char* unitp) { m_sptrace.set_time_resolution(unitp); }
void set_time_resolution(const std::string& unit) { set_time_resolution(unit.c_str()); }

View File

@ -438,6 +438,8 @@ extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp
extern void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp,
...) VL_MT_SAFE;
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
extern void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
int width) VL_MT_SAFE;
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE;
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, CData& rdr) VL_MT_SAFE {
WData rwp[2]; // WData must always be at least 2

View File

@ -173,6 +173,8 @@ public:
class VerilatedImp {
// Whole class is internal use only - Global information shared between verilated*.cpp files.
protected:
friend class Verilated;
// TYPES
typedef std::vector<std::string> ArgVec;
@ -182,7 +184,24 @@ class VerilatedImp {
// MEMBERS
static VerilatedImp s_s; ///< Static Singleton; One and only static this
// Nothing here is save-restored; users expected to re-register appropriately
struct Serialized { // All these members serialized/deserialized
int m_timeFormatUnits; // $timeformat units
int m_timeFormatPrecision; // $timeformat number of decimal places
int m_timeFormatWidth; // $timeformat character width
enum { UNITS_NONE = 99 }; // Default based on precision
Serialized()
: m_timeFormatUnits(UNITS_NONE)
, m_timeFormatPrecision(0)
, m_timeFormatWidth(20) {}
~Serialized() {}
} m_ser;
VerilatedMutex m_sergMutex; ///< Protect m_ser
struct SerializedG { // All these members serialized/deserialized and guarded
std::string m_timeFormatSuffix; // $timeformat printf format
} m_serg VL_GUARDED_BY(m_sergMutex);
// Nothing below here is save-restored; users expected to re-register appropriately
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
/// Argument list (NOT save-restored, may want different results)
@ -411,6 +430,22 @@ public: // But only for verilated*.cpp
// We don't free up m_exportMap until the end, because we can't be sure
// what other models are using the assigned funcnum's.
public: // But only for verilated*.cpp
// METHODS - timeformat
static std::string timeFormatSuffix() VL_MT_SAFE;
static void timeFormatSuffix(const std::string& value) VL_MT_SAFE;
static int timeFormatUnits() VL_MT_SAFE {
if (s_s.m_ser.m_timeFormatUnits == Serialized::UNITS_NONE) {
return Verilated::timeprecision();
}
return s_s.m_ser.m_timeFormatUnits;
}
static int timeFormatPrecision() VL_MT_SAFE { return s_s.m_ser.m_timeFormatPrecision; }
static int timeFormatWidth() VL_MT_SAFE { return s_s.m_ser.m_timeFormatWidth; }
static void timeFormatUnits(int value) VL_MT_SAFE;
static void timeFormatPrecision(int value) VL_MT_SAFE;
static void timeFormatWidth(int value) VL_MT_SAFE;
public: // But only for verilated*.cpp
// METHODS - file IO
static IData fdNew(FILE* fp) VL_MT_SAFE {

View File

@ -79,7 +79,8 @@ void VerilatedSerialize::header() VL_MT_UNSAFE_ONE {
// Verilated doesn't do it itself, as if we're not using save/restore
// it doesn't need to compile this stuff in
os.write(Verilated::serializedPtr(), Verilated::serializedSize());
os.write(Verilated::serialized1Ptr(), Verilated::serialized1Size());
os.write(Verilated::serialized2Ptr(), Verilated::serialized2Size());
}
void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
@ -91,7 +92,8 @@ void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
close();
}
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
os.read(Verilated::serialized1Ptr(), Verilated::serialized1Size());
os.read(Verilated::serialized2Ptr(), Verilated::serialized2Size());
}
void VerilatedSerialize::trailer() VL_MT_UNSAFE_ONE {

View File

@ -159,7 +159,6 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
m_fileNewed = (filep == NULL);
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
m_namemapp = NULL;
m_timeRes = m_timeUnit = 1e-9;
m_timeLastDump = 0;
m_sigs_oldvalp = NULL;
m_evcd = false;
@ -171,6 +170,9 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
m_writep = m_wrBufp;
m_wroteBytes = 0;
m_suffixesp = NULL;
m_timeRes = m_timeUnit = 1e-9;
set_time_unit(Verilated::timeunitString());
set_time_resolution(Verilated::timeprecisionString());
}
void VerilatedVcd::open(const char* filename) {

View File

@ -458,11 +458,11 @@ public:
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
/// Set time units (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_unit(const char* unit) { m_sptrace.set_time_unit(unit); }
void set_time_unit(const std::string& unit) { set_time_unit(unit.c_str()); }
/// Set time resolution (s/ms, defaults to ns)
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_resolution(const char* unit) { m_sptrace.set_time_resolution(unit); }
void set_time_resolution(const std::string& unit) { set_time_resolution(unit.c_str()); }

View File

@ -1241,10 +1241,12 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
_VL_VPI_ERROR_RESET();
switch (property) {
case vpiTimePrecision: {
return VL_TIME_PRECISION;
return Verilated::timeprecision();
}
case vpiTimeUnit: {
return VL_TIME_UNIT;
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
if (!vop) return Verilated::timeunit(); // Null asks for global, not unlikely
return vop->scopep()->timeunit();
}
case vpiType: {
VerilatedVpio* vop = VerilatedVpio::castp(object);
@ -1903,7 +1905,7 @@ void vpi_put_value_array(vpiHandle /*object*/, p_vpi_arrayvalue /*arrayvalue_p*/
// time processing
void vpi_get_time(vpiHandle /*object*/, p_vpi_time time_p) {
void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
VerilatedVpiImp::assertOneCheck();
// cppcheck-suppress nullPointer
if (VL_UNLIKELY(!time_p)) {
@ -1917,6 +1919,15 @@ void vpi_get_time(vpiHandle /*object*/, p_vpi_time time_p) {
time_p->low = itime[0];
time_p->high = itime[1];
return;
} else if (time_p->type == vpiScaledRealTime) {
double dtime = VL_TIME_D();
if (VerilatedVpioScope* vop = VerilatedVpioScope::castp(object)) {
int scalePow10 = Verilated::timeprecision() - vop->scopep()->timeunit();
double scale = vl_time_multiplier(scalePow10); // e.g. 0.0001
dtime *= scale;
}
time_p->real = dtime;
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", VL_FUNC, time_p->type);
}

View File

@ -55,7 +55,7 @@ private:
nodep->displayType(AstDisplayType::DT_WRITE);
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
// cppcheck-suppress nullPointer
AstNode* timenewp = new AstTime(nodep->fileline());
AstNode* timenewp = new AstTime(nodep->fileline(), m_modp->timeunit());
if (AstNode* timesp = nodep->fmtp()->exprsp()) {
timesp->unlinkFrBackWithNext();
timenewp->addNext(timesp);

View File

@ -2671,6 +2671,7 @@ private:
int m_level; // 1=top module, 2=cell off top module, ...
int m_varNum; // Incrementing variable number
int m_typeNum; // Incrementing implicit type number
VTimescale m_timeunit; // Global time unit
VOptionBool m_unconnectedDrive; // State of `unconnected_drive
public:
AstNodeModule(AstType t, FileLine* fl, const string& name)
@ -2721,6 +2722,8 @@ public:
bool recursive() const { return m_recursive; }
void recursiveClone(bool flag) { m_recursiveClone = flag; }
bool recursiveClone() const { return m_recursiveClone; }
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
};

View File

@ -225,6 +225,16 @@ AstNode* AstInsideRange::newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode
return newp;
}
void AstNetlist::timeprecisionMerge(FileLine*, const VTimescale& value) {
VTimescale prec = v3Global.opt.timeComputePrec(value);
if (prec.isNone() || prec == m_timeprecision) {
} else if (m_timeprecision.isNone()) {
m_timeprecision = prec;
} else if (prec < m_timeprecision) {
m_timeprecision = prec;
}
}
bool AstVar::isSigPublic() const {
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
}
@ -1181,6 +1191,22 @@ void AstPin::dump(std::ostream& str) const {
}
if (svImplicit()) str << " [.SV]";
}
void AstPrintTimeScale::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " " << timeunit();
}
void AstTime::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " " << timeunit();
}
void AstTimeD::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " " << timeunit();
}
void AstTimeImport::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " " << timeunit();
}
void AstTypedef::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (attrPublic()) str << " [PUBLIC]";
@ -1254,6 +1280,10 @@ string AstUnpackArrayDType::prettyDTypeName() const {
os << subp->prettyDTypeName() << "$" << ranges;
return os.str();
}
void AstNetlist::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " [" << timeunit() << "/" << timeprecision() << "]";
}
void AstNodeModule::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " L" << level();
@ -1265,6 +1295,7 @@ void AstNodeModule::dump(std::ostream& str) const {
} else if (recursive()) {
str << " [RECURSIVE]";
}
str << " [" << timeunit() << "]";
}
void AstPackageExport::dump(std::ostream& str) const {
this->AstNode::dump(str);

View File

@ -113,6 +113,13 @@ public:
m_num.width(32, true);
dtypeSetLogicUnsized(32, m_num.widthMin(), AstNumeric::SIGNED);
}
class Unsized64 {}; // for creator type-overload selection
AstConst(FileLine* fl, Unsized64, vluint64_t num)
: ASTGEN_SUPER(fl)
, m_num(this, 64, 0) {
m_num.setQuad(num);
dtypeSetLogicSized(64, AstNumeric::UNSIGNED);
}
class SizedEData {}; // for creator type-overload selection
AstConst(FileLine* fl, SizedEData, vluint64_t num)
: ASTGEN_SUPER(fl)
@ -2677,12 +2684,15 @@ private:
string m_name; // Cell name, possibly {a}__DOT__{b}...
string m_origModName; // Original name of the module, ignoring name() changes, for dot lookup
AstScope* m_scopep; // The scope that the cell is inlined into
VTimescale m_timeunit; // Parent module time unit
public:
AstCellInline(FileLine* fl, const string& name, const string& origModName)
AstCellInline(FileLine* fl, const string& name, const string& origModName,
const VTimescale& timeunit)
: ASTGEN_SUPER(fl)
, m_name(name)
, m_origModName(origModName)
, m_scopep(NULL) {}
, m_scopep(NULL)
, m_timeunit(timeunit) {}
ASTNODE_NODE_FUNCS(CellInline)
virtual void dump(std::ostream& str) const;
virtual const char* broken() const {
@ -2695,6 +2705,8 @@ public:
virtual void name(const string& name) { m_name = name; }
void scopep(AstScope* scp) { m_scopep = scp; }
AstScope* scopep() const { return m_scopep; }
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstCellRef : public AstNode {
@ -3478,6 +3490,7 @@ class AstSFormatF : public AstNode {
bool m_hidden; // Under display, etc
bool m_hasFormat; // Has format code
char m_missingArgChar; // Format code when argument without format, 'h'/'o'/'b'
VTimescale m_timeunit; // Parent module time unit
public:
class NoFormat {};
AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp,
@ -3523,6 +3536,8 @@ public:
void hasFormat(bool flag) { m_hasFormat = flag; }
bool hasFormat() const { return m_hasFormat; }
char missingArgChar() const { return m_missingArgChar; }
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstDisplay : public AstNodeStmt {
@ -4620,6 +4635,28 @@ public:
}
};
class AstPrintTimeScale : public AstNodeStmt {
// Parents: stmtlist
string m_name; // Parent module name
VTimescale m_timeunit; // Parent module time unit
public:
AstPrintTimeScale(FileLine* fl)
: ASTGEN_SUPER(fl) {}
ASTNODE_NODE_FUNCS(PrintTimeScale)
virtual void name(const string& name) { m_name = name; }
virtual string name() const { return m_name; } // * = Var name
virtual void dump(std::ostream& str) const;
virtual string verilogKwd() const { return "$printtimescale"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isPure() const { return false; }
virtual bool isOutputter() const { return true; }
virtual int instrCount() const { return instrCountPli(); }
virtual V3Hash sameHash() const { return V3Hash(); }
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstStop : public AstNodeStmt {
public:
AstStop(FileLine* fl, bool maybe)
@ -4671,6 +4708,31 @@ public:
virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); }
};
class AstTimeFormat : public AstNodeStmt {
// Parents: stmtlist
public:
AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp,
AstNode* widthp)
: ASTGEN_SUPER(fl) {
setOp1p(unitsp);
setOp2p(precisionp);
setOp3p(suffixp);
setOp4p(widthp);
}
ASTNODE_NODE_FUNCS(TimeFormat)
virtual string verilogKwd() const { return "$timeformat"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isPure() const { return false; }
virtual bool isOutputter() const { return true; }
virtual int instrCount() const { return instrCountPli(); }
virtual V3Hash sameHash() const { return V3Hash(); }
AstNode* unitsp() const { return op1p(); }
AstNode* precisionp() const { return op2p(); }
AstNode* suffixp() const { return op3p(); }
AstNode* widthp() const { return op4p(); }
};
class AstTraceDecl : public AstNodeStmt {
// Trace point declaration
// Separate from AstTraceInc; as a declaration can't be deleted
@ -4924,37 +4986,47 @@ public:
};
class AstTime : public AstNodeTermop {
VTimescale m_timeunit; // Parent module time unit
public:
explicit AstTime(FileLine* fl)
: ASTGEN_SUPER(fl) {
AstTime(FileLine* fl, const VTimescale& timeunit)
: ASTGEN_SUPER(fl)
, m_timeunit(timeunit) {
dtypeSetUInt64();
}
ASTNODE_NODE_FUNCS(Time)
virtual string emitVerilog() { return "%f$time"; }
virtual string emitC() { return "VL_TIME_%nq()"; }
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual int instrCount() const { return instrCountTime(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
virtual void dump(std::ostream& str = std::cout) const;
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstTimeD : public AstNodeTermop {
VTimescale m_timeunit; // Parent module time unit
public:
explicit AstTimeD(FileLine* fl)
: ASTGEN_SUPER(fl) {
AstTimeD(FileLine* fl, const VTimescale& timeunit)
: ASTGEN_SUPER(fl)
, m_timeunit(timeunit) {
dtypeSetDouble();
}
ASTNODE_NODE_FUNCS(TimeD)
virtual string emitVerilog() { return "%f$realtime"; }
virtual string emitC() { return "VL_TIME_D()"; }
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual int instrCount() const { return instrCountTime(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
virtual void dump(std::ostream& str = std::cout) const;
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstUCFunc : public AstNodeMath {
@ -5813,6 +5885,23 @@ public:
virtual bool cleanLhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
};
class AstTimeImport : public AstNodeUniop {
// Take a constant that represents a time and needs conversion based on time units
VTimescale m_timeunit; // Parent module time unit
public:
AstTimeImport(FileLine* fl, AstNode* lhsp)
: ASTGEN_SUPER(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TimeImport)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%l"; }
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return false; }
virtual bool sizeMattersLhs() const { return false; }
virtual void dump(std::ostream& str = std::cout) const;
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstAtoN : public AstNodeUniop {
// string.atoi(), atobin(), atohex(), atooct(), atoireal()
@ -8272,6 +8361,8 @@ private:
AstPackage* m_dollarUnitPkgp; // $unit
AstCFunc* m_evalp; // The '_eval' function
AstExecGraph* m_execGraphp; // Execution MTask graph for threads>1 mode
VTimescale m_timeunit; // Global time unit
VTimescale m_timeprecision; // Global time precision
public:
AstNetlist()
: ASTGEN_SUPER(new FileLine(FileLine::builtInFilename()))
@ -8285,6 +8376,7 @@ public:
BROKEN_RTN(m_evalp && !m_evalp->brokeExists());
return NULL;
}
virtual void dump(std::ostream& str) const;
AstNodeModule* modulesp() const { // op1 = List of modules
return VN_CAST(op1p(), NodeModule);
}
@ -8317,6 +8409,14 @@ public:
void evalp(AstCFunc* evalp) { m_evalp = evalp; }
AstExecGraph* execGraphp() const { return m_execGraphp; }
void execGraphp(AstExecGraph* graphp) { m_execGraphp = graphp; }
VTimescale timeunit() const { return m_timeunit; }
void timeunit(const VTimescale& value) { m_timeunit = value; }
VTimescale timeprecision() const { return m_timeprecision; }
void timeInit() {
m_timeunit = v3Global.opt.timeDefaultUnit();
m_timeprecision = v3Global.opt.timeDefaultPrec();
}
void timeprecisionMerge(FileLine*, const VTimescale& value);
};
//######################################################################

View File

@ -135,8 +135,8 @@ private:
}
// Create CellInline for dotted var resolution
if (!m_ftaskp) {
AstCellInline* inlinep
= new AstCellInline(nodep->fileline(), m_unnamedScope, "__BEGIN__");
AstCellInline* inlinep = new AstCellInline(
nodep->fileline(), m_unnamedScope, "__BEGIN__", m_modp->timeunit());
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
}
}

View File

@ -2067,6 +2067,10 @@ private:
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
case 'l': break; // %l - auto insert "library"
case 't': // FALLTHRU
case '^': // %t/%^ - don't know $timeformat so can't constify
if (argp) argp = argp->nextp();
break;
default: // Most operators, just move to next argument
if (argp) {
AstNode* nextp = argp->nextp();

View File

@ -748,6 +748,38 @@ public:
puts(cvtToStr(nodep->fileline()->lineno()));
puts(", \"\");\n");
}
virtual void visit(AstPrintTimeScale* nodep) VL_OVERRIDE {
puts("VL_PRINTTIMESCALE(");
putsQuoted(protect(nodep->name()));
puts(", ");
putsQuoted(nodep->timeunit().ascii());
puts(");\n");
}
virtual void visit(AstTime* nodep) VL_OVERRIDE {
puts("VL_TIME_UNITED_Q(");
if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time has no units");
puts(cvtToStr(nodep->timeunit().multiplier()
/ v3Global.rootp()->timeprecision().multiplier()));
puts(")");
}
virtual void visit(AstTimeD* nodep) VL_OVERRIDE {
puts("VL_TIME_UNITED_D(");
if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$realtime has no units");
puts(cvtToStr(nodep->timeunit().multiplier()
/ v3Global.rootp()->timeprecision().multiplier()));
puts(")");
}
virtual void visit(AstTimeFormat* nodep) VL_OVERRIDE {
puts("VL_TIMEFORMAT_IINI(");
iterateAndNextNull(nodep->unitsp());
puts(", ");
iterateAndNextNull(nodep->precisionp());
puts(", ");
emitCvtPackStr(nodep->suffixp());
puts(", ");
iterateAndNextNull(nodep->widthp());
puts(");\n");
}
virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE {
if (nodep->tracking() || m_trackText) {
puts(nodep->text());
@ -2040,7 +2072,7 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const
// string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter;
string pfmt;
if ((fmtLetter == '#' || fmtLetter == 'd' || fmtLetter == 't') && !isScan
if ((fmtLetter == '#' || fmtLetter == 'd') && !isScan
&& vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros
const double mantissabits = argp->widthMin() - ((fmtLetter == 'd') ? 1 : 0);
// This is log10(2**mantissabits) as log2(2**mantissabits)/log2(10),
@ -2251,7 +2283,15 @@ void EmitCImp::emitConfigureImp(AstNodeModule* modp) {
puts("if (false && first) {} // Prevent unused\n");
puts("this->__VlSymsp = vlSymsp;\n"); // First, as later stuff needs it.
puts("if (false && this->__VlSymsp) {} // Prevent unused\n");
if (v3Global.opt.coverage()) puts(protect("_configure_coverage") + "(vlSymsp, first);\n");
if (v3Global.opt.coverage()) { puts(protect("_configure_coverage") + "(vlSymsp, first);\n"); }
if (modp->isTop() && !v3Global.rootp()->timeunit().isNone()) {
puts("Verilated::timeunit(" + cvtToStr(v3Global.rootp()->timeunit().negativeInt())
+ ");\n");
}
if (modp->isTop() && !v3Global.rootp()->timeprecision().isNone()) {
puts("Verilated::timeprecision("
+ cvtToStr(v3Global.rootp()->timeprecision().negativeInt()) + ");\n");
}
puts("}\n");
splitSizeInc(10);
}

View File

@ -42,10 +42,13 @@ class EmitCSyms : EmitCBaseVisitor {
struct ScopeData {
string m_symName;
string m_prettyName;
int m_timeunit;
string m_type;
ScopeData(const string& symName, const string& prettyName, const string& type)
ScopeData(const string& symName, const string& prettyName, int timeunit,
const string& type)
: m_symName(symName)
, m_prettyName(prettyName)
, m_timeunit(timeunit)
, m_type(type) {}
};
struct ScopeFuncData {
@ -220,7 +223,7 @@ class EmitCSyms : EmitCBaseVisitor {
if (v3Global.opt.vpi()) varHierarchyScopes(scpName);
if (m_scopeNames.find(scpSym) == m_scopeNames.end()) {
m_scopeNames.insert(
make_pair(scpSym, ScopeData(scpSym, scpPretty, "SCOPE_OTHER")));
make_pair(scpSym, ScopeData(scpSym, scpPretty, 0, "SCOPE_OTHER")));
}
m_scopeVars.insert(
make_pair(scpSym + " " + varp->name(),
@ -289,8 +292,9 @@ class EmitCSyms : EmitCBaseVisitor {
string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE";
string name = nodep->scopep()->name() + "__DOT__" + nodep->name();
string name_dedot = AstNode::dedotName(name);
int timeunit = m_modp->timeunit().negativeInt();
m_vpiScopeCandidates.insert(
make_pair(name, ScopeData(scopeSymString(name), name_dedot, type)));
make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type)));
}
}
virtual void visit(AstScope* nodep) VL_OVERRIDE {
@ -301,18 +305,20 @@ class EmitCSyms : EmitCBaseVisitor {
if (v3Global.opt.vpi() && !nodep->isTop()) {
string name_dedot = AstNode::dedotName(nodep->shortName());
int timeunit = m_modp->timeunit().negativeInt();
m_vpiScopeCandidates.insert(
make_pair(nodep->name(),
ScopeData(scopeSymString(nodep->name()), name_dedot, "SCOPE_MODULE")));
make_pair(nodep->name(), ScopeData(scopeSymString(nodep->name()), name_dedot,
timeunit, "SCOPE_MODULE")));
}
}
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
string name = nodep->scopeSymName();
// UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()<<" ss
// "<<name<<endl);
// UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()
// <<" ss"<<name<<endl);
int timeunit = m_modp ? m_modp->timeunit().negativeInt() : 0;
if (m_scopeNames.find(name) == m_scopeNames.end()) {
m_scopeNames.insert(
make_pair(name, ScopeData(name, nodep->scopePrettySymName(), "SCOPE_OTHER")));
m_scopeNames.insert(make_pair(
name, ScopeData(name, nodep->scopePrettySymName(), timeunit, "SCOPE_OTHER")));
}
if (nodep->dpiExport()) {
UASSERT_OBJ(m_funcp, nodep, "ScopeName not under DPI function");
@ -320,9 +326,10 @@ class EmitCSyms : EmitCBaseVisitor {
make_pair(name + " " + m_funcp->name(), ScopeFuncData(nodep, m_funcp, m_modp)));
} else {
if (m_scopeNames.find(nodep->scopeDpiName()) == m_scopeNames.end()) {
m_scopeNames.insert(make_pair(
nodep->scopeDpiName(),
ScopeData(nodep->scopeDpiName(), nodep->scopePrettyDpiName(), "SCOPE_OTHER")));
m_scopeNames.insert(
make_pair(nodep->scopeDpiName(),
ScopeData(nodep->scopeDpiName(), nodep->scopePrettyDpiName(),
timeunit, "SCOPE_OTHER")));
}
}
}
@ -683,6 +690,8 @@ void EmitCSyms::emitSymImp() {
putsQuoted(protectWordsIf(it->second.m_prettyName, true));
puts(", ");
putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName)));
puts(", ");
puts(cvtToStr(it->second.m_timeunit));
puts(", VerilatedScope::" + it->second.m_type + ");\n");
++m_numStmts;
}

View File

@ -105,6 +105,7 @@ public:
SYMRSVDWORD, // Symbol is Reserved Word
SYNCASYNCNET, // Mixed sync + async reset
TICKCOUNT, // Too large tick count
TIMESCALEMOD, // Need timescale for module
UNDRIVEN, // No drivers
UNOPT, // Unoptimizable block
UNOPTFLAT, // Unoptimizable block after flattening
@ -158,7 +159,7 @@ public:
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
"REALCVT", "REDEFMACRO",
"SELRANGE", "SHORTREAL", "SPLITVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT",
"TICKCOUNT", "TIMESCALEMOD",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSIGNED", "UNUSED",
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
@ -176,7 +177,8 @@ public:
// Later -Werror- options may make more of these.
bool pretendError() const {
return (m_e == ASSIGNIN || m_e == BLKANDNBLK || m_e == BLKLOOPINIT || m_e == CONTASSREG
|| m_e == IMPURE || m_e == PROCASSWIRE);
|| m_e == IMPURE || m_e == PROCASSWIRE //
|| m_e == TIMESCALEMOD); // Says IEEE
}
// Warnings to mention manual
bool mentionManual() const {

View File

@ -552,7 +552,8 @@ private:
{ InlineCollectVisitor(nodep->modp()); } // {} to destroy visitor immediately
// Create data for dotted variable resolution
AstCellInline* inlinep
= new AstCellInline(nodep->fileline(), nodep->name(), nodep->modp()->origName());
= new AstCellInline(nodep->fileline(), nodep->name(), nodep->modp()->origName(),
nodep->modp()->timeunit());
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
// Create assignments to the pins
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {

View File

@ -72,6 +72,8 @@ void V3LinkLevel::modSortByLevel() {
}
}
timescaling(mods);
// Reorder the netlist's modules to have modules in level sorted order
stable_sort(mods.begin(), mods.end(), CmpLevel()); // Sort the vector
UINFO(9, "modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666
@ -90,6 +92,44 @@ void V3LinkLevel::modSortByLevel() {
V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
void V3LinkLevel::timescaling(const ModVec& mods) {
// Timescale determination
AstNodeModule* modTimedp = NULL;
VTimescale unit(VTimescale::NONE);
// Use highest level module as default unit - already sorted in proper order
for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) {
if (!modTimedp && !(*it)->timeunit().isNone()) {
modTimedp = *it;
unit = modTimedp->timeunit();
break;
}
}
unit = v3Global.opt.timeComputeUnit(unit); // Apply override
if (unit.isNone()) unit = VTimescale(VTimescale::TS_DEFAULT);
v3Global.rootp()->timeunit(unit);
for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) {
AstNodeModule* nodep = *it;
if (nodep->timeunit().isNone()) {
if (modTimedp && !VN_IS(nodep, Iface)
&& !(VN_IS(nodep, Package) && VN_CAST(nodep, Package)->isDollarUnit())) {
nodep->v3warn(TIMESCALEMOD,
"Timescale missing on this module as other modules have "
"it (IEEE 1800-2017 3.14.2.2)\n"
<< modTimedp->warnOther()
<< "... Location of module with timescale\n"
<< modTimedp->warnContextSecondary());
}
nodep->timeunit(unit);
}
}
if (v3Global.rootp()->timeprecision().isNone()) {
v3Global.rootp()->timeprecisionMerge(v3Global.rootp()->fileline(),
VTimescale(VTimescale::TS_DEFAULT));
}
}
//######################################################################
// Wrapping
@ -108,6 +148,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) {
newmodp->level(1);
newmodp->modPublic(true);
newmodp->protect(false);
newmodp->timeunit(oldmodp->timeunit());
rootp->addModulep(newmodp);
// TODO the module creation above could be done after linkcells, but

View File

@ -27,6 +27,9 @@
class V3LinkLevel {
private:
typedef std::vector<AstNodeModule*> ModVec;
static void timescaling(const ModVec& mods);
static void wrapTopCell(AstNetlist* rootp);
static void wrapTopPackages(AstNetlist* rootp);

View File

@ -497,6 +497,28 @@ private:
cleanFileline(nodep);
iterateChildren(nodep);
}
virtual void visit(AstPrintTimeScale* nodep) VL_OVERRIDE {
// Inlining may change hierarchy, so just save timescale where needed
iterateChildren(nodep);
nodep->name(m_modp->name());
nodep->timeunit(m_modp->timeunit());
}
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->timeunit(m_modp->timeunit());
}
virtual void visit(AstTime* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->timeunit(m_modp->timeunit());
}
virtual void visit(AstTimeD* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->timeunit(m_modp->timeunit());
}
virtual void visit(AstTimeImport* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->timeunit(m_modp->timeunit());
}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate

View File

@ -31,6 +31,7 @@
#ifndef _WIN32
# include <sys/utsname.h>
#endif
#include <algorithm>
#include <cctype>
#include <dirent.h>
#include <fcntl.h>
@ -117,6 +118,75 @@ V3LangCode::V3LangCode(const char* textp) {
m_e = V3LangCode::L_ERROR;
}
//######################################################################
// VTimescale class functions
VTimescale::VTimescale(const string& value, bool& badr)
: m_e(VTimescale::NONE) {
badr = true;
string spaceless = VString::removeWhitespace(value);
for (int i = TS_1S; i < _ENUM_END; ++i) {
VTimescale ts(i);
if (spaceless == ts.ascii()) {
badr = false;
m_e = ts.m_e;
break;
}
}
}
void VTimescale::parseSlashed(FileLine* fl, const char* textp, VTimescale& unitr,
VTimescale& precr, bool allowEmpty) {
// Parse `timescale of <number><units> / <number><units>
unitr = VTimescale::NONE;
precr = VTimescale::NONE;
const char* cp = textp;
for (; isspace(*cp); ++cp) {}
const char* unitp = cp;
for (; *cp && *cp != '/'; ++cp) {}
string unitStr(unitp, cp - unitp);
for (; isspace(*cp); ++cp) {}
string precStr;
if (*cp == '/') {
++cp;
for (; isspace(*cp); ++cp) {}
const char* precp = cp;
for (; *cp && *cp != '/'; ++cp) {}
precStr = string(precp, cp - precp);
}
for (; isspace(*cp); ++cp) {}
if (*cp) {
fl->v3error("`timescale syntax error: '" << textp << "'");
return;
}
bool unitbad;
VTimescale unit(unitStr, unitbad /*ref*/);
if (unitbad && !(unitStr.empty() && allowEmpty)) {
fl->v3error("`timescale timeunit syntax error: '" << unitStr << "'");
return;
}
unitr = unit;
if (!precStr.empty()) {
VTimescale prec(VTimescale::NONE);
bool precbad;
prec = VTimescale(precStr, precbad /*ref*/);
if (precbad) {
fl->v3error("`timescale timeprecision syntax error: '" << precStr << "'");
return;
}
if (!unit.isNone() && !prec.isNone() && unit < prec) {
fl->v3error("`timescale timeunit '"
<< unitStr << "' must be greater than or equal to timeprecision '"
<< precStr << "'");
return;
}
precr = prec;
}
}
//######################################################################
// V3Options class functions
@ -590,6 +660,26 @@ void V3Options::throwSigsegv() {
#endif
}
VTimescale V3Options::timeComputePrec(const VTimescale& flag) const {
if (!timeOverridePrec().isNone()) {
return timeOverridePrec();
} else if (flag.isNone()) {
return timeDefaultPrec();
} else {
return flag;
}
}
VTimescale V3Options::timeComputeUnit(const VTimescale& flag) const {
if (!timeOverrideUnit().isNone()) {
return timeOverrideUnit();
} else if (flag.isNone()) {
return timeDefaultUnit();
} else {
return flag;
}
}
//######################################################################
// V3 Options utilities
@ -1127,6 +1217,26 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
m_threadsMaxMTasks = atoi(argv[i]);
if (m_threadsMaxMTasks < 1)
fl->v3fatal("--threads-max-mtasks must be >= 1: " << argv[i]);
} else if (!strcmp(sw, "-timescale") && (i + 1) < argc) {
shift;
VTimescale unit;
VTimescale prec;
VTimescale::parseSlashed(fl, argv[i], unit /*ref*/, prec /*ref*/);
if (!unit.isNone() && timeOverrideUnit().isNone()) m_timeDefaultUnit = unit;
if (!prec.isNone() && timeOverridePrec().isNone()) m_timeDefaultPrec = prec;
} else if (!strcmp(sw, "-timescale-override") && (i + 1) < argc) {
shift;
VTimescale unit;
VTimescale prec;
VTimescale::parseSlashed(fl, argv[i], unit /*ref*/, prec /*ref*/, true);
if (!unit.isNone()) {
m_timeDefaultUnit = unit;
m_timeOverrideUnit = unit;
}
if (!prec.isNone()) {
m_timeDefaultPrec = prec;
m_timeOverridePrec = prec;
}
} else if (!strcmp(sw, "-top-module") && (i + 1) < argc) {
shift;
m_topModule = argv[i];

View File

@ -69,6 +69,85 @@ inline std::ostream& operator<<(std::ostream& os, const VOptionBool& rhs) {
//######################################################################
class VTimescale {
public:
enum en {
TS_1S = 0,
// clang-format off
TS_100MS = 1, TS_10MS = 2, TS_1MS = 3,
TS_100US = 4, TS_10US = 5, TS_1US = 6,
TS_100NS = 7, TS_10NS = 8, TS_1NS = 9,
TS_100PS = 10, TS_10PS = 11, TS_1PS = 12,
TS_100FS = 13, TS_10FS = 14, TS_1FS = 15,
// clang-format on
NONE = 16,
_ENUM_END
};
enum { TS_DEFAULT = TS_1PS };
enum en m_e;
// CONSTRUCTOR
inline VTimescale()
: m_e(NONE) {}
// cppcheck-suppress noExplicitConstructor
inline VTimescale(en _e)
: m_e(_e) {}
explicit inline VTimescale(int _e)
: m_e(static_cast<en>(_e)) {}
int negativeInt() { return -static_cast<int>(m_e); }
// Construct from string
VTimescale(const string& value, bool& badr);
VTimescale(double value, bool& badr) {
badr = false;
// clang-format off
if (value == 1e0) m_e = TS_1S;
else if (value == 1e-1) m_e = TS_100MS;
else if (value == 1e-2) m_e = TS_10MS;
else if (value == 1e-3) m_e = TS_1MS;
else if (value == 1e-4) m_e = TS_100US;
else if (value == 1e-5) m_e = TS_10US;
else if (value == 1e-6) m_e = TS_1US;
else if (value == 1e-7) m_e = TS_100NS;
else if (value == 1e-8) m_e = TS_10NS;
else if (value == 1e-9) m_e = TS_1NS;
else if (value == 1e-10) m_e = TS_100PS;
else if (value == 1e-11) m_e = TS_10PS;
else if (value == 1e-12) m_e = TS_1PS;
else if (value == 1e-13) m_e = TS_100FS;
else if (value == 1e-14) m_e = TS_10FS;
else if (value == 1e-15) m_e = TS_1FS;
// clang-format on
else {
m_e = NONE;
badr = true;
}
}
bool isNone() const { return m_e == NONE; }
// Parse a "unit/precision" string into two VTimescales, with error checking
static void parseSlashed(FileLine* fl, const char* textp, VTimescale& unitr, VTimescale& precr,
bool allowEmpty = false);
const char* ascii() const {
static const char* const names[]
= {"1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns", "10ns",
"1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs", "NONE"};
return names[m_e];
}
double multiplier() const {
static double values[] = {1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 0};
return values[m_e];
}
};
inline bool operator==(const VTimescale& lhs, const VTimescale& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VTimescale& lhs, VTimescale::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VTimescale::en lhs, const VTimescale& rhs) { return lhs == rhs.m_e; }
// Comparisons are based on time, not enum values, so seconds > milliseconds
inline bool operator<(const VTimescale& lhs, const VTimescale& rhs) { return lhs.m_e > rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VTimescale& rhs) {
return os << rhs.ascii();
}
//######################################################################
class TraceFormat {
public:
enum en { VCD = 0, FST, FST_THREAD } m_e;
@ -207,6 +286,10 @@ private:
VOptionBool m_skipIdentical; // main switch: --skip-identical
int m_threads; // main switch: --threads (0 == --no-threads)
int m_threadsMaxMTasks; // main switch: --threads-max-mtasks
VTimescale m_timeDefaultPrec; // main switch: --timescale
VTimescale m_timeDefaultUnit; // main switch: --timescale
VTimescale m_timeOverridePrec; // main switch: --timescale-override
VTimescale m_timeOverrideUnit; // main switch: --timescale-override
int m_traceDepth; // main switch: --trace-depth
TraceFormat m_traceFormat; // main switch: --trace or --trace-fst
int m_traceMaxArray;// main switch: --trace-max-array
@ -392,6 +475,12 @@ public:
int threads() const { return m_threads; }
int threadsMaxMTasks() const { return m_threadsMaxMTasks; }
bool mtasks() const { return (m_threads > 1); }
VTimescale timeDefaultPrec() const { return m_timeDefaultPrec; }
VTimescale timeDefaultUnit() const { return m_timeDefaultUnit; }
VTimescale timeOverridePrec() const { return m_timeOverridePrec; }
VTimescale timeOverrideUnit() const { return m_timeOverrideUnit; }
VTimescale timeComputePrec(const VTimescale& flag) const;
VTimescale timeComputeUnit(const VTimescale& flag) const;
int traceDepth() const { return m_traceDepth; }
TraceFormat traceFormat() const { return m_traceFormat; }
int traceMaxArray() const { return m_traceMaxArray; }

View File

@ -86,6 +86,44 @@ void V3ParseImp::ppline(const char* textp) {
}
}
void V3ParseImp::timescalePreproc(FileLine* fl, const char* textp) {
// Parse `timescale of <number><units> / <number><units>
VTimescale unit;
VTimescale prec;
VTimescale::parseSlashed(fl, textp, unit /*ref*/, prec /*ref*/);
m_timeLastUnit = v3Global.opt.timeComputeUnit(unit);
v3Global.rootp()->timeprecisionMerge(fileline(), prec);
}
void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal,
bool precSet, double precVal) {
VTimescale unit(VTimescale::NONE);
if (unitSet) {
bool bad;
unit = VTimescale(unitVal, bad /*ref*/);
if (bad) {
UINFO(1, "Value = " << unitVal << endl);
fl->v3error("timeunit illegal value");
}
}
VTimescale prec(VTimescale::NONE);
if (precSet) {
bool bad;
prec = VTimescale(precVal, bad /*ref*/);
if (bad) {
UINFO(1, "Value = " << precVal << endl);
fl->v3error("timeprecision illegal value");
}
}
if (!unit.isNone()) {
if (modp) {
modp->timeunit(v3Global.opt.timeComputeUnit(unit));
} else {
fl->v3error("timeunit/timeprecision not under a module");
}
}
v3Global.rootp()->timeprecisionMerge(fileline(), prec);
}
void V3ParseImp::verilatorCmtLintSave() { m_lintState.push_back(*parsep()->fileline()); }
void V3ParseImp::verilatorCmtLintRestore() {
@ -171,6 +209,40 @@ double V3ParseImp::parseDouble(const char* textp, size_t length, bool* successp)
return d;
}
double V3ParseImp::parseTimenum(const char* textp) {
size_t length = strlen(textp);
char* strgp = new char[length + 1];
char* dp = strgp;
const char* sp = textp;
for (; isdigit(*sp) || *sp == '_' || *sp == '.'; ++sp) {
if (*sp != '_') *dp++ = *sp;
}
*dp++ = '\0';
double d = strtod(strgp, NULL);
string suffix(sp);
double divisor = 1;
if (suffix == "s") {
divisor = 1;
} else if (suffix == "ms") {
divisor = 1e3;
} else if (suffix == "us") {
divisor = 1e6;
} else if (suffix == "ns") {
divisor = 1e9;
} else if (suffix == "ps") {
divisor = 1e12;
} else if (suffix == "fs") {
divisor = 1e15;
} else {
// verilog.l checks the suffix for us, so this is an assert
v3fatalSrc("Unknown time suffix " << suffix);
}
VL_DO_DANGLING(delete[] strgp, strgp);
return d / divisor;
}
//######################################################################
// Parser tokenization

View File

@ -124,6 +124,8 @@ class V3ParseImp {
string m_tag; // Contents (if any) of current verilator tag
AstNode* m_tagNodep; // Points to the node to set to m_tag or NULL to not set.
VTimescale m_timeLastUnit; // Last `timescale's unit
public:
// Note these are an exception to using the filename as the debug type
static int debugBison() {
@ -152,7 +154,12 @@ public:
void tag(const char* text);
void tagNodep(AstNode* nodep) { m_tagNodep = nodep; }
AstNode* tagNodep() const { return m_tagNodep; }
void timescalePreproc(FileLine* fl, const char* textp);
void timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal,
bool precSet, double precVal);
VTimescale timeLastUnit() const { return m_timeLastUnit; }
static double parseTimenum(const char* text);
static double parseDouble(const char* text, size_t length, bool* successp = NULL);
void pushBeginKeywords(int state) {
m_inBeginKwd++;
@ -246,6 +253,7 @@ public:
m_prevBisonVal.token = 0;
// m_aheadVal not used as m_ahead = false, and not all compilers support initing it
m_tagNodep = NULL;
m_timeLastUnit = v3Global.opt.timeDefaultUnit();
}
~V3ParseImp();
void parserClear();

View File

@ -138,6 +138,14 @@ private:
txtp->addNodep(m_modPortsp);
txtp->addText(fl, ");\n\n");
// Timescale
addComment(txtp, fl,
"Precision of submodule"
" (commented out to avoid requiring timescale on all modules)");
addComment(txtp, fl, string("timeunit ") + v3Global.rootp()->timeunit().ascii() + ";");
addComment(txtp, fl,
string("timeprecision ") + v3Global.rootp()->timeprecision().ascii() + ";\n");
// DPI declarations
hashComment(txtp, fl);
txtp->addText(fl, "import \"DPI-C\" function void " + m_libName

View File

@ -109,6 +109,15 @@ string VString::spaceUnprintable(const string& str) {
return out;
}
string VString::removeWhitespace(const string& str) {
string out;
out.reserve(str.size());
for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) {
if (!isspace(*pos)) out += *pos;
}
return out;
}
bool VString::isWhitespace(const string& str) {
for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) {
if (!isspace(*pos)) return false;

View File

@ -87,6 +87,8 @@ public:
// Replace any unprintable with space
// This includes removing tabs, so column tracking is correct
static string spaceUnprintable(const string& str);
// Remove any whitespace
static string removeWhitespace(const string& str);
// Return true if only whitespace or ""
static bool isWhitespace(const string& str);
};

View File

@ -1129,6 +1129,21 @@ private:
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p());
// Type set in constructor
}
virtual void visit(AstTimeImport* nodep) VL_OVERRIDE {
// LHS is a real number in seconds
// Need to round to time units and precision
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p());
AstConst* constp = VN_CAST(nodep->lhsp(), Const);
if (!constp || !constp->isDouble()) nodep->v3fatalSrc("Times should be doubles");
if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time import no units");
double time = constp->num().toDouble();
if (v3Global.rootp()->timeprecision().isNone()) nodep->v3fatalSrc("Never set precision?");
time /= nodep->timeunit().multiplier();
// IEEE claims you should round to time precision here, but no simulator seems to do this
AstConst* newp = new AstConst(nodep->fileline(), AstConst::RealDouble(), time);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstAttrOf* nodep) VL_OVERRIDE {
AstAttrOf* oldAttr = m_attrp;
m_attrp = nodep;
@ -3118,10 +3133,35 @@ private:
break;
}
case 't': { // Convert decimal time to realtime
if (argp && argp->isDouble()) { // Convert it
ch = '^';
if (argp) {
AstNode* nextp = argp->nextp();
if (argp->isDouble()) ch = '^'; // Convert it
if (nodep->timeunit().isNone()) {
nodep->v3fatalSrc("display %t has no time units");
}
double scale = nodep->timeunit().multiplier()
/ v3Global.rootp()->timeprecision().multiplier();
if (scale != 1.0) {
AstNode* newp;
AstNRelinker relinkHandle;
argp->unlinkFrBack(&relinkHandle);
if (argp->isDouble()) { // Convert it
ch = '^';
newp = new AstMulD(
argp->fileline(),
new AstConst(argp->fileline(), AstConst::RealDouble(), scale),
argp);
} else {
newp = new AstMul(argp->fileline(),
new AstConst(argp->fileline(),
AstConst::Unsized64(),
llround(scale)),
argp);
}
relinkHandle.relink(newp);
}
argp = nextp;
}
if (argp) argp = argp->nextp();
break;
}
case 'f': // FALLTHRU
@ -3333,6 +3373,13 @@ private:
nodep->dtypeChgWidthSigned(32, 1, AstNumeric::SIGNED); // Spec says integer return
}
}
virtual void visit(AstTimeFormat* nodep) VL_OVERRIDE {
assertAtStatement(nodep);
iterateCheckSigned32(nodep, "units", nodep->unitsp(), BOTH);
iterateCheckSigned32(nodep, "precision", nodep->precisionp(), BOTH);
iterateCheckString(nodep, "suffix", nodep->suffixp(), BOTH);
iterateCheckSigned32(nodep, "width", nodep->widthp(), BOTH);
}
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
// Just let all arguments seek their natural sizes
assertAtStatement(nodep);

View File

@ -630,6 +630,7 @@ int main(int argc, char** argv, char** env) {
// Validate settings (aka Boost.Program_options)
v3Global.opt.notify();
v3Global.rootp()->timeInit();
V3Error::abortIfErrors();

View File

@ -242,6 +242,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$nochange" { FL; return yaTIMINGSPEC; }
"$period" { FL; return yaTIMINGSPEC; }
"$pow" { FL; return yD_POW; }
"$printtimescale" { FL; return yD_PRINTTIMESCALE; }
"$random" { FL; return yD_RANDOM; }
"$readmemb" { FL; return yD_READMEMB; }
"$readmemh" { FL; return yD_READMEMH; }
@ -275,6 +276,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
"$time" { FL; return yD_TIME; }
"$timeskew" { FL; return yaTIMINGSPEC; }
"$timeformat" { FL; return yD_TIMEFORMAT; }
"$typename" { FL; return yD_TYPENAME; }
"$ungetc" { FL; return yD_UNGETC; }
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
@ -891,8 +893,12 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM;
}
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
FL; yylval.cdouble = 0; /* Only for times, not used yet */
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s) {
FL; yylval.cdouble = PARSEP->parseTimenum(yytext);
return yaTIMENUM;
}
1step {
FL; yylval.cdouble = 0; // Unsupported
return yaTIMENUM;
}
}
@ -975,7 +981,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"`resetall" { FL; PARSEP->fileline()->warnOn(V3ErrorCode::I_DEF_NETTYPE_WIRE, true);
return yaT_RESETALL; } // Rest handled by preproc
"`suppress_faults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility
"`timescale"{ws}+[^\n\r]* { FL_FWD; FL_BRK; } // Verilog spec - not supported
"`timescale"{ws}+[^\n\r]* { FL_FWD; PARSEP->timescalePreproc(PARSEP->fileline(),
yytext + strlen("`timescale"));
FL_BRK; }
"`unconnected_drive"{ws}+"pull0" { FL_FWD; PARSEP->unconnectedDrive(VOptionBool::OPT_FALSE); FL_BRK; }
"`unconnected_drive"{ws}+"pull1" { FL_FWD; PARSEP->unconnectedDrive(VOptionBool::OPT_TRUE); FL_BRK; }
"`unconnected_drive" { FL_FWD; yyerrorf("Bad `unconnected_drive syntax"); FL_BRK; }

View File

@ -55,6 +55,7 @@ public:
AstCase* m_caseAttrp; // Current case statement for attribute adding
AstNodeDType* m_varDTypep; // Pointer to data type for next signal declaration
AstNodeDType* m_memDTypep; // Pointer to data type for next member declaration
AstNodeModule* m_modp; // Last module for timeunits
bool m_pinAnsi; // In ANSI port list
int m_pinNum; // Pin number currently parsing
FileLine* m_instModuleFl; // Fileline of module referenced for instantiations
@ -73,6 +74,7 @@ public:
m_varDTypep = NULL;
m_gateRangep = NULL;
m_memDTypep = NULL;
m_modp = NULL;
m_pinAnsi = false;
m_pinNum = -1;
m_instModuleFl = NULL;
@ -600,6 +602,7 @@ class AstSenTree;
%token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_PAST "$past"
%token<fl> yD_POW "$pow"
%token<fl> yD_PRINTTIMESCALE "$printtimescale"
%token<fl> yD_RANDOM "$random"
%token<fl> yD_READMEMB "$readmemb"
%token<fl> yD_READMEMH "$readmemh"
@ -629,6 +632,7 @@ class AstSenTree;
%token<fl> yD_TANH "$tanh"
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_TIMEFORMAT "$timeformat"
%token<fl> yD_TYPENAME "$typename"
%token<fl> yD_UNGETC "$ungetc"
%token<fl> yD_UNIT "$unit"
@ -820,9 +824,12 @@ description: // ==IEEE: description
;
timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
yTIMEUNIT yaTIMENUM ';' { $$ = NULL; }
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';' { $$ = NULL; }
| yTIMEPRECISION yaTIMENUM ';' { $$ = NULL; }
yTIMEUNIT yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, GRAMMARP->m_modp, true, $2, false, 0); $$ = NULL; }
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, GRAMMARP->m_modp, true, $2, true, $4); $$ = NULL; }
| yTIMEPRECISION yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, GRAMMARP->m_modp, false, 0, true, $2); $$ = NULL; }
;
//**********************************************************************
@ -832,6 +839,7 @@ package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
GRAMMARP->m_modp = NULL;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>4,$1,$4); }
;
@ -841,8 +849,10 @@ packageFront<modulep>:
{ $$ = new AstPackage($<fl>3, *$3);
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
SYMP->pushNew($$);
GRAMMARP->m_modp = $$; }
;
package_itemListE<nodep>: // IEEE: [{ package_item }]
@ -931,6 +941,7 @@ module_declaration: // ==IEEE: module_declaration
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
GRAMMARP->m_modp = NULL;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
| udpFront parameter_port_listE portsStarE ';'
@ -939,6 +950,7 @@ module_declaration: // ==IEEE: module_declaration
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
GRAMMARP->m_tracingParse = true;
GRAMMARP->m_modp = NULL;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
//
@ -953,9 +965,11 @@ modFront<modulep>:
{ $$ = new AstModule($<fl>3,*$3);
$$->inLibrary(PARSEP->inLibrary() || PARSEP->inCellDefine());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
$$->unconnectedDrive(PARSEP->unconnectedDrive());
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
SYMP->pushNew($$);
GRAMMARP->m_modp = $$; }
;
importsAndParametersE<nodep>: // IEEE: common part of module_declaration, interface_declaration, program_declaration
@ -982,7 +996,7 @@ parameter_value_assignmentE<pinp>: // IEEE: [ parameter_value_assignment ]
| '#' yaFLOATNUM { $$ = new AstPin($<fl>2, 1, "",
new AstConst($<fl>2, AstConst::Unsized32(),
(int)(($2<0)?($2-0.5):($2+0.5)))); }
//UNSUP '#' yaTIMENUM { UNSUP }
| '#' timeNumAdjusted { $$ = new AstPin($<fl>2, 1, "", $2); }
| '#' idClassSel { $$ = new AstPin($<fl>2, 1, "", $2); }
// // Not needed in Verilator:
// // Side effect of combining *_instantiations
@ -1224,6 +1238,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
GRAMMARP->m_modp = NULL;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
| yEXTERN pgmFront parameter_port_listE portsStarE ';'
@ -1236,8 +1251,10 @@ pgmFront<modulep>:
{ $$ = new AstModule($<fl>3,*$3);
$$->inLibrary(PARSEP->inLibrary() || PARSEP->inCellDefine());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
SYMP->pushNew($$);
GRAMMARP->m_modp = $$; }
;
program_itemListE<nodep>: // ==IEEE: [{ program_item }]
@ -2272,14 +2289,11 @@ delay_value: // ==IEEE:delay_value
ps_id_etc { }
| yaINTNUM { }
| yaFLOATNUM { }
| yaTIMENUM { }
| timeNumAdjusted { DEL($1); }
;
delayExpr:
expr { DEL($1); }
// // Verilator doesn't support yaTIMENUM, so not in expr
//UNSUP below doesn't belong here:
| yaTIMENUM { }
;
minTypMax: // IEEE: mintypmax_expression and constant_mintypmax_expression
@ -3285,6 +3299,11 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); DEL($3); }
| yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, $5); $$->addNext(new AstStop($1, false)); DEL($3); }
//
| yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale($1); }
| yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale($1); }
| yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale($1); DEL($3); }
| yD_TIMEFORMAT '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstTimeFormat($1, $3, $5, $7, $9); }
//
| yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
| yD_READMEMB '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); }
@ -3366,7 +3385,7 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
| yD_RANDOM '(' expr ')' { $$ = NULL; $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
| yD_RANDOM parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1, VTimescale(VTimescale::NONE)); }
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
| yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); }
| yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); }
@ -3382,11 +3401,11 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_SIZE '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,$5); }
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
| yD_STIME parenE { $$ = new AstSel($1, new AstTime($1, VTimescale(VTimescale::NONE)), 0, 32); }
| yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); }
| yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); }
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
| yD_TIME parenE { $$ = new AstTime($1); }
| yD_TIME parenE { $$ = new AstTime($1, VTimescale(VTimescale::NONE)); }
| yD_TYPENAME '(' exprOrDataType ')' { $$ = new AstAttrOf($1, AstAttrType::TYPENAME, $3); }
| yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first
| yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
@ -3779,7 +3798,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// // IEEE: primary_literal (minus string, which is handled specially)
| yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
//UNSUP yaTIMENUM { UNSUP }
| timeNumAdjusted { $$ = $1; }
| strAsInt~noStr__IGNORE~ { $$ = $1; }
//
// // IEEE: "... hierarchical_identifier select" see below
@ -5728,6 +5747,14 @@ memberQualOne<nodep>: // IEEE: property_qualifier + method_qualifier
//UNSUP | ySTATIC__CONSTRAINT { $$ = true; }
//UNSUP ;
//**********************************************************************
// Constants
timeNumAdjusted<nodep>: // Time constant, adjusted to module's time units/precision
yaTIMENUM
{ $$ = new AstTimeImport($<fl>1, new AstConst($<fl>1, AstConst::RealDouble(), $1)); }
;
//**********************************************************************
// VLT Files

View File

@ -35,16 +35,16 @@ $SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork; die "Quitting...\n"; }
# Map of all scenarios, with the names used to enable them
our %All_Scenarios
= (dist => [ "dist"],
atsim => [ "simulator", "atsim"],
ghdl => ["linter", "simulator", "ghdl"],
iv => [ "simulator", "iv"],
ms => ["linter", "simulator", "ms"],
nc => ["linter", "simulator", "nc"],
vcs => ["linter", "simulator", "vcs"],
xsim => ["linter", "simulator", "xsim"],
vlt => ["linter", "simulator", "vlt_all", "vlt"],
vltmt => [ "simulator", "vlt_all", "vltmt"],
= (dist => [ "dist"],
atsim => [ "simulator", "simulator_st", "atsim"],
ghdl => ["linter", "simulator", "simulator_st", "ghdl"],
iv => [ "simulator", "simulator_st", "iv"],
ms => ["linter", "simulator", "simulator_st", "ms"],
nc => ["linter", "simulator", "simulator_st", "nc"],
vcs => ["linter", "simulator", "simulator_st", "vcs"],
xsim => ["linter", "simulator", "simulator_st", "xsim"],
vlt => ["linter", "simulator", "simulator_st", "vlt_all", "vlt"],
vltmt => [ "simulator", "vlt_all", "vltmt"],
);
#======================================================================
@ -546,6 +546,7 @@ sub new {
make_top_shell => 1, # Make a default __top.v file
make_main => 1, # Make __main.cpp
make_pli => 0, # need to compile pli
sc_time_resolution => "SC_PS", # Keep - PS is SystemC default
sim_time => 1100,
benchmark => $opt_benchmark,
verbose => $opt_verbose,
@ -1613,7 +1614,7 @@ sub _make_main {
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
print $fh "// Test defines\n";
print $fh "#define VL_TIME_MULTIPLIER $self->{vl_time_multiplier}\n" if $self->{vl_time_multiplier};
print $fh "#define MAIN_TIME_MULTIPLIER ".($self->{main_time_multiplier} || 1)."\n";
print $fh "// OS header\n";
print $fh "#include \"verilatedos.h\"\n";
@ -1632,8 +1633,13 @@ sub _make_main {
print $fh "$VM_PREFIX* topp;\n";
if (!$self->sc) {
print $fh "vluint64_t main_time = false;\n";
print $fh "double sc_time_stamp() { return main_time; }\n";
if ($self->{vl_time_stamp64}) {
print $fh "vluint64_t main_time = 0;\n";
print $fh "vluint64_t vl_time_stamp() { return main_time; }\n";
} else {
print $fh "double main_time = 0;\n";
print $fh "double sc_time_stamp() { return main_time; }\n";
}
}
if ($self->{savable}) {
@ -1663,7 +1669,8 @@ sub _make_main {
print $fh "int sc_main(int argc, char** argv) {\n";
print $fh " sc_signal<bool> fastclk;\n" if $self->{inputs}{fastclk};
print $fh " sc_signal<bool> clk;\n" if $self->{inputs}{clk};
print $fh " sc_time sim_time($self->{sim_time}, SC_NS);\n";
print $fh " sc_set_time_resolution(1, $Self->{sc_time_resolution});\n";
print $fh " sc_time sim_time($self->{sim_time}, $Self->{sc_time_resolution});\n";
} else {
print $fh "int main(int argc, char** argv, char** env) {\n";
print $fh " double sim_time = $self->{sim_time};\n";
@ -1719,7 +1726,8 @@ sub _make_main {
_print_advance_time($self, $fh, 10);
print $fh " }\n";
print $fh " while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {\n";
print $fh " while ((sc_time_stamp() < sim_time * MAIN_TIME_MULTIPLIER)\n";
print $fh " && !Verilated::gotFinish()) {\n";
for (my $i=0; $i<5; $i++) {
my $action = 0;
if ($self->{inputs}{fastclk}) {
@ -1775,7 +1783,7 @@ sub _print_advance_time {
if ($self->sc) {
print $fh "#if (SYSTEMC_VERSION>=20070314)\n";
print $fh " sc_start(${time}, SC_NS);\n";
print $fh " sc_start(${time}, $Self->{sc_time_resolution});\n";
print $fh "#else\n";
print $fh " sc_start(${time});\n";
print $fh "#endif\n";
@ -1788,7 +1796,7 @@ sub _print_advance_time {
$fh->print("#endif // VM_TRACE\n");
}
}
print $fh " main_time += ${time};\n";
print $fh " main_time += ${time} * MAIN_TIME_MULTIPLIER;\n";
}
}

View File

@ -1,7 +1,7 @@
$version Generated by VerilatedVcd $end
$date Fri Jun 22 19:23:24 2018
$end
$timescale 1ns $end
$timescale 1ps $end
$scope module top $end
$var wire 1 $ clk $end

View File

@ -1,7 +1,7 @@
$version Generated by VerilatedVcd $end
$date Thu Mar 19 18:37:02 2020
$end
$timescale 1ns $end
$timescale 1ps $end
$scope module top $end
$var wire 1 5! clk $end

View File

@ -1,7 +1,7 @@
$version Generated by VerilatedVcd $end
$date Thu Oct 24 09:44:07 2019
$end
$timescale 1ns $end
$timescale 1ps $end
$scope module top $end
$var wire 1 ) clk $end

View File

@ -1,3 +1,3 @@
default: [10.000] 0t time [ 10.000] No0 time p= 10000 0p='h2710
default: [10] 0t time [ 10] No0 time p= 10 0p='ha
*-* All Finished *-*

View File

@ -11,8 +11,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
compile(
verilator_flags2 => ['-DVL_TIME_MULTIPLER=1000'],
make_flags => 'CPPFLAGS_ADD=-DVL_TIME_MULTIPLIER=1000',
);
execute(

View File

@ -1,3 +1,3 @@
[1000.000] cyc==99 crc=2961926edde3e5c6018be970cdbf327b72b5f3c5eab42995891005eec8767e5fdf03051edbe9d222ee756ee34d8d6c83ee877aad65c487140ac87d26c636a66214b4a69acad924c568cc8e8c79f97d07a6eedf91011919d0e3cdda5215ee58c942f6c4dea48b3f38abc77bf47e4f6d6a859fcc5b5d46ec9d2f6a5bf7b978b1ba7ca15d0713a2eb06ade1570c4e3a12db687625eef8dfebcb4095ab4bdffe79c1298f609307a5ef773a6432b855e3e54deb88ca342bf5a7fecc5f2f3e165a59cdb9179718a2d11c9d55f14d69f40b01e41fcb7335a8872a6ba7876ec684d6a3af0b82aa31cca6e26340a2589cf7bf886faa8d23844596dc71233c7025c5250a968b770ab72db90b03d8c045fb8848159df544a3a3bf063269be0aa11d5507f5c8b328b760a6df9e3fbe276faad8eadee126443ad3f99d595b12d0ae514b20693298a58642a07718f9ab7ea8c66575f7f8d0e3ba77d992235b3d5a4e015a7ff9b97a8c4f48ebdbfc2365e6bca4dd3ba6bfc7e850f7c8e2842c717a1d85a977a033f564fc
[1000.000] cyc==99 crc=001010010110000110010010011011101101110111100011111001011100011000000001100010111110100101110000110011011011111100110010011110110111001010110101111100111100010111101010101101000010100110010101100010010001000000000101111011101100100001110110011111100101111111011111000000110000010100011110110110111110100111010010001000101110111001110101011011101110001101001101100011010110110010000011111011101000011101111010101011010110010111000100100001110001010000001010110010000111110100100110110001100011011010100110011000100001010010110100101001101001101011001010110110010010010011000101011010001100110010001110100011000111100111111001011111010000011110100110111011101101111110010001000000010001100100011001110100001110001111001101110110100101001000010101111011100101100011001001010000101111011011000100110111101010010010001011001111110011100010101011110001110111101111110100011111100100111101101101011010101000010110011111110011000101101101011101010001101110110010011101001011110110101001011011111101111011100101111000101100011011101001111100101000010101110100000111000100111010001011101011000001101010110111100001010101110000110001001110001110100001001011011011011010000111011000100101111011101111100011011111111010111100101101000000100101011010101101001011110111111111111001111001110000010010100110001111011000001001001100000111101001011110111101110111001110100110010000110010101110000101010111100011111001010100110111101011100010001100101000110100001010111111010110100111111111101100110001011111001011110011111000010110010110100101100111001101101110010001011110010111000110001010001011010001000111001001110101010101111100010100110101101001111101000000101100000001111001000001111111001011011100110011010110101000100001110010101001101011101001111000011101101110110001101000010011010110101000111010111100001011100000101010101000110001110011001010011011100010011000110100000010100010010110001001110011110111101111111000100001101111101010101000110100100011100001000100010110010110110111000111000100100011001111000111000000100101110001010010010100001010100101101000101101110111000010101011011100101101101110010000101100000011110110001100000001000101111110111000100001001000000101011001110111110101010001001010001110100011101111110000011000110010011010011011111000001010101000010001110101010101000001111111010111001000101100110010100010110111011000001010011011011111100111100011111110111110001001110110111110101010110110001110101011011110111000010010011001000100001110101101001111111001100111010101100101011011000100101101000010101110010100010100101100100000011010010011001010011000101001011000011001000010101000000111011100011000111110011010101101111110101010001100011001100101011101011111011111111000110100001110001110111010011101111101100110010010001000110101101100111101010110100100111000000001010110100111111111111001101110010111101010001100010011110100100011101011110110111111110000100011011001011110011010111100101001001101110100111011101001101011111111000111111010000101000011110111110010001110001010000100001011000111000101111010000111011000010110101001011101111010000000110011111101010110010011111100
[1000] cyc==99 crc=2961926edde3e5c6018be970cdbf327b72b5f3c5eab42995891005eec8767e5fdf03051edbe9d222ee756ee34d8d6c83ee877aad65c487140ac87d26c636a66214b4a69acad924c568cc8e8c79f97d07a6eedf91011919d0e3cdda5215ee58c942f6c4dea48b3f38abc77bf47e4f6d6a859fcc5b5d46ec9d2f6a5bf7b978b1ba7ca15d0713a2eb06ade1570c4e3a12db687625eef8dfebcb4095ab4bdffe79c1298f609307a5ef773a6432b855e3e54deb88ca342bf5a7fecc5f2f3e165a59cdb9179718a2d11c9d55f14d69f40b01e41fcb7335a8872a6ba7876ec684d6a3af0b82aa31cca6e26340a2589cf7bf886faa8d23844596dc71233c7025c5250a968b770ab72db90b03d8c045fb8848159df544a3a3bf063269be0aa11d5507f5c8b328b760a6df9e3fbe276faad8eadee126443ad3f99d595b12d0ae514b20693298a58642a07718f9ab7ea8c66575f7f8d0e3ba77d992235b3d5a4e015a7ff9b97a8c4f48ebdbfc2365e6bca4dd3ba6bfc7e850f7c8e2842c717a1d85a977a033f564fc
[1000] cyc==99 crc=001010010110000110010010011011101101110111100011111001011100011000000001100010111110100101110000110011011011111100110010011110110111001010110101111100111100010111101010101101000010100110010101100010010001000000000101111011101100100001110110011111100101111111011111000000110000010100011110110110111110100111010010001000101110111001110101011011101110001101001101100011010110110010000011111011101000011101111010101011010110010111000100100001110001010000001010110010000111110100100110110001100011011010100110011000100001010010110100101001101001101011001010110110010010010011000101011010001100110010001110100011000111100111111001011111010000011110100110111011101101111110010001000000010001100100011001110100001110001111001101110110100101001000010101111011100101100011001001010000101111011011000100110111101010010010001011001111110011100010101011110001110111101111110100011111100100111101101101011010101000010110011111110011000101101101011101010001101110110010011101001011110110101001011011111101111011100101111000101100011011101001111100101000010101110100000111000100111010001011101011000001101010110111100001010101110000110001001110001110100001001011011011011010000111011000100101111011101111100011011111111010111100101101000000100101011010101101001011110111111111111001111001110000010010100110001111011000001001001100000111101001011110111101110111001110100110010000110010101110000101010111100011111001010100110111101011100010001100101000110100001010111111010110100111111111101100110001011111001011110011111000010110010110100101100111001101101110010001011110010111000110001010001011010001000111001001110101010101111100010100110101101001111101000000101100000001111001000001111111001011011100110011010110101000100001110010101001101011101001111000011101101110110001101000010011010110101000111010111100001011100000101010101000110001110011001010011011100010011000110100000010100010010110001001110011110111101111111000100001101111101010101000110100100011100001000100010110010110110111000111000100100011001111000111000000100101110001010010010100001010100101101000101101110111000010101011011100101101101110010000101100000011110110001100000001000101111110111000100001001000000101011001110111110101010001001010001110100011101111110000011000110010011010011011111000001010101000010001110101010101000001111111010111001000101100110010100010110111011000001010011011011111100111100011111110111110001001110110111110101010110110001110101011011110111000010010011001000100001110101101001111111001100111010101100101011011000100101101000010101110010100010100101100100000011010010011001010011000101001011000011001000010101000000111011100011000111110011010101101111110101010001100011001100101011101011111011111111000110100001110001110111010011101111101100110010010001000110101101100111101010110100100111000000001010110100111111111111001101110010111101010001100010011110100100011101011110110111111110000100011011001011110011010111100101001001101110100111011101001101011111111000111111010000101000011110111110010001110001010000100001011000111000101111010000111011000010110101001011101111010000000110011111101010110010011111100
*-* All Finished *-*

View File

@ -11,7 +11,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
compile(
make_flags => 'CPPFLAGS_ADD=-DVL_TIME_MULTIPLIER=1000',
);
execute(

View File

@ -0,0 +1,2 @@
Time scale of t is 1ms / 1us
*-* All Finished *-*

View File

@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
compile(
verilator_flags2 => ["-timescale 1ms/1us"],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,13 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
initial begin
$printtimescale;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,2 @@
Time scale of t is 1ms / 1us
*-* All Finished *-*

View File

@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
compile(
verilator_flags2 => ["-timescale-override 1ms/1us"],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`timescale 1s/1s
module t;
initial begin
$printtimescale;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,2 @@
Time scale of t is 1s / 1us
*-* All Finished *-*

View File

@ -0,0 +1,26 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_flag_timescale_override.v");
compile(
verilator_flags2 => ["-timescale-override /1us"],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -9,11 +9,6 @@ module t (/*AUTOARG*/
clk
);
`ifdef verilator // Otherwise need it in every module, including test, but that'll make a mess
timeunit 1ns;
timeprecision 1ns;
`endif
input clk;
integer cyc; initial cyc=1;

View File

@ -1,7 +1,7 @@
$version Generated by VerilatedVcd $end
$date Wed Dec 4 07:47:51 2019
$end
$timescale 1ns $end
$timescale 1ps $end
$scope module top $end
$var wire 1 0 clk $end

View File

@ -9,9 +9,6 @@ module t;
endmodule
module sub ();
timeunit 1ns;
timeprecision 1ps;
parameter REAL = 0.0;
initial begin

View File

@ -1,7 +1,7 @@
$version Generated by VerilatedVcd $end
$date Fri Jun 22 19:27:45 2018
$end
$timescale 1ns $end
$timescale 1ps $end
$scope module top $end
$var wire 1 / clk $end

View File

@ -1,7 +1,7 @@
$version Generated by VerilatedVcd $end
$date Tue Feb 11 16:07:02 2020
$end
$timescale 1ns $end
$timescale 1ps $end
$scope module top $end
$var wire 1 o2 clk $end

View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2019 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,32 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
`timescale 1ns/1ps
module t;
time t;
// realtime value scaled to timeunit, rounded to timeprecision
initial begin
// verilator lint_off REALCVT
t = 1s; `checkd(t, 64'd1000000000);
t = 2ms; `checkd(t, 2000000);
t = 1ms; `checkd(t, 1000000);
t = 1us; `checkd(t, 1000);
t = 1ns; `checkd(t, 1);
t = 1ps; `checkd(t, 0); // Below precision
t = 1fs; `checkd(t, 0);
t = 2.3ps; `checkd(t, 0);
t = 2.4us; `checkd(t, 2400);
// verilator lint_on REALCVT
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,3 @@
top.t.ps: Input time 5432109.877000ns 5432109877
top.t.ns: Input time 5432109877.000000ns 5432109877
*-* All Finished *-*

23
test_regress/t/t_time_passed.pl Executable file
View 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 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,64 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`timescale 1ns/1ps
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc = 0;
time in;
// verilator lint_off REALCVT
initial in = 5432109876.543210ns; // Will round to time units
// verilator lint_on REALCVT
// This shows time changes when passed between modules with different units
// See also discussion in uvm_tlm2_time.svh
ps ps (.*);
ns ns (.*);
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc == 60) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
`timescale 1ps/1ps
module ps
(input clk,
input integer cyc,
input time in);
always @ (posedge clk) begin
if (cyc == 10) begin
$timeformat(-9, 6, "ns", 16);
$write("%m: Input time %t %d\n", in, in);
end
end
endmodule
`timescale 1ns/1ps
module ns
(input clk,
input integer cyc,
input time in);
always @ (posedge clk) begin
if (cyc == 20) begin
$timeformat(-9, 6, "ns", 16);
$write("%m: Input time %t %d\n", in, in);
end
end
endmodule

View File

@ -0,0 +1,10 @@
[0] In top.t: Hi
Time scale of t is 1ns / 1ps
Time: ' 0' 10ns=10000
Time: ' 0-my-ms' 10ns=0-my-ms
Time: ' 0.0-my-ms' 10ns=0.0-my-ms
Time: ' 0.00-my-us' 10ns=0.01-my-us
Time: ' 0.000-my-ns' 10ns=10.000-my-ns
Time: ' 0.000-my-ps' 10ns=10000.000-my-ps
Time: ' 0.0000-my-fs' 10ns=10000000.0000-my-fs
*-* All Finished *-*

23
test_regress/t/t_time_print.pl Executable file
View 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 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
timeunit 1ns;
timeprecision 1ps;
time t;
initial begin
t = 10ns;
$write("[%0t] In %m: Hi\n", $time);
$printtimescale;
$write("Time: '%t' 10ns=%0t\n", $time, t);
$timeformat(-3, 0, "-my-ms", 8);
$write("Time: '%t' 10ns=%0t\n", $time, t);
$timeformat(-3, 1, "-my-ms", 10);
$write("Time: '%t' 10ns=%0t\n", $time, t);
$timeformat(-6, 2, "-my-us", 12);
$write("Time: '%t' 10ns=%0t\n", $time, t);
$timeformat(-9, 3, "-my-ns", 13);
$write("Time: '%t' 10ns=%0t\n", $time, t);
$timeformat(-12, 3, "-my-ps", 13);
$write("Time: '%t' 10ns=%0t\n", $time, t);
$timeformat(-15, 4, "-my-fs", 14);
$write("Time: '%t' 10ns=%0t\n", $time, t);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,31 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
time texpect = `TEST_EXPECT;
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc == 1) begin
$printtimescale;
$write("[%0t] In %m: Hi - expect this is %0t\n", $time, texpect);
if ($time != texpect) begin
$write("[%0t] delta = %d\n", $time, $time - texpect);
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,2 @@
%Error: SystemC's sc_set_time_resolution is 10^-9, which does not match Verilog timeprecision 10^-12. Suggest use 'sc_set_time_resolution(1ps)', or Verilator '--timescale-override 1ns/1ns'
Aborting...

29
test_regress/t/t_time_sc_bad.pl Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_time_sc.v");
$Self->{sc_time_resolution} = 'SC_NS';
compile(
verilator_flags2 => ['-sc', '-timescale 1ps/1ps', # Mismatch w/sc_time_resolution
'+define+TEST_EXPECT=2us'],
);
execute(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,3 @@
Time scale of t is 1fs / 1fs
[20] In top.t: Hi - expect this is 20
*-* All Finished *-*

29
test_regress/t/t_time_sc_fs.pl Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_time_sc.v");
$Self->{sc_time_resolution} = 'SC_FS';
compile(
verilator_flags2 => ['-sc', '-timescale 1fs/1fs',
'+define+TEST_EXPECT=20fs'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,6 @@
Warning: (W516) default time unit changed to time resolution
In file: /svaha/sicortex/eda/systemc/systemc-2.3.3/systemc-2.3.3/src/sysc/kernel/sc_time.cpp:412
Time scale of t is 1ms / 1ms
[20] In top.t: Hi - expect this is 20
*-* All Finished *-*

29
test_regress/t/t_time_sc_ms.pl Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_time_sc.v");
$Self->{sc_time_resolution} = 'SC_MS';
compile(
verilator_flags2 => ['-sc', '-timescale 1ms/1ms',
'+define+TEST_EXPECT=20ms'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,3 @@
Time scale of t is 1ns / 1ns
[20] In top.t: Hi - expect this is 20
*-* All Finished *-*

29
test_regress/t/t_time_sc_ns.pl Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_time_sc.v");
$Self->{sc_time_resolution} = 'SC_NS';
compile(
verilator_flags2 => ['-sc', '-timescale 1ns/1ns',
'+define+TEST_EXPECT=20ns'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,6 @@
Warning: (W516) default time unit changed to time resolution
In file: /svaha/sicortex/eda/systemc/systemc-2.3.3/systemc-2.3.3/src/sysc/kernel/sc_time.cpp:412
Time scale of t is 1s / 1s
[20] In top.t: Hi - expect this is 20
*-* All Finished *-*

29
test_regress/t/t_time_sc_sec.pl Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_time_sc.v");
$Self->{sc_time_resolution} = 'SC_SEC';
compile(
verilator_flags2 => ['-sc', '-timescale 1s/1s',
'+define+TEST_EXPECT=20s'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,6 @@
Warning: (W516) default time unit changed to time resolution
In file: /svaha/sicortex/eda/systemc/systemc-2.3.3/systemc-2.3.3/src/sysc/kernel/sc_time.cpp:412
Time scale of t is 1us / 1us
[20] In top.t: Hi - expect this is 20
*-* All Finished *-*

29
test_regress/t/t_time_sc_us.pl Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
top_filename("t/t_time_sc.v");
$Self->{sc_time_resolution} = 'SC_US';
compile(
verilator_flags2 => ['-sc', '-timescale 1us/1us',
'+define+TEST_EXPECT=20us'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,26 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt_all => 1);
# Verilator before 4.033 had 'double sc_time_stamp()', make sure new form compiles
$self->{vl_time_stamp64} = 1;
compile(
verilator_flags2 => ['-DVL_TIME_STAMP64=1'],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,25 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
always @ (posedge clk) begin
cyc <= cyc + 1;
if (cyc == 1) begin
$write("[%0t] In %m: Hi\n", $time);
$printtimescale;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,28 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt_all => 1);
top_filename('t/t_time_stamp64.v');
# Verilator before 4.033 had 'double sc_time_stamp()', make sure this still compiles
$self->{vl_time_stamp64} = 0;
compile(
verilator_flags2 => [],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,50 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`timescale `time_scale_units / `time_scale_prec
import "DPI-C" function void dpii_check();
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc = 0;
// verilator lint_off REALCVT
time digits = 5432109876.543210ns; // Will round to time units
realtime rdigits = 5432109876.543210ns; // Will round to time precision
// verilator lint_on REALCVT
always @ (posedge clk) begin
cyc <= cyc + 1;
`ifdef TEST_VERBOSE
$write("- [%0t] tick\n", $time);
`endif
if ($time >= 60) begin
$write(":: In %m\n");
$printtimescale;
$write("[%0t] time%%0d=%0d 123%%0t=%0t\n", $time, $time, 123);
$write(" dig%%0t=%0t dig%%0d=%0d\n", digits, digits);
$write(" rdig%%0t=%0t rdig%%0f=%0f\n", rdigits, rdigits);
$timeformat(-9, 6, "ns", 16);
$write("[%0t] time%%0d=%0d 123%%0t=%0t\n", $time, $time, 123);
$write(" dig%%0t=%0t dig%%0d=%0d\n", digits, digits);
$write(" rdig%%0t=%0t rdig%%0f=%0f\n", rdigits, rdigits);
$write("[%0t] stime%%0t=%0t stime%%0d=%0d stime%%0f=%0f\n",
$time, $stime, $stime, $stime);
// verilator lint_off REALCVT
$write("[%0t] rtime%%0t=%0t rtime%%0d=%0d rtime%%0f=%0f\n",
$time, $realtime, $realtime, $realtime);
// verilator lint_on REALCVT
dpii_check();
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 10ms / 10ns
[60000000] time%0d=60 123%0t=123000000
dig%0t=543000000 dig%0d=543
rdig%0t=543210987 rdig%0f=543.210988
[600000000.000000ns] time%0d=60 123%0t=1230000000.000000ns
dig%0t=5430000000.000000ns dig%0d=543
rdig%0t=5432109876.543210ns rdig%0f=543.210988
[600000000.000000ns] stime%0t=600000000.000000ns stime%0d=60 stime%0f=60.000000
[600000000.000000ns] rtime%0t=600000000.000000ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 0,60000000 vpiScaledRealTime = 6e+07
global vpiTimeUnit = -2 vpiTimePrecision = -8
top.t vpiSimTime = 0,60000000 vpiScaledRealTime = 60
top.t vpiTimeUnit = -2 vpiTimePrecision = -8
*-* All Finished *-*

View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 10e-3 / 10e-9;
compile(
v_flags2 => ['+define+time_scale_units=10ms +define+time_scale_prec=10ns',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 1fs / 1fs
[60] time%0d=60 123%0t=123
dig%0t=5432109876543210 dig%0d=5432109876543210
rdig%0t=5432109876543210 rdig%0f=5432109876543210.000000
[0.000060ns] time%0d=60 123%0t=0.000123ns
dig%0t=5432109876.543210ns dig%0d=5432109876543210
rdig%0t=5432109876.543210ns rdig%0f=5432109876543210.000000
[0.000060ns] stime%0t=0.000060ns stime%0d=60 stime%0f=60.000000
[0.000060ns] rtime%0t=0.000060ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 0,60 vpiScaledRealTime = 60
global vpiTimeUnit = -15 vpiTimePrecision = -15
top.t vpiSimTime = 0,60 vpiScaledRealTime = 60
top.t vpiTimeUnit = -15 vpiTimePrecision = -15
*-* All Finished *-*

View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 1e-15 / 1e-15;
compile(
v_flags2 => ['+define+time_scale_units=1fs +define+time_scale_prec=1fs',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 1ms / 10ns
[6000000] time%0d=60 123%0t=12300000
dig%0t=543200000 dig%0d=5432
rdig%0t=543210987 rdig%0f=5432.109877
[60000000.000000ns] time%0d=60 123%0t=123000000.000000ns
dig%0t=5432000000.000000ns dig%0d=5432
rdig%0t=5432109876.543210ns rdig%0f=5432.109877
[60000000.000000ns] stime%0t=60000000.000000ns stime%0d=60 stime%0f=60.000000
[60000000.000000ns] rtime%0t=60000000.000000ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 0,6000000 vpiScaledRealTime = 6e+06
global vpiTimeUnit = -3 vpiTimePrecision = -8
top.t vpiSimTime = 0,6000000 vpiScaledRealTime = 60
top.t vpiTimeUnit = -3 vpiTimePrecision = -8
*-* All Finished *-*

View File

@ -0,0 +1,32 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 1e-3 / 10e-9;
compile(
v_flags2 => ['+define+time_scale_units=1ms +define+time_scale_prec=10ns',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi --trace'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
file_grep("$Self->{obj_dir}/simx.vcd", qr!timescale +10ns!);
ok(1);
1;

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 1ns / 1ns
[60] time%0d=60 123%0t=123
dig%0t=5432109877 dig%0d=5432109877
rdig%0t=5432109876 rdig%0f=5432109876.543210
[60.000000ns] time%0d=60 123%0t=123.000000ns
dig%0t=5432109877.000000ns dig%0d=5432109877
rdig%0t=5432109876.543210ns rdig%0f=5432109876.543210
[60.000000ns] stime%0t=60.000000ns stime%0d=60 stime%0f=60.000000
[60.000000ns] rtime%0t=60.000000ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 0,60 vpiScaledRealTime = 60
global vpiTimeUnit = -9 vpiTimePrecision = -9
top.t vpiSimTime = 0,60 vpiScaledRealTime = 60
top.t vpiTimeUnit = -9 vpiTimePrecision = -9
*-* All Finished *-*

View File

@ -0,0 +1,32 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 1e-9 / 1e-9;
compile(
v_flags2 => ['+define+time_scale_units=1ns +define+time_scale_prec=1ns',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi --trace'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
file_grep("$Self->{obj_dir}/simx.vcd", qr!timescale +1ns!);
ok(1);
1;

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 1ps / 1fs
[60000] time%0d=60 123%0t=123000
dig%0t=5432109876543000 dig%0d=5432109876543
rdig%0t=5432109876543209 rdig%0f=5432109876543.209961
[0.060000ns] time%0d=60 123%0t=0.123000ns
dig%0t=5432109876.543000ns dig%0d=5432109876543
rdig%0t=5432109876.543209ns rdig%0f=5432109876543.209961
[0.060000ns] stime%0t=0.060000ns stime%0d=60 stime%0f=60.000000
[0.060000ns] rtime%0t=0.059999ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 0,60000 vpiScaledRealTime = 60000
global vpiTimeUnit = -12 vpiTimePrecision = -15
top.t vpiSimTime = 0,60000 vpiScaledRealTime = 60
top.t vpiTimeUnit = -12 vpiTimePrecision = -15
*-* All Finished *-*

View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 1e-12 / 10e-15;
compile(
v_flags2 => ['+define+time_scale_units=1ps +define+time_scale_prec=1fs',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 1s / 10ns
[6000000000] time%0d=60 123%0t=12300000000
dig%0t=500000000 dig%0d=5
rdig%0t=543210987 rdig%0f=5.432110
[60000000000.000000ns] time%0d=60 123%0t=123000000000.000000ns
dig%0t=5000000000.000000ns dig%0d=5
rdig%0t=5432109876.543210ns rdig%0f=5.432110
[60000000000.000000ns] stime%0t=60000000000.000000ns stime%0d=60 stime%0f=60.000000
[60000000000.000000ns] rtime%0t=60000000000.000000ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 1,1705032704 vpiScaledRealTime = 6e+09
global vpiTimeUnit = 0 vpiTimePrecision = -8
top.t vpiSimTime = 1,1705032704 vpiScaledRealTime = 60
top.t vpiTimeUnit = 0 vpiTimePrecision = -8
*-* All Finished *-*

View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 1e0 / 10e-9;
compile(
v_flags2 => ['+define+time_scale_units=1s +define+time_scale_prec=10ns',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
:: In top.t
Time scale of t is 1us / 1ns
[60000] time%0d=60 123%0t=123000
dig%0t=5432110000 dig%0d=5432110
rdig%0t=5432109876 rdig%0f=5432109.876543
[60000.000000ns] time%0d=60 123%0t=123000.000000ns
dig%0t=5432110000.000000ns dig%0d=5432110
rdig%0t=5432109876.543209ns rdig%0f=5432109.876543
[60000.000000ns] stime%0t=60000.000000ns stime%0d=60 stime%0f=60.000000
[60000.000000ns] rtime%0t=59999.999999ns rtime%0d=60 rtime%0f=60.000000
global vpiSimTime = 0,60000 vpiScaledRealTime = 60000
global vpiTimeUnit = -6 vpiTimePrecision = -9
top.t vpiSimTime = 0,60000 vpiScaledRealTime = 60
top.t vpiTimeUnit = -6 vpiTimePrecision = -9
*-* All Finished *-*

View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator_st => 1);
top_filename("t/t_time_vpi.v");
$Self->{main_time_multiplier} = 1e-6 / 1e-9;
compile(
v_flags2 => ['+define+time_scale_units=1us +define+time_scale_prec=1ns',
't/t_time_vpi_c.cpp'],
verilator_flags2 => ['--vpi'],
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,62 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2009-2011 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.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
#include <cstdio>
#include "svdpi.h"
#include "vpi_user.h"
//======================================================================
#define NEED_EXTERNS
#ifdef NEED_EXTERNS
extern "C" {
extern void dpii_check();
}
#endif
//======================================================================
void show(vpiHandle obj) {
const char* namep;
if (obj) {
namep = vpi_get_str(vpiName, obj);
} else {
namep = "global";
}
s_vpi_time t;
t.type = vpiSimTime;
vpi_get_time(obj, &t);
vpi_printf(const_cast<char*>("%s vpiSimTime = %d,%d"), namep, (int)t.high, (int)t.low);
// Should be same value as vpiSimTime, just converted to real
t.type = vpiScaledRealTime;
vpi_get_time(obj, &t);
vpi_printf(const_cast<char*>(" vpiScaledRealTime = %g\n"), t.real);
// These will both print the precision, because the 0 asks for global scope
int u = vpi_get(vpiTimeUnit, obj);
int p = vpi_get(vpiTimePrecision, obj);
vpi_printf(const_cast<char*>("%s vpiTimeUnit = %d"), namep, u);
vpi_printf(const_cast<char*>(" vpiTimePrecision = %d\n"), p);
}
void dpii_check() {
show(0);
vpiHandle mod = vpi_handle_by_name((PLI_BYTE8*)"top.t", NULL);
if (!mod) {
vpi_printf(const_cast<char*>("-- Cannot vpi_find module\n"));
} else {
show(mod);
}
}

View File

@ -0,0 +1,2 @@
Time scale of t is 1ps / 1ps
*-* All Finished *-*

View 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 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,15 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under The Creative Commons Public Domain, for
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// Intentionally no timescale here, nor in driver file
module t;
initial begin
// Unspecified, but general consensus is 1s is default timeunit
$printtimescale;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

Some files were not shown because too many files have changed in this diff Show More