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:
parent
73e60f4b81
commit
4986e550b1
|
|
@ -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; }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
44
vvp/delay.cc
44
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<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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue