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 <steve@icarus.com>
This commit is contained in:
Stephen Williams 2007-11-22 17:34:51 -08:00
parent 73e60f4b81
commit 4986e550b1
4 changed files with 104 additions and 16 deletions

View File

@ -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 <string_val> hierarchical_identifier
%type <string_val> port port_instance port_spec
%type <real_val> rvalue rtriple signed_real_number
%type <real_val> delval
%type <delval_list> 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; }
;
%%

View File

@ -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

View File

@ -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)

View File

@ -576,19 +576,53 @@ static void modpath_src_put_delays ( vpiHandle ref, p_vpi_delay delays )
vvp_fun_modpath_src *fun = dynamic_cast<vvp_fun_modpath_src*>(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);
}