diff --git a/Documentation/usage/vvp_flags.rst b/Documentation/usage/vvp_flags.rst index 482aab064..87eb4a9ff 100644 --- a/Documentation/usage/vvp_flags.rst +++ b/Documentation/usage/vvp_flags.rst @@ -82,6 +82,13 @@ behavior. Generate LXT or LXT2format instead of VCD format waveform dumps. The LXT2 format is more advanced. +* -dumpfile= + + Set the default dumpfile. If unspecified, the default is "dump". This + command line flag allows you do change it. If no suffix is specified, + then the suffix will be chosen based on the dump type. In any case, the + $dumpfile system task overrides this flag. + SDF Support ^^^^^^^^^^^ diff --git a/vpi/sys_fst.c b/vpi/sys_fst.c index f01771629..1797dc7d7 100644 --- a/vpi/sys_fst.c +++ b/vpi/sys_fst.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2023 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 @@ -32,7 +32,6 @@ # include # include "ivl_alloc.h" -static char *dump_path = NULL; static int dump_no_date = 0; static struct fstContext *dump_file = NULL; @@ -114,7 +113,6 @@ struct vcd_names_list_s fst_tab = { 0, 0, 0, 0 }; struct vcd_names_list_s fst_var = { 0, 0, 0, 0 }; -static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ static PLI_UINT64 dumpvars_time; __inline__ static int dump_header_pending(void) { @@ -224,8 +222,7 @@ static PLI_INT32 finish_cb(p_cb_data cause) vcd_names_delete(&fst_tab); vcd_names_delete(&fst_var); nexus_ident_delete(); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return 0; } @@ -346,18 +343,17 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) static void open_dumpfile(vpiHandle callh) { - if (dump_path == 0) dump_path = strdup("dump.fst"); + char* use_dump_path = vcd_get_dump_path("fst"); - dump_file = fstWriterCreate(dump_path, 1); + dump_file = fstWriterCreate(use_dump_path, 1); if (dump_file == 0) { vpi_printf("FST Error: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); - vpi_printf("Unable to open %s for output.\n", dump_path); + vpi_printf("Unable to open %s for output.\n", use_dump_path); vpip_set_return_value(1); vpi_control(vpiFinish, 1); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return; } else { int prec = vpi_get(vpiTimePrecision, 0); @@ -367,7 +363,7 @@ static void open_dumpfile(vpiHandle callh) char scale_buf[65]; vpi_printf("FST info: dumpfile %s opened for output.\n", - dump_path); + use_dump_path); time(&walltime); @@ -381,10 +377,10 @@ static void open_dumpfile(vpiHandle callh) prec -= 1; } - if (!dump_no_date) - fstWriterSetDate(dump_file, asctime(localtime(&walltime))); - else - fstWriterSetDate(dump_file, ""); + if (!dump_no_date) + fstWriterSetDate(dump_file, asctime(localtime(&walltime))); + else + fstWriterSetDate(dump_file, ""); fstWriterSetVersion(dump_file, "Icarus Verilog"); sprintf(scale_buf, "\t%u%s\n", scale, units_names[udx]); fstWriterSetTimescaleFromString(dump_file, scale_buf); @@ -403,37 +399,8 @@ static void open_dumpfile(vpiHandle callh) static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { - 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) { - char msg[64]; - snprintf(msg, sizeof(msg), "FST warning: %s:%d:", - vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - msg[sizeof(msg)-1] = 0; - 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; - } - - path = get_filename_with_suffix(callh, name, vpi_scan(argv), "fst"); - vpi_free_object(argv); - if (! path) return 0; - - if (dump_path) { - vpi_printf("FST 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; - - return 0; + (void)name; + return sys_dumpfile_common("FST", "fst"); } static PLI_INT32 sys_dumpflush_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index 66d66dbe7..fc632db8f 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2023 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,7 +35,6 @@ # include "ivl_alloc.h" -static char *dump_path = NULL; static struct lt_trace *dump_file = NULL; static struct t_vpi_time zero_delay = { vpiSimTime, 0, 0, 0.0 }; @@ -197,7 +196,6 @@ static void show_this_item_x(struct vcd_info*info) struct vcd_names_list_s lxt_tab; -static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ static PLI_UINT64 dumpvars_time; __inline__ static int dump_header_pending(void) { @@ -314,8 +312,7 @@ static PLI_INT32 finish_cb(p_cb_data cause) vcd_names_delete(&lxt_tab); nexus_ident_delete(); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return 0; } @@ -442,24 +439,23 @@ static void *close_dumpfile(void) static void open_dumpfile(vpiHandle callh) { - if (dump_path == 0) dump_path = strdup("dump.lxt"); + char* use_dump_path = vcd_get_dump_path("lxt"); - dump_file = lt_init(dump_path); + dump_file = lt_init(use_dump_path); if (dump_file == 0) { vpi_printf("LXT Error: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); - vpi_printf("Unable to open %s for output.\n", dump_path); + vpi_printf("Unable to open %s for output.\n", use_dump_path); vpip_set_return_value(1); vpi_control(vpiFinish, 1); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return; } else { int prec = vpi_get(vpiTimePrecision, 0); vpi_printf("LXT info: dumpfile %s opened for output.\n", - dump_path); + use_dump_path); assert(prec >= -15); lt_set_timescale(dump_file, prec); @@ -473,37 +469,8 @@ static void open_dumpfile(vpiHandle callh) static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { - 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) { - char msg[64]; - snprintf(msg, sizeof(msg), "LXT warning: %s:%d:", - vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - msg[sizeof(msg)-1] = 0; - 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; - } - - path = get_filename_with_suffix(callh, name, vpi_scan(argv), "lxt"); - vpi_free_object(argv); - if (! path) return 0; - - if (dump_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; - - return 0; + (void)name; + return sys_dumpfile_common("LXT", "lxt"); } /* diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index ff470eb20..65fe6dd5d 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2023 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,7 +35,6 @@ # include "ivl_alloc.h" -static char *dump_path = NULL; static struct lxt2_wr_trace *dump_file = NULL; static void* lxt2_thread(void*arg); @@ -244,7 +243,6 @@ static void show_this_item_x(struct vcd_info*info) } -static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ static PLI_UINT64 dumpvars_time; __inline__ static int dump_header_pending(void) { @@ -349,8 +347,7 @@ static PLI_INT32 finish_cb(p_cb_data cause) vcd_scope_names_delete(); nexus_ident_delete(); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return 0; } @@ -479,9 +476,9 @@ static void *close_dumpfile(void) static void open_dumpfile(vpiHandle callh) { off_t use_file_size_limit = lxt2_file_size_limit; - if (dump_path == 0) dump_path = strdup("dump.lx2"); + char* use_dump_path = vcd_get_dump_path("lx2"); - dump_file = lxt2_wr_init(dump_path); + dump_file = lxt2_wr_init(use_dump_path); if (getenv("LXT_FILE_SIZE_LIMIT")) { const char*limit_string = getenv("LXT_FILE_SIZE_LIMIT"); @@ -499,17 +496,16 @@ static void open_dumpfile(vpiHandle callh) if (dump_file == 0) { vpi_printf("LXT2 Error: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); - vpi_printf("Unable to open %s for output.\n", dump_path); + vpi_printf("Unable to open %s for output.\n", use_dump_path); vpip_set_return_value(1); vpi_control(vpiFinish, 1); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return; } else { int prec = vpi_get(vpiTimePrecision, 0); vpi_printf("LXT2 info: dumpfile %s opened for output.\n", - dump_path); + use_dump_path); assert(prec >= -15); lxt2_wr_set_timescale(dump_file, prec); @@ -526,37 +522,8 @@ static void open_dumpfile(vpiHandle callh) static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { - 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) { - char msg[64]; - snprintf(msg, sizeof(msg), "LXT2 warning: %s:%d:", - vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - msg[sizeof(msg)-1] = 0; - 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; - } - - path = get_filename_with_suffix(callh, name, vpi_scan(argv), "lx2"); - vpi_free_object(argv); - if (! path) return 0; - - if (dump_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; - - return 0; + (void)name; + return sys_dumpfile_common("LXT2", "lx2"); } /* diff --git a/vpi/sys_priv.c b/vpi/sys_priv.c index b9fb61029..222970a81 100644 --- a/vpi/sys_priv.c +++ b/vpi/sys_priv.c @@ -104,11 +104,11 @@ char *get_filename(vpiHandle callh, const char *name, vpiHandle file) return strdup(val.value.str); } -char* get_filename_with_suffix(vpiHandle callh, const char *name, vpiHandle file, const char*suff) +/* + * Create a new copy of the path with the suffix appended. + */ +char* attach_suffix_to_filename(char *path, const char*suff) { - char*path = get_filename(callh, name, file); - if (path == 0) return 0; - /* If the name already has a suffix, then don't replace it or add another suffix. Just return this path. */ char*tailp = strrchr(path, '.'); @@ -124,6 +124,14 @@ char* get_filename_with_suffix(vpiHandle callh, const char *name, vpiHandle file return new_path; } +char* get_filename_with_suffix(vpiHandle callh, const char *name, vpiHandle file, const char*suff) +{ + char*path = get_filename(callh, name, file); + if (path == 0) return 0; + + return attach_suffix_to_filename(path, suff); +} + void check_for_extra_args(vpiHandle argv, vpiHandle callh, const char *name, const char *arg_str, unsigned opt) { diff --git a/vpi/sys_priv.h b/vpi/sys_priv.h index 473a5650e..dea7d55ac 100644 --- a/vpi/sys_priv.h +++ b/vpi/sys_priv.h @@ -41,6 +41,7 @@ extern char *as_escaped(char *arg); extern char *get_filename(vpiHandle callh, const char *name, vpiHandle file); extern char *get_filename_with_suffix(vpiHandle callh, const char*name, vpiHandle file, const char*suff); +extern char *attach_suffix_to_filename(char *path, const char*suff); extern void check_for_extra_args(vpiHandle argv, vpiHandle callh, const char *name, const char *arg_str, unsigned opt); diff --git a/vpi/sys_table.c b/vpi/sys_table.c index 23b2c9142..1067b238c 100644 --- a/vpi/sys_table.c +++ b/vpi/sys_table.c @@ -19,6 +19,7 @@ # include "vpi_config.h" # include "vpi_user.h" +# include "vcd_priv.h" # include # include # include @@ -149,6 +150,8 @@ static void sys_lxt_or_vcd_register(void) } else if (strcmp(vlog_info.argv[idx],"-none") == 0) { dumper = "none"; + } else if (strncmp(vlog_info.argv[idx],"-dumpfile=",10) == 0) { + vcd_set_dump_path_default(vlog_info.argv[idx]+10); } } diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 13eea5e5d..1d7b1638d 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2023 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 @@ -31,7 +31,6 @@ # include # include "ivl_alloc.h" -static char *dump_path = NULL; static FILE *dump_file = NULL; static int dump_no_date = 0; @@ -158,7 +157,6 @@ struct vcd_names_list_s vcd_tab = { 0, 0, 0, 0 }; struct vcd_names_list_s vcd_var = { 0, 0, 0, 0 }; -static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ static PLI_UINT64 dumpvars_time; __inline__ static int dump_header_pending(void) { @@ -283,8 +281,7 @@ static PLI_INT32 finish_cb(p_cb_data cause) vcd_names_delete(&vcd_tab); vcd_names_delete(&vcd_var); nexus_ident_delete(); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return 0; } @@ -408,18 +405,17 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) static void open_dumpfile(vpiHandle callh) { - if (dump_path == 0) dump_path = strdup("dump.vcd"); + char* use_dump_path = vcd_get_dump_path("vcd"); - dump_file = fopen(dump_path, "w"); + dump_file = fopen(use_dump_path, "w"); if (dump_file == 0) { vpi_printf("VCD Error: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); - vpi_printf("Unable to open %s for output.\n", dump_path); + vpi_printf("Unable to open %s for output.\n", use_dump_path); vpip_set_return_value(1); vpi_control(vpiFinish, 1); - free(dump_path); - dump_path = 0; + vcd_free_dump_path(); return; } else { int prec = vpi_get(vpiTimePrecision, 0); @@ -428,7 +424,7 @@ static void open_dumpfile(vpiHandle callh) time_t walltime; vpi_printf("VCD info: dumpfile %s opened for output.\n", - dump_path); + use_dump_path); time(&walltime); @@ -458,37 +454,8 @@ static void open_dumpfile(vpiHandle callh) static PLI_INT32 sys_dumpfile_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { - 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) { - char msg[64]; - snprintf(msg, sizeof(msg), "VCD warning: %s:%d:", - vpi_get_str(vpiFile, callh), - (int)vpi_get(vpiLineNo, callh)); - msg[sizeof(msg)-1] = 0; - 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; - } - - path = get_filename_with_suffix(callh, name, vpi_scan(argv), "vcd"); - vpi_free_object(argv); - if (! path) return 0; - - if (dump_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; - - return 0; + (void) name; + return sys_dumpfile_common("VCD", "vcd"); } static PLI_INT32 sys_dumpflush_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) diff --git a/vpi/vcd_priv.c b/vpi/vcd_priv.c index ea01e0a4b..f508a16f3 100644 --- a/vpi/vcd_priv.c +++ b/vpi/vcd_priv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2023 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 @@ -27,6 +27,10 @@ #include #include "stringheap.h" +static const char* vcd_dump_path_default = "dump"; +static char* vcd_dump_path = NULL; +int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */ + int is_escaped_id(const char *name) { assert(name); @@ -220,3 +224,63 @@ PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } + +void vcd_set_dump_path_default(const char*text) +{ + vcd_dump_path_default = text; +} + +char* vcd_get_dump_path(const char*suffix) +{ + if (vcd_dump_path) + return vcd_dump_path; + + vcd_dump_path = attach_suffix_to_filename(strdup(vcd_dump_path_default), suffix); + return vcd_dump_path; +} + +void vcd_free_dump_path(void) +{ + free(vcd_dump_path); + vcd_dump_path = NULL; +} + +/* + * Common implementation of $dumpfile() for the various dumper types. + * string argument is the title to use in error messages. + */ +PLI_INT32 sys_dumpfile_common(const char*title, const char*suffix) +{ + static const char* name = "$dumpfile"; + 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) { + char msg[64]; + snprintf(msg, sizeof(msg), "%s warning: %s:%d:", title, + vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + msg[sizeof(msg)-1] = 0; + vpi_printf("%s %s called after $dumpvars started,\n", msg, name); + vpi_printf("%*s using existing file (%s).\n", + (int) strlen(msg), " ", vcd_dump_path); + vpi_free_object(argv); + return 0; + } + + path = get_filename_with_suffix(callh, name, vpi_scan(argv), suffix); + vpi_free_object(argv); + if (! path) return 0; + + if (vcd_dump_path) { + vpi_printf("%s warning: %s:%d: ", title, vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Overriding dump file %s with %s.\n", vcd_dump_path, path); + free(vcd_dump_path); + } + vcd_dump_path = path; + + return 0; +} diff --git a/vpi/vcd_priv.h b/vpi/vcd_priv.h index 629b9ed05..791043dc1 100644 --- a/vpi/vcd_priv.h +++ b/vpi/vcd_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_vcd_priv_H #define IVL_vcd_priv_H /* - * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2023 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 @@ -129,6 +129,15 @@ EXTERN void vcd_work_emit_bits(struct lxt2_wr_symbol*sym, const char*bits); /* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */ EXTERN PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name); +/* + * Common implementation of the sys_dumpfile calltf. + */ +EXTERN PLI_INT32 sys_dumpfile_common(const char*title, const char*suffix); +EXTERN void vcd_set_dump_path_default(const char*text); +EXTERN char* vcd_get_dump_path(const char*suffix); +EXTERN void vcd_free_dump_path(void); +EXTERN int dumpvars_status; + /* * The vcd_list is the list of all the objects that are tracked for * dumping. The vcd_checkpoint goes through the list to dump the current