From fa7234ff687a41fc5214b43ab672c4fe02f24e2c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 2 Mar 2024 09:02:21 -0500 Subject: [PATCH] Support 1800-2023 DPI headers, svGetTime/svgGetTimeUnit/svGetTimePrecision methods. --- Changes | 3 +- include/verilated_dpi.cpp | 30 ++++++++++++++ include/vltstd/sv_vpi_user.h | 19 ++++++++- include/vltstd/svdpi.h | 57 +++++++++++++++++++++++--- include/vltstd/vpi_user.h | 15 +++++-- test_regress/t/t_time_vpi_100s10ms.out | 4 ++ test_regress/t/t_time_vpi_10ms10ns.out | 4 ++ test_regress/t/t_time_vpi_1fs1fs.out | 4 ++ test_regress/t/t_time_vpi_1ms10ns.out | 4 ++ test_regress/t/t_time_vpi_1ns1ns.out | 4 ++ test_regress/t/t_time_vpi_1ps1fs.out | 4 ++ test_regress/t/t_time_vpi_1s10ns.out | 4 ++ test_regress/t/t_time_vpi_1us1ns.out | 4 ++ test_regress/t/t_time_vpi_c.cpp | 57 ++++++++++++++++++++++++-- 14 files changed, 196 insertions(+), 17 deletions(-) diff --git a/Changes b/Changes index cc192ba53..cc43a2354 100644 --- a/Changes +++ b/Changes @@ -14,11 +14,10 @@ Verilator 5.023 devel **Major:** * Support 1800-2023 keywords. - +* Support 1800-2023 DPI headers, svGetTime/svgGetTimeUnit/svGetTimePrecision methods. **Minor:** -* Add warning on 'TOP'-named modules (#4935). [Yanglin Xun] * Fix invalid cast on string structure creation (#4921). [esynr3z] diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index 86e2a20a3..76be56b5e 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -770,6 +770,36 @@ int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) { return true; } +//====================================================================== +// Time + +int svGetTime(const svScope scope, svTimeVal* time) { + if (VL_UNLIKELY(!time)) return -1; + const QData qtime = VL_TIME_Q(); + VlWide<2> itime; + VL_SET_WQ(itime, qtime); + time->low = itime[0]; + time->high = itime[1]; + return 0; +} + +int svGetTimeUnit(const svScope scope, int32_t* time_unit) { + if (VL_UNLIKELY(!time_unit)) return -1; + const VerilatedScope* const vscopep = reinterpret_cast(scope); + if (!vscopep) { // Null asks for global, not unlikely + *time_unit = Verilated::threadContextp()->timeunit(); + } else { + *time_unit = vscopep->timeunit(); + } + return 0; +} + +int svGetTimePrecision(const svScope scope, int32_t* time_precision) { + if (VL_UNLIKELY(!time_precision)) return -1; + *time_precision = Verilated::threadContextp()->timeprecision(); + return 0; +} + //====================================================================== // Disables diff --git a/include/vltstd/sv_vpi_user.h b/include/vltstd/sv_vpi_user.h index 56aaa24f5..fb8039c59 100644 --- a/include/vltstd/sv_vpi_user.h +++ b/include/vltstd/sv_vpi_user.h @@ -150,10 +150,21 @@ extern "C" { #define vpiIntegerNet 681 #define vpiLogicNet vpiNet #define vpiTimeNet 682 +#define vpiUnionNet 525 +#define vpiShortRealNet 526 +#define vpiRealNet 527 +#define vpiByteNet 528 +#define vpiShortIntNet 529 +#define vpiIntNet 530 +#define vpiLongIntNet 531 +#define vpiBitNet 532 +#define vpiInterconnectNet 533 +#define vpiInterconnectArray 534 #define vpiStructNet 683 #define vpiBreak 684 #define vpiContinue 685 #define vpiPackedArrayNet 693 +#define vpiNettypeDecl 523 #define vpiConstraintExpr 747 #define vpiElseConst 748 #define vpiImplication 749 @@ -174,6 +185,8 @@ extern "C" { #define vpiBaseTypespec 703 #define vpiElemTypespec 704 +#define vpiNetTypedefAlias 705 + #define vpiInputSkew 706 #define vpiOutputSkew 707 #define vpiGlobalClocking 708 @@ -206,7 +219,8 @@ extern "C" { #define vpiMessages 735 #define vpiLoopVars 737 -#define vpiConcurrentAssertions 740 +#define vpiConcurrentAssertion 740 +#define vpiConcurrentAssertions vpiConcurrentAssertion #define vpiMatchItem 741 #define vpiMember 742 #define vpiElement 743 @@ -221,6 +235,7 @@ extern "C" { /**************************************************************************/ /************************ generic object properties ***********************/ /**************************************************************************/ + #define vpiTop 600 #define vpiUnit 602 @@ -255,7 +270,6 @@ extern "C" { #define vpiModportPort 2 /* vpiPort is also a port type. It is defined in vpi_user.h */ - #define vpiConstantVariable 612 #define vpiStructUnionMember 615 @@ -407,6 +421,7 @@ extern "C" { /***************************** structure *****************************/ /**************************** CALLBACK REASONS ****************************/ +#define vpiMethodFuncCall 648 #define cbStartOfThread 600 /* callback on thread creation */ #define cbEndOfThread 601 /* callback on thread termination */ #define cbEnterThread 602 /* callback on reentering thread */ diff --git a/include/vltstd/svdpi.h b/include/vltstd/svdpi.h index 6b560e2cf..4afe10043 100644 --- a/include/vltstd/svdpi.h +++ b/include/vltstd/svdpi.h @@ -7,7 +7,7 @@ * This file contains the constant definitions, structure definitions, * and routine declarations used by SystemVerilog DPI. * - * This file is from the SystemVerilog IEEE 1800-2017 Annex I. + * This file is from the SystemVerilog IEEE 1800-2023 Annex I. */ #ifndef INCLUDED_SVDPI @@ -111,6 +111,26 @@ typedef uint32_t svBitVecVal; ((N) == 32 ? (VALUE) : \ (((VALUE) & (1 << (N))) ? ((VALUE) | ~SV_MASK(N)) : ((VALUE) & SV_MASK(N)))) +#ifndef VPI_TIME +#define VPI_TIME +typedef struct t_vpi_time { + int32_t type; + uint32_t high, low; + double real; +} s_vpi_time, *p_vpi_time; + +#define vpiScaledRealTime 1 +#define vpiSimTime 2 +#define vpiSuppressTime 3 +#endif + +/* time value */ +typedef s_vpi_time svTimeVal; + +/* time value types */ +#define sv_scaled_real_time vpiScaledRealTime +#define sv_sim_time vpiSimTime + /* * Implementation-dependent representation. */ @@ -277,7 +297,7 @@ XXTERN svScope svGetScope( void ); /* * Set context for subsequent export function execution. - * This function must be called before calling an export function, unless + * This function shall be called before calling an export function, unless * the export function is called while executing an import function. In that * case the export function shall inherit the scope of the surrounding import * function. This is known as the "default scope". @@ -297,7 +317,7 @@ XXTERN svScope svGetScopeFromName(const char* scopeName); /* * Store an arbitrary user data pointer for later retrieval by svGetUserData() - * The userKey is generated by the user. It must be guaranteed by the user to + * The userKey is generated by the user. It needs to be guaranteed by the user to * be unique from all other userKey's for all unique data storage requirements * It is recommended that the address of static functions or variables in the * user's C code be used as the userKey. @@ -329,24 +349,49 @@ XXTERN void* svGetUserData(const svScope scope, void* userKey); * modified. Whether this information is available or not is implementation- * specific. Note that the string provided (if any) is owned by the SV * implementation and is valid only until the next call to any SV function. - * Applications must not modify this string or free it + * Applications shall not modify this string or free it. */ XXTERN int svGetCallerInfo(const char** fileName, int *lineNumber); /* * Returns 1 if the current execution thread is in the disabled state. - * Disable protocol must be adhered to if in the disabled state. + * Disable protocol shall be adhered to if in the disabled state. */ XXTERN int svIsDisabledState( void ); /* * Imported functions call this API function during disable processing to * acknowledge that they are correctly participating in the DPI disable protocol. - * This function must be called before returning from an imported function that is + * This function shall be called before returning from an imported function that is * in the disabled state. */ XXTERN void svAckDisabledState( void ); +/* Mantis 5713/D9 + * Retrieve the current simulation time, scaled to the time unit of the scope. +* If scope is NULL, then time is scaled to the simulation time unit. +* It is an error to call svGetTime() with an invalid svScope. +* This function returns -1 for all error cases, 0 upon success. +*/ +XXTERN int svGetTime(const svScope scope, svTimeVal* time); + +/* + * Retrieve the time unit for scope. + * If scope is NULL, then simulation time unit is retrieved. +* It is an error to call svGetTimeUnit() with an invalid svScope. +* This function returns -1 for all error cases, 0 upon success. +*/ +XXTERN int svGetTimeUnit(const svScope scope, int32_t* time_unit); + +/* + * Retrieve the time precision for scope. + * If scope is NULL, then simulation time unit is retrieved. +* It is an error to call svGetTimePrecision() with an invalid svScope. +* This function returns -1 for all error cases, 0 upon success. +*/ +XXTERN int svGetTimePrecision(const svScope scope, int32_t* time_precision); + + /* ********************************************************** * DEPRECATED PORTION OF FILE STARTS FROM HERE. diff --git a/include/vltstd/vpi_user.h b/include/vltstd/vpi_user.h index bc830c014..b3bc11e2e 100644 --- a/include/vltstd/vpi_user.h +++ b/include/vltstd/vpi_user.h @@ -1,7 +1,7 @@ /******************************************************************************* * vpi_user.h * - * IEEE Std 1800-2017 Programming Language Interface (PLI) + * IEEE Std 1800-2023 Programming Language Interface (PLI) * * This file contains the constant definitions, structure definitions, and * routine declarations used by the SystemVerilog Verification Procedural @@ -344,6 +344,9 @@ typedef PLI_UINT32 *vpiHandle; #define vpiSupply0 11 /* supply-0 net */ #define vpiNone 12 /* no default net type (1364-2001) */ #define vpiUwire 13 /* unresolved wire net (1364-2005) */ +#define vpiNettypeNet 14 /* user-defined nettype net */ +#define vpiNettypeNetSelect 15 /* user-defined nettype net subelement */ +#define vpiInterconnect 16 /* interconnect net */ #define vpiExplicitScalared 23 /* explicitly scalared (Boolean) */ #define vpiExplicitVectored 24 /* explicitly vectored (Boolean) */ @@ -573,6 +576,9 @@ typedef PLI_UINT32 *vpiHandle; /******************************* time structure *******************************/ +#ifndef VPI_TIME /* added in 1800-2023 */ +#define VPI_TIME + typedef struct t_vpi_time { PLI_INT32 type; /* [vpiScaledRealTime, vpiSimTime, @@ -587,6 +593,8 @@ typedef struct t_vpi_time #define vpiSimTime 2 #define vpiSuppressTime 3 +#endif + /****************************** delay structures ******************************/ typedef struct t_vpi_delay @@ -741,9 +749,8 @@ typedef struct t_vpi_arrayvalue typedef struct t_vpi_systf_data { PLI_INT32 type; /* vpiSysTask, vpiSysFunc */ - PLI_INT32 sysfunctype; /* vpiSysTask, vpi[Int,Real,Time,Sized, - SizedSigned]Func */ - PLI_BYTE8 *tfname; /* first character must be '$' */ + PLI_INT32 sysfunctype; /* vpi[Int,Real,Time,Sized,SizedSigned]Func */ + PLI_BYTE8 *tfname; /* first character has to be '$' */ PLI_INT32 (*calltf)(PLI_BYTE8 *); PLI_INT32 (*compiletf)(PLI_BYTE8 *); PLI_INT32 (*sizetf)(PLI_BYTE8 *); /* for sized function callbacks only */ diff --git a/test_regress/t/t_time_vpi_100s10ms.out b/test_regress/t/t_time_vpi_100s10ms.out index 8a0428fea..ca822c555 100644 --- a/test_regress/t/t_time_vpi_100s10ms.out +++ b/test_regress/t/t_time_vpi_100s10ms.out @@ -10,8 +10,12 @@ Time scale of t is 100s / 10ms acc%0t=1234567890123456789000000000000.000000ns acc%0d=12345678901234567890 [1000000000000000.000000ns] stime%0t=1000000000000000.000000ns stime%0d=10000 stime%0f=10000.000000 [1000000000000000.000000ns] rtime%0t=1000000000000000.000000ns rtime%0d=10000 rtime%0f=10000.000000 +global svGetTime = 0 0,100000000 +global svGetTimeUnit = 0 -2 svGetTmePrecision = 0 -2 global vpiSimTime = 0,100000000 vpiScaledRealTime = 1e+08 global vpiTimeUnit = -2 vpiTimePrecision = -2 +top.t svGetTime = 0 0,100000000 +top.t svGetTimeUnit = 0 2 svGetTmePrecision = 0 -2 top.t vpiSimTime = 0,100000000 vpiScaledRealTime = 10000 top.t vpiTimeUnit = 2 vpiTimePrecision = -2 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_10ms10ns.out b/test_regress/t/t_time_vpi_10ms10ns.out index b09a31d11..de44e88cd 100644 --- a/test_regress/t/t_time_vpi_10ms10ns.out +++ b/test_regress/t/t_time_vpi_10ms10ns.out @@ -10,8 +10,12 @@ Time scale of t is 10ms / 10ns acc%0t=123456789012345678900000000.000000ns acc%0d=12345678901234567890 [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 svGetTime = 0 0,60000000 +global svGetTimeUnit = 0 -2 svGetTmePrecision = 0 -8 global vpiSimTime = 0,60000000 vpiScaledRealTime = 6e+07 global vpiTimeUnit = -2 vpiTimePrecision = -8 +top.t svGetTime = 0 0,60000000 +top.t svGetTimeUnit = 0 -2 svGetTmePrecision = 0 -8 top.t vpiSimTime = 0,60000000 vpiScaledRealTime = 60 top.t vpiTimeUnit = -2 vpiTimePrecision = -8 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_1fs1fs.out b/test_regress/t/t_time_vpi_1fs1fs.out index a353d9cea..135c2d861 100644 --- a/test_regress/t/t_time_vpi_1fs1fs.out +++ b/test_regress/t/t_time_vpi_1fs1fs.out @@ -10,8 +10,12 @@ Time scale of t is 1fs / 1fs acc%0t=12345678901234.567890ns acc%0d=12345678901234567890 [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 svGetTime = 0 0,60 +global svGetTimeUnit = 0 -15 svGetTmePrecision = 0 -15 global vpiSimTime = 0,60 vpiScaledRealTime = 60 global vpiTimeUnit = -15 vpiTimePrecision = -15 +top.t svGetTime = 0 0,60 +top.t svGetTimeUnit = 0 -15 svGetTmePrecision = 0 -15 top.t vpiSimTime = 0,60 vpiScaledRealTime = 60 top.t vpiTimeUnit = -15 vpiTimePrecision = -15 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_1ms10ns.out b/test_regress/t/t_time_vpi_1ms10ns.out index 1276f8d4c..f7bf66576 100644 --- a/test_regress/t/t_time_vpi_1ms10ns.out +++ b/test_regress/t/t_time_vpi_1ms10ns.out @@ -10,8 +10,12 @@ Time scale of t is 1ms / 10ns acc%0t=12345678901234567890000000.000000ns acc%0d=12345678901234567890 [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 svGetTime = 0 0,6000000 +global svGetTimeUnit = 0 -3 svGetTmePrecision = 0 -8 global vpiSimTime = 0,6000000 vpiScaledRealTime = 6e+06 global vpiTimeUnit = -3 vpiTimePrecision = -8 +top.t svGetTime = 0 0,6000000 +top.t svGetTimeUnit = 0 -3 svGetTmePrecision = 0 -8 top.t vpiSimTime = 0,6000000 vpiScaledRealTime = 60 top.t vpiTimeUnit = -3 vpiTimePrecision = -8 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_1ns1ns.out b/test_regress/t/t_time_vpi_1ns1ns.out index b9e6d3ed1..c91300994 100644 --- a/test_regress/t/t_time_vpi_1ns1ns.out +++ b/test_regress/t/t_time_vpi_1ns1ns.out @@ -10,8 +10,12 @@ Time scale of t is 1ns / 1ns acc%0t=12345678901234567890.000000ns acc%0d=12345678901234567890 [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 svGetTime = 0 0,60 +global svGetTimeUnit = 0 -9 svGetTmePrecision = 0 -9 global vpiSimTime = 0,60 vpiScaledRealTime = 60 global vpiTimeUnit = -9 vpiTimePrecision = -9 +top.t svGetTime = 0 0,60 +top.t svGetTimeUnit = 0 -9 svGetTmePrecision = 0 -9 top.t vpiSimTime = 0,60 vpiScaledRealTime = 60 top.t vpiTimeUnit = -9 vpiTimePrecision = -9 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_1ps1fs.out b/test_regress/t/t_time_vpi_1ps1fs.out index 3a391485d..dd146d39a 100644 --- a/test_regress/t/t_time_vpi_1ps1fs.out +++ b/test_regress/t/t_time_vpi_1ps1fs.out @@ -10,8 +10,12 @@ Time scale of t is 1ps / 1fs acc%0t=12345678901234567.890000ns acc%0d=12345678901234567890 [0.060000ns] stime%0t=0.060000ns stime%0d=60 stime%0f=60.000000 [0.060000ns] rtime%0t=0.060000ns rtime%0d=60 rtime%0f=60.000000 +global svGetTime = 0 0,60000 +global svGetTimeUnit = 0 -12 svGetTmePrecision = 0 -15 global vpiSimTime = 0,60000 vpiScaledRealTime = 60000 global vpiTimeUnit = -12 vpiTimePrecision = -15 +top.t svGetTime = 0 0,60000 +top.t svGetTimeUnit = 0 -12 svGetTmePrecision = 0 -15 top.t vpiSimTime = 0,60000 vpiScaledRealTime = 60 top.t vpiTimeUnit = -12 vpiTimePrecision = -15 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_1s10ns.out b/test_regress/t/t_time_vpi_1s10ns.out index b950e9176..329f18892 100644 --- a/test_regress/t/t_time_vpi_1s10ns.out +++ b/test_regress/t/t_time_vpi_1s10ns.out @@ -10,8 +10,12 @@ Time scale of t is 1s / 10ns acc%0t=12345678901234567890000000000.000000ns acc%0d=12345678901234567890 [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 svGetTime = 0 1,1705032704 +global svGetTimeUnit = 0 0 svGetTmePrecision = 0 -8 global vpiSimTime = 1,1705032704 vpiScaledRealTime = 6e+09 global vpiTimeUnit = 0 vpiTimePrecision = -8 +top.t svGetTime = 0 1,1705032704 +top.t svGetTimeUnit = 0 0 svGetTmePrecision = 0 -8 top.t vpiSimTime = 1,1705032704 vpiScaledRealTime = 60 top.t vpiTimeUnit = 0 vpiTimePrecision = -8 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_1us1ns.out b/test_regress/t/t_time_vpi_1us1ns.out index 59d7e4ea8..0c7330d8a 100644 --- a/test_regress/t/t_time_vpi_1us1ns.out +++ b/test_regress/t/t_time_vpi_1us1ns.out @@ -10,8 +10,12 @@ Time scale of t is 1us / 1ns acc%0t=12345678901234567890000.000000ns acc%0d=12345678901234567890 [60000.000000ns] stime%0t=60000.000000ns stime%0d=60 stime%0f=60.000000 [60000.000000ns] rtime%0t=60000.000000ns rtime%0d=60 rtime%0f=60.000000 +global svGetTime = 0 0,60000 +global svGetTimeUnit = 0 -6 svGetTmePrecision = 0 -9 global vpiSimTime = 0,60000 vpiScaledRealTime = 60000 global vpiTimeUnit = -6 vpiTimePrecision = -9 +top.t svGetTime = 0 0,60000 +top.t svGetTimeUnit = 0 -6 svGetTmePrecision = 0 -9 top.t vpiSimTime = 0,60000 vpiScaledRealTime = 60 top.t vpiTimeUnit = -6 vpiTimePrecision = -9 *-* All Finished *-* diff --git a/test_regress/t/t_time_vpi_c.cpp b/test_regress/t/t_time_vpi_c.cpp index 9b520afe4..db53b192f 100644 --- a/test_regress/t/t_time_vpi_c.cpp +++ b/test_regress/t/t_time_vpi_c.cpp @@ -13,10 +13,14 @@ #include "vpi_user.h" #include +#include // These require the above. Comment prevents clang-format moving them +#include "TestCheck.h" #include "TestVpi.h" +int errors = 0; + //====================================================================== #define NEED_EXTERNS @@ -29,7 +33,45 @@ extern void dpii_check(); //====================================================================== -void show(vpiHandle obj) { +void dpi_bad() { + { + int res = svGetTime(0, nullptr); + TEST_CHECK_EQ(res, -1); + } + { + int res = svGetTimeUnit(0, nullptr); + TEST_CHECK_EQ(res, -1); + } + { + int res = svGetTimePrecision(0, nullptr); + TEST_CHECK_EQ(res, -1); + } +} + +void dpi_show(svScope obj) { + const char* namep; + if (obj) { + namep = svGetNameFromScope(obj); + } else { + namep = "global"; + } + + svTimeVal t; // aka s_vpi_time + t.type = vpiSimTime; + int gres = svGetTime(obj, &t); + vpi_printf(const_cast("%s svGetTime = %d %d,%d\n"), namep, gres, (int)t.high, + (int)t.low); + + // These will both print the precision, because the 0 asks for global scope + int32_t u = 99; + int ures = svGetTimeUnit(obj, &u); + int32_t p = 99; + int pres = svGetTimePrecision(obj, &p); + vpi_printf(const_cast("%s svGetTimeUnit = %d %d"), namep, ures, u); + vpi_printf(const_cast(" svGetTmePrecision = %d %d\n"), pres, p); +} + +void vpi_show(vpiHandle obj) { const char* namep; if (obj) { namep = vpi_get_str(vpiName, obj); @@ -55,12 +97,21 @@ void show(vpiHandle obj) { } void dpii_check() { - show(0); + dpi_bad(); + dpi_show(0); + vpi_show(0); + + svScope smod = svGetScopeFromName("top.t"); + if (!smod) { + vpi_printf(const_cast("-- Cannot svGetScopeFromName\n")); + } else { + dpi_show(smod); + } TestVpiHandle mod = vpi_handle_by_name((PLI_BYTE8*)"top.t", NULL); if (!mod) { vpi_printf(const_cast("-- Cannot vpi_find module\n")); } else { - show(mod); + vpi_show(mod); } }