Add vpiTimeUnit and allow to specify time as string, bug1636.

Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Stefan Wallentowitz 2019-12-13 19:11:37 -05:00 committed by Wilson Snyder
parent 39950d16d0
commit 3ac6745658
20 changed files with 141 additions and 42 deletions

View File

@ -12,6 +12,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Update FST trace API for better performance.
**** Add vpiTimeUnit and allow to specify time as string, bug1636. [Stefan Wallentowitz]
**** Fix little endian cell ranges, bug1631. [Julien Margetts]

View File

@ -1837,6 +1837,30 @@ IData VL_ATOI_N(const std::string& str, int base) VL_PURE {
return static_cast<IData>(v);
}
//===========================================================================
// Timescale conversion
// Helper function for conversion of timescale strings
// Converts (1|10|100)(s|ms|us|ns|ps|fs) to power of then
int VL_TIME_STR_CONVERT(const char* strp) {
int scale = 0;
if (!strp) return 0;
if (*strp++ != '1') return 0;
while (*strp == '0') { scale++; strp++; }
switch (*strp++) {
case 's': break;
case 'm': scale -= 3; break;
case 'u': scale -= 6; break;
case 'n': scale -= 9; break;
case 'p': scale -= 12; break;
case 'f': scale -= 15; break;
default: return 0;
}
if ((scale < 0) && (*strp++ != 's')) return 0;
if (*strp) return 0;
return scale;
}
//===========================================================================
// Verilated:: Methods

View File

@ -737,8 +737,21 @@ extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
//=========================================================================
// Pli macros
extern int VL_TIME_STR_CONVERT(const char* strp) VL_PURE;
#ifndef VL_TIME_PRECISION
# define VL_TIME_PRECISION (-12) ///< Timescale units only for for VPI return - picoseconds
# 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
# 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
# endif
#endif
#ifndef VL_TIME_MULTIPLIER
# define VL_TIME_MULTIPLIER 1

View File

@ -1224,6 +1224,9 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
case vpiTimePrecision: {
return VL_TIME_PRECISION;
}
case vpiTimeUnit: {
return VL_TIME_UNIT;
}
case vpiType: {
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return 0;

View File

@ -432,6 +432,12 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# define VL_STRCASECMP strcasecmp
#endif
//=========================================================================
// Stringify macros
#define VL_STRINGIFY(x) VL_STRINGIFY2(x)
#define VL_STRINGIFY2(x) #x
//=========================================================================
#endif // Guard

View File

@ -5,9 +5,6 @@
#include "verilated.h"
#include "verilated_vcd_c.h"
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
Vt_order_multidriven* vcore;
VerilatedVcdC* vcd;
vluint64_t vtime;
@ -46,7 +43,7 @@ int main() {
vcd = new VerilatedVcdC;
vcore->trace(vcd, 99);
vcd->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
vcd->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
vcore->i_clk_wr = 0;
vcore->i_clk_rd = 0;

View File

@ -13,9 +13,6 @@
#include "Vt_scope_map.h"
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
using namespace std;
unsigned long long main_time = 0;
@ -31,7 +28,7 @@ int main(int argc, char** argv, char** env) {
VerilatedVcdC* tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
top->CLK = 0;
top->eval();

View File

@ -0,0 +1,53 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
#include <verilated.h>
#include VM_PREFIX_INCLUDE
unsigned long long main_time = 0;
double sc_time_stamp() { return (double)main_time; }
#include <iostream>
using namespace std;
#define FILENM "t_timescale.cpp"
#define CHECK_RESULT(got, exp) \
if ((got) != (exp)) { \
cout << dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \
<< " EXP = " << (exp) << endl; \
return __LINE__; \
}
int main(int argc, char** argv, char** env) {
VM_PREFIX* top = new VM_PREFIX("top");
CHECK_RESULT(VL_TIME_STR_CONVERT("100s"), 2);
CHECK_RESULT(VL_TIME_STR_CONVERT("10s"), 1);
CHECK_RESULT(VL_TIME_STR_CONVERT("1s"), 0);
CHECK_RESULT(VL_TIME_STR_CONVERT("100ms"), -1);
CHECK_RESULT(VL_TIME_STR_CONVERT("10ms"), -2);
CHECK_RESULT(VL_TIME_STR_CONVERT("1ms"), -3);
CHECK_RESULT(VL_TIME_STR_CONVERT("100us"), -4);
CHECK_RESULT(VL_TIME_STR_CONVERT("10us"), -5);
CHECK_RESULT(VL_TIME_STR_CONVERT("1us"), -6);
CHECK_RESULT(VL_TIME_STR_CONVERT("100ns"), -7);
CHECK_RESULT(VL_TIME_STR_CONVERT("10ns"), -8);
CHECK_RESULT(VL_TIME_STR_CONVERT("1ns"), -9);
CHECK_RESULT(VL_TIME_STR_CONVERT("100ps"), -10);
CHECK_RESULT(VL_TIME_STR_CONVERT("10ps"), -11);
CHECK_RESULT(VL_TIME_STR_CONVERT("1ps"), -12);
CHECK_RESULT(VL_TIME_STR_CONVERT("100fs"), -13);
CHECK_RESULT(VL_TIME_STR_CONVERT("10fs"), -14);
CHECK_RESULT(VL_TIME_STR_CONVERT("1fs"), -15);
CHECK_RESULT(VL_TIME_STR_CONVERT("1.5s"), 0);
CHECK_RESULT(VL_TIME_STR_CONVERT("1s "), 0);
CHECK_RESULT(VL_TIME_STR_CONVERT("1ss"), 0);
CHECK_RESULT(VL_TIME_STR_CONVERT("s"), 0);
CHECK_RESULT(VL_TIME_STR_CONVERT(0), 0);
top->final();
printf("*-* All Finished *-*\n");
return 0;
}

23
test_regress/t/t_timescale.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-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.
scenarios(vlt_all => 1);
compile(
make_top_shell => 0,
make_main => 0,
v_flags2 => ["--exe $Self->{t_dir}/t_timescale.cpp"],
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,3 @@
module t;
endmodule

View File

@ -10,15 +10,12 @@
#include VM_PREFIX_INCLUDE
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
unsigned long long main_time = 0;
double sc_time_stamp() { return (double)main_time; }
const char* trace_name() {
static char name[1000];
VL_SNPRINTF(name, 1000, STRINGIFY(TEST_OBJ_DIR) "/simpart_%04d.vcd", (int)main_time);
VL_SNPRINTF(name, 1000, VL_STRINGIFY(TEST_OBJ_DIR) "/simpart_%04d.vcd", (int)main_time);
return name;
}

View File

@ -12,9 +12,6 @@
#include "Vt_trace_public_func_t.h"
#include "Vt_trace_public_func_glbl.h"
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
unsigned long long main_time = 0;
double sc_time_stamp() { return (double)main_time; }
@ -28,7 +25,7 @@ int main(int argc, char** argv, char** env) {
VerilatedVcdC* tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
while (main_time <= 20) {
top->CLK = (main_time / dt_2) % 2;

View File

@ -12,9 +12,6 @@
#include "Vt_trace_public_sig_t.h"
#include "Vt_trace_public_sig_glbl.h"
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
unsigned long long main_time = 0;
double sc_time_stamp() { return (double)main_time; }
@ -28,7 +25,7 @@ int main(int argc, char** argv, char** env) {
VerilatedVcdC* tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
while (main_time <= 20) {
top->CLK = (main_time / dt_2) % 2;

View File

@ -10,9 +10,6 @@
#include VM_PREFIX_INCLUDE
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
unsigned long long main_time = 0;
double sc_time_stamp() { return ((double)main_time) / VL_TIME_MULTIPLIER; }
@ -28,7 +25,7 @@ int main(int argc, char** argv, char** env) {
top->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
top->clk = 0;

View File

@ -47,9 +47,6 @@ using namespace std;
unsigned int main_time = false;
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
//======================================================================
#define CHECK_RESULT_VH(got, exp) \
@ -257,7 +254,7 @@ int main(int argc, char** argv, char** env) {
VL_PRINTF("Enabling waves...\n");
VerilatedVcdC* tfp = new VerilatedVcdC;
topp->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
#endif
topp->eval();

View File

@ -47,9 +47,6 @@ using namespace std;
unsigned int main_time = false;
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
//======================================================================
#define CHECK_RESULT_VH(got, exp) \
@ -227,7 +224,7 @@ int main(int argc, char** argv, char** env) {
VL_PRINTF("Enabling waves...\n");
VerilatedVcdC* tfp = new VerilatedVcdC;
topp->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
#endif
topp->eval();

View File

@ -86,6 +86,7 @@ unsigned int callback_count_start_of_sim = 0;
#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp)
// We cannot replace those with VL_STRINGIFY, not available when PLI is build
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x

View File

@ -35,9 +35,6 @@
unsigned int main_time = false;
unsigned int callback_count = false;
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
//======================================================================
#define CHECK_RESULT_VH(got, exp) \
@ -163,7 +160,7 @@ int main(int argc, char** argv, char** env) {
VL_PRINTF("Enabling waves...\n");
VerilatedVcdC* tfp = new VerilatedVcdC;
topp->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
#endif
topp->eval();

View File

@ -90,6 +90,7 @@ unsigned int callback_count_strs_max = 500;
#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp)
// We cannot replace those with VL_STRINGIFY, not available when PLI is build
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x

View File

@ -85,9 +85,6 @@ unsigned int callback_count_start_of_sim = 0;
#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp)
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
//======================================================================
#ifdef IS_VPI
@ -166,12 +163,12 @@ int main(int argc, char** argv, char** env) {
VL_PRINTF("Enabling waves...\n");
VerilatedVcdC* tfp = new VerilatedVcdC;
topp->trace(tfp, 99);
tfp->open(STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
#endif
// Load and initialize the PLI application
{
const char* filenamep = STRINGIFY(TEST_OBJ_DIR) "/libvpi.so";
const char* filenamep = VL_STRINGIFY(TEST_OBJ_DIR) "/libvpi.so";
void* lib = dlopen(filenamep, RTLD_LAZY);
void* bootstrap = dlsym(lib, "vpi_compat_bootstrap");
if (!bootstrap) {