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.
This commit is contained in:
Martin Whitaker 2025-07-08 21:14:49 +01:00
parent fd7029a299
commit 7161dc0ab1
4 changed files with 31 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}
/*