From 1d2aef714237dc1f55d97407032c1903ccd449a2 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 11 Dec 2015 12:58:25 +0100 Subject: [PATCH] vpi: $sformatf() function. --- vpi/sys_display.c | 82 +++++++++++++++++++++++++++++++++++++++++------ vpi/system.sft | 2 ++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index a7a34dfa7..c65c1b14d 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -169,10 +169,11 @@ static int get_default_format(const char *name) int default_format; switch(name[ strlen(name)-1 ]){ - /* writE/strobE or monitoR or displaY/fdisplaY or sformaT */ + /* writE/strobE or monitoR or displaY/fdisplaY or sformaT/sformatF */ case 'e': case 'r': case 't': + case 'f': case 'y': default_format = vpiDecStrVal; break; case 'h': default_format = vpiHexStrVal; break; case 'o': default_format = vpiOctStrVal; break; @@ -1238,7 +1239,8 @@ static PLI_INT32 sys_display_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) return sys_common_compiletf(name, 0, 0); } -/* This implements the $display/$fdisplay and the $write/$fwrite based tasks. */ +/* This implements the $sformatf, $display/$fdisplay + * and the $write/$fwrite based tasks. */ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh, argv, scope; @@ -1246,6 +1248,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) char* result; unsigned int size; PLI_UINT32 fd_mcd; + s_vpi_value val; callh = vpi_handle(vpiSysTfCall, 0); argv = vpi_iterate(vpiArgument, callh); @@ -1254,7 +1257,6 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) if(name[1] == 'f') { errno = 0; vpiHandle arg = vpi_scan(argv); - s_vpi_value val; val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; @@ -1275,7 +1277,11 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) vpi_free_object(argv); return 0; } + } else if(strncmp(name,"$sformatf",9) == 0) { + /* return as a string */ + fd_mcd = 0; } else { + /* stdout */ fd_mcd = 1; } @@ -1293,13 +1299,21 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* Because %u and %z may put embedded NULL characters into the * returned string strlen() may not match the real size! */ result = get_display(&size, &info); - my_mcd_rawwrite(fd_mcd, result, size); - if ((strncmp(name,"$display",8) == 0) || - (strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1); + if(fd_mcd > 0) { + my_mcd_rawwrite(fd_mcd, result, size); + if ((strncmp(name,"$display",8) == 0) || + (strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1); + } else { + /* Return as a string ($sformatf) */ + val.format = vpiStringVal; + val.value.str = result; + vpi_put_value(callh, &val, 0, vpiNoDelay); + } + + free(result); free(info.filename); free(info.items); - free(result); return 0; } @@ -1665,7 +1679,7 @@ static PLI_INT32 sys_sformat_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) if (argv == 0) { vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s requires at least two argument.\n", name); + vpi_printf("%s requires at least two arguments.\n", name); vpi_control(vpiFinish, 1); return 0; } @@ -1686,7 +1700,7 @@ static PLI_INT32 sys_sformat_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) if (arg == 0) { vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); - vpi_printf("%s requires at least two argument.\n", name); + vpi_printf("%s requires at least two arguments.\n", name); vpi_control(vpiFinish, 1); return 0; } @@ -1754,6 +1768,46 @@ static PLI_INT32 sys_sformat_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } +static PLI_INT32 sys_sformatf_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + PLI_INT32 type; + + /* Check that there are arguments. */ + if (argv == 0) { + vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s requires at least one argument.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + + /* The first argument must be a string, a register or a SV string. */ + arg = vpi_scan(argv); + if (arg == 0) { + vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s requires at least one argument.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + type = vpi_get(vpiType, arg); + if (((type != vpiConstant && type != vpiParameter) || + vpi_get(vpiConstType, arg) != vpiStringConst) && + type != vpiReg && type != vpiStringVar) { + vpi_printf("ERROR:%s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("%s's first argument must be a string or a register.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + + if (sys_check_args(callh, argv, name, 0, 0)) vpi_control(vpiFinish, 1); + return 0; +} + static PLI_INT32 sys_end_of_compile(p_cb_data cb_data) { (void)cb_data; /* Parameter is not used. */ @@ -2434,6 +2488,16 @@ void sys_display_register(void) res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiStringFunc; + tf_data.tfname = "$sformatf"; + tf_data.calltf = sys_display_calltf; + tf_data.compiletf = sys_sformatf_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$sformatf"; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + /*============================ timeformat */ tf_data.type = vpiSysTask; tf_data.tfname = "$timeformat"; diff --git a/vpi/system.sft b/vpi/system.sft index f3048198f..be082c85f 100644 --- a/vpi/system.sft +++ b/vpi/system.sft @@ -24,3 +24,5 @@ $table_model vpiSysFuncReal $ivl_string_method$len vpiSysFuncInt $ivl_string_method$to_vec vpiSysFuncVoid + +$sformatf vpiSysFuncString