diff --git a/vpi/sys_icarus.c b/vpi/sys_icarus.c index ff6998d5f..af92be7db 100644 --- a/vpi/sys_icarus.c +++ b/vpi/sys_icarus.c @@ -48,6 +48,93 @@ static PLI_INT32 size_32(PLI_BYTE8* ud) return 32; } + +/* + * Routine to finish the simulation and return a value to the + * calling environment. + */ +static PLI_INT32 finish_and_return_compiletf(PLI_BYTE8* ud) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + (void) ud; /* Not used! */ + + /* We must have at least one argument. */ + if (argv == 0) { + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("$finish_and_return requires an argument.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + + /* This must be a numeric argument. */ + arg = vpi_scan(argv); + switch(vpi_get(vpiType, arg)) { + case vpiConstant: + case vpiParameter: + /* String constants are invalid numeric values. */ + if (vpi_get(vpiConstType, arg) == vpiStringConst) { + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("The argument to $finish_and_return must be numeric.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + break; + + case vpiIntegerVar: + case vpiMemoryWord: + case vpiNet: + case vpiRealVar: + case vpiReg: + case vpiTimeVar: + break; + + default: + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("The argument to $finish_and_return must be numeric.\n"); + vpi_control(vpiFinish, 1); + return 0; + break; + } + + /* We can only have one argument. */ + if (vpi_scan(argv) != 0) { + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("$finish_and_return takes a single argument.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + + return 0; +} + +static PLI_INT32 finish_and_return_calltf(PLI_BYTE8* ud) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + s_vpi_value val; + (void) ud; /* Not used! */ + + /* Get the return value. */ + arg = vpi_scan(argv); + vpi_free_object(argv); + val.format = vpiIntVal; + vpi_get_value(arg, &val); + + /* Set the return value. */ + vpip_set_return_value(val.value.integer); + + /* Now finish. */ + vpi_control(vpiFinish, 1); + return 0; +} + /* * Register the function with Verilog. */ @@ -55,7 +142,6 @@ void sys_special_register(void) { s_vpi_systf_data tf_data; - /* Register the single argument functions. */ tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiIntFunc; tf_data.calltf = vvp_cpu_wordsize_calltf; @@ -64,4 +150,12 @@ void sys_special_register(void) tf_data.tfname = "$vvp_cpu_wordsize"; tf_data.user_data = 0; vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.calltf = finish_and_return_calltf; + tf_data.compiletf = finish_and_return_compiletf; + tf_data.sizetf = 0; + tf_data.tfname = "$finish_and_return"; + tf_data.user_data = 0; + vpi_register_systf(&tf_data); } diff --git a/vpi_user.h b/vpi_user.h index 8c93d8c2e..0087b52b5 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -563,6 +563,7 @@ extern DLLEXPORT void (*vlog_startup_routines[])(); /* Format a scalar a la %v. The str points to a 4byte character buffer. The value must be a vpiStrengthVal. */ extern void vpip_format_strength(char*str, s_vpi_value*value, unsigned bit); +extern void vpip_set_return_value(int value); EXTERN_C_END diff --git a/vvp/main.cc b/vvp/main.cc index c820b2c3c..d303d9028 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 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 @@ -66,6 +66,12 @@ extern "C" long int lround(double x) #endif bool verbose_flag = false; +static int vvp_return_value = 0; + +void vpip_set_return_value(int value) +{ + vvp_return_value = value; +} static char log_buffer[4096]; @@ -305,6 +311,5 @@ int main(int argc, char*argv[]) count_gen_events); } - return 0; + return vvp_return_value; } - diff --git a/vvp/vvp.def b/vvp/vvp.def index a745529b0..ad3990f05 100644 --- a/vvp/vvp.def +++ b/vvp/vvp.def @@ -36,3 +36,4 @@ vpi_sim_vcontrol vpi_vprintf vpip_format_strength +vpip_set_return_value