scanf support for real values.

This commit is contained in:
steve 2006-08-12 03:38:12 +00:00
parent 54c7ef72cb
commit 2c7e96caec
3 changed files with 150 additions and 16 deletions

View File

@ -17,12 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_display.c,v 1.71 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: sys_display.c,v 1.72 2006/08/12 03:38:12 steve Exp $"
#endif
# include "vpi_config.h"
# include "vpi_user.h"
# include "sys_priv.h"
# include <assert.h>
# include <string.h>
# include <ctype.h>
@ -51,13 +52,6 @@ static PLI_INT32 my_mcd_printf(PLI_UINT32 mcd, const char *fmt, ...)
return r;
}
struct timeformat_info_s {
int units;
unsigned prec;
char*suff;
unsigned width;
};
struct timeformat_info_s timeformat_info = { 0, 0, 0, 20 };
struct strobe_cb_info {
@ -1566,6 +1560,9 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.72 2006/08/12 03:38:12 steve
* scanf support for real values.
*
* Revision 1.71 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_priv.h,v 1.5 2004/01/21 01:22:53 steve Exp $"
#ident "$Id: sys_priv.h,v 1.6 2006/08/12 03:38:12 steve Exp $"
#endif
# include "vpi_config.h"
@ -47,8 +47,21 @@ extern int is_constant(vpiHandle obj);
extern PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time);
struct timeformat_info_s {
int units;
unsigned prec;
char*suff;
unsigned width;
};
extern struct timeformat_info_s timeformat_info;
/*
* $Log: sys_priv.h,v $
* Revision 1.6 2006/08/12 03:38:12 steve
* scanf support for real values.
*
* Revision 1.5 2004/01/21 01:22:53 steve
* Give the vip directory its own configure and vpi_config.h
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_scanf.c,v 1.1 2006/08/03 05:06:04 steve Exp $"
#ident "$Id: sys_scanf.c,v 1.2 2006/08/12 03:38:12 steve Exp $"
#endif
# include "vpi_user.h"
@ -26,6 +26,7 @@
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <assert.h>
struct byte_source {
@ -60,6 +61,121 @@ static void byte_ungetc(struct byte_source*src, int ch)
}
static int sys_fscanf_compiletf(char*name)
{
return 0;
}
/*
* This function matches the input characters of a floating point
* number and generates a floating point (double) from that string.
*/
static double float_string(struct byte_source*src)
{
int ch;
char*str = 0;
size_t len;
double sign_flag = 1.0;
ch = byte_getc(src);
if (ch == '+') {
sign_flag = 1.0;
ch = byte_getc(src);
} else if (ch == '-') {
sign_flag = -1.0;
ch = byte_getc(src);
}
str = malloc(1);
len = 0;
*str = 0;
while (isdigit(ch)) {
str = realloc(str, len+2);
str[len++] = ch;
ch = byte_getc(src);
}
if (ch == '.') {
str = realloc(str, len+2);
str[len++] = ch;
ch = byte_getc(src);
while (isdigit(ch)) {
str = realloc(str, len+2);
str[len++] = ch;
ch = byte_getc(src);
}
}
if (ch == 'e' || ch == 'E') {
str = realloc(str, len+2);
str[len++] = ch;
ch = byte_getc(src);
if (ch == '-' || ch == '+') {
str = realloc(str, len+2);
str[len++] = ch;
ch - byte_getc(src);
}
while (isdigit(ch)) {
src = realloc(str, len+2);
str[len++] = ch;
ch = byte_getc(src);
}
}
str[len] = 0;
sign_flag *= strtod(str, 0);
free(str);
if (ch != EOF)
byte_ungetc(src, ch);
return sign_flag;
}
static int scan_format_float(struct byte_source*src,
vpiHandle arg)
{
s_vpi_value val;
val.format = vpiRealVal;
val.value.real = float_string(src);
vpi_put_value(arg, &val, 0, vpiNoDelay);
return 1;
}
static int scan_format_float_time(vpiHandle sys,
struct byte_source*src,
vpiHandle arg)
{
vpiHandle scope = vpi_handle(vpiScope, sys);
int time_units = vpi_get(vpiTimeUnit, scope);
double scale;
s_vpi_value val;
val.format = vpiRealVal;
val.value.real = float_string(src);
/* Round the value to the specified precision. Handle this bit
by shifting the decimal point to the precision where we
want to round, do the rounding, then shift the point back */
scale = pow(10.0, timeformat_info.prec);
val.value.real = round(val.value.real*scale) / scale;
/* Change the units from the timeformat to the timescale. */
scale = pow(10.0, timeformat_info.units - time_units);
val.value.real *= scale;
vpi_put_value(arg, &val, 0, vpiNoDelay);
return 1;
}
/*
* The $fscanf and $sscanf functions are the same except for the first
* argument, which is the source. The wrapper functions below peel off
@ -180,7 +296,6 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv)
rc += 1;
break;
case 'd':
/* Decimal integer */
ch = byte_getc(src);
@ -203,6 +318,14 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv)
rc += 1;
break;
case 'e':
case 'f':
case 'g':
item = vpi_scan(argv);
assert(item);
rc += scan_format_float(src, item);
break;
case 'h':
case 'x':
/* Hex integer */
@ -264,6 +387,12 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv)
rc += 1;
break;
case 't':
item = vpi_scan(argv);
assert(item);
rc += scan_format_float_time(sys, src, item);
break;
default:
vpi_printf("$scanf: Unknown format code: %c\n", code);
break;
@ -281,11 +410,6 @@ static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv)
return 0;
}
static int sys_fscanf_compiletf(char*name)
{
return 0;
}
static int sys_fscanf_calltf(char*name)
{
s_vpi_value val;