Factor out the common code for checking if a FD/MCD is valid

This commit is contained in:
Cary R 2020-05-16 18:02:46 -07:00
parent cf44f05cd3
commit 9b9be11cf6
4 changed files with 109 additions and 93 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -27,8 +27,6 @@
# include <math.h> # include <math.h>
# include "ivl_alloc.h" # include "ivl_alloc.h"
#define IS_MCD(mcd) !((mcd)>>31&1)
// Flag to enable better compatibility with other simulators // Flag to enable better compatibility with other simulators
static unsigned compatible_flag = 0; static unsigned compatible_flag = 0;
@ -230,7 +228,7 @@ static void get_time(char *rtn, const char *value, int prec,
shift -= 1; shift -= 1;
} }
if (prec > 0) strcat(rtn, "."); if (prec > 0) strcat(rtn, ".");
while(prec > 0) { while (prec > 0) {
strcat(rtn, "0"); strcat(rtn, "0");
prec -= 1; prec -= 1;
} }
@ -654,15 +652,15 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
* therefore we need to restore it after the call. */ * therefore we need to restore it after the call. */
prev_suff = timeformat_info.suff; prev_suff = timeformat_info.suff;
if(time_units < -12) if (time_units < -12)
timeformat_info.suff = strdup(" fs"); timeformat_info.suff = strdup(" fs");
else if(time_units < -9) else if (time_units < -9)
timeformat_info.suff = strdup(" ps"); timeformat_info.suff = strdup(" ps");
else if(time_units < -6) else if (time_units < -6)
timeformat_info.suff = strdup(" ns"); timeformat_info.suff = strdup(" ns");
else if(time_units < -3) else if (time_units < -3)
timeformat_info.suff = strdup(" us"); timeformat_info.suff = strdup(" us");
else if(time_units < 0) else if (time_units < 0)
timeformat_info.suff = strdup(" ms"); timeformat_info.suff = strdup(" ms");
else else
timeformat_info.suff = strdup(" s"); timeformat_info.suff = strdup(" s");
@ -691,7 +689,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
cp = tbuf; cp = tbuf;
swidth = strlen(tbuf); swidth = strlen(tbuf);
if(plus != 0) { if (plus != 0) {
/* Restore the previous suffix string, overridden by /* Restore the previous suffix string, overridden by
* a vhdlpp-specific $sformatf() call. */ * a vhdlpp-specific $sformatf() call. */
free(timeformat_info.suff); free(timeformat_info.suff);
@ -986,10 +984,10 @@ static char *get_display(unsigned int *rtnsz, const struct strobe_cb_info *info)
value.format = vpiRealVal; value.format = vpiRealVal;
vpi_get_value(item, &value); vpi_get_value(item, &value);
#if !defined(__GNUC__) #if !defined(__GNUC__)
if(compatible_flag) if (compatible_flag)
sprintf(buf, "%g", value.value.real); sprintf(buf, "%g", value.value.real);
else { else {
if(value.value.real == 0.0 || value.value.real == -0.0) if (value.value.real == 0.0 || value.value.real == -0.0)
sprintf(buf, "%.05f", value.value.real); sprintf(buf, "%.05f", value.value.real);
else else
sprintf(buf, "%#g", value.value.real); sprintf(buf, "%#g", value.value.real);
@ -1236,7 +1234,7 @@ static PLI_INT32 sys_common_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name, int no_au
callh = vpi_handle(vpiSysTfCall, 0); callh = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, callh); argv = vpi_iterate(vpiArgument, callh);
if(name[1] == 'f') { if (name[1] == 'f') {
/* Check that there is a fd/mcd and that it is numeric. */ /* Check that there is a fd/mcd and that it is numeric. */
if (argv == 0) { if (argv == 0) {
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
@ -1284,7 +1282,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
argv = vpi_iterate(vpiArgument, callh); argv = vpi_iterate(vpiArgument, callh);
/* Get the file/MC descriptor and verify it is valid. */ /* Get the file/MC descriptor and verify it is valid. */
if(name[1] == 'f') { if (name[1] == 'f') {
errno = 0; errno = 0;
vpiHandle arg = vpi_scan(argv); vpiHandle arg = vpi_scan(argv);
val.format = vpiIntVal; val.format = vpiIntVal;
@ -1297,8 +1295,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
return 0; return 0;
} }
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || if (! is_valid_fd_mcd(fd_mcd)) {
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given " vpi_printf("invalid file descriptor/MCD (0x%x) given "
@ -1307,7 +1304,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
vpi_free_object(argv); vpi_free_object(argv);
return 0; return 0;
} }
} else if(strncmp(name,"$sformatf",9) == 0) { } else if (strncmp(name,"$sformatf",9) == 0) {
/* return as a string */ /* return as a string */
fd_mcd = 0; fd_mcd = 0;
} else { } else {
@ -1330,7 +1327,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
* returned string strlen() may not match the real size! */ * returned string strlen() may not match the real size! */
result = get_display(&size, &info); result = get_display(&size, &info);
if(fd_mcd > 0) { if (fd_mcd > 0) {
my_mcd_rawwrite(fd_mcd, result, size); my_mcd_rawwrite(fd_mcd, result, size);
if ((strncmp(name,"$display",8) == 0) || if ((strncmp(name,"$display",8) == 0) ||
(strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1); (strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1);
@ -1361,8 +1358,7 @@ static PLI_INT32 strobe_cb(p_cb_data cb)
/* We really need to cancel any $fstrobe() calls for a file when it /* We really need to cancel any $fstrobe() calls for a file when it
* is closed, but for now we will just skip processing the result. * is closed, but for now we will just skip processing the result.
* Which has the same basic effect. */ * Which has the same basic effect. */
if ((! IS_MCD(info->fd_mcd) && vpi_get_file(info->fd_mcd) != NULL) || if (is_valid_fd_mcd(info->fd_mcd)) {
( IS_MCD(info->fd_mcd) && my_mcd_printf(info->fd_mcd, "") != EOF)) {
char* result; char* result;
unsigned int size; unsigned int size;
/* Because %u and %z may put embedded NULL characters into the /* Because %u and %z may put embedded NULL characters into the
@ -1399,7 +1395,7 @@ static PLI_INT32 sys_strobe_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
argv = vpi_iterate(vpiArgument, callh); argv = vpi_iterate(vpiArgument, callh);
/* Get the file/MC descriptor and verify it is valid. */ /* Get the file/MC descriptor and verify it is valid. */
if(name[1] == 'f') { if (name[1] == 'f') {
errno = 0; errno = 0;
vpiHandle arg = vpi_scan(argv); vpiHandle arg = vpi_scan(argv);
s_vpi_value val; s_vpi_value val;
@ -1413,8 +1409,7 @@ static PLI_INT32 sys_strobe_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
return 0; return 0;
} }
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || if (! is_valid_fd_mcd(fd_mcd)) {
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given " vpi_printf("invalid file descriptor/MCD (0x%x) given "
@ -1452,6 +1447,7 @@ static PLI_INT32 sys_strobe_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
cb.value = 0; cb.value = 0;
cb.user_data = (char*)info; cb.user_data = (char*)info;
vpi_register_cb(&cb); vpi_register_cb(&cb);
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2018 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2020 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -26,7 +26,6 @@
# include <stdlib.h> # include <stdlib.h>
# include "ivl_alloc.h" # include "ivl_alloc.h"
#define IS_MCD(mcd) !((mcd)>>31&1)
/* /*
* Implement the $fopen system function. * Implement the $fopen system function.
@ -223,9 +222,10 @@ static PLI_INT32 sys_fclose_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
vpi_get_value(fd, &val); vpi_get_value(fd, &val);
fd_mcd = val.value.integer; fd_mcd = val.value.integer;
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || /* If the MCD is zero we have nothing to do so just return. */
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) || if (fd_mcd == 0) return 0;
(! fd_mcd)) {
if (! is_valid_fd_mcd(fd_mcd)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n", vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n",
@ -270,9 +270,7 @@ static PLI_INT32 sys_fflush_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
/* If the MCD is zero we have nothing to do so just return. */ /* If the MCD is zero we have nothing to do so just return. */
if (fd_mcd == 0) return 0; if (fd_mcd == 0) return 0;
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || if (! is_valid_fd_mcd(fd_mcd)) {
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) ||
(! fd_mcd)) {
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh)); (int)vpi_get(vpiLineNo, callh));
vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n", vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n",
@ -883,11 +881,10 @@ static PLI_INT32 sys_fseek_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
#if defined(__GNUC__) #if defined(__GNUC__)
val.value.integer = fseek(fp, offset, oper); val.value.integer = fseek(fp, offset, oper);
#else #else
if(oper < 0) { if (oper < 0) {
val.value.integer = EOF; val.value.integer = EOF;
errno = EINVAL; errno = EINVAL;
} } else
else
val.value.integer = fseek(fp, offset, oper); val.value.integer = fseek(fp, offset, oper);
#endif #endif
vpi_put_value(callh, &val, 0 , vpiNoDelay); vpi_put_value(callh, &val, 0 , vpiNoDelay);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2018 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2020 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -248,6 +248,25 @@ unsigned is_string_obj(vpiHandle obj)
} }
/*
* Check if the file descriptor or MCD is valid.
* For a MCD check that every bit set is a valid file and
* for a FD make sure it exists.
*/
unsigned is_valid_fd_mcd(PLI_UINT32 fd_mcd)
{
assert(fd_mcd); // Should already be handled!
if (IS_MCD(fd_mcd)){
if (vpi_mcd_printf(fd_mcd, "%s", "") == EOF) return 0;
} else {
if (vpi_get_file(fd_mcd) == NULL) return 0;
}
return 1;
}
/* /*
* Find the enclosing module. If there is no enclosing module (which can be * Find the enclosing module. If there is no enclosing module (which can be
* the case in SystemVerilog), return the highest enclosing scope. * the case in SystemVerilog), return the highest enclosing scope.

View File

@ -1,7 +1,7 @@
#ifndef IVL_sys_priv_H #ifndef IVL_sys_priv_H
#define IVL_sys_priv_H #define IVL_sys_priv_H
/* /*
* Copyright (c) 2002-2018 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2020 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -22,6 +22,8 @@
#include "vpi_config.h" #include "vpi_config.h"
#include "sv_vpi_user.h" #include "sv_vpi_user.h"
#define IS_MCD(mcd) !((mcd)>>31&1)
/* /*
* Context structure for PRNG in mt19937int.c * Context structure for PRNG in mt19937int.c
*/ */
@ -56,6 +58,8 @@ extern unsigned is_constant_obj(vpiHandle obj);
extern unsigned is_numeric_obj(vpiHandle obj); extern unsigned is_numeric_obj(vpiHandle obj);
extern unsigned is_string_obj(vpiHandle obj); extern unsigned is_string_obj(vpiHandle obj);
extern unsigned is_valid_fd_mcd(PLI_UINT32 fd_mcd);
extern vpiHandle sys_func_module(vpiHandle obj); extern vpiHandle sys_func_module(vpiHandle obj);
/* /*