diff --git a/vpi/sys_fileio.c b/vpi/sys_fileio.c index 82a11c337..24234cd99 100644 --- a/vpi/sys_fileio.c +++ b/vpi/sys_fileio.c @@ -96,12 +96,12 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name) int fail = 0; char *mode_string = 0; unsigned idx; - vpiHandle item = vpi_scan(argv); + vpiHandle fileh = vpi_scan(argv); + char *fname; vpiHandle mode = vpi_scan(argv); - unsigned len; - /* Get the mode handle if it exists. */ if (mode) { + char *esc_md; val.format = vpiStringVal; vpi_get_value(mode, &val); /* Verify that we have a string and that it is not NULL. */ @@ -119,8 +119,10 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name) vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); + esc_md = as_escaped(val.value.str); vpi_printf("%s's mode argument (%s) is too long.\n", - name, val.value.str); + name, esc_md); + free(esc_md); fail = 1; } else { unsigned bin = 0, plus = 0; @@ -150,8 +152,10 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name) vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); + esc_md = as_escaped(val.value.str); vpi_printf("%s's mode argument (%s) is invalid.\n", - name, val.value.str); + name, esc_md); + free(esc_md); fail = 1; break; } @@ -162,49 +166,18 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name) vpi_free_object(argv); } - /* Get the string form of the file name from the file name - argument. */ - val.format = vpiStringVal; - vpi_get_value(item, &val); - - /* Verify that we have a string and that it is not NULL. */ - if (val.format != vpiStringVal || !*(val.value.str)) { - vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s's file name argument is not a valid string.\n", - name); - fail = 1; - if (mode) free(mode_string); - } - - /* - * Verify that the file name is composed of only printable - * characters. - */ - len = strlen(val.value.str); - for (idx = 0; idx < len; idx++) { - if (! isprint(val.value.str[idx])) { - char msg [64]; - snprintf(msg, 64, "WARNING: %s:%d:", - vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s %s's file name argument contains non-" - "printable characters.\n", msg, name); - vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", val.value.str); - fail = 1; - if (mode) free(mode_string); - } - } + fname = get_filename(callh, name, fileh); + if (fname == 0 && mode) free(mode_string); /* If either the mode or file name are not valid just return. */ - if (fail) return 0; + if (fail || fname == 0) return 0; val.format = vpiIntVal; if (mode) { - val.value.integer = vpi_fopen(val.value.str, mode_string); + val.value.integer = vpi_fopen(fname, mode_string); free(mode_string); } else - val.value.integer = vpi_mcd_open(val.value.str); + val.value.integer = vpi_mcd_open(fname); vpi_put_value(callh, &val, 0, vpiNoDelay); @@ -220,51 +193,23 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle file = vpi_scan(argv); s_vpi_value val; - char *mode; - unsigned idx, len; + char *mode, *fname; - vpi_free_object(argv); /* Get the mode. */ mode = name + strlen(name) - 1; - /* Get the filename. */ - val.format = vpiStringVal; - vpi_get_value(file, &val); - - /* Verify that we have a string and that it is not NULL. */ - if (val.format != vpiStringVal || !*(val.value.str)) { - vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s's file name argument is not a valid string.\n", - name); - return 0; - } - - /* - * Verify that the file name is composed of only printable - * characters. - */ - len = strlen(val.value.str); - for (idx = 0; idx < len; idx++) { - if (! isprint(val.value.str[idx])) { - char msg [64]; - snprintf(msg, 64, "WARNING: %s:%d:", - vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s %s's file name argument contains non-" - "printable characters.\n", msg, name); - vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", val.value.str); - return 0; - } - } + /* Get the file name. */ + fname = get_filename(callh, name, vpi_scan(argv)); + vpi_free_object(argv); + if (fname == 0) return 0; /* Open the file and return the result. */ val.format = vpiIntVal; - val.value.integer = vpi_fopen(val.value.str, mode); + val.value.integer = vpi_fopen(fname, mode); vpi_put_value(callh, &val, 0, vpiNoDelay); + free(fname); return 0; } diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index ac9972c57..f2c9cf950 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2009 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 @@ -168,7 +168,7 @@ static void show_this_item(struct vcd_info*info) { s_vpi_value value; - if (vpi_get(vpiType,info->item) == vpiRealVar) { + if (vpi_get(vpiType, info->item) == vpiRealVar) { value.format = vpiRealVal; vpi_get_value(info->item, &value); lt_emit_value_double(dump_file, info->sym, 0, value.value.real); @@ -177,8 +177,8 @@ static void show_this_item(struct vcd_info*info) value.format = vpiBinStrVal; vpi_get_value(info->item, &value); lt_emit_value_bit_string(dump_file, info->sym, - 0 /* array row */, - value.value.str); + 0 /* array row */, + value.value.str); } } @@ -252,10 +252,10 @@ static PLI_INT32 variable_cb_1(p_cb_data cause) struct t_cb_data cb; struct vcd_info*info = (struct vcd_info*)cause->user_data; - if (dump_is_full) return 0; - if (dump_is_off) return 0; + if (dump_is_full) return 0; + if (dump_is_off) return 0; if (dump_header_pending()) return 0; - if (info->scheduled) return 0; + if (info->scheduled) return 0; if ((dump_limit > 0) && (ftell(dump_file->handle) > dump_limit)) { dump_is_full = 1; @@ -280,8 +280,7 @@ static PLI_INT32 variable_cb_1(p_cb_data cause) static PLI_INT32 dumpvars_cb(p_cb_data cause) { - if (dumpvars_status != 1) - return 0; + if (dumpvars_status != 1) return 0; dumpvars_status = 2; @@ -298,13 +297,11 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause) static PLI_INT32 finish_cb(p_cb_data cause) { - if (finish_status != 0) - return 0; + if (finish_status != 0) return 0; finish_status = 1; dumpvars_time = timerec_to_time64(cause->time); - if (!dump_is_off && !dump_is_full && dumpvars_time != vcd_cur_time) { lt_set_time64(dump_file, dumpvars_time); } @@ -317,8 +314,7 @@ __inline__ static int install_dumpvars_callback(void) struct t_cb_data cb; static struct t_vpi_time now; - if (dumpvars_status == 1) - return 0; + if (dumpvars_status == 1) return 0; if (dumpvars_status == 2) { vpi_printf("LXT warning: $dumpvars ignored, previously" @@ -362,8 +358,8 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name) now64 = timerec_to_time64(&now); if (now64 > vcd_cur_time) { - lt_set_time64(dump_file, now64); - vcd_cur_time = now64; + lt_set_time64(dump_file, now64); + vcd_cur_time = now64; } lt_set_dumpoff(dump_file); @@ -389,8 +385,8 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name) now64 = timerec_to_time64(&now); if (now64 > vcd_cur_time) { - lt_set_time64(dump_file, now64); - vcd_cur_time = now64; + lt_set_time64(dump_file, now64); + vcd_cur_time = now64; } lt_set_dumpon(dump_file); @@ -412,9 +408,9 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64> vcd_cur_time) { - lt_set_time64(dump_file, now64); - vcd_cur_time = now64; + if (now64 > vcd_cur_time) { + lt_set_time64(dump_file, now64); + vcd_cur_time = now64; } vcd_checkpoint(); @@ -450,7 +446,7 @@ static void open_dumpfile(vpiHandle callh) lt_set_timescale(dump_file, prec); lt_set_initial_value(dump_file, 'x'); - lt_set_clock_compress(dump_file); + lt_set_clock_compress(dump_file); atexit((void(*)(void))close_dumpfile); } @@ -460,31 +456,33 @@ static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); - s_vpi_value value; - - char*path; + char *path; /* $dumpfile must be called before $dumpvars starts! */ if (dumpvars_status != 0) { - vpi_printf("LXT warning: %s called after $dumpvars started,\n" - " using existing file (%s).\n", - name, dump_path); + char msg [64]; + snprintf(msg, 64, "LXT warning: %s:%d:", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s %s called after $dumpvars started,\n", msg, name); + vpi_printf("%*s using existing file (%s).\n", + (int) strlen(msg), " ", dump_path); + vpi_free_object(argv); return 0; } - assert(argv); - value.format = vpiStringVal; - vpi_get_value(vpi_scan(argv), &value); - path = strdup(value.value.str); + path = get_filename(callh, name, vpi_scan(argv)); + vpi_free_object(argv); + if (! path) return 0; if (dump_path) { - vpi_printf("LXT warning: Overriding dump file %s with %s\n", - dump_path, path); + vpi_printf("LXT warning: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Overriding dump file %s with %s.\n", dump_path, path); free(dump_path); } dump_path = path; - vpi_free_object(argv); return 0; } @@ -500,12 +498,11 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle limit = vpi_scan(argv); s_vpi_value val; /* Get the value and set the dump limit. */ val.format = vpiIntVal; - vpi_get_value(limit, &val); + vpi_get_value(vpi_scan(argv), &val); dump_limit = val.value.integer; vpi_free_object(argv); @@ -566,8 +563,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info = malloc(sizeof(*info)); info->time.type = vpiSimTime; - info->item = item; - info->sym = lt_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiLeftRange, item), vpi_get(vpiRightRange, item), LT_SYM_F_BITS); + info->item = item; + info->sym = lt_symbol_add(dump_file, ident, + 0 /* array rows */, + vpi_get(vpiLeftRange, item), + vpi_get(vpiRightRange, item), + LT_SYM_F_BITS); info->scheduled = 0; cb.time = &info->time; @@ -603,8 +604,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info = malloc(sizeof(*info)); info->time.type = vpiSimTime; - info->item = item; - info->sym = lt_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiSize, item)-1, 0, LT_SYM_F_DOUBLE); + info->item = item; + info->sym = lt_symbol_add(dump_file, ident, + 0 /* array rows */, + vpi_get(vpiSize, item)-1, + 0, LT_SYM_F_DOUBLE); info->scheduled = 0; cb.time = &info->time; @@ -675,8 +679,7 @@ static int draw_scope(vpiHandle item) const char *name; vpiHandle scope = vpi_handle(vpiScope, item); - if (!scope) - return 0; + if (!scope) return 0; depth = 1 + draw_scope(scope); name = vpi_get_str(vpiName, scope); @@ -696,10 +699,16 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) if (dump_file == 0) { open_dumpfile(callh); - if (dump_file == 0) return 0; + if (dump_file == 0) { + vpi_free_object(argv); + return 0; + } } - if (install_dumpvars_callback()) return 0; + if (install_dumpvars_callback()) { + vpi_free_object(argv); + return 0; + } /* Get the depth if it exists. */ if (argv) { @@ -727,7 +736,9 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) } /* Most effective compression. */ - if (lxm_optimum_mode == LXM_SPACE) lt_set_no_interlace(dump_file); + if (lxm_optimum_mode == LXM_SPACE) { + lt_set_no_interlace(dump_file); + } return 0; } diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index 65c1a0d02..65074b2c3 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2009 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 @@ -142,7 +142,7 @@ static char *create_full_name(const char *name) } -static char *dump_path; +static char *dump_path = 0; static struct lxt2_wr_trace *dump_file = 0; struct vcd_info { @@ -169,7 +169,7 @@ static void show_this_item(struct vcd_info*info) { s_vpi_value value; - if (vpi_get(vpiType,info->item) == vpiRealVar) { + if (vpi_get(vpiType, info->item) == vpiRealVar) { value.format = vpiRealVal; vpi_get_value(info->item, &value); lxt2_wr_emit_value_double(dump_file, info->sym, 0, @@ -179,8 +179,8 @@ static void show_this_item(struct vcd_info*info) value.format = vpiBinStrVal; vpi_get_value(info->item, &value); lxt2_wr_emit_value_bit_string(dump_file, info->sym, - 0 /* array row */, - value.value.str); + 0 /* array row */, + value.value.str); } } @@ -360,8 +360,8 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name) now64 = timerec_to_time64(&now); if (now64 > vcd_cur_time) { - lxt2_wr_set_time(dump_file, now64); - vcd_cur_time = now.low; + lxt2_wr_set_time(dump_file, now64); + vcd_cur_time = now64; } lxt2_wr_set_dumpoff(dump_file); @@ -387,8 +387,8 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name) now64 = timerec_to_time64(&now); if (now64 > vcd_cur_time) { - lxt2_wr_set_time64(dump_file, now64); - vcd_cur_time = now64; + lxt2_wr_set_time64(dump_file, now64); + vcd_cur_time = now64; } lxt2_wr_set_dumpon(dump_file); @@ -410,9 +410,10 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) - lxt2_wr_set_time64(dump_file, now64); - vcd_cur_time = now64; + if (now64 > vcd_cur_time) { + lxt2_wr_set_time64(dump_file, now64); + vcd_cur_time = now64; + } vcd_checkpoint(); @@ -458,33 +459,35 @@ static void open_dumpfile(vpiHandle callh) static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) { - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - s_vpi_value value; - - char*path; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + char *path; /* $dumpfile must be called before $dumpvars starts! */ if (dumpvars_status != 0) { - vpi_printf("LXT2 warning: %s called after $dumpvars started,\n" - " using existing file (%s).\n", - name, dump_path); + char msg [64]; + snprintf(msg, 64, "LXT2 warning: %s:%d:", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s %s called after $dumpvars started,\n", msg, name); + vpi_printf("%*s using existing file (%s).\n", + (int) strlen(msg), " ", dump_path); + vpi_free_object(argv); return 0; } - assert(argv); - value.format = vpiStringVal; - vpi_get_value(vpi_scan(argv), &value); - path = strdup(value.value.str); + path = get_filename(callh, name, vpi_scan(argv)); + vpi_free_object(argv); + if (! path) return 0; if (dump_path) { - vpi_printf("LXT2 warning: Overriding dump file %s with %s.\n", - dump_path, path); + vpi_printf("LXT2 warning: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Overriding dump file %s with %s.\n", dump_path, path); free(dump_path); } dump_path = path; - vpi_free_object(argv); return 0; } @@ -572,12 +575,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info = malloc(sizeof(*info)); info->time.type = vpiSimTime; - info->item = item; - info->sym = lxt2_wr_symbol_add(dump_file, ident, - 0 /* array rows */, - vpi_get(vpiLeftRange, item), - vpi_get(vpiRightRange, item), - LXT2_WR_SYM_F_BITS); + info->item = item; + info->sym = lxt2_wr_symbol_add(dump_file, ident, + 0 /* array rows */, + vpi_get(vpiLeftRange, item), + vpi_get(vpiRightRange, item), + LXT2_WR_SYM_F_BITS); info->scheduled = 0; cb.time = &info->time; @@ -613,11 +616,11 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info = malloc(sizeof(*info)); info->time.type = vpiSimTime; - info->item = item; - info->sym = lxt2_wr_symbol_add(dump_file, ident, - 0 /* array rows */, - vpi_get(vpiSize, item)-1, - 0, LXT2_WR_SYM_F_DOUBLE); + info->item = item; + info->sym = lxt2_wr_symbol_add(dump_file, ident, + 0 /* array rows */, + vpi_get(vpiSize, item)-1, + 0, LXT2_WR_SYM_F_DOUBLE); info->scheduled = 0; cb.time = &info->time; @@ -708,10 +711,16 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) if (dump_file == 0) { open_dumpfile(callh); - if (dump_file == 0) return 0; + if (dump_file == 0) { + vpi_free_object(argv); + return 0; + } } - if (install_dumpvars_callback()) return 0; + if (install_dumpvars_callback()) { + vpi_free_object(argv); + return 0; + } /* Get the depth if it exists. */ if (argv) { diff --git a/vpi/sys_priv.c b/vpi/sys_priv.c index 2535a84b6..926c1e710 100644 --- a/vpi/sys_priv.c +++ b/vpi/sys_priv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2009 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 @@ -18,6 +18,8 @@ */ #include +#include +#include #include #include "sys_priv.h" @@ -32,6 +34,73 @@ PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time) return tmp; } +char * as_escaped(char *arg) +{ + unsigned idx, cur, cnt, len = strlen(arg); + char *res = (char *) malloc(sizeof(char *) * len); + cur = 0; + cnt = len; + for (idx = 0; idx < cnt; idx++) { + if (isprint(arg[idx])) { + res[cur] = arg[idx]; + cur += 1; + } else { + len += 3; + res = (char *) realloc(res, sizeof(char *) * len); + sprintf(&(res[cur]), "\\%03o", arg[idx]); + cur += 4; + } + } + res[cur] = 0; + return res; +} + +/* + * Generic routine to get the filename from the given handle. + * The result is duplicated so call free when the name is no + * longer needed. Returns 0 (NULL) for an error. + */ +char * get_filename(vpiHandle callh, char *name, vpiHandle file) +{ + s_vpi_value val; + unsigned len, idx; + + /* Get the filename. */ + val.format = vpiStringVal; + vpi_get_value(file, &val); + + /* Verify that we have a string and that it is not NULL. */ + if (val.format != vpiStringVal || !*(val.value.str)) { + vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's file name argument (%s) is not a valid string.\n", + name, vpi_get_str(vpiType, file)); + return 0; + } + + /* + * Verify that the file name is composed of only printable + * characters. + */ + len = strlen(val.value.str); + for (idx = 0; idx < len; idx++) { + if (! isprint(val.value.str[idx])) { + char msg [64]; + char *esc_fname = as_escaped(val.value.str); + snprintf(msg, 64, "WARNING: %s:%d:", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s %s's file name argument contains non-" + "printable characters.\n", msg, name); + vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_fname); + free(esc_fname); + return 0; + } + } + + return strdup(val.value.str); +} + /* * This routine returns 1 if the argument is a constant value, * otherwise it returns 0. diff --git a/vpi/sys_priv.h b/vpi/sys_priv.h index 82b7f2a8d..a5cc66ff6 100644 --- a/vpi/sys_priv.h +++ b/vpi/sys_priv.h @@ -1,7 +1,7 @@ #ifndef __vpi_sys_priv_H #define __vpi_sys_priv_H /* - * Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2009 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 @@ -35,6 +35,9 @@ extern unsigned long genrand(struct context_s *context); extern PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time); +extern char * as_escaped(char *arg); +extern char * get_filename(vpiHandle callh, char *name, vpiHandle file); + struct timeformat_info_s { int units; unsigned prec; diff --git a/vpi/sys_readmem.c b/vpi/sys_readmem.c index b6c09c07a..ccbc9fd98 100644 --- a/vpi/sys_readmem.c +++ b/vpi/sys_readmem.c @@ -20,105 +20,267 @@ # include "vpi_config.h" # include "vpi_user.h" +# include "sys_priv.h" +# include # include # include # include # include # include "sys_readmem_lex.h" -static int check_integer_constant(char*name, vpiHandle handle) +static void get_mem_params(vpiHandle argv, vpiHandle callh, char *name, + char **fname, vpiHandle *mitem, + vpiHandle *start_item, vpiHandle *stop_item) { - if (vpi_get(vpiType, handle) != vpiConstant){ - vpi_printf("ERROR: %s parameter must be a constant (vpiType=%d)\n", - name, vpi_get(vpiType, handle)); - return 0; - } + /* Get the first parameter (file name). */ + *fname = get_filename(callh, name, vpi_scan(argv)); - switch(vpi_get(vpiConstType, handle)){ - case vpiDecConst: - case vpiBinaryConst: - case vpiOctConst: - case vpiHexConst: - return 1; - break; + /* Get the second parameter (memory). */ + *mitem = vpi_scan(argv); - /* We rely on vpi_get_value for reals and strings to return a correct */ - /* integer value when this is requested. So only a warning is generated. */ - case vpiRealConst: - vpi_printf("Warning: real supplied to %s instead of integer.\n", name); - return 1; - break; + /* Get optional third parameter (start address). */ + *start_item = vpi_scan(argv); + if (*start_item) { + /* Warn the user if they gave a real value for the start + * address. */ + switch (vpi_get(vpiType, *start_item)) { + case vpiConstant: + case vpiParameter: + if (vpi_get(vpiConstType, *start_item) != vpiRealConst) break; + case vpiRealVar: + vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's third argument (start address) is a real " + "value.\n", name); + } - case vpiStringConst: - vpi_printf("Warning: string supplied to %s instead of integer.\n", name); - return 1; - break; - } - - /* switch statement covers all possibilities. Code should never come here... */ - assert(0); - return 0; + /* Get optional forth parameter (finish address). */ + *stop_item = vpi_scan(argv); + if (*stop_item) { + /* Warn the user if they gave a real value for the finish + * address. */ + switch (vpi_get(vpiType, *stop_item)) { + case vpiConstant: + case vpiParameter: + if (vpi_get(vpiConstType, *stop_item) != vpiRealConst) { + break; + } + case vpiRealVar: + vpi_printf("WARNING: %s:%d: ", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's fourth argument (finish address) is a " + "real value.\n", name); + } + vpi_free_object(argv); + } + } else { + *stop_item = 0; + } } -/* - * This function makes sure the handle is of an object that can get a - * string value for a file name. - */ -static int check_file_name(const char*name, vpiHandle item) +static int process_params(vpiHandle mitem, + vpiHandle start_item, vpiHandle stop_item, + vpiHandle callh, char *name, + int *start_addr, int *stop_addr, int *addr_incr, + int *min_addr, int *max_addr) { - switch (vpi_get(vpiType, item)) { + s_vpi_value val; + int left_addr, right_addr; - case vpiConstant: - if (vpi_get(vpiConstType, item) != vpiStringConst) { - vpi_printf("ERROR: %s argument 1: file name argument " - "must be a string.\n", name); - return 0; - } - break; + /* Get left addr of memory */ + val.format = vpiIntVal; + vpi_get_value(vpi_handle(vpiLeftRange, mitem), &val); + left_addr = val.value.integer; - case vpiParameter: - if (vpi_get(vpiConstType,item) != vpiStringConst) { - vpi_printf("ERROR: %s argument 1: Parameter %s is " - "not a string in this context.\n", - name, vpi_get_str(vpiName,item)); - return 0; - } - break; + /* Get right addr of memory */ + val.format = vpiIntVal; + vpi_get_value(vpi_handle(vpiRightRange, mitem), &val); + right_addr = val.value.integer; - case vpiReg: - break; + /* Get start_addr, stop_addr and addr_incr */ + if (! start_item) { + *start_addr = left_addr right_addr)) { + vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s: Standard inconsistency, following 1364-2005.\n", + name); + } + + /* Check that start_addr and stop_addr are within the memory + range */ + if (left_addr < right_addr) { + if (*start_addr < left_addr || *start_addr > right_addr) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s: Start address %d is out of bounds for memory " + "\'%s[%d:%d]\'!\n", name, *start_addr, + vpi_get_str(vpiFullName, mitem), + left_addr, right_addr); + return 1; + } + + if (*stop_addr < left_addr || *stop_addr > right_addr) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s: Finish address %d is out of bounds for memory " + "\'%s[%d:%d]\'!\n", name, *stop_addr, + vpi_get_str(vpiFullName, mitem), + left_addr, right_addr); + return 1; + } + } else { + if (*start_addr < right_addr || *start_addr > left_addr) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s: Start address %d is out of bounds for memory " + "\'%s[%d:%d]\'!\n", name, *start_addr, + vpi_get_str(vpiFullName, mitem), + left_addr, right_addr); + return 1; + } + + if (*stop_addr < right_addr || *stop_addr > left_addr) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s: Finish address %d is out of bounds for memory " + "\'%s[%d:%d]\'!\n", name, *stop_addr, + vpi_get_str(vpiFullName, mitem), + left_addr, right_addr); + return 1; + } + } + return 0; +} + +static PLI_INT32 sys_mem_compiletf(PLI_BYTE8*name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + + /* Check that there is a file name argument. */ + if (argv == 0) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s requires two arguments.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + if (! is_string_obj(vpi_scan(argv))) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's first argument must be a file name (string).\n", + name); + vpi_control(vpiFinish, 1); + } + + /* Check that there is a memory argument. */ + arg = vpi_scan(argv); + if (! arg) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s requires a second (memory) argument.\n", name); + vpi_control(vpiFinish, 1); return 0; } - return 1; -} + if (vpi_get(vpiType, arg) != vpiMemory) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's second argument must be a memory.\n", name); + vpi_control(vpiFinish, 1); + } + /* Check if there is a starting address argument. */ + arg = vpi_scan(argv); + if (! arg) return 0; + + if (! is_numeric_obj(arg)) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's third argument must be a start address " + "(numeric).\n", name); + vpi_control(vpiFinish, 1); + } + + /* Check if there is a finish address argument. */ + arg = vpi_scan(argv); + if (! arg) return 0; + + if (! is_numeric_obj(arg)) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's fourth argument must be a finish address " + "(numeric).\n", name); + vpi_control(vpiFinish, 1); + } + + /* Make sure there are no extra arguments. */ + if (vpi_scan(argv) != 0) { + char msg [64]; + unsigned argc; + + snprintf(msg, 64, "ERROR: %s:%d:", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + + argc = 1; + while (vpi_scan(argv)) argc += 1; + + vpi_printf("%s %s takes at most four arguments.\n", + msg, name); + vpi_printf("%*s Found %u extra argument%s.\n", + (int) strlen(msg), " ", argc, argc == 1 ? "" : "s"); + vpi_control(vpiFinish, 1); + } + + return 0; +} static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) { - int code; - int wwid; - char*path; - char*mem_name; + int code, wwid, addr; FILE*file; - unsigned addr; + char *fname = 0; s_vpi_value value; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle item = vpi_scan(argv); - vpiHandle mitem; - vpiHandle start_item; - vpiHandle stop_item; - vpiHandle left_range; - vpiHandle right_range; - vpiHandle word_index; - - /* These are left and right hand side parameters in the - declaration of the memory. */ - int left_addr, right_addr; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle mitem = 0; + vpiHandle start_item = 0; + vpiHandle stop_item = 0; /* start_addr and stop_addr are the parameters given to $readmem in the Verilog code. When not specified, start_addr is equal to the lower of @@ -128,159 +290,37 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) /* min_addr and max_addr are equal to start_addr and stop_addr if start_addr right_addr) { - vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - - if (stop_addr right_addr) { - vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - } - else{ - if (start_addr left_addr) { - vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - - if (stop_addr left_addr) { - vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - } - - item = vpi_handle_by_index(mitem,min_addr); - wwid = vpi_get(vpiSize, item); + wwid = vpi_get(vpiSize, vpi_handle_by_index(mitem, min_addr)); /* variable that will be uses by the lexer to pass values back to this code */ @@ -293,7 +333,6 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) else sys_readmem_start_file(file, 0, wwid, value.value.vector); - /*======================================== Read memory file */ /* Run through the input file and store the new contents in the memory */ @@ -302,44 +341,67 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) switch (code) { case MEM_ADDRESS: addr = value.value.vector->aval; + if (addr < min_addr || addr > max_addr) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s(%s): address (0x%x) is out of range " + "[0x%x:0x%x]\n", + name, fname, addr, start_addr, stop_addr); + goto bailout; + } /* if there is an address in the memory file, then turn off any possible warnings about not having enough words to load the memory. This is standard - behavior. */ + behavior from 1364-2005. */ word_count = 0; break; case MEM_WORD: - if (addr >= min_addr && addr <= max_addr){ + if (addr >= min_addr && addr <= max_addr) { + vpiHandle word_index; word_index = vpi_handle_by_index(mitem, addr); assert(word_index); vpi_put_value(word_index, &value, 0, vpiNoDelay); - if (word_count > 0) - word_count -= 1; - } - else{ - vpi_printf("%s(%s): address (0x%x) out of range (0x%x:0x%x)\n", - name, path, addr, start_addr, stop_addr); + if (word_count > 0) word_count -= 1; + } else { + vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s(%s): Too many words in the file for the " + "requested range [%d:%d].\n", + name, fname, start_addr, stop_addr); goto bailout; } addr += addr_incr; break; + case MEM_ERROR: + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s(%s): Invalid input character: %s\n", name, + fname, readmem_error_token); + goto bailout; + break; + default: - vpi_printf("Huh?! (%d)\n", code); + assert(0); break; } } - if (word_count > 0) - vpi_printf("%s(%s): Not enough words in the read file " - "for requested range.\n", name, path); + /* Print a warning if there are not enough words in the data file. */ + if (word_count > 0) { + vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s(%s): Not enough words in the file for the " + "requested range [%d:%d].\n", name, fname, + start_addr, stop_addr); + } bailout: free(value.value.vector); - free(path); + free(fname); fclose(file); destroy_readmem_lexor(file); return 0; @@ -347,197 +409,53 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name) { - int wwid; - char*path; - char*mem_name; + int addr; FILE*file; - unsigned addr = 0; - unsigned cnt = 0; + char*fname = 0; + unsigned cnt; s_vpi_value value; - vpiHandle words; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle item = vpi_scan(argv); - vpiHandle mitem; - vpiHandle start_item; - vpiHandle stop_item; - vpiHandle word_index; - vpiHandle left_range; - vpiHandle right_range; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle mitem = 0; + vpiHandle start_item = 0; + vpiHandle stop_item = 0; - int left_addr, right_addr; int start_addr, stop_addr, addr_incr; - int min_addr, max_addr; + int min_addr, max_addr; // Not used in this routine. /*======================================== Get parameters */ - if (item == 0) { - vpi_printf("%s: file name parameter missing.\n", name); - return 0; - } + get_mem_params(argv, callh, name, + &fname, &mitem, &start_item, &stop_item); - if (vpi_get(vpiType, item) != vpiConstant) { - vpi_printf("ERROR: %s parameter must be a constant\n", name); - vpi_free_object(argv); - return 0; - } - - if (vpi_get(vpiConstType, item) != vpiStringConst) { - vpi_printf("ERROR: %s parameter must be a string\n", name); - vpi_free_object(argv); - return 0; - } - - value.format = vpiStringVal; - vpi_get_value(item, &value); - path = strdup(value.value.str); - - /* Get and check the second parameter. It must be a memory. */ - mitem = vpi_scan(argv); - if (mitem == 0) { - vpi_printf("%s: Missing memory parameter\n", name); - free(path); - return 0; - } - - if (vpi_get(vpiType, mitem) != vpiMemory) { - vpi_printf("%s: Second parameter must be a memory.\n", name); - free(path); - vpi_free_object(argv); - return 0; - } - - mem_name = vpi_get_str(vpiFullName, mitem); - - /* Get optional third parameter. It must be a constant. */ - start_item = vpi_scan(argv); - if (start_item!=0){ - if (check_integer_constant(name, start_item) == 0){ - free(path); - vpi_free_object(argv); - return 0; - } - - /* Get optional forth parameter. It must be a constant. */ - stop_item = vpi_scan(argv); - if (stop_item!=0){ - if (check_integer_constant(name, stop_item) == 0){ - free(path); - vpi_free_object(argv); - return 0; - } - - /* Check that there is no 5th parameter */ - if (vpi_scan(argv) != 0){ - vpi_printf("ERROR: %s accepts maximum 4 parameters!\n", name ); - free(path); - vpi_free_object(argv); - return 0; - } - - } - } - else{ - stop_item = 0; - } + if (fname == 0) return 0; /*======================================== Process parameters */ + if (process_params(mitem, start_item, stop_item, callh, name, + &start_addr, &stop_addr, &addr_incr, + &min_addr, &max_addr)) return 0; + /* Open the data file. */ - file = fopen(path, "w"); + file = fopen(fname, "w"); if (file == 0) { - vpi_printf("%s: Unable to open %s for writing.\n", name, path); - free(path); + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s: Unable to open %s for writing.\n", name, fname); + free(fname); return 0; } - /* Get left addr of memory */ - left_range = vpi_handle(vpiLeftRange, mitem); - value.format = vpiIntVal; - vpi_get_value(left_range, &value); - left_addr = value.value.integer; - - /* Get right addr of memory */ - right_range = vpi_handle(vpiRightRange, mitem); - value.format = vpiIntVal; - vpi_get_value(right_range, &value); - right_addr = value.value.integer; - - /* Get start_addr, stop_addr and addr_incr */ - if (start_item==0){ - start_addr = left_addr right_addr) { - vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - - if (stop_addr right_addr) { - vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - } - else{ - if (start_addr left_addr) { - vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - - if (stop_addr left_addr) { - vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name); - return 0; - } - } - - - words = vpi_iterate(vpiMemoryWord, mitem); - assert(words); - - item = vpi_scan(words); - wwid = vpi_get(vpiSize, item); - vpi_free_object(words); - - if (strcmp(name,"$writememb")==0){ - value.format = vpiBinStrVal; - } - else{ - value.format = vpiHexStrVal; - } + if (strcmp(name,"$writememb")==0) value.format = vpiBinStrVal; + else value.format = vpiHexStrVal; /*======================================== Write memory file */ - cnt=0; - for(addr=start_addr; addr!=stop_addr+addr_incr; addr+=addr_incr, ++cnt){ - if (cnt%16 == 0) - fprintf(file, "// 0x%08x\n", cnt); + cnt = 0; + for(addr=start_addr; addr!=stop_addr+addr_incr; addr+=addr_incr, ++cnt) { + vpiHandle word_index; + + if (cnt%16 == 0) fprintf(file, "// 0x%08x\n", cnt); word_index = vpi_handle_by_index(mitem, addr); assert(word_index); @@ -546,7 +464,7 @@ static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name) } fclose(file); - free(path); + free(fname); return 0; } @@ -557,7 +475,7 @@ void sys_readmem_register() tf_data.type = vpiSysTask; tf_data.tfname = "$readmemh"; tf_data.calltf = sys_readmem_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_mem_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$readmemh"; vpi_register_systf(&tf_data); @@ -565,7 +483,7 @@ void sys_readmem_register() tf_data.type = vpiSysTask; tf_data.tfname = "$readmemb"; tf_data.calltf = sys_readmem_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_mem_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$readmemb"; vpi_register_systf(&tf_data); @@ -573,7 +491,7 @@ void sys_readmem_register() tf_data.type = vpiSysTask; tf_data.tfname = "$writememh"; tf_data.calltf = sys_writemem_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_mem_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$writememh"; vpi_register_systf(&tf_data); @@ -581,7 +499,7 @@ void sys_readmem_register() tf_data.type = vpiSysTask; tf_data.tfname = "$writememb"; tf_data.calltf = sys_writemem_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_mem_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$writememb"; vpi_register_systf(&tf_data); diff --git a/vpi/sys_readmem_lex.h b/vpi/sys_readmem_lex.h index e050e4c82..2083739d5 100644 --- a/vpi/sys_readmem_lex.h +++ b/vpi/sys_readmem_lex.h @@ -24,6 +24,9 @@ # define MEM_ADDRESS 257 # define MEM_WORD 258 +# define MEM_ERROR 259 + +extern char *readmem_error_token; extern void sys_readmem_start_file(FILE*in, int bin_flag, unsigned width, struct t_vpi_vecval*val); diff --git a/vpi/sys_readmem_lex.lex b/vpi/sys_readmem_lex.lex index 2cceeaba0..e17ede241 100644 --- a/vpi/sys_readmem_lex.lex +++ b/vpi/sys_readmem_lex.lex @@ -30,6 +30,8 @@ static void make_bin_value(); static int save_state; +char *readmem_error_token = 0; + %} %x BIN @@ -51,6 +53,9 @@ static int save_state; "*" { ; } "*"+"/" { BEGIN(save_state); } + /* Catch any invalid tokens and flagged them as an error. */ +. { readmem_error_token = yytext; return MEM_ERROR; } + %% static unsigned word_width = 0; static struct t_vpi_vecval*vecval = 0; diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index cb5861b33..feb6bdde1 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -286,34 +286,19 @@ static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name) static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name) { - s_vpi_value value; vpiHandle callh = vpi_handle(vpiSysTfCall,0); vpiHandle argv = vpi_iterate(vpiArgument, callh); + FILE *sdf_fd; + char *fname = get_filename(callh, name, vpi_scan(argv)); - /* The first argument is the path to the SDF file. */ - vpiHandle path = vpi_scan(argv); - assert(path); + if (fname == 0) return 0; - value.format = vpiStringVal; - vpi_get_value(path, &value); - - if ((value.format != vpiStringVal) || !*(value.value.str)) { - vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s's file name argument (type=%s)" - " does not have a string value.\n", - name, vpi_get_str(vpiType, path)); - vpi_control(vpiFinish, 1); - return 0; - } - - char*path_str = strdup(value.value.str); - FILE*sdf_fd = fopen(path_str, "r"); + sdf_fd = fopen(fname, "r"); if (sdf_fd == 0) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("Unable to open SDF file \"%s\"." - " Skipping this annotation.\n", path_str); + " Skipping this annotation.\n", fname); return 0; } @@ -324,11 +309,11 @@ static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name) sdf_cur_cell = 0; sdf_callh = callh; - sdf_process_file(sdf_fd, path_str); + sdf_process_file(sdf_fd, fname); sdf_callh = 0; fclose(sdf_fd); - free(path_str); + free(fname); return 0; } diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 9b882b07a..e7637ea90 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -404,7 +404,8 @@ static void open_dumpfile(vpiHandle callh) unsigned udx = 0; time_t walltime; - vpi_printf("VCD info: dumpfile %s opened for output.\n", dump_path); + vpi_printf("VCD info: dumpfile %s opened for output.\n", + dump_path); time(&walltime); @@ -434,32 +435,33 @@ static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); - s_vpi_value value; - - char*path; + char *path; /* $dumpfile must be called before $dumpvars starts! */ if (dumpvars_status != 0) { - vpi_printf("VCD warning: %s called after $dumpvars started,\n" - " using existing file (%s).\n", - name, dump_path); + char msg [64]; + snprintf(msg, 64, "VCD warning: %s:%d:", + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s %s called after $dumpvars started,\n", msg, name); + vpi_printf("%*s using existing file (%s).\n", + (int) strlen(msg), " ", dump_path); vpi_free_object(argv); return 0; } - assert(argv); - value.format = vpiStringVal; - vpi_get_value(vpi_scan(argv), &value); - path = strdup(value.value.str); + path = get_filename(callh, name, vpi_scan(argv)); + vpi_free_object(argv); + if (! path) return 0; if (dump_path) { - vpi_printf("VCD warning: Overriding dump file %s with %s\n", - dump_path, path); + vpi_printf("VCD warning: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Overriding dump file %s with %s.\n", dump_path, path); free(dump_path); } dump_path = path; - vpi_free_object(argv); return 0; }