From 7161dc0ab14b664215e197bbad232e18f8054356 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 8 Jul 2025 21:14:49 +0100 Subject: [PATCH] Fix return type of vpi_control() and vpi_sim_control() (issue #1208). These were implemented as returning nothing (void), and passing an invalid operation value would trigger an assertion failure. The IEEE standards define them as returning 1 on success and 0 on failure. vpi_sim_control() is the name used in Verilog-AMS. Strictly speaking it should return a bool, but to avoid polluting the namespace by including stdbool.h, we return a PLI_INT32. As C is a weakly typed language, this should make no practical difference. --- vpi/libvpi.c | 12 +++++++----- vpi_modules.cc | 8 ++++---- vpi_user.h | 12 +++++++----- vvp/vpi_priv.cc | 23 +++++++++++++---------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/vpi/libvpi.c b/vpi/libvpi.c index cf4c2ee72..af1221116 100644 --- a/vpi/libvpi.c +++ b/vpi/libvpi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Martin Whitaker (icarus@martin-whitaker.me.uk) + * Copyright (c) 2019-2025 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 @@ -232,21 +232,23 @@ PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info info) // control routines -void vpi_control(PLI_INT32 operation, ...) +PLI_INT32 vpi_control(PLI_INT32 operation, ...) { va_list ap; va_start(ap, operation); assert(vpip_routines); - vpip_routines->vcontrol(operation, ap); + PLI_INT32 r = vpip_routines->vcontrol(operation, ap); va_end(ap); + return r; } -void vpi_sim_control(PLI_INT32 operation, ...) +PLI_INT32 vpi_sim_control(PLI_INT32 operation, ...) { va_list ap; va_start(ap, operation); assert(vpip_routines); - vpip_routines->vcontrol(operation, ap); + PLI_INT32 r = vpip_routines->vcontrol(operation, ap); va_end(ap); + return r; } // proposed standard extensions diff --git a/vpi_modules.cc b/vpi_modules.cc index fad45600d..12ec42c5c 100644 --- a/vpi_modules.cc +++ b/vpi_modules.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2024 Martin Whitaker (icarus@martin-whitaker.me.uk) + * Copyright (c) 2019-2025 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 @@ -108,8 +108,8 @@ PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info info) // control routines -void vpi_control(PLI_INT32, ...) { } -void vpi_sim_control(PLI_INT32, ...) { } +PLI_INT32 vpi_control(PLI_INT32, ...) { return 0; } +PLI_INT32 vpi_sim_control(PLI_INT32, ...) { return 0; } // proposed standard extensions @@ -128,7 +128,7 @@ void vpip_format_strength(char*, s_vpi_value*, unsigned) { } void vpip_make_systf_system_defined(vpiHandle) { } void vpip_mcd_rawwrite(PLI_UINT32, const char*, size_t) { } void vpip_set_return_value(int) { } -void vpi_vcontrol(PLI_INT32, va_list) { } +PLI_INT32 vpi_vcontrol(PLI_INT32, va_list) { return 0; } /* When a module registers a system function, extract and save the return diff --git a/vpi_user.h b/vpi_user.h index 40bf4879d..be869a784 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -1,7 +1,7 @@ #ifndef VPI_USER_H #define VPI_USER_H /* - * Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2025 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 @@ -520,7 +520,7 @@ extern PLI_INT32 vpi_remove_cb(vpiHandle ref); * vpiReset - * vpiSetInteractiveScope - */ -extern void vpi_control(PLI_INT32 operation, ...); +extern PLI_INT32 vpi_control(PLI_INT32 operation, ...); /************* vpi_control() constants (added with 1364-2000) *************/ #define vpiStop 66 /* execute simulator's $stop */ #define vpiFinish 67 /* execute simulator's $finish */ @@ -529,8 +529,10 @@ extern void vpi_control(PLI_INT32 operation, ...); #define __ivl_legacy_vpiStop 1 #define __ivl_legacy_vpiFinish 2 -/* vpi_sim_control is the incorrect name for vpi_control. */ -extern void vpi_sim_control(PLI_INT32 operation, ...); +/* Verilog-AMS still uses the original name of vpi_sim_control. It defines + the return type to be bool, but to avoid polluting the namespace, we + return a PLI_INT32. */ +extern PLI_INT32 vpi_sim_control(PLI_INT32 operation, ...); extern vpiHandle vpi_handle(PLI_INT32 type, vpiHandle ref); extern vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle ref); @@ -727,7 +729,7 @@ typedef struct { PLI_INT32 (*free_object)(vpiHandle); PLI_INT32 (*release_handle)(vpiHandle); PLI_INT32 (*get_vlog_info)(p_vpi_vlog_info info) ; - void (*vcontrol)(PLI_INT32, va_list); + PLI_INT32 (*vcontrol)(PLI_INT32, va_list); PLI_INT32 (*fopen)(const char*, const char*); FILE* (*get_file)(PLI_INT32); s_vpi_vecval(*calc_clog2)(vpiHandle); diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 27fe86210..577b8b2a4 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2025 Stephen Williams (steve@icarus.com) * Copyright (c) 2023 Leo Moser (leo.moser@pm.me) * * This source code is free software; you can redistribute it @@ -1877,43 +1877,46 @@ extern "C" PLI_INT32 vpi_flush(void) } -extern "C" void vpi_sim_vcontrol(int operation, va_list ap) +extern "C" PLI_INT32 vpi_sim_vcontrol(int operation, va_list ap) { long diag_msg; switch (operation) { case vpiFinish: case __ivl_legacy_vpiFinish: - diag_msg = va_arg(ap, long); + diag_msg = va_arg(ap, PLI_INT32); schedule_finish(diag_msg); break; case vpiStop: case __ivl_legacy_vpiStop: - diag_msg = va_arg(ap, long); + diag_msg = va_arg(ap, PLI_INT32); schedule_stop(diag_msg); break; default: - fprintf(stderr, "Unsupported operation %d.\n", operation); - assert(0); + fprintf(stderr, "Unsupported VPI control operation %d.\n", operation); + return 0; } + return 1; } -extern "C" void vpi_sim_control(PLI_INT32 operation, ...) +extern "C" PLI_INT32 vpi_sim_control(PLI_INT32 operation, ...) { va_list ap; va_start(ap, operation); - vpi_sim_vcontrol(operation, ap); + int r = vpi_sim_vcontrol(operation, ap); va_end(ap); + return r; } -extern "C" void vpi_control(PLI_INT32 operation, ...) +extern "C" PLI_INT32 vpi_control(PLI_INT32 operation, ...) { va_list ap; va_start(ap, operation); - vpi_sim_vcontrol(operation, ap); + int r = vpi_sim_vcontrol(operation, ap); va_end(ap); + return r; } /*