From 3ac6745658253bb45a74a0827b0b9260bda69027 Mon Sep 17 00:00:00 2001 From: Stefan Wallentowitz Date: Fri, 13 Dec 2019 19:11:37 -0500 Subject: [PATCH] Add vpiTimeUnit and allow to specify time as string, bug1636. Signed-off-by: Wilson Snyder --- Changes | 2 + include/verilated.cpp | 24 ++++++++++++ include/verilated.h | 15 +++++++- include/verilated_vpi.cpp | 3 ++ include/verilatedos.h | 6 +++ test_regress/t/t_order_multidriven.cpp | 5 +-- test_regress/t/t_scope_map.cpp | 5 +-- test_regress/t/t_timescale.cpp | 53 ++++++++++++++++++++++++++ test_regress/t/t_timescale.pl | 23 +++++++++++ test_regress/t/t_timescale.v | 3 ++ test_regress/t/t_trace_cat.cpp | 5 +-- test_regress/t/t_trace_public_func.cpp | 5 +-- test_regress/t/t_trace_public_sig.cpp | 5 +-- test_regress/t/t_trace_timescale.cpp | 5 +-- test_regress/t/t_vpi_get.cpp | 5 +-- test_regress/t/t_vpi_memory.cpp | 5 +-- test_regress/t/t_vpi_time_cb.cpp | 1 + test_regress/t/t_vpi_unimpl.cpp | 5 +-- test_regress/t/t_vpi_var.cpp | 1 + test_regress/t/t_vpi_zero_time_cb.cpp | 7 +--- 20 files changed, 141 insertions(+), 42 deletions(-) create mode 100644 test_regress/t/t_timescale.cpp create mode 100755 test_regress/t/t_timescale.pl create mode 100644 test_regress/t/t_timescale.v diff --git a/Changes b/Changes index fe5ad5f31..ed764aacf 100644 --- a/Changes +++ b/Changes @@ -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] diff --git a/include/verilated.cpp b/include/verilated.cpp index d0bc7de08..8a53a49a9 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1837,6 +1837,30 @@ IData VL_ATOI_N(const std::string& str, int base) VL_PURE { return static_cast(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 diff --git a/include/verilated.h b/include/verilated.h index 7634ef713..724ca5215 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -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 diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 439b9d555..28fc11458 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -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; diff --git a/include/verilatedos.h b/include/verilatedos.h index e60ea5754..d874677ba 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -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 diff --git a/test_regress/t/t_order_multidriven.cpp b/test_regress/t/t_order_multidriven.cpp index b08e4d14a..7e4f76744 100644 --- a/test_regress/t/t_order_multidriven.cpp +++ b/test_regress/t/t_order_multidriven.cpp @@ -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; diff --git a/test_regress/t/t_scope_map.cpp b/test_regress/t/t_scope_map.cpp index 3e15a7a02..4179e9c7c 100644 --- a/test_regress/t/t_scope_map.cpp +++ b/test_regress/t/t_scope_map.cpp @@ -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(); diff --git a/test_regress/t/t_timescale.cpp b/test_regress/t/t_timescale.cpp new file mode 100644 index 000000000..befd0843a --- /dev/null +++ b/test_regress/t/t_timescale.cpp @@ -0,0 +1,53 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- + +#include + +#include VM_PREFIX_INCLUDE + +unsigned long long main_time = 0; +double sc_time_stamp() { return (double)main_time; } + +#include +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; +} diff --git a/test_regress/t/t_timescale.pl b/test_regress/t/t_timescale.pl new file mode 100755 index 000000000..cd165daa1 --- /dev/null +++ b/test_regress/t/t_timescale.pl @@ -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; diff --git a/test_regress/t/t_timescale.v b/test_regress/t/t_timescale.v new file mode 100644 index 000000000..396bc9b35 --- /dev/null +++ b/test_regress/t/t_timescale.v @@ -0,0 +1,3 @@ +module t; + +endmodule diff --git a/test_regress/t/t_trace_cat.cpp b/test_regress/t/t_trace_cat.cpp index ab001d474..d919121d6 100644 --- a/test_regress/t/t_trace_cat.cpp +++ b/test_regress/t/t_trace_cat.cpp @@ -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; } diff --git a/test_regress/t/t_trace_public_func.cpp b/test_regress/t/t_trace_public_func.cpp index 21498ceec..cf5606ed5 100644 --- a/test_regress/t/t_trace_public_func.cpp +++ b/test_regress/t/t_trace_public_func.cpp @@ -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; diff --git a/test_regress/t/t_trace_public_sig.cpp b/test_regress/t/t_trace_public_sig.cpp index 56b99eace..457c76560 100644 --- a/test_regress/t/t_trace_public_sig.cpp +++ b/test_regress/t/t_trace_public_sig.cpp @@ -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; diff --git a/test_regress/t/t_trace_timescale.cpp b/test_regress/t/t_trace_timescale.cpp index 76ea0c5e1..8dead4e12 100644 --- a/test_regress/t/t_trace_timescale.cpp +++ b/test_regress/t/t_trace_timescale.cpp @@ -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; diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp index 6f09bdd4b..d44c6f35a 100644 --- a/test_regress/t/t_vpi_get.cpp +++ b/test_regress/t/t_vpi_get.cpp @@ -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(); diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp index 753cc795c..6bab9ae2e 100644 --- a/test_regress/t/t_vpi_memory.cpp +++ b/test_regress/t/t_vpi_memory.cpp @@ -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(); diff --git a/test_regress/t/t_vpi_time_cb.cpp b/test_regress/t/t_vpi_time_cb.cpp index f897225d0..4d277adb7 100644 --- a/test_regress/t/t_vpi_time_cb.cpp +++ b/test_regress/t/t_vpi_time_cb.cpp @@ -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 diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp index 49e28c548..987e77300 100644 --- a/test_regress/t/t_vpi_unimpl.cpp +++ b/test_regress/t/t_vpi_unimpl.cpp @@ -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(); diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index 933f8e9b7..91ba19008 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -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 diff --git a/test_regress/t/t_vpi_zero_time_cb.cpp b/test_regress/t/t_vpi_zero_time_cb.cpp index 2de6fcbd4..610d7f5cb 100644 --- a/test_regress/t/t_vpi_zero_time_cb.cpp +++ b/test_regress/t/t_vpi_zero_time_cb.cpp @@ -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) {