diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 6517b17a6..4df68ac0c 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -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 # include # include @@ -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. * diff --git a/vpi/sys_priv.h b/vpi/sys_priv.h index 943bbec02..3a7ef66d3 100644 --- a/vpi/sys_priv.h +++ b/vpi/sys_priv.h @@ -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 * diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index dbd3a88f1..45cb4c7c9 100644 --- a/vpi/sys_scanf.c +++ b/vpi/sys_scanf.c @@ -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 # include # include +# include # include 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;