From 4986e550b12cbf74174b6b3cd686166c6cabdd02 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 22 Nov 2007 17:34:51 -0800 Subject: [PATCH] Pass SDF delays into simulation Pass parsed SDF delays into the vvp run time as vpiScaledRealTime variables, and handling the mapping of 2-values to 12-delays. Signed-off-by: Stephen Williams --- vpi/sdf_parse.y | 39 +++++++++++++++++++++++++++++++++++---- vpi/sdf_priv.h | 9 ++++++++- vpi/sys_sdf.c | 28 ++++++++++++++++++++++------ vvp/delay.cc | 44 +++++++++++++++++++++++++++++++++++++++----- 4 files changed, 104 insertions(+), 16 deletions(-) diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index 3afe61c3e..6d1551016 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -35,6 +35,8 @@ static char use_hchar = '.'; unsigned long int_val; double real_val; char* string_val; + + struct sdf_delval_list_s delval_list; }; %token K_ABSOLUTE K_CELL K_CELLTYPE K_DATE K_DELAYFILE K_DELAY K_DESIGN @@ -51,6 +53,11 @@ static char use_hchar = '.'; %type hierarchical_identifier %type port port_instance port_spec +%type rvalue rtriple signed_real_number +%type delval + +%type delval_list + %% source_file @@ -203,7 +210,7 @@ del_def_list del_def : '(' K_IOPATH port_spec port_instance delval_list ')' - { sdf_iopath_delays($3, $4); + { sdf_iopath_delays($3, $4, &$5); free($3); free($4); } @@ -229,18 +236,41 @@ port delval_list : delval_list delval + { int idx; + $$.count = $1.count; + for (idx = 0 ; idx < $$.count ; idx += 1) + $$.val[idx] = $1.val[idx]; + if ($$.count < 12) { + $$.val[$$.count] = $2; + $$.count += 1; + } + } | delval + { $$.count = 1; + $$.val[0] = $1; + } ; delval : rvalue + { $$ = $1; } | '(' rvalue rvalue ')' + { $$ = $2; + vpi_printf("%s:%d: SDF WARNING: Pulse rejection limits ignored\n", + sdf_parse_path, @3.first_line); + } | '(' rvalue rvalue rvalue ')' + { $$ = $2; + vpi_printf("%s:%d: SDF WARNING: Pulse rejection limits ignored\n", + sdf_parse_path, @3.first_line); + } ; rvalue : '(' signed_real_number ')' + { $$ = $2; } | '(' rtriple ')' + { $$ = $2; } ; hierarchical_identifier @@ -250,12 +280,13 @@ hierarchical_identifier rtriple : signed_real_number ':' signed_real_number ':' signed_real_number + { $$ = $3; /* XXXX Assume typical value. */ } ; signed_real_number - : REAL_NUMBER - | '+' REAL_NUMBER - | '-' REAL_NUMBER + : REAL_NUMBER { $$ = $1; } + | '+' REAL_NUMBER { $$ = $2; } + | '-' REAL_NUMBER { $$ = -$2; } ; %% diff --git a/vpi/sdf_priv.h b/vpi/sdf_priv.h index f5707c87c..5a981dd57 100644 --- a/vpi/sdf_priv.h +++ b/vpi/sdf_priv.h @@ -33,7 +33,14 @@ extern void sdf_process_file(FILE*fd, const char*path); * These functions are called by the parser to process the SDF file as * it is parsed. */ + +struct sdf_delval_list_s { + int count; + double val[12]; +}; + extern void sdf_select_instance(const char*celltype, const char*inst); -extern void sdf_iopath_delays(const char*src, const char*dst); +extern void sdf_iopath_delays(const char*src, const char*dst, + const struct sdf_delval_list_s*delval); #endif diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index 75ae2bbe2..d382738d3 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -74,18 +74,19 @@ void sdf_select_instance(const char*celltype, const char*cellinst) vpi_printf("SDF WARNING: Unable to find %s in current scope\n", cellinst); } -void sdf_iopath_delays(const char*src, const char*dst) +void sdf_iopath_delays(const char*src, const char*dst, + const struct sdf_delval_list_s*delval_list) { assert(sdf_cur_cell); - vpiHandle idx = vpi_iterate(vpiModPath, sdf_cur_cell); - assert(idx); + vpiHandle iter = vpi_iterate(vpiModPath, sdf_cur_cell); + assert(iter); /* Search for the modpath that matches the IOPATH by looking for the modpath that uses the same ports as the ports that the parser has found. */ vpiHandle path; - while ( (path = vpi_scan(idx)) ) { + while ( (path = vpi_scan(iter)) ) { vpiHandle path_in = vpi_handle(vpiModPathIn,path); vpiHandle path_out = vpi_handle(vpiModPathOut,path); @@ -113,9 +114,24 @@ void sdf_iopath_delays(const char*src, const char*dst) } /* No longer need the iterator. */ - vpi_free_object(idx); + vpi_free_object(iter); - vpi_printf("XXXX Found the modpath object.\n"); + struct t_vpi_time delay_vals[12]; + int idx; + for (idx = 0 ; idx < delval_list->count ; idx += 1) { + delay_vals[idx].type = vpiScaledRealTime; + delay_vals[idx].real = delval_list->val[idx]; + } + + s_vpi_delay delays; + delays.da = delay_vals; + delays.no_of_delays = delval_list->count; + delays.time_type = vpiScaledRealTime; + delays.mtm_flag = 0; + delays.append_flag = 0; + delays.plusere_flag = 0; + + vpi_put_delays(path, &delays); } static PLI_INT32 sys_sdf_annotate_compiletf(PLI_BYTE8*name) diff --git a/vvp/delay.cc b/vvp/delay.cc index 446795e37..4497f8901 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -576,19 +576,53 @@ static void modpath_src_put_delays ( vpiHandle ref, p_vpi_delay delays ) vvp_fun_modpath_src *fun = dynamic_cast(src->net->fun); assert( fun ); - assert(delays->no_of_delays == 12); + + typedef unsigned char map_array_t[12]; + static const map_array_t map_2 = {0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0}; + static const map_array_t map12 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + + const map_array_t*use_map = 0; + switch (delays->no_of_delays) { + case 2: + use_map = &map_2; + break; + case 12: + use_map = &map12; + break; + default: + assert(0); + break; + } if (delays->time_type == vpiSimTime) { - for (idx = 0 ; idx < delays->no_of_delays ; idx += 1) { - tmp[idx] = vpip_timestruct_to_time(delays->da+idx); + for (idx = 0 ; idx < 12 ; idx += 1) { + tmp[idx] = vpip_timestruct_to_time(delays->da+use_map[0][idx]); } } else { - for (idx = 0 ; idx < delays->no_of_delays ; idx += 1) { - tmp[idx] = vpip_scaled_real_to_time64(delays->da[idx].real, + for (idx = 0 ; idx < 12 ; idx += 1) { + tmp[idx] = vpip_scaled_real_to_time64(delays->da[use_map[0][idx]].real, src->dest->scope); } } + /* Now clean up any to-from-x delays to me the min/max based on + the rules for selecting X delays. This only needs to happen + if the X delays are not already explicitly given. */ + if (delays->no_of_delays <= 6) { + vvp_time64_t t_max = tmp[0]; + vvp_time64_t t_min = tmp[1]; + for (idx = 1 ; idx < delays->no_of_delays ; idx += 1) { + if (tmp[idx] > t_max) t_max = tmp[idx]; + if (tmp[idx] < t_min) t_min = tmp[idx]; + } + tmp[DELAY_EDGE_0x] = t_min; + tmp[DELAY_EDGE_x1] = t_max; + tmp[DELAY_EDGE_1x] = t_min; + tmp[DELAY_EDGE_x0] = t_max; + tmp[DELAY_EDGE_xz] = t_max; + tmp[DELAY_EDGE_zx] = t_min; + } + fun->put_delay12(tmp); }