From ebf2dc16853bec99073968b97cee772980fe0ff8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 25 Jan 2026 17:48:22 -0800 Subject: [PATCH] Add basic support for vpi_get64() to return the nexus pointer --- vpi/sys_fst.c | 4 ++-- vpi/sys_lxt.c | 6 +++--- vpi/sys_lxt2.c | 4 ++-- vpi/sys_vcd.c | 6 +++--- vpi/vcd_priv.h | 6 +++--- vpi/vcd_priv2.cc | 10 +++++----- vpi_modules.cc | 4 +++- vpi_user.h | 4 +++- vvp/cppcheck.sup | 38 +++++++++++++++++++------------------- vvp/vpi_priv.cc | 26 +++++++++++++++++++++++++- vvp/vpi_priv.h | 2 ++ vvp/vpi_signal.cc | 28 +++++++++++++++++++++++----- 12 files changed, 93 insertions(+), 45 deletions(-) diff --git a/vpi/sys_fst.c b/vpi/sys_fst.c index 9aef37c3d..6119e7036 100644 --- a/vpi/sys_fst.c +++ b/vpi/sys_fst.c @@ -442,7 +442,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) char *escname; const char *ident; fstHandle new_ident; - int nexus_id; + int64_t nexus_id; unsigned size; PLI_INT32 item_type; @@ -557,7 +557,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) } else escname = strdup(name); /* Some signals can have an alias so handle that. */ - nexus_id = vpi_get(_vpiNexusId, item); + nexus_id = vpi_get64(_vpiNexusId, item); ident = 0; if (nexus_id) ident = find_nexus_ident(nexus_id); diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index 75e5665d2..e985d5a6c 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -523,7 +523,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) const char* name; const char* ident; - int nexus_id; + int64_t nexus_id; switch (vpi_get(vpiType, item)) { @@ -558,7 +558,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); - nexus_id = vpi_get(_vpiNexusId, item); + nexus_id = vpi_get64(_vpiNexusId, item); if (nexus_id) { ident = find_nexus_ident(nexus_id); } else { diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index b342d5d9a..b001508f0 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -582,7 +582,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) const char* name; const char* ident; - int nexus_id; + int64_t nexus_id; switch (vpi_get(vpiType, item)) { @@ -617,7 +617,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); - nexus_id = vpi_get(_vpiNexusId, item); + nexus_id = vpi_get64(_vpiNexusId, item); if (nexus_id) { ident = find_nexus_ident(nexus_id); } else { diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 3eece52a0..968f56b42 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -510,7 +510,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) const char *fullname; const char *prefix; const char *ident; - int nexus_id; + int64_t nexus_id; unsigned size; PLI_INT32 item_type; @@ -622,7 +622,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) prefix = is_escaped_id(name) ? "\\" : ""; /* Some signals can have an alias so handle that. */ - nexus_id = vpi_get(_vpiNexusId, item); + nexus_id = vpi_get64(_vpiNexusId, item); ident = 0; if (nexus_id) ident = find_nexus_ident(nexus_id); diff --git a/vpi/vcd_priv.h b/vpi/vcd_priv.h index e2e9723eb..d07c4b1f4 100644 --- a/vpi/vcd_priv.h +++ b/vpi/vcd_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_vcd_priv_H #define IVL_vcd_priv_H /* - * Copyright (c) 2003-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -52,8 +52,8 @@ EXTERN void vcd_names_delete(struct vcd_names_list_s*tab); /* * Keep a map of nexus ident's to help with alias detection. */ -EXTERN const char*find_nexus_ident(int nex); -EXTERN void set_nexus_ident(int nex, const char *id); +EXTERN const char*find_nexus_ident(int64_t nex); +EXTERN void set_nexus_ident(int64_t nex, const char *id); EXTERN void nexus_ident_delete(void); diff --git a/vpi/vcd_priv2.cc b/vpi/vcd_priv2.cc index 80e122b0d..7c4d33008 100644 --- a/vpi/vcd_priv2.cc +++ b/vpi/vcd_priv2.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2010-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -44,18 +44,18 @@ The _vpiNexusId is a private (int) property of IVL simulators. */ -static std::map nexus_ident_map; +static std::map nexus_ident_map; -extern "C" const char*find_nexus_ident(int nex) +extern "C" const char*find_nexus_ident(int64_t nex) { - std::map::const_iterator cur = nexus_ident_map.find(nex); + std::map::const_iterator cur = nexus_ident_map.find(nex); if (cur == nexus_ident_map.end()) return 0; else return cur->second; } -extern "C" void set_nexus_ident(int nex, const char*id) +extern "C" void set_nexus_ident(int64_t nex, const char*id) { nexus_ident_map[nex] = id; } diff --git a/vpi_modules.cc b/vpi_modules.cc index 29533c4a3..ec62af550 100644 --- a/vpi_modules.cc +++ b/vpi_modules.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2025 Martin Whitaker (icarus@martin-whitaker.me.uk) + * Copyright (c) 2019-2026 Martin Whitaker (icarus@martin-whitaker.me.uk) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -57,6 +57,7 @@ vpiHandle vpi_scan(vpiHandle) { return 0; } // for processing properties PLI_INT32 vpi_get(int, vpiHandle) { return 0; } +PLI_INT64 vpi_get64(int, vpiHandle) { return 0; } char* vpi_get_str(PLI_INT32, vpiHandle) { return 0; } // delay processing @@ -202,6 +203,7 @@ vpip_routines_s vpi_routines = { .iterate = vpi_iterate, .scan = vpi_scan, .get = vpi_get, + .get64 = vpi_get64, .get_str = vpi_get_str, .get_delays = vpi_get_delays, .put_delays = vpi_put_delays, diff --git a/vpi_user.h b/vpi_user.h index bad846192..c347fe15e 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -1,7 +1,7 @@ #ifndef VPI_USER_H #define VPI_USER_H /* - * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -543,6 +543,7 @@ extern vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle ref1, vpiHandle ref extern void vpi_get_time(vpiHandle obj, s_vpi_time*t); extern PLI_INT32 vpi_get(int property, vpiHandle ref); +extern PLI_INT64 vpi_get64(int property, vpiHandle ref); extern char *vpi_get_str(PLI_INT32 property, vpiHandle ref); extern void vpi_get_value(vpiHandle expr, p_vpi_value value); @@ -709,6 +710,7 @@ typedef struct { vpiHandle (*iterate)(PLI_INT32, vpiHandle); vpiHandle (*scan)(vpiHandle); PLI_INT32 (*get)(int, vpiHandle); + PLI_INT64 (*get64)(int, vpiHandle); char* (*get_str)(PLI_INT32, vpiHandle); void (*get_delays)(vpiHandle, p_vpi_delay); void (*put_delays)(vpiHandle, p_vpi_delay); diff --git a/vvp/cppcheck.sup b/vvp/cppcheck.sup index bbe4c3269..75a5954d4 100644 --- a/vvp/cppcheck.sup +++ b/vvp/cppcheck.sup @@ -21,7 +21,7 @@ invalidPointerCast:class_type.cc:332 invalidPointerCast:class_type.cc:338 invalidPointerCast:class_type.cc:339 cstyleCast:ufunc.cc:80 -cstyleCast:vpi_priv.cc:226 +cstyleCast:vpi_priv.cc:229 cstyleCast:vpi_scope.cc:615 // Skip the sscanf() field width limit warning @@ -29,12 +29,12 @@ invalidscanf:compile.cc:597 invalidscanf:compile.cc:609 // By convention we put statics at the top scope. -variableScope:vpi_priv.cc:623 +variableScope:vpi_priv.cc:647 // Changing this breaks the compile constParameterPointer:vthread.cc:423 useInitializationList:delay.cc:513 -constParameterPointer:vpi_priv.cc:1434 +constParameterPointer:vpi_priv.cc:1458 // Operator new/delete are static so cannot override duplInheritedMember:vvp_net.h:1476 @@ -79,27 +79,27 @@ duplicateValueTernary:class_type.cc:268 // cppcheck is wrong this can be true or false knownConditionTrueFalse:vthread.cc:2986 -knownConditionTrueFalse:vpi_priv.cc:657 -knownConditionTrueFalse:vpi_priv.cc:1955 +knownConditionTrueFalse:vpi_priv.cc:681 +knownConditionTrueFalse:vpi_priv.cc:1979 // cppcheck is wrong this is already const constParameterPointer:vpi_tasks.cc:259 // For some cases this expression can be different -duplicateExpression:vpi_signal.cc:1189 +duplicateExpression:vpi_signal.cc:1207 // cppcheck does not relize this is deleted[] in the called routine leakNoVarFunctionCall:compile.cc:452 // Yes, these are not currently initialized in the constructor // All are added after __vpiSysTaskCall is built -uninitMemberVar:vpi_priv.h:944 +uninitMemberVar:vpi_priv.h:946 // All are added after __vpiSignal is built -uninitMemberVar:vpi_priv.h:392 +uninitMemberVar:vpi_priv.h:394 // run_run_ptr is added after the event is built uninitMemberVar:delay.h:79 // The array values are added after it is allocated -noConstructor:vpi_priv.h:778 +noConstructor:vpi_priv.h:780 // The enum values are added after this is built uninitMemberVar:enum_type.cc:54 // The names for the enum values are added after allocation @@ -107,10 +107,10 @@ uninitMemberVar:enum_type.cc:100 // The thread values get assigned after being created uninitMemberVar:vthread.cc:316 // The mod path has the values added after creation -uninitMemberVar:delay.cc:1005 -uninitMemberVar:delay.cc:1045 +uninitMemberVar:delay.cc:1006 +uninitMemberVar:delay.cc:1046 // The intermod path has the values added after creation -uninitMemberVar:delay.cc:1395 +uninitMemberVar:delay.cc:1396 // The island values are set after creation uninitDerivedMemberVar:island_tran.cc:60 // The cb_data is set after creation @@ -124,24 +124,24 @@ uninitMemberVar:vpi_scope.cc:353 // The real var values are set after creation uninitMemberVar:vpi_real.cc:158 // The PV values are set after creation -uninitMemberVar:vpi_signal.cc:1577 +uninitMemberVar:vpi_signal.cc:1595 // The info/is_user_defn are added ater creation uninitMemberVar:vpi_tasks.cc:41 // All the values are set after creation using the default constructor noConstructor:vpi_tasks.cc:158 // We check memory usage using valgrind. -unsafeClassCanLeak:vpi_priv.h:750 +unsafeClassCanLeak:vpi_priv.h:752 unsafeClassCanLeak:permaheap.h:47 // Index calculation -thisSubtraction:vpi_priv.h:430 +thisSubtraction:vpi_priv.h:432 thisSubtraction:array_common.h:91 // The interface is from the standard. -constParameterCallback:vpi_priv.cc:1110 +constParameterCallback:vpi_priv.cc:1134 +constParameterPointer:vpi_priv.cc:1134 constParameterPointer:vpi_mcd.cc:158 -constParameterPointer:vpi_priv.cc:1110 // cppcheck is missing the code adds a \0 at the previous location. knownConditionTrueFalse:vpi_modules.cc:118 @@ -220,13 +220,13 @@ unusedFunction:lib_main.cc:76 // alias_word() unusedFunction:array.cc:848 // intermodpath_delete() -unusedFunction:delay.cc:1462 +unusedFunction:delay.cc:1463 // count_force4_pool() unusedFunction:schedule.cc:404 // call_scope() unusedFunction:ufunc.h:62 // get_bit() -unusedFunction:vpi_priv.h:477 +unusedFunction:vpi_priv.h:479 // copy_bits() unusedFunction:vvp_net.cc:615 // mov() diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 4630c531f..69fefe386 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2026 Stephen Williams (steve@icarus.com) * Copyright (c) 2023 Leo Moser (leo.moser@pm.me) * * This source code is free software; you can redistribute it @@ -67,6 +67,9 @@ __vpiHandle::~__vpiHandle() int __vpiHandle::vpi_get(int) { return vpiUndefined; } +int64_t __vpiHandle::vpi_get64(int code) +{ return (code == _vpiNexusId) ? 0 : vpiUndefined; } + char* __vpiHandle::vpi_get_str(int) { return 0; } @@ -331,6 +334,8 @@ static const char* vpi_property_str(PLI_INT32 code) return "vpiTimePrecision"; case vpiSize: return "vpiSize"; + case _vpiNexusId: + return "_vpiNexusId"; default: snprintf(buf, sizeof(buf), "%d", (int)code); } @@ -449,6 +454,25 @@ PLI_INT32 vpi_get(int property, vpiHandle ref) return res; } +PLI_INT64 vpi_get64(int property, vpiHandle ref) +{ + // For now we only support getting the nexus id. + if ((ref == 0) || (property != _vpiNexusId)) { + fprintf(vpi_trace, "vpi_get64(%s, %p) is not currently supported.\n", + vpi_property_str(property), ref); + return vpiUndefined; + } + + int64_t res = ref->vpi_get64(property); + + if (vpi_trace) { + fprintf(vpi_trace, "vpi_get64(%s, %p) --> %" PRId64 "\n", + vpi_property_str(property), ref, res); + } + + return res; +} + char* vpi_get_str(PLI_INT32 property, vpiHandle ref) { /* We don't care what the ref is there is only one delay selection. */ diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 1cf234ada..3b253c999 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -124,6 +124,7 @@ class __vpiHandle { virtual int get_type_code(void) const =0; virtual int vpi_get(int code); + virtual int64_t vpi_get64(int code); virtual char* vpi_get_str(int code); virtual void vpi_get_value(p_vpi_value val); @@ -352,6 +353,7 @@ extern void vpip_make_root_iterator(class __vpiHandle**&table, */ struct __vpiSignal : public __vpiHandle { int vpi_get(int code) override; + int64_t vpi_get64(int code) override; char* vpi_get_str(int code) override; void vpi_get_value(p_vpi_value val) override; vpiHandle vpi_put_value(p_vpi_value val, int flags) override; diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 350eff834..aeb41f424 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -593,15 +593,30 @@ static int signal_get(int code, vpiHandle ref) return _vpiNoThr; #endif + default: + fprintf(stderr, "VPI error: unknown signal_get property %d.\n", + code); + return vpiUndefined; + } +} + +/* + * implement vpi_get64 for vpiReg objects. + */ +static int64_t signal_get64(int code, vpiHandle ref) +{ + struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref); + assert(rfp); + + switch (code) { // This private property must return zero when undefined. case _vpiNexusId: if (rfp->msb.get_value() == rfp->lsb.get_value()) - return (int) (uintptr_t) rfp->node; - else - return 0; + return reinterpret_cast(rfp->node); + return 0; default: - fprintf(stderr, "VPI error: unknown signal_get property %d.\n", + fprintf(stderr, "VPI error: unknown signal_get64 property %d.\n", code); return vpiUndefined; } @@ -1050,6 +1065,9 @@ vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid) int __vpiSignal::vpi_get(int code) { return signal_get(code, this); } +int64_t __vpiSignal::vpi_get64(int code) +{ return signal_get64(code, this); } + char* __vpiSignal::vpi_get_str(int code) { return signal_get_str(code, this); }